39 |
|
|
40 |
@implementation Quaternion |
@implementation Quaternion |
41 |
|
|
|
/* |
|
|
* This method builds an instance of Quaternion, |
|
|
* with all the attributes initialised at 0 |
|
|
*/ |
|
|
- (id) init |
|
|
{ |
|
|
self = [super init]; |
|
|
|
|
|
if (self != nil) |
|
|
{ |
|
|
_x = _y = _z = 0.0f; |
|
|
_w = 1.0f; |
|
|
} |
|
|
return self; |
|
|
} |
|
42 |
|
|
43 |
/* |
/* |
44 |
* This method builds an instance of Quaternion, |
* This method builds an instance of Quaternion, |
45 |
* with all the attributes initialised with the parameters |
* with all the attributes initialised with the parameters |
46 |
*/ |
*/ |
47 |
- (id) initWithValuesX: (float) x |
- (id) initWithValuesX: (float)x |
48 |
Y: (float) y |
Y: (float)y |
49 |
Z: (float) z |
Z: (float)z |
50 |
W: (float) w |
W: (float)w |
51 |
{ |
{ |
52 |
self = [super init]; |
self = [super init]; |
|
|
|
53 |
if (self != nil) |
if (self != nil) |
54 |
{ |
{ |
55 |
_x = x; |
_x = x; |
57 |
_z = z; |
_z = z; |
58 |
_w = w; |
_w = w; |
59 |
} |
} |
|
return self; |
|
|
} |
|
|
|
|
60 |
|
|
61 |
/* |
return self; |
|
* Frees memory. |
|
|
*/ |
|
|
- (void) dealloc { |
|
|
if (_matrix) |
|
|
free (_matrix); |
|
|
[super dealloc]; |
|
62 |
} |
} |
63 |
|
|
|
|
|
64 |
/* This method builds an instance of Quaternion, |
/* This method builds an instance of Quaternion, |
65 |
* by converting the matrix in parameter |
* by converting the matrix in parameter |
66 |
* This matrix must be a 4x4 matrix, otherwise the function will crash. |
* This matrix must be a 4x4 matrix, otherwise the function will crash. |
67 |
*/ |
*/ |
68 |
- (id) initWithMatrix: (float *)matrix |
- (id) initWithRotation: (Matrix)rotation |
69 |
{ |
{ |
70 |
NSParameterAssert (matrix); |
NSParameterAssert (rotation); |
71 |
|
|
72 |
self = [super init]; |
self = [super init]; |
|
|
|
73 |
if (self != nil) |
if (self != nil) |
74 |
{ |
{ |
75 |
float trace = matrix[0] + matrix[5] + matrix[10] + 1; |
float trace = rotation[0] + rotation[5] + rotation[10] + 1; |
76 |
float scale = 0.0f; |
float scale = 0.0f; |
77 |
|
|
78 |
if (trace > 0 + DELTA) |
if (trace > 0 + DELTA) |
79 |
{ |
{ |
80 |
scale = (float) (sqrt (trace) * 2); |
scale = (float)(sqrt (trace) * 2); |
81 |
|
|
82 |
_x = (matrix[9] - matrix[6] ) / scale; |
_x = (rotation[9] - rotation[6]) / scale; |
83 |
_y = (matrix[2] - matrix[8] ) / scale; |
_y = (rotation[2] - rotation[8]) / scale; |
84 |
_z = (matrix[4] - matrix[1] ) / scale; |
_z = (rotation[4] - rotation[1]) / scale; |
85 |
_w = 0.25f * scale; |
_w = 0.25f * scale; |
86 |
} |
} |
87 |
else |
else |
88 |
{ |
{ |
89 |
if (matrix[0] > matrix[5] && matrix[0] > matrix[10]) |
if (rotation[0] > rotation[5] && rotation[0] > rotation[10]) |
90 |
{ |
{ |
91 |
scale = |
scale = |
92 |
(float) sqrt (1.0f + matrix[0] - matrix[5] - matrix[10]) *2.0f; |
(float)sqrt (1.0f + rotation[0] - rotation[5] - rotation[10]) |
93 |
|
* 2.0f; |
94 |
|
|
95 |
_x = 0.25f * scale; |
_x = 0.25f * scale; |
96 |
_y = (matrix[4] + matrix[1] ) / scale; |
_y = (rotation[4] + rotation[1]) / scale; |
97 |
_z = (matrix[2] + matrix[8] ) / scale; |
_z = (rotation[2] + rotation[8]) / scale; |
98 |
_w = (matrix[9] - matrix[6] ) / scale; |
_w = (rotation[9] - rotation[6]) / scale; |
99 |
} |
} |
100 |
else if (matrix[5] > matrix[10]) |
else if (rotation[5] > rotation[10]) |
101 |
{ |
{ |
102 |
scale = |
scale = |
103 |
(float) sqrt (1.0f + matrix[5] - matrix[0] - matrix[10]) *2.0f; |
(float)sqrt (1.0f + rotation[5] - rotation[0] - rotation[10]) |
104 |
|
* 2.0f; |
105 |
|
|
106 |
_x = (matrix[4] + matrix[1]) / scale; |
_x = (rotation[4] + rotation[1]) / scale; |
107 |
_y = 0.25f * scale; |
_y = 0.25f * scale; |
108 |
_z = (matrix[9] + matrix[6]) / scale; |
_z = (rotation[9] + rotation[6]) / scale; |
109 |
_w = (matrix[2] - matrix[8]) / scale; |
_w = (rotation[2] - rotation[8]) / scale; |
110 |
} |
} |
111 |
else |
else |
112 |
{ |
{ |
113 |
scale = |
scale = |
114 |
(float) sqrt (1.0f + matrix[10] - matrix[0] - matrix[5]) *2.0f; |
(float)sqrt (1.0f + rotation[10] - rotation[0] - rotation[5]) |
115 |
|
* 2.0f; |
116 |
|
|
117 |
_x = (matrix[2] + matrix[8]) / scale; |
_x = (rotation[2] + rotation[8]) / scale; |
118 |
_y = (matrix[9] + matrix[6]) / scale; |
_y = (rotation[9] + rotation[6]) / scale; |
119 |
_z = 0.25f * scale; |
_z = 0.25f * scale; |
120 |
_w = (matrix[4] - matrix[1]) / scale; |
_w = (rotation[4] - rotation[1]) / scale; |
121 |
} |
} |
122 |
} |
} |
123 |
} |
} |
124 |
|
|
125 |
return self; |
return self; |
126 |
} |
} |
127 |
|
|
128 |
/* |
/* |
129 |
* This method returns the matrix 4x4 corresponding to the quaternion. |
* This method returns the rotation matrix 4x4 corresponding to the quaternion. |
130 |
* So it converts a quaternion to a matrix 4x4. |
* So it converts a quaternion to a matrix 4x4. |
131 |
*/ |
*/ |
132 |
- (float *) createMatrix |
- (void) convertToRotation: (Matrix)rotation |
133 |
{ |
{ |
|
if ((_matrix = (float *) malloc (16 * sizeof (float))) == NULL) |
|
|
{ |
|
|
fprintf (stderr, "It ' s impossible to create a 4x4 matrix: " |
|
|
"memory allocation has failed.\n"); |
|
|
exit (-1); |
|
|
} |
|
|
|
|
134 |
float xx = _x * _x; |
float xx = _x * _x; |
135 |
float xy = _x * _y; |
float xy = _x * _y; |
136 |
float xz = _x * _z; |
float xz = _x * _z; |
142 |
float zw = _z * _w; |
float zw = _z * _w; |
143 |
|
|
144 |
/* first row */ |
/* first row */ |
145 |
_matrix[0] = 1.0f - 2.0f * ( yy + zz ); |
rotation[0] = 1.0f - 2.0f * (yy + zz); |
146 |
_matrix[1] = 2.0f * ( xy - zw ); |
rotation[1] = 2.0f * (xy - zw); |
147 |
_matrix[2] = 2.0f * ( xz + yw ); |
rotation[2] = 2.0f * (xz + yw); |
148 |
_matrix[3] = 0; |
rotation[3] = 0; |
149 |
|
|
150 |
/* second row */ |
/* second row */ |
151 |
_matrix[4] = 2.0f * ( xy + zw ); |
rotation[4] = 2.0f * (xy + zw); |
152 |
_matrix[5] = 1.0f - 2.0f * ( xx + zz ); |
rotation[5] = 1.0f - 2.0f * (xx + zz); |
153 |
_matrix[6] = 2.0f * ( yz - xw ); |
rotation[6] = 2.0f * (yz - xw); |
154 |
_matrix[7] = 0; |
rotation[7] = 0; |
155 |
|
|
156 |
/* third row */ |
/* third row */ |
157 |
_matrix[8] = 2.0f * ( xz - yw ); |
rotation[8] = 2.0f * (xz - yw); |
158 |
_matrix[9] = 2.0f * ( yz + xw ); |
rotation[9] = 2.0f * (yz + xw); |
159 |
_matrix[10] = 1.0f - 2.0f * ( xx + yy ); |
rotation[10] = 1.0f - 2.0f * (xx + yy); |
160 |
_matrix[11] = 0; |
rotation[11] = 0; |
161 |
|
|
162 |
/* fourth row */ |
/* fourth row */ |
163 |
_matrix[12] = 0; |
rotation[12] = 0; |
164 |
_matrix[13] = 0; |
rotation[13] = 0; |
165 |
_matrix[14] = 0; |
rotation[14] = 0; |
166 |
_matrix[15] = 1.0f; |
rotation[15] = 1.0f; |
|
|
|
|
return _matrix; |
|
167 |
} |
} |
168 |
|
|
169 |
|
|
171 |
* Says if the quaternion in parameter is egal to the current quaternionn, i.e. |
* Says if the quaternion in parameter is egal to the current quaternionn, i.e. |
172 |
* the values x, y, z and z are egal. |
* the values x, y, z and z are egal. |
173 |
*/ |
*/ |
174 |
- (BOOL) isEqual: (Quaternion *) quat |
- (BOOL) isEqual: (Quaternion *)quat |
175 |
{ |
{ |
176 |
NSParameterAssert (quat); |
NSParameterAssert (quat); |
177 |
|
|
192 |
* t represents the time for the interpolation; it must be valued |
* t represents the time for the interpolation; it must be valued |
193 |
* between 0 and 1. |
* between 0 and 1. |
194 |
*/ |
*/ |
195 |
- (void) slerp: (Quaternion *) q1 |
- (void) slerp: (Quaternion *)q1 |
196 |
with: (Quaternion *) q2 |
with: (Quaternion *)q2 |
197 |
accordingTime: (float) t |
accordingTime: (float)t |
198 |
{ |
{ |
199 |
NSParameterAssert (q1); |
NSParameterAssert (q1); |
200 |
NSParameterAssert (q2); |
NSParameterAssert (q2); |
205 |
if ([q1 isEqual: q2]) |
if ([q1 isEqual: q2]) |
206 |
{ |
{ |
207 |
[self initWithValuesX: q1->_x |
[self initWithValuesX: q1->_x |
208 |
Y: q1->_y |
Y: q1->_y |
209 |
Z: q1->_z |
Z: q1->_z |
210 |
W: q1->_w]; |
W: q1->_w]; |
211 |
} |
} |
|
|
|
212 |
else |
else |
213 |
{ |
{ |
214 |
float dotProduct = |
float dotProduct = |
215 |
(q1->_x * q2->_x) + (q1->_y * q2->_y) + |
q1->_x * q2->_x + q1->_y * q2->_y + |
216 |
(q1->_z * q2->_z) + (q1->_w * q2->_w); |
q1->_z * q2->_z + q1->_w * q2->_w; |
217 |
float scale0 = 1 - t, scale1 = t; |
float scale0 = 1 - t; |
218 |
|
float scale1 = t; |
219 |
|
|
220 |
if (dotProduct < 0.0f) /* angle >= 90° */ |
if (dotProduct < 0.0f) /* angle >= 90° */ |
221 |
{ |
{ |
230 |
*/ |
*/ |
231 |
if (1 - dotProduct > MIN_VALUE_SPHERICAL_INTERPOLATION) |
if (1 - dotProduct > MIN_VALUE_SPHERICAL_INTERPOLATION) |
232 |
{ |
{ |
233 |
float theta = (float) acos (dotProduct); |
float theta = (float)acos (dotProduct); |
234 |
float sinTheta = (float) sin (theta); |
float sinTheta = (float)sin (theta); |
235 |
|
|
236 |
scale0 = (float) sin ((1-t) * theta) / sinTheta; |
scale0 = (float)sin ((1-t) * theta) / sinTheta; |
237 |
scale1 = (float) sin (t * theta) / sinTheta; |
scale1 = (float)sin (t * theta) / sinTheta; |
238 |
} |
} |
239 |
|
|
240 |
_x = (scale0 * q1->_x) + (scale1 * q2->_x); |
_x = scale0 * q1->_x + scale1 * q2->_x; |
241 |
_y = (scale0 * q1->_y) + (scale1 * q2->_y); |
_y = scale0 * q1->_y + scale1 * q2->_y; |
242 |
_z = (scale0 * q1->_z) + (scale1 * q2->_z); |
_z = scale0 * q1->_z + scale1 * q2->_z; |
243 |
_w = (scale0 * q1->_w) + (scale1 * q2->_w); |
_w = scale0 * q1->_w + scale1 * q2->_w; |
244 |
} |
} |
245 |
} |
} |
246 |
|
|