Geometry.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  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. */
  8. THREE.Geometry = function () {
  9. this.id = THREE.GeometryLib.length;
  10. THREE.GeometryLib.push( this );
  11. this.name = '';
  12. this.vertices = [];
  13. this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon
  14. this.materials = [];
  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.boundingBox = null;
  24. this.boundingSphere = null;
  25. this.hasTangents = false;
  26. this.dynamic = true; // the intermediate typearrays will be deleted when set to false
  27. // update flags
  28. this.verticesNeedUpdate = false;
  29. this.elementsNeedUpdate = false;
  30. this.uvsNeedUpdate = false;
  31. this.normalsNeedUpdate = false;
  32. this.tangentsNeedUpdate = false;
  33. this.colorsNeedUpdate = false;
  34. };
  35. THREE.Geometry.prototype = {
  36. constructor : THREE.Geometry,
  37. applyMatrix: function ( matrix ) {
  38. var matrixRotation = new THREE.Matrix4();
  39. matrixRotation.extractRotation( matrix );
  40. for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
  41. var vertex = this.vertices[ i ];
  42. matrix.multiplyVector3( vertex );
  43. }
  44. for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
  45. var face = this.faces[ i ];
  46. matrixRotation.multiplyVector3( face.normal );
  47. for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
  48. matrixRotation.multiplyVector3( face.vertexNormals[ j ] );
  49. }
  50. matrix.multiplyVector3( face.centroid );
  51. }
  52. },
  53. computeCentroids: function () {
  54. var f, fl, face;
  55. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  56. face = this.faces[ f ];
  57. face.centroid.set( 0, 0, 0 );
  58. if ( face instanceof THREE.Face3 ) {
  59. face.centroid.addSelf( this.vertices[ face.a ] );
  60. face.centroid.addSelf( this.vertices[ face.b ] );
  61. face.centroid.addSelf( this.vertices[ face.c ] );
  62. face.centroid.divideScalar( 3 );
  63. } else if ( face instanceof THREE.Face4 ) {
  64. face.centroid.addSelf( this.vertices[ face.a ] );
  65. face.centroid.addSelf( this.vertices[ face.b ] );
  66. face.centroid.addSelf( this.vertices[ face.c ] );
  67. face.centroid.addSelf( this.vertices[ face.d ] );
  68. face.centroid.divideScalar( 4 );
  69. }
  70. }
  71. },
  72. computeFaceNormals: function () {
  73. var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
  74. cb = new THREE.Vector3(), ab = new THREE.Vector3();
  75. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  76. face = this.faces[ f ];
  77. vA = this.vertices[ face.a ];
  78. vB = this.vertices[ face.b ];
  79. vC = this.vertices[ face.c ];
  80. cb.sub( vC, vB );
  81. ab.sub( vA, vB );
  82. cb.crossSelf( ab );
  83. if ( !cb.isZero() ) {
  84. cb.normalize();
  85. }
  86. face.normal.copy( cb );
  87. }
  88. },
  89. computeVertexNormals: function () {
  90. var v, vl, f, fl, face, vertices;
  91. // create internal buffers for reuse when calling this method repeatedly
  92. // (otherwise memory allocation / deallocation every frame is big resource hog)
  93. if ( this.__tmpVertices === undefined ) {
  94. this.__tmpVertices = new Array( this.vertices.length );
  95. vertices = this.__tmpVertices;
  96. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  97. vertices[ v ] = new THREE.Vector3();
  98. }
  99. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  100. face = this.faces[ f ];
  101. if ( face instanceof THREE.Face3 ) {
  102. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  103. } else if ( face instanceof THREE.Face4 ) {
  104. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  105. }
  106. }
  107. } else {
  108. vertices = this.__tmpVertices;
  109. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  110. vertices[ v ].set( 0, 0, 0 );
  111. }
  112. }
  113. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  114. face = this.faces[ f ];
  115. if ( face instanceof THREE.Face3 ) {
  116. vertices[ face.a ].addSelf( face.normal );
  117. vertices[ face.b ].addSelf( face.normal );
  118. vertices[ face.c ].addSelf( face.normal );
  119. } else if ( face instanceof THREE.Face4 ) {
  120. vertices[ face.a ].addSelf( face.normal );
  121. vertices[ face.b ].addSelf( face.normal );
  122. vertices[ face.c ].addSelf( face.normal );
  123. vertices[ face.d ].addSelf( face.normal );
  124. }
  125. }
  126. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  127. vertices[ v ].normalize();
  128. }
  129. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  130. face = this.faces[ f ];
  131. if ( face instanceof THREE.Face3 ) {
  132. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  133. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  134. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  135. } else if ( face instanceof THREE.Face4 ) {
  136. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  137. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  138. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  139. face.vertexNormals[ 3 ].copy( vertices[ face.d ] );
  140. }
  141. }
  142. },
  143. computeMorphNormals: function () {
  144. var i, il, f, fl, face;
  145. // save original normals
  146. // - create temp variables on first access
  147. // otherwise just copy (for faster repeated calls)
  148. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  149. face = this.faces[ f ];
  150. if ( ! face.__originalFaceNormal ) {
  151. face.__originalFaceNormal = face.normal.clone();
  152. } else {
  153. face.__originalFaceNormal.copy( face.normal );
  154. }
  155. if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
  156. for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
  157. if ( ! face.__originalVertexNormals[ i ] ) {
  158. face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
  159. } else {
  160. face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
  161. }
  162. }
  163. }
  164. // use temp geometry to compute face and vertex normals for each morph
  165. var tmpGeo = new THREE.Geometry();
  166. tmpGeo.faces = this.faces;
  167. for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
  168. // create on first access
  169. if ( ! this.morphNormals[ i ] ) {
  170. this.morphNormals[ i ] = {};
  171. this.morphNormals[ i ].faceNormals = [];
  172. this.morphNormals[ i ].vertexNormals = [];
  173. var dstNormalsFace = this.morphNormals[ i ].faceNormals;
  174. var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
  175. var faceNormal, vertexNormals;
  176. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  177. face = this.faces[ f ];
  178. faceNormal = new THREE.Vector3();
  179. if ( face instanceof THREE.Face3 ) {
  180. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
  181. } else {
  182. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3(), d: new THREE.Vector3() };
  183. }
  184. dstNormalsFace.push( faceNormal );
  185. dstNormalsVertex.push( vertexNormals );
  186. }
  187. }
  188. var morphNormals = this.morphNormals[ i ];
  189. // set vertices to morph target
  190. tmpGeo.vertices = this.morphTargets[ i ].vertices;
  191. // compute morph normals
  192. tmpGeo.computeFaceNormals();
  193. tmpGeo.computeVertexNormals();
  194. // store morph normals
  195. var faceNormal, vertexNormals;
  196. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  197. face = this.faces[ f ];
  198. faceNormal = morphNormals.faceNormals[ f ];
  199. vertexNormals = morphNormals.vertexNormals[ f ];
  200. faceNormal.copy( face.normal );
  201. if ( face instanceof THREE.Face3 ) {
  202. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  203. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  204. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  205. } else {
  206. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  207. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  208. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  209. vertexNormals.d.copy( face.vertexNormals[ 3 ] );
  210. }
  211. }
  212. }
  213. // restore original normals
  214. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  215. face = this.faces[ f ];
  216. face.normal = face.__originalFaceNormal;
  217. face.vertexNormals = face.__originalVertexNormals;
  218. }
  219. },
  220. computeTangents: function () {
  221. // based on http://www.terathon.com/code/tangent.html
  222. // tangents go to vertices
  223. var f, fl, v, vl, i, il, vertexIndex,
  224. face, uv, vA, vB, vC, uvA, uvB, uvC,
  225. x1, x2, y1, y2, z1, z2,
  226. s1, s2, t1, t2, r, t, test,
  227. tan1 = [], tan2 = [],
  228. sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
  229. tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
  230. n = new THREE.Vector3(), w;
  231. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  232. tan1[ v ] = new THREE.Vector3();
  233. tan2[ v ] = new THREE.Vector3();
  234. }
  235. function handleTriangle( context, a, b, c, ua, ub, uc ) {
  236. vA = context.vertices[ a ];
  237. vB = context.vertices[ b ];
  238. vC = context.vertices[ c ];
  239. uvA = uv[ ua ];
  240. uvB = uv[ ub ];
  241. uvC = uv[ uc ];
  242. x1 = vB.x - vA.x;
  243. x2 = vC.x - vA.x;
  244. y1 = vB.y - vA.y;
  245. y2 = vC.y - vA.y;
  246. z1 = vB.z - vA.z;
  247. z2 = vC.z - vA.z;
  248. s1 = uvB.u - uvA.u;
  249. s2 = uvC.u - uvA.u;
  250. t1 = uvB.v - uvA.v;
  251. t2 = uvC.v - uvA.v;
  252. r = 1.0 / ( s1 * t2 - s2 * t1 );
  253. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  254. ( t2 * y1 - t1 * y2 ) * r,
  255. ( t2 * z1 - t1 * z2 ) * r );
  256. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  257. ( s1 * y2 - s2 * y1 ) * r,
  258. ( s1 * z2 - s2 * z1 ) * r );
  259. tan1[ a ].addSelf( sdir );
  260. tan1[ b ].addSelf( sdir );
  261. tan1[ c ].addSelf( sdir );
  262. tan2[ a ].addSelf( tdir );
  263. tan2[ b ].addSelf( tdir );
  264. tan2[ c ].addSelf( tdir );
  265. }
  266. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  267. face = this.faces[ f ];
  268. uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
  269. if ( face instanceof THREE.Face3 ) {
  270. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  271. } else if ( face instanceof THREE.Face4 ) {
  272. handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
  273. handleTriangle( this, face.b, face.c, face.d, 1, 2, 3 );
  274. }
  275. }
  276. var faceIndex = [ 'a', 'b', 'c', 'd' ];
  277. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  278. face = this.faces[ f ];
  279. for ( i = 0; i < face.vertexNormals.length; i++ ) {
  280. n.copy( face.vertexNormals[ i ] );
  281. vertexIndex = face[ faceIndex[ i ] ];
  282. t = tan1[ vertexIndex ];
  283. // Gram-Schmidt orthogonalize
  284. tmp.copy( t );
  285. tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
  286. // Calculate handedness
  287. tmp2.cross( face.vertexNormals[ i ], t );
  288. test = tmp2.dot( tan2[ vertexIndex ] );
  289. w = (test < 0.0) ? -1.0 : 1.0;
  290. face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
  291. }
  292. }
  293. this.hasTangents = true;
  294. },
  295. computeBoundingBox: function () {
  296. if ( ! this.boundingBox ) {
  297. this.boundingBox = { min: new THREE.Vector3(), max: new THREE.Vector3() };
  298. }
  299. if ( this.vertices.length > 0 ) {
  300. var position, firstPosition = this.vertices[ 0 ];
  301. this.boundingBox.min.copy( firstPosition );
  302. this.boundingBox.max.copy( firstPosition );
  303. var min = this.boundingBox.min,
  304. max = this.boundingBox.max;
  305. for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
  306. position = this.vertices[ v ];
  307. if ( position.x < min.x ) {
  308. min.x = position.x;
  309. } else if ( position.x > max.x ) {
  310. max.x = position.x;
  311. }
  312. if ( position.y < min.y ) {
  313. min.y = position.y;
  314. } else if ( position.y > max.y ) {
  315. max.y = position.y;
  316. }
  317. if ( position.z < min.z ) {
  318. min.z = position.z;
  319. } else if ( position.z > max.z ) {
  320. max.z = position.z;
  321. }
  322. }
  323. } else {
  324. this.boundingBox.min.set( 0, 0, 0 );
  325. this.boundingBox.max.set( 0, 0, 0 );
  326. }
  327. },
  328. computeBoundingSphere: function () {
  329. var maxRadiusSq = 0;
  330. if ( this.boundingSphere === null ) this.boundingSphere = { radius: 0 };
  331. for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
  332. var radiusSq = this.vertices[ i ].lengthSq();
  333. if ( radiusSq > maxRadiusSq ) maxRadiusSq = radiusSq;
  334. }
  335. this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
  336. },
  337. /*
  338. * Checks for duplicate vertices with hashmap.
  339. * Duplicated vertices are removed
  340. * and faces' vertices are updated.
  341. */
  342. mergeVertices: function () {
  343. var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
  344. var unique = [], changes = [];
  345. var v, key;
  346. var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
  347. var precision = Math.pow( 10, precisionPoints );
  348. var i,il, face;
  349. var abcd = 'abcd', o, k, j, jl, u;
  350. for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
  351. v = this.vertices[ i ];
  352. key = [ Math.round( v.x * precision ), Math.round( v.y * precision ), Math.round( v.z * precision ) ].join( '_' );
  353. if ( verticesMap[ key ] === undefined ) {
  354. verticesMap[ key ] = i;
  355. unique.push( this.vertices[ i ] );
  356. changes[ i ] = unique.length - 1;
  357. } else {
  358. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  359. changes[ i ] = changes[ verticesMap[ key ] ];
  360. }
  361. };
  362. // Start to patch face indices
  363. for( i = 0, il = this.faces.length; i < il; i ++ ) {
  364. face = this.faces[ i ];
  365. if ( face instanceof THREE.Face3 ) {
  366. face.a = changes[ face.a ];
  367. face.b = changes[ face.b ];
  368. face.c = changes[ face.c ];
  369. } else if ( face instanceof THREE.Face4 ) {
  370. face.a = changes[ face.a ];
  371. face.b = changes[ face.b ];
  372. face.c = changes[ face.c ];
  373. face.d = changes[ face.d ];
  374. // check dups in (a, b, c, d) and convert to -> face3
  375. o = [ face.a, face.b, face.c, face.d ];
  376. for ( k = 3; k > 0; k -- ) {
  377. if ( o.indexOf( face[ abcd[ k ] ] ) !== k ) {
  378. // console.log('faces', face.a, face.b, face.c, face.d, 'dup at', k);
  379. o.splice( k, 1 );
  380. this.faces[ i ] = new THREE.Face3( o[0], o[1], o[2], face.normal, face.color, face.materialIndex );
  381. for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  382. u = this.faceVertexUvs[ j ][ i ];
  383. if ( u ) u.splice( k, 1 );
  384. }
  385. this.faces[ i ].vertexColors = face.vertexColors;
  386. break;
  387. }
  388. }
  389. }
  390. }
  391. // Use unique set of vertices
  392. var diff = this.vertices.length - unique.length;
  393. this.vertices = unique;
  394. return diff;
  395. },
  396. clone: function () {
  397. // TODO
  398. }
  399. };
  400. THREE.GeometryLib = [];
粤ICP备19079148号