Vector3.js 11.4 KB
Newer Older
M
Mr.doob 已提交
1
/**
M
Mr.doob 已提交
2
 * @author mrdoob / http://mrdoob.com/
3
 * @author *kile / http://kile.stravaganza.org/
M
Mr.doob 已提交
4
 * @author philogb / http://blog.thejit.org/
5
 * @author mikael emtinger / http://gomo.se/
M
Mr.doob 已提交
6
 * @author egraether / http://egraether.com/
W
WestLangley 已提交
7
 * @author WestLangley / http://github.com/WestLangley
M
Mr.doob 已提交
8 9
 */

A
alteredq 已提交
10
THREE.Vector3 = function ( x, y, z ) {
11

12 13 14
	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;
M
Mr.doob 已提交
15

16
};
17

18

19
THREE.Vector3.prototype = {
20

21 22 23
	constructor: THREE.Vector3,

	set: function ( x, y, z ) {
M
Mr.doob 已提交
24

A
alteredq 已提交
25 26 27
		this.x = x;
		this.y = y;
		this.z = z;
M
Mr.doob 已提交
28

29
		return this;
30

31
	},
32

M
Mr.doob 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
	setX: function ( x ) {

		this.x = x;

		return this;

	},

	setY: function ( y ) {

		this.y = y;

		return this;

	},

	setZ: function ( z ) {

		this.z = z;

		return this;

	},

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

M
Mr.doob 已提交
59
		switch ( index ) {
60

M
Mr.doob 已提交
61 62 63 64
			case 0: this.x = value; break;
			case 1: this.y = value; break;
			case 2: this.z = value; break;
			default: throw new Error( "index is out of range: " + index );
B
Ben Houston 已提交
65

M
Mr.doob 已提交
66
		}
B
Ben Houston 已提交
67

M
Mr.doob 已提交
68
	},
69

M
Mr.doob 已提交
70
	getComponent: function ( index ) {
71

M
Mr.doob 已提交
72
		switch ( index ) {
73

M
Mr.doob 已提交
74 75 76 77
			case 0: return this.x;
			case 1: return this.y;
			case 2: return this.z;
			default: throw new Error( "index is out of range: " + index );
78

M
Mr.doob 已提交
79
		}
80

M
Mr.doob 已提交
81
	},
82

83
	copy: function ( v ) {
M
Mr.doob 已提交
84

M
Mr.doob 已提交
85 86 87
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
M
Mr.doob 已提交
88

89
		return this;
M
Mr.doob 已提交
90

91
	},
92

93 94 95 96 97 98 99 100
	add: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
M
Mr.doob 已提交
101

M
Mr.doob 已提交
102 103 104
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
105

B
Ben Nolan 已提交
106 107
		return this;

108
	},
109

110
	addScalar: function ( s ) {
M
Mr.doob 已提交
111

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

B
Ben Nolan 已提交
116 117
		return this;

118
	},
119

120
	addVectors: function ( a, b ) {
121

122 123 124
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
125

126
		return this;
M
Mr.doob 已提交
127

128
	},
129

130 131 132 133 134 135 136 137
	sub: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
138

M
Mr.doob 已提交
139 140 141
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
142

B
Ben Nolan 已提交
143 144
		return this;

145
	},
146

147
	subVectors: function ( a, b ) {
148

149 150 151
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
152

153
		return this;
M
Mr.doob 已提交
154

155
	},
156

157 158 159 160 161 162 163 164
	multiply: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
165

M
Mr.doob 已提交
166 167
		this.x *= v.x;
		this.y *= v.y;
N
Nico Kruithof 已提交
168
		this.z *= v.z;
M
Mr.doob 已提交
169 170 171 172 173

		return this;

	},

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

M
Mr.doob 已提交
176 177 178
		this.x *= s;
		this.y *= s;
		this.z *= s;
179

B
Ben Nolan 已提交
180 181
		return this;

182
	},
183

