Vector4.js 7.3 KB
Newer Older
1 2
/**
 * @author supereggbert / http://www.paulbrunt.co.uk/
M
Mr.doob 已提交
3
 * @author philogb / http://blog.thejit.org/
4
 * @author mikael emtinger / http://gomo.se/
M
Mr.doob 已提交
5
 * @author egraether / http://egraether.com/
W
WestLangley 已提交
6
 * @author WestLangley / http://github.com/WestLangley
7 8 9 10
 */

THREE.Vector4 = function ( x, y, z, w ) {

11 12 13
	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;
14
	this.w = ( w !== undefined ) ? w : 1;
15 16 17 18 19

};

THREE.Vector4.prototype = {

20 21 22
	constructor: THREE.Vector4,

	set: function ( x, y, z, w ) {
23

24 25 26 27
		this.x = x;
		this.y = y;
		this.z = z;
		this.w = w;
28

29
		return this;
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
	setX: function ( x ) {

		this.x = x;

		return this;

	},

	setY: function ( y ) {

		this.y = y;

		return this;

	},

	setZ: function ( z ) {

		this.z = z;

		return this;

	},

	setW: function ( w ) {

		this.w = w;

		return this;

	},

65 66 67 68 69 70 71 72
	setComponent: function ( index, value ) {
		this[ THREE.Vector4.__indexToName[ index ] ] = value;
	},

	getComponent: function ( index ) {
		return this[ THREE.Vector4.__indexToName[ index ] ];
	},

73
	copy: function ( v ) {
M
Mr.doob 已提交
74

75 76 77
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
78
		this.w = ( v.w !== undefined ) ? v.w : 1;
79

80 81
		return this;

82
	},
83

84 85 86 87 88 89 90 91 92 93 94
	addScalar: function ( s ) {

		this.x += s;
		this.y += s;
		this.z += s;
		this.w += s;

		return this;

	},

M
Mr.doob 已提交
95
	add: function ( a, b ) {
M
Mr.doob 已提交
96

M
Mr.doob 已提交
97 98 99 100
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
		this.w = a.w + b.w;
101

102 103
		return this;

104
	},
105

106
	addSelf: function ( v ) {
M
Mr.doob 已提交
107

M
Mr.doob 已提交
108 109 110 111
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
		this.w += v.w;
112

M
Mr.doob 已提交
113
		return this;
M
Mr.doob 已提交
114

M
Mr.doob 已提交
115 116
	},

M
Mr.doob 已提交
117
	sub: function ( a, b ) {
M
Mr.doob 已提交
118

M
Mr.doob 已提交
119 120 121 122
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
		this.w = a.w - b.w;
123

B
Ben Nolan 已提交
124 125
		return this;

126
	},
127

128
	subSelf: function ( v ) {
M
Mr.doob 已提交
129 130 131 132 133

		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
		this.w -= v.w;
M
Mr.doob 已提交
134

M
Mr.doob 已提交
135
		return this;
136

M
Mr.doob 已提交
137
	},
M
Mr.doob 已提交
138

139
	multiplyScalar: function ( s ) {
M
Mr.doob 已提交
140 141 142 143 144

		this.x *= s;
		this.y *= s;
		this.z *= s;
		this.w *= s;
145

146 147
		return this;

148
	},
149

150
	divideScalar: function ( s ) {
M
Mr.doob 已提交
151

M
Mr.doob 已提交
152
		if ( s ) {
M
Mr.doob 已提交
153

M
Mr.doob 已提交
154 155 156 157
			this.x /= s;
			this.y /= s;
			this.z /= s;
			this.w /= s;
158

M
Mr.doob 已提交
159 160
		} else {

161 162 163 164
			this.x = 0;
			this.y = 0;
			this.z = 0;
			this.w = 1;
M
Mr.doob 已提交
165 166

		}
167

B
Ben Nolan 已提交
168 169
		return this;

170
	},
M
Mr.doob 已提交
171

172 173
	minSelf: function ( v ) {

A
alteredq 已提交
174 175
		if ( this.x > v.x ) {

176
			this.x = v.x;
A
alteredq 已提交
177

178
		}
A
alteredq 已提交
179 180 181

		if ( this.y > v.y ) {

182
			this.y = v.y;
A
alteredq 已提交
183

184
		}
A
alteredq 已提交
185 186 187

		if ( this.z > v.z ) {

188
			this.z = v.z;
A
alteredq 已提交
189

190
		}
A
alteredq 已提交
191 192 193

		if ( this.w > v.w ) {

194
			this.w = v.w;
A
alteredq 已提交
195

196 197 198 199 200 201 202 203
		}

		return this;

	},

	maxSelf: function ( v ) {

A
alteredq 已提交
204 205
		if ( this.x < v.x ) {

206
			this.x = v.x;
A
alteredq 已提交
207

208
		}
A
alteredq 已提交
209 210 211

		if ( this.y < v.y ) {

212
			this.y = v.y;
A
alteredq 已提交
213

214
		}
A
alteredq 已提交
215 216 217

		if ( this.z < v.z ) {

218
			this.z = v.z;
A
alteredq 已提交
219

220
		}
A
alteredq 已提交
221 222 223

		if ( this.w < v.w ) {

224
			this.w = v.w;
A
alteredq 已提交
225

226 227 228 229 230 231 232 233 234 235
		}

		return this;

	},

	clampSelf: function ( min, max ) {

		// This function assumes min < max, if this assumption isn't true it will not operate correctly

A
alteredq 已提交
236 237
		if ( this.x < min.x ) {

238
			this.x = min.x;
A
alteredq 已提交
239 240 241

		} else if ( this.x > max.x ) {

242
			this.x = max.x;
A
alteredq 已提交
243

244 245
		}

A
alteredq 已提交
246 247
		if ( this.y < min.y ) {

248
			this.y = min.y;
A
alteredq 已提交
249 250 251

		} else if ( this.y > max.y ) {

252
			this.y = max.y;
A
alteredq 已提交
253

254 255
		}

A
alteredq 已提交
256 257
		if ( this.z < min.z ) {

258
			this.z = min.z;
A
alteredq 已提交
259 260 261

		} else if ( this.z > max.z ) {

262
			this.z = max.z;
A
alteredq 已提交
263

264 265
		}

A
alteredq 已提交
266 267
		if ( this.w < min.w ) {

268
			this.w = min.w;
A
alteredq 已提交
269 270 271

		} else if ( this.w > max.w ) {

272
			this.w = max.w;
A
alteredq 已提交
273

274 275 276
		}

		return this;
A
alteredq 已提交
277

278
	},
M
Mr.doob 已提交
279

280
	negate: function() {
M
Mr.doob 已提交
281

M
Mr.doob 已提交
282
		return this.multiplyScalar( -1 );
M
Mr.doob 已提交
283

M
Mr.doob 已提交
284
	},
M
Mr.doob 已提交
285

286
	dot: function ( v ) {
M
Mr.doob 已提交
287 288

		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
M
Mr.doob 已提交
289 290 291

	},

292
	lengthSq: function () {
M
Mr.doob 已提交
293

M
Mr.doob 已提交
294
		return this.dot( this );
M
Mr.doob 已提交
295

M
Mr.doob 已提交
296
	},
M
Mr.doob 已提交
297

298
	length: function () {
M
Mr.doob 已提交
299

M
Mr.doob 已提交
300
		return Math.sqrt( this.lengthSq() );
M
Mr.doob 已提交
301 302

	},
M
Mr.doob 已提交
303

304 305 306 307 308
	lengthManhattan: function () {

		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );

	},
M
Mr.doob 已提交
309

310
	normalize: function () {
M
Mr.doob 已提交
311 312

		return this.divideScalar( this.length() );
M
Mr.doob 已提交
313

M
Mr.doob 已提交
314
	},
M
Mr.doob 已提交
315

316
	setLength: function ( l ) {
M
Mr.doob 已提交
317

M
Mr.doob 已提交
318
		return this.normalize().multiplyScalar( l );
319

M
Mr.doob 已提交
320
	},
321

322
	lerpSelf: function ( v, alpha ) {
M
Mr.doob 已提交
323

324 325 326 327
		this.x += ( v.x - this.x ) * alpha;
		this.y += ( v.y - this.y ) * alpha;
		this.z += ( v.z - this.z ) * alpha;
		this.w += ( v.w - this.w ) * alpha;
328

M
Mr.doob 已提交
329 330
		return this;

M
Mr.doob 已提交
331 332
	},

333 334 335 336 337 338
	equals: function ( v ) {

		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );

	},

