Geometry.js 14.5 KB
Newer Older
M
Mr.doob 已提交
1
/**
M
Mr.doob 已提交
2
 * @author mrdoob / 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

M
Mr.doob 已提交
11
	THREE.GeometryLibrary.push( this );
M
Mr.doob 已提交
12

M
Mr.doob 已提交
13 14
	this.id = THREE.GeometryIdCount ++;

M
Mr.doob 已提交
15 16
	this.name = '';

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

20 21
	this.materials = [];

M
Mr.doob 已提交
22
	this.faces = [];
23

24 25
	this.faceUvs = [[]];
	this.faceVertexUvs = [[]];
26

27
	this.morphTargets = [];
M
Mr.doob 已提交
28
	this.morphColors = [];
A
alteredq 已提交
29
	this.morphNormals = [];
M
Mr.doob 已提交
30

31 32
	this.skinWeights = [];
	this.skinIndices = [];
M
Mr.doob 已提交
33

34 35 36
	this.boundingBox = null;
	this.boundingSphere = null;

37
	this.hasTangents = false;
38

A
alteredq 已提交
39
	this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
40

41 42 43 44 45 46 47 48 49
	// update flags

	this.verticesNeedUpdate = false;
	this.elementsNeedUpdate = false;
	this.uvsNeedUpdate = false;
	this.normalsNeedUpdate = false;
	this.tangentsNeedUpdate = false;
	this.colorsNeedUpdate = false;

A
alteredq 已提交
50 51
	this.buffersNeedUpdate = false;

M
Mr.doob 已提交
52 53 54 55
};

THREE.Geometry.prototype = {

56 57
	constructor : THREE.Geometry,

58 59 60
	applyMatrix: function ( matrix ) {

		var matrixRotation = new THREE.Matrix4();
A
alteredq 已提交
61
		matrixRotation.extractRotation( matrix );
62 63 64 65 66

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

			var vertex = this.vertices[ i ];

67
			matrix.multiplyVector3( vertex );
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

		}

		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 已提交
89 90 91 92
	computeCentroids: function () {

		var f, fl, face;

M
Mr.doob 已提交
93
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
94 95 96 97 98 99

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

			if ( face instanceof THREE.Face3 ) {

100 101 102
				face.centroid.addSelf( this.vertices[ face.a ] );
				face.centroid.addSelf( this.vertices[ face.b ] );
				face.centroid.addSelf( this.vertices[ face.c ] );
M
Mr.doob 已提交
103 104 105 106
				face.centroid.divideScalar( 3 );

			} else if ( face instanceof THREE.Face4 ) {

107 108 109 110
				face.centroid.addSelf( this.vertices[ face.a ] );
				face.centroid.addSelf( this.vertices[ face.b ] );
				face.centroid.addSelf( this.vertices[ face.c ] );
				face.centroid.addSelf( this.vertices[ face.d ] );
M
Mr.doob 已提交
111 112 113 114 115 116 117 118
				face.centroid.divideScalar( 4 );

			}

		}

	},

119
	computeFaceNormals: function () {
120

121 122
		var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
		cb = new THREE.Vector3(), ab = new THREE.Vector3();
123

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

M
Mr.doob 已提交
126
			face = this.faces[ f ];
127

128 129 130
			vA = this.vertices[ face.a ];
			vB = this.vertices[ face.b ];
			vC = this.vertices[ face.c ];
U
unknown 已提交
131

132 133
			cb.sub( vC, vB );
			ab.sub( vA, vB );
134
			cb.crossSelf( ab );
U
unknown 已提交
135

136
			if ( !cb.isZero() ) {
U
unknown 已提交
137

138
				cb.normalize();
139 140 141

			}

142 143
			face.normal.copy( cb );

144 145 146 147
		}

	},

148 149
	computeVertexNormals: function () {

150
		var v, vl, f, fl, face, vertices;
151

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

155
		if ( this.__tmpVertices === undefined ) {
M
Mr.doob 已提交
156

157 158
			this.__tmpVertices = new Array( this.vertices.length );
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
159

160 161 162 163 164
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
M
Mr.doob 已提交
165

166 167 168 169 170 171 172
			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 已提交
173

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

176 177 178 179 180
					face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];

				}

			}
M
Mr.doob 已提交
181

182
		} else {
M
Mr.doob 已提交
183

184
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
185

186 187 188 189 190
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
M
Mr.doob 已提交
191

M
Mr.doob 已提交
192 193 194 195 196 197 198
		}

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

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
199

M
Mr.doob 已提交
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
				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 ) {

227 228 229
				face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
				face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
				face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
M
Mr.doob 已提交
230 231 232

			} else if ( face instanceof THREE.Face4 ) {

233 234 235 236
				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 已提交
237 238

			}
239 240 241 242 243

		}

	},

244 245 246 247
	computeMorphNormals: function () {

		var i, il, f, fl, face;

248 249 250
		// save original normals
		// - create temp variables on first access
		//   otherwise just copy (for faster repeated calls)
251 252 253 254

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

			face = this.faces[ f ];
255 256 257 258 259 260 261 262 263 264 265 266

			if ( ! face.__originalFaceNormal ) {

				face.__originalFaceNormal = face.normal.clone();

			} else {

				face.__originalFaceNormal.copy( face.normal );

			}

			if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
267 268 269

			for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {

270 271 272 273 274 275 276 277 278
				if ( ! face.__originalVertexNormals[ i ] ) {

					face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();

				} else {

					face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );

				}
279 280 281 282 283 284 285 286 287 288 289 290

			}

		}

		// use temp geometry to compute face and vertex normals for each morph

		var tmpGeo = new THREE.Geometry();
		tmpGeo.faces = this.faces;

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

291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
			// create on first access

			if ( ! this.morphNormals[ i ] ) {

				this.morphNormals[ i ] = {};
				this.morphNormals[ i ].faceNormals = [];
				this.morphNormals[ i ].vertexNormals = [];

				var dstNormalsFace = this.morphNormals[ i ].faceNormals;
				var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;

				var faceNormal, vertexNormals;

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

					face = this.faces[ f ];

					faceNormal = new THREE.Vector3();

					if ( face instanceof THREE.Face3 ) {

						vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };

					} else {

						vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3(), d: new THREE.Vector3() };

					}

					dstNormalsFace.push( faceNormal );
					dstNormalsVertex.push( vertexNormals );

				}

			}

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
			var morphNormals = this.morphNormals[ i ];

			// set vertices to morph target

			tmpGeo.vertices = this.morphTargets[ i ].vertices;

			// compute morph normals

			tmpGeo.computeFaceNormals();
			tmpGeo.computeVertexNormals();

			// store morph normals

			var faceNormal, vertexNormals;

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

				face = this.faces[ f ];

				faceNormal = morphNormals.faceNormals[ f ];
				vertexNormals = morphNormals.vertexNormals[ f ];

				faceNormal.copy( face.normal );

				if ( face instanceof THREE.Face3 ) {

					vertexNormals.a.copy( face.vertexNormals[ 0 ] );
					vertexNormals.b.copy( face.vertexNormals[ 1 ] );
					vertexNormals.c.copy( face.vertexNormals[ 2 ] );

				} else {

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

				}

			}

		}

370
		// restore original normals
371 372 373 374

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

			face = this.faces[ f ];
375 376

			face.normal = face.__originalFaceNormal;
377 378 379 380 381 382
			face.vertexNormals = face.__originalVertexNormals;

		}

	},

383
	computeTangents: function () {
384

385 386
		// based on http://www.terathon.com/code/tangent.html
		// tangents go to vertices
387

388 389
		var f, fl, v, vl, i, il, vertexIndex,
			face, uv, vA, vB, vC, uvA, uvB, uvC,
390
			x1, x2, y1, y2, z1, z2,
391
			s1, s2, t1, t2, r, t, test,
392 393
			tan1 = [], tan2 = [],
			sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
394
			tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
395
			n = new THREE.Vector3(), w;
396

397 398 399 400 401 402
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

		}
403

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

406 407 408
			vA = context.vertices[ a ];
			vB = context.vertices[ b ];
			vC = context.vertices[ c ];
409

M
Mr.doob 已提交
410 411 412
			uvA = uv[ ua ];
			uvB = uv[ ub ];
			uvC = uv[ uc ];
413

414 415 416 417 418 419 420 421 422 423 424 425 426
			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 );
427
			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
428 429
					  ( t2 * y1 - t1 * y2 ) * r,
					  ( t2 * z1 - t1 * z2 ) * r );
430
			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
431 432
					  ( s1 * y2 - s2 * y1 ) * r,
					  ( s1 * z2 - s2 * z1 ) * r );
433

434 435 436
			tan1[ a ].addSelf( sdir );
			tan1[ b ].addSelf( sdir );
			tan1[ c ].addSelf( sdir );
437

438 439 440
			tan2[ a ].addSelf( tdir );
			tan2[ b ].addSelf( tdir );
			tan2[ c ].addSelf( tdir );
441

442
		}
443

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

446
			face = this.faces[ f ];
447
			uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
448

449
			if ( face instanceof THREE.Face3 ) {
450

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

453
			} else if ( face instanceof THREE.Face4 ) {
454

M
Mr.doob 已提交
455
				handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
456
				handleTriangle( this, face.b, face.c, face.d, 1, 2, 3 );
457 458

			}
459

460
		}
461

462
		var faceIndex = [ 'a', 'b', 'c', 'd' ];
463

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

466
			face = this.faces[ f ];
467

468
			for ( i = 0; i < face.vertexNormals.length; i++ ) {
469

470
				n.copy( face.vertexNormals[ i ] );
471

472
				vertexIndex = face[ faceIndex[ i ] ];
473

474
				t = tan1[ vertexIndex ];
475

476
				// Gram-Schmidt orthogonalize
477

478 479
				tmp.copy( t );
				tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
480

481
				// Calculate handedness
482

483 484 485
				tmp2.cross( face.vertexNormals[ i ], t );
				test = tmp2.dot( tan2[ vertexIndex ] );
				w = (test < 0.0) ? -1.0 : 1.0;
486

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

489
			}
490

491
		}
492

493
		this.hasTangents = true;
494

495
	},
496

497
	computeBoundingBox: function () {
498

499
		if ( ! this.boundingBox ) {
500

501
			this.boundingBox = { min: new THREE.Vector3(), max: new THREE.Vector3() };
502

503
		}
504

505
		if ( this.vertices.length > 0 ) {
506

507
			var position, firstPosition = this.vertices[ 0 ];
508

509 510
			this.boundingBox.min.copy( firstPosition );
			this.boundingBox.max.copy( firstPosition );
511 512 513

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

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

517
				position = this.vertices[ v ];
518

519
				if ( position.x < min.x ) {
520

521
					min.x = position.x;
522

523
				} else if ( position.x > max.x ) {
524

525
					max.x = position.x;
526 527 528

				}

529
				if ( position.y < min.y ) {
530

531
					min.y = position.y;
532

533
				} else if ( position.y > max.y ) {
534

535
					max.y = position.y;
536 537 538

				}

539
				if ( position.z < min.z ) {
540

541
					min.z = position.z;
542

543
				} else if ( position.z > max.z ) {
544

545
					max.z = position.z;
546 547 548 549

				}

			}
550

551 552 553 554 555
		} else {

			this.boundingBox.min.set( 0, 0, 0 );
			this.boundingBox.max.set( 0, 0, 0 );

556 557
		}

M
Mr.doob 已提交
558 559
	},

560
	computeBoundingSphere: function () {
561

562
		var maxRadiusSq = 0;
563

564 565 566
		if ( this.boundingSphere === null ) this.boundingSphere = { radius: 0 };

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

			var radiusSq = this.vertices[ i ].lengthSq();
569
			if ( radiusSq > maxRadiusSq ) maxRadiusSq = radiusSq;
570 571 572

		}

573
		this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
574

575
	},
576 577 578

	/*
	 * Checks for duplicate vertices with hashmap.
579
	 * Duplicated vertices are removed
580
	 * and faces' vertices are updated.
581
	 */
