Vector3.js 12.8 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 20
THREE.Vector3.prototype = {

	constructor: THREE.Vector3,
21

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

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

28
		return this;
29

30
	},
31

M
Mr.doob 已提交
32 33 34 35 36 37 38 39 40 41
	setScalar: function ( scalar ) {

		this.x = scalar;
		this.y = scalar;
		this.z = scalar;

		return this;

	},

M
Mr.doob 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
	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 已提交
66
	setComponent: function ( index, value ) {
B
Ben Houston 已提交
67

M
Mr.doob 已提交
68
		switch ( index ) {
69

M
Mr.doob 已提交
70 71 72
			case 0: this.x = value; break;
			case 1: this.y = value; break;
			case 2: this.z = value; break;
73
			default: throw new Error( 'index is out of range: ' + index );
B
Ben Houston 已提交
74

M
Mr.doob 已提交
75
		}
B
Ben Houston 已提交
76

M
Mr.doob 已提交
77
	},
78

M
Mr.doob 已提交
79
	getComponent: function ( index ) {
80

M
Mr.doob 已提交
81
		switch ( index ) {
82

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

M
Mr.doob 已提交
88
		}
89

M
Mr.doob 已提交
90
	},
91

92 93 94 95 96 97
	clone: function () {

		return new this.constructor( this.x, this.y, this.z );

	},

98
	copy: function ( v ) {
M
Mr.doob 已提交
99

M
Mr.doob 已提交
100 101 102
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
M
Mr.doob 已提交
103

104
		return this;
M
Mr.doob 已提交
105

106
	},
107

108 109 110 111
	add: function ( v, w ) {

		if ( w !== undefined ) {

112
			console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
113 114 115
			return this.addVectors( v, w );

		}
M
Mr.doob 已提交
116

M
Mr.doob 已提交
117 118 119
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
120

B
Ben Nolan 已提交
121 122
		return this;

123
	},
124

125
	addScalar: function ( s ) {
M
Mr.doob 已提交
126

M
Mr.doob 已提交
127 128 129
		this.x += s;
		this.y += s;
		this.z += s;
130

B
Ben Nolan 已提交
131 132
		return this;

133
	},
134

135
	addVectors: function ( a, b ) {
136

137 138 139
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
140

141
		return this;
M
Mr.doob 已提交
142

143
	},
144

G
gero3 已提交
145 146
	addScaledVector: function ( v, s ) {

G
gero3 已提交
147 148 149
		this.x += v.x * s;
		this.y += v.y * s;
		this.z += v.z * s;
G
gero3 已提交
150

G
gero3 已提交
151
		return this;
G
gero3 已提交
152

G
gero3 已提交
153
	},
154

155 156 157 158
	sub: function ( v, w ) {

		if ( w !== undefined ) {

159
			console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
160 161 162
			return this.subVectors( v, w );

		}
163

M
Mr.doob 已提交
164 165 166
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
167

B
Ben Nolan 已提交
168 169
		return this;

170
	},
171

C
Corey Birnbaum 已提交
172 173 174 175 176 177 178 179 180
	subScalar: function ( s ) {

		this.x -= s;
		this.y -= s;
		this.z -= s;

		return this;

	},
181

182
	subVectors: function ( a, b ) {
183

184 185 186
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
187

188
		return this;
M
Mr.doob 已提交
189

190
	},
191

192 193 194 195
	multiply: function ( v, w ) {

		if ( w !== undefined ) {

196
			console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
197 198 199
			return this.multiplyVectors( v, w );

		}
200

M
Mr.doob 已提交
201 202
		this.x *= v.x;
		this.y *= v.y;
N
Nico Kruithof 已提交
203
		this.z *= v.z;
M
Mr.doob 已提交
204 205 206 207 208

		return this;

	},

209
	multiplyScalar: function ( scalar ) {
M
Mr.doob 已提交
210

M
Mr.doob 已提交
211
		if ( isFinite( scalar ) ) {
M
Mr.doob 已提交
212

M
Mr.doob 已提交
213 214 215
			this.x *= scalar;
			this.y *= scalar;
			this.z *= scalar;
M
Mr.doob 已提交
216

M
Mr.doob 已提交
217
		} else {
M
Mr.doob 已提交
218

M
Mr.doob 已提交
219 220 221
			this.x = 0;
			this.y = 0;
			this.z = 0;
M
Mr.doob 已提交
222

M
Mr.doob 已提交
223
		}
224

B
Ben Nolan 已提交
225 226
		return this;

227
	},
