Vector3.js 10.6 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

M
Mr.doob 已提交
93
	add: function ( a, b ) {
M
Mr.doob 已提交
94

M
Mr.doob 已提交
95 96 97
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
M
Mr.doob 已提交
98

99
		return this;
100

101
	},
102

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

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

B
Ben Nolan 已提交
109 110
		return this;

111
	},
112

113
	addScalar: function ( s ) {
M
Mr.doob 已提交
114

M
Mr.doob 已提交
115 116 117
		this.x += s;
		this.y += s;
		this.z += s;
118

B
Ben Nolan 已提交
119 120
		return this;

121
	},
122

M
Mr.doob 已提交
123
	sub: function ( a, b ) {
124

M
Mr.doob 已提交
125 126 127
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
128

129
		return this;
M
Mr.doob 已提交
130

131
	},
132

133
	subSelf: function ( v ) {
M
Mr.doob 已提交
134

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

B
Ben Nolan 已提交
139 140
		return this;

141
	},
142

143
	multiply: function ( a, b ) {
144

M
Mr.doob 已提交
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

153
	multiplySelf: function ( v ) {
M
Mr.doob 已提交
154

M
Mr.doob 已提交
155 156
		this.x *= v.x;
		this.y *= v.y;
N
Nico Kruithof 已提交
157
		this.z *= v.z;
M
Mr.doob 已提交
158 159 160 161 162

		return this;

	},

163
	multiplyScalar: function ( s ) {
M
Mr.doob 已提交
164

M
Mr.doob 已提交
165 166 167
		this.x *= s;
		this.y *= s;
		this.z *= s;
168

B
Ben Nolan 已提交
169 170
		return this;

171
	},
172

173
	applyMatrix3: function ( m ) {
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

		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;

	},

189
	applyMatrix4: function ( m ) {
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

		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;

	},

206
	applyQuaternion: function ( q ) {
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233

		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;

	},

234
	divideSelf: function ( v ) {
235

236 237 238 239 240
		this.x /= v.x;
		this.y /= v.y;
		this.z /= v.z;

		return this;
M
Mr.doob 已提交
241

M
Mr.doob 已提交
242
	},
243

244
	divideScalar: function ( s ) {
245

B
Ben Houston 已提交
246
		if ( s !== 0 ) {
247

M
Mr.doob 已提交
248 249 250
			this.x /= s;
			this.y /= s;
			this.z /= s;
M
Mr.doob 已提交
251

M
Mr.doob 已提交
252
		} else {
M
Mr.doob 已提交
253

254 255 256
			this.x = 0;
			this.y = 0;
			this.z = 0;
257

M
Mr.doob 已提交
258
		}
259

B
Ben Nolan 已提交
260 261
		return this;

262
	},
263

264 265
	minSelf: function ( v ) {

A
alteredq 已提交
266 267
		if ( this.x > v.x ) {

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

270
		}
A
alteredq 已提交
271 272 273

		if ( this.y > v.y ) {

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

276
		}
A
alteredq 已提交
277 278 279

		if ( this.z > v.z ) {

280
			this.z = v.z;
A
alteredq 已提交
281

282
		}
283 284 285 286 287 288 289

		return this;

	},

	maxSelf: function ( v ) {

A
alteredq 已提交
290 291
		if ( this.x < v.x ) {

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

294
		}
A
alteredq 已提交
295 296 297

		if ( this.y < v.y ) {

298
			this.y = v.y;
A
alteredq 已提交
299

300
		}
A
alteredq 已提交
301 302 303

		if ( this.z < v.z ) {

304
			this.z = v.z;
A
alteredq 已提交
305

306
		}
307 308 309 310

		return this;

	},
M
Mr.doob 已提交
311

312 313 314 315
	clampSelf: function ( min, max ) {

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

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

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

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

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

324 325
		}

A
alteredq 已提交
326 327
		if ( this.y < min.y ) {

328
			this.y = min.y;
A
alteredq 已提交
329 330 331

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

332
			this.y = max.y;
A
alteredq 已提交
333

334 335
		}

A
alteredq 已提交
336 337
		if ( this.z < min.z ) {

338
			this.z = min.z;
A
alteredq 已提交
339 340 341

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

342
			this.z = max.z;
A
alteredq 已提交
343

344 345 346
		}

		return this;
A
alteredq 已提交
347

348 349
	},

350
	negate: function() {
M
Mr.doob 已提交
351

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

354
	},
355

356
	dot: function ( v ) {
M
Mr.doob 已提交
357

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

M
Mr.doob 已提交
360
	},
M
Mr.doob 已提交
361

362
	lengthSq: function () {
M
Mr.doob 已提交
363

M
Mr.doob 已提交
364
		return this.x * this.x + this.y * this.y + this.z * this.z;
M
Mr.doob 已提交
365 366 367

	},

368
	length: function () {
M
Mr.doob 已提交
369

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

M
Mr.doob 已提交
372
	},
373

374
	lengthManhattan: function () {
375

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

378 379
	},

380
	normalize: function () {
381

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

384
	},
385

386
	setLength: function ( l ) {
387

388
		var oldLength = this.length();
M
Mr.doob 已提交
389

B
Ben Houston 已提交
390
		if ( oldLength !== 0 && l !== oldLength  ) {
391 392 393 394 395

			this.multiplyScalar( l / oldLength );
		}

		return this;
396

397
	},
398

399 400 401 402 403 404 405 406 407
	lerpSelf: function ( v, alpha ) {

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

		return this;

	},
408

