Vector3.js 12.9 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
 */

M
Mr.doob 已提交
14
function Vector3( x, y, z ) {
15

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

M
Mr.doob 已提交
20
}
21

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

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

26 27
	isVector3: true,

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

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

34
		return this;
35

36
	},
37

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

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

		return this;

	},

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

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

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

M
Mr.doob 已提交
81
		}
M
Mugen87 已提交
82

M
matthias-w 已提交
83
		return this;
B
Ben Houston 已提交
84

M
Mr.doob 已提交
85
	},
86

M
Mr.doob 已提交
87
	getComponent: function ( index ) {
88

M
Mr.doob 已提交
89
		switch ( index ) {
90

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

M
Mr.doob 已提交
96
		}
97

M
Mr.doob 已提交
98
	},
99

100 101 102 103 104 105
	clone: function () {

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

	},

106
	copy: function ( v ) {
M
Mr.doob 已提交
107

M
Mr.doob 已提交
108 109 110
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
M
Mr.doob 已提交
111

112
		return this;
M
Mr.doob 已提交
113

114
	},
115

116 117 118 119
	add: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
M
Mr.doob 已提交
124

M
Mr.doob 已提交
125 126 127
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
128

B
Ben Nolan 已提交
129 130
		return this;

131
	},
132

133
	addScalar: function ( s ) {
M
Mr.doob 已提交
134

M
Mr.doob 已提交
135 136 137
		this.x += s;
		this.y += s;
		this.z += s;
138

B
Ben Nolan 已提交
139 140
		return this;

141
	},
142

143
	addVectors: function ( a, b ) {
144

145 146 147
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
148

149
		return this;
M
Mr.doob 已提交
150

151
	},
152

G
gero3 已提交
153 154
	addScaledVector: function ( v, s ) {

G
gero3 已提交
155 156 157
		this.x += v.x * s;
		this.y += v.y * s;
		this.z += v.z * s;
G
gero3 已提交
158

G
gero3 已提交
159
		return this;
G
gero3 已提交
160

G
gero3 已提交
161
	},
162

163 164 165 166
	sub: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
171

M
Mr.doob 已提交
172 173 174
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
175

B
Ben Nolan 已提交
176 177
		return this;

178
	},
179

C
Corey Birnbaum 已提交
180 181 182 183 184 185 186 187 188
	subScalar: function ( s ) {

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

		return this;

	},
189

190
	subVectors: function ( a, b ) {
191

192 193 194
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
195

196
		return this;
M
Mr.doob 已提交
197

198
	},
199

200 201 202 203
	multiply: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
208

M
Mr.doob 已提交
209 210
		this.x *= v.x;
		this.y *= v.y;
N
Nico Kruithof 已提交
211
		this.z *= v.z;
M
Mr.doob 已提交
212 213 214 215 216

		return this;

	},

217
	multiplyScalar: function ( scalar ) {
M
Mr.doob 已提交
218

M
Mr.doob 已提交
219
		if ( isFinite( scalar ) ) {
M
Mr.doob 已提交
220

M
Mr.doob 已提交
221 222 223
			this.x *= scalar;
			this.y *= scalar;
			this.z *= scalar;
M
Mr.doob 已提交
224

M
Mr.doob 已提交
225
		} else {
M
Mr.doob 已提交
226

M
Mr.doob 已提交
227 228 229
			this.x = 0;
			this.y = 0;
			this.z = 0;
M
Mr.doob 已提交
230

M
Mr.doob 已提交
231
		}
232

B
Ben Nolan 已提交
233 234
		return this;

235
	},
236

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

		var quaternion;

251
		return function applyEuler( euler ) {
M
Mr.doob 已提交
252

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

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

			}

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

261
			return this.applyQuaternion( quaternion.setFromEuler( euler ) );
M
Mr.doob 已提交
262 263 264 265 266 267 268 269 270

		};

	}(),

	applyAxisAngle: function () {

		var quaternion;

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

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

275
			return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
M
Mr.doob 已提交
276 277 278 279 280

		};

	}(),

281
	applyMatrix3: function ( m ) {
282

283
		var x = this.x, y = this.y, z = this.z;
284 285
		var e = m.elements;

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

		return this;

	},

