Vector3.js 12.8 KB
Newer Older
R
Rich Harris 已提交
1 2 3 4
import { _Math } from './Math';
import { Matrix4 } from './Matrix4';
import { Quaternion } from './Quaternion';

M
Mr.doob 已提交
5
/**
M
Mr.doob 已提交
6
 * @author mrdoob / http://mrdoob.com/
7
 * @author *kile / http://kile.stravaganza.org/
M
Mr.doob 已提交
8
 * @author philogb / http://blog.thejit.org/
9
 * @author mikael emtinger / http://gomo.se/
M
Mr.doob 已提交
10
 * @author egraether / http://egraether.com/
W
WestLangley 已提交
11
 * @author WestLangley / http://github.com/WestLangley
M
Mr.doob 已提交
12 13
 */

R
Rich Harris 已提交
14 15
function Vector3 ( x, y, z ) {
	this.isVector3 = true;
16

17 18 19
	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;
M
Mr.doob 已提交
20

21
};
22

R
Rich Harris 已提交
23
Vector3.prototype = {
24

R
Rich Harris 已提交
25
	constructor: Vector3,
26

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

A
alteredq 已提交
29 30 31
		this.x = x;
		this.y = y;
		this.z = z;
M
Mr.doob 已提交
32

33
		return this;
34

35
	},
36

M
Mr.doob 已提交
37 38 39 40 41 42 43 44 45 46
	setScalar: function ( scalar ) {

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

		return this;

	},

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

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

M
Mr.doob 已提交
75 76 77
			case 0: this.x = value; break;
			case 1: this.y = value; break;
			case 2: this.z = value; break;
78
			default: throw new Error( 'index is out of range: ' + index );
B
Ben Houston 已提交
79

M
Mr.doob 已提交
80
		}
B
Ben Houston 已提交
81

M
Mr.doob 已提交
82
	},
83

M
Mr.doob 已提交
84
	getComponent: function ( index ) {
85

M
Mr.doob 已提交
86
		switch ( index ) {
87

M
Mr.doob 已提交
88 89 90
			case 0: return this.x;
			case 1: return this.y;
			case 2: return this.z;
91
			default: throw new Error( 'index is out of range: ' + index );
92

M
Mr.doob 已提交
93
		}
94

M
Mr.doob 已提交
95
	},
96

97 98 99 100 101 102
	clone: function () {

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

	},

103
	copy: function ( v ) {
M
Mr.doob 已提交
104

M
Mr.doob 已提交
105 106 107
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
M
Mr.doob 已提交
108

109
		return this;
M
Mr.doob 已提交
110

111
	},
112

113 114 115 116
	add: function ( v, w ) {

		if ( w !== undefined ) {

117
			console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
118 119 120
			return this.addVectors( v, w );

		}
M
Mr.doob 已提交
121

M
Mr.doob 已提交
122 123 124
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
125

B
Ben Nolan 已提交
126 127
		return this;

128
	},
129

130
	addScalar: function ( s ) {
M
Mr.doob 已提交
131

M
Mr.doob 已提交
132 133 134
		this.x += s;
		this.y += s;
		this.z += s;
135

B
Ben Nolan 已提交
136 137
		return this;

138
	},
139

140
	addVectors: function ( a, b ) {
141

142 143 144
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
145

146
		return this;
M
Mr.doob 已提交
147

148
	},
149

G
gero3 已提交
150 151
	addScaledVector: function ( v, s ) {

G
gero3 已提交
152 153 154
		this.x += v.x * s;
		this.y += v.y * s;
		this.z += v.z * s;
G
gero3 已提交
155

G
gero3 已提交
156
		return this;
G
gero3 已提交
157

G
gero3 已提交
158
	},
159

160 161 162 163
	sub: function ( v, w ) {

		if ( w !== undefined ) {

164
			console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
165 166 167
			return this.subVectors( v, w );

		}
168

M
Mr.doob 已提交
169 170 171
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
172

B
Ben Nolan 已提交
173 174
		return this;

175
	},
176

C
Corey Birnbaum 已提交
177 178 179 180 181 182 183 184 185
	subScalar: function ( s ) {

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

		return this;

	},
186

187
	subVectors: function ( a, b ) {
188

189 190 191
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
192

193
		return this;
M
Mr.doob 已提交
194

195
	},
196

