Geometry.js 10.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,

M
Mr.doob 已提交
41 42 43 44
	computeCentroids: function () {

		var f, fl, face;

M
Mr.doob 已提交
45
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
46 47 48 49 50 51

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

			if ( face instanceof THREE.Face3 ) {

M
Mr.doob 已提交
52 53 54
				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 已提交
55 56 57 58
				face.centroid.divideScalar( 3 );

			} else if ( face instanceof THREE.Face4 ) {

M
Mr.doob 已提交
59 60 61
				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 已提交
62 63 64 65 66 67 68 69 70
				face.centroid.addSelf( this.vertices[ face.d ].position );
				face.centroid.divideScalar( 4 );

			}

		}

	},

71
	computeFaceNormals: function ( useVertexNormals ) {
72

73 74
		var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
		cb = new THREE.Vector3(), ab = new THREE.Vector3();
75

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

M
Mr.doob 已提交
79 80
			vertex = this.vertices[ v ];
			vertex.normal.set( 0, 0, 0 );
81 82

		}
83
		*/
84

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

M
Mr.doob 已提交
87
			face = this.faces[ f ];
88

89
			if ( useVertexNormals && face.vertexNormals.length  ) {
90

91
				cb.set( 0, 0, 0 );
92

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

95
					cb.addSelf( face.vertexNormals[n] );
96

97
				}
U
unknown 已提交
98

99
				cb.divideScalar( 3 );
U
unknown 已提交
100

101
				if ( ! cb.isZero() ) {
U
unknown 已提交
102

103
					cb.normalize();
U
unknown 已提交
104

105
				}
U
unknown 已提交
106

107
				face.normal.copy( cb );
U
unknown 已提交
108

109
			} else {
110

111 112 113 114 115 116 117 118 119 120
				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 已提交
121
					cb.normalize();
122 123 124 125 126 127 128 129 130 131 132

				}

				face.normal.copy( cb );

			}

		}

	},

133 134
	computeVertexNormals: function () {

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

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

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

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

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

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

			}
M
Mr.doob 已提交
150

151 152 153 154 155 156 157
			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 已提交
158

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

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

				}

			}
M
Mr.doob 已提交
166

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

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

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

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

			}
M
Mr.doob 已提交
176

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

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

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
184

M
Mr.doob 已提交
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 211
				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 ) {

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

			} else if ( face instanceof THREE.Face4 ) {

218 219 220 221
				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 已提交
222 223

			}
224 225 226 227 228

		}

	},

229
	computeTangents: function () {
230

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

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

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

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

		}
249

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

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

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

260 261 262 263 264 265 266 267 268 269 270 271 272
			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 );
273
			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
274 275
					  ( t2 * y1 - t1 * y2 ) * r,
					  ( t2 * z1 - t1 * z2 ) * r );
276
			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
277 278
					  ( s1 * y2 - s2 * y1 ) * r,
					  ( s1 * z2 - s2 * z1 ) * r );
279

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

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

288
		}
289

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

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

295
			if ( face instanceof THREE.Face3 ) {
296

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

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

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

			}
305

306
		}
307

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

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

312
			face = this.faces[ f ];
313

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

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

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

320
				t = tan1[ vertexIndex ];
321

322
				// Gram-Schmidt orthogonalize
323

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

327
				// Calculate handedness
328

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

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

335
			}
336

337
		}
338

339
		this.hasTangents = true;
340

341
	},
342

343
	computeBoundingBox: function () {
344

345 346
		var vertex;

347 348
		if ( this.vertices.length > 0 ) {

M
Mr.doob 已提交
349
			this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ],
350
			'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ],
351 352
			'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };

M
Mr.doob 已提交
353
			for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
354 355 356

				vertex = this.vertices[ v ];

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

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

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

M
Mr.doob 已提交
363
					this.boundingBox.x[ 1 ] = vertex.position.x;
364 365 366

				}

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

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

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

M
Mr.doob 已提交
373
					this.boundingBox.y[ 1 ] = vertex.position.y;
374 375 376

				}

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

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

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

M
Mr.doob 已提交
383
					this.boundingBox.z[ 1 ] = vertex.position.z;
384 385 386 387

				}

			}
388 389 390

		}

M
Mr.doob 已提交
391 392
	},

393 394
	computeBoundingSphere: function () {

395 396 397
		// var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius;

		var radius = 0;
398 399 400 401 402 403 404 405 406

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

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

		}

		this.boundingSphere = { radius: radius };

407 408 409 410 411 412
	},

	computeEdgeFaces: function () {

		function edge_hash( a, b ) {

413
			return Math.min( a, b ) + "_" + Math.max( a, b );
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 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 501 502 503 504 505 506 507 508

		};

		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

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

				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

		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 ] );

			}

		}

509
	}
510

M
Mr.doob 已提交
511
};
512

513
THREE.GeometryCount = 0;