Vector4.js 7.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

};

THREE.Vector4.prototype = {

20 21 22
	constructor: THREE.Vector4,

	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;

	},

65
	copy: function ( v ) {
M
Mr.doob 已提交
66

67 68 69
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
70
		this.w = ( v.w !== undefined ) ? v.w : 1;
71

72 73
		return this;

74
	},
75

76 77 78 79 80 81 82 83 84 85 86
	addScalar: function ( s ) {

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

		return this;

	},

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

M
Mr.doob 已提交
89 90 91 92
		this.x = a.x + b.x;
		this.y = a.y + b.y;
		this.z = a.z + b.z;
		this.w = a.w + b.w;
93

94 95
		return this;

96
	},
97

98
	addSelf: function ( v ) {
M
Mr.doob 已提交
99

M
Mr.doob 已提交
100 101 102 103
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
		this.w += v.w;
104

M
Mr.doob 已提交
105
		return this;
M
Mr.doob 已提交
106

M
Mr.doob 已提交
107 108
	},

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

M
Mr.doob 已提交
111 112 113 114
		this.x = a.x - b.x;
		this.y = a.y - b.y;
		this.z = a.z - b.z;
		this.w = a.w - b.w;
115

B
Ben Nolan 已提交
116 117
		return this;

118
	},
119

120
	subSelf: function ( v ) {
M
Mr.doob 已提交
121 122 123 124 125

		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
		this.w -= v.w;
M
Mr.doob 已提交
126

M
Mr.doob 已提交
127
		return this;
128

M
Mr.doob 已提交
129
	},
M
Mr.doob 已提交
130

131
	multiplyScalar: function ( s ) {
M
Mr.doob 已提交
132 133 134 135 136

		this.x *= s;
		this.y *= s;
		this.z *= s;
		this.w *= s;
137

138 139
		return this;

140
	},
141

142
	divideScalar: function ( s ) {
M
Mr.doob 已提交
143

M
Mr.doob 已提交
144
		if ( s ) {
M
Mr.doob 已提交
145

M
Mr.doob 已提交
146 147 148 149
			this.x /= s;
			this.y /= s;
			this.z /= s;
			this.w /= s;
150

M
Mr.doob 已提交
151 152
		} else {

153 154 155 156
			this.x = 0;
			this.y = 0;
			this.z = 0;
			this.w = 1;
M
Mr.doob 已提交
157 158

		}
159

B
Ben Nolan 已提交
160 161
		return this;

162
	},
M
Mr.doob 已提交
163

164 165
	minSelf: function ( v ) {

A
alteredq 已提交
166 167
		if ( this.x > v.x ) {

168
			this.x = v.x;
A
alteredq 已提交
169

170
		}
A
alteredq 已提交
171 172 173

		if ( this.y > v.y ) {

174
			this.y = v.y;
A
alteredq 已提交
175

176
		}
A
alteredq 已提交
177 178 179

		if ( this.z > v.z ) {

180
			this.z = v.z;
A
alteredq 已提交
181

182
		}
A
alteredq 已提交
183 184 185

		if ( this.w > v.w ) {

186
			this.w = v.w;
A
alteredq 已提交
187

188 189 190 191 192 193 194 195
		}

		return this;

	},

	maxSelf: function ( v ) {

A
alteredq 已提交
196 197
		if ( this.x < v.x ) {

198
			this.x = v.x;
A
alteredq 已提交
199

200
		}
A
alteredq 已提交
201 202 203

		if ( this.y < v.y ) {

204
			this.y = v.y;
A
alteredq 已提交
205

206
		}
A
alteredq 已提交
207 208 209

		if ( this.z < v.z ) {

210
			this.z = v.z;
A
alteredq 已提交
211

212
		}
A
alteredq 已提交
213 214 215

		if ( this.w < v.w ) {

216
			this.w = v.w;
A
alteredq 已提交
217

218 219 220 221 222 223 224 225 226 227
		}

		return this;

	},

	clampSelf: function ( min, max ) {

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

A
alteredq 已提交
228 229
		if ( this.x < min.x ) {

230
			this.x = min.x;
A
alteredq 已提交
231 232 233

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

234
			this.x = max.x;
A
alteredq 已提交
235

236 237
		}

A
alteredq 已提交
238 239
		if ( this.y < min.y ) {

240
			this.y = min.y;
A
alteredq 已提交
241 242 243

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

244
			this.y = max.y;
A
alteredq 已提交
245

246 247
		}

A
alteredq 已提交
248 249
		if ( this.z < min.z ) {

250
			this.z = min.z;
A
alteredq 已提交
251 252 253

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

254
			this.z = max.z;
A
alteredq 已提交
255

256 257
		}

A
alteredq 已提交
258 259
		if ( this.w < min.w ) {

260
			this.w = min.w;
A
alteredq 已提交
261 262 263

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

264
			this.w = max.w;
A
alteredq 已提交
265

266 267 268
		}

		return this;
A
alteredq 已提交
269

270
	},