M
Mr.doob 已提交
339 340 341 342
	clone: function () {

		return new THREE.Vector4( this.x, this.y, this.z, this.w );

W
WestLangley 已提交
343 344 345 346 347
	},

	setAxisAngleFromQuaternion: function ( q ) {

		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
M
Mr.doob 已提交
348

W
WestLangley 已提交
349
		// q is assumed to be normalized
M
Mr.doob 已提交
350

W
WestLangley 已提交
351
		this.w = 2 * Math.acos( q.w );
M
Mr.doob 已提交
352

W
WestLangley 已提交
353
		var s = Math.sqrt( 1 - q.w * q.w );
M
Mr.doob 已提交
354

W
WestLangley 已提交
355
		if ( s < 0.0001 ) {
M
Mr.doob 已提交
356

W
WestLangley 已提交
357 358 359
			 this.x = 1;
			 this.y = 0;
			 this.z = 0;
M
Mr.doob 已提交
360

W
WestLangley 已提交
361
		} else {
M
Mr.doob 已提交
362

W
WestLangley 已提交
363 364 365
			 this.x = q.x / s;
			 this.y = q.y / s;
			 this.z = q.z / s;
M
Mr.doob 已提交
366

W
WestLangley 已提交
367
		}
M
Mr.doob 已提交
368

W
WestLangley 已提交
369 370 371 372 373 374 375
		return this;

	},

	setAxisAngleFromRotationMatrix: function ( m ) {

		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
M
Mr.doob 已提交
376

W
WestLangley 已提交
377
		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
M
Mr.doob 已提交
378

W
WestLangley 已提交
379 380 381
		var angle, x, y, z,		// variables for result
			epsilon = 0.01,		// margin to allow for rounding errors
			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
M
Mr.doob 已提交
382

W
WestLangley 已提交
383
			te = m.elements,
M
Mr.doob 已提交
384

W
WestLangley 已提交
385 386 387 388 389 390 391
			m11 = te[0], m12 = te[4], m13 = te[8],
			m21 = te[1], m22 = te[5], m23 = te[9],
			m31 = te[2], m32 = te[6], m33 = te[10];

		if ( ( Math.abs( m12 - m21 ) < epsilon )
		  && ( Math.abs( m13 - m31 ) < epsilon )
		  && ( Math.abs( m23 - m32 ) < epsilon ) ) {
M
Mr.doob 已提交
392

W
WestLangley 已提交
393 394 395
			// singularity found
			// first check for identity matrix which must have +1 for all terms
			// in leading diagonal and zero in other terms
M
Mr.doob 已提交
396

W
WestLangley 已提交
397 398 399 400
			if ( ( Math.abs( m12 + m21 ) < epsilon2 )
			  && ( Math.abs( m13 + m31 ) < epsilon2 )
			  && ( Math.abs( m23 + m32 ) < epsilon2 )
			  && ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
M
Mr.doob 已提交
401

W
WestLangley 已提交
402
				// this singularity is identity matrix so angle = 0
M
Mr.doob 已提交
403

W
WestLangley 已提交
404
				this.set( 1, 0, 0, 0 );
M
Mr.doob 已提交
405

W
WestLangley 已提交
406
				return this; // zero angle, arbitrary axis
M
Mr.doob 已提交
407

W
WestLangley 已提交
408
			}
M
Mr.doob 已提交
409

W
WestLangley 已提交
410
			// otherwise this singularity is angle = 180
M
Mr.doob 已提交
411

W
WestLangley 已提交
412
			angle = Math.PI;
M
Mr.doob 已提交
413

W
WestLangley 已提交
414 415 416 417 418 419
			var xx = ( m11 + 1 ) / 2;
			var yy = ( m22 + 1 ) / 2;
			var zz = ( m33 + 1 ) / 2;
			var xy = ( m12 + m21 ) / 4;
			var xz = ( m13 + m31 ) / 4;
			var yz = ( m23 + m32 ) / 4;
M
Mr.doob 已提交
420

W
WestLangley 已提交
421
			if ( ( xx > yy ) && ( xx > zz ) ) { // m11 is the largest diagonal term
M
Mr.doob 已提交
422

W
WestLangley 已提交
423
				if ( xx < epsilon ) {
M
Mr.doob 已提交
424

W
WestLangley 已提交
425 426 427
					x = 0;
					y = 0.707106781;
					z = 0.707106781;
M
Mr.doob 已提交
428

W
WestLangley 已提交
429
				} else {
M
Mr.doob 已提交
430

W
WestLangley 已提交
431 432 433
					x = Math.sqrt( xx );
					y = xy / x;
					z = xz / x;
M
Mr.doob 已提交
434

W
WestLangley 已提交
435
				}
M
Mr.doob 已提交
436

W
WestLangley 已提交
437
			} else if ( yy > zz ) { // m22 is the largest diagonal term
M
Mr.doob 已提交
438

W
WestLangley 已提交
439
				if ( yy < epsilon ) {
M
Mr.doob 已提交
440

W
WestLangley 已提交
441 442 443
					x = 0.707106781;
					y = 0;
					z = 0.707106781;
M
Mr.doob 已提交
444

W
WestLangley 已提交
445
				} else {
M
Mr.doob 已提交
446

W
WestLangley 已提交
447 448 449
					y = Math.sqrt( yy );
					x = xy / y;
					z = yz / y;
M
Mr.doob 已提交
450 451 452

				}

W
WestLangley 已提交
453
			} else { // m33 is the largest diagonal term so base result on this
M
Mr.doob 已提交
454

W
WestLangley 已提交
455
				if ( zz < epsilon ) {
M
Mr.doob 已提交
456

W
WestLangley 已提交
457 458 459
					x = 0.707106781;
					y = 0.707106781;
					z = 0;
M
Mr.doob 已提交
460

W
WestLangley 已提交
461
				} else {
M
Mr.doob 已提交
462

W
WestLangley 已提交
463 464 465
					z = Math.sqrt( zz );
					x = xz / z;
					y = yz / z;
M
Mr.doob 已提交
466

W
WestLangley 已提交
467
				}
M
Mr.doob 已提交
468

W
WestLangley 已提交
469
			}
M
Mr.doob 已提交
470

W
WestLangley 已提交
471
			this.set( x, y, z, angle );
M
Mr.doob 已提交
472

W
WestLangley 已提交
473
			return this; // return 180 deg rotation
M
Mr.doob 已提交
474

W
WestLangley 已提交
475
		}
M
Mr.doob 已提交
476

W
WestLangley 已提交
477
		// as we have reached here there are no singularities so we can handle normally
M
Mr.doob 已提交
478

W
WestLangley 已提交
479 480 481
		var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
						 + ( m13 - m31 ) * ( m13 - m31 )
						 + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
M
Mr.doob 已提交
482

A
alteredq 已提交
483
		if ( Math.abs( s ) < 0.001 ) s = 1;
M
Mr.doob 已提交
484

W
WestLangley 已提交
485 486
		// prevent divide by zero, should not happen if matrix is orthogonal and should be
		// caught by singularity test above, but I've left it in just in case
M
Mr.doob 已提交
487

W
WestLangley 已提交
488 489 490 491
		this.x = ( m32 - m23 ) / s;
		this.y = ( m13 - m31 ) / s;
		this.z = ( m21 - m12 ) / s;
		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
M
Mr.doob 已提交
492

W
WestLangley 已提交
493 494
		return this;

495
	}
496 497

};
498 499 500 501 502 503 504

THREE.Vector4.__indexToName = {
  0: 'x',
  1: 'y',
  2: 'z',
  3: 'w'
};