228

229 230 231 232 233 234 235 236 237 238
	multiplyVectors: function ( a, b ) {

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

		return this;

	},

M
Mr.doob 已提交
239 240 241 242
	applyEuler: function () {

		var quaternion;

243
		return function applyEuler( euler ) {
M
Mr.doob 已提交
244 245 246

			if ( euler instanceof THREE.Euler === false ) {

P
paulmasson 已提交
247
				console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
M
Mr.doob 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264

			}

			if ( quaternion === undefined ) quaternion = new THREE.Quaternion();

			this.applyQuaternion( quaternion.setFromEuler( euler ) );

			return this;

		};

	}(),

	applyAxisAngle: function () {

		var quaternion;

265
		return function applyAxisAngle( axis, angle ) {
M
Mr.doob 已提交
266 267 268 269 270 271 272 273 274 275 276

			if ( quaternion === undefined ) quaternion = new THREE.Quaternion();

			this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );

			return this;

		};

	}(),

277
	applyMatrix3: function ( m ) {
278 279 280 281 282 283 284

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

		var e = m.elements;

285 286 287
		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;
288 289 290 291 292

		return this;

	},

293
	applyMatrix4: function ( m ) {
294

295 296 297
		// input: THREE.Matrix4 affine matrix

		var x = this.x, y = this.y, z = this.z;
298 299 300

		var e = m.elements;

301 302 303
		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z + e[ 12 ];
		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z + e[ 13 ];
		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ];
304 305 306 307 308

		return this;

	},

309 310 311 312 313 314 315
	applyProjection: function ( m ) {

		// input: THREE.Matrix4 projection matrix

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

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

318 319 320
		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;
321 322 323 324 325

		return this;

	},

326
	applyQuaternion: function ( q ) {
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341

		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;
342
		var iw = - qx * x - qy * y - qz * z;
343 344 345

		// calculate result * inverse quat

346 347 348
		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;
349 350 351 352 353

		return this;

	},

354
	project: function () {
355

356
		var matrix;
357

358
		return function project( camera ) {
359

360
			if ( matrix === undefined ) matrix = new THREE.Matrix4();
361

362 363
			matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
			return this.applyProjection( matrix );
364 365 366 367 368

		};

	}(),

369
	unproject: function () {
370

371
		var matrix;
372

373
		return function unproject( camera ) {
374

375
			if ( matrix === undefined ) matrix = new THREE.Matrix4();
376

377 378
			matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
			return this.applyProjection( matrix );
379 380 381 382 383

		};

	}(),

384 385 386 387 388 389 390 391 392
	transformDirection: function ( m ) {

		// input: THREE.Matrix4 affine matrix
		// vector interpreted as a direction

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

		var e = m.elements;

393 394 395
		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z;
		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z;
		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
396 397 398 399 400 401 402

		this.normalize();

		return this;

	},

403
	divide: function ( v ) {
404

405 406 407 408 409
		this.x /= v.x;
		this.y /= v.y;
		this.z /= v.z;

		return this;
M
Mr.doob 已提交
410

M
Mr.doob 已提交
411
	},
412

413
	divideScalar: function ( scalar ) {
414

M
Mr.doob 已提交
415
		return this.multiplyScalar( 1 / scalar );
B
Ben Nolan 已提交
416

417
	},
418

419
	min: function ( v ) {
420

M
Mr.doob 已提交
421 422 423
		this.x = Math.min( this.x, v.x );
		this.y = Math.min( this.y, v.y );
		this.z = Math.min( this.z, v.z );
424 425 426 427 428

		return this;

	},

429
	max: function ( v ) {
430

M
Mr.doob 已提交
431 432 433
		this.x = Math.max( this.x, v.x );
		this.y = Math.max( this.y, v.y );
		this.z = Math.max( this.z, v.z );
434 435 436 437

		return this;

	},
M
Mr.doob 已提交
438

439
	clamp: function ( min, max ) {
440 441 442

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

M
Mr.doob 已提交
443 444 445
		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
446 447

		return this;
A
alteredq 已提交
448

449 450
	},

451
	clampScalar: function () {
M
Mr.doob 已提交
452

453 454
		var min, max;

455
		return function clampScalar( minVal, maxVal ) {
M
Mr.doob 已提交
456 457 458

			if ( min === undefined ) {

459 460
				min = new THREE.Vector3();
				max = new THREE.Vector3();
M
Mr.doob 已提交
461

462 463
			}

M
Mr.doob 已提交
464 465 466 467
			min.set( minVal, minVal, minVal );
			max.set( maxVal, maxVal, maxVal );

			return this.clamp( min, max );
468 469

		};
M
Mr.doob 已提交
470

471
	}(),
