Vector4.js 11.1 KB
Newer Older
1 2
/**
 * @author supereggbert / http://www.paulbrunt.co.uk/
M
Mr.doob 已提交
3
 * @author philogb / http://blog.thejit.org/
4
 * @author mikael emtinger / http://gomo.se/
M
Mr.doob 已提交
5
 * @author egraether / http://egraether.com/
W
WestLangley 已提交
6
 * @author WestLangley / http://github.com/WestLangley
7 8 9 10
 */

THREE.Vector4 = function ( x, y, z, w ) {

11 12 13
	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;
14
	this.w = ( w !== undefined ) ? w : 1;
15 16 17

};

18 19 20
THREE.Vector4.prototype = {

	constructor: THREE.Vector4,
21

22
	set: function ( x, y, z, w ) {
23

24 25 26 27
		this.x = x;
		this.y = y;
		this.z = z;
		this.w = w;
28

29
		return this;
30

31
	},
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
	setX: function ( x ) {

		this.x = x;

		return this;

	},

	setY: function ( y ) {

		this.y = y;

		return this;

	},

	setZ: function ( z ) {

		this.z = z;

		return this;

	},

	setW: function ( w ) {

		this.w = w;

		return this;

	},

M
Mr.doob 已提交
65
	setComponent: function ( index, value ) {
B
Ben Houston 已提交
66

M
Mr.doob 已提交
67
		switch ( index ) {
B
Ben Houston 已提交
68

M
Mr.doob 已提交
69 70 71 72
			case 0: this.x = value; break;
			case 1: this.y = value; break;
			case 2: this.z = value; break;
			case 3: this.w = value; break;
73
			default: throw new Error( 'index is out of range: ' + index );
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 86
			case 0: return this.x;
			case 1: return this.y;
			case 2: return this.z;
			case 3: return this.w;
87
			default: throw new Error( 'index is out of range: ' + index );
88

M
Mr.doob 已提交
89
		}
90

M
Mr.doob 已提交
91
	},
92

93
	copy: function ( v ) {
M
Mr.doob 已提交
94

95 96 97
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
98
		this.w = ( v.w !== undefined ) ? v.w : 1;
99

100 101
		return this;

102
	},
103

104 105 106 107
	add: function ( v, w ) {

		if ( w !== undefined ) {

108
			console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
109 110 111
			return this.addVectors( v, w );

		}
112 113 114 115 116 117 118 119 120 121

		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
		this.w += v.w;

		return this;

	},

122 123 124 125 126 127 128 129 130 131 132
	addScalar: function ( s ) {

		this.x += s;
		this.y += s;
		this.z += s;
		this.w += s;

		return this;

	},

133
	addVectors: function ( a, b ) {
M
Mr.doob 已提交
134

M
Mr.doob 已提交
135 136 137 138
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
		this.w = a.w + b.w;
139

140 141
		return this;

142
	},
143

G
gero3 已提交
144 145 146 147 148 149 150 151 152 153
	addScaledVector: function ( v, s ) {

        this.x += v.x * s;
        this.y += v.y * s;
        this.z += v.z * s;
        this.w += v.w * s;

        return this;

    },
154

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

		if ( w !== undefined ) {

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

		}
M
Mr.doob 已提交
163

164 165 166 167
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
		this.w -= v.w;
168

M
Mr.doob 已提交
169
		return this;
M
Mr.doob 已提交
170

M
Mr.doob 已提交
171 172
	},

173 174 175 176 177 178 179 180 181 182 183
	subScalar: function ( s ) {

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

		return this;

	},

184
	subVectors: function ( a, b ) {
M
Mr.doob 已提交
185

M
Mr.doob 已提交
186 187 188 189
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
		this.w = a.w - b.w;
190

B
Ben Nolan 已提交
191 192
		return this;

193
	},
194

195
	multiplyScalar: function ( scalar ) {
M
Mr.doob 已提交
196

197 198 199 200
		this.x *= scalar;
		this.y *= scalar;
		this.z *= scalar;
		this.w *= scalar;
201

202 203
		return this;

204
	},
205

206
	applyMatrix4: function ( m ) {
207 208 209 210 211 212 213 214

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

		var e = m.elements;

215 216 217 218
		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
219 220 221 222 223

		return this;

	},