197 198 199 200
	multiply: function ( v, w ) {

		if ( w !== undefined ) {

201
			console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
202 203 204
			return this.multiplyVectors( v, w );

		}
205

M
Mr.doob 已提交
206 207
		this.x *= v.x;
		this.y *= v.y;
N
Nico Kruithof 已提交
208
		this.z *= v.z;
M
Mr.doob 已提交
209 210 211 212 213

		return this;

	},

214
	multiplyScalar: function ( scalar ) {
M
Mr.doob 已提交
215

M
Mr.doob 已提交
216
		if ( isFinite( scalar ) ) {
M
Mr.doob 已提交
217

M
Mr.doob 已提交
218 219 220
			this.x *= scalar;
			this.y *= scalar;
			this.z *= scalar;
M
Mr.doob 已提交
221

M
Mr.doob 已提交
222
		} else {
M
Mr.doob 已提交
223

M
Mr.doob 已提交
224 225 226
			this.x = 0;
			this.y = 0;
			this.z = 0;
M
Mr.doob 已提交
227

M
Mr.doob 已提交
228
		}
229

B
Ben Nolan 已提交
230 231
		return this;

232
	},
233

234 235 236 237 238 239 240 241 242 243
	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 已提交
244 245 246 247
	applyEuler: function () {

		var quaternion;

248
		return function applyEuler( euler ) {
M
Mr.doob 已提交
249

R
Rich Harris 已提交
250
			if ( (euler && euler.isEuler) === false ) {
M
Mr.doob 已提交
251

P
paulmasson 已提交
252
				console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
M
Mr.doob 已提交
253 254 255

			}

R
Rich Harris 已提交
256
			if ( quaternion === undefined ) quaternion = new Quaternion();
M
Mr.doob 已提交
257

258
			return this.applyQuaternion( quaternion.setFromEuler( euler ) );
M
Mr.doob 已提交
259 260 261 262 263 264 265 266 267

		};

	}(),

	applyAxisAngle: function () {

		var quaternion;

268
		return function applyAxisAngle( axis, angle ) {
M
Mr.doob 已提交
269

R
Rich Harris 已提交
270
			if ( quaternion === undefined ) quaternion = new Quaternion();
M
Mr.doob 已提交
271

272
			return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
M
Mr.doob 已提交
273 274 275 276 277

		};

	}(),

278
	applyMatrix3: function ( m ) {
279

280
		var x = this.x, y = this.y, z = this.z;
281 282
		var e = m.elements;

283 284 285
		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;
286 287 288 289 290

		return this;

	},

291
	applyMatrix4: function ( m ) {
292

293 294 295
		// input: THREE.Matrix4 affine matrix

		var x = this.x, y = this.y, z = this.z;
296 297
		var e = m.elements;

298 299 300
		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 ];
301 302 303 304 305

		return this;

	},

306 307 308 309 310 311
	applyProjection: function ( m ) {

		// input: THREE.Matrix4 projection matrix

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

314 315 316
		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;
317 318 319 320 321

		return this;

	},

322
	applyQuaternion: function ( q ) {
323

324 325
		var x = this.x, y = this.y, z = this.z;
		var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
326 327 328 329 330 331

		// 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;
332
		var iw = - qx * x - qy * y - qz * z;
333 334 335

		// calculate result * inverse quat

336 337 338
		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;
339 340 341 342 343

		return this;

	},

344
	project: function () {
345

346
		var matrix;
347

348
		return function project( camera ) {
349

R
Rich Harris 已提交
350
			if ( matrix === undefined ) matrix = new Matrix4();
351

352 353
			matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
			return this.applyProjection( matrix );
354 355 356 357 358

		};

	}(),

359
	unproject: function () {
360

361
		var matrix;
362

363
		return function unproject( camera ) {
364

R
Rich Harris 已提交
365
			if ( matrix === undefined ) matrix = new Matrix4();
366

367 368
			matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
			return this.applyProjection( matrix );
369 370 371 372 373

		};

	}(),

374 375 376 377 378 379 380 381
	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;

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

386
		return this.normalize();
387 388 389

	},

390
	divide: function ( v ) {
391

392 393 394 395 396
		this.x /= v.x;
		this.y /= v.y;
		this.z /= v.z;

		return this;
M
Mr.doob 已提交
397

M
Mr.doob 已提交
398
	},
399

400
	divideScalar: function ( scalar ) {
401

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

404
	},
405

406
	min: function ( v ) {
407

M
Mr.doob 已提交
408 409 410
		this.x = Math.min( this.x, v.x );
		this.y = Math.min( this.y, v.y );
		this.z = Math.min( this.z, v.z );
411 412 413 414 415

		return this;

	},

