Geometry.js 10.2 KB
Newer Older
M
Mr.doob 已提交
1 2
/**
 * @author mr.doob / http://mrdoob.com/
M
Mr.doob 已提交
3
 * @author kile / http://kile.stravaganza.org/
M
Mr.doob 已提交
4
 * @author alteredq / http://alteredqualia.com/
5
 * @author mikael emtinger / http://gomo.se/
6
 * @author zz85 / http://www.lab4games.net/zz85/blog
M
Mr.doob 已提交
7 8
 */

M
Mr.doob 已提交
9
THREE.Geometry = function () {
10

11
	this.id = THREE.GeometryCount ++;
M
Mr.doob 已提交
12

M
Mr.doob 已提交
13
	this.vertices = [];
14
	this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon
15

16 17
	this.materials = [];

M
Mr.doob 已提交
18
	this.faces = [];
19

20 21
	this.faceUvs = [[]];
	this.faceVertexUvs = [[]];
22

23
	this.morphTargets = [];
M
Mr.doob 已提交
24
	this.morphColors = [];
M
Mr.doob 已提交
25

26 27
	this.skinWeights = [];
	this.skinIndices = [];
M
Mr.doob 已提交
28

29 30 31
	this.boundingBox = null;
	this.boundingSphere = null;

32
	this.hasTangents = false;
33

34 35
	this.dynamic = false; // unless set to true the *Arrays will be deleted once sent to a buffer.

M
Mr.doob 已提交
36 37 38 39
};

THREE.Geometry.prototype = {

40 41
	constructor : THREE.Geometry,

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
	applyMatrix: function ( matrix ) {

		var matrixRotation = new THREE.Matrix4();
		matrixRotation.extractRotation( matrix, new THREE.Vector3( 1, 1, 1 ) );

		for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {

			var vertex = this.vertices[ i ];

			matrix.multiplyVector3( vertex.position );

		}

		for ( var i = 0, il = this.faces.length; i < il; i ++ ) {

			var face = this.faces[ i ];

			matrixRotation.multiplyVector3( face.normal );

			for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {

				matrixRotation.multiplyVector3( face.vertexNormals[ j ] );

			}

			matrix.multiplyVector3( face.centroid );

		}

	},

M
Mr.doob 已提交
73 74 75 76
	computeCentroids: function () {

		var f, fl, face;

M
Mr.doob 已提交
77
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
78 79 80 81 82 83

			face = this.faces[ f ];
			face.centroid.set( 0, 0, 0 );

			if ( face instanceof THREE.Face3 ) {

M
Mr.doob 已提交
84 85 86
				face.centroid.addSelf( this.vertices[ face.a ].position );
				face.centroid.addSelf( this.vertices[ face.b ].position );
				face.centroid.addSelf( this.vertices[ face.c ].position );
M
Mr.doob 已提交
87 88 89 90
				face.centroid.divideScalar( 3 );

			} else if ( face instanceof THREE.Face4 ) {

M
Mr.doob 已提交
91 92 93
				face.centroid.addSelf( this.vertices[ face.a ].position );
				face.centroid.addSelf( this.vertices[ face.b ].position );
				face.centroid.addSelf( this.vertices[ face.c ].position );
M
Mr.doob 已提交
94 95 96 97 98 99 100 101 102
				face.centroid.addSelf( this.vertices[ face.d ].position );
				face.centroid.divideScalar( 4 );

			}

		}

	},

103
	computeFaceNormals: function () {
104

105 106
		var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
		cb = new THREE.Vector3(), ab = new THREE.Vector3();
107

M
Mr.doob 已提交
108
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
109

M
Mr.doob 已提交
110
			face = this.faces[ f ];
111

112 113 114
			vA = this.vertices[ face.a ];
			vB = this.vertices[ face.b ];
			vC = this.vertices[ face.c ];
U
unknown 已提交
115

116 117 118
			cb.sub( vC.position, vB.position );
			ab.sub( vA.position, vB.position );
			cb.crossSelf( ab );
U
unknown 已提交
119

120
			if ( !cb.isZero() ) {
U
unknown 已提交
121

122
				cb.normalize();
123 124 125

			}

126 127
			face.normal.copy( cb );

128 129 130 131
		}

	},

