Geometry.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  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. THREE.Geometry = function () {
  10. this.id = THREE.Math.generateUUID();
  11. this.name = '';
  12. this.vertices = [];
  13. this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon
  14. this.normals = []; // one-to-one vertex normals, used in Ribbon
  15. this.faces = [];
  16. this.faceUvs = [[]];
  17. this.faceVertexUvs = [[]];
  18. this.morphTargets = [];
  19. this.morphColors = [];
  20. this.morphNormals = [];
  21. this.skinWeights = [];
  22. this.skinIndices = [];
  23. this.lineDistances = [];
  24. this.boundingBox = null;
  25. this.boundingSphere = null;
  26. this.hasTangents = false;
  27. this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
  28. // update flags
  29. this.verticesNeedUpdate = false;
  30. this.elementsNeedUpdate = false;
  31. this.uvsNeedUpdate = false;
  32. this.normalsNeedUpdate = false;
  33. this.tangentsNeedUpdate = false;
  34. this.colorsNeedUpdate = false;
  35. this.lineDistancesNeedUpdate = false;
  36. this.buffersNeedUpdate = false;
  37. };
  38. THREE.Geometry.prototype = {
  39. constructor: THREE.Geometry,
  40. addEventListener: THREE.EventDispatcher.prototype.addEventListener,
  41. hasEventListener: THREE.EventDispatcher.prototype.hasEventListener,
  42. removeEventListener: THREE.EventDispatcher.prototype.removeEventListener,
  43. dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent,
  44. applyMatrix: function ( matrix ) {
  45. var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
  46. for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
  47. var vertex = this.vertices[ i ];
  48. vertex.applyMatrix4( matrix );
  49. }
  50. for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
  51. var face = this.faces[ i ];
  52. face.normal.applyMatrix3( normalMatrix ).normalize();
  53. for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
  54. face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
  55. }
  56. face.centroid.applyMatrix4( matrix );
  57. }
  58. if ( this.boundingBox instanceof THREE.Box3 ) {
  59. this.computeBoundingBox();
  60. }
  61. if ( this.boundingSphere instanceof THREE.Sphere ) {
  62. this.computeBoundingSphere();
  63. }
  64. },
  65. computeCentroids: function () {
  66. var f, fl, face;
  67. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  68. face = this.faces[ f ];
  69. face.centroid.set( 0, 0, 0 );
  70. if ( face instanceof THREE.Face3 ) {
  71. face.centroid.add( this.vertices[ face.a ] );
  72. face.centroid.add( this.vertices[ face.b ] );
  73. face.centroid.add( this.vertices[ face.c ] );
  74. face.centroid.divideScalar( 3 );
  75. } else if ( face instanceof THREE.Face4 ) {
  76. face.centroid.add( this.vertices[ face.a ] );
  77. face.centroid.add( this.vertices[ face.b ] );
  78. face.centroid.add( this.vertices[ face.c ] );
  79. face.centroid.add( this.vertices[ face.d ] );
  80. face.centroid.divideScalar( 4 );
  81. }
  82. }
  83. },
  84. computeFaceNormals: function () {
  85. var cb = new THREE.Vector3(), ab = new THREE.Vector3();
  86. for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
  87. var face = this.faces[ f ];
  88. var vA = this.vertices[ face.a ];
  89. var vB = this.vertices[ face.b ];
  90. var vC = this.vertices[ face.c ];
  91. cb.subVectors( vC, vB );
  92. ab.subVectors( vA, vB );
  93. cb.cross( ab );
  94. cb.normalize();
  95. face.normal.copy( cb );
  96. }
  97. },
  98. computeVertexNormals: function ( areaWeighted ) {
  99. var v, vl, f, fl, face, vertices;
  100. // create internal buffers for reuse when calling this method repeatedly
  101. // (otherwise memory allocation / deallocation every frame is big resource hog)
  102. if ( this.__tmpVertices === undefined ) {
  103. this.__tmpVertices = new Array( this.vertices.length );
  104. vertices = this.__tmpVertices;
  105. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  106. vertices[ v ] = new THREE.Vector3();
  107. }
  108. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  109. face = this.faces[ f ];
  110. if ( face instanceof THREE.Face3 ) {
  111. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  112. } else if ( face instanceof THREE.Face4 ) {
  113. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  114. }
  115. }
  116. } else {
  117. vertices = this.__tmpVertices;
  118. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  119. vertices[ v ].set( 0, 0, 0 );
  120. }
  121. }
  122. if ( areaWeighted ) {
  123. // vertex normals weighted by triangle areas
  124. // http://www.iquilezles.org/www/articles/normals/normals.htm
  125. var vA, vB, vC, vD;
  126. var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
  127. db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
  128. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  129. face = this.faces[ f ];
  130. if ( face instanceof THREE.Face3 ) {
  131. vA = this.vertices[ face.a ];
  132. vB = this.vertices[ face.b ];
  133. vC = this.vertices[ face.c ];
  134. cb.subVectors( vC, vB );
  135. ab.subVectors( vA, vB );
  136. cb.cross( ab );
  137. vertices[ face.a ].add( cb );
  138. vertices[ face.b ].add( cb );
  139. vertices[ face.c ].add( cb );
  140. } else if ( face instanceof THREE.Face4 ) {
  141. vA = this.vertices[ face.a ];
  142. vB = this.vertices[ face.b ];
  143. vC = this.vertices[ face.c ];
  144. vD = this.vertices[ face.d ];
  145. // abd
  146. db.subVectors( vD, vB );
  147. ab.subVectors( vA, vB );
  148. db.cross( ab );
  149. vertices[ face.a ].add( db );
  150. vertices[ face.b ].add( db );
  151. vertices[ face.d ].add( db );
  152. // bcd
  153. dc.subVectors( vD, vC );
  154. bc.subVectors( vB, vC );
  155. dc.cross( bc );
  156. vertices[ face.b ].add( dc );
  157. vertices[ face.c ].add( dc );
  158. vertices[ face.d ].add( dc );
  159. }
  160. }
  161. } else {
  162. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  163. face = this.faces[ f ];
  164. if ( face instanceof THREE.Face3 ) {
  165. vertices[ face.a ].add( face.normal );
  166. vertices[ face.b ].add( face.normal );
  167. vertices[ face.c ].add( face.normal );
  168. } else if ( face instanceof THREE.Face4 ) {
  169. vertices[ face.a ].add( face.normal );
  170. vertices[ face.b ].add( face.normal );
  171. vertices[ face.c ].add( face.normal );
  172. vertices[ face.d ].add( face.normal );
  173. }
  174. }
  175. }
  176. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  177. vertices[ v ].normalize();
  178. }
  179. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  180. face = this.faces[ f ];
  181. if ( face instanceof THREE.Face3 ) {
  182. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  183. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  184. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  185. } else if ( face instanceof THREE.Face4 ) {
  186. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  187. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  188. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  189. face.vertexNormals[ 3 ].copy( vertices[ face.d ] );
  190. }
  191. }
  192. },
  193. computeMorphNormals: function () {
  194. var i, il, f, fl, face;
  195. // save original normals
  196. // - create temp variables on first access
  197. // otherwise just copy (for faster repeated calls)
  198. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  199. face = this.faces[ f ];
  200. if ( ! face.__originalFaceNormal ) {
  201. face.__originalFaceNormal = face.normal.clone();
  202. } else {
  203. face.__originalFaceNormal.copy( face.normal );
  204. }
  205. if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
  206. for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
  207. if ( ! face.__originalVertexNormals[ i ] ) {
  208. face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
  209. } else {
  210. face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
  211. }
  212. }
  213. }
  214. // use temp geometry to compute face and vertex normals for each morph
  215. var tmpGeo = new THREE.Geometry();
  216. tmpGeo.faces = this.faces;
  217. for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
  218. // create on first access
  219. if ( ! this.morphNormals[ i ] ) {
  220. this.morphNormals[ i ] = {};
  221. this.morphNormals[ i ].faceNormals = [];
  222. this.morphNormals[ i ].vertexNormals = [];
  223. var dstNormalsFace = this.morphNormals[ i ].faceNormals;
  224. var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
  225. var faceNormal, vertexNormals;
  226. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  227. face = this.faces[ f ];
  228. faceNormal = new THREE.Vector3();
  229. if ( face instanceof THREE.Face3 ) {
  230. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
  231. } else {
  232. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3(), d: new THREE.Vector3() };
  233. }
  234. dstNormalsFace.push( faceNormal );
  235. dstNormalsVertex.push( vertexNormals );
  236. }
  237. }
  238. var morphNormals = this.morphNormals[ i ];
  239. // set vertices to morph target
  240. tmpGeo.vertices = this.morphTargets[ i ].vertices;
  241. // compute morph normals
  242. tmpGeo.computeFaceNormals();
  243. tmpGeo.computeVertexNormals();
  244. // store morph normals
  245. var faceNormal, vertexNormals;
  246. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  247. face = this.faces[ f ];
  248. faceNormal = morphNormals.faceNormals[ f ];
  249. vertexNormals = morphNormals.vertexNormals[ f ];
  250. faceNormal.copy( face.normal );
  251. if ( face instanceof THREE.Face3 ) {
  252. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  253. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  254. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  255. } else {
  256. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  257. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  258. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  259. vertexNormals.d.copy( face.vertexNormals[ 3 ] );
  260. }
  261. }
  262. }
  263. // restore original normals
  264. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  265. face = this.faces[ f ];
  266. face.normal = face.__originalFaceNormal;
  267. face.vertexNormals = face.__originalVertexNormals;
  268. }
  269. },
  270. computeTangents: function () {
  271. // based on http://www.terathon.com/code/tangent.html
  272. // tangents go to vertices
  273. var f, fl, v, vl, i, il, vertexIndex,
  274. face, uv, vA, vB, vC, uvA, uvB, uvC,
  275. x1, x2, y1, y2, z1, z2,
  276. s1, s2, t1, t2, r, t, test,
  277. tan1 = [], tan2 = [],
  278. sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
  279. tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
  280. n = new THREE.Vector3(), w;
  281. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  282. tan1[ v ] = new THREE.Vector3();
  283. tan2[ v ] = new THREE.Vector3();
  284. }
  285. function handleTriangle( context, a, b, c, ua, ub, uc ) {
  286. vA = context.vertices[ a ];
  287. vB = context.vertices[ b ];
  288. vC = context.vertices[ c ];
  289. uvA = uv[ ua ];
  290. uvB = uv[ ub ];
  291. uvC = uv[ uc ];
  292. x1 = vB.x - vA.x;
  293. x2 = vC.x - vA.x;
  294. y1 = vB.y - vA.y;
  295. y2 = vC.y - vA.y;
  296. z1 = vB.z - vA.z;
  297. z2 = vC.z - vA.z;
  298. s1 = uvB.x - uvA.x;
  299. s2 = uvC.x - uvA.x;
  300. t1 = uvB.y - uvA.y;
  301. t2 = uvC.y - uvA.y;
  302. r = 1.0 / ( s1 * t2 - s2 * t1 );
  303. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  304. ( t2 * y1 - t1 * y2 ) * r,
  305. ( t2 * z1 - t1 * z2 ) * r );
  306. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  307. ( s1 * y2 - s2 * y1 ) * r,
  308. ( s1 * z2 - s2 * z1 ) * r );
  309. tan1[ a ].add( sdir );
  310. tan1[ b ].add( sdir );
  311. tan1[ c ].add( sdir );
  312. tan2[ a ].add( tdir );
  313. tan2[ b ].add( tdir );
  314. tan2[ c ].add( tdir );
  315. }
  316. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  317. face = this.faces[ f ];
  318. uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
  319. if ( face instanceof THREE.Face3 ) {
  320. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  321. } else if ( face instanceof THREE.Face4 ) {
  322. handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
  323. handleTriangle( this, face.b, face.c, face.d, 1, 2, 3 );
  324. }
  325. }
  326. var faceIndex = [ 'a', 'b', 'c', 'd' ];
  327. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  328. face = this.faces[ f ];
  329. for ( i = 0; i < face.vertexNormals.length; i++ ) {
  330. n.copy( face.vertexNormals[ i ] );
  331. vertexIndex = face[ faceIndex[ i ] ];
  332. t = tan1[ vertexIndex ];
  333. // Gram-Schmidt orthogonalize
  334. tmp.copy( t );
  335. tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
  336. // Calculate handedness
  337. tmp2.crossVectors( face.vertexNormals[ i ], t );
  338. test = tmp2.dot( tan2[ vertexIndex ] );
  339. w = (test < 0.0) ? -1.0 : 1.0;
  340. face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
  341. }
  342. }
  343. this.hasTangents = true;
  344. },
  345. computeLineDistances: function ( ) {
  346. var d = 0;
  347. var vertices = this.vertices;
  348. for ( var i = 0, il = vertices.length; i < il; i ++ ) {
  349. if ( i > 0 ) {
  350. d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
  351. }
  352. this.lineDistances[ i ] = d;
  353. }
  354. },
  355. computeBoundingBox: function () {
  356. if ( this.boundingBox === null ) {
  357. this.boundingBox = new THREE.Box3();
  358. }
  359. this.boundingBox.setFromPoints( this.vertices );
  360. },
  361. computeBoundingSphere: function () {
  362. if ( this.boundingSphere === null ) {
  363. this.boundingSphere = new THREE.Sphere();
  364. }
  365. this.boundingSphere.setFromPoints( this.vertices );
  366. },
  367. /*
  368. * Checks for duplicate vertices with hashmap.
  369. * Duplicated vertices are removed
  370. * and faces' vertices are updated.
  371. */
  372. mergeVertices: function () {
  373. var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
  374. var unique = [], changes = [];
  375. var v, key;
  376. var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
  377. var precision = Math.pow( 10, precisionPoints );
  378. var i,il, face;
  379. var indices, k, j, jl, u;
  380. // reset cache of vertices as it now will be changing.
  381. this.__tmpVertices = undefined;
  382. for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
  383. v = this.vertices[ i ];
  384. key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
  385. if ( verticesMap[ key ] === undefined ) {
  386. verticesMap[ key ] = i;
  387. unique.push( this.vertices[ i ] );
  388. changes[ i ] = unique.length - 1;
  389. } else {
  390. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  391. changes[ i ] = changes[ verticesMap[ key ] ];
  392. }
  393. };
  394. // if faces are completely degenerate after merging vertices, we
  395. // have to remove them from the geometry.
  396. var faceIndicesToRemove = [];
  397. for( i = 0, il = this.faces.length; i < il; i ++ ) {
  398. face = this.faces[ i ];
  399. if ( face instanceof THREE.Face3 ) {
  400. face.a = changes[ face.a ];
  401. face.b = changes[ face.b ];
  402. face.c = changes[ face.c ];
  403. indices = [ face.a, face.b, face.c ];
  404. var dupIndex = -1;
  405. // if any duplicate vertices are found in a Face3
  406. // we have to remove the face as nothing can be saved
  407. for ( var n = 0; n < 3; n ++ ) {
  408. if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
  409. dupIndex = n;
  410. faceIndicesToRemove.push( i );
  411. break;
  412. }
  413. }
  414. } else if ( face instanceof THREE.Face4 ) {
  415. face.a = changes[ face.a ];
  416. face.b = changes[ face.b ];
  417. face.c = changes[ face.c ];
  418. face.d = changes[ face.d ];
  419. // check dups in (a, b, c, d) and convert to -> face3
  420. indices = [ face.a, face.b, face.c, face.d ];
  421. var dupIndex = -1;
  422. for ( var n = 0; n < 4; n ++ ) {
  423. if ( indices[ n ] == indices[ ( n + 1 ) % 4 ] ) {
  424. // if more than one duplicated vertex is found
  425. // we can't generate any valid Face3's, thus
  426. // we need to remove this face complete.
  427. if ( dupIndex >= 0 ) {
  428. faceIndicesToRemove.push( i );
  429. }
  430. dupIndex = n;
  431. }
  432. }
  433. if ( dupIndex >= 0 ) {
  434. indices.splice( dupIndex, 1 );
  435. var newFace = new THREE.Face3( indices[0], indices[1], indices[2], face.normal, face.color, face.materialIndex );
  436. for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  437. u = this.faceVertexUvs[ j ][ i ];
  438. if ( u ) {
  439. u.splice( dupIndex, 1 );
  440. }
  441. }
  442. if( face.vertexNormals && face.vertexNormals.length > 0) {
  443. newFace.vertexNormals = face.vertexNormals;
  444. newFace.vertexNormals.splice( dupIndex, 1 );
  445. }
  446. if( face.vertexColors && face.vertexColors.length > 0 ) {
  447. newFace.vertexColors = face.vertexColors;
  448. newFace.vertexColors.splice( dupIndex, 1 );
  449. }
  450. this.faces[ i ] = newFace;
  451. }
  452. }
  453. }
  454. for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
  455. this.faces.splice( i, 1 );
  456. for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  457. this.faceVertexUvs[ j ].splice( i, 1 );
  458. }
  459. }
  460. // Use unique set of vertices
  461. var diff = this.vertices.length - unique.length;
  462. this.vertices = unique;
  463. return diff;
  464. },
  465. clone: function () {
  466. var geometry = new THREE.Geometry();
  467. var vertices = this.vertices;
  468. for ( var i = 0, il = vertices.length; i < il; i ++ ) {
  469. geometry.vertices.push( vertices[ i ].clone() );
  470. }
  471. var faces = this.faces;
  472. for ( var i = 0, il = faces.length; i < il; i ++ ) {
  473. geometry.faces.push( faces[ i ].clone() );
  474. }
  475. var uvs = this.faceVertexUvs[ 0 ];
  476. for ( var i = 0, il = uvs.length; i < il; i ++ ) {
  477. var uv = uvs[ i ], uvCopy = [];
  478. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  479. uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
  480. }
  481. geometry.faceVertexUvs[ 0 ].push( uvCopy );
  482. }
  483. return geometry;
  484. },
  485. dispose: function () {
  486. this.dispatchEvent( { type: 'dispose' } );
  487. }
  488. };
粤ICP备19079148号