294
	applyMatrix4: function ( m ) {
295

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

		var x = this.x, y = this.y, z = this.z;
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
	applyProjection: function ( m ) {

		// input: THREE.Matrix4 projection matrix

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

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

		return this;

	},

325
	applyQuaternion: function ( q ) {
326

327 328
		var x = this.x, y = this.y, z = this.z;
		var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
329 330 331 332 333 334

		// 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;
335
		var iw = - qx * x - qy * y - qz * z;
336 337 338

		// calculate result * inverse quat

339 340 341
		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;
342 343 344 345 346

		return this;

	},

347
	project: function () {
348

349
		var matrix;
350

351
		return function project( camera ) {
352

R
Rich Harris 已提交
353
			if ( matrix === undefined ) matrix = new Matrix4();
354

355 356
			matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
			return this.applyProjection( matrix );
357 358 359 360 361

		};

	}(),

362
	unproject: function () {
363

364
		var matrix;
365

366
		return function unproject( camera ) {
367

R
Rich Harris 已提交
368
			if ( matrix === undefined ) matrix = new Matrix4();
369

370 371
			matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
			return this.applyProjection( matrix );
372 373 374 375 376

		};

	}(),

377 378 379 380 381 382 383 384
	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;

385 386 387
		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;
388

389
		return this.normalize();
390 391 392

	},

393
	divide: function ( v ) {
394

395 396 397 398 399
		this.x /= v.x;
		this.y /= v.y;
		this.z /= v.z;

		return this;
M
Mr.doob 已提交
400

M
Mr.doob 已提交
401
	},
402

403
	divideScalar: function ( scalar ) {
404

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

407
	},
408

409
	min: function ( v ) {
410

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

		return this;

	},

419
	max: function ( v ) {
420

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

		return this;

	},
M
Mr.doob 已提交
428

429
	clamp: function ( min, max ) {
430 431 432

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

M
Mr.doob 已提交
433 434 435
		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 ) );
436 437

		return this;
A
alteredq 已提交
438

439 440
	},

441
	clampScalar: function () {
M
Mr.doob 已提交
442

443 444
		var min, max;

445
		return function clampScalar( minVal, maxVal ) {
M
Mr.doob 已提交
446 447 448

			if ( min === undefined ) {

R
Rich Harris 已提交
449 450
				min = new Vector3();
				max = new Vector3();
M
Mr.doob 已提交
451

452 453
			}

M
Mr.doob 已提交
454 455 456 457
			min.set( minVal, minVal, minVal );
			max.set( maxVal, maxVal, maxVal );

			return this.clamp( min, max );
458 459

		};
M
Mr.doob 已提交
460

461
	}(),
462

M
Mugen87 已提交
463
	clampLength: function ( min, max ) {
464

M
Mugen87 已提交
465
		var length = this.length();
466

467
		return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
468

M
Mugen87 已提交
469
	},
470

M
Mr.doob 已提交
471 472 473 474 475 476
	floor: function () {

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

477
		return this;
M
Mr.doob 已提交
478

479 480
	},

M
Mr.doob 已提交
481 482 483 484 485 486
	ceil: function () {

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

487
		return this;
M
Mr.doob 已提交
488

489 490
	},

M
Mr.doob 已提交
491 492 493 494 495 496
	round: function () {

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

497
		return this;
M
Mr.doob 已提交
498

499 500
	},

M
Mr.doob 已提交
501 502 503 504 505 506
	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 );

507
		return this;
M
Mr.doob 已提交
508

509
	},
510

511
	negate: function () {
M
Mr.doob 已提交
512

M
Mr.doob 已提交
513 514 515 516 517
		this.x = - this.x;
		this.y = - this.y;
		this.z = - this.z;

		return this;
B
Ben Nolan 已提交
518

519
	},
520

521
	dot: function ( v ) {
M
Mr.doob 已提交
522

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

M
Mr.doob 已提交
525
	},
M
Mr.doob 已提交
526

527
	lengthSq: function () {
M
Mr.doob 已提交
528

M
Mr.doob 已提交
529
		return this.x * this.x + this.y * this.y + this.z * this.z;
M
Mr.doob 已提交
530 531 532

	},

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

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

M
Mr.doob 已提交
537
	},
538

539
	lengthManhattan: function () {
540

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

543 544
	},

545
	normalize: function () {
546

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

549
	},
550

551
	setLength: function ( length ) {
552

M
Mr.doob 已提交
553
		return this.multiplyScalar( length / this.length() );
554

555
	},
556

557
	lerp: function ( v, alpha ) {
558 559 560 561 562 563 564 565

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

		return this;

	},
566

W
WestLangley 已提交
567 568
	lerpVectors: function ( v1, v2, alpha ) {

569
		return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
W
WestLangley 已提交
570 571 572

	},