184 185 186 187 188 189 190 191 192 193
	multiplyVectors: function ( a, b ) {

		this.x = a.x * b.x;
		this.y = a.y * b.y;
		this.z = a.z * b.z;

		return this;

	},

194
	applyMatrix3: function ( m ) {
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

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

		var e = m.elements;

		this.x = e[0] * x + e[3] * y + e[6] * z;
		this.y = e[1] * x + e[4] * y + e[7] * z;
		this.z = e[2] * x + e[5] * y + e[8] * z;

		return this;

	},

210
	applyMatrix4: function ( m ) {
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

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

		var e = m.elements;
		var d = 1 / ( e[3] * x + e[7] * y + e[11] * z + e[15] );

		this.x = ( e[0] * x + e[4] * y + e[8] * z + e[12] ) * d;
		this.y = ( e[1] * x + e[5] * y + e[9] * z + e[13] ) * d;
		this.z = ( e[2] * x + e[6] * y + e[10] * z + e[14] ) * d;

		return this;

	},

227
	applyQuaternion: function ( q ) {
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254

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

		var qx = q.x;
		var qy = q.y;
		var qz = q.z;
		var qw = q.w;

		// calculate quat * vector

		var ix =  qw * x + qy * z - qz * y;
		var iy =  qw * y + qz * x - qx * z;
		var iz =  qw * z + qx * y - qy * x;
		var iw = -qx * x - qy * y - qz * z;

		// calculate result * inverse quat

		this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
		this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
		this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;

		return this;

	},

255
	divide: function ( v ) {
256

257 258 259 260 261
		this.x /= v.x;
		this.y /= v.y;
		this.z /= v.z;

		return this;
M
Mr.doob 已提交
262

M
Mr.doob 已提交
263
	},
264

265
	divideScalar: function ( s ) {
266

B
Ben Houston 已提交
267
		if ( s !== 0 ) {
268

M
Mr.doob 已提交
269 270 271
			this.x /= s;
			this.y /= s;
			this.z /= s;
M
Mr.doob 已提交
272

M
Mr.doob 已提交
273
		} else {
M
Mr.doob 已提交
274

275 276 277
			this.x = 0;
			this.y = 0;
			this.z = 0;
278

M
Mr.doob 已提交
279
		}
280

B
Ben Nolan 已提交
281 282
		return this;

283
	},
284

285
	min: function ( v ) {
286

A
alteredq 已提交
287 288
		if ( this.x > v.x ) {

289
			this.x = v.x;
A
alteredq 已提交
290

291
		}
A
alteredq 已提交
292 293 294

		if ( this.y > v.y ) {

295
			this.y = v.y;
A
alteredq 已提交
296

297
		}
A
alteredq 已提交
298 299 300

		if ( this.z > v.z ) {

301
			this.z = v.z;
A
alteredq 已提交
302

303
		}
304 305 306 307 308

		return this;

	},

309
	max: function ( v ) {
310

A
alteredq 已提交
311 312
		if ( this.x < v.x ) {

313
			this.x = v.x;
A
alteredq 已提交
314

315
		}
A
alteredq 已提交
316 317 318

		if ( this.y < v.y ) {

319
			this.y = v.y;
A
alteredq 已提交
320

321
		}
A
alteredq 已提交
322 323 324

		if ( this.z < v.z ) {

325
			this.z = v.z;
A
alteredq 已提交
326

327
		}
328 329 330 331

		return this;

	},
M
Mr.doob 已提交
332

333
	clamp: function ( min, max ) {
334 335 336

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

A
alteredq 已提交
337 338
		if ( this.x < min.x ) {

339
			this.x = min.x;
A
alteredq 已提交
340 341 342

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

343
			this.x = max.x;
A
alteredq 已提交
344

345 346
		}

A
alteredq 已提交
347 348
		if ( this.y < min.y ) {

349
			this.y = min.y;
A
alteredq 已提交
350 351 352

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

353
			this.y = max.y;
A
alteredq 已提交
354

355 356
		}

A
alteredq 已提交
357 358
		if ( this.z < min.z ) {

359
			this.z = min.z;
A
alteredq 已提交
360 361 362

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

363
			this.z = max.z;
A
alteredq 已提交
364

365 366 367
		}

		return this;
A
alteredq 已提交
368

369 370
	},

