Vector4.js 7.5 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
	setComponent: function ( index, value ) {
B
Ben Houston 已提交
66

67
		this[ THREE.Vector4.__indexToName[ index ] ] = value;
B
Ben Houston 已提交
68

69 70 71
	},

	getComponent: function ( index ) {
B
Ben Houston 已提交
72

73
		return this[ THREE.Vector4.__indexToName[ index ] ];
B
Ben Houston 已提交
74
		
75 76
	},

77
	copy: function ( v ) {
M
Mr.doob 已提交
78

79 80 81
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
82
		this.w = ( v.w !== undefined ) ? v.w : 1;
83

84 85
		return this;

86
	},
87

88 89 90 91 92 93 94 95 96 97 98
	addScalar: function ( s ) {

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

		return this;

	},

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

M
Mr.doob 已提交
101 102 103 104
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
		this.w = a.w + b.w;
105

106 107
		return this;

108
	},
109

110
	addSelf: function ( v ) {
M
Mr.doob 已提交
111

M
Mr.doob 已提交
112 113 114 115
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
		this.w += v.w;
116

M
Mr.doob 已提交
117
		return this;
M
Mr.doob 已提交
118

M
Mr.doob 已提交
119 120
	},

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

M
Mr.doob 已提交
123 124 125 126
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
		this.w = a.w - b.w;
127

B
Ben Nolan 已提交
128 129
		return this;

130
	},
131

132
	subSelf: function ( v ) {
M
Mr.doob 已提交
133 134 135 136 137

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

M
Mr.doob 已提交
139
		return this;
140

M
Mr.doob 已提交
141
	},
M
Mr.doob 已提交
142

143
	multiplyScalar: function ( s ) {
M
Mr.doob 已提交
144 145 146 147 148

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

150 151
		return this;

152
	},
153

154
	divideScalar: function ( s ) {
M
Mr.doob 已提交
155

M
Mr.doob 已提交
156
		if ( s ) {
M
Mr.doob 已提交
157

M
Mr.doob 已提交
158 159 160 161
			this.x /= s;
			this.y /= s;
			this.z /= s;
			this.w /= s;
162

M
Mr.doob 已提交
163 164
		} else {

165 166 167 168
			this.x = 0;
			this.y = 0;
			this.z = 0;
			this.w = 1;
M
Mr.doob 已提交
169 170

		}
171

B
Ben Nolan 已提交
172 173
		return this;

174
	},
M
Mr.doob 已提交
175

176 177
	minSelf: function ( v ) {

A
alteredq 已提交
178 179
		if ( this.x > v.x ) {

180
			this.x = v.x;
A
alteredq 已提交
181

182
		}
A
alteredq 已提交
183 184 185

		if ( this.y > v.y ) {

186
			this.y = v.y;
A
alteredq 已提交
187

188
		}
A
alteredq 已提交
189 190 191

		if ( this.z > v.z ) {

192
			this.z = v.z;
A
alteredq 已提交
193

194
		}
A
alteredq 已提交
195 196 197

		if ( this.w > v.w ) {

198
			this.w = v.w;
A
alteredq 已提交
199

200 201 202 203 204 205 206 207
		}

		return this;

	},

	maxSelf: function ( v ) {

A
alteredq 已提交
208 209
		if ( this.x < v.x ) {

210
			this.x = v.x;
A
alteredq 已提交
211

212
		}
A
alteredq 已提交
213 214 215

		if ( this.y < v.y ) {

216
			this.y = v.y;
A
alteredq 已提交
217

218
		}
A
alteredq 已提交
219 220 221

		if ( this.z < v.z ) {

222
			this.z = v.z;
A
alteredq 已提交
223

224
		}
A
alteredq 已提交
225 226 227

		if ( this.w < v.w ) {

228
			this.w = v.w;
A
alteredq 已提交
229

230 231 232 233 234 235 236 237 238 239
		}

		return this;

	},

	clampSelf: function ( min, max ) {

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

A
alteredq 已提交
240 241
		if ( this.x < min.x ) {

242
			this.x = min.x;
A
alteredq 已提交
243 244 245

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

246
			this.x = max.x;
A
alteredq 已提交
247

248 249
		}

A
alteredq 已提交
250 251
		if ( this.y < min.y ) {

252
			this.y = min.y;
A
alteredq 已提交
253 254 255

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

256
			this.y = max.y;
A
alteredq 已提交
257

258 259
		}

A
alteredq 已提交
260 261
		if ( this.z < min.z ) {

262
			this.z = min.z;
A
alteredq 已提交
263 264 265

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

266
			this.z = max.z;
A
alteredq 已提交
267

268 269
		}

A
alteredq 已提交
270 271
		if ( this.w < min.w ) {

272
			this.w = min.w;
A
alteredq 已提交
273 274 275

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

276
			this.w = max.w;
A
alteredq 已提交
277

278 279 280
		}

		return this;
A
alteredq 已提交
281

282
	},
M
Mr.doob 已提交
283