224
	divideScalar: function ( scalar ) {
M
Mr.doob 已提交
225

226
		if ( scalar !== 0 ) {
M
Mr.doob 已提交
227

228 229 230 231 232 233
			var invScalar = 1 / scalar;

			this.x *= invScalar;
			this.y *= invScalar;
			this.z *= invScalar;
			this.w *= invScalar;
234

M
Mr.doob 已提交
235 236
		} else {

237 238 239 240
			this.x = 0;
			this.y = 0;
			this.z = 0;
			this.w = 1;
M
Mr.doob 已提交
241 242

		}
243

B
Ben Nolan 已提交
244 245
		return this;

246
	},
M
Mr.doob 已提交
247

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
	setAxisAngleFromQuaternion: function ( q ) {

		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm

		// q is assumed to be normalized

		this.w = 2 * Math.acos( q.w );

		var s = Math.sqrt( 1 - q.w * q.w );

		if ( s < 0.0001 ) {

			 this.x = 1;
			 this.y = 0;
			 this.z = 0;

		} else {

			 this.x = q.x / s;
			 this.y = q.y / s;
			 this.z = q.z / s;

		}

		return this;

	},

	setAxisAngleFromRotationMatrix: function ( m ) {

		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm

		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)

		var angle, x, y, z,		// variables for result
			epsilon = 0.01,		// margin to allow for rounding errors
			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees

			te = m.elements,

288 289 290
			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
291 292

		if ( ( Math.abs( m12 - m21 ) < epsilon )
293 294
		   && ( Math.abs( m13 - m31 ) < epsilon )
		   && ( Math.abs( m23 - m32 ) < epsilon ) ) {
295 296 297 298 299 300

			// singularity found
			// first check for identity matrix which must have +1 for all terms
			// in leading diagonal and zero in other terms

			if ( ( Math.abs( m12 + m21 ) < epsilon2 )
301 302 303
			   && ( Math.abs( m13 + m31 ) < epsilon2 )
			   && ( Math.abs( m23 + m32 ) < epsilon2 )
			   && ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

				// this singularity is identity matrix so angle = 0

				this.set( 1, 0, 0, 0 );

				return this; // zero angle, arbitrary axis

			}

			// otherwise this singularity is angle = 180

			angle = Math.PI;

			var xx = ( m11 + 1 ) / 2;
			var yy = ( m22 + 1 ) / 2;
			var zz = ( m33 + 1 ) / 2;
			var xy = ( m12 + m21 ) / 4;
			var xz = ( m13 + m31 ) / 4;
			var yz = ( m23 + m32 ) / 4;

			if ( ( xx > yy ) && ( xx > zz ) ) { // m11 is the largest diagonal term

				if ( xx < epsilon ) {

					x = 0;
					y = 0.707106781;
					z = 0.707106781;

				} else {

					x = Math.sqrt( xx );
					y = xy / x;
					z = xz / x;

				}

			} else if ( yy > zz ) { // m22 is the largest diagonal term

				if ( yy < epsilon ) {

					x = 0.707106781;
					y = 0;
					z = 0.707106781;

				} else {

					y = Math.sqrt( yy );
					x = xy / y;
					z = yz / y;

				}

			} else { // m33 is the largest diagonal term so base result on this

				if ( zz < epsilon ) {

					x = 0.707106781;
					y = 0.707106781;
					z = 0;

				} else {

					z = Math.sqrt( zz );
					x = xz / z;
					y = yz / z;

				}

			}

			this.set( x, y, z, angle );

			return this; // return 180 deg rotation

		}

		// as we have reached here there are no singularities so we can handle normally

		var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
383 384
						  + ( m13 - m31 ) * ( m13 - m31 )
						  + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399

		if ( Math.abs( s ) < 0.001 ) s = 1;

		// prevent divide by zero, should not happen if matrix is orthogonal and should be
		// caught by singularity test above, but I've left it in just in case

		this.x = ( m32 - m23 ) / s;
		this.y = ( m13 - m31 ) / s;
		this.z = ( m21 - m12 ) / s;
		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );

		return this;

	},