409
	cross: function ( a, b ) {
410

M
Mr.doob 已提交
411 412 413
		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;
414

M
Mr.doob 已提交
415
		return this;
416

417
	},
418

419
	crossSelf: function ( v ) {
M
Mr.doob 已提交
420

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

423 424 425
		this.x = y * v.z - z * v.y;
		this.y = z * v.x - x * v.z;
		this.z = x * v.y - y * v.x;
426

427
		return this;
428 429 430

	},

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

W
Wilt 已提交
433
		return Math.acos( this.dot( v ) / this.length() / v.length() );
M
Mr.doob 已提交
434 435

	},
W
Wilt 已提交
436

437
	distanceTo: function ( v ) {
438

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

M
Mr.doob 已提交
441 442
	},

443
	distanceToSquared: function ( v ) {
M
Mr.doob 已提交
444

M
Mr.doob 已提交
445 446 447 448
		var dx = this.x - v.x;
		var dy = this.y - v.y;
		var dz = this.z - v.z;

449
		return dx * dx + dy * dy + dz * dz;
M
Mr.doob 已提交
450

451
	},
M
Mr.doob 已提交
452

M
Mr.doob 已提交
453
	getPositionFromMatrix: function ( m ) {
M
Mr.doob 已提交
454

455 456 457
		this.x = m.elements[12];
		this.y = m.elements[13];
		this.z = m.elements[14];
458

459 460
		return this;

461 462
	},

W
WestLangley 已提交
463 464 465
	setEulerFromRotationMatrix: function ( m, order ) {

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

W
WestLangley 已提交
467
		// clamp, to handle numerical problems
M
Mr.doob 已提交
468 469 470 471 472 473

		function clamp( x ) {

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

		}
474 475 476 477 478 479 480 481 482

		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 已提交
483

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

486 487
				this.x = Math.atan2( - m23, m33 );
				this.z = Math.atan2( - m12, m11 );
M
Mr.doob 已提交
488

489
			} else {
M
Mr.doob 已提交
490

491
				this.x = Math.atan2( m32, m22 );
492
				this.z = 0;
M
Mr.doob 已提交
493

494 495 496
			}

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

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

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

502 503
				this.y = Math.atan2( m13, m33 );
				this.z = Math.atan2( m21, m22 );
M
Mr.doob 已提交
504

505
			} else {
M
Mr.doob 已提交
506

507 508
				this.y = Math.atan2( - m31, m11 );
				this.z = 0;
M
Mr.doob 已提交
509

510
			}
M
Mr.doob 已提交
511

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

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

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

518 519
				this.y = Math.atan2( - m31, m33 );
				this.z = Math.atan2( - m12, m22 );
M
Mr.doob 已提交
520

521
			} else {
M
Mr.doob 已提交
522

523
				this.y = 0;
524
				this.z = Math.atan2( m21, m11 );
M
Mr.doob 已提交
525

526 527 528
			}

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

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

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

534 535
				this.x = Math.atan2( m32, m33 );
				this.z = Math.atan2( m21, m11 );
M
Mr.doob 已提交
536

537
			} else {
M
Mr.doob 已提交
538

539 540
				this.x = 0;
				this.z = Math.atan2( - m12, m22 );
M
Mr.doob 已提交
541

542
			}
M
Mr.doob 已提交
543

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

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

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

550 551
				this.x = Math.atan2( - m23, m22 );
				this.y = Math.atan2( - m31, m11 );
M
Mr.doob 已提交
552

553
			} else {
M
Mr.doob 已提交
554

555
				this.x = 0;
556
				this.y = Math.atan2( m13, m33 );
M
Mr.doob 已提交
557

558
			}
M
Mr.doob 已提交
559

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

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

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

566 567
				this.x = Math.atan2( m32, m22 );
				this.y = Math.atan2( m13, m11 );
M
Mr.doob 已提交
568

569
			} else {
M
Mr.doob 已提交
570

571
				this.x = Math.atan2( - m23, m33 );
572
				this.y = 0;
M
Mr.doob 已提交
573

574
			}
M
Mr.doob 已提交
575

576
		}
M
Mr.doob 已提交
577

578 579 580 581
		return this;

	},

W
WestLangley 已提交
582 583 584
	setEulerFromQuaternion: function ( q, order ) {

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

W
WestLangley 已提交
586
		// clamp, to handle numerical problems
M
Mr.doob 已提交
587 588 589 590 591 592 593 594

		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 已提交
595

M
Mr.doob 已提交
596 597 598 599
		var sqx = q.x * q.x;
		var sqy = q.y * q.y;
		var sqz = q.z * q.z;
		var sqw = q.w * q.w;
600 601 602 603 604 605

		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 已提交
606

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

609 610 611
			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 已提交
612

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

615 616 617
			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 已提交
618

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

621 622 623
			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 已提交
624

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

627 628 629
			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 已提交
630

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

633 634 635
			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 已提交
636

A
alteredq 已提交
637
		}
M
Mr.doob 已提交
638

W
WestLangley 已提交
639
		return this;
A
alteredq 已提交
640 641

	},
642

M
Mr.doob 已提交
643 644
	getScaleFromMatrix: function ( m ) {

645 646 647
		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 已提交
648

649 650 651
		this.x = sx;
		this.y = sy;
		this.z = sz;
M
Mr.doob 已提交
652

653
		return this;
M
Mr.doob 已提交
654 655 656
	},

	equals: function ( v ) {
657 658 659

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

660 661
	},

M
Mr.doob 已提交
662 663 664 665
	clone: function () {

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

666
	}
667

M
Mr.doob 已提交
668
};