132 133
	computeVertexNormals: function () {

134
		var v, vl, f, fl, face, vertices;
135

136 137
		// create internal buffers for reuse when calling this method repeatedly
		// (otherwise memory allocation / deallocation every frame is big resource hog)
M
Mr.doob 已提交
138

139
		if ( this.__tmpVertices === undefined ) {
M
Mr.doob 已提交
140

141 142
			this.__tmpVertices = new Array( this.vertices.length );
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
143

144 145 146 147 148
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

				vertices[ v ] = new THREE.Vector3();

			}
M
Mr.doob 已提交
149

150 151 152 153 154 155 156
			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {

				face = this.faces[ f ];

				if ( face instanceof THREE.Face3 ) {

					face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
M
Mr.doob 已提交
157

158
				} else if ( face instanceof THREE.Face4 ) {
M
Mr.doob 已提交
159

160 161 162 163 164
					face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];

				}

			}
M
Mr.doob 已提交
165

166
		} else {
M
Mr.doob 已提交
167

168
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
169

170 171 172 173 174
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

				vertices[ v ].set( 0, 0, 0 );

			}
M
Mr.doob 已提交
175

M
Mr.doob 已提交
176 177 178 179 180 181 182
		}

		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
183

M
Mr.doob 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
				vertices[ face.a ].addSelf( face.normal );
				vertices[ face.b ].addSelf( face.normal );
				vertices[ face.c ].addSelf( face.normal );

			} else if ( face instanceof THREE.Face4 ) {

				vertices[ face.a ].addSelf( face.normal );
				vertices[ face.b ].addSelf( face.normal );
				vertices[ face.c ].addSelf( face.normal );
				vertices[ face.d ].addSelf( face.normal );

			}

		}

		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

			vertices[ v ].normalize();

		}

		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {

211 212 213
				face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
				face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
				face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
M
Mr.doob 已提交
214 215 216

			} else if ( face instanceof THREE.Face4 ) {

217 218 219 220
				face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
				face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
				face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
				face.vertexNormals[ 3 ].copy( vertices[ face.d ] );
M
Mr.doob 已提交
221 222

			}
223 224 225 226 227

		}

	},

228
	computeTangents: function () {
229

230 231
		// based on http://www.terathon.com/code/tangent.html
		// tangents go to vertices
232

233 234
		var f, fl, v, vl, i, il, vertexIndex,
			face, uv, vA, vB, vC, uvA, uvB, uvC,
235
			x1, x2, y1, y2, z1, z2,
236
			s1, s2, t1, t2, r, t, test,
237 238
			tan1 = [], tan2 = [],
			sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
239
			tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
240
			n = new THREE.Vector3(), w;
241

242 243 244 245 246 247
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

			tan1[ v ] = new THREE.Vector3();
			tan2[ v ] = new THREE.Vector3();

		}
248

M
Mr.doob 已提交
249
		function handleTriangle( context, a, b, c, ua, ub, uc ) {
250

251 252 253
			vA = context.vertices[ a ].position;
			vB = context.vertices[ b ].position;
			vC = context.vertices[ c ].position;
254

M
Mr.doob 已提交
255 256 257
			uvA = uv[ ua ];
			uvB = uv[ ub ];
			uvC = uv[ uc ];
258

259 260 261 262 263 264 265 266 267 268 269 270 271
			x1 = vB.x - vA.x;
			x2 = vC.x - vA.x;
			y1 = vB.y - vA.y;
			y2 = vC.y - vA.y;
			z1 = vB.z - vA.z;
			z2 = vC.z - vA.z;

			s1 = uvB.u - uvA.u;
			s2 = uvC.u - uvA.u;
			t1 = uvB.v - uvA.v;
			t2 = uvC.v - uvA.v;

			r = 1.0 / ( s1 * t2 - s2 * t1 );
272
			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
273 274
					  ( t2 * y1 - t1 * y2 ) * r,
					  ( t2 * z1 - t1 * z2 ) * r );
275
			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
276 277
					  ( s1 * y2 - s2 * y1 ) * r,
					  ( s1 * z2 - s2 * z1 ) * r );
278

279 280 281
			tan1[ a ].addSelf( sdir );
			tan1[ b ].addSelf( sdir );
			tan1[ c ].addSelf( sdir );
282

283 284 285
			tan2[ a ].addSelf( tdir );
			tan2[ b ].addSelf( tdir );
			tan2[ c ].addSelf( tdir );
286

287
		}
288

289
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
290

291
			face = this.faces[ f ];
292
			uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
293

294
			if ( face instanceof THREE.Face3 ) {
295

M
Mr.doob 已提交
296
				handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
297

298
			} else if ( face instanceof THREE.Face4 ) {
299

M
Mr.doob 已提交
300 301
				handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
				handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
302 303

			}