582

583
	mergeVertices: function () {
584

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

588
		var v, key;
589 590
		var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
		var precision = Math.pow( 10, precisionPoints );
591
		var i,il, face;
Z
zz85 已提交
592
		var abcd = 'abcd', o, k, j, jl, u;
593 594 595

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

596
			v = this.vertices[ i ];
597 598 599 600 601 602 603 604
			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;

605
			} else {
606

607
				//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
608 609
				changes[ i ] = changes[ verticesMap[ key ] ];

610
			}
611

612
		};
613 614 615 616


		// Start to patch face indices

617 618 619 620 621
		for( i = 0, il = this.faces.length; i < il; i ++ ) {

			face = this.faces[ i ];

			if ( face instanceof THREE.Face3 ) {
622 623 624 625 626 627 628 629 630 631 632 633

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

634
				// check dups in (a, b, c, d) and convert to -> face3
635 636 637 638 639 640 641

				o = [ face.a, face.b, face.c, face.d ];

				for ( k = 3; k > 0; k -- ) {

					if ( o.indexOf( face[ abcd[ k ] ] ) !== k ) {

642
						// console.log('faces', face.a, face.b, face.c, face.d, 'dup at', k);
643 644 645 646 647 648 649 650 651 652

						o.splice( k, 1 );

						this.faces[ i ] = new THREE.Face3( o[0], o[1], o[2], face.normal, face.color, face.materialIndex );

						for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {

							u = this.faceVertexUvs[ j ][ i ];
							if ( u ) u.splice( k, 1 );

Z
zz85 已提交
653
						}
654

Z
zz85 已提交
655
						this.faces[ i ].vertexColors = face.vertexColors;
656

Z
zz85 已提交
657
						break;
658 659
					}

660
				}
661

662
			}
663

664
		}
665

666
		// Use unique set of vertices
667

Z
zz85 已提交
668
		var diff = this.vertices.length - unique.length;
669
		this.vertices = unique;
Z
zz85 已提交
670
		return diff;
671

672 673 674 675 676 677
	},

	clone: function () {

		// TODO

678 679 680 681
	},

	deallocate: function () {

M
Mr.doob 已提交
682 683
		var index = THREE.GeometryLibrary.indexOf( this );
		if ( index !== -1 ) THREE.GeometryLibrary.splice( index, 1 );
684

685
	}
686

M
Mr.doob 已提交
687
};
688

M
Mr.doob 已提交
689
THREE.GeometryIdCount = 0;
M
Mr.doob 已提交
690
THREE.GeometryLibrary = [];