573 574 575 576
	cross: function ( v, w ) {

		if ( w !== undefined ) {

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

		}
581

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

584 585 586
		this.x = y * v.z - z * v.y;
		this.y = z * v.x - x * v.z;
		this.z = x * v.y - y * v.x;
587

588
		return this;
589 590 591

	},

592 593
	crossVectors: function ( a, b ) {

594 595 596 597 598 599
		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;
600 601 602 603 604

		return this;

	},

605
	projectOnVector: function ( vector ) {
M
Mr.doob 已提交
606

607
		var scalar = vector.dot( this ) / vector.lengthSq();
608

609
		return this.copy( vector ).multiplyScalar( scalar );
610

611
	},
M
Mr.doob 已提交
612 613 614 615 616

	projectOnPlane: function () {

		var v1;

617
		return function projectOnPlane( planeNormal ) {
M
Mr.doob 已提交
618

R
Rich Harris 已提交
619
			if ( v1 === undefined ) v1 = new Vector3();
M
Mr.doob 已提交
620 621 622 623 624

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

			return this.sub( v1 );

M
Mr.doob 已提交
625
		};
M
Mr.doob 已提交
626 627 628 629 630 631 632 633 634 635

	}(),

	reflect: function () {

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

		var v1;

636
		return function reflect( normal ) {
M
Mr.doob 已提交
637

R
Rich Harris 已提交
638
			if ( v1 === undefined ) v1 = new Vector3();
M
Mr.doob 已提交
639 640 641

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

M
Mr.doob 已提交
642
		};
M
Mr.doob 已提交
643 644 645

	}(),

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

648
		var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
649

650 651
		// clamp, to handle numerical problems

R
Rich Harris 已提交
652
		return Math.acos( _Math.clamp( theta, - 1, 1 ) );
M
Mr.doob 已提交
653 654

	},
W
Wilt 已提交
655

656
	distanceTo: function ( v ) {
657

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

M
Mr.doob 已提交
660 661
	},

662
	distanceToSquared: function ( v ) {
M
Mr.doob 已提交
663

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

666
		return dx * dx + dy * dy + dz * dz;
M
Mr.doob 已提交
667

668
	},
M
Mr.doob 已提交
669

W
WestLangley 已提交
670 671 672 673 674 675
	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 已提交
676 677 678
	setFromSpherical: function( s ) {

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

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

		return this;

	},

M
Mugen87 已提交
688 689 690 691 692 693 694 695 696 697
	setFromCylindrical: function( c ) {

		this.x = c.radius * Math.sin( c.theta );
		this.y = c.y;
		this.z = c.radius * Math.cos( c.theta );

		return this;

	},

698 699
	setFromMatrixPosition: function ( m ) {

M
Mr.doob 已提交
700
		return this.setFromMatrixColumn( m, 3 );
701 702 703 704 705

	},

	setFromMatrixScale: function ( m ) {

706 707 708 709 710 711 712
		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 已提交
713

714
		return this;
G
gero3 已提交
715

M
Mr.doob 已提交
716 717
	},

718
	setFromMatrixColumn: function ( m, index ) {
719

720 721 722
		if ( typeof m === 'number' ) {

			console.warn( 'THREE.Vector3: setFromMatrixColumn now expects ( matrix, index ).' );
723 724 725
			var temp = m
			m = index;
			index = temp;
726 727 728

		}

M
Mr.doob 已提交
729
		return this.fromArray( m.elements, index * 4 );
W
WestLangley 已提交
730 731 732

	},

M
Mr.doob 已提交
733
	equals: function ( v ) {
734 735 736

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

737 738
	},

739
	fromArray: function ( array, offset ) {
740

741 742 743 744 745
		if ( offset === undefined ) offset = 0;

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

M
Mr.doob 已提交
747 748
		return this;

749 750
	},

751
	toArray: function ( array, offset ) {
752

A
arose 已提交
753 754
		if ( array === undefined ) array = [];
		if ( offset === undefined ) offset = 0;
755

A
arose 已提交
756 757 758
		array[ offset ] = this.x;
		array[ offset + 1 ] = this.y;
		array[ offset + 2 ] = this.z;
759

A
arose 已提交
760
		return array;
761

762 763
	},

764
	fromAttribute: function ( attribute, index ) {
W
WestLangley 已提交
765

766 767 768
		this.x = attribute.getX( index );
		this.y = attribute.getY( index );
		this.z = attribute.getZ( index );
W
WestLangley 已提交
769

G
gero3 已提交
770
		return this;
W
WestLangley 已提交
771

772
	}
773

774
};
R
Rich Harris 已提交
775 776


777
export { Vector3 };