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

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

M
Mr.doob 已提交
9 10
	this.vertices = [];
	this.faces = [];
11
	this.uvs = [];
M
Mr.doob 已提交
12

13 14 15
	this.boundingBox = null;
	this.boundingSphere = null;

M
Mr.doob 已提交
16
	this.geometryChunks = {};
17

18
	this.hasTangents = false;
19

M
Mr.doob 已提交
20 21 22 23
};

THREE.Geometry.prototype = {

M
Mr.doob 已提交
24 25 26 27
	computeCentroids: function () {

		var f, fl, face;

M
Mr.doob 已提交
28
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
29 30 31 32 33 34

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

			if ( face instanceof THREE.Face3 ) {

M
Mr.doob 已提交
35 36 37
				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 已提交
38 39 40 41
				face.centroid.divideScalar( 3 );

			} else if ( face instanceof THREE.Face4 ) {

M
Mr.doob 已提交
42 43 44
				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 已提交
45 46 47 48 49 50 51 52 53
				face.centroid.addSelf( this.vertices[ face.d ].position );
				face.centroid.divideScalar( 4 );

			}

		}

	},

54
	computeFaceNormals: function ( useVertexNormals ) {
55

56 57
		var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
		cb = new THREE.Vector3(), ab = new THREE.Vector3();
58

M
Mr.doob 已提交
59
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
60

M
Mr.doob 已提交
61 62
			vertex = this.vertices[ v ];
			vertex.normal.set( 0, 0, 0 );
63 64 65

		}

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

M
Mr.doob 已提交
68
			face = this.faces[ f ];
69

70
			if ( useVertexNormals && face.vertexNormals.length  ) {
71

72
				cb.set( 0, 0, 0 );
73

74
				for ( n = 0, nl = face.normal.length; n < nl; n++ ) {
75

76
					cb.addSelf( face.vertexNormals[n] );
77

78
				}
U
unknown 已提交
79

80
				cb.divideScalar( 3 );
U
unknown 已提交
81

82
				if ( ! cb.isZero() ) {
U
unknown 已提交
83

84
					cb.normalize();
U
unknown 已提交
85

86
				}
U
unknown 已提交
87

88
				face.normal.copy( cb );
U
unknown 已提交
89

90
			} else {
91

92 93 94 95 96 97 98 99 100 101
				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 已提交
102
					cb.normalize();
103 104 105 106 107 108 109 110 111 112 113

				}

				face.normal.copy( cb );

			}

		}

	},

114 115
	computeVertexNormals: function () {

116
		var v, vl, f, fl, face, vertices;
117

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
		// create internal buffers for reuse when calling this method repeatedly
		// (otherwise memory allocation / deallocation every frame is big resource hog)
		
		if ( this.__tmpVertices == undefined ) {
			
			this.__tmpVertices = new Array( this.vertices.length );
			vertices = this.__tmpVertices;
			
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
			
			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 已提交
139

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

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
					face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];

				}

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

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

			}
			
M
Mr.doob 已提交
158
		}
159
		
M
Mr.doob 已提交
160 161 162 163 164 165

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

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
166

M
Mr.doob 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
				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 ) {

194 195 196
				face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
				face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
				face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
M
Mr.doob 已提交
197 198 199

			} else if ( face instanceof THREE.Face4 ) {

200 201 202 203
				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 已提交
204 205

			}
206 207 208 209 210

		}

	},

211
	computeTangents: function() {
212

213 214
		// based on http://www.terathon.com/code/tangent.html
		// tangents go to vertices
215

216 217
		var f, fl, v, vl, face, uv, vA, vB, vC, uvA, uvB, uvC,
			x1, x2, y1, y2, z1, z2,
218
			s1, s2, t1, t2, r, t, test,
219 220
			tan1 = [], tan2 = [],
			sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
221
			tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
222
			n = new THREE.Vector3(), w;
223

224 225 226 227 228 229
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

		}
230

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

233 234 235
			vA = context.vertices[ a ].position;
			vB = context.vertices[ b ].position;
			vC = context.vertices[ c ].position;
236

M
Mr.doob 已提交
237 238 239
			uvA = uv[ ua ];
			uvB = uv[ ub ];
			uvC = uv[ uc ];
240

241 242 243 244 245 246 247 248 249 250 251 252 253
			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 );
254
			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
255 256
					  ( t2 * y1 - t1 * y2 ) * r,
					  ( t2 * z1 - t1 * z2 ) * r );
257
			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
258 259
					  ( s1 * y2 - s2 * y1 ) * r,
					  ( s1 * z2 - s2 * z1 ) * r );
260

261 262 263
			tan1[ a ].addSelf( sdir );
			tan1[ b ].addSelf( sdir );
			tan1[ c ].addSelf( sdir );
264

265 266 267
			tan2[ a ].addSelf( tdir );
			tan2[ b ].addSelf( tdir );
			tan2[ c ].addSelf( tdir );
268

269
		}
270

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