284
	negate: function() {
M
Mr.doob 已提交
285

M
Mr.doob 已提交
286
		return this.multiplyScalar( -1 );
M
Mr.doob 已提交
287

M
Mr.doob 已提交
288
	},
M
Mr.doob 已提交
289

290
	dot: function ( v ) {
M
Mr.doob 已提交
291 292

		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
M
Mr.doob 已提交
293 294 295

	},

296
	lengthSq: function () {
M
Mr.doob 已提交
297

298
		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
M
Mr.doob 已提交
299

M
Mr.doob 已提交
300
	},
M
Mr.doob 已提交
301

302
	length: function () {
M
Mr.doob 已提交
303

304
		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
M
Mr.doob 已提交
305 306

	},
M
Mr.doob 已提交
307

308 309 310 311 312
	lengthManhattan: function () {

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

	},
M
Mr.doob 已提交
313

314
	normalize: function () {
M
Mr.doob 已提交
315 316

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

M
Mr.doob 已提交
318
	},
M
Mr.doob 已提交
319

320
	setLength: function ( l ) {
M
Mr.doob 已提交
321

322 323 324
		var oldLength = this.length();
		
		if( oldLength ) {
325

326 327 328 329 330
			this.multiplyScalar( l / oldLength );
		}

		return this;
		
M
Mr.doob 已提交
331
	},
332

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

335 336 337 338
		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;
339

M
Mr.doob 已提交
340 341
		return this;

M
Mr.doob 已提交
342 343
	},

344 345 346 347 348 349
	equals: function ( v ) {

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

	},

M
Mr.doob 已提交
350 351 352 353
	clone: function () {

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

W
WestLangley 已提交
354 355 356 357 358
	},

	setAxisAngleFromQuaternion: function ( q ) {

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

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

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

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

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

W
WestLangley 已提交
368 369 370
			 this.x = 1;
			 this.y = 0;
			 this.z = 0;
M
Mr.doob 已提交
371

W
WestLangley 已提交
372
		} else {
M
Mr.doob 已提交
373

W
WestLangley 已提交
374 375 376
			 this.x = q.x / s;
			 this.y = q.y / s;
			 this.z = q.z / s;
M
Mr.doob 已提交
377

W
WestLangley 已提交
378
		}
M
Mr.doob 已提交
379

W
WestLangley 已提交
380 381 382 383 384 385 386
		return this;

	},

	setAxisAngleFromRotationMatrix: function ( m ) {

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

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

W
WestLangley 已提交
390 391 392
		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 已提交
393

W
WestLangley 已提交
394
			te = m.elements,
M
Mr.doob 已提交
395

W
WestLangley 已提交
396 397 398 399 400 401 402
			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 已提交
403

W
WestLangley 已提交
404 405 406
			// 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 已提交
407

W
WestLangley 已提交
408 409 410 411
			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 已提交
412

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

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

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

W
WestLangley 已提交
419
			}
M
Mr.doob 已提交
420

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

W
WestLangley 已提交
423
			angle = Math.PI;
M
Mr.doob 已提交
424

W
WestLangley 已提交
425 426 427 428 429 430
			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 已提交
431

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

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

W
WestLangley 已提交
436 437 438
					x = 0;
					y = 0.707106781;
					z = 0.707106781;
M
Mr.doob 已提交
439

W
WestLangley 已提交
440
				} else {
M
Mr.doob 已提交
441

W
WestLangley 已提交
442 443 444
					x = Math.sqrt( xx );
					y = xy / x;
					z = xz / x;
M
Mr.doob 已提交
445

W
WestLangley 已提交
446
				}
M
Mr.doob 已提交
447

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

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

W
WestLangley 已提交
452 453 454
					x = 0.707106781;
					y = 0;
					z = 0.707106781;
M
Mr.doob 已提交
455

W
WestLangley 已提交
456
				} else {
M
Mr.doob 已提交
457

W
WestLangley 已提交
458 459 460
					y = Math.sqrt( yy );
					x = xy / y;
					z = yz / y;
M
Mr.doob 已提交
461 462 463

				}

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

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

W
WestLangley 已提交
468 469 470
					x = 0.707106781;
					y = 0.707106781;
					z = 0;
M
Mr.doob 已提交
471

W
WestLangley 已提交
472
				} else {
M
Mr.doob 已提交
473

W
WestLangley 已提交
474 475 476
					z = Math.sqrt( zz );
					x = xz / z;
					y = yz / z;
M
Mr.doob 已提交
477

W
WestLangley 已提交
478
				}
M
Mr.doob 已提交
479

W
WestLangley 已提交
480
			}
M
Mr.doob 已提交
481

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

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

W
WestLangley 已提交
486
		}
M
Mr.doob 已提交
487

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

W
WestLangley 已提交
490 491 492
		var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
						 + ( m13 - m31 ) * ( m13 - m31 )
						 + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
M
Mr.doob 已提交
493

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

W
WestLangley 已提交
496 497
		// 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 已提交
498

W
WestLangley 已提交
499 500 501 502
		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 已提交
503

W
WestLangley 已提交
504 505
		return this;

506
	}
507 508

};
509 510 511 512 513 514

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