371
	negate: function() {
M
Mr.doob 已提交
372

M
Mr.doob 已提交
373
		return this.multiplyScalar( - 1 );
B
Ben Nolan 已提交
374

375
	},
376

377
	dot: function ( v ) {
M
Mr.doob 已提交
378

M
Mr.doob 已提交
379
		return this.x * v.x + this.y * v.y + this.z * v.z;
M
Mr.doob 已提交
380

M
Mr.doob 已提交
381
	},
M
Mr.doob 已提交
382

383
	lengthSq: function () {
M
Mr.doob 已提交
384

M
Mr.doob 已提交
385
		return this.x * this.x + this.y * this.y + this.z * this.z;
M
Mr.doob 已提交
386 387 388

	},

389
	length: function () {
M
Mr.doob 已提交
390

391
		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
M
Mr.doob 已提交
392

M
Mr.doob 已提交
393
	},
394

395
	lengthManhattan: function () {
396

397
		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
A
alteredq 已提交
398

399 400
	},

401
	normalize: function () {
402

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

405
	},
406

407
	setLength: function ( l ) {
408

409
		var oldLength = this.length();
M
Mr.doob 已提交
410

B
Ben Houston 已提交
411
		if ( oldLength !== 0 && l !== oldLength  ) {
412 413 414 415 416

			this.multiplyScalar( l / oldLength );
		}

		return this;
417

418
	},
419

420
	lerp: function ( v, alpha ) {
421 422 423 424 425 426 427 428

		this.x += ( v.x - this.x ) * alpha;
		this.y += ( v.y - this.y ) * alpha;
		this.z += ( v.z - this.z ) * alpha;

		return this;

	},
429

430 431 432 433 434 435 436 437
	cross: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
438

439
		var x = this.x, y = this.y, z = this.z;
440

441 442 443
		this.x = y * v.z - z * v.y;
		this.y = z * v.x - x * v.z;
		this.z = x * v.y - y * v.x;
444

445
		return this;
446 447 448

	},

449 450 451 452 453 454 455 456 457 458
	crossVectors: function ( a, b ) {

		this.x = a.y * b.z - a.z * b.y;
		this.y = a.z * b.x - a.x * b.z;
		this.z = a.x * b.y - a.y * b.x;

		return this;

	},

W
Wilt 已提交
459
	angleTo: function ( v ) {
M
Mr.doob 已提交
460

W
Wilt 已提交
461
		return Math.acos( this.dot( v ) / this.length() / v.length() );
M
Mr.doob 已提交
462 463

	},
W
Wilt 已提交
464

465
	distanceTo: function ( v ) {
466

M
Mr.doob 已提交
467
		return Math.sqrt( this.distanceToSquared( v ) );
468

M
Mr.doob 已提交
469 470
	},

471
	distanceToSquared: function ( v ) {
M
Mr.doob 已提交
472

M
Mr.doob 已提交
473 474 475 476
		var dx = this.x - v.x;
		var dy = this.y - v.y;
		var dz = this.z - v.z;

477
		return dx * dx + dy * dy + dz * dz;
M
Mr.doob 已提交
478

479
	},
M
Mr.doob 已提交
480

M
Mr.doob 已提交
481
	getPositionFromMatrix: function ( m ) {
M
Mr.doob 已提交
482

483 484 485
		this.x = m.elements[12];
		this.y = m.elements[13];
		this.z = m.elements[14];
486

487 488
		return this;

489 490
	},

