Vector4.js 8.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
THREE.extend( THREE.Vector4.prototype, {
19

20
	set: function ( x, y, z, w ) {
21

22 23 24 25
		this.x = x;
		this.y = y;
		this.z = z;
		this.w = w;
26

27
		return this;
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
	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;

	},

M
Mr.doob 已提交
63
	setComponent: function ( index, value ) {
B
Ben Houston 已提交
64

M
Mr.doob 已提交
65
		switch ( index ) {
B
Ben Houston 已提交
66

M
Mr.doob 已提交
67 68 69 70 71
			case 0: this.x = value; break;
			case 1: this.y = value; break;
			case 2: this.z = value; break;
			case 3: this.w = value; break;
			default: throw new Error( "index is out of range: " + index );
72

M
Mr.doob 已提交
73
		}
B
Ben Houston 已提交
74

M
Mr.doob 已提交
75
	},
76

M
Mr.doob 已提交
77
	getComponent: function ( index ) {
78

M
Mr.doob 已提交
79
		switch ( index ) {
80

M
Mr.doob 已提交
81 82 83 84 85
			case 0: return this.x;
			case 1: return this.y;
			case 2: return this.z;
			case 3: return this.w;
			default: throw new Error( "index is out of range: " + index );
86

M
Mr.doob 已提交
87
		}
88

M
Mr.doob 已提交
89
	},
90

91
	copy: function ( v ) {
M
Mr.doob 已提交
92

93 94 95
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
96
		this.w = ( v.w !== undefined ) ? v.w : 1;
97

98 99
		return this;

100
	},
101

102 103 104 105 106 107 108 109
	add: function ( v, w ) {

		if ( w !== undefined ) {

			console.warn( 'DEPRECATED: Vector4\'s .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
			return this.addVectors( v, w );

		}
110 111 112 113 114 115 116 117 118 119

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

		return this;

	},

120 121 122 123 124 125 126 127 128 129 130
	addScalar: function ( s ) {

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

		return this;

	},

131
	addVectors: function ( a, b ) {
M
Mr.doob 已提交
132

M
Mr.doob 已提交
133 134 135 136
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
		this.w = a.w + b.w;
137

138 139
		return this;

140
	},
141

142 143 144 145 146 147 148 149
	sub: function ( v, w ) {

		if ( w !== undefined ) {

			console.warn( 'DEPRECATED: Vector4\'s .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
			return this.subVectors( v, w );

		}
M
Mr.doob 已提交
150

151 152 153 154
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
		this.w -= v.w;
155

M
Mr.doob 已提交
156
		return this;
M
Mr.doob 已提交
157

M
Mr.doob 已提交
158 159
	},

160
	subVectors: function ( a, b ) {
M
Mr.doob 已提交
161

M
Mr.doob 已提交
162 163 164 165
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
		this.w = a.w - b.w;
166

B
Ben Nolan 已提交
167 168
		return this;

169
	},
170

171
	multiplyScalar: function ( s ) {
M
Mr.doob 已提交
172 173 174 175 176

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

178 179
		return this;

180
	},
181

182
	applyMatrix4: function ( m ) {
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199

		var x = this.x;
		var y = this.y;
		var z = this.z;
		var w = this.w;

		var e = m.elements;

		this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w;
		this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w;
		this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w;
		this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w;

		return this;

	},

200
	divideScalar: function ( s ) {
M
Mr.doob 已提交
201

B
Ben Houston 已提交
202
		if ( s !== 0 ) {
M
Mr.doob 已提交
203

M
Mr.doob 已提交
204 205 206 207
			this.x /= s;
			this.y /= s;
			this.z /= s;
			this.w /= s;
208

M
Mr.doob 已提交
209 210
		} else {

211 212 213 214
			this.x = 0;
			this.y = 0;
			this.z = 0;
			this.w = 1;
M
Mr.doob 已提交
215 216

		}
217

B
Ben Nolan 已提交
218 219
		return this;

220
	},
M
Mr.doob 已提交
221

222
	min: function ( v ) {
223

A
alteredq 已提交
224 225
		if ( this.x > v.x ) {

226
			this.x = v.x;
A
alteredq 已提交
227

228
		}
A
alteredq 已提交
229 230 231

		if ( this.y > v.y ) {

232
			this.y = v.y;
A
alteredq 已提交
233

234
		}
A
alteredq 已提交
235 236 237

		if ( this.z > v.z ) {

238
			this.z = v.z;
A
alteredq 已提交
239

240
		}
A
alteredq 已提交
241 242 243

		if ( this.w > v.w ) {

244
			this.w = v.w;
A
alteredq 已提交
245

246 247 248 249 250 251
		}

		return this;

	},

252
	max: function ( v ) {
253

A
alteredq 已提交
254 255
		if ( this.x < v.x ) {

256
			this.x = v.x;
A
alteredq 已提交
257

258
		}
A
alteredq 已提交
259 260 261

		if ( this.y < v.y ) {

262
			this.y = v.y;
A
alteredq 已提交
263

264
		}
A
alteredq 已提交
265 266 267

		if ( this.z < v.z ) {

268
			this.z = v.z;
A
alteredq 已提交
269

270
		}
A
alteredq 已提交
271 272 273

		if ( this.w < v.w ) {

274
			this.w = v.w;
A
alteredq 已提交
275

276 277 278 279 280 281
		}

		return this;

	},

282
	clamp: function ( min, max ) {
283 284 285

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

A
alteredq 已提交
286 287
		if ( this.x < min.x ) {

288
			this.x = min.x;
A
alteredq 已提交
289 290 291

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

292
			this.x = max.x;
A
alteredq 已提交
293

294 295
		}

A
alteredq 已提交
296 297
		if ( this.y < min.y ) {

298
			this.y = min.y;
A
alteredq 已提交
299 300 301

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

302
			this.y = max.y;
A
alteredq 已提交
303

304 305
		}

A
alteredq 已提交
306 307
		if ( this.z < min.z ) {

308
			this.z = min.z;
A
alteredq 已提交
309 310 311

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

312
			this.z = max.z;
A
alteredq 已提交
313

314 315
		}

A
alteredq 已提交
316 317
		if ( this.w < min.w ) {

318
			this.w = min.w;
A
alteredq 已提交
319 320 321

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

322
			this.w = max.w;
A
alteredq 已提交
323

324 325 326
		}

		return this;
A
alteredq 已提交
327

328
	},
M
Mr.doob 已提交
329

330
	negate: function() {
M
Mr.doob 已提交
331

M
Mr.doob 已提交
332
		return this.multiplyScalar( -1 );
M
Mr.doob 已提交
333

M
Mr.doob 已提交
334
	},
M
Mr.doob 已提交
335

336
	dot: function ( v ) {
M
Mr.doob 已提交
337 338

		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
M
Mr.doob 已提交
339 340 341

	},

342
	lengthSq: function () {
M
Mr.doob 已提交
343

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

M
Mr.doob 已提交
346
	},
M
Mr.doob 已提交
347

348
	length: function () {
M
Mr.doob 已提交
349

350
		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
M
Mr.doob 已提交
351 352

	},
M
Mr.doob 已提交
353

354 355 356 357 358
	lengthManhattan: function () {

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

	},
M
Mr.doob 已提交
359

360
	normalize: function () {
M
Mr.doob 已提交
361 362

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

M
Mr.doob 已提交
364
	},
M
Mr.doob 已提交
365

366
	setLength: function ( l ) {
M
Mr.doob 已提交
367

368
		var oldLength = this.length();
M
Mr.doob 已提交
369 370

		if ( oldLength !== 0 && l !== oldLength ) {
371

372 373 374 375
			this.multiplyScalar( l / oldLength );
		}

		return this;
M
Mr.doob 已提交
376

M
Mr.doob 已提交
377
	},
378

379
	lerp: function ( v, alpha ) {
M
Mr.doob 已提交
380

381 382 383 384
		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;
385

M
Mr.doob 已提交
386 387
		return this;

M
Mr.doob 已提交
388 389
	},

390 391 392 393 394 395
	equals: function ( v ) {

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

	},

M
Mr.doob 已提交
396 397 398 399
	clone: function () {

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

W
WestLangley 已提交
400 401 402 403 404
	},

	setAxisAngleFromQuaternion: function ( q ) {

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

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

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

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

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

W
WestLangley 已提交
414 415 416
			 this.x = 1;
			 this.y = 0;
			 this.z = 0;
M
Mr.doob 已提交
417

W
WestLangley 已提交
418
		} else {
M
Mr.doob 已提交
419

W
WestLangley 已提交
420 421 422
			 this.x = q.x / s;
			 this.y = q.y / s;
			 this.z = q.z / s;
M
Mr.doob 已提交
423

W
WestLangley 已提交
424
		}
M
Mr.doob 已提交
425

W
WestLangley 已提交
426 427 428 429 430 431 432
		return this;

	},

	setAxisAngleFromRotationMatrix: function ( m ) {

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

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

W
WestLangley 已提交
436 437 438
		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 已提交
439

W
WestLangley 已提交
440
			te = m.elements,
M
Mr.doob 已提交
441

W
WestLangley 已提交
442 443 444 445 446 447 448
			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 已提交
449

W
WestLangley 已提交
450 451 452
			// 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 已提交
453

W
WestLangley 已提交
454 455 456 457
			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 已提交
458

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

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

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

W
WestLangley 已提交
465
			}
M
Mr.doob 已提交
466

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

W
WestLangley 已提交
469
			angle = Math.PI;
M
Mr.doob 已提交
470

W
WestLangley 已提交
471 472 473 474 475 476
			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 已提交
477

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

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

W
WestLangley 已提交
482 483 484
					x = 0;
					y = 0.707106781;
					z = 0.707106781;
M
Mr.doob 已提交
485

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

W
WestLangley 已提交
488 489 490
					x = Math.sqrt( xx );
					y = xy / x;
					z = xz / x;
M
Mr.doob 已提交
491

W
WestLangley 已提交
492
				}
M
Mr.doob 已提交
493

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

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

W
WestLangley 已提交
498 499 500
					x = 0.707106781;
					y = 0;
					z = 0.707106781;
M
Mr.doob 已提交
501

W
WestLangley 已提交
502
				} else {
M
Mr.doob 已提交
503

W
WestLangley 已提交
504 505 506
					y = Math.sqrt( yy );
					x = xy / y;
					z = yz / y;
M
Mr.doob 已提交
507 508 509

				}

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

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

W
WestLangley 已提交
514 515 516
					x = 0.707106781;
					y = 0.707106781;
					z = 0;
M
Mr.doob 已提交
517

W
WestLangley 已提交
518
				} else {
M
Mr.doob 已提交
519

W
WestLangley 已提交
520 521 522
					z = Math.sqrt( zz );
					x = xz / z;
					y = yz / z;
M
Mr.doob 已提交
523

W
WestLangley 已提交
524
				}
M
Mr.doob 已提交
525

W
WestLangley 已提交
526
			}
M
Mr.doob 已提交
527

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

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

W
WestLangley 已提交
532
		}
M
Mr.doob 已提交
533

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

W
WestLangley 已提交
536 537 538
		var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
						 + ( m13 - m31 ) * ( m13 - m31 )
						 + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
M
Mr.doob 已提交
539

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

W
WestLangley 已提交
542 543
		// 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 已提交
544

W
WestLangley 已提交
545 546 547 548
		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 已提交
549

W
WestLangley 已提交
550 551
		return this;

552
	}
553

M
Mr.doob 已提交
554
} );