source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/src/core/Geometry.js@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 12.6 KB
Line 
1/**
2 * @author mrdoob / http://mrdoob.com/
3 * @author kile / http://kile.stravaganza.org/
4 * @author alteredq / http://alteredqualia.com/
5 * @author mikael emtinger / http://gomo.se/
6 * @author zz85 / http://www.lab4games.net/zz85/blog
7 * @author bhouston / http://exocortex.com
8 */
9
10THREE.Geometry = function () {
11
12 this.id = THREE.GeometryIdCount ++;
13 this.uuid = THREE.Math.generateUUID();
14
15 this.name = '';
16
17 this.vertices = [];
18 this.colors = []; // one-to-one vertex colors, used in ParticleSystem and Line
19
20 this.faces = [];
21
22 this.faceVertexUvs = [[]];
23
24 this.morphTargets = [];
25 this.morphColors = [];
26 this.morphNormals = [];
27
28 this.skinWeights = [];
29 this.skinIndices = [];
30
31 this.lineDistances = [];
32
33 this.boundingBox = null;
34 this.boundingSphere = null;
35
36 this.hasTangents = false;
37
38 this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
39
40 // update flags
41
42 this.verticesNeedUpdate = false;
43 this.elementsNeedUpdate = false;
44 this.uvsNeedUpdate = false;
45 this.normalsNeedUpdate = false;
46 this.tangentsNeedUpdate = false;
47 this.colorsNeedUpdate = false;
48 this.lineDistancesNeedUpdate = false;
49
50 this.buffersNeedUpdate = false;
51
52};
53
54THREE.Geometry.prototype = {
55
56 constructor: THREE.Geometry,
57
58 applyMatrix: function ( matrix ) {
59
60 var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
61
62 for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
63
64 var vertex = this.vertices[ i ];
65 vertex.applyMatrix4( matrix );
66
67 }
68
69 for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
70
71 var face = this.faces[ i ];
72 face.normal.applyMatrix3( normalMatrix ).normalize();
73
74 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
75
76 face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
77
78 }
79
80 face.centroid.applyMatrix4( matrix );
81
82 }
83
84 if ( this.boundingBox instanceof THREE.Box3 ) {
85
86 this.computeBoundingBox();
87
88 }
89
90 if ( this.boundingSphere instanceof THREE.Sphere ) {
91
92 this.computeBoundingSphere();
93
94 }
95
96 },
97
98 computeCentroids: function () {
99
100 var f, fl, face;
101
102 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
103
104 face = this.faces[ f ];
105 face.centroid.set( 0, 0, 0 );
106
107 face.centroid.add( this.vertices[ face.a ] );
108 face.centroid.add( this.vertices[ face.b ] );
109 face.centroid.add( this.vertices[ face.c ] );
110 face.centroid.divideScalar( 3 );
111
112 }
113
114 },
115
116 computeFaceNormals: function () {
117
118 var cb = new THREE.Vector3(), ab = new THREE.Vector3();
119
120 for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
121
122 var face = this.faces[ f ];
123
124 var vA = this.vertices[ face.a ];
125 var vB = this.vertices[ face.b ];
126 var vC = this.vertices[ face.c ];
127
128 cb.subVectors( vC, vB );
129 ab.subVectors( vA, vB );
130 cb.cross( ab );
131
132 cb.normalize();
133
134 face.normal.copy( cb );
135
136 }
137
138 },
139
140 computeVertexNormals: function ( areaWeighted ) {
141
142 var v, vl, f, fl, face, vertices;
143
144 vertices = new Array( this.vertices.length );
145
146 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
147
148 vertices[ v ] = new THREE.Vector3();
149
150 }
151
152 if ( areaWeighted ) {
153
154 // vertex normals weighted by triangle areas
155 // http://www.iquilezles.org/www/articles/normals/normals.htm
156
157 var vA, vB, vC, vD;
158 var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
159 db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
160
161 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
162
163 face = this.faces[ f ];
164
165 vA = this.vertices[ face.a ];
166 vB = this.vertices[ face.b ];
167 vC = this.vertices[ face.c ];
168
169 cb.subVectors( vC, vB );
170 ab.subVectors( vA, vB );
171 cb.cross( ab );
172
173 vertices[ face.a ].add( cb );
174 vertices[ face.b ].add( cb );
175 vertices[ face.c ].add( cb );
176
177 }
178
179 } else {
180
181 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
182
183 face = this.faces[ f ];
184
185 vertices[ face.a ].add( face.normal );
186 vertices[ face.b ].add( face.normal );
187 vertices[ face.c ].add( face.normal );
188
189 }
190
191 }
192
193 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
194
195 vertices[ v ].normalize();
196
197 }
198
199 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
200
201 face = this.faces[ f ];
202
203 face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
204 face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
205 face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
206
207 }
208
209 },
210
211 computeMorphNormals: function () {
212
213 var i, il, f, fl, face;
214
215 // save original normals
216 // - create temp variables on first access
217 // otherwise just copy (for faster repeated calls)
218
219 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
220
221 face = this.faces[ f ];
222
223 if ( ! face.__originalFaceNormal ) {
224
225 face.__originalFaceNormal = face.normal.clone();
226
227 } else {
228
229 face.__originalFaceNormal.copy( face.normal );
230
231 }
232
233 if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
234
235 for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
236
237 if ( ! face.__originalVertexNormals[ i ] ) {
238
239 face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
240
241 } else {
242
243 face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
244
245 }
246
247 }
248
249 }
250
251 // use temp geometry to compute face and vertex normals for each morph
252
253 var tmpGeo = new THREE.Geometry();
254 tmpGeo.faces = this.faces;
255
256 for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
257
258 // create on first access
259
260 if ( ! this.morphNormals[ i ] ) {
261
262 this.morphNormals[ i ] = {};
263 this.morphNormals[ i ].faceNormals = [];
264 this.morphNormals[ i ].vertexNormals = [];
265
266 var dstNormalsFace = this.morphNormals[ i ].faceNormals;
267 var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
268
269 var faceNormal, vertexNormals;
270
271 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
272
273 face = this.faces[ f ];
274
275 faceNormal = new THREE.Vector3();
276 vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
277
278 dstNormalsFace.push( faceNormal );
279 dstNormalsVertex.push( vertexNormals );
280
281 }
282
283 }
284
285 var morphNormals = this.morphNormals[ i ];
286
287 // set vertices to morph target
288
289 tmpGeo.vertices = this.morphTargets[ i ].vertices;
290
291 // compute morph normals
292
293 tmpGeo.computeFaceNormals();
294 tmpGeo.computeVertexNormals();
295
296 // store morph normals
297
298 var faceNormal, vertexNormals;
299
300 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
301
302 face = this.faces[ f ];
303
304 faceNormal = morphNormals.faceNormals[ f ];
305 vertexNormals = morphNormals.vertexNormals[ f ];
306
307 faceNormal.copy( face.normal );
308
309 vertexNormals.a.copy( face.vertexNormals[ 0 ] );
310 vertexNormals.b.copy( face.vertexNormals[ 1 ] );
311 vertexNormals.c.copy( face.vertexNormals[ 2 ] );
312
313 }
314
315 }
316
317 // restore original normals
318
319 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
320
321 face = this.faces[ f ];
322
323 face.normal = face.__originalFaceNormal;
324 face.vertexNormals = face.__originalVertexNormals;
325
326 }
327
328 },
329
330 computeTangents: function () {
331
332 // based on http://www.terathon.com/code/tangent.html
333 // tangents go to vertices
334
335 var f, fl, v, vl, i, il, vertexIndex,
336 face, uv, vA, vB, vC, uvA, uvB, uvC,
337 x1, x2, y1, y2, z1, z2,
338 s1, s2, t1, t2, r, t, test,
339 tan1 = [], tan2 = [],
340 sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
341 tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
342 n = new THREE.Vector3(), w;
343
344 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
345
346 tan1[ v ] = new THREE.Vector3();
347 tan2[ v ] = new THREE.Vector3();
348
349 }
350
351 function handleTriangle( context, a, b, c, ua, ub, uc ) {
352
353 vA = context.vertices[ a ];
354 vB = context.vertices[ b ];
355 vC = context.vertices[ c ];
356
357 uvA = uv[ ua ];
358 uvB = uv[ ub ];
359 uvC = uv[ uc ];
360
361 x1 = vB.x - vA.x;
362 x2 = vC.x - vA.x;
363 y1 = vB.y - vA.y;
364 y2 = vC.y - vA.y;
365 z1 = vB.z - vA.z;
366 z2 = vC.z - vA.z;
367
368 s1 = uvB.x - uvA.x;
369 s2 = uvC.x - uvA.x;
370 t1 = uvB.y - uvA.y;
371 t2 = uvC.y - uvA.y;
372
373 r = 1.0 / ( s1 * t2 - s2 * t1 );
374 sdir.set( ( t2 * x1 - t1 * x2 ) * r,
375 ( t2 * y1 - t1 * y2 ) * r,
376 ( t2 * z1 - t1 * z2 ) * r );
377 tdir.set( ( s1 * x2 - s2 * x1 ) * r,
378 ( s1 * y2 - s2 * y1 ) * r,
379 ( s1 * z2 - s2 * z1 ) * r );
380
381 tan1[ a ].add( sdir );
382 tan1[ b ].add( sdir );
383 tan1[ c ].add( sdir );
384
385 tan2[ a ].add( tdir );
386 tan2[ b ].add( tdir );
387 tan2[ c ].add( tdir );
388
389 }
390
391 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
392
393 face = this.faces[ f ];
394 uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
395
396 handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
397
398 }
399
400 var faceIndex = [ 'a', 'b', 'c', 'd' ];
401
402 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
403
404 face = this.faces[ f ];
405
406 for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i++ ) {
407
408 n.copy( face.vertexNormals[ i ] );
409
410 vertexIndex = face[ faceIndex[ i ] ];
411
412 t = tan1[ vertexIndex ];
413
414 // Gram-Schmidt orthogonalize
415
416 tmp.copy( t );
417 tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
418
419 // Calculate handedness
420
421 tmp2.crossVectors( face.vertexNormals[ i ], t );
422 test = tmp2.dot( tan2[ vertexIndex ] );
423 w = (test < 0.0) ? -1.0 : 1.0;
424
425 face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
426
427 }
428
429 }
430
431 this.hasTangents = true;
432
433 },
434
435 computeLineDistances: function ( ) {
436
437 var d = 0;
438 var vertices = this.vertices;
439
440 for ( var i = 0, il = vertices.length; i < il; i ++ ) {
441
442 if ( i > 0 ) {
443
444 d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
445
446 }
447
448 this.lineDistances[ i ] = d;
449
450 }
451
452 },
453
454 computeBoundingBox: function () {
455
456 if ( this.boundingBox === null ) {
457
458 this.boundingBox = new THREE.Box3();
459
460 }
461
462 this.boundingBox.setFromPoints( this.vertices );
463
464 },
465
466 computeBoundingSphere: function () {
467
468 if ( this.boundingSphere === null ) {
469
470 this.boundingSphere = new THREE.Sphere();
471
472 }
473
474 this.boundingSphere.setFromPoints( this.vertices );
475
476 },
477
478 /*
479 * Checks for duplicate vertices with hashmap.
480 * Duplicated vertices are removed
481 * and faces' vertices are updated.
482 */
483
484 mergeVertices: function () {
485
486 var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
487 var unique = [], changes = [];
488
489 var v, key;
490 var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
491 var precision = Math.pow( 10, precisionPoints );
492 var i,il, face;
493 var indices, k, j, jl, u;
494
495 for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
496
497 v = this.vertices[ i ];
498 key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
499
500 if ( verticesMap[ key ] === undefined ) {
501
502 verticesMap[ key ] = i;
503 unique.push( this.vertices[ i ] );
504 changes[ i ] = unique.length - 1;
505
506 } else {
507
508 //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
509 changes[ i ] = changes[ verticesMap[ key ] ];
510
511 }
512
513 };
514
515
516 // if faces are completely degenerate after merging vertices, we
517 // have to remove them from the geometry.
518 var faceIndicesToRemove = [];
519
520 for( i = 0, il = this.faces.length; i < il; i ++ ) {
521
522 face = this.faces[ i ];
523
524 face.a = changes[ face.a ];
525 face.b = changes[ face.b ];
526 face.c = changes[ face.c ];
527
528 indices = [ face.a, face.b, face.c ];
529
530 var dupIndex = -1;
531
532 // if any duplicate vertices are found in a Face3
533 // we have to remove the face as nothing can be saved
534 for ( var n = 0; n < 3; n ++ ) {
535 if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
536
537 dupIndex = n;
538 faceIndicesToRemove.push( i );
539 break;
540
541 }
542 }
543
544 }
545
546 for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
547 var idx = faceIndicesToRemove[ i ];
548
549 this.faces.splice( idx, 1 );
550
551 for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
552
553 this.faceVertexUvs[ j ].splice( idx, 1 );
554
555 }
556
557 }
558
559 // Use unique set of vertices
560
561 var diff = this.vertices.length - unique.length;
562 this.vertices = unique;
563 return diff;
564
565 },
566
567 clone: function () {
568
569 var geometry = new THREE.Geometry();
570
571 var vertices = this.vertices;
572
573 for ( var i = 0, il = vertices.length; i < il; i ++ ) {
574
575 geometry.vertices.push( vertices[ i ].clone() );
576
577 }
578
579 var faces = this.faces;
580
581 for ( var i = 0, il = faces.length; i < il; i ++ ) {
582
583 geometry.faces.push( faces[ i ].clone() );
584
585 }
586
587 var uvs = this.faceVertexUvs[ 0 ];
588
589 for ( var i = 0, il = uvs.length; i < il; i ++ ) {
590
591 var uv = uvs[ i ], uvCopy = [];
592
593 for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
594
595 uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
596
597 }
598
599 geometry.faceVertexUvs[ 0 ].push( uvCopy );
600
601 }
602
603 return geometry;
604
605 },
606
607 dispose: function () {
608
609 this.dispatchEvent( { type: 'dispose' } );
610
611 }
612
613};
614
615THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
616
617THREE.GeometryIdCount = 0;
Note: See TracBrowser for help on using the repository browser.