W
WestLangley 已提交
491 492 493
	setEulerFromRotationMatrix: function ( m, order ) {

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

W
WestLangley 已提交
495
		// clamp, to handle numerical problems
M
Mr.doob 已提交
496 497 498 499 500 501

		function clamp( x ) {

			return Math.min( Math.max( x, -1 ), 1 );

		}
502 503 504 505 506 507 508 509 510

		var te = m.elements;
		var m11 = te[0], m12 = te[4], m13 = te[8];
		var m21 = te[1], m22 = te[5], m23 = te[9];
		var m31 = te[2], m32 = te[6], m33 = te[10];

		if ( order === undefined || order === 'XYZ' ) {

			this.y = Math.asin( clamp( m13 ) );
M
Mr.doob 已提交
511

512
			if ( Math.abs( m13 ) < 0.99999 ) {
M
Mr.doob 已提交
513

514 515
				this.x = Math.atan2( - m23, m33 );
				this.z = Math.atan2( - m12, m11 );
M
Mr.doob 已提交
516

517
			} else {
M
Mr.doob 已提交
518

519
				this.x = Math.atan2( m32, m22 );
520
				this.z = 0;
M
Mr.doob 已提交
521

522 523 524
			}

		} else if ( order === 'YXZ' ) {
M
Mr.doob 已提交
525

526
			this.x = Math.asin( - clamp( m23 ) );
M
Mr.doob 已提交
527

528
			if ( Math.abs( m23 ) < 0.99999 ) {
M
Mr.doob 已提交
529

530 531
				this.y = Math.atan2( m13, m33 );
				this.z = Math.atan2( m21, m22 );
M
Mr.doob 已提交
532

533
			} else {
M
Mr.doob 已提交
534

535 536
				this.y = Math.atan2( - m31, m11 );
				this.z = 0;
M
Mr.doob 已提交
537

538
			}
M
Mr.doob 已提交
539

540
		} else if ( order === 'ZXY' ) {
M
Mr.doob 已提交
541

542
			this.x = Math.asin( clamp( m32 ) );
M
Mr.doob 已提交
543

544
			if ( Math.abs( m32 ) < 0.99999 ) {
M
Mr.doob 已提交
545

546 547
				this.y = Math.atan2( - m31, m33 );
				this.z = Math.atan2( - m12, m22 );
M
Mr.doob 已提交
548

549
			} else {
M
Mr.doob 已提交
550

551
				this.y = 0;
552
				this.z = Math.atan2( m21, m11 );
M
Mr.doob 已提交
553

554 555 556
			}

		} else if ( order === 'ZYX' ) {
M
Mr.doob 已提交
557

558
			this.y = Math.asin( - clamp( m31 ) );
M
Mr.doob 已提交
559

560
			if ( Math.abs( m31 ) < 0.99999 ) {
M
Mr.doob 已提交
561

562 563
				this.x = Math.atan2( m32, m33 );
				this.z = Math.atan2( m21, m11 );
M
Mr.doob 已提交
564

565
			} else {
M
Mr.doob 已提交
566

567 568
				this.x = 0;
				this.z = Math.atan2( - m12, m22 );
M
Mr.doob 已提交
569

570
			}
M
Mr.doob 已提交
571

572
		} else if ( order === 'YZX' ) {
M
Mr.doob 已提交
573

574
			this.z = Math.asin( clamp( m21 ) );
M
Mr.doob 已提交
575

576
			if ( Math.abs( m21 ) < 0.99999 ) {
M
Mr.doob 已提交
577

578 579
				this.x = Math.atan2( - m23, m22 );
				this.y = Math.atan2( - m31, m11 );
M
Mr.doob 已提交
580

581
			} else {
M
Mr.doob 已提交
582

583
				this.x = 0;
584
				this.y = Math.atan2( m13, m33 );
M
Mr.doob 已提交
585

586
			}
M
Mr.doob 已提交
587

588
		} else if ( order === 'XZY' ) {
M
Mr.doob 已提交
589

590
			this.z = Math.asin( - clamp( m12 ) );
M
Mr.doob 已提交
591

592
			if ( Math.abs( m12 ) < 0.99999 ) {
M
Mr.doob 已提交
593

594 595
				this.x = Math.atan2( m32, m22 );
				this.y = Math.atan2( m13, m11 );
M
Mr.doob 已提交
596

597
			} else {
M
Mr.doob 已提交
598

599
				this.x = Math.atan2( - m23, m33 );
600
				this.y = 0;
M
Mr.doob 已提交
601

602
			}
M
Mr.doob 已提交
603

604
		}
M
Mr.doob 已提交
605

606 607 608 609
		return this;

	},

