2
0

BufferGeometry.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.BufferGeometry = function () {
  5. this.id = THREE.GeometryIdCount ++;
  6. this.uuid = THREE.Math.generateUUID();
  7. // attributes
  8. this.attributes = {};
  9. // attributes typed arrays are kept only if dynamic flag is set
  10. this.dynamic = false;
  11. // offsets for chunks when using indexed elements
  12. this.offsets = [];
  13. // boundings
  14. this.boundingBox = null;
  15. this.boundingSphere = null;
  16. this.hasTangents = false;
  17. // for compatibility
  18. this.morphTargets = [];
  19. };
  20. THREE.BufferGeometry.prototype = {
  21. constructor: THREE.BufferGeometry,
  22. addEventListener: THREE.EventDispatcher.prototype.addEventListener,
  23. hasEventListener: THREE.EventDispatcher.prototype.hasEventListener,
  24. removeEventListener: THREE.EventDispatcher.prototype.removeEventListener,
  25. dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent,
  26. applyMatrix: function ( matrix ) {
  27. var positionArray;
  28. var normalArray;
  29. if ( this.attributes[ "position" ] ) positionArray = this.attributes[ "position" ].array;
  30. if ( this.attributes[ "normal" ] ) normalArray = this.attributes[ "normal" ].array;
  31. if ( positionArray !== undefined ) {
  32. matrix.multiplyVector3Array( positionArray );
  33. this.verticesNeedUpdate = true;
  34. }
  35. if ( normalArray !== undefined ) {
  36. var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
  37. normalMatrix.multiplyVector3Array( normalArray );
  38. this.normalizeNormals();
  39. this.normalsNeedUpdate = true;
  40. }
  41. },
  42. computeBoundingBox: function () {
  43. if ( this.boundingBox === null ) {
  44. this.boundingBox = new THREE.Box3();
  45. }
  46. var positions = this.attributes[ "position" ].array;
  47. if ( positions ) {
  48. var bb = this.boundingBox;
  49. var x, y, z;
  50. if( positions.length >= 3 ) {
  51. bb.min.x = bb.max.x = positions[ 0 ];
  52. bb.min.y = bb.max.y = positions[ 1 ];
  53. bb.min.z = bb.max.z = positions[ 2 ];
  54. }
  55. for ( var i = 3, il = positions.length; i < il; i += 3 ) {
  56. x = positions[ i ];
  57. y = positions[ i + 1 ];
  58. z = positions[ i + 2 ];
  59. // bounding box
  60. if ( x < bb.min.x ) {
  61. bb.min.x = x;
  62. } else if ( x > bb.max.x ) {
  63. bb.max.x = x;
  64. }
  65. if ( y < bb.min.y ) {
  66. bb.min.y = y;
  67. } else if ( y > bb.max.y ) {
  68. bb.max.y = y;
  69. }
  70. if ( z < bb.min.z ) {
  71. bb.min.z = z;
  72. } else if ( z > bb.max.z ) {
  73. bb.max.z = z;
  74. }
  75. }
  76. }
  77. if ( positions === undefined || positions.length === 0 ) {
  78. this.boundingBox.min.set( 0, 0, 0 );
  79. this.boundingBox.max.set( 0, 0, 0 );
  80. }
  81. },
  82. computeBoundingSphere: function () {
  83. if ( this.boundingSphere === null ) {
  84. this.boundingSphere = new THREE.Sphere();
  85. }
  86. var positions = this.attributes[ "position" ].array;
  87. if ( positions ) {
  88. var radiusSq, maxRadiusSq = 0;
  89. var x, y, z;
  90. for ( var i = 0, il = positions.length; i < il; i += 3 ) {
  91. x = positions[ i ];
  92. y = positions[ i + 1 ];
  93. z = positions[ i + 2 ];
  94. radiusSq = x * x + y * y + z * z;
  95. if ( radiusSq > maxRadiusSq ) maxRadiusSq = radiusSq;
  96. }
  97. this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
  98. }
  99. },
  100. computeVertexNormals: function () {
  101. if ( this.attributes[ "position" ] ) {
  102. var i, il;
  103. var j, jl;
  104. var nVertexElements = this.attributes[ "position" ].array.length;
  105. if ( this.attributes[ "normal" ] === undefined ) {
  106. this.attributes[ "normal" ] = {
  107. itemSize: 3,
  108. array: new Float32Array( nVertexElements )
  109. };
  110. } else {
  111. // reset existing normals to zero
  112. for ( i = 0, il = this.attributes[ "normal" ].array.length; i < il; i ++ ) {
  113. this.attributes[ "normal" ].array[ i ] = 0;
  114. }
  115. }
  116. var positions = this.attributes[ "position" ].array;
  117. var normals = this.attributes[ "normal" ].array;
  118. var vA, vB, vC, x, y, z,
  119. pA = new THREE.Vector3(),
  120. pB = new THREE.Vector3(),
  121. pC = new THREE.Vector3(),
  122. cb = new THREE.Vector3(),
  123. ab = new THREE.Vector3();
  124. // indexed elements
  125. if ( this.attributes[ "index" ] ) {
  126. var indices = this.attributes[ "index" ].array;
  127. var offsets = this.offsets;
  128. for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
  129. var start = offsets[ j ].start;
  130. var count = offsets[ j ].count;
  131. var index = offsets[ j ].index;
  132. for ( i = start, il = start + count; i < il; i += 3 ) {
  133. vA = index + indices[ i ];
  134. vB = index + indices[ i + 1 ];
  135. vC = index + indices[ i + 2 ];
  136. x = positions[ vA * 3 ];
  137. y = positions[ vA * 3 + 1 ];
  138. z = positions[ vA * 3 + 2 ];
  139. pA.set( x, y, z );
  140. x = positions[ vB * 3 ];
  141. y = positions[ vB * 3 + 1 ];
  142. z = positions[ vB * 3 + 2 ];
  143. pB.set( x, y, z );
  144. x = positions[ vC * 3 ];
  145. y = positions[ vC * 3 + 1 ];
  146. z = positions[ vC * 3 + 2 ];
  147. pC.set( x, y, z );
  148. cb.subVectors( pC, pB );
  149. ab.subVectors( pA, pB );
  150. cb.cross( ab );
  151. normals[ vA * 3 ] += cb.x;
  152. normals[ vA * 3 + 1 ] += cb.y;
  153. normals[ vA * 3 + 2 ] += cb.z;
  154. normals[ vB * 3 ] += cb.x;
  155. normals[ vB * 3 + 1 ] += cb.y;
  156. normals[ vB * 3 + 2 ] += cb.z;
  157. normals[ vC * 3 ] += cb.x;
  158. normals[ vC * 3 + 1 ] += cb.y;
  159. normals[ vC * 3 + 2 ] += cb.z;
  160. }
  161. }
  162. // non-indexed elements (unconnected triangle soup)
  163. } else {
  164. for ( i = 0, il = positions.length; i < il; i += 9 ) {
  165. x = positions[ i ];
  166. y = positions[ i + 1 ];
  167. z = positions[ i + 2 ];
  168. pA.set( x, y, z );
  169. x = positions[ i + 3 ];
  170. y = positions[ i + 4 ];
  171. z = positions[ i + 5 ];
  172. pB.set( x, y, z );
  173. x = positions[ i + 6 ];
  174. y = positions[ i + 7 ];
  175. z = positions[ i + 8 ];
  176. pC.set( x, y, z );
  177. cb.subVectors( pC, pB );
  178. ab.subVectors( pA, pB );
  179. cb.cross( ab );
  180. normals[ i ] = cb.x;
  181. normals[ i + 1 ] = cb.y;
  182. normals[ i + 2 ] = cb.z;
  183. normals[ i + 3 ] = cb.x;
  184. normals[ i + 4 ] = cb.y;
  185. normals[ i + 5 ] = cb.z;
  186. normals[ i + 6 ] = cb.x;
  187. normals[ i + 7 ] = cb.y;
  188. normals[ i + 8 ] = cb.z;
  189. }
  190. }
  191. this.normalizeNormals();
  192. this.normalsNeedUpdate = true;
  193. }
  194. },
  195. normalizeNormals: function () {
  196. var normals = this.attributes[ "normal" ].array;
  197. var x, y, z, n;
  198. for ( var i = 0, il = normals.length; i < il; i += 3 ) {
  199. x = normals[ i ];
  200. y = normals[ i + 1 ];
  201. z = normals[ i + 2 ];
  202. n = 1.0 / Math.sqrt( x * x + y * y + z * z );
  203. normals[ i ] *= n;
  204. normals[ i + 1 ] *= n;
  205. normals[ i + 2 ] *= n;
  206. }
  207. },
  208. computeTangents: function () {
  209. // based on http://www.terathon.com/code/tangent.html
  210. // (per vertex tangents)
  211. if ( this.attributes[ "index" ] === undefined ||
  212. this.attributes[ "position" ] === undefined ||
  213. this.attributes[ "normal" ] === undefined ||
  214. this.attributes[ "uv" ] === undefined ) {
  215. console.warn( "Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()" );
  216. return;
  217. }
  218. var indices = this.attributes[ "index" ].array;
  219. var positions = this.attributes[ "position" ].array;
  220. var normals = this.attributes[ "normal" ].array;
  221. var uvs = this.attributes[ "uv" ].array;
  222. var nVertices = positions.length / 3;
  223. if ( this.attributes[ "tangent" ] === undefined ) {
  224. var nTangentElements = 4 * nVertices;
  225. this.attributes[ "tangent" ] = {
  226. itemSize: 4,
  227. array: new Float32Array( nTangentElements )
  228. };
  229. }
  230. var tangents = this.attributes[ "tangent" ].array;
  231. var tan1 = [], tan2 = [];
  232. for ( var k = 0; k < nVertices; k ++ ) {
  233. tan1[ k ] = new THREE.Vector3();
  234. tan2[ k ] = new THREE.Vector3();
  235. }
  236. var xA, yA, zA,
  237. xB, yB, zB,
  238. xC, yC, zC,
  239. uA, vA,
  240. uB, vB,
  241. uC, vC,
  242. x1, x2, y1, y2, z1, z2,
  243. s1, s2, t1, t2, r;
  244. var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();
  245. function handleTriangle( a, b, c ) {
  246. xA = positions[ a * 3 ];
  247. yA = positions[ a * 3 + 1 ];
  248. zA = positions[ a * 3 + 2 ];
  249. xB = positions[ b * 3 ];
  250. yB = positions[ b * 3 + 1 ];
  251. zB = positions[ b * 3 + 2 ];
  252. xC = positions[ c * 3 ];
  253. yC = positions[ c * 3 + 1 ];
  254. zC = positions[ c * 3 + 2 ];
  255. uA = uvs[ a * 2 ];
  256. vA = uvs[ a * 2 + 1 ];
  257. uB = uvs[ b * 2 ];
  258. vB = uvs[ b * 2 + 1 ];
  259. uC = uvs[ c * 2 ];
  260. vC = uvs[ c * 2 + 1 ];
  261. x1 = xB - xA;
  262. x2 = xC - xA;
  263. y1 = yB - yA;
  264. y2 = yC - yA;
  265. z1 = zB - zA;
  266. z2 = zC - zA;
  267. s1 = uB - uA;
  268. s2 = uC - uA;
  269. t1 = vB - vA;
  270. t2 = vC - vA;
  271. r = 1.0 / ( s1 * t2 - s2 * t1 );
  272. sdir.set(
  273. ( t2 * x1 - t1 * x2 ) * r,
  274. ( t2 * y1 - t1 * y2 ) * r,
  275. ( t2 * z1 - t1 * z2 ) * r
  276. );
  277. tdir.set(
  278. ( s1 * x2 - s2 * x1 ) * r,
  279. ( s1 * y2 - s2 * y1 ) * r,
  280. ( s1 * z2 - s2 * z1 ) * r
  281. );
  282. tan1[ a ].add( sdir );
  283. tan1[ b ].add( sdir );
  284. tan1[ c ].add( sdir );
  285. tan2[ a ].add( tdir );
  286. tan2[ b ].add( tdir );
  287. tan2[ c ].add( tdir );
  288. }
  289. var i, il;
  290. var j, jl;
  291. var iA, iB, iC;
  292. var offsets = this.offsets;
  293. for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
  294. var start = offsets[ j ].start;
  295. var count = offsets[ j ].count;
  296. var index = offsets[ j ].index;
  297. for ( i = start, il = start + count; i < il; i += 3 ) {
  298. iA = index + indices[ i ];
  299. iB = index + indices[ i + 1 ];
  300. iC = index + indices[ i + 2 ];
  301. handleTriangle( iA, iB, iC );
  302. }
  303. }
  304. var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
  305. var n = new THREE.Vector3(), n2 = new THREE.Vector3();
  306. var w, t, test;
  307. function handleVertex( v ) {
  308. n.x = normals[ v * 3 ];
  309. n.y = normals[ v * 3 + 1 ];
  310. n.z = normals[ v * 3 + 2 ];
  311. n2.copy( n );
  312. t = tan1[ v ];
  313. // Gram-Schmidt orthogonalize
  314. tmp.copy( t );
  315. tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
  316. // Calculate handedness
  317. tmp2.crossVectors( n2, t );
  318. test = tmp2.dot( tan2[ v ] );
  319. w = ( test < 0.0 ) ? -1.0 : 1.0;
  320. tangents[ v * 4 ] = tmp.x;
  321. tangents[ v * 4 + 1 ] = tmp.y;
  322. tangents[ v * 4 + 2 ] = tmp.z;
  323. tangents[ v * 4 + 3 ] = w;
  324. }
  325. for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
  326. var start = offsets[ j ].start;
  327. var count = offsets[ j ].count;
  328. var index = offsets[ j ].index;
  329. for ( i = start, il = start + count; i < il; i += 3 ) {
  330. iA = index + indices[ i ];
  331. iB = index + indices[ i + 1 ];
  332. iC = index + indices[ i + 2 ];
  333. handleVertex( iA );
  334. handleVertex( iB );
  335. handleVertex( iC );
  336. }
  337. }
  338. this.hasTangents = true;
  339. this.tangentsNeedUpdate = true;
  340. },
  341. dispose: function () {
  342. this.dispatchEvent( { type: 'dispose' } );
  343. }
  344. };