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 = [];
12
	this.uvs2 = [];
M
Mr.doob 已提交
13

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

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

19
	this.hasTangents = false;
20

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

THREE.Geometry.prototype = {

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

		var f, fl, face;

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

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

			if ( face instanceof THREE.Face3 ) {

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

			} else if ( face instanceof THREE.Face4 ) {

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

			}

		}

	},

55
	computeFaceNormals: function ( useVertexNormals ) {
56

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

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

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

		}

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

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

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

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

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

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

79
				}
U
unknown 已提交
80

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

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

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

87
				}
U
unknown 已提交
88

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

91
			} else {
92

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

				}

				face.normal.copy( cb );

			}

		}

	},

115 116
	computeVertexNormals: function () {

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

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
		// 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 已提交
140

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

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
					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 已提交
159
		}
160
		
M
Mr.doob 已提交
161 162 163 164 165 166

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

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
167

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

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

			} else if ( face instanceof THREE.Face4 ) {

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

			}
207 208 209 210 211

		}

	},

212
	computeTangents: function() {
213

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

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

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

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

		}
231

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

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

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

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

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

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

270
		}
271

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

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

277
			if ( face instanceof THREE.Face3 ) {
278

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

281 282 283
				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 ] );
284 285


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

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

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

296
			}
297

298
		}
299

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

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

305
			// Gram-Schmidt orthogonalize
306

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

310
			// Calculate handedness
311

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

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

318
		}
319

320
		this.hasTangents = true;
321

322
	},
323

324
	computeBoundingBox: function () {
325

326 327
		var vertex;

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

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

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

				vertex = this.vertices[ v ];

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

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

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

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

				}

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

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

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

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

				}

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

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

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

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

				}

			}
369 370 371

		}

M
Mr.doob 已提交
372 373
	},

374 375 376 377 378 379 380 381 382 383 384 385 386 387
	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 已提交
388 389 390 391 392 393 394
	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

395
		var i, l, f, fl, face, material, materials, vertices, mhash, ghash, hash_map = {};
M
Mr.doob 已提交
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 421

		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 已提交
422
			materials = face.materials;
M
Mr.doob 已提交
423

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

			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 已提交
436
				this.geometryChunks[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0 };
M
Mr.doob 已提交
437 438 439 440 441 442 443 444 445 446 447 448

			}

			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 已提交
449
					this.geometryChunks[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0 };
M
Mr.doob 已提交
450 451 452 453 454 455 456 457 458 459 460

				}

			}

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

		}

	},
M
Mr.doob 已提交
461

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

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

	}
467

M
Mr.doob 已提交
468
};