304

305
		}
306

307
		var faceIndex = [ 'a', 'b', 'c', 'd' ];
308

309
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
310

311
			face = this.faces[ f ];
312

313
			for ( i = 0; i < face.vertexNormals.length; i++ ) {
314

315
				n.copy( face.vertexNormals[ i ] );
316

317
				vertexIndex = face[ faceIndex[ i ] ];
318

319
				t = tan1[ vertexIndex ];
320

321
				// Gram-Schmidt orthogonalize
322

323 324
				tmp.copy( t );
				tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
325

326
				// Calculate handedness
327

328 329 330
				tmp2.cross( face.vertexNormals[ i ], t );
				test = tmp2.dot( tan2[ vertexIndex ] );
				w = (test < 0.0) ? -1.0 : 1.0;
331

332
				face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
333

334
			}
335

336
		}
337

338
		this.hasTangents = true;
339

340
	},
341

342
	computeBoundingBox: function () {
343 344 345

		if ( this.vertices.length > 0 ) {

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
			var position, firstPosition = this.vertices[ 0 ].position;

			if ( ! this.boundingBox ) {

				this.boundingBox = { min: firstPosition.clone(), max: firstPosition.clone() };

			} else {

				this.boundingBox.min.copy( firstPosition );
				this.boundingBox.max.copy( firstPosition );

			}

			var min = this.boundingBox.min,
				max = this.boundingBox.max;
361

M
Mr.doob 已提交
362
			for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
363

364
				position = this.vertices[ v ].position;
365

366
				if ( position.x < min.x ) {
367

368
					min.x = position.x;
369

370
				} else if ( position.x > max.x ) {
371

372
					max.x = position.x;
373 374 375

				}

376
				if ( position.y < min.y ) {
377

378
					min.y = position.y;
379

380
				} else if ( position.y > max.y ) {
381

382
					max.y = position.y;
383 384 385

				}

386
				if ( position.z < min.z ) {
387

388
					min.z = position.z;
389

390
				} else if ( position.z > max.z ) {
391

392
					max.z = position.z;
393 394 395 396

				}

			}
397 398 399

		}

M
Mr.doob 已提交
400 401
	},

402 403
	computeBoundingSphere: function () {

404 405 406
		// var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius;

		var radius = 0;
407 408 409 410 411 412 413 414 415

		for ( var v = 0, vl = this.vertices.length; v < vl; v ++ ) {

			radius = Math.max( radius, this.vertices[ v ].position.length() );

		}

		this.boundingSphere = { radius: radius };

416
	},
417 418 419

	/*
	 * Checks for duplicate vertices with hashmap.
420
	 * Duplicated vertices are removed
421
	 * and faces' vertices are updated.
422
	 */
423

424
	mergeVertices: function() {
425

426
		var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
427
		var unique = [], changes = [];
428

429
		var v, key;
430 431
		var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
		var precision = Math.pow( 10, precisionPoints );
432
		var i,il, face;
433 434 435 436 437 438 439 440 441 442 443 444

		for ( i = 0, il = this.vertices.length; i < il; i ++ ) {

			v = this.vertices[ i ].position;
			key = [ Math.round( v.x * precision ), Math.round( v.y * precision ), Math.round( v.z * precision ) ].join( '_' );

			if ( verticesMap[ key ] === undefined ) {

				verticesMap[ key ] = i;
				unique.push( this.vertices[ i ] );
				changes[ i ] = unique.length - 1;

445
			} else {
446

447
				//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
448 449
				changes[ i ] = changes[ verticesMap[ key ] ];

450
			}
451

452
		};
453 454 455 456


		// Start to patch face indices

457 458 459 460 461
		for( i = 0, il = this.faces.length; i < il; i ++ ) {

			face = this.faces[ i ];

			if ( face instanceof THREE.Face3 ) {
462 463 464 465 466 467 468 469 470 471 472 473

				face.a = changes[ face.a ];
				face.b = changes[ face.b ];
				face.c = changes[ face.c ];

			} else if ( face instanceof THREE.Face4 ) {

				face.a = changes[ face.a ];
				face.b = changes[ face.b ];
				face.c = changes[ face.c ];
				face.d = changes[ face.d ];

474
			}
475

476
		}
477

478
		// Use unique set of vertices
479

480
		this.vertices = unique;
481

482
	}
483

M
Mr.doob 已提交
484
};
485

486
THREE.GeometryCount = 0;