M
Mr.doob 已提交
271

272
	negate: function() {
M
Mr.doob 已提交
273

M
Mr.doob 已提交
274
		return this.multiplyScalar( -1 );
M
Mr.doob 已提交
275

M
Mr.doob 已提交
276
	},
M
Mr.doob 已提交
277

278
	dot: function ( v ) {
M
Mr.doob 已提交
279 280

		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
M
Mr.doob 已提交
281 282 283

	},

284
	lengthSq: function () {
M
Mr.doob 已提交
285

M
Mr.doob 已提交
286
		return this.dot( this );
M
Mr.doob 已提交
287

M
Mr.doob 已提交
288
	},
M
Mr.doob 已提交
289

290
	length: function () {
M
Mr.doob 已提交
291

M
Mr.doob 已提交
292
		return Math.sqrt( this.lengthSq() );
M
Mr.doob 已提交
293 294

	},
M
Mr.doob 已提交
295

296 297 298 299 300
	lengthManhattan: function () {

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

	},
M
Mr.doob 已提交
301

302
	normalize: function () {
M
Mr.doob 已提交
303 304

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

M
Mr.doob 已提交
306
	},
M
Mr.doob 已提交
307

308
	setLength: function ( l ) {
M
Mr.doob 已提交
309

M
Mr.doob 已提交
310
		return this.normalize().multiplyScalar( l );
311

M
Mr.doob 已提交
312
	},
313

314
	lerpSelf: function ( v, alpha ) {
M
Mr.doob 已提交
315

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

M
Mr.doob 已提交
321 322
		return this;

M
Mr.doob 已提交
323 324
	},

325 326 327 328 329 330
	equals: function ( v ) {

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

	},