416
	max: function ( v ) {
417

M
Mr.doob 已提交
418 419 420
		this.x = Math.max( this.x, v.x );
		this.y = Math.max( this.y, v.y );
		this.z = Math.max( this.z, v.z );
421 422 423 424

		return this;

	},
M
Mr.doob 已提交
425

426
	clamp: function ( min, max ) {
427 428 429

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

M
Mr.doob 已提交
430 431 432
		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 ) );
433 434

		return this;
A
alteredq 已提交
435

436 437
	},

438
	clampScalar: function () {
M
Mr.doob 已提交
439

440 441
		var min, max;

442
		return function clampScalar( minVal, maxVal ) {
M
Mr.doob 已提交
443 444 445

			if ( min === undefined ) {

R
Rich Harris 已提交
446 447
				min = new Vector3();
				max = new Vector3();
M
Mr.doob 已提交
448

449 450
			}

M
Mr.doob 已提交
451 452 453 454
			min.set( minVal, minVal, minVal );
			max.set( maxVal, maxVal, maxVal );

			return this.clamp( min, max );
455 456

		};
M
Mr.doob 已提交
457

458
	}(),
459

M
Mugen87 已提交
460
	clampLength: function ( min, max ) {
461

M
Mugen87 已提交
462
		var length = this.length();
463

464
		return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
465

M
Mugen87 已提交
466
	},
467

M
Mr.doob 已提交
468 469 470 471 472 473
	floor: function () {

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

474
		return this;
M
Mr.doob 已提交
475

476 477
	},

M
Mr.doob 已提交
478 479 480 481 482 483
	ceil: function () {

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

484
		return this;
M
Mr.doob 已提交
485

486 487
	},

M
Mr.doob 已提交
488 489 490 491 492 493
	round: function () {

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

494
		return this;
M
Mr.doob 已提交
495

496 497
	},

M
Mr.doob 已提交
498 499 500 501 502 503
	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 );

504
		return this;
M
Mr.doob 已提交
505

506
	},
507

508
	negate: function () {
M
Mr.doob 已提交
509

M
Mr.doob 已提交
510 511 512 513 514
		this.x = - this.x;
		this.y = - this.y;
		this.z = - this.z;

		return this;
B
Ben Nolan 已提交
515

516
	},
517

518
	dot: function ( v ) {
M
Mr.doob 已提交
519

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

M
Mr.doob 已提交
522
	},
M
Mr.doob 已提交
523

524
	lengthSq: function () {
M
Mr.doob 已提交
525

M
Mr.doob 已提交
526
		return this.x * this.x + this.y * this.y + this.z * this.z;
M
Mr.doob 已提交
527 528 529

	},

530
	length: function () {
M
Mr.doob 已提交
531

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

M
Mr.doob 已提交
534
	},
535

536
	lengthManhattan: function () {
537

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

540 541
	},

542
	normalize: function () {
543

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

546
	},
547

548
	setLength: function ( length ) {
549

M
Mr.doob 已提交
550
		return this.multiplyScalar( length / this.length() );
551

552
	},
553

554
	lerp: function ( v, alpha ) {
555 556 557 558 559 560 561 562

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

		return this;

	},
563

W
WestLangley 已提交
564 565
	lerpVectors: function ( v1, v2, alpha ) {

566
		return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
W
WestLangley 已提交
567 568 569

	},

570 571 572 573
	cross: function ( v, w ) {

		if ( w !== undefined ) {

574
			console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
575 576 577
			return this.crossVectors( v, w );

		}
578

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

581 582 583
		this.x = y * v.z - z * v.y;
		this.y = z * v.x - x * v.z;
		this.z = x * v.y - y * v.x;
584

585
		return this;
586 587 588

	},

589 590
	crossVectors: function ( a, b ) {

591 592 593 594 595 596
		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;
597 598 599 600 601

		return this;

	},

602
	projectOnVector: function ( vector ) {
M
Mr.doob 已提交
603

604 605 606 607 608
		var scalar = vector.dot( this ) / vector.lengthSq();
	
		return this.copy( vector ).multiplyScalar( scalar );
	
	},
