Geometry.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /**
  2. * @author mr.doob / 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.GeometryCount ++;
  10. this.vertices = [];
  11. this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon
  12. this.materials = [];
  13. this.faces = [];
  14. this.faceUvs = [[]];
  15. this.faceVertexUvs = [[]];
  16. this.morphTargets = [];
  17. this.morphColors = [];
  18. this.skinWeights = [];
  19. this.skinIndices = [];
  20. this.boundingBox = null;
  21. this.boundingSphere = null;
  22. this.hasTangents = false;
  23. this.dynamic = false; // unless set to true the *Arrays will be deleted once sent to a buffer.
  24. };
  25. THREE.Geometry.prototype = {
  26. constructor : THREE.Geometry,
  27. applyMatrix: function ( matrix ) {
  28. var matrixRotation = new THREE.Matrix4();
  29. matrixRotation.extractRotation( matrix, new THREE.Vector3( 1, 1, 1 ) );
  30. for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
  31. var vertex = this.vertices[ i ];
  32. matrix.multiplyVector3( vertex.position );
  33. }
  34. for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
  35. var face = this.faces[ i ];
  36. matrixRotation.multiplyVector3( face.normal );
  37. for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
  38. matrixRotation.multiplyVector3( face.vertexNormals[ j ] );
  39. }
  40. matrix.multiplyVector3( face.centroid );
  41. }
  42. },
  43. computeCentroids: function () {
  44. var f, fl, face;
  45. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  46. face = this.faces[ f ];
  47. face.centroid.set( 0, 0, 0 );
  48. if ( face instanceof THREE.Face3 ) {
  49. face.centroid.addSelf( this.vertices[ face.a ].position );
  50. face.centroid.addSelf( this.vertices[ face.b ].position );
  51. face.centroid.addSelf( this.vertices[ face.c ].position );
  52. face.centroid.divideScalar( 3 );
  53. } else if ( face instanceof THREE.Face4 ) {
  54. face.centroid.addSelf( this.vertices[ face.a ].position );
  55. face.centroid.addSelf( this.vertices[ face.b ].position );
  56. face.centroid.addSelf( this.vertices[ face.c ].position );
  57. face.centroid.addSelf( this.vertices[ face.d ].position );
  58. face.centroid.divideScalar( 4 );
  59. }
  60. }
  61. },
  62. computeFaceNormals: function () {
  63. var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
  64. cb = new THREE.Vector3(), ab = new THREE.Vector3();
  65. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  66. face = this.faces[ f ];
  67. vA = this.vertices[ face.a ];
  68. vB = this.vertices[ face.b ];
  69. vC = this.vertices[ face.c ];
  70. cb.sub( vC.position, vB.position );
  71. ab.sub( vA.position, vB.position );
  72. cb.crossSelf( ab );
  73. if ( !cb.isZero() ) {
  74. cb.normalize();
  75. }
  76. face.normal.copy( cb );
  77. }
  78. },
  79. computeVertexNormals: function () {
  80. var v, vl, f, fl, face, vertices;
  81. // create internal buffers for reuse when calling this method repeatedly
  82. // (otherwise memory allocation / deallocation every frame is big resource hog)
  83. if ( this.__tmpVertices === undefined ) {
  84. this.__tmpVertices = new Array( this.vertices.length );
  85. vertices = this.__tmpVertices;
  86. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  87. vertices[ v ] = new THREE.Vector3();
  88. }
  89. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  90. face = this.faces[ f ];
  91. if ( face instanceof THREE.Face3 ) {
  92. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  93. } else if ( face instanceof THREE.Face4 ) {
  94. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  95. }
  96. }
  97. } else {
  98. vertices = this.__tmpVertices;
  99. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  100. vertices[ v ].set( 0, 0, 0 );
  101. }
  102. }
  103. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  104. face = this.faces[ f ];
  105. if ( face instanceof THREE.Face3 ) {
  106. vertices[ face.a ].addSelf( face.normal );
  107. vertices[ face.b ].addSelf( face.normal );
  108. vertices[ face.c ].addSelf( face.normal );
  109. } else if ( face instanceof THREE.Face4 ) {
  110. vertices[ face.a ].addSelf( face.normal );
  111. vertices[ face.b ].addSelf( face.normal );
  112. vertices[ face.c ].addSelf( face.normal );
  113. vertices[ face.d ].addSelf( face.normal );
  114. }
  115. }
  116. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  117. vertices[ v ].normalize();
  118. }
  119. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  120. face = this.faces[ f ];
  121. if ( face instanceof THREE.Face3 ) {
  122. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  123. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  124. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  125. } else if ( face instanceof THREE.Face4 ) {
  126. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  127. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  128. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  129. face.vertexNormals[ 3 ].copy( vertices[ face.d ] );
  130. }
  131. }
  132. },
  133. computeTangents: function () {
  134. // based on http://www.terathon.com/code/tangent.html
  135. // tangents go to vertices
  136. var f, fl, v, vl, i, il, vertexIndex,
  137. face, uv, vA, vB, vC, uvA, uvB, uvC,
  138. x1, x2, y1, y2, z1, z2,
  139. s1, s2, t1, t2, r, t, test,
  140. tan1 = [], tan2 = [],
  141. sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
  142. tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
  143. n = new THREE.Vector3(), w;
  144. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  145. tan1[ v ] = new THREE.Vector3();
  146. tan2[ v ] = new THREE.Vector3();
  147. }
  148. function handleTriangle( context, a, b, c, ua, ub, uc ) {
  149. vA = context.vertices[ a ].position;
  150. vB = context.vertices[ b ].position;
  151. vC = context.vertices[ c ].position;
  152. uvA = uv[ ua ];
  153. uvB = uv[ ub ];
  154. uvC = uv[ uc ];
  155. x1 = vB.x - vA.x;
  156. x2 = vC.x - vA.x;
  157. y1 = vB.y - vA.y;
  158. y2 = vC.y - vA.y;
  159. z1 = vB.z - vA.z;
  160. z2 = vC.z - vA.z;
  161. s1 = uvB.u - uvA.u;
  162. s2 = uvC.u - uvA.u;
  163. t1 = uvB.v - uvA.v;
  164. t2 = uvC.v - uvA.v;
  165. r = 1.0 / ( s1 * t2 - s2 * t1 );
  166. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  167. ( t2 * y1 - t1 * y2 ) * r,
  168. ( t2 * z1 - t1 * z2 ) * r );
  169. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  170. ( s1 * y2 - s2 * y1 ) * r,
  171. ( s1 * z2 - s2 * z1 ) * r );
  172. tan1[ a ].addSelf( sdir );
  173. tan1[ b ].addSelf( sdir );
  174. tan1[ c ].addSelf( sdir );
  175. tan2[ a ].addSelf( tdir );
  176. tan2[ b ].addSelf( tdir );
  177. tan2[ c ].addSelf( tdir );
  178. }
  179. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  180. face = this.faces[ f ];
  181. uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
  182. if ( face instanceof THREE.Face3 ) {
  183. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  184. } else if ( face instanceof THREE.Face4 ) {
  185. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  186. handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
  187. }
  188. }
  189. var faceIndex = [ 'a', 'b', 'c', 'd' ];
  190. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  191. face = this.faces[ f ];
  192. for ( i = 0; i < face.vertexNormals.length; i++ ) {
  193. n.copy( face.vertexNormals[ i ] );
  194. vertexIndex = face[ faceIndex[ i ] ];
  195. t = tan1[ vertexIndex ];
  196. // Gram-Schmidt orthogonalize
  197. tmp.copy( t );
  198. tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
  199. // Calculate handedness
  200. tmp2.cross( face.vertexNormals[ i ], t );
  201. test = tmp2.dot( tan2[ vertexIndex ] );
  202. w = (test < 0.0) ? -1.0 : 1.0;
  203. face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
  204. }
  205. }
  206. this.hasTangents = true;
  207. },
  208. computeBoundingBox: function () {
  209. var vertex;
  210. if ( this.vertices.length > 0 ) {
  211. this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ],
  212. 'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ],
  213. 'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };
  214. for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
  215. vertex = this.vertices[ v ];
  216. if ( vertex.position.x < this.boundingBox.x[ 0 ] ) {
  217. this.boundingBox.x[ 0 ] = vertex.position.x;
  218. } else if ( vertex.position.x > this.boundingBox.x[ 1 ] ) {
  219. this.boundingBox.x[ 1 ] = vertex.position.x;
  220. }
  221. if ( vertex.position.y < this.boundingBox.y[ 0 ] ) {
  222. this.boundingBox.y[ 0 ] = vertex.position.y;
  223. } else if ( vertex.position.y > this.boundingBox.y[ 1 ] ) {
  224. this.boundingBox.y[ 1 ] = vertex.position.y;
  225. }
  226. if ( vertex.position.z < this.boundingBox.z[ 0 ] ) {
  227. this.boundingBox.z[ 0 ] = vertex.position.z;
  228. } else if ( vertex.position.z > this.boundingBox.z[ 1 ] ) {
  229. this.boundingBox.z[ 1 ] = vertex.position.z;
  230. }
  231. }
  232. }
  233. },
  234. computeBoundingSphere: function () {
  235. // var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius;
  236. var radius = 0;
  237. for ( var v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  238. radius = Math.max( radius, this.vertices[ v ].position.length() );
  239. }
  240. this.boundingSphere = { radius: radius };
  241. },
  242. /*
  243. * Checks for duplicate vertices with hashmap.
  244. * Duplicated vertices are removed
  245. * and faces' vertices are updated.
  246. */
  247. mergeVertices: function() {
  248. var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
  249. var unique = [], changes = [];
  250. var v, key;
  251. var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
  252. var precision = Math.pow( 10, precisionPoints );
  253. var i,il, face;
  254. for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
  255. v = this.vertices[ i ].position;
  256. key = [ Math.round( v.x * precision ), Math.round( v.y * precision ), Math.round( v.z * precision ) ].join( '_' );
  257. if ( verticesMap[ key ] === undefined ) {
  258. verticesMap[ key ] = i;
  259. unique.push( this.vertices[ i ] );
  260. changes[ i ] = unique.length - 1;
  261. } else {
  262. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  263. changes[ i ] = changes[ verticesMap[ key ] ];
  264. }
  265. };
  266. // Start to patch face indices
  267. for( i = 0, il = this.faces.length; i < il; i ++ ) {
  268. face = this.faces[ i ];
  269. if ( face instanceof THREE.Face3 ) {
  270. face.a = changes[ face.a ];
  271. face.b = changes[ face.b ];
  272. face.c = changes[ face.c ];
  273. } else if ( face instanceof THREE.Face4 ) {
  274. face.a = changes[ face.a ];
  275. face.b = changes[ face.b ];
  276. face.c = changes[ face.c ];
  277. face.d = changes[ face.d ];
  278. }
  279. }
  280. // Use unique set of vertices
  281. this.vertices = unique;
  282. }
  283. };
  284. THREE.GeometryCount = 0;