400
	min: function ( v ) {
401

A
alteredq 已提交
402 403
		if ( this.x > v.x ) {

404
			this.x = v.x;
A
alteredq 已提交
405

406
		}
A
alteredq 已提交
407 408 409

		if ( this.y > v.y ) {

410
			this.y = v.y;
A
alteredq 已提交
411

412
		}
A
alteredq 已提交
413 414 415

		if ( this.z > v.z ) {

416
			this.z = v.z;
A
alteredq 已提交
417

418
		}
A
alteredq 已提交
419 420 421

		if ( this.w > v.w ) {

422
			this.w = v.w;
A
alteredq 已提交
423

424 425 426 427 428 429
		}

		return this;

	},

430
	max: function ( v ) {
431

A
alteredq 已提交
432 433
		if ( this.x < v.x ) {

434
			this.x = v.x;
A
alteredq 已提交
435

436
		}
A
alteredq 已提交
437 438 439

		if ( this.y < v.y ) {

440
			this.y = v.y;
A
alteredq 已提交
441

442
		}
A
alteredq 已提交
443 444 445

		if ( this.z < v.z ) {

446
			this.z = v.z;
A
alteredq 已提交
447

448
		}
A
alteredq 已提交
449 450 451

		if ( this.w < v.w ) {

452
			this.w = v.w;
A
alteredq 已提交
453

454 455 456 457 458 459
		}

		return this;

	},

460
	clamp: function ( min, max ) {
461 462 463

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

A
alteredq 已提交
464 465
		if ( this.x < min.x ) {

466
			this.x = min.x;
A
alteredq 已提交
467 468 469

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

470
			this.x = max.x;
A
alteredq 已提交
471

472 473
		}

A
alteredq 已提交
474 475
		if ( this.y < min.y ) {

476
			this.y = min.y;
A
alteredq 已提交
477 478 479

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

480
			this.y = max.y;
A
alteredq 已提交
481

482 483
		}

A
alteredq 已提交
484 485
		if ( this.z < min.z ) {

486
			this.z = min.z;
A
alteredq 已提交
487 488 489

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

490
			this.z = max.z;
A
alteredq 已提交
491

492 493
		}

A
alteredq 已提交
494 495
		if ( this.w < min.w ) {

496
			this.w = min.w;
A
alteredq 已提交
497 498 499

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

500
			this.w = max.w;
A
alteredq 已提交
501

502 503 504
		}

		return this;
A
alteredq 已提交
505

506
	},
M
Mr.doob 已提交
507

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

510
		var min, max;
511

512
		return function clampScalar( minVal, maxVal ) {
M
Mr.doob 已提交
513 514 515

			if ( min === undefined ) {

516 517
				min = new THREE.Vector4();
				max = new THREE.Vector4();
M
Mr.doob 已提交
518

519 520
			}

M
Mr.doob 已提交
521 522 523 524
			min.set( minVal, minVal, minVal, minVal );
			max.set( maxVal, maxVal, maxVal, maxVal );

			return this.clamp( min, max );
525 526

		};
M
Mr.doob 已提交
527

528
	}(),
529

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

M
Mr.doob 已提交
532 533 534 535
		this.x = Math.floor( this.x );
		this.y = Math.floor( this.y );
		this.z = Math.floor( this.z );
		this.w = Math.floor( this.w );
M
Mr.doob 已提交
536

M
Mr.doob 已提交
537
		return this;
M
Mr.doob 已提交
538

M
Mr.doob 已提交
539
  },
540

M
Mr.doob 已提交
541
  ceil: function () {
M
Mr.doob 已提交
542

M
Mr.doob 已提交
543 544 545 546
		this.x = Math.ceil( this.x );
		this.y = Math.ceil( this.y );
		this.z = Math.ceil( this.z );
		this.w = Math.ceil( this.w );
M
Mr.doob 已提交
547

M
Mr.doob 已提交
548
		return this;
M
Mr.doob 已提交
549

M
Mr.doob 已提交
550
  },
551

M
Mr.doob 已提交
552
  round: function () {
M
Mr.doob 已提交
553

M
Mr.doob 已提交
554 555 556 557
		this.x = Math.round( this.x );
		this.y = Math.round( this.y );
		this.z = Math.round( this.z );
		this.w = Math.round( this.w );
M
Mr.doob 已提交
558

M
Mr.doob 已提交
559
		return this;
M
Mr.doob 已提交
560

M
Mr.doob 已提交
561
  },
