-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtrackball.cpp
161 lines (144 loc) · 5.77 KB
/
trackball.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <math.h>
#include "trackball.hpp"
/*******************************************************
*
* void vCalcRotVec(float fNewX, float fNewY,
* float fOldX, float fOldY,
* float fDiameter,
* float *fVecX, float *fVecY, float *fVecZ);
*
* Calculates a rotation vector based on mouse motion over
* a virtual trackball.
*
* The fNew and fOld mouse positions
* should be in 'trackball' space. That is, they have been
* transformed into a coordinate system centered at the middle
* of the trackball. fNew, fOld, and fDiameter must all be specified
* in the same units (pixels for example).
*
* Parameters: fNewX, fNewY - New mouse position in trackball space.
* This is the second point along direction
* of rotation.
* fOldX, fOldY - Old mouse position in trackball space.
* This is the first point along direction
* of rotation.
* fDiameter - Diameter of the trackball. This should
* be specified in the same units as fNew and fOld.
* (ie, usually pixels if fNew and fOld are transformed
* mouse positions)
* fVec - The output rotation vector. The length of the vector
* is proportional to the angle of rotation.
*
*******************************************************/
void vCalcRotVec(float fNewX, float fNewY,
float fOldX, float fOldY,
float fDiameter,
float *fVecX, float *fVecY, float *fVecZ) {
long nXOrigin, nYOrigin;
float fNewVecX, fNewVecY, fNewVecZ, /* Vector corresponding to new mouse location */
fOldVecX, fOldVecY, fOldVecZ, /* Vector corresponding to old mouse location */
fLength;
/* Vector pointing from center of virtual trackball to
* new mouse position
*/
fNewVecX = fNewX * 2.0 / fDiameter;
fNewVecY = fNewY * 2.0 / fDiameter;
fNewVecZ = (1.0 - fNewVecX * fNewVecX - fNewVecY * fNewVecY);
/* If the Z component is less than 0, the mouse point
* falls outside of the trackball which is interpreted
* as rotation about the Z axis.
*/
if (fNewVecZ < 0.0) {
fLength = sqrt(1.0 - fNewVecZ);
fNewVecZ = 0.0;
fNewVecX /= fLength;
fNewVecY /= fLength;
} else {
fNewVecZ = sqrt(fNewVecZ);
}
/* Vector pointing from center of virtual trackball to
* old mouse position
*/
fOldVecX = fOldX * 2.0 / fDiameter;
fOldVecY = fOldY * 2.0 / fDiameter;
fOldVecZ = (1.0 - fOldVecX * fOldVecX - fOldVecY * fOldVecY);
/* If the Z component is less than 0, the mouse point
* falls outside of the trackball which is interpreted
* as rotation about the Z axis.
*/
if (fOldVecZ < 0.0) {
fLength = sqrt(1.0 - fOldVecZ);
fOldVecZ = 0.0;
fOldVecX /= fLength;
fOldVecY /= fLength;
} else {
fOldVecZ = sqrt(fOldVecZ);
}
/* Generate rotation vector by calculating cross product:
*
* fOldVec x fNewVec.
*
* The rotation vector is the axis of rotation
* and is non-unit length since the length of a crossproduct
* is related to the angle between fOldVec and fNewVec which we need
* in order to perform the rotation.
*/
*fVecX = fOldVecY * fNewVecZ - fNewVecY * fOldVecZ;
*fVecY = fOldVecZ * fNewVecX - fNewVecZ * fOldVecX;
*fVecZ = fOldVecX * fNewVecY - fNewVecX * fOldVecY;
}
/*******************************************************
* void vAxisRotMatrix(float fVecX, float fVecY, float fVecZ, Matrix mNewMat)
*
* Calculate the rotation matrix for rotation about an arbitrary axis.
*
* The axis of rotation is specified by (fVecX,fVecY,fVecZ). The length
* of the vector is the amount to rotate by.
*
* Parameters: fVecX,fVecY,fVecZ - Axis of rotation
* mNewMat - Output matrix of rotation in column-major format
* (ie, translation components are in column 3 on rows
* 0,1, and 2).
*
*******************************************************/
glm::mat4 vAxisRotMatrix(float fVecX, float fVecY, float fVecZ) {
glm::mat4 mNewMat;
float fRadians, fInvLength, fNewVecX, fNewVecY, fNewVecZ;
/* Find the length of the vector which is the angle of rotation
* (in radians)
*/
fRadians = sqrt(fVecX * fVecX + fVecY * fVecY + fVecZ * fVecZ);
/* If the vector has zero length - return the identity matrix */
if (fRadians > -0.000001 && fRadians < 0.000001) {
mNewMat = glm::mat4();
return mNewMat;
}
/* Normalize the rotation vector now in preparation for making
* rotation matrix.
*/
fInvLength = 1 / fRadians;
fNewVecX = fVecX * fInvLength;
fNewVecY = fVecY * fInvLength;
fNewVecZ = fVecZ * fInvLength;
/* Create the arbitrary axis rotation matrix */
double dSinAlpha = sin(fRadians);
double dCosAlpha = cos(fRadians);
double dT = 1 - dCosAlpha;
mNewMat[0][0] = dCosAlpha + fNewVecX*fNewVecX*dT;
mNewMat[0][1] = fNewVecX*fNewVecY*dT + fNewVecZ*dSinAlpha;
mNewMat[0][2] = fNewVecX*fNewVecZ*dT - fNewVecY*dSinAlpha;
mNewMat[0][3] = 0;
mNewMat[1][0] = fNewVecX*fNewVecY*dT - dSinAlpha*fNewVecZ;
mNewMat[1][1] = dCosAlpha + fNewVecY*fNewVecY*dT;
mNewMat[1][2] = fNewVecY*fNewVecZ*dT + dSinAlpha*fNewVecX;
mNewMat[1][3] = 0;
mNewMat[2][0] = fNewVecZ*fNewVecX*dT + dSinAlpha*fNewVecY;
mNewMat[2][1] = fNewVecZ*fNewVecY*dT - dSinAlpha*fNewVecX;
mNewMat[2][2] = dCosAlpha + fNewVecZ*fNewVecZ*dT;
mNewMat[2][3] = 0;
mNewMat[3][0] = 0;
mNewMat[3][1] = 0;
mNewMat[3][2] = 0;
mNewMat[3][3] = 1;
return mNewMat;
}