Vector3.js 9.5 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
	divideSelf: function ( v ) {
174

175 176 177 178 179
		this.x /= v.x;
		this.y /= v.y;
		this.z /= v.z;

		return this;
M
Mr.doob 已提交
180

M
Mr.doob 已提交
181
	},
182

183
	divideScalar: function ( s ) {
184

B
Ben Houston 已提交
185
		if ( s !== 0 ) {
186

M
Mr.doob 已提交
187 188 189
			this.x /= s;
			this.y /= s;
			this.z /= s;
M
Mr.doob 已提交
190

M
Mr.doob 已提交
191
		} else {
M
Mr.doob 已提交
192

193 194 195
			this.x = 0;
			this.y = 0;
			this.z = 0;
196

M
Mr.doob 已提交
197
		}
198

B
Ben Nolan 已提交
199 200
		return this;

201
	},
202

203 204
	minSelf: function ( v ) {

A
alteredq 已提交
205 206
		if ( this.x > v.x ) {

207
			this.x = v.x;
A
alteredq 已提交
208

209
		}
A
alteredq 已提交
210 211 212

		if ( this.y > v.y ) {

213
			this.y = v.y;
A
alteredq 已提交
214

215
		}
A
alteredq 已提交
216 217 218

		if ( this.z > v.z ) {

219
			this.z = v.z;
A
alteredq 已提交
220

221
		}
222 223 224 225 226 227 228

		return this;

	},

	maxSelf: function ( v ) {

A
alteredq 已提交
229 230
		if ( this.x < v.x ) {

231
			this.x = v.x;
A
alteredq 已提交
232

233
		}
A
alteredq 已提交
234 235 236

		if ( this.y < v.y ) {

237
			this.y = v.y;
A
alteredq 已提交
238

239
		}
A
alteredq 已提交
240 241 242

		if ( this.z < v.z ) {

243
			this.z = v.z;
A
alteredq 已提交
244

245
		}
246 247 248 249

		return this;

	},
M
Mr.doob 已提交
250

251 252 253 254
	clampSelf: function ( min, max ) {

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

A
alteredq 已提交
255 256
		if ( this.x < min.x ) {

257
			this.x = min.x;
A
alteredq 已提交
258 259 260

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

261
			this.x = max.x;
A
alteredq 已提交
262

263 264
		}

A
alteredq 已提交
265 266
		if ( this.y < min.y ) {

267
			this.y = min.y;
A
alteredq 已提交
268 269 270

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

271
			this.y = max.y;
A
alteredq 已提交
272

273 274
		}

A
alteredq 已提交
275 276
		if ( this.z < min.z ) {

277
			this.z = min.z;
A
alteredq 已提交
278 279 280

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

281
			this.z = max.z;
A
alteredq 已提交
282

283 284 285
		}

		return this;
A
alteredq 已提交
286

287 288
	},

289
	negate: function() {
M
Mr.doob 已提交
290

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

293
	},
294

295
	dot: function ( v ) {
M
Mr.doob 已提交
296

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

M
Mr.doob 已提交
299
	},
M
Mr.doob 已提交
300

301
	lengthSq: function () {
M
Mr.doob 已提交
302

M
Mr.doob 已提交
303
		return this.x * this.x + this.y * this.y + this.z * this.z;
M
Mr.doob 已提交
304 305 306

	},

307
	length: function () {
M
Mr.doob 已提交
308

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

M
Mr.doob 已提交
311
	},
312

313
	lengthManhattan: function () {
314

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

317 318
	},

319
	normalize: function () {
320

M
Mr.doob 已提交
321
		return this.divideScalar( this.length() );
322

323
	},
324

325
	setLength: function ( l ) {
326

327
		var oldLength = this.length();
M
Mr.doob 已提交
328

B
Ben Houston 已提交
329
		if ( oldLength !== 0 && l !== oldLength  ) {
330 331 332 333 334

			this.multiplyScalar( l / oldLength );
		}

		return this;
335

336
	},
337

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

	},
347

348
	cross: function ( a, b ) {
349

M
Mr.doob 已提交
350 351 352
		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;
353

M
Mr.doob 已提交
354
		return this;
355

356
	},
357

358
	crossSelf: function ( v ) {
M
Mr.doob 已提交
359

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

362 363 364
		this.x = y * v.z - z * v.y;
		this.y = z * v.x - x * v.z;
		this.z = x * v.y - y * v.x;
365

366
		return this;
367 368 369

	},

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

W
Wilt 已提交
372
		return Math.acos( this.dot( v ) / this.length() / v.length() );
M
Mr.doob 已提交
373 374

	},
W
Wilt 已提交
375

376
	distanceTo: function ( v ) {
377

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

M
Mr.doob 已提交
380 381
	},

