[4] | 1 | //
|
---|
| 2 | // ============================================================
|
---|
| 3 | // === OpenGL Library ===
|
---|
| 4 | //
|
---|
| 5 | // $Date: 2004/10/28 22:43:53 $
|
---|
| 6 | // $Revision: 1.1 $
|
---|
| 7 | //
|
---|
| 8 | // Hacked into C++ from SGI's trackball.h---see copyright
|
---|
| 9 | // at end.
|
---|
| 10 | //
|
---|
| 11 | // ============================================================
|
---|
| 12 | //
|
---|
| 13 |
|
---|
| 14 | #include <iostream.h>
|
---|
| 15 | #include <string.h>
|
---|
| 16 | #include <limits.h>
|
---|
| 17 | #include <assert.h>
|
---|
| 18 | #include <math.h>
|
---|
| 19 |
|
---|
| 20 | #include "Trackball.h"
|
---|
| 21 | #include "VectorMath.h"
|
---|
| 22 | #include "MatrixMath.h"
|
---|
| 23 |
|
---|
| 24 |
|
---|
| 25 | //===========================================================================
|
---|
| 26 | //===========================================================================
|
---|
| 27 | // Static Initialization
|
---|
| 28 | //===========================================================================
|
---|
| 29 | //===========================================================================
|
---|
| 30 |
|
---|
| 31 | // This size should really be based on the distance from the center of
|
---|
| 32 | // rotation to the point on the object underneath the mouse. That
|
---|
| 33 | // point would then track the mouse as closely as possible. This is a
|
---|
| 34 | // simple example, though, so that is left as an Exercise for the
|
---|
| 35 | // Programmer.
|
---|
| 36 | float Trackball::trackballSize = (float)0.9;
|
---|
| 37 |
|
---|
| 38 | // Number of iterations before we renormalize.
|
---|
| 39 | int Trackball::renormCount = 97;
|
---|
| 40 |
|
---|
| 41 |
|
---|
| 42 | //===========================================================================
|
---|
| 43 | //===========================================================================
|
---|
| 44 | // Constructors/Destructor
|
---|
| 45 | //===========================================================================
|
---|
| 46 | //===========================================================================
|
---|
| 47 |
|
---|
| 48 | Trackball::Trackball()
|
---|
| 49 | {
|
---|
| 50 | lastX = 0.0;
|
---|
| 51 | lastY = 0.0;
|
---|
| 52 | vZero(lastQuat);
|
---|
| 53 | vZero(curQuat);
|
---|
| 54 | lastQuat[3] = 1.0;
|
---|
| 55 | curQuat[3] = 1.0;
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 |
|
---|
| 59 | Trackball::~Trackball()
|
---|
| 60 | {
|
---|
| 61 | // Empty.
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 |
|
---|
| 65 |
|
---|
| 66 | //===========================================================================
|
---|
| 67 | // Public Member Functions
|
---|
| 68 | //===========================================================================
|
---|
| 69 |
|
---|
| 70 | void
|
---|
| 71 | Trackball::start(float x, float y)
|
---|
| 72 | {
|
---|
| 73 | lastX = x;
|
---|
| 74 | lastY = y;
|
---|
| 75 | vZero(lastQuat);
|
---|
| 76 | lastQuat[3] = 1.0;
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 |
|
---|
| 80 |
|
---|
| 81 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 82 | //
|
---|
| 83 | // Ok, simulate a track-ball. Project the points onto the virtual
|
---|
| 84 | // trackball, then figure out the axis of rotation, which is the cross
|
---|
| 85 | // product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
|
---|
| 86 | // Note: This is a deformed trackball-- is a trackball in the center,
|
---|
| 87 | // but is deformed into a hyperbolic sheet of rotation away from the
|
---|
| 88 | // center. This particular function was chosen after trying out
|
---|
| 89 | // several variations.
|
---|
| 90 | //
|
---|
| 91 | // It is assumed that the arguments to this routine are in the range
|
---|
| 92 | // (-1.0 ... 1.0)
|
---|
| 93 | //
|
---|
| 94 | void
|
---|
| 95 | Trackball::update(float x, float y)
|
---|
| 96 | {
|
---|
| 97 | float p1[3], p2[3], d[3];
|
---|
| 98 | float t;
|
---|
| 99 |
|
---|
| 100 | // Might just be able to return here.
|
---|
| 101 | if (lastX == x && lastY == y) {
|
---|
| 102 | /* Zero rotation */
|
---|
| 103 | vZero(lastQuat);
|
---|
| 104 | lastQuat[3] = 1.0;
|
---|
| 105 | return;
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | /*
|
---|
| 109 | * First, figure out z-coordinates for projection of P1 and P2 to
|
---|
| 110 | * deformed sphere
|
---|
| 111 | */
|
---|
| 112 | vSet(p1, lastX, lastY, projectToSphere(trackballSize, lastX, lastY));
|
---|
| 113 | vSet(p2, x, y, projectToSphere(trackballSize, x, y));
|
---|
| 114 |
|
---|
| 115 | /*
|
---|
| 116 | * Now, we want the cross product of P1 and P2
|
---|
| 117 | */
|
---|
| 118 | vCross(p2, p1, a);
|
---|
| 119 |
|
---|
| 120 | /*
|
---|
| 121 | * Figure out how much to rotate around that axis.
|
---|
| 122 | */
|
---|
| 123 | vSub(p1,p2,d);
|
---|
| 124 | t = (float)(vLength(d) / (2.0*trackballSize));
|
---|
| 125 |
|
---|
| 126 | /*
|
---|
| 127 | * Avoid problems with out-of-control values...
|
---|
| 128 | */
|
---|
| 129 | if (t > 1.0) t = 1.0;
|
---|
| 130 | if (t < -1.0) t = -1.0;
|
---|
| 131 | phi = (float)(2.0 * asin(t));
|
---|
| 132 |
|
---|
| 133 | axisToQuat(a, phi, lastQuat);
|
---|
| 134 |
|
---|
| 135 | lastX = x;
|
---|
| 136 | lastY = y;
|
---|
| 137 |
|
---|
| 138 | addQuats(lastQuat, curQuat, curQuat);
|
---|
| 139 | }
|
---|
| 140 |
|
---|
| 141 | //get the axis and angle for the rotation
|
---|
| 142 | void Trackball::getAxisAngle(float& angle, float axis[3]) {
|
---|
| 143 | angle = phi*180.0f/3.141517;
|
---|
| 144 | for (int i=0;i<3;i++)
|
---|
| 145 | axis[i] = a[i];
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 149 | // joeys clear
|
---|
| 150 | //
|
---|
| 151 | void
|
---|
| 152 | Trackball::clear()
|
---|
| 153 | {
|
---|
| 154 | lastX = 0.0;
|
---|
| 155 | lastY = 0.0;
|
---|
| 156 | vZero(lastQuat);
|
---|
| 157 | vZero(curQuat);
|
---|
| 158 | lastQuat[3] = 1.0;
|
---|
| 159 | curQuat[3] = 1.0;
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 |
|
---|
| 163 |
|
---|
| 164 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 165 | //
|
---|
| 166 | // Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
|
---|
| 167 | // if we are away from the center of the sphere.
|
---|
| 168 | //
|
---|
| 169 | float
|
---|
| 170 | Trackball::projectToSphere(float r, float x, float y)
|
---|
| 171 | {
|
---|
| 172 | float d, t, z;
|
---|
| 173 |
|
---|
| 174 | d = (float)(sqrt(x*x + y*y));
|
---|
| 175 | if (d < r * 0.70710678118654752440) { /* Inside sphere */
|
---|
| 176 | z = (float)(sqrt(r*r - d*d));
|
---|
| 177 | } else { /* On hyperbola */
|
---|
| 178 | t = (float)(r / 1.41421356237309504880);
|
---|
| 179 | z = t*t / d;
|
---|
| 180 | }
|
---|
| 181 | return z;
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 |
|
---|
| 185 |
|
---|
| 186 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 187 | //
|
---|
| 188 | // Build a rotation matrix, given a quaternion rotation.
|
---|
| 189 | //
|
---|
| 190 | void
|
---|
| 191 | Trackball::buildRotMatrix(float m[4][4])
|
---|
| 192 | {
|
---|
| 193 | m[0][0] = (float)(1.0 - 2.0 * (curQuat[1] * curQuat[1] + curQuat[2] * curQuat[2]));
|
---|
| 194 | m[0][1] = (float)(2.0 * (curQuat[0] * curQuat[1] - curQuat[2] * curQuat[3]));
|
---|
| 195 | m[0][2] = (float)(2.0 * (curQuat[2] * curQuat[0] + curQuat[1] * curQuat[3]));
|
---|
| 196 | m[0][3] = (float)(0.0);
|
---|
| 197 |
|
---|
| 198 | m[1][0] = (float)(2.0 * (curQuat[0] * curQuat[1] + curQuat[2] * curQuat[3]));
|
---|
| 199 | m[1][1]= (float)(1.0 - 2.0 * (curQuat[2] * curQuat[2] + curQuat[0] * curQuat[0]));
|
---|
| 200 | m[1][2] = (float)(2.0 * (curQuat[1] * curQuat[2] - curQuat[0] * curQuat[3]));
|
---|
| 201 | m[1][3] = (float)(0.0);
|
---|
| 202 |
|
---|
| 203 | m[2][0] = (float)(2.0 * (curQuat[2] * curQuat[0] - curQuat[1] * curQuat[3]));
|
---|
| 204 | m[2][1] = (float)(2.0 * (curQuat[1] * curQuat[2] + curQuat[0] * curQuat[3]));
|
---|
| 205 | m[2][2] = (float)(1.0 - 2.0 * (curQuat[1] * curQuat[1] + curQuat[0] * curQuat[0]));
|
---|
| 206 | m[2][3] = (float)(0.0);
|
---|
| 207 |
|
---|
| 208 | m[3][0] = (float)(0.0);
|
---|
| 209 | m[3][1] = (float)(0.0);
|
---|
| 210 | m[3][2] = (float)(0.0);
|
---|
| 211 | m[3][3] = (float)(1.0);
|
---|
| 212 | }
|
---|
| 213 |
|
---|
| 214 | void
|
---|
| 215 | Trackball::reapply()
|
---|
| 216 | {
|
---|
| 217 | addQuats(lastQuat, curQuat, curQuat);
|
---|
| 218 | }
|
---|