M
Mr.doob 已提交
331 332 333 334
	clone: function () {

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

W
WestLangley 已提交
335 336 337 338 339
	},

	setAxisAngleFromQuaternion: function ( q ) {

		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
M
Mr.doob 已提交
340

W
WestLangley 已提交
341
		// q is assumed to be normalized
M
Mr.doob 已提交
342

W
WestLangley 已提交
343
		this.w = 2 * Math.acos( q.w );
M
Mr.doob 已提交
344

W
WestLangley 已提交
345
		var s = Math.sqrt( 1 - q.w * q.w );
M
Mr.doob 已提交
346

W
WestLangley 已提交
347
		if ( s < 0.0001 ) {
M
Mr.doob 已提交
348

W
WestLangley 已提交
349 350 351
			 this.x = 1;
			 this.y = 0;
			 this.z = 0;
M
Mr.doob 已提交
352

W
WestLangley 已提交
353
		} else {
M
Mr.doob 已提交
354

W
WestLangley 已提交
355 356 357
			 this.x = q.x / s;
			 this.y = q.y / s;
			 this.z = q.z / s;
M
Mr.doob 已提交
358

W
WestLangley 已提交
359
		}
M
Mr.doob 已提交
360

W
WestLangley 已提交
361 362 363 364 365 366 367
		return this;

	},

	setAxisAngleFromRotationMatrix: function ( m ) {

		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
M
Mr.doob 已提交
368

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

W
WestLangley 已提交
371 372 373
		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
M
Mr.doob 已提交
374

W
WestLangley 已提交
375
			te = m.elements,
M
Mr.doob 已提交
376

W
WestLangley 已提交
377 378 379 380 381 382 383
			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];

		if ( ( Math.abs( m12 - m21 ) < epsilon )
		  && ( Math.abs( m13 - m31 ) < epsilon )
		  && ( Math.abs( m23 - m32 ) < epsilon ) ) {
M
Mr.doob 已提交
384

W
WestLangley 已提交
385 386 387
			// singularity found
			// first check for identity matrix which must have +1 for all terms
			// in leading diagonal and zero in other terms
M
Mr.doob 已提交
388

W
WestLangley 已提交
389 390 391 392
			if ( ( Math.abs( m12 + m21 ) < epsilon2 )
			  && ( Math.abs( m13 + m31 ) < epsilon2 )
			  && ( Math.abs( m23 + m32 ) < epsilon2 )
			  && ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
M
Mr.doob 已提交
393

W
WestLangley 已提交
394
				// this singularity is identity matrix so angle = 0
M
Mr.doob 已提交
395

W
WestLangley 已提交
396
				this.set( 1, 0, 0, 0 );
M
Mr.doob 已提交
397

W
WestLangley 已提交
398
				return this; // zero angle, arbitrary axis
M
Mr.doob 已提交
399

W
WestLangley 已提交
400
			}
M
Mr.doob 已提交
401

W
WestLangley 已提交
402
			// otherwise this singularity is angle = 180
M
Mr.doob 已提交
403

W
WestLangley 已提交
404
			angle = Math.PI;
M
Mr.doob 已提交
405

W
WestLangley 已提交
406 407 408 409 410 411
			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;
M
Mr.doob 已提交
412

W
WestLangley 已提交
413
			if ( ( xx > yy ) && ( xx > zz ) ) { // m11 is the largest diagonal term
M
Mr.doob 已提交
414

W
WestLangley 已提交
415
				if ( xx < epsilon ) {
M
Mr.doob 已提交
416

W
WestLangley 已提交
417 418 419
					x = 0;
					y = 0.707106781;
					z = 0.707106781;
M
Mr.doob 已提交
420

W
WestLangley 已提交
421
				} else {
M
Mr.doob 已提交
422

W
WestLangley 已提交
423 424 425
					x = Math.sqrt( xx );
					y = xy / x;
					z = xz / x;
M
Mr.doob 已提交
426

W
WestLangley 已提交
427
				}
M
Mr.doob 已提交
428

W
WestLangley 已提交
429
			} else if ( yy > zz ) { // m22 is the largest diagonal term
M
Mr.doob 已提交
430

W
WestLangley 已提交
431
				if ( yy < epsilon ) {
M
Mr.doob 已提交
432

W
WestLangley 已提交
433 434 435
					x = 0.707106781;
					y = 0;
					z = 0.707106781;
M
Mr.doob 已提交
436

W
WestLangley 已提交
437
				} else {
M
Mr.doob 已提交
438

W
WestLangley 已提交
439 440 441
					y = Math.sqrt( yy );
					x = xy / y;
					z = yz / y;
M
Mr.doob 已提交
442 443 444

				}

W
WestLangley 已提交
445
			} else { // m33 is the largest diagonal term so base result on this
M
Mr.doob 已提交
446

W
WestLangley 已提交
447
				if ( zz < epsilon ) {
M
Mr.doob 已提交
448

W
WestLangley 已提交
449 450 451
					x = 0.707106781;
					y = 0.707106781;
					z = 0;
M
Mr.doob 已提交
452

W
WestLangley 已提交
453
				} else {
M
Mr.doob 已提交
454

W
WestLangley 已提交
455 456 457
					z = Math.sqrt( zz );
					x = xz / z;
					y = yz / z;
M
Mr.doob 已提交
458

W
WestLangley 已提交
459
				}
M
Mr.doob 已提交
460

W
WestLangley 已提交
461
			}
M
Mr.doob 已提交
462

W
WestLangley 已提交
463
			this.set( x, y, z, angle );
M
Mr.doob 已提交
464

W
WestLangley 已提交
465
			return this; // return 180 deg rotation
M
Mr.doob 已提交
466

W
WestLangley 已提交
467
		}
M
Mr.doob 已提交
468

W
WestLangley 已提交
469
		// as we have reached here there are no singularities so we can handle normally
M
Mr.doob 已提交
470

W
WestLangley 已提交
471 472 473
		var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
						 + ( m13 - m31 ) * ( m13 - m31 )
						 + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
M
Mr.doob 已提交
474

A
alteredq 已提交
475
		if ( Math.abs( s ) < 0.001 ) s = 1;
M
Mr.doob 已提交
476

W
WestLangley 已提交
477 478
		// 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
M
Mr.doob 已提交
479

W
WestLangley 已提交
480 481 482 483
		this.x = ( m32 - m23 ) / s;
		this.y = ( m13 - m31 ) / s;
		this.z = ( m21 - m12 ) / s;
		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
M
Mr.doob 已提交
484

W
WestLangley 已提交
485 486
		return this;

487
	}
488 489

};