382
	distanceToSquared: function ( v ) {
M
Mr.doob 已提交
383

M
Mr.doob 已提交
384 385 386 387
		var dx = this.x - v.x;
		var dy = this.y - v.y;
		var dz = this.z - v.z;

388
		return dx * dx + dy * dy + dz * dz;
M
Mr.doob 已提交
389

390
	},
M
Mr.doob 已提交
391

M
Mr.doob 已提交
392
	getPositionFromMatrix: function ( m ) {
M
Mr.doob 已提交
393

394 395 396
		this.x = m.elements[12];
		this.y = m.elements[13];
		this.z = m.elements[14];
397

398 399
		return this;

400 401
	},

W
WestLangley 已提交
402 403 404
	setEulerFromRotationMatrix: function ( m, order ) {

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

W
WestLangley 已提交
406
		// clamp, to handle numerical problems
M
Mr.doob 已提交
407 408 409 410 411 412

		function clamp( x ) {

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

		}
413 414 415 416 417 418 419 420 421

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

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

425 426
				this.x = Math.atan2( - m23, m33 );
				this.z = Math.atan2( - m12, m11 );
M
Mr.doob 已提交
427

428
			} else {
M
Mr.doob 已提交
429

430
				this.x = Math.atan2( m32, m22 );
431
				this.z = 0;
M
Mr.doob 已提交
432

433 434 435
			}

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

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

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

441 442
				this.y = Math.atan2( m13, m33 );
				this.z = Math.atan2( m21, m22 );
M
Mr.doob 已提交
443

444
			} else {
M
Mr.doob 已提交
445

446 447
				this.y = Math.atan2( - m31, m11 );
				this.z = 0;
M
Mr.doob 已提交
448

449
			}
M
Mr.doob 已提交
450

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

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

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

457 458
				this.y = Math.atan2( - m31, m33 );
				this.z = Math.atan2( - m12, m22 );
M
Mr.doob 已提交
459

460
			} else {
M
Mr.doob 已提交
461

462
				this.y = 0;
463
				this.z = Math.atan2( m21, m11 );
M
Mr.doob 已提交
464

465 466 467
			}

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

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

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

473 474
				this.x = Math.atan2( m32, m33 );
				this.z = Math.atan2( m21, m11 );
M
Mr.doob 已提交
475

476
			} else {
M
Mr.doob 已提交
477

478 479
				this.x = 0;
				this.z = Math.atan2( - m12, m22 );
M
Mr.doob 已提交
480

481
			}
M
Mr.doob 已提交
482

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

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

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

489 490
				this.x = Math.atan2( - m23, m22 );
				this.y = Math.atan2( - m31, m11 );
M
Mr.doob 已提交
491

492
			} else {
M
Mr.doob 已提交
493

494
				this.x = 0;
495
				this.y = Math.atan2( m13, m33 );
M
Mr.doob 已提交
496

497
			}
M
Mr.doob 已提交
498

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

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

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

505 506
				this.x = Math.atan2( m32, m22 );
				this.y = Math.atan2( m13, m11 );
M
Mr.doob 已提交
507

508
			} else {
M
Mr.doob 已提交
509

510
				this.x = Math.atan2( - m23, m33 );
511
				this.y = 0;
M
Mr.doob 已提交
512

513
			}
M
Mr.doob 已提交
514

515
		}
M
Mr.doob 已提交
516

517 518 519 520
		return this;

	},

W
WestLangley 已提交
521 522 523
	setEulerFromQuaternion: function ( q, order ) {

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

W
WestLangley 已提交
525
		// clamp, to handle numerical problems
M
Mr.doob 已提交
526 527 528 529 530 531 532 533

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

M
Mr.doob 已提交
535 536 537 538
		var sqx = q.x * q.x;
		var sqy = q.y * q.y;
		var sqz = q.z * q.z;
		var sqw = q.w * q.w;
539 540 541 542 543 544

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

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

548 549 550
			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 已提交
551

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

554 555 556
			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 已提交
557

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

560 561 562
			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 已提交
563

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

566 567 568
			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 已提交
569

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

572 573 574
			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 已提交
575

A
alteredq 已提交
576
		}
M
Mr.doob 已提交
577

W
WestLangley 已提交
578
		return this;
A
alteredq 已提交
579 580

	},
581

M
Mr.doob 已提交
582 583
	getScaleFromMatrix: function ( m ) {

584 585 586
		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 已提交
587

588 589 590
		this.x = sx;
		this.y = sy;
		this.z = sz;
M
Mr.doob 已提交
591

592
		return this;
M
Mr.doob 已提交
593 594 595
	},

	equals: function ( v ) {
596 597 598

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

599 600
	},

M
Mr.doob 已提交
601 602 603 604
	clone: function () {

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

605
	}
606

M
Mr.doob 已提交
607
};