562

M
Mr.doob 已提交
563
  roundToZero: function () {
M
Mr.doob 已提交
564

M
Mr.doob 已提交
565 566 567 568
		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 );
		this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
M
Mr.doob 已提交
569

M
Mr.doob 已提交
570
		return this;
M
Mr.doob 已提交
571

M
Mr.doob 已提交
572
  },
573

M
Mr.doob 已提交
574
	negate: function () {
M
Mr.doob 已提交
575

M
Mr.doob 已提交
576 577 578 579 580 581
		this.x = - this.x;
		this.y = - this.y;
		this.z = - this.z;
		this.w = - this.w;

		return this;
M
Mr.doob 已提交
582

M
Mr.doob 已提交
583
	},
M
Mr.doob 已提交
584

585
	dot: function ( v ) {
M
Mr.doob 已提交
586 587

		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
M
Mr.doob 已提交
588 589 590

	},

591
	lengthSq: function () {
M
Mr.doob 已提交
592

593
		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
M
Mr.doob 已提交
594

M
Mr.doob 已提交
595
	},
M
Mr.doob 已提交
596

597
	length: function () {
M
Mr.doob 已提交
598

599
		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
M
Mr.doob 已提交
600 601

	},
M
Mr.doob 已提交
602

603 604 605 606 607
	lengthManhattan: function () {

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

	},
M
Mr.doob 已提交
608

609
	normalize: function () {
M
Mr.doob 已提交
610 611

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

M
Mr.doob 已提交
613
	},
M
Mr.doob 已提交
614

615
	setLength: function ( l ) {
M
Mr.doob 已提交
616

617
		var oldLength = this.length();
M
Mr.doob 已提交
618 619

		if ( oldLength !== 0 && l !== oldLength ) {
620

621
			this.multiplyScalar( l / oldLength );
622

623 624 625
		}

		return this;
M
Mr.doob 已提交
626

M
Mr.doob 已提交
627
	},
628

629
	lerp: function ( v, alpha ) {
M
Mr.doob 已提交
630

631 632 633 634
		this.x += ( v.x - this.x ) * alpha;
		this.y += ( v.y - this.y ) * alpha;
		this.z += ( v.z - this.z ) * alpha;
		this.w += ( v.w - this.w ) * alpha;
635

M
Mr.doob 已提交
636 637
		return this;

M
Mr.doob 已提交
638 639
	},

W
WestLangley 已提交
640 641
	lerpVectors: function ( v1, v2, alpha ) {

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

G
gero3 已提交
644
		return this;
W
WestLangley 已提交
645 646 647

	},

648 649 650 651 652 653
	equals: function ( v ) {

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

	},

654
	fromArray: function ( array, offset ) {
655

656 657 658 659 660 661
		if ( offset === undefined ) offset = 0;

		this.x = array[ offset ];
		this.y = array[ offset + 1 ];
		this.z = array[ offset + 2 ];
		this.w = array[ offset + 3 ];
662

M
Mr.doob 已提交
663 664
		return this;

665
	},
666

A
arose 已提交
667
	toArray: function ( array, offset ) {
668

A
arose 已提交
669 670
		if ( array === undefined ) array = [];
		if ( offset === undefined ) offset = 0;
671

A
arose 已提交
672 673 674 675
		array[ offset ] = this.x;
		array[ offset + 1 ] = this.y;
		array[ offset + 2 ] = this.z;
		array[ offset + 3 ] = this.w;
676

A
arose 已提交
677
		return array;
678

679 680
	},

W
WestLangley 已提交
681 682
	fromAttribute: function ( attribute, index, offset ) {

G
gero3 已提交
683
		if ( offset === undefined ) offset = 0;
W
WestLangley 已提交
684

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

G
gero3 已提交
687 688 689 690
		this.x = attribute.array[ index ];
		this.y = attribute.array[ index + 1 ];
		this.z = attribute.array[ index + 2 ];
		this.w = attribute.array[ index + 3 ];
W
WestLangley 已提交
691

G
gero3 已提交
692
		return this;
W
WestLangley 已提交
693 694 695

	},

M
Mr.doob 已提交
696 697 698 699
	clone: function () {

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

700
	}
701

702
};