Geometry.js 8.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

M
Mr.doob 已提交
10
	this.id = "Geometry" + THREE.GeometryIdCounter ++;
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.faceUvs = [[]];
	this.faceVertexUvs = [[]];
19

20
	this.morphTargets = [];
M
Mr.doob 已提交
21
	this.morphColors = [];
M
Mr.doob 已提交
22

23 24
	this.skinWeights = [];
	this.skinIndices = [];
M
Mr.doob 已提交
25

26 27 28
	this.boundingBox = null;
	this.boundingSphere = null;

29
	this.hasTangents = false;
30

M
Mr.doob 已提交
31 32 33 34
};

THREE.Geometry.prototype = {

M
Mr.doob 已提交
35 36 37 38
	computeCentroids: function () {

		var f, fl, face;

M
Mr.doob 已提交
39
		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
40 41 42 43 44 45

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

			if ( face instanceof THREE.Face3 ) {

M
Mr.doob 已提交
46 47 48
				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 已提交
49 50 51 52
				face.centroid.divideScalar( 3 );

			} else if ( face instanceof THREE.Face4 ) {

M
Mr.doob 已提交
53 54 55
				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 已提交
56 57 58 59 60 61 62 63 64
				face.centroid.addSelf( this.vertices[ face.d ].position );
				face.centroid.divideScalar( 4 );

			}

		}

	},

65
	computeFaceNormals: function ( useVertexNormals ) {
66

67 68
		var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
		cb = new THREE.Vector3(), ab = new THREE.Vector3();
69

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

M
Mr.doob 已提交
73 74
			vertex = this.vertices[ v ];
			vertex.normal.set( 0, 0, 0 );
75 76

		}
77
		*/
78

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

M
Mr.doob 已提交
81
			face = this.faces[ f ];
82

83
			if ( useVertexNormals && face.vertexNormals.length  ) {
84

85
				cb.set( 0, 0, 0 );
86

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

89
					cb.addSelf( face.vertexNormals[n] );
90

91
				}
U
unknown 已提交
92

93
				cb.divideScalar( 3 );
U
unknown 已提交
94

95
				if ( ! cb.isZero() ) {
U
unknown 已提交
96

97
					cb.normalize();
U
unknown 已提交
98

99
				}
U
unknown 已提交
100

101
				face.normal.copy( cb );
U
unknown 已提交
102

103
			} else {
104

105 106 107 108 109 110 111 112 113 114
				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 已提交
115
					cb.normalize();
116 117 118 119 120 121 122 123 124 125 126

				}

				face.normal.copy( cb );

			}

		}

	},

127 128
	computeVertexNormals: function () {

129
		var v, vl, f, fl, face, vertices;
130

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

134
		if ( this.__tmpVertices == undefined ) {
M
Mr.doob 已提交
135

136 137
			this.__tmpVertices = new Array( this.vertices.length );
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
138

139 140 141 142 143
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
M
Mr.doob 已提交
144

145 146 147 148 149 150 151
			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 已提交
152

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

155 156 157 158 159
					face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];

				}

			}
M
Mr.doob 已提交
160

161
		} else {
M
Mr.doob 已提交
162

163
			vertices = this.__tmpVertices;
M
Mr.doob 已提交
164

165 166 167 168 169
			for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

			}
M
Mr.doob 已提交
170

M
Mr.doob 已提交
171 172 173 174 175 176 177
		}

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

			face = this.faces[ f ];

			if ( face instanceof THREE.Face3 ) {
178

M
Mr.doob 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
				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 ) {

206 207 208
				face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
				face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
				face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
M
Mr.doob 已提交
209 210 211

			} else if ( face instanceof THREE.Face4 ) {

212 213 214 215
				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 已提交
216 217

			}
218 219 220 221 222

		}

	},

223
	computeTangents: function () {
224

225 226
		// based on http://www.terathon.com/code/tangent.html
		// tangents go to vertices
227

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

237 238 239 240 241 242
		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {

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

		}
243

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

246 247 248
			vA = context.vertices[ a ].position;
			vB = context.vertices[ b ].position;
			vC = context.vertices[ c ].position;
249

M
Mr.doob 已提交
250 251 252
			uvA = uv[ ua ];
			uvB = uv[ ub ];
			uvC = uv[ uc ];
253

254 255 256 257 258 259 260 261 262 263 264 265 266
			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 );
267
			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
268 269
					  ( t2 * y1 - t1 * y2 ) * r,
					  ( t2 * z1 - t1 * z2 ) * r );
270
			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
271 272
					  ( s1 * y2 - s2 * y1 ) * r,
					  ( s1 * z2 - s2 * z1 ) * r );
273

274 275 276
			tan1[ a ].addSelf( sdir );
			tan1[ b ].addSelf( sdir );
			tan1[ c ].addSelf( sdir );
277

278 279 280
			tan2[ a ].addSelf( tdir );
			tan2[ b ].addSelf( tdir );
			tan2[ c ].addSelf( tdir );
281

282
		}
283

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

286
			face = this.faces[ f ];
287
			uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
288

289
			if ( face instanceof THREE.Face3 ) {
290

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

293
			} else if ( face instanceof THREE.Face4 ) {
294

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

			}
299

300
		}
301

302
		var faceIndex = [ 'a', 'b', 'c', 'd' ];
303

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

306
			face = this.faces[ f ];
307

308
			for ( i = 0; i < face.vertexNormals.length; i++ ) {
309

310
				n.copy( face.vertexNormals[ i ] );
311

312
				vertexIndex = face[ faceIndex[ i ] ];
313

314
				t = tan1[ vertexIndex ];
315

316
				// Gram-Schmidt orthogonalize
317

318 319
				tmp.copy( t );
				tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
320

321
				// Calculate handedness
322

323 324 325
				tmp2.cross( face.vertexNormals[ i ], t );
				test = tmp2.dot( tan2[ vertexIndex ] );
				w = (test < 0.0) ? -1.0 : 1.0;
326

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

329
			}
330

331
		}
332

333
		this.hasTangents = true;
334

335
	},
336

337
	computeBoundingBox: function () {
338

339 340
		var vertex;

341 342
		if ( this.vertices.length > 0 ) {

M
Mr.doob 已提交
343
			this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ],
344
			'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ],
345 346
			'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };

M
Mr.doob 已提交
347
			for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
348 349 350

				vertex = this.vertices[ v ];

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

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

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

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

				}

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

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

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

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

				}

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

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

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

M
Mr.doob 已提交
377
					this.boundingBox.z[ 1 ] = vertex.position.z;
378 379 380 381

				}

			}
382 383 384

		}

M
Mr.doob 已提交
385 386
	},

387 388 389 390 391 392 393 394 395 396 397 398
	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 已提交
399
	}
400

M
Mr.doob 已提交
401
};
402 403

THREE.GeometryIdCounter = 0;