Geometry.js 11.6 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/
M
Mr.doob 已提交
6 7
 */

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

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

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

M
Mr.doob 已提交
15
	this.faces = [];
16

17 18
	this.edges = [];

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

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

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

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

31
	this.hasTangents = false;
32

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

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

THREE.Geometry.prototype = {

39 40
	constructor : THREE.Geometry,

41 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
	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 已提交
72 73 74 75
	computeCentroids: function () {

		var f, fl, face;

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

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

			if ( face instanceof THREE.Face3 ) {

M
Mr.doob 已提交
83 84 85
				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 已提交
86 87 88 89
				face.centroid.divideScalar( 3 );

			} else if ( face instanceof THREE.Face4 ) {

M
Mr.doob 已提交
90 91 92
				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 已提交
93 94 95 96 97 98 99 100 101
				face.centroid.addSelf( this.vertices[ face.d ].position );
				face.centroid.divideScalar( 4 );

			}

		}

	},

102
	computeFaceNormals: function ( useVertexNormals ) {
103

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

107
		/*
M
Mr.doob 已提交
108
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
109

M
Mr.doob 已提交
110 111
			vertex = this.vertices[ v ];
			vertex.normal.set( 0, 0, 0 );
112 113

		}
114
		*/
115

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

M
Mr.doob 已提交
118
			face = this.faces[ f ];
119

120
			if ( useVertexNormals && face.vertexNormals.length  ) {
121

122
				cb.set( 0, 0, 0 );
123

124
				for ( n = 0, nl = face.vertexNormals.length; n < nl; n++ ) {
125

126
					cb.addSelf( face.vertexNormals[n] );
127

128
				}
U
unknown 已提交
129

130
				cb.divideScalar( 3 );
U
unknown 已提交
131

132
				if ( ! cb.isZero() ) {
U
unknown 已提交
133

134
					cb.normalize();
U
unknown 已提交
135

136
				}
U
unknown 已提交
137

138
				face.normal.copy( cb );
U
unknown 已提交
139

140
			} else {
141

142 143 144 145 146 147 148 149 150 151
				vA = this.vertices[ face.a ];
				vB = this.vertices[ face.b ];
				vC = this.vertices[ face.c ];

				cb.sub( vC.position, vB.position );
				ab.sub( vA.position, vB.position );
				cb.crossSelf( ab );

				if ( !cb.isZero() ) {

M
Mr.doob 已提交
152
					cb.normalize();
153 154 155 156 157 158 159 160 161 162 163

				}

				face.normal.copy( cb );

			}

		}

	},

164 165
	computeVertexNormals: function () {

166
		var v, vl, f, fl, face, vertices;
167

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

171
		if ( this.__tmpVertices == undefined ) {
M
Mr.doob 已提交
172

173 174
			this.__tmpVertices = new Array( this.vertices.length );
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
175

176 177 178 179 180
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
M
Mr.doob 已提交
181

182 183 184 185 186 187 188
			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 已提交
189

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

192 193 194 195 196
					face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];

				}

			}
M
Mr.doob 已提交
197

198
		} else {
M
Mr.doob 已提交
199

200
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
201

202 203 204 205 206
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
M
Mr.doob 已提交
207

M
Mr.doob 已提交
208 209 210 211 212 213 214
		}

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

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
215

M
Mr.doob 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
				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 ) {

243 244 245
				face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
				face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
				face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
M
Mr.doob 已提交
246 247 248

			} else if ( face instanceof THREE.Face4 ) {

249 250 251 252
				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 已提交
253 254

			}
255 256 257 258 259

		}

	},

260
	computeTangents: function () {
261

262 263
		// based on http://www.terathon.com/code/tangent.html
		// tangents go to vertices
264

265 266
		var f, fl, v, vl, i, il, vertexIndex,
			face, uv, vA, vB, vC, uvA, uvB, uvC,
267
			x1, x2, y1, y2, z1, z2,
268
			s1, s2, t1, t2, r, t, test,
269 270
			tan1 = [], tan2 = [],
			sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
271
			tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
272
			n = new THREE.Vector3(), w;
273

274 275 276 277 278 279
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

		}
280

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

283 284 285
			vA = context.vertices[ a ].position;
			vB = context.vertices[ b ].position;
			vC = context.vertices[ c ].position;
286

M
Mr.doob 已提交
287 288 289
			uvA = uv[ ua ];
			uvB = uv[ ub ];
			uvC = uv[ uc ];
290

291 292 293 294 295 296 297 298 299 300 301 302 303
			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 );
304
			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
305 306
					  ( t2 * y1 - t1 * y2 ) * r,
					  ( t2 * z1 - t1 * z2 ) * r );
307
			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
308 309
					  ( s1 * y2 - s2 * y1 ) * r,
					  ( s1 * z2 - s2 * z1 ) * r );
310

311 312 313
			tan1[ a ].addSelf( sdir );
			tan1[ b ].addSelf( sdir );
			tan1[ c ].addSelf( sdir );
314

315 316 317
			tan2[ a ].addSelf( tdir );
			tan2[ b ].addSelf( tdir );
			tan2[ c ].addSelf( tdir );
318

319
		}
320

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

323
			face = this.faces[ f ];
324
			uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
325

326
			if ( face instanceof THREE.Face3 ) {
327

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

330
			} else if ( face instanceof THREE.Face4 ) {
331

M
Mr.doob 已提交
332 333
				handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
				handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
334 335

			}
336

337
		}
338

339
		var faceIndex = [ 'a', 'b', 'c', 'd' ];
340

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

343
			face = this.faces[ f ];
344