273 274
			face = this.faces[ f ];
			uv = this.uvs[ f ];
275

276
			if ( face instanceof THREE.Face3 ) {
277

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

280 281 282
				this.vertices[ face.a ].normal.copy( face.vertexNormals[ 0 ] );
				this.vertices[ face.b ].normal.copy( face.vertexNormals[ 1 ] );
				this.vertices[ face.c ].normal.copy( face.vertexNormals[ 2 ] );
283 284


285
			} else if ( face instanceof THREE.Face4 ) {
286

M
Mr.doob 已提交
287 288
				handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
				handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
289 290 291 292 293

				this.vertices[ face.a ].normal.copy( face.vertexNormals[ 0 ] );
				this.vertices[ face.b ].normal.copy( face.vertexNormals[ 1 ] );
				this.vertices[ face.c ].normal.copy( face.vertexNormals[ 2 ] );
				this.vertices[ face.d ].normal.copy( face.vertexNormals[ 3 ] );
294

295
			}
296

297
		}
298

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

301 302
			n.copy( this.vertices[ v ].normal );
			t = tan1[ v ];
303

304
			// Gram-Schmidt orthogonalize
305

306 307
			tmp.copy( t );
			tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
308

309
			// Calculate handedness
310

311 312 313
			tmp2.cross( this.vertices[ v ].normal, t );
			test = tmp2.dot( tan2[ v ] );
			w = (test < 0.0) ? -1.0 : 1.0;
314

315
			this.vertices[ v ].tangent.set( tmp.x, tmp.y, tmp.z, w );
316

317
		}
318

319
		this.hasTangents = true;
320

321
	},
322

323
	computeBoundingBox: function () {
324

325 326
		var vertex;

327 328
		if ( this.vertices.length > 0 ) {

M
Mr.doob 已提交
329
			this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ],
330
			'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ],
331 332
			'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };

M
Mr.doob 已提交
333
			for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
334 335 336

				vertex = this.vertices[ v ];

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

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

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

M
Mr.doob 已提交
343
					this.boundingBox.x[ 1 ] = vertex.position.x;
344 345 346

				}

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

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

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

M
Mr.doob 已提交
353
					this.boundingBox.y[ 1 ] = vertex.position.y;
354 355 356

				}

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

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

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

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

				}

			}
368 369 370

		}

M
Mr.doob 已提交
371 372
	},

373 374 375 376 377 378 379 380 381 382 383 384 385 386
	computeBoundingSphere: function () {

		var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius;

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

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

		}

		this.boundingSphere = { radius: radius };

	},

M
Mr.doob 已提交
387 388 389 390 391 392 393
	sortFacesByMaterial: function () {

		// TODO
		// Should optimize by grouping faces with ColorFill / ColorStroke materials
		// which could then use vertex color attributes instead of each being
		// in its separate VBO

394
		var i, l, f, fl, face, material, materials, vertices, mhash, ghash, hash_map = {};
M
Mr.doob 已提交
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420

		function materialHash( material ) {

			var hash_array = [];

			for ( i = 0, l = material.length; i < l; i++ ) {

				if ( material[ i ] == undefined ) {

					hash_array.push( "undefined" );

				} else {

					hash_array.push( material[ i ].toString() );

				}

			}

			return hash_array.join( '_' );

		}

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

			face = this.faces[ f ];
M
Mr.doob 已提交
421
			materials = face.materials;
M
Mr.doob 已提交
422

M
Mr.doob 已提交
423
			mhash = materialHash( materials );
M
Mr.doob 已提交
424 425 426 427 428 429 430 431 432 433 434

			if ( hash_map[ mhash ] == undefined ) {

				hash_map[ mhash ] = { 'hash': mhash, 'counter': 0 };

			}

			ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter;

			if ( this.geometryChunks[ ghash ] == undefined ) {

M
Mr.doob 已提交
435
				this.geometryChunks[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0 };
M
Mr.doob 已提交
436 437 438 439 440 441 442 443 444 445 446 447

			}

			vertices = face instanceof THREE.Face3 ? 3 : 4;

			if ( this.geometryChunks[ ghash ].vertices + vertices > 65535 ) {

				hash_map[ mhash ].counter += 1;
				ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter;

				if ( this.geometryChunks[ ghash ] == undefined ) {

M
Mr.doob 已提交
448
					this.geometryChunks[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0 };
M
Mr.doob 已提交
449 450 451 452 453 454 455 456 457 458 459

				}

			}

			this.geometryChunks[ ghash ].faces.push( f );
			this.geometryChunks[ ghash ].vertices += vertices;

		}

	},
M
Mr.doob 已提交
460

M
Mr.doob 已提交
461 462
	toString: function () {

463
		return 'THREE.Geometry ( vertices: ' + this.vertices + ', faces: ' + this.faces + ', uvs: ' + this.uvs + ' )';
M
Mr.doob 已提交
464 465

	}
466

M
Mr.doob 已提交
467
};