source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/src/math/Quaternion.js@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 8.4 KB
Line 
1/**
2 * @author mikael emtinger / http://gomo.se/
3 * @author alteredq / http://alteredqualia.com/
4 * @author WestLangley / http://github.com/WestLangley
5 * @author bhouston / http://exocortex.com
6 */
7
8THREE.Quaternion = function ( x, y, z, w ) {
9
10 this._x = x || 0;
11 this._y = y || 0;
12 this._z = z || 0;
13 this._w = ( w !== undefined ) ? w : 1;
14
15};
16
17THREE.Quaternion.prototype = {
18
19 constructor: THREE.Quaternion,
20
21 _x: 0,_y: 0, _z: 0, _w: 0,
22
23 _euler: undefined,
24
25 _updateEuler: function ( callback ) {
26
27 if ( this._euler !== undefined ) {
28
29 this._euler.setFromQuaternion( this, undefined, false );
30
31 }
32
33 },
34
35 get x () {
36
37 return this._x;
38
39 },
40
41 set x ( value ) {
42
43 this._x = value;
44 this._updateEuler();
45
46 },
47
48 get y () {
49
50 return this._y;
51
52 },
53
54 set y ( value ) {
55
56 this._y = value;
57 this._updateEuler();
58
59 },
60
61 get z () {
62
63 return this._z;
64
65 },
66
67 set z ( value ) {
68
69 this._z = value;
70 this._updateEuler();
71
72 },
73
74 get w () {
75
76 return this._w;
77
78 },
79
80 set w ( value ) {
81
82 this._w = value;
83 this._updateEuler();
84
85 },
86
87 set: function ( x, y, z, w ) {
88
89 this._x = x;
90 this._y = y;
91 this._z = z;
92 this._w = w;
93
94 this._updateEuler();
95
96 return this;
97
98 },
99
100 copy: function ( quaternion ) {
101
102 this._x = quaternion._x;
103 this._y = quaternion._y;
104 this._z = quaternion._z;
105 this._w = quaternion._w;
106
107 this._updateEuler();
108
109 return this;
110
111 },
112
113 setFromEuler: function ( euler, update ) {
114
115 if ( euler instanceof THREE.Euler === false ) {
116
117 throw new Error( 'ERROR: Quaternion\'s .setFromEuler() now expects a Euler rotation rather than a Vector3 and order. Please update your code.' );
118 }
119
120 // http://www.mathworks.com/matlabcentral/fileexchange/
121 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
122 // content/SpinCalc.m
123
124 var c1 = Math.cos( euler._x / 2 );
125 var c2 = Math.cos( euler._y / 2 );
126 var c3 = Math.cos( euler._z / 2 );
127 var s1 = Math.sin( euler._x / 2 );
128 var s2 = Math.sin( euler._y / 2 );
129 var s3 = Math.sin( euler._z / 2 );
130
131 if ( euler.order === 'XYZ' ) {
132
133 this._x = s1 * c2 * c3 + c1 * s2 * s3;
134 this._y = c1 * s2 * c3 - s1 * c2 * s3;
135 this._z = c1 * c2 * s3 + s1 * s2 * c3;
136 this._w = c1 * c2 * c3 - s1 * s2 * s3;
137
138 } else if ( euler.order === 'YXZ' ) {
139
140 this._x = s1 * c2 * c3 + c1 * s2 * s3;
141 this._y = c1 * s2 * c3 - s1 * c2 * s3;
142 this._z = c1 * c2 * s3 - s1 * s2 * c3;
143 this._w = c1 * c2 * c3 + s1 * s2 * s3;
144
145 } else if ( euler.order === 'ZXY' ) {
146
147 this._x = s1 * c2 * c3 - c1 * s2 * s3;
148 this._y = c1 * s2 * c3 + s1 * c2 * s3;
149 this._z = c1 * c2 * s3 + s1 * s2 * c3;
150 this._w = c1 * c2 * c3 - s1 * s2 * s3;
151
152 } else if ( euler.order === 'ZYX' ) {
153
154 this._x = s1 * c2 * c3 - c1 * s2 * s3;
155 this._y = c1 * s2 * c3 + s1 * c2 * s3;
156 this._z = c1 * c2 * s3 - s1 * s2 * c3;
157 this._w = c1 * c2 * c3 + s1 * s2 * s3;
158
159 } else if ( euler.order === 'YZX' ) {
160
161 this._x = s1 * c2 * c3 + c1 * s2 * s3;
162 this._y = c1 * s2 * c3 + s1 * c2 * s3;
163 this._z = c1 * c2 * s3 - s1 * s2 * c3;
164 this._w = c1 * c2 * c3 - s1 * s2 * s3;
165
166 } else if ( euler.order === 'XZY' ) {
167
168 this._x = s1 * c2 * c3 - c1 * s2 * s3;
169 this._y = c1 * s2 * c3 - s1 * c2 * s3;
170 this._z = c1 * c2 * s3 + s1 * s2 * c3;
171 this._w = c1 * c2 * c3 + s1 * s2 * s3;
172
173 }
174
175 if ( update !== false ) this._updateEuler();
176
177 return this;
178
179 },
180
181 setFromAxisAngle: function ( axis, angle ) {
182
183 // from http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
184 // axis have to be normalized
185
186 var halfAngle = angle / 2, s = Math.sin( halfAngle );
187
188 this._x = axis.x * s;
189 this._y = axis.y * s;
190 this._z = axis.z * s;
191 this._w = Math.cos( halfAngle );
192
193 this._updateEuler();
194
195 return this;
196
197 },
198
199 setFromRotationMatrix: function ( m ) {
200
201 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
202
203 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
204
205 var te = m.elements,
206
207 m11 = te[0], m12 = te[4], m13 = te[8],
208 m21 = te[1], m22 = te[5], m23 = te[9],
209 m31 = te[2], m32 = te[6], m33 = te[10],
210
211 trace = m11 + m22 + m33,
212 s;
213
214 if ( trace > 0 ) {
215
216 s = 0.5 / Math.sqrt( trace + 1.0 );
217
218 this._w = 0.25 / s;
219 this._x = ( m32 - m23 ) * s;
220 this._y = ( m13 - m31 ) * s;
221 this._z = ( m21 - m12 ) * s;
222
223 } else if ( m11 > m22 && m11 > m33 ) {
224
225 s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
226
227 this._w = (m32 - m23 ) / s;
228 this._x = 0.25 * s;
229 this._y = (m12 + m21 ) / s;
230 this._z = (m13 + m31 ) / s;
231
232 } else if ( m22 > m33 ) {
233
234 s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
235
236 this._w = (m13 - m31 ) / s;
237 this._x = (m12 + m21 ) / s;
238 this._y = 0.25 * s;
239 this._z = (m23 + m32 ) / s;
240
241 } else {
242
243 s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
244
245 this._w = ( m21 - m12 ) / s;
246 this._x = ( m13 + m31 ) / s;
247 this._y = ( m23 + m32 ) / s;
248 this._z = 0.25 * s;
249
250 }
251
252 this._updateEuler();
253
254 return this;
255
256 },
257
258 inverse: function () {
259
260 this.conjugate().normalize();
261
262 return this;
263
264 },
265
266 conjugate: function () {
267
268 this._x *= -1;
269 this._y *= -1;
270 this._z *= -1;
271
272 this._updateEuler();
273
274 return this;
275
276 },
277
278 lengthSq: function () {
279
280 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
281
282 },
283
284 length: function () {
285
286 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
287
288 },
289
290 normalize: function () {
291
292 var l = this.length();
293
294 if ( l === 0 ) {
295
296 this._x = 0;
297 this._y = 0;
298 this._z = 0;
299 this._w = 1;
300
301 } else {
302
303 l = 1 / l;
304
305 this._x = this._x * l;
306 this._y = this._y * l;
307 this._z = this._z * l;
308 this._w = this._w * l;
309
310 }
311
312 return this;
313
314 },
315
316 multiply: function ( q, p ) {
317
318 if ( p !== undefined ) {
319
320 console.warn( 'DEPRECATED: Quaternion\'s .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
321 return this.multiplyQuaternions( q, p );
322
323 }
324
325 return this.multiplyQuaternions( this, q );
326
327 },
328
329 multiplyQuaternions: function ( a, b ) {
330
331 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
332
333 var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
334 var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
335
336 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
337 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
338 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
339 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
340
341 this._updateEuler();
342
343 return this;
344
345 },
346
347 multiplyVector3: function ( vector ) {
348
349 console.warn( 'DEPRECATED: Quaternion\'s .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
350 return vector.applyQuaternion( this );
351
352 },
353
354 slerp: function ( qb, t ) {
355
356 var x = this._x, y = this._y, z = this._z, w = this._w;
357
358 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
359
360 var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
361
362 if ( cosHalfTheta < 0 ) {
363
364 this._w = -qb._w;
365 this._x = -qb._x;
366 this._y = -qb._y;
367 this._z = -qb._z;
368
369 cosHalfTheta = -cosHalfTheta;
370
371 } else {
372
373 this.copy( qb );
374
375 }
376
377 if ( cosHalfTheta >= 1.0 ) {
378
379 this._w = w;
380 this._x = x;
381 this._y = y;
382 this._z = z;
383
384 return this;
385
386 }
387
388 var halfTheta = Math.acos( cosHalfTheta );
389 var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
390
391 if ( Math.abs( sinHalfTheta ) < 0.001 ) {
392
393 this._w = 0.5 * ( w + this._w );
394 this._x = 0.5 * ( x + this._x );
395 this._y = 0.5 * ( y + this._y );
396 this._z = 0.5 * ( z + this._z );
397
398 return this;
399
400 }
401
402 var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
403 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
404
405 this._w = ( w * ratioA + this._w * ratioB );
406 this._x = ( x * ratioA + this._x * ratioB );
407 this._y = ( y * ratioA + this._y * ratioB );
408 this._z = ( z * ratioA + this._z * ratioB );
409
410 this._updateEuler();
411
412 return this;
413
414 },
415
416 equals: function ( quaternion ) {
417
418 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
419
420 },
421
422 fromArray: function ( array ) {
423
424 this._x = array[ 0 ];
425 this._y = array[ 1 ];
426 this._z = array[ 2 ];
427 this._w = array[ 3 ];
428
429 this._updateEuler();
430
431 return this;
432
433 },
434
435 toArray: function () {
436
437 return [ this._x, this._y, this._z, this._w ];
438
439 },
440
441 clone: function () {
442
443 return new THREE.Quaternion( this._x, this._y, this._z, this._w );
444
445 }
446
447};
448
449THREE.Quaternion.slerp = function ( qa, qb, qm, t ) {
450
451 return qm.copy( qa ).slerp( qb, t );
452
453}
Note: See TracBrowser for help on using the repository browser.