345
			for ( i = 0; i < face.vertexNormals.length; i++ ) {
346

347
				n.copy( face.vertexNormals[ i ] );
348

349
				vertexIndex = face[ faceIndex[ i ] ];
350

351
				t = tan1[ vertexIndex ];
352

353
				// Gram-Schmidt orthogonalize
354

355 356
				tmp.copy( t );
				tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
357

358
				// Calculate handedness
359

360 361 362
				tmp2.cross( face.vertexNormals[ i ], t );
				test = tmp2.dot( tan2[ vertexIndex ] );
				w = (test < 0.0) ? -1.0 : 1.0;
363

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

366
			}
367

368
		}
369

370
		this.hasTangents = true;
371

372
	},
373

374
	computeBoundingBox: function () {
375

376 377
		var vertex;

378 379
		if ( this.vertices.length > 0 ) {

M
Mr.doob 已提交
380
			this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ],
381
			'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ],
382 383
			'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };

M
Mr.doob 已提交
384
			for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
385 386 387

				vertex = this.vertices[ v ];

M
Mr.doob 已提交
388
				if ( vertex.position.x < this.boundingBox.x[ 0 ] ) {
389

M
Mr.doob 已提交
390
					this.boundingBox.x[ 0 ] = vertex.position.x;
391

M
Mr.doob 已提交
392
				} else if ( vertex.position.x > this.boundingBox.x[ 1 ] ) {
393

M
Mr.doob 已提交
394
					this.boundingBox.x[ 1 ] = vertex.position.x;
395 396 397

				}

M
Mr.doob 已提交
398
				if ( vertex.position.y < this.boundingBox.y[ 0 ] ) {
399

M
Mr.doob 已提交
400
					this.boundingBox.y[ 0 ] = vertex.position.y;
401

M
Mr.doob 已提交
402
				} else if ( vertex.position.y > this.boundingBox.y[ 1 ] ) {
403

M
Mr.doob 已提交
404
					this.boundingBox.y[ 1 ] = vertex.position.y;
405 406 407

				}

M
Mr.doob 已提交
408
				if ( vertex.position.z < this.boundingBox.z[ 0 ] ) {
409

M
Mr.doob 已提交
410
					this.boundingBox.z[ 0 ] = vertex.position.z;
411

M
Mr.doob 已提交
412
				} else if ( vertex.position.z > this.boundingBox.z[ 1 ] ) {
413

M
Mr.doob 已提交
414
					this.boundingBox.z[ 1 ] = vertex.position.z;
415 416 417 418

				}

			}
419 420 421

		}

M
Mr.doob 已提交
422 423
	},

424 425
	computeBoundingSphere: function () {

426 427 428
		// var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius;

		var radius = 0;
429 430 431 432 433 434 435 436 437

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

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

		}

		this.boundingSphere = { radius: radius };

438 439 440 441 442 443
	},

	computeEdgeFaces: function () {

		function edge_hash( a, b ) {

444
			return Math.min( a, b ) + "_" + Math.max( a, b );
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

		};

		function addToMap( map, hash, i ) {

			if ( map[ hash ] === undefined ) {

				map[ hash ] = { "set": {}, "array": [] };
				map[ hash ].set[ i ] = 1;
				map[ hash ].array.push( i );

			} else {

				if( map[ hash ].set[ i ] === undefined ) {

					map[ hash ].set[ i ] = 1;
					map[ hash ].array.push( i );

				}

			}

		};

		var i, il, v1, v2, j, k,
			face, faceIndices, faceIndex,
			edge,
			hash,
			vfMap = {};

		// construct vertex -> face map

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

			face = this.faces[ i ];

			if ( face instanceof THREE.Face3 ) {

				hash = edge_hash( face.a, face.b );
				addToMap( vfMap, hash, i );

				hash = edge_hash( face.b, face.c );
				addToMap( vfMap, hash, i );

				hash = edge_hash( face.a, face.c );
				addToMap( vfMap, hash, i );

			} else if ( face instanceof THREE.Face4 ) {

				// in WebGLRenderer quad is tesselated
				// to triangles: a,b,d / b,c,d
				// shared edge is: b,d

				// should shared edge be included?
				// comment out if not

501 502
				// hash = edge_hash( face.b, face.d ); 
				// addToMap( vfMap, hash, i );
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

				hash = edge_hash( face.a, face.b );
				addToMap( vfMap, hash, i );

				hash = edge_hash( face.a, face.d );
				addToMap( vfMap, hash, i );

				hash = edge_hash( face.b, face.c );
				addToMap( vfMap, hash, i );

				hash = edge_hash( face.c, face.d );
				addToMap( vfMap, hash, i );

			}

		}

		// extract faces
521 522 523 524 525 526 527 528 529 530 531
		
	
		this.vfMap = vfMap;
		
		var numOfEdges = 0;
		for (i in vfMap) {
			numOfEdges++;
			
			edge = vfMap[i];
			this.edges.push(edge.array);
			
532
		}
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
		
		//console.log('vfMap', vfMap, 'this.edges',this.edges, 'numOfEdges', numOfEdges);

		// Not sure what the below does.
		
		// for( i = 0, il = this.edges.length; i < il; i ++ ) {
		// 
		// 	edge = this.edges[ i ];
		// 
		// 	v1 = edge.vertexIndices[ 0 ];
		// 	v2 = edge.vertexIndices[ 1 ];
		// 
		// 	edge.faceIndices = vfMap[ edge_hash( v1, v2 ) ].array;
		// 
		// 	for( j = 0; j < edge.faceIndices.length; j ++ ) {
		// 
		// 		faceIndex = edge.faceIndices[ j ];
		// 		edge.faces.push( this.faces[ faceIndex ] );
		// 
		// 	}
		// 
		// }
555

556
	}
557

M
Mr.doob 已提交
558
};
559

560
THREE.GeometryCount = 0;