W
WestLangley 已提交
610 611 612
	setEulerFromQuaternion: function ( q, order ) {

		// q is assumed to be normalized
M
Mr.doob 已提交
613

W
WestLangley 已提交
614
		// clamp, to handle numerical problems
M
Mr.doob 已提交
615 616 617 618 619 620 621 622

		function clamp( x ) {

			return Math.min( Math.max( x, -1 ), 1 );

		}

		// http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
M
Mr.doob 已提交
623

M
Mr.doob 已提交
624 625 626 627
		var sqx = q.x * q.x;
		var sqy = q.y * q.y;
		var sqz = q.z * q.z;
		var sqw = q.w * q.w;
628 629 630 631 632 633

		if ( order === undefined || order === 'XYZ' ) {

			this.x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) );
			this.y = Math.asin(  clamp( 2 * ( q.x * q.z + q.y * q.w ) ) );
			this.z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) );
M
Mr.doob 已提交
634

635
		} else if ( order ===  'YXZ' ) {
M
Mr.doob 已提交
636

637 638 639
			this.x = Math.asin(  clamp( 2 * ( q.x * q.w - q.y * q.z ) ) );
			this.y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) );
			this.z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) );
M
Mr.doob 已提交
640

641
		} else if ( order === 'ZXY' ) {
M
Mr.doob 已提交
642

643 644 645
			this.x = Math.asin(  clamp( 2 * ( q.x * q.w + q.y * q.z ) ) );
			this.y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) );
			this.z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) );
M
Mr.doob 已提交
646

647
		} else if ( order === 'ZYX' ) {
M
Mr.doob 已提交
648

649 650 651
			this.x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) );
			this.y = Math.asin(  clamp( 2 * ( q.y * q.w - q.x * q.z ) ) );
			this.z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) );
M
Mr.doob 已提交
652

653
		} else if ( order === 'YZX' ) {
M
Mr.doob 已提交
654

655 656 657
			this.x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) );
			this.y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) );
			this.z = Math.asin(  clamp( 2 * ( q.x * q.y + q.z * q.w ) ) );
M
Mr.doob 已提交
658

659
		} else if ( order === 'XZY' ) {
M
Mr.doob 已提交
660

661 662 663
			this.x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) );
			this.y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) );
			this.z = Math.asin(  clamp( 2 * ( q.z * q.w - q.x * q.y ) ) );
M
Mr.doob 已提交
664

A
alteredq 已提交
665
		}
M
Mr.doob 已提交
666

W
WestLangley 已提交
667
		return this;
A
alteredq 已提交
668 669

	},
670

M
Mr.doob 已提交
671 672
	getScaleFromMatrix: function ( m ) {

673 674 675
		var sx = this.set( m.elements[0], m.elements[1], m.elements[2] ).length();
		var sy = this.set( m.elements[4], m.elements[5], m.elements[6] ).length();
		var sz = this.set( m.elements[8], m.elements[9], m.elements[10] ).length();
M
Mr.doob 已提交
676

677 678 679
		this.x = sx;
		this.y = sy;
		this.z = sz;
M
Mr.doob 已提交
680

681
		return this;
M
Mr.doob 已提交
682 683 684
	},

	equals: function ( v ) {
685 686 687

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

688 689
	},

M
Mr.doob 已提交
690 691 692 693
	clone: function () {

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

694
	}
695

M
Mr.doob 已提交
696
};