472

M
Mugen87 已提交
473
	clampLength: function ( min, max ) {
474

M
Mugen87 已提交
475
		var length = this.length();
476

M
Mugen87 已提交
477
		this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
478

M
Mugen87 已提交
479
		return this;
480

M
Mugen87 已提交
481
	},
482

M
Mr.doob 已提交
483 484 485 486 487 488
	floor: function () {

		this.x = Math.floor( this.x );
		this.y = Math.floor( this.y );
		this.z = Math.floor( this.z );

489
		return this;
M
Mr.doob 已提交
490

491 492
	},

M
Mr.doob 已提交
493 494 495 496 497 498
	ceil: function () {

		this.x = Math.ceil( this.x );
		this.y = Math.ceil( this.y );
		this.z = Math.ceil( this.z );

499
		return this;
M
Mr.doob 已提交
500

501 502
	},

M
Mr.doob 已提交
503 504 505 506 507 508
	round: function () {

		this.x = Math.round( this.x );
		this.y = Math.round( this.y );
		this.z = Math.round( this.z );

509
		return this;
M
Mr.doob 已提交
510

511 512
	},

M
Mr.doob 已提交
513 514 515 516 517 518
	roundToZero: function () {

		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
		this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );

519
		return this;
M
Mr.doob 已提交
520

521
	},
522

523
	negate: function () {
M
Mr.doob 已提交
524

M
Mr.doob 已提交
525 526 527 528 529
		this.x = - this.x;
		this.y = - this.y;
		this.z = - this.z;

		return this;
B
Ben Nolan 已提交
530

531
	},
532

533
	dot: function ( v ) {
M
Mr.doob 已提交
534

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

M
Mr.doob 已提交
537
	},
M
Mr.doob 已提交
538

539
	lengthSq: function () {
M
Mr.doob 已提交
540

M
Mr.doob 已提交
541
		return this.x * this.x + this.y * this.y + this.z * this.z;
M
Mr.doob 已提交
542 543 544

	},

545
	length: function () {
M
Mr.doob 已提交
546

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

M
Mr.doob 已提交
549
	},
550

551
	lengthManhattan: function () {
552

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

555 556
	},

557
	normalize: function () {
558

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

561
	},
562

563
	setLength: function ( length ) {
564

M
Mr.doob 已提交
565
		return this.multiplyScalar( length / this.length() );
566

567
	},
568

569
	lerp: function ( v, alpha ) {
570 571 572 573 574 575 576 577

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

		return this;

	},
578

W
WestLangley 已提交
579 580
	lerpVectors: function ( v1, v2, alpha ) {

G
gero3 已提交
581
		this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
W
WestLangley 已提交
582

G
gero3 已提交
583
		return this;
W
WestLangley 已提交
584 585 586

	},

587 588 589 590
	cross: function ( v, w ) {

		if ( w !== undefined ) {

591
			console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
592 593 594
			return this.crossVectors( v, w );

		}
595

596
		var x = this.x, y = this.y, z = this.z;
597

598 599 600
		this.x = y * v.z - z * v.y;
		this.y = z * v.x - x * v.z;
		this.z = x * v.y - y * v.x;
601

602
		return this;
603 604 605

	},

606 607
	crossVectors: function ( a, b ) {

608 609 610 611 612 613
		var ax = a.x, ay = a.y, az = a.z;
		var bx = b.x, by = b.y, bz = b.z;

		this.x = ay * bz - az * by;
		this.y = az * bx - ax * bz;
		this.z = ax * by - ay * bx;
614 615 616 617 618

		return this;

	},

