diff --git a/Common/Context.cpp b/Common/Context.cpp index d7a402d96c59d4fddf38c60ae804ba206f1eec7a..65f6fa3fde53762d7c89cef511afaa55386b5f25 100644 --- a/Common/Context.cpp +++ b/Common/Context.cpp @@ -1,4 +1,4 @@ -/* $Id: Context.cpp,v 1.10 2000-12-05 15:23:54 geuzaine Exp $ */ +/* $Id: Context.cpp,v 1.11 2000-12-05 16:59:11 remacle Exp $ */ #include "Gmsh.h" #include "Const.h" @@ -6,6 +6,7 @@ #include "Mesh.h" #include "Draw.h" #include "Context.h" +#include "trackball.c" extern Context_T CTX ; @@ -345,6 +346,9 @@ void Init_Context(void){ // Default color options Init_Colors(0); + CTX.useTrackball = 1; + trackball(CTX.quaternion, 0.0, 0.0, 0.0, 0.0); + //Print_Context(stdout); } @@ -390,3 +394,28 @@ void Print_Context(FILE *file){ fprintf(file, "}\n"); } +void Context_T::buildRotmatrix(float m[4][4]) +{ + build_rotmatrix(m, quaternion); + + r[1] = atan2(-m[0][2],sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2])); + + double c = cos(r[1]); + if(c != 0.0) + { + r[0] = atan2(m[1][2]/c,m[2][2]/c); + r[2] = atan2(-m[1][0]/c,m[0][0]/c); + r[0] *= 180./(Pi); + r[2] *= 180./(Pi); + } + // lazyyyyyy + r[1] *= 180./(Pi); +} + +void Context_T::addQuaternion (float p1x, float p1y, float p2x, float p2y) +{ + float quat[4]; + trackball(quat,p1x,p1y,p2x,p2y); + add_quats(quat, quaternion, quaternion); +} + diff --git a/Common/Context.h b/Common/Context.h index 87c4a5685973980909d98e77e483316fd0efdeef..f1ae9985c87fb04d6499d2c1aafa0651d190c7d5 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -1,4 +1,4 @@ -/* $Id: Context.h,v 1.11 2000-12-05 15:23:54 geuzaine Exp $ */ +/* $Id: Context.h,v 1.12 2000-12-05 16:59:11 remacle Exp $ */ #ifndef _CONTEXT_H_ #define _CONTEXT_H_ @@ -53,8 +53,8 @@ typedef struct{ }rgbacolors; -typedef struct { - +class Context_T { + public : int interactive; /* 0=full gfx; -1=just parse; 1,2,3=batch mesh */ int verbosity; /* 0=silent -> 3=debug */ int expose; /* 1 if everything is ready to expose and draw */ @@ -63,12 +63,15 @@ typedef struct { int rlock[3], tlock[3], slock[3]; /* locks for r, t and s */ + float quaternion[4]; /* the actual quaternion used for "trackball" rotating */ + int useTrackball; /* do or do not use the trackball for rotations */ + double min[3]; /* x, y and z min for the current geometry */ double max[3]; /* x, y and z max for the current geometry */ double range[3]; /* maximum range in the three directions */ double lc, lc_middle; /* characteristic lengths for the whole problem, */ double lc_order; /* and never used in mesh generation (->only for geo/post) */ - + int db; /* double buffer? */ int overlay; /* overlay graphic window? */ int stream; /* output stream: TO_SCREEN or TO_FILE */ @@ -141,7 +144,10 @@ typedef struct { int font_size; } print; -} Context_T; + // trackball functions + void buildRotmatrix(float m[4][4]); + void addQuaternion (float p1x, float p1y, float p2x, float p2y); +}; typedef struct { char *str ; diff --git a/Common/trackball.c b/Common/trackball.c new file mode 100644 index 0000000000000000000000000000000000000000..f23d3db30b53cf5f401f7900dd70e4b84e58f921 --- /dev/null +++ b/Common/trackball.c @@ -0,0 +1,324 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +#include <math.h> +#include "trackball.h" + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.8) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float [4]); + +void +vzero(float *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +void +vset(float *v, float x, float y, float z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +void +vsub(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +void +vcopy(const float *v1, float *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +void +vcross(const float *v1, const float *v2, float *cross) +{ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +float +vlength(const float *v) +{ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +void +vscale(float *v, float div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +void +vnormal(float *v) +{ + vscale(v,1.0/vlength(v)); +} + +float +vdot(const float *v1, const float *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void +vadd(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y) +{ + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d) / (2.0*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0 * asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(float a[3], float phi, float q[4]) +{ + vnormal(a); + vcopy(a,q); + vscale(q,sin(phi/2.0)); + q[3] = cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float +tb_project_to_sphere(float r, float x, float y) +{ + float d, t, z; + + d = sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(float q1[4], float q2[4], float dest[4]) +{ + static int count=0; + float t1[4], t2[4], t3[4]; + float tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(float q[4]) +{ + int i; + float mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(float m[4][4], float q[4]) +{ + m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0; + + m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0; + + m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0; + + m[3][0] = 0.0; + m[3][1] = 0.0; + m[3][2] = 0.0; + m[3][3] = 1.0; +} + diff --git a/Common/trackball.h b/Common/trackball.h new file mode 100644 index 0000000000000000000000000000000000000000..b676fb4e54ba7cd70f22a02087a88ac31db343f0 --- /dev/null +++ b/Common/trackball.h @@ -0,0 +1,78 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(float *q1, float *q2, float *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(float m[4][4], float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void +axis_to_quat(float a[3], float phi, float q[4]); + diff --git a/Graphics/Draw.cpp b/Graphics/Draw.cpp index 06f9c03c14e2b35400b9d7b36530bdaf783131f1..de6abda2efe66b72f938ebfdc0eb290309b418b3 100644 --- a/Graphics/Draw.cpp +++ b/Graphics/Draw.cpp @@ -1,4 +1,4 @@ -/* $Id: Draw.cpp,v 1.7 2000-12-05 15:23:56 geuzaine Exp $ */ +/* $Id: Draw.cpp,v 1.8 2000-12-05 16:59:11 remacle Exp $ */ #include "Gmsh.h" #include "GmshUI.h" @@ -229,9 +229,19 @@ void InitNoShading(void){ void InitPosition(void){ glScaled (CTX.s[0], CTX.s[1], CTX.s[2]); glTranslated(CTX.t[0], CTX.t[1], CTX.t[2]); - glRotated (CTX.r[0], 1., 0., 0.); - glRotated (CTX.r[1], 0., 1., 0.); - glRotated (CTX.r[2], 0., 0., 1.); + + if(CTX.useTrackball) + { + float m[4][4]; + CTX.buildRotmatrix(m); + glMultMatrixf(&(m[0][0])); + } + else + { + glRotated (CTX.r[0], 1., 0., 0.); + glRotated (CTX.r[1], 0., 1., 0.); + glRotated (CTX.r[2], 0., 0., 1.); + } } /* ------------------------------------------------------------------------ */ diff --git a/Graphics/gl2gif.cpp b/Graphics/gl2gif.cpp index f7c26abf9c08158195346835588fa7423648ebd6..a83d130b6b2aada30301c5483394c86b276b990a 100644 --- a/Graphics/gl2gif.cpp +++ b/Graphics/gl2gif.cpp @@ -1,4 +1,3 @@ -/* $Id: gl2gif.cpp,v 1.3 2000-11-26 15:43:46 geuzaine Exp $ */ /* This file is a big hack from diff --git a/Graphics/gl2gif.h b/Graphics/gl2gif.h index 882fab9092ceb1e9d24e77577fab59a1ed2623cb..bbad10d3e3b8ec77e33a1a2f30aedd80629b7d71 100644 --- a/Graphics/gl2gif.h +++ b/Graphics/gl2gif.h @@ -1,4 +1,3 @@ -/* $Id: gl2gif.h,v 1.3 2000-11-26 15:43:46 geuzaine Exp $ */ #ifndef _GL2GIF_H_ #define _GL2GIF_H_ diff --git a/Makefile b/Makefile index 0467be7e49eeae44b5c055a7e91a0155651aeacd..9f35aa63f4923a811f54e167fe068a52aeecffa0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.8 2000-11-27 08:24:51 geuzaine Exp $ +# $Id: Makefile,v 1.9 2000-12-05 16:59:11 remacle Exp $ # ---------------------------------------------------------------------- # Makefile for Gmsh # ---------------------------------------------------------------------- @@ -21,7 +21,8 @@ MESA_STATIC_LIB = $(HOME)/SOURCES/Mesa-3.0-static/lib/libGLw.a\ $(HOME)/SOURCES/Mesa-3.0-static/lib/libGLU.a\ $(HOME)/SOURCES/Mesa-3.0-static/lib/libGL.a - MOTIF_LIB = -L/usr/X11R6/LessTif/Motif1.2/lib -lXm + MOTIF_LIB = /usr/local/lib/libXm.so.2 +# MOTIF_LIB = -L/usr/X11R6/LessTif/Motif1.2/lib -lXm X_LIB = -L/usr/X11R6/lib -lXt -lX11 -lXext THREAD_LIB = -L/usr/lib -lpthread diff --git a/Unix/CbInput.cpp b/Unix/CbInput.cpp index ce68e187453f40fab5a49b9fbfda06dff712ce39..95630d4d6397461fba2190a97ea88bfce8ff5a84 100644 --- a/Unix/CbInput.cpp +++ b/Unix/CbInput.cpp @@ -1,4 +1,4 @@ -/* $Id: CbInput.cpp,v 1.8 2000-12-05 15:23:58 geuzaine Exp $ */ +/* $Id: CbInput.cpp,v 1.9 2000-12-05 16:59:11 remacle Exp $ */ #include "Gmsh.h" #include "GmshUI.h" @@ -634,11 +634,23 @@ void InputCb (Widget w, XtPointer client_data, GLwDrawingAreaCallbackStruct *cb) switch(ibut){ case 1: - set_r(1, CTX.r[1] + ((abs(movx) > abs(movy))?180*(float)movx/(float)width:0)); - set_r(0, CTX.r[0] + ((abs(movx) > abs(movy))?0:180*(float)movy/(float)height)); + + if(CTX.useTrackball) + { + CTX.addQuaternion ((2.0*x - width) / width, + (height - 2.0*y) / height, + (2.0*event->xbutton.x - width) / width, + (height - 2.0*event->xbutton.y) / height); + } + else + { + set_r(1, CTX.r[1] + ((abs(movx) > abs(movy))?180*(float)movx/(float)width:0)); + set_r(0, CTX.r[0] + ((abs(movx) > abs(movy))?0:180*(float)movy/(float)height)); + } break; case 2: - set_r(2, CTX.r[2] + ((abs(movy) > abs(movx))?0:-180*(float)movx/(float)width)); + if(!CTX.useTrackball) + set_r(2, CTX.r[2] + ((abs(movy) > abs(movx))?0:-180*(float)movx/(float)width)); set_s(0, CTX.s[0] * ( (abs(movy) > abs(movx)) ? ( (movy>0) ? (float)(1.04*(abs(movy)+height))/(float)height @@ -706,3 +718,4 @@ void InputCb (Widget w, XtPointer client_data, GLwDrawingAreaCallbackStruct *cb) break; } } +