|
@@ -0,0 +1,664 @@
|
|
|
+/**
|
|
|
+ * @author mrdoob / http://mrdoob.com/
|
|
|
+ * @author kile / http://kile.stravaganza.org/
|
|
|
+ * @author alteredq / http://alteredqualia.com/
|
|
|
+ * @author mikael emtinger / http://gomo.se/
|
|
|
+ * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
+ * @author bhouston / http://exocortex.com
|
|
|
+ */
|
|
|
+
|
|
|
+THREE.Geometry = function () {
|
|
|
+
|
|
|
+ this.id = THREE.GeometryIdCount ++;
|
|
|
+ this.uuid = THREE.Math.generateUUID();
|
|
|
+
|
|
|
+ this.name = '';
|
|
|
+
|
|
|
+ this.vertices = [];
|
|
|
+ this.colors = []; // one-to-one vertex colors, used in ParticleSystem and Line
|
|
|
+
|
|
|
+ this.faces = [];
|
|
|
+
|
|
|
+ this.faceVertexUvs = [[]];
|
|
|
+
|
|
|
+ this.morphTargets = [];
|
|
|
+ this.morphColors = [];
|
|
|
+ this.morphNormals = [];
|
|
|
+
|
|
|
+ this.skinWeights = [];
|
|
|
+ this.skinIndices = [];
|
|
|
+
|
|
|
+ this.lineDistances = [];
|
|
|
+
|
|
|
+ this.boundingBox = null;
|
|
|
+ this.boundingSphere = null;
|
|
|
+
|
|
|
+ this.hasTangents = false;
|
|
|
+
|
|
|
+ this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
|
|
|
+
|
|
|
+ // update flags
|
|
|
+
|
|
|
+ this.verticesNeedUpdate = false;
|
|
|
+ this.elementsNeedUpdate = false;
|
|
|
+ this.uvsNeedUpdate = false;
|
|
|
+ this.normalsNeedUpdate = false;
|
|
|
+ this.tangentsNeedUpdate = false;
|
|
|
+ this.colorsNeedUpdate = false;
|
|
|
+ this.lineDistancesNeedUpdate = false;
|
|
|
+
|
|
|
+ this.buffersNeedUpdate = false;
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+THREE.Geometry.prototype = {
|
|
|
+
|
|
|
+ constructor: THREE.Geometry,
|
|
|
+
|
|
|
+ applyMatrix: function ( matrix ) {
|
|
|
+
|
|
|
+ var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
|
|
|
+
|
|
|
+ for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ var vertex = this.vertices[ i ];
|
|
|
+ vertex.applyMatrix4( matrix );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ var face = this.faces[ i ];
|
|
|
+ face.normal.applyMatrix3( normalMatrix ).normalize();
|
|
|
+
|
|
|
+ for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
|
|
|
+
|
|
|
+ face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( this.boundingBox instanceof THREE.Box3 ) {
|
|
|
+
|
|
|
+ this.computeBoundingBox();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( this.boundingSphere instanceof THREE.Sphere ) {
|
|
|
+
|
|
|
+ this.computeBoundingSphere();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeFaceNormals: function () {
|
|
|
+
|
|
|
+ var cb = new THREE.Vector3(), ab = new THREE.Vector3();
|
|
|
+
|
|
|
+ for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ var face = this.faces[ f ];
|
|
|
+
|
|
|
+ var vA = this.vertices[ face.a ];
|
|
|
+ var vB = this.vertices[ face.b ];
|
|
|
+ var vC = this.vertices[ face.c ];
|
|
|
+
|
|
|
+ cb.subVectors( vC, vB );
|
|
|
+ ab.subVectors( vA, vB );
|
|
|
+ cb.cross( ab );
|
|
|
+
|
|
|
+ cb.normalize();
|
|
|
+
|
|
|
+ face.normal.copy( cb );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeVertexNormals: function ( areaWeighted ) {
|
|
|
+
|
|
|
+ var v, vl, f, fl, face, vertices;
|
|
|
+
|
|
|
+ vertices = new Array( this.vertices.length );
|
|
|
+
|
|
|
+ for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
|
|
|
+
|
|
|
+ vertices[ v ] = new THREE.Vector3();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( areaWeighted ) {
|
|
|
+
|
|
|
+ // vertex normals weighted by triangle areas
|
|
|
+ // http://www.iquilezles.org/www/articles/normals/normals.htm
|
|
|
+
|
|
|
+ var vA, vB, vC, vD;
|
|
|
+ var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
|
|
|
+ db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+
|
|
|
+ vA = this.vertices[ face.a ];
|
|
|
+ vB = this.vertices[ face.b ];
|
|
|
+ vC = this.vertices[ face.c ];
|
|
|
+
|
|
|
+ cb.subVectors( vC, vB );
|
|
|
+ ab.subVectors( vA, vB );
|
|
|
+ cb.cross( ab );
|
|
|
+
|
|
|
+ vertices[ face.a ].add( cb );
|
|
|
+ vertices[ face.b ].add( cb );
|
|
|
+ vertices[ face.c ].add( cb );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+
|
|
|
+ vertices[ face.a ].add( face.normal );
|
|
|
+ vertices[ face.b ].add( face.normal );
|
|
|
+ vertices[ face.c ].add( 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 ];
|
|
|
+
|
|
|
+ face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
|
|
|
+ face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
|
|
|
+ face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeMorphNormals: function () {
|
|
|
+
|
|
|
+ var i, il, f, fl, face;
|
|
|
+
|
|
|
+ // save original normals
|
|
|
+ // - create temp variables on first access
|
|
|
+ // otherwise just copy (for faster repeated calls)
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+
|
|
|
+ if ( ! face.__originalFaceNormal ) {
|
|
|
+
|
|
|
+ face.__originalFaceNormal = face.normal.clone();
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ face.__originalFaceNormal.copy( face.normal );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
|
|
|
+
|
|
|
+ for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ if ( ! face.__originalVertexNormals[ i ] ) {
|
|
|
+
|
|
|
+ face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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 ++ ) {
|
|
|
+
|
|
|
+ // 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();
|
|
|
+ vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
|
|
|
+
|
|
|
+ dstNormalsFace.push( faceNormal );
|
|
|
+ dstNormalsVertex.push( vertexNormals );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 );
|
|
|
+
|
|
|
+ vertexNormals.a.copy( face.vertexNormals[ 0 ] );
|
|
|
+ vertexNormals.b.copy( face.vertexNormals[ 1 ] );
|
|
|
+ vertexNormals.c.copy( face.vertexNormals[ 2 ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // restore original normals
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+
|
|
|
+ face.normal = face.__originalFaceNormal;
|
|
|
+ face.vertexNormals = face.__originalVertexNormals;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeTangents: function () {
|
|
|
+
|
|
|
+ // based on http://www.terathon.com/code/tangent.html
|
|
|
+ // tangents go to vertices
|
|
|
+
|
|
|
+ var f, fl, v, vl, i, il, vertexIndex,
|
|
|
+ face, uv, vA, vB, vC, uvA, uvB, uvC,
|
|
|
+ x1, x2, y1, y2, z1, z2,
|
|
|
+ s1, s2, t1, t2, r, t, test,
|
|
|
+ tan1 = [], tan2 = [],
|
|
|
+ sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
|
|
|
+ tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
|
|
|
+ n = new THREE.Vector3(), w;
|
|
|
+
|
|
|
+ for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
|
|
|
+
|
|
|
+ tan1[ v ] = new THREE.Vector3();
|
|
|
+ tan2[ v ] = new THREE.Vector3();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleTriangle( context, a, b, c, ua, ub, uc ) {
|
|
|
+
|
|
|
+ vA = context.vertices[ a ];
|
|
|
+ vB = context.vertices[ b ];
|
|
|
+ vC = context.vertices[ c ];
|
|
|
+
|
|
|
+ uvA = uv[ ua ];
|
|
|
+ uvB = uv[ ub ];
|
|
|
+ uvC = uv[ uc ];
|
|
|
+
|
|
|
+ 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.x - uvA.x;
|
|
|
+ s2 = uvC.x - uvA.x;
|
|
|
+ t1 = uvB.y - uvA.y;
|
|
|
+ t2 = uvC.y - uvA.y;
|
|
|
+
|
|
|
+ r = 1.0 / ( s1 * t2 - s2 * t1 );
|
|
|
+ sdir.set( ( t2 * x1 - t1 * x2 ) * r,
|
|
|
+ ( t2 * y1 - t1 * y2 ) * r,
|
|
|
+ ( t2 * z1 - t1 * z2 ) * r );
|
|
|
+ tdir.set( ( s1 * x2 - s2 * x1 ) * r,
|
|
|
+ ( s1 * y2 - s2 * y1 ) * r,
|
|
|
+ ( s1 * z2 - s2 * z1 ) * r );
|
|
|
+
|
|
|
+ tan1[ a ].add( sdir );
|
|
|
+ tan1[ b ].add( sdir );
|
|
|
+ tan1[ c ].add( sdir );
|
|
|
+
|
|
|
+ tan2[ a ].add( tdir );
|
|
|
+ tan2[ b ].add( tdir );
|
|
|
+ tan2[ c ].add( tdir );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+ uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
|
|
|
+
|
|
|
+ handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var faceIndex = [ 'a', 'b', 'c', 'd' ];
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+
|
|
|
+ for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i++ ) {
|
|
|
+
|
|
|
+ n.copy( face.vertexNormals[ i ] );
|
|
|
+
|
|
|
+ vertexIndex = face[ faceIndex[ i ] ];
|
|
|
+
|
|
|
+ t = tan1[ vertexIndex ];
|
|
|
+
|
|
|
+ // Gram-Schmidt orthogonalize
|
|
|
+
|
|
|
+ tmp.copy( t );
|
|
|
+ tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
|
|
|
+
|
|
|
+ // Calculate handedness
|
|
|
+
|
|
|
+ tmp2.crossVectors( face.vertexNormals[ i ], t );
|
|
|
+ test = tmp2.dot( tan2[ vertexIndex ] );
|
|
|
+ w = (test < 0.0) ? -1.0 : 1.0;
|
|
|
+
|
|
|
+ face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.hasTangents = true;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeLineDistances: function ( ) {
|
|
|
+
|
|
|
+ var d = 0;
|
|
|
+ var vertices = this.vertices;
|
|
|
+
|
|
|
+ for ( var i = 0, il = vertices.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ if ( i > 0 ) {
|
|
|
+
|
|
|
+ d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.lineDistances[ i ] = d;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeBoundingBox: function () {
|
|
|
+
|
|
|
+ if ( this.boundingBox === null ) {
|
|
|
+
|
|
|
+ this.boundingBox = new THREE.Box3();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.boundingBox.setFromPoints( this.vertices );
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ computeBoundingSphere: function () {
|
|
|
+
|
|
|
+ if ( this.boundingSphere === null ) {
|
|
|
+
|
|
|
+ this.boundingSphere = new THREE.Sphere();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.boundingSphere.setFromPoints( this.vertices );
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Checks for duplicate vertices with hashmap.
|
|
|
+ * Duplicated vertices are removed
|
|
|
+ * and faces' vertices are updated.
|
|
|
+ */
|
|
|
+
|
|
|
+ mergeVertices: function () {
|
|
|
+
|
|
|
+ var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
|
|
|
+ var unique = [], changes = [];
|
|
|
+
|
|
|
+ var v, key;
|
|
|
+ var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
|
|
|
+ var precision = Math.pow( 10, precisionPoints );
|
|
|
+ var i,il, face;
|
|
|
+ var indices, k, j, jl, u;
|
|
|
+
|
|
|
+ for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ v = this.vertices[ i ];
|
|
|
+ key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
|
|
|
+
|
|
|
+ if ( verticesMap[ key ] === undefined ) {
|
|
|
+
|
|
|
+ verticesMap[ key ] = i;
|
|
|
+ unique.push( this.vertices[ i ] );
|
|
|
+ changes[ i ] = unique.length - 1;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
|
|
|
+ changes[ i ] = changes[ verticesMap[ key ] ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ // if faces are completely degenerate after merging vertices, we
|
|
|
+ // have to remove them from the geometry.
|
|
|
+ var faceIndicesToRemove = [];
|
|
|
+
|
|
|
+ for( i = 0, il = this.faces.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ i ];
|
|
|
+
|
|
|
+ face.a = changes[ face.a ];
|
|
|
+ face.b = changes[ face.b ];
|
|
|
+ face.c = changes[ face.c ];
|
|
|
+
|
|
|
+ indices = [ face.a, face.b, face.c ];
|
|
|
+
|
|
|
+ var dupIndex = -1;
|
|
|
+
|
|
|
+ // if any duplicate vertices are found in a Face3
|
|
|
+ // we have to remove the face as nothing can be saved
|
|
|
+ for ( var n = 0; n < 3; n ++ ) {
|
|
|
+ if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
|
|
|
+
|
|
|
+ dupIndex = n;
|
|
|
+ faceIndicesToRemove.push( i );
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
|
|
|
+ var idx = faceIndicesToRemove[ i ];
|
|
|
+
|
|
|
+ this.faces.splice( idx, 1 );
|
|
|
+
|
|
|
+ for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
|
|
|
+
|
|
|
+ this.faceVertexUvs[ j ].splice( idx, 1 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // Use unique set of vertices
|
|
|
+
|
|
|
+ var diff = this.vertices.length - unique.length;
|
|
|
+ this.vertices = unique;
|
|
|
+ return diff;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // Geometry splitting
|
|
|
+
|
|
|
+ makeGroups: ( function () {
|
|
|
+
|
|
|
+ var geometryGroupCounter = 0;
|
|
|
+
|
|
|
+ return function ( usesFaceMaterial, maxVerticesInGroup ) {
|
|
|
+
|
|
|
+ var f, fl, face, materialIndex,
|
|
|
+ groupHash, hash_map = {};
|
|
|
+
|
|
|
+ var numMorphTargets = this.morphTargets.length;
|
|
|
+ var numMorphNormals = this.morphNormals.length;
|
|
|
+
|
|
|
+ this.geometryGroups = {};
|
|
|
+
|
|
|
+ for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
|
|
+
|
|
|
+ face = this.faces[ f ];
|
|
|
+ materialIndex = usesFaceMaterial ? face.materialIndex : 0;
|
|
|
+
|
|
|
+ if ( ! ( materialIndex in hash_map ) ) {
|
|
|
+
|
|
|
+ hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
|
|
|
+
|
|
|
+ if ( ! ( groupHash in this.geometryGroups ) ) {
|
|
|
+
|
|
|
+ this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( this.geometryGroups[ groupHash ].vertices + 3 > maxVerticesInGroup ) {
|
|
|
+
|
|
|
+ hash_map[ materialIndex ].counter += 1;
|
|
|
+ groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
|
|
|
+
|
|
|
+ if ( ! ( groupHash in this.geometryGroups ) ) {
|
|
|
+
|
|
|
+ this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.geometryGroups[ groupHash ].faces3.push( f );
|
|
|
+ this.geometryGroups[ groupHash ].vertices += 3;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.geometryGroupsList = [];
|
|
|
+
|
|
|
+ for ( var g in this.geometryGroups ) {
|
|
|
+
|
|
|
+ this.geometryGroups[ g ].id = geometryGroupCounter ++;
|
|
|
+
|
|
|
+ this.geometryGroupsList.push( this.geometryGroups[ g ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ } )(),
|
|
|
+
|
|
|
+ clone: function () {
|
|
|
+
|
|
|
+ var geometry = new THREE.Geometry();
|
|
|
+
|
|
|
+ var vertices = this.vertices;
|
|
|
+
|
|
|
+ for ( var i = 0, il = vertices.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ geometry.vertices.push( vertices[ i ].clone() );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var faces = this.faces;
|
|
|
+
|
|
|
+ for ( var i = 0, il = faces.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ geometry.faces.push( faces[ i ].clone() );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var uvs = this.faceVertexUvs[ 0 ];
|
|
|
+
|
|
|
+ for ( var i = 0, il = uvs.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ var uv = uvs[ i ], uvCopy = [];
|
|
|
+
|
|
|
+ for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
|
|
|
+
|
|
|
+ uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ geometry.faceVertexUvs[ 0 ].push( uvCopy );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return geometry;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ dispose: function () {
|
|
|
+
|
|
|
+ this.dispatchEvent( { type: 'dispose' } );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
|
|
|
+
|
|
|
+THREE.GeometryIdCount = 0;
|