M
Mr.doob 已提交
619 620
	projectOnVector: function () {

M
Mr.doob 已提交
621
		var v1, dot;
M
Mr.doob 已提交
622

623
		return function projectOnVector( vector ) {
M
Mr.doob 已提交
624 625 626 627 628

			if ( v1 === undefined ) v1 = new THREE.Vector3();

			v1.copy( vector ).normalize();

M
Mr.doob 已提交
629 630 631
			dot = this.dot( v1 );

			return this.copy( v1 ).multiplyScalar( dot );
M
Mr.doob 已提交
632 633 634 635 636 637 638 639 640

		};

	}(),

	projectOnPlane: function () {

		var v1;

641
		return function projectOnPlane( planeNormal ) {
M
Mr.doob 已提交
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659

			if ( v1 === undefined ) v1 = new THREE.Vector3();

			v1.copy( this ).projectOnVector( planeNormal );

			return this.sub( v1 );

		}

	}(),

	reflect: function () {

		// reflect incident vector off plane orthogonal to normal
		// normal is assumed to have unit length

		var v1;

660
		return function reflect( normal ) {
M
Mr.doob 已提交
661 662 663 664 665 666 667 668 669

			if ( v1 === undefined ) v1 = new THREE.Vector3();

			return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );

		}

	}(),

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

672
		var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
673

674 675
		// clamp, to handle numerical problems

676
		return Math.acos( THREE.Math.clamp( theta, - 1, 1 ) );
M
Mr.doob 已提交
677 678

	},
W
Wilt 已提交
679

680
	distanceTo: function ( v ) {
681

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

M
Mr.doob 已提交
684 685
	},

686
	distanceToSquared: function ( v ) {
M
Mr.doob 已提交
687

M
Mr.doob 已提交
688 689 690 691
		var dx = this.x - v.x;
		var dy = this.y - v.y;
		var dz = this.z - v.z;

692
		return dx * dx + dy * dy + dz * dz;
M
Mr.doob 已提交
693

694
	},
M
Mr.doob 已提交
695

B
Ben Houston 已提交
696 697 698 699 700 701 702 703 704 705 706
	setFromSpherical: function( s ) {

		var sinPhiRadius = Math.sin( s.phi ) * s.radius;
		this.x = sinPhiRadius * Math.sin( s.theta );
		this.y = Math.cos( s.phi ) * s.radius;
		this.z = sinPhiRadius * Math.cos( s.theta );

		return this;

	},

707 708
	setFromMatrixPosition: function ( m ) {

709
		this.setFromMatrixColumn( 3, m );
710 711 712 713 714 715 716

		return this;

	},

	setFromMatrixScale: function ( m ) {

717 718 719
		var sx = this.setFromMatrixColumn( 0, m ).length();
		var sy = this.setFromMatrixColumn( 1, m ).length();
		var sz = this.setFromMatrixColumn( 2, m ).length();
M
Mr.doob 已提交
720

721 722 723
		this.x = sx;
		this.y = sy;
		this.z = sz;
M
Mr.doob 已提交
724

725
		return this;
G
gero3 已提交
726

M
Mr.doob 已提交
727 728
	},

729
	setFromMatrixColumn: function ( index, matrix ) {
730

731
		var offset = index * 4;
W
WestLangley 已提交
732

733
		var me = matrix.elements;
W
WestLangley 已提交
734

735 736 737
		this.x = me[ offset ];
		this.y = me[ offset + 1 ];
		this.z = me[ offset + 2 ];
W
WestLangley 已提交
738 739 740 741 742

		return this;

	},

M
Mr.doob 已提交
743
	equals: function ( v ) {
744 745 746

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

747 748
	},

749
	fromArray: function ( array, offset ) {
750

751 752 753 754 755
		if ( offset === undefined ) offset = 0;

		this.x = array[ offset ];
		this.y = array[ offset + 1 ];
		this.z = array[ offset + 2 ];
756

M
Mr.doob 已提交
757 758
		return this;

759 760
	},

761
	toArray: function ( array, offset ) {
762

A
arose 已提交
763 764
		if ( array === undefined ) array = [];
		if ( offset === undefined ) offset = 0;
765

A
arose 已提交
766 767 768
		array[ offset ] = this.x;
		array[ offset + 1 ] = this.y;
		array[ offset + 2 ] = this.z;
769

A
arose 已提交
770
		return array;
771

772 773
	},

W
WestLangley 已提交
774 775
	fromAttribute: function ( attribute, index, offset ) {

G
gero3 已提交
776
		if ( offset === undefined ) offset = 0;
W
WestLangley 已提交
777

G
gero3 已提交
778
		index = index * attribute.itemSize + offset;
W
WestLangley 已提交
779

G
gero3 已提交
780 781 782
		this.x = attribute.array[ index ];
		this.y = attribute.array[ index + 1 ];
		this.z = attribute.array[ index + 2 ];
W
WestLangley 已提交
783

G
gero3 已提交
784
		return this;
W
WestLangley 已提交
785

786
	}
787

788
};