M
Mr.doob 已提交
609 610 611 612 613

	projectOnPlane: function () {

		var v1;

614
		return function projectOnPlane( planeNormal ) {
M
Mr.doob 已提交
615

R
Rich Harris 已提交
616
			if ( v1 === undefined ) v1 = new Vector3();
M
Mr.doob 已提交
617 618 619 620 621

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

			return this.sub( v1 );

M
Mr.doob 已提交
622
		};
M
Mr.doob 已提交
623 624 625 626 627 628 629 630 631 632

	}(),

	reflect: function () {

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

		var v1;

633
		return function reflect( normal ) {
M
Mr.doob 已提交
634

R
Rich Harris 已提交
635
			if ( v1 === undefined ) v1 = new Vector3();
M
Mr.doob 已提交
636 637 638

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

M
Mr.doob 已提交
639
		};
M
Mr.doob 已提交
640 641 642

	}(),

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

645
		var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
646

647 648
		// clamp, to handle numerical problems

R
Rich Harris 已提交
649
		return Math.acos( _Math.clamp( theta, - 1, 1 ) );
M
Mr.doob 已提交
650 651

	},
W
Wilt 已提交
652

653
	distanceTo: function ( v ) {
654

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

M
Mr.doob 已提交
657 658
	},

659
	distanceToSquared: function ( v ) {
M
Mr.doob 已提交
660

661
		var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
M
Mr.doob 已提交
662

663
		return dx * dx + dy * dy + dz * dz;
M
Mr.doob 已提交
664

665
	},
M
Mr.doob 已提交
666

W
WestLangley 已提交
667 668 669 670 671 672
	distanceToManhattan: function ( v ) {

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

	},

B
Ben Houston 已提交
673 674 675
	setFromSpherical: function( s ) {

		var sinPhiRadius = Math.sin( s.phi ) * s.radius;
M
Mr.doob 已提交
676

B
Ben Houston 已提交
677 678 679 680 681 682 683 684
		this.x = sinPhiRadius * Math.sin( s.theta );
		this.y = Math.cos( s.phi ) * s.radius;
		this.z = sinPhiRadius * Math.cos( s.theta );

		return this;

	},

685 686
	setFromMatrixPosition: function ( m ) {

M
Mr.doob 已提交
687
		return this.setFromMatrixColumn( m, 3 );
688 689 690 691 692

	},

	setFromMatrixScale: function ( m ) {

693 694 695 696 697 698 699
		var sx = this.setFromMatrixColumn( m, 0 ).length();
		var sy = this.setFromMatrixColumn( m, 1 ).length();
		var sz = this.setFromMatrixColumn( m, 2 ).length();

		this.x = sx;
		this.y = sy;
		this.z = sz;
M
Mr.doob 已提交
700

701
		return this;
G
gero3 已提交
702

M
Mr.doob 已提交
703 704
	},

705
	setFromMatrixColumn: function ( m, index ) {
706

707 708 709
		if ( typeof m === 'number' ) {

			console.warn( 'THREE.Vector3: setFromMatrixColumn now expects ( matrix, index ).' );
710 711 712
			var temp = m
			m = index;
			index = temp;
713 714 715

		}

M
Mr.doob 已提交
716
		return this.fromArray( m.elements, index * 4 );
W
WestLangley 已提交
717 718 719

	},

M
Mr.doob 已提交
720
	equals: function ( v ) {
721 722 723

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

724 725
	},

726
	fromArray: function ( array, offset ) {
727

728 729 730 731 732
		if ( offset === undefined ) offset = 0;

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

M
Mr.doob 已提交
734 735
		return this;

736 737
	},

738
	toArray: function ( array, offset ) {
739

A
arose 已提交
740 741
		if ( array === undefined ) array = [];
		if ( offset === undefined ) offset = 0;
742

A
arose 已提交
743 744 745
		array[ offset ] = this.x;
		array[ offset + 1 ] = this.y;
		array[ offset + 2 ] = this.z;
746

A
arose 已提交
747
		return array;
748

749 750
	},

W
WestLangley 已提交
751 752
	fromAttribute: function ( attribute, index, offset ) {

G
gero3 已提交
753
		if ( offset === undefined ) offset = 0;
W
WestLangley 已提交
754

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

G
gero3 已提交
757 758 759
		this.x = attribute.array[ index ];
		this.y = attribute.array[ index + 1 ];
		this.z = attribute.array[ index + 2 ];
W
WestLangley 已提交
760

G
gero3 已提交
761
		return this;
W
WestLangley 已提交
762

763
	}
764

765
};
R
Rich Harris 已提交
766 767 768


export { Vector3 };