babylon.mesh.vertexData.js 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822
  1. var BABYLON;
  2. (function (BABYLON) {
  3. var VertexData = (function () {
  4. function VertexData() {
  5. }
  6. VertexData.prototype.set = function (data, kind) {
  7. switch (kind) {
  8. case BABYLON.VertexBuffer.PositionKind:
  9. this.positions = data;
  10. break;
  11. case BABYLON.VertexBuffer.NormalKind:
  12. this.normals = data;
  13. break;
  14. case BABYLON.VertexBuffer.UVKind:
  15. this.uvs = data;
  16. break;
  17. case BABYLON.VertexBuffer.UV2Kind:
  18. this.uvs2 = data;
  19. break;
  20. case BABYLON.VertexBuffer.UV3Kind:
  21. this.uvs3 = data;
  22. break;
  23. case BABYLON.VertexBuffer.UV4Kind:
  24. this.uvs4 = data;
  25. break;
  26. case BABYLON.VertexBuffer.UV5Kind:
  27. this.uvs5 = data;
  28. break;
  29. case BABYLON.VertexBuffer.UV6Kind:
  30. this.uvs6 = data;
  31. break;
  32. case BABYLON.VertexBuffer.ColorKind:
  33. this.colors = data;
  34. break;
  35. case BABYLON.VertexBuffer.MatricesIndicesKind:
  36. this.matricesIndices = data;
  37. break;
  38. case BABYLON.VertexBuffer.MatricesWeightsKind:
  39. this.matricesWeights = data;
  40. break;
  41. case BABYLON.VertexBuffer.MatricesIndicesExtraKind:
  42. this.matricesIndicesExtra = data;
  43. break;
  44. case BABYLON.VertexBuffer.MatricesWeightsExtraKind:
  45. this.matricesWeightsExtra = data;
  46. break;
  47. }
  48. };
  49. VertexData.prototype.applyToMesh = function (mesh, updatable) {
  50. this._applyTo(mesh, updatable);
  51. };
  52. VertexData.prototype.applyToGeometry = function (geometry, updatable) {
  53. this._applyTo(geometry, updatable);
  54. };
  55. VertexData.prototype.updateMesh = function (mesh, updateExtends, makeItUnique) {
  56. this._update(mesh);
  57. };
  58. VertexData.prototype.updateGeometry = function (geometry, updateExtends, makeItUnique) {
  59. this._update(geometry);
  60. };
  61. VertexData.prototype._applyTo = function (meshOrGeometry, updatable) {
  62. if (this.positions) {
  63. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updatable);
  64. }
  65. if (this.normals) {
  66. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updatable);
  67. }
  68. if (this.uvs) {
  69. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updatable);
  70. }
  71. if (this.uvs2) {
  72. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uvs2, updatable);
  73. }
  74. if (this.uvs3) {
  75. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV3Kind, this.uvs3, updatable);
  76. }
  77. if (this.uvs4) {
  78. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV4Kind, this.uvs4, updatable);
  79. }
  80. if (this.uvs5) {
  81. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV5Kind, this.uvs5, updatable);
  82. }
  83. if (this.uvs6) {
  84. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.UV6Kind, this.uvs6, updatable);
  85. }
  86. if (this.colors) {
  87. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updatable);
  88. }
  89. if (this.matricesIndices) {
  90. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updatable);
  91. }
  92. if (this.matricesWeights) {
  93. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updatable);
  94. }
  95. if (this.matricesIndicesExtra) {
  96. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, this.matricesIndicesExtra, updatable);
  97. }
  98. if (this.matricesWeightsExtra) {
  99. meshOrGeometry.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsExtraKind, this.matricesWeightsExtra, updatable);
  100. }
  101. if (this.indices) {
  102. meshOrGeometry.setIndices(this.indices);
  103. }
  104. };
  105. VertexData.prototype._update = function (meshOrGeometry, updateExtends, makeItUnique) {
  106. if (this.positions) {
  107. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.PositionKind, this.positions, updateExtends, makeItUnique);
  108. }
  109. if (this.normals) {
  110. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
  111. }
  112. if (this.uvs) {
  113. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
  114. }
  115. if (this.uvs2) {
  116. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV2Kind, this.uvs2, updateExtends, makeItUnique);
  117. }
  118. if (this.uvs3) {
  119. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV3Kind, this.uvs3, updateExtends, makeItUnique);
  120. }
  121. if (this.uvs4) {
  122. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV4Kind, this.uvs4, updateExtends, makeItUnique);
  123. }
  124. if (this.uvs5) {
  125. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV5Kind, this.uvs5, updateExtends, makeItUnique);
  126. }
  127. if (this.uvs6) {
  128. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.UV6Kind, this.uvs6, updateExtends, makeItUnique);
  129. }
  130. if (this.colors) {
  131. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.ColorKind, this.colors, updateExtends, makeItUnique);
  132. }
  133. if (this.matricesIndices) {
  134. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, this.matricesIndices, updateExtends, makeItUnique);
  135. }
  136. if (this.matricesWeights) {
  137. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, this.matricesWeights, updateExtends, makeItUnique);
  138. }
  139. if (this.matricesIndicesExtra) {
  140. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, this.matricesIndicesExtra, updateExtends, makeItUnique);
  141. }
  142. if (this.matricesWeightsExtra) {
  143. meshOrGeometry.updateVerticesData(BABYLON.VertexBuffer.MatricesWeightsExtraKind, this.matricesWeightsExtra, updateExtends, makeItUnique);
  144. }
  145. if (this.indices) {
  146. meshOrGeometry.setIndices(this.indices);
  147. }
  148. };
  149. VertexData.prototype.transform = function (matrix) {
  150. var transformed = BABYLON.Vector3.Zero();
  151. var index;
  152. if (this.positions) {
  153. var position = BABYLON.Vector3.Zero();
  154. for (index = 0; index < this.positions.length; index += 3) {
  155. BABYLON.Vector3.FromArrayToRef(this.positions, index, position);
  156. BABYLON.Vector3.TransformCoordinatesToRef(position, matrix, transformed);
  157. this.positions[index] = transformed.x;
  158. this.positions[index + 1] = transformed.y;
  159. this.positions[index + 2] = transformed.z;
  160. }
  161. }
  162. if (this.normals) {
  163. var normal = BABYLON.Vector3.Zero();
  164. for (index = 0; index < this.normals.length; index += 3) {
  165. BABYLON.Vector3.FromArrayToRef(this.normals, index, normal);
  166. BABYLON.Vector3.TransformNormalToRef(normal, matrix, transformed);
  167. this.normals[index] = transformed.x;
  168. this.normals[index + 1] = transformed.y;
  169. this.normals[index + 2] = transformed.z;
  170. }
  171. }
  172. };
  173. VertexData.prototype.merge = function (other) {
  174. if (other.indices) {
  175. if (!this.indices) {
  176. this.indices = [];
  177. }
  178. var offset = this.positions ? this.positions.length / 3 : 0;
  179. for (var index = 0; index < other.indices.length; index++) {
  180. //TODO check type - if Int32Array!
  181. this.indices.push(other.indices[index] + offset);
  182. }
  183. }
  184. this.positions = this._mergeElement(this.positions, other.positions);
  185. this.normals = this._mergeElement(this.normals, other.normals);
  186. this.uvs = this._mergeElement(this.uvs, other.uvs);
  187. this.uvs2 = this._mergeElement(this.uvs2, other.uvs2);
  188. this.uvs3 = this._mergeElement(this.uvs3, other.uvs3);
  189. this.uvs4 = this._mergeElement(this.uvs4, other.uvs4);
  190. this.uvs5 = this._mergeElement(this.uvs5, other.uvs5);
  191. this.uvs6 = this._mergeElement(this.uvs6, other.uvs6);
  192. this.colors = this._mergeElement(this.colors, other.colors);
  193. this.matricesIndices = this._mergeElement(this.matricesIndices, other.matricesIndices);
  194. this.matricesWeights = this._mergeElement(this.matricesWeights, other.matricesWeights);
  195. this.matricesIndicesExtra = this._mergeElement(this.matricesIndicesExtra, other.matricesIndicesExtra);
  196. this.matricesWeightsExtra = this._mergeElement(this.matricesWeightsExtra, other.matricesWeightsExtra);
  197. };
  198. VertexData.prototype._mergeElement = function (source, other) {
  199. if (!other)
  200. return source;
  201. if (!source)
  202. return other;
  203. var len = other.length + source.length;
  204. var isSrcTypedArray = source instanceof Float32Array;
  205. var isOthTypedArray = other instanceof Float32Array;
  206. // use non-loop method when the source is Float32Array
  207. if (isSrcTypedArray) {
  208. var ret32 = new Float32Array(len);
  209. ret32.set(source);
  210. ret32.set(other, source.length);
  211. return ret32;
  212. }
  213. else if (!isOthTypedArray) {
  214. return source.concat(other);
  215. }
  216. else {
  217. var ret = source.slice(0); // copy source to a separate array
  218. for (var i = 0, len = other.length; i < len; i++) {
  219. ret.push(other[i]);
  220. }
  221. return ret;
  222. }
  223. };
  224. VertexData.prototype.serialize = function () {
  225. var serializationObject = this.serialize();
  226. if (this.positions) {
  227. serializationObject.positions = this.positions;
  228. }
  229. if (this.normals) {
  230. serializationObject.normals = this.normals;
  231. }
  232. if (this.uvs) {
  233. serializationObject.uvs = this.uvs;
  234. }
  235. if (this.uvs2) {
  236. serializationObject.uvs2 = this.uvs2;
  237. }
  238. if (this.uvs3) {
  239. serializationObject.uvs3 = this.uvs3;
  240. }
  241. if (this.uvs4) {
  242. serializationObject.uvs4 = this.uvs4;
  243. }
  244. if (this.uvs5) {
  245. serializationObject.uvs5 = this.uvs5;
  246. }
  247. if (this.uvs6) {
  248. serializationObject.uvs6 = this.uvs6;
  249. }
  250. if (this.colors) {
  251. serializationObject.colors = this.colors;
  252. }
  253. if (this.matricesIndices) {
  254. serializationObject.matricesIndices = this.matricesIndices;
  255. serializationObject.matricesIndices._isExpanded = true;
  256. }
  257. if (this.matricesWeights) {
  258. serializationObject.matricesWeights = this.matricesWeights;
  259. }
  260. if (this.matricesIndicesExtra) {
  261. serializationObject.matricesIndicesExtra = this.matricesIndicesExtra;
  262. serializationObject.matricesIndicesExtra._isExpanded = true;
  263. }
  264. if (this.matricesWeightsExtra) {
  265. serializationObject.matricesWeightsExtra = this.matricesWeightsExtra;
  266. }
  267. serializationObject.indices = this.indices;
  268. return serializationObject;
  269. };
  270. // Statics
  271. VertexData.ExtractFromMesh = function (mesh, copyWhenShared) {
  272. return VertexData._ExtractFrom(mesh, copyWhenShared);
  273. };
  274. VertexData.ExtractFromGeometry = function (geometry, copyWhenShared) {
  275. return VertexData._ExtractFrom(geometry, copyWhenShared);
  276. };
  277. VertexData._ExtractFrom = function (meshOrGeometry, copyWhenShared) {
  278. var result = new VertexData();
  279. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
  280. result.positions = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.PositionKind, copyWhenShared);
  281. }
  282. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
  283. result.normals = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.NormalKind, copyWhenShared);
  284. }
  285. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
  286. result.uvs = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UVKind, copyWhenShared);
  287. }
  288. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
  289. result.uvs2 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV2Kind, copyWhenShared);
  290. }
  291. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV3Kind)) {
  292. result.uvs3 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV3Kind, copyWhenShared);
  293. }
  294. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV4Kind)) {
  295. result.uvs4 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV4Kind, copyWhenShared);
  296. }
  297. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV5Kind)) {
  298. result.uvs5 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV5Kind, copyWhenShared);
  299. }
  300. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV6Kind)) {
  301. result.uvs6 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV6Kind, copyWhenShared);
  302. }
  303. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
  304. result.colors = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.ColorKind, copyWhenShared);
  305. }
  306. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)) {
  307. result.matricesIndices = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, copyWhenShared);
  308. }
  309. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
  310. result.matricesWeights = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, copyWhenShared);
  311. }
  312. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesExtraKind)) {
  313. result.matricesIndicesExtra = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, copyWhenShared);
  314. }
  315. if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsExtraKind)) {
  316. result.matricesWeightsExtra = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsExtraKind, copyWhenShared);
  317. }
  318. result.indices = meshOrGeometry.getIndices(copyWhenShared);
  319. return result;
  320. };
  321. VertexData.CreateRibbon = function (options) {
  322. var pathArray = options.pathArray;
  323. var closeArray = options.closeArray || false;
  324. var closePath = options.closePath || false;
  325. var defaultOffset = Math.floor(pathArray[0].length / 2);
  326. var offset = options.offset || defaultOffset;
  327. offset = offset > defaultOffset ? defaultOffset : Math.floor(offset); // offset max allowed : defaultOffset
  328. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  329. var positions = [];
  330. var indices = [];
  331. var normals = [];
  332. var uvs = [];
  333. var us = []; // us[path_id] = [uDist1, uDist2, uDist3 ... ] distances between points on path path_id
  334. var vs = []; // vs[i] = [vDist1, vDist2, vDist3, ... ] distances between points i of consecutives paths from pathArray
  335. var uTotalDistance = []; // uTotalDistance[p] : total distance of path p
  336. var vTotalDistance = []; // vTotalDistance[i] : total distance between points i of first and last path from pathArray
  337. var minlg; // minimal length among all paths from pathArray
  338. var lg = []; // array of path lengths : nb of vertex per path
  339. var idx = []; // array of path indexes : index of each path (first vertex) in the total vertex number
  340. var p; // path iterator
  341. var i; // point iterator
  342. var j; // point iterator
  343. // if single path in pathArray
  344. if (pathArray.length < 2) {
  345. var ar1 = [];
  346. var ar2 = [];
  347. for (i = 0; i < pathArray[0].length - offset; i++) {
  348. ar1.push(pathArray[0][i]);
  349. ar2.push(pathArray[0][i + offset]);
  350. }
  351. pathArray = [ar1, ar2];
  352. }
  353. // positions and horizontal distances (u)
  354. var idc = 0;
  355. var closePathCorr = (closePath) ? 1 : 0;
  356. var path;
  357. var l;
  358. minlg = pathArray[0].length;
  359. var vectlg;
  360. var dist;
  361. for (p = 0; p < pathArray.length; p++) {
  362. uTotalDistance[p] = 0;
  363. us[p] = [0];
  364. path = pathArray[p];
  365. l = path.length;
  366. minlg = (minlg < l) ? minlg : l;
  367. j = 0;
  368. while (j < l) {
  369. positions.push(path[j].x, path[j].y, path[j].z);
  370. if (j > 0) {
  371. vectlg = path[j].subtract(path[j - 1]).length();
  372. dist = vectlg + uTotalDistance[p];
  373. us[p].push(dist);
  374. uTotalDistance[p] = dist;
  375. }
  376. j++;
  377. }
  378. if (closePath) {
  379. j--;
  380. positions.push(path[0].x, path[0].y, path[0].z);
  381. vectlg = path[j].subtract(path[0]).length();
  382. dist = vectlg + uTotalDistance[p];
  383. us[p].push(dist);
  384. uTotalDistance[p] = dist;
  385. }
  386. lg[p] = l + closePathCorr;
  387. idx[p] = idc;
  388. idc += (l + closePathCorr);
  389. }
  390. // vertical distances (v)
  391. var path1;
  392. var path2;
  393. var vertex1;
  394. var vertex2;
  395. for (i = 0; i < minlg + closePathCorr; i++) {
  396. vTotalDistance[i] = 0;
  397. vs[i] = [0];
  398. for (p = 0; p < pathArray.length - 1; p++) {
  399. path1 = pathArray[p];
  400. path2 = pathArray[p + 1];
  401. if (i === minlg) {
  402. vertex1 = path1[0];
  403. vertex2 = path2[0];
  404. }
  405. else {
  406. vertex1 = path1[i];
  407. vertex2 = path2[i];
  408. }
  409. vectlg = vertex2.subtract(vertex1).length();
  410. dist = vectlg + vTotalDistance[i];
  411. vs[i].push(dist);
  412. vTotalDistance[i] = dist;
  413. }
  414. if (closeArray) {
  415. path1 = pathArray[p];
  416. path2 = pathArray[0];
  417. if (i === minlg) {
  418. vertex2 = path2[0];
  419. }
  420. vectlg = vertex2.subtract(vertex1).length();
  421. dist = vectlg + vTotalDistance[i];
  422. vTotalDistance[i] = dist;
  423. }
  424. }
  425. // uvs
  426. var u;
  427. var v;
  428. for (p = 0; p < pathArray.length; p++) {
  429. for (i = 0; i < minlg + closePathCorr; i++) {
  430. u = us[p][i] / uTotalDistance[p];
  431. v = vs[i][p] / vTotalDistance[i];
  432. uvs.push(u, v);
  433. }
  434. }
  435. // indices
  436. p = 0; // path index
  437. var pi = 0; // positions array index
  438. var l1 = lg[p] - 1; // path1 length
  439. var l2 = lg[p + 1] - 1; // path2 length
  440. var min = (l1 < l2) ? l1 : l2; // current path stop index
  441. var shft = idx[1] - idx[0]; // shift
  442. var path1nb = closeArray ? lg.length : lg.length - 1; // number of path1 to iterate on
  443. while (pi <= min && p < path1nb) {
  444. // draw two triangles between path1 (p1) and path2 (p2) : (p1.pi, p2.pi, p1.pi+1) and (p2.pi+1, p1.pi+1, p2.pi) clockwise
  445. indices.push(pi, pi + shft, pi + 1);
  446. indices.push(pi + shft + 1, pi + 1, pi + shft);
  447. pi += 1;
  448. if (pi === min) {
  449. p++;
  450. if (p === lg.length - 1) {
  451. shft = idx[0] - idx[p];
  452. l1 = lg[p] - 1;
  453. l2 = lg[0] - 1;
  454. }
  455. else {
  456. shft = idx[p + 1] - idx[p];
  457. l1 = lg[p] - 1;
  458. l2 = lg[p + 1] - 1;
  459. }
  460. pi = idx[p];
  461. min = (l1 < l2) ? l1 + pi : l2 + pi;
  462. }
  463. }
  464. // normals
  465. VertexData.ComputeNormals(positions, indices, normals);
  466. if (closePath) {
  467. var indexFirst = 0;
  468. var indexLast = 0;
  469. for (p = 0; p < pathArray.length; p++) {
  470. indexFirst = idx[p] * 3;
  471. if (p + 1 < pathArray.length) {
  472. indexLast = (idx[p + 1] - 1) * 3;
  473. }
  474. else {
  475. indexLast = normals.length - 3;
  476. }
  477. normals[indexFirst] = (normals[indexFirst] + normals[indexLast]) * 0.5;
  478. normals[indexFirst + 1] = (normals[indexFirst + 1] + normals[indexLast + 1]) * 0.5;
  479. normals[indexFirst + 2] = (normals[indexFirst + 2] + normals[indexLast + 2]) * 0.5;
  480. normals[indexLast] = normals[indexFirst];
  481. normals[indexLast + 1] = normals[indexFirst + 1];
  482. normals[indexLast + 2] = normals[indexFirst + 2];
  483. }
  484. }
  485. // sides
  486. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  487. // Result
  488. var vertexData = new VertexData();
  489. vertexData.indices = indices;
  490. vertexData.positions = positions;
  491. vertexData.normals = normals;
  492. vertexData.uvs = uvs;
  493. if (closePath) {
  494. vertexData._idx = idx;
  495. }
  496. return vertexData;
  497. };
  498. VertexData.CreateBox = function (options) {
  499. var normalsSource = [
  500. new BABYLON.Vector3(0, 0, 1),
  501. new BABYLON.Vector3(0, 0, -1),
  502. new BABYLON.Vector3(1, 0, 0),
  503. new BABYLON.Vector3(-1, 0, 0),
  504. new BABYLON.Vector3(0, 1, 0),
  505. new BABYLON.Vector3(0, -1, 0)
  506. ];
  507. var indices = [];
  508. var positions = [];
  509. var normals = [];
  510. var uvs = [];
  511. var width = options.width || options.size || 1;
  512. var height = options.height || options.size || 1;
  513. var depth = options.depth || options.size || 1;
  514. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  515. var faceUV = options.faceUV || new Array(6);
  516. var faceColors = options.faceColors;
  517. var colors = [];
  518. // default face colors and UV if undefined
  519. for (var f = 0; f < 6; f++) {
  520. if (faceUV[f] === undefined) {
  521. faceUV[f] = new BABYLON.Vector4(0, 0, 1, 1);
  522. }
  523. if (faceColors && faceColors[f] === undefined) {
  524. faceColors[f] = new BABYLON.Color4(1, 1, 1, 1);
  525. }
  526. }
  527. var scaleVector = new BABYLON.Vector3(width / 2, height / 2, depth / 2);
  528. // Create each face in turn.
  529. for (var index = 0; index < normalsSource.length; index++) {
  530. var normal = normalsSource[index];
  531. // Get two vectors perpendicular to the face normal and to each other.
  532. var side1 = new BABYLON.Vector3(normal.y, normal.z, normal.x);
  533. var side2 = BABYLON.Vector3.Cross(normal, side1);
  534. // Six indices (two triangles) per face.
  535. var verticesLength = positions.length / 3;
  536. indices.push(verticesLength);
  537. indices.push(verticesLength + 1);
  538. indices.push(verticesLength + 2);
  539. indices.push(verticesLength);
  540. indices.push(verticesLength + 2);
  541. indices.push(verticesLength + 3);
  542. // Four vertices per face.
  543. var vertex = normal.subtract(side1).subtract(side2).multiply(scaleVector);
  544. positions.push(vertex.x, vertex.y, vertex.z);
  545. normals.push(normal.x, normal.y, normal.z);
  546. uvs.push(faceUV[index].z, faceUV[index].w);
  547. if (faceColors) {
  548. colors.push(faceColors[index].r, faceColors[index].g, faceColors[index].b, faceColors[index].a);
  549. }
  550. vertex = normal.subtract(side1).add(side2).multiply(scaleVector);
  551. positions.push(vertex.x, vertex.y, vertex.z);
  552. normals.push(normal.x, normal.y, normal.z);
  553. uvs.push(faceUV[index].x, faceUV[index].w);
  554. if (faceColors) {
  555. colors.push(faceColors[index].r, faceColors[index].g, faceColors[index].b, faceColors[index].a);
  556. }
  557. vertex = normal.add(side1).add(side2).multiply(scaleVector);
  558. positions.push(vertex.x, vertex.y, vertex.z);
  559. normals.push(normal.x, normal.y, normal.z);
  560. uvs.push(faceUV[index].x, faceUV[index].y);
  561. if (faceColors) {
  562. colors.push(faceColors[index].r, faceColors[index].g, faceColors[index].b, faceColors[index].a);
  563. }
  564. vertex = normal.add(side1).subtract(side2).multiply(scaleVector);
  565. positions.push(vertex.x, vertex.y, vertex.z);
  566. normals.push(normal.x, normal.y, normal.z);
  567. uvs.push(faceUV[index].z, faceUV[index].y);
  568. if (faceColors) {
  569. colors.push(faceColors[index].r, faceColors[index].g, faceColors[index].b, faceColors[index].a);
  570. }
  571. }
  572. // sides
  573. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  574. // Result
  575. var vertexData = new VertexData();
  576. vertexData.indices = indices;
  577. vertexData.positions = positions;
  578. vertexData.normals = normals;
  579. vertexData.uvs = uvs;
  580. if (faceColors) {
  581. var totalColors = (sideOrientation === BABYLON.Mesh.DOUBLESIDE) ? colors.concat(colors) : colors;
  582. vertexData.colors = totalColors;
  583. }
  584. return vertexData;
  585. };
  586. VertexData.CreateSphere = function (options) {
  587. var segments = options.segments || 32;
  588. var diameterX = options.diameterX || options.diameter || 1;
  589. var diameterY = options.diameterY || options.diameter || 1;
  590. var diameterZ = options.diameterZ || options.diameter || 1;
  591. var arc = (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
  592. var slice = (options.slice <= 0) ? 1.0 : options.slice || 1.0;
  593. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  594. var radius = new BABYLON.Vector3(diameterX / 2, diameterY / 2, diameterZ / 2);
  595. var totalZRotationSteps = 2 + segments;
  596. var totalYRotationSteps = 2 * totalZRotationSteps;
  597. var indices = [];
  598. var positions = [];
  599. var normals = [];
  600. var uvs = [];
  601. for (var zRotationStep = 0; zRotationStep <= totalZRotationSteps; zRotationStep++) {
  602. var normalizedZ = zRotationStep / totalZRotationSteps;
  603. var angleZ = normalizedZ * Math.PI * slice;
  604. for (var yRotationStep = 0; yRotationStep <= totalYRotationSteps; yRotationStep++) {
  605. var normalizedY = yRotationStep / totalYRotationSteps;
  606. var angleY = normalizedY * Math.PI * 2 * arc;
  607. var rotationZ = BABYLON.Matrix.RotationZ(-angleZ);
  608. var rotationY = BABYLON.Matrix.RotationY(angleY);
  609. var afterRotZ = BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.Up(), rotationZ);
  610. var complete = BABYLON.Vector3.TransformCoordinates(afterRotZ, rotationY);
  611. var vertex = complete.multiply(radius);
  612. var normal = complete.divide(radius).normalize();
  613. positions.push(vertex.x, vertex.y, vertex.z);
  614. normals.push(normal.x, normal.y, normal.z);
  615. uvs.push(normalizedY, normalizedZ);
  616. }
  617. if (zRotationStep > 0) {
  618. var verticesCount = positions.length / 3;
  619. for (var firstIndex = verticesCount - 2 * (totalYRotationSteps + 1); (firstIndex + totalYRotationSteps + 2) < verticesCount; firstIndex++) {
  620. indices.push((firstIndex));
  621. indices.push((firstIndex + 1));
  622. indices.push(firstIndex + totalYRotationSteps + 1);
  623. indices.push((firstIndex + totalYRotationSteps + 1));
  624. indices.push((firstIndex + 1));
  625. indices.push((firstIndex + totalYRotationSteps + 2));
  626. }
  627. }
  628. }
  629. // Sides
  630. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  631. // Result
  632. var vertexData = new VertexData();
  633. vertexData.indices = indices;
  634. vertexData.positions = positions;
  635. vertexData.normals = normals;
  636. vertexData.uvs = uvs;
  637. return vertexData;
  638. };
  639. // Cylinder and cone
  640. VertexData.CreateCylinder = function (options) {
  641. var height = options.height || 2;
  642. var diameterTop = (options.diameterTop === 0) ? 0 : options.diameterTop || options.diameter || 1;
  643. var diameterBottom = options.diameterBottom || options.diameter || 1;
  644. var tessellation = options.tessellation || 24;
  645. var subdivisions = options.subdivisions || 1;
  646. var hasRings = options.hasRings;
  647. var enclose = options.enclose;
  648. var arc = (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
  649. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  650. var faceUV = options.faceUV || new Array(3);
  651. var faceColors = options.faceColors;
  652. // default face colors and UV if undefined
  653. var quadNb = (arc !== 1 && enclose) ? 2 : 0;
  654. var ringNb = (hasRings) ? subdivisions : 1;
  655. var surfaceNb = 2 + (1 + quadNb) * ringNb;
  656. var f;
  657. for (f = 0; f < surfaceNb; f++) {
  658. if (faceColors && faceColors[f] === undefined) {
  659. faceColors[f] = new BABYLON.Color4(1, 1, 1, 1);
  660. }
  661. }
  662. for (f = 0; f < surfaceNb; f++) {
  663. if (faceUV && faceUV[f] === undefined) {
  664. faceUV[f] = new BABYLON.Vector4(0, 0, 1, 1);
  665. }
  666. }
  667. var indices = [];
  668. var positions = [];
  669. var normals = [];
  670. var uvs = [];
  671. var colors = [];
  672. var angle_step = Math.PI * 2 * arc / tessellation;
  673. var angle;
  674. var h;
  675. var radius;
  676. var tan = (diameterBottom - diameterTop) / 2 / height;
  677. var ringVertex = BABYLON.Vector3.Zero();
  678. var ringNormal = BABYLON.Vector3.Zero();
  679. var ringFirstVertex = BABYLON.Vector3.Zero();
  680. var ringFirstNormal = BABYLON.Vector3.Zero();
  681. var quadNormal = BABYLON.Vector3.Zero();
  682. var Y = BABYLON.Axis.Y;
  683. // positions, normals, uvs
  684. var i;
  685. var j;
  686. var r;
  687. var ringIdx = 1;
  688. var s = 1; // surface index
  689. var cs = 0;
  690. var v = 0;
  691. for (i = 0; i <= subdivisions; i++) {
  692. h = i / subdivisions;
  693. radius = (h * (diameterTop - diameterBottom) + diameterBottom) / 2;
  694. ringIdx = (hasRings && i !== 0 && i !== subdivisions) ? 2 : 1;
  695. for (r = 0; r < ringIdx; r++) {
  696. if (hasRings) {
  697. s += r;
  698. }
  699. if (enclose) {
  700. s += 2 * r;
  701. }
  702. for (j = 0; j <= tessellation; j++) {
  703. angle = j * angle_step;
  704. // position
  705. ringVertex.x = Math.cos(-angle) * radius;
  706. ringVertex.y = -height / 2 + h * height;
  707. ringVertex.z = Math.sin(-angle) * radius;
  708. // normal
  709. if (diameterTop === 0 && i === subdivisions) {
  710. // if no top cap, reuse former normals
  711. ringNormal.x = normals[normals.length - (tessellation + 1) * 3];
  712. ringNormal.y = normals[normals.length - (tessellation + 1) * 3 + 1];
  713. ringNormal.z = normals[normals.length - (tessellation + 1) * 3 + 2];
  714. }
  715. else {
  716. ringNormal.x = ringVertex.x;
  717. ringNormal.z = ringVertex.z;
  718. ringNormal.y = Math.sqrt(ringNormal.x * ringNormal.x + ringNormal.z * ringNormal.z) * tan;
  719. ringNormal.normalize();
  720. }
  721. // keep first ring vertex values for enclose
  722. if (j === 0) {
  723. ringFirstVertex.copyFrom(ringVertex);
  724. ringFirstNormal.copyFrom(ringNormal);
  725. }
  726. positions.push(ringVertex.x, ringVertex.y, ringVertex.z);
  727. normals.push(ringNormal.x, ringNormal.y, ringNormal.z);
  728. if (hasRings) {
  729. v = (cs !== s) ? faceUV[s].y : faceUV[s].w;
  730. }
  731. else {
  732. v = faceUV[s].y + (faceUV[s].w - faceUV[s].y) * h;
  733. }
  734. uvs.push(faceUV[s].x + (faceUV[s].z - faceUV[s].x) * j / tessellation, v);
  735. if (faceColors) {
  736. colors.push(faceColors[s].r, faceColors[s].g, faceColors[s].b, faceColors[s].a);
  737. }
  738. }
  739. // if enclose, add four vertices and their dedicated normals
  740. if (arc !== 1 && enclose) {
  741. positions.push(ringVertex.x, ringVertex.y, ringVertex.z);
  742. positions.push(0, ringVertex.y, 0);
  743. positions.push(0, ringVertex.y, 0);
  744. positions.push(ringFirstVertex.x, ringFirstVertex.y, ringFirstVertex.z);
  745. BABYLON.Vector3.CrossToRef(Y, ringNormal, quadNormal);
  746. quadNormal.normalize();
  747. normals.push(quadNormal.x, quadNormal.y, quadNormal.z, quadNormal.x, quadNormal.y, quadNormal.z);
  748. BABYLON.Vector3.CrossToRef(ringFirstNormal, Y, quadNormal);
  749. quadNormal.normalize();
  750. normals.push(quadNormal.x, quadNormal.y, quadNormal.z, quadNormal.x, quadNormal.y, quadNormal.z);
  751. if (hasRings) {
  752. v = (cs !== s) ? faceUV[s + 1].y : faceUV[s + 1].w;
  753. }
  754. else {
  755. v = faceUV[s + 1].y + (faceUV[s + 1].w - faceUV[s + 1].y) * h;
  756. }
  757. uvs.push(faceUV[s + 1].x, v);
  758. uvs.push(faceUV[s + 1].z, v);
  759. if (hasRings) {
  760. v = (cs !== s) ? faceUV[s + 2].y : faceUV[s + 2].w;
  761. }
  762. else {
  763. v = faceUV[s + 2].y + (faceUV[s + 2].w - faceUV[s + 2].y) * h;
  764. }
  765. uvs.push(faceUV[s + 2].x, v);
  766. uvs.push(faceUV[s + 2].z, v);
  767. if (faceColors) {
  768. colors.push(faceColors[s + 1].r, faceColors[s + 1].g, faceColors[s + 1].b, faceColors[s + 1].a);
  769. colors.push(faceColors[s + 1].r, faceColors[s + 1].g, faceColors[s + 1].b, faceColors[s + 1].a);
  770. colors.push(faceColors[s + 2].r, faceColors[s + 2].g, faceColors[s + 2].b, faceColors[s + 2].a);
  771. colors.push(faceColors[s + 2].r, faceColors[s + 2].g, faceColors[s + 2].b, faceColors[s + 2].a);
  772. }
  773. }
  774. if (cs !== s) {
  775. cs = s;
  776. }
  777. }
  778. }
  779. // indices
  780. var e = (arc !== 1 && enclose) ? tessellation + 4 : tessellation; // correction of number of iteration if enclose
  781. var s;
  782. i = 0;
  783. for (s = 0; s < subdivisions; s++) {
  784. for (j = 0; j < tessellation; j++) {
  785. var i0 = i * (e + 1) + j;
  786. var i1 = (i + 1) * (e + 1) + j;
  787. var i2 = i * (e + 1) + (j + 1);
  788. var i3 = (i + 1) * (e + 1) + (j + 1);
  789. indices.push(i0, i1, i2);
  790. indices.push(i3, i2, i1);
  791. }
  792. if (arc !== 1 && enclose) {
  793. indices.push(i0 + 2, i1 + 2, i2 + 2);
  794. indices.push(i3 + 2, i2 + 2, i1 + 2);
  795. indices.push(i0 + 4, i1 + 4, i2 + 4);
  796. indices.push(i3 + 4, i2 + 4, i1 + 4);
  797. }
  798. i = (hasRings) ? (i + 2) : (i + 1);
  799. }
  800. // Caps
  801. var createCylinderCap = function (isTop) {
  802. var radius = isTop ? diameterTop / 2 : diameterBottom / 2;
  803. if (radius === 0) {
  804. return;
  805. }
  806. // Cap positions, normals & uvs
  807. var angle;
  808. var circleVector;
  809. var i;
  810. var u = (isTop) ? faceUV[surfaceNb - 1] : faceUV[0];
  811. var c;
  812. if (faceColors) {
  813. c = (isTop) ? faceColors[surfaceNb - 1] : faceColors[0];
  814. }
  815. // cap center
  816. var vbase = positions.length / 3;
  817. var offset = isTop ? height / 2 : -height / 2;
  818. var center = new BABYLON.Vector3(0, offset, 0);
  819. positions.push(center.x, center.y, center.z);
  820. normals.push(0, isTop ? 1 : -1, 0);
  821. uvs.push(u.x + (u.z - u.x) * 0.5, u.y + (u.w - u.y) * 0.5);
  822. if (faceColors) {
  823. colors.push(c.r, c.g, c.b, c.a);
  824. }
  825. var textureScale = new BABYLON.Vector2(0.5, 0.5);
  826. for (i = 0; i <= tessellation; i++) {
  827. angle = Math.PI * 2 * i * arc / tessellation;
  828. var cos = Math.cos(-angle);
  829. var sin = Math.sin(-angle);
  830. circleVector = new BABYLON.Vector3(cos * radius, offset, sin * radius);
  831. var textureCoordinate = new BABYLON.Vector2(cos * textureScale.x + 0.5, sin * textureScale.y + 0.5);
  832. positions.push(circleVector.x, circleVector.y, circleVector.z);
  833. normals.push(0, isTop ? 1 : -1, 0);
  834. uvs.push(u.x + (u.z - u.x) * textureCoordinate.x, u.y + (u.w - u.y) * textureCoordinate.y);
  835. if (faceColors) {
  836. colors.push(c.r, c.g, c.b, c.a);
  837. }
  838. }
  839. // Cap indices
  840. for (i = 0; i < tessellation; i++) {
  841. if (!isTop) {
  842. indices.push(vbase);
  843. indices.push(vbase + (i + 1));
  844. indices.push(vbase + (i + 2));
  845. }
  846. else {
  847. indices.push(vbase);
  848. indices.push(vbase + (i + 2));
  849. indices.push(vbase + (i + 1));
  850. }
  851. }
  852. };
  853. // add caps to geometry
  854. createCylinderCap(false);
  855. createCylinderCap(true);
  856. // Sides
  857. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  858. var vertexData = new VertexData();
  859. vertexData.indices = indices;
  860. vertexData.positions = positions;
  861. vertexData.normals = normals;
  862. vertexData.uvs = uvs;
  863. if (faceColors) {
  864. vertexData.colors = colors;
  865. }
  866. return vertexData;
  867. };
  868. VertexData.CreateTorus = function (options) {
  869. var indices = [];
  870. var positions = [];
  871. var normals = [];
  872. var uvs = [];
  873. var diameter = options.diameter || 1;
  874. var thickness = options.thickness || 0.5;
  875. var tessellation = options.tessellation || 16;
  876. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  877. var stride = tessellation + 1;
  878. for (var i = 0; i <= tessellation; i++) {
  879. var u = i / tessellation;
  880. var outerAngle = i * Math.PI * 2.0 / tessellation - Math.PI / 2.0;
  881. var transform = BABYLON.Matrix.Translation(diameter / 2.0, 0, 0).multiply(BABYLON.Matrix.RotationY(outerAngle));
  882. for (var j = 0; j <= tessellation; j++) {
  883. var v = 1 - j / tessellation;
  884. var innerAngle = j * Math.PI * 2.0 / tessellation + Math.PI;
  885. var dx = Math.cos(innerAngle);
  886. var dy = Math.sin(innerAngle);
  887. // Create a vertex.
  888. var normal = new BABYLON.Vector3(dx, dy, 0);
  889. var position = normal.scale(thickness / 2);
  890. var textureCoordinate = new BABYLON.Vector2(u, v);
  891. position = BABYLON.Vector3.TransformCoordinates(position, transform);
  892. normal = BABYLON.Vector3.TransformNormal(normal, transform);
  893. positions.push(position.x, position.y, position.z);
  894. normals.push(normal.x, normal.y, normal.z);
  895. uvs.push(textureCoordinate.x, textureCoordinate.y);
  896. // And create indices for two triangles.
  897. var nextI = (i + 1) % stride;
  898. var nextJ = (j + 1) % stride;
  899. indices.push(i * stride + j);
  900. indices.push(i * stride + nextJ);
  901. indices.push(nextI * stride + j);
  902. indices.push(i * stride + nextJ);
  903. indices.push(nextI * stride + nextJ);
  904. indices.push(nextI * stride + j);
  905. }
  906. }
  907. // Sides
  908. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  909. // Result
  910. var vertexData = new VertexData();
  911. vertexData.indices = indices;
  912. vertexData.positions = positions;
  913. vertexData.normals = normals;
  914. vertexData.uvs = uvs;
  915. return vertexData;
  916. };
  917. VertexData.CreateLineSystem = function (options) {
  918. var indices = [];
  919. var positions = [];
  920. var lines = options.lines;
  921. var idx = 0;
  922. for (var l = 0; l < lines.length; l++) {
  923. var points = lines[l];
  924. for (var index = 0; index < points.length; index++) {
  925. positions.push(points[index].x, points[index].y, points[index].z);
  926. if (index > 0) {
  927. indices.push(idx - 1);
  928. indices.push(idx);
  929. }
  930. idx++;
  931. }
  932. }
  933. var vertexData = new VertexData();
  934. vertexData.indices = indices;
  935. vertexData.positions = positions;
  936. return vertexData;
  937. };
  938. VertexData.CreateDashedLines = function (options) {
  939. var dashSize = options.dashSize || 3;
  940. var gapSize = options.gapSize || 1;
  941. var dashNb = options.dashNb || 200;
  942. var points = options.points;
  943. var positions = new Array();
  944. var indices = new Array();
  945. var curvect = BABYLON.Vector3.Zero();
  946. var lg = 0;
  947. var nb = 0;
  948. var shft = 0;
  949. var dashshft = 0;
  950. var curshft = 0;
  951. var idx = 0;
  952. var i = 0;
  953. for (i = 0; i < points.length - 1; i++) {
  954. points[i + 1].subtractToRef(points[i], curvect);
  955. lg += curvect.length();
  956. }
  957. shft = lg / dashNb;
  958. dashshft = dashSize * shft / (dashSize + gapSize);
  959. for (i = 0; i < points.length - 1; i++) {
  960. points[i + 1].subtractToRef(points[i], curvect);
  961. nb = Math.floor(curvect.length() / shft);
  962. curvect.normalize();
  963. for (var j = 0; j < nb; j++) {
  964. curshft = shft * j;
  965. positions.push(points[i].x + curshft * curvect.x, points[i].y + curshft * curvect.y, points[i].z + curshft * curvect.z);
  966. positions.push(points[i].x + (curshft + dashshft) * curvect.x, points[i].y + (curshft + dashshft) * curvect.y, points[i].z + (curshft + dashshft) * curvect.z);
  967. indices.push(idx, idx + 1);
  968. idx += 2;
  969. }
  970. }
  971. // Result
  972. var vertexData = new VertexData();
  973. vertexData.positions = positions;
  974. vertexData.indices = indices;
  975. return vertexData;
  976. };
  977. VertexData.CreateGround = function (options) {
  978. var indices = [];
  979. var positions = [];
  980. var normals = [];
  981. var uvs = [];
  982. var row, col;
  983. var width = options.width || 1;
  984. var height = options.height || 1;
  985. var subdivisions = options.subdivisions || 1;
  986. for (row = 0; row <= subdivisions; row++) {
  987. for (col = 0; col <= subdivisions; col++) {
  988. var position = new BABYLON.Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));
  989. var normal = new BABYLON.Vector3(0, 1.0, 0);
  990. positions.push(position.x, position.y, position.z);
  991. normals.push(normal.x, normal.y, normal.z);
  992. uvs.push(col / subdivisions, 1.0 - row / subdivisions);
  993. }
  994. }
  995. for (row = 0; row < subdivisions; row++) {
  996. for (col = 0; col < subdivisions; col++) {
  997. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  998. indices.push(col + 1 + row * (subdivisions + 1));
  999. indices.push(col + row * (subdivisions + 1));
  1000. indices.push(col + (row + 1) * (subdivisions + 1));
  1001. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  1002. indices.push(col + row * (subdivisions + 1));
  1003. }
  1004. }
  1005. // Result
  1006. var vertexData = new VertexData();
  1007. vertexData.indices = indices;
  1008. vertexData.positions = positions;
  1009. vertexData.normals = normals;
  1010. vertexData.uvs = uvs;
  1011. return vertexData;
  1012. };
  1013. VertexData.CreateTiledGround = function (options) {
  1014. var xmin = options.xmin;
  1015. var zmin = options.zmin;
  1016. var xmax = options.xmax;
  1017. var zmax = options.zmax;
  1018. var subdivisions = options.subdivisions || { w: 1, h: 1 };
  1019. var precision = options.precision || { w: 1, h: 1 };
  1020. var indices = [];
  1021. var positions = [];
  1022. var normals = [];
  1023. var uvs = [];
  1024. var row, col, tileRow, tileCol;
  1025. subdivisions.h = (subdivisions.w < 1) ? 1 : subdivisions.h;
  1026. subdivisions.w = (subdivisions.w < 1) ? 1 : subdivisions.w;
  1027. precision.w = (precision.w < 1) ? 1 : precision.w;
  1028. precision.h = (precision.h < 1) ? 1 : precision.h;
  1029. var tileSize = {
  1030. 'w': (xmax - xmin) / subdivisions.w,
  1031. 'h': (zmax - zmin) / subdivisions.h
  1032. };
  1033. function applyTile(xTileMin, zTileMin, xTileMax, zTileMax) {
  1034. // Indices
  1035. var base = positions.length / 3;
  1036. var rowLength = precision.w + 1;
  1037. for (row = 0; row < precision.h; row++) {
  1038. for (col = 0; col < precision.w; col++) {
  1039. var square = [
  1040. base + col + row * rowLength,
  1041. base + (col + 1) + row * rowLength,
  1042. base + (col + 1) + (row + 1) * rowLength,
  1043. base + col + (row + 1) * rowLength
  1044. ];
  1045. indices.push(square[1]);
  1046. indices.push(square[2]);
  1047. indices.push(square[3]);
  1048. indices.push(square[0]);
  1049. indices.push(square[1]);
  1050. indices.push(square[3]);
  1051. }
  1052. }
  1053. // Position, normals and uvs
  1054. var position = BABYLON.Vector3.Zero();
  1055. var normal = new BABYLON.Vector3(0, 1.0, 0);
  1056. for (row = 0; row <= precision.h; row++) {
  1057. position.z = (row * (zTileMax - zTileMin)) / precision.h + zTileMin;
  1058. for (col = 0; col <= precision.w; col++) {
  1059. position.x = (col * (xTileMax - xTileMin)) / precision.w + xTileMin;
  1060. position.y = 0;
  1061. positions.push(position.x, position.y, position.z);
  1062. normals.push(normal.x, normal.y, normal.z);
  1063. uvs.push(col / precision.w, row / precision.h);
  1064. }
  1065. }
  1066. }
  1067. for (tileRow = 0; tileRow < subdivisions.h; tileRow++) {
  1068. for (tileCol = 0; tileCol < subdivisions.w; tileCol++) {
  1069. applyTile(xmin + tileCol * tileSize.w, zmin + tileRow * tileSize.h, xmin + (tileCol + 1) * tileSize.w, zmin + (tileRow + 1) * tileSize.h);
  1070. }
  1071. }
  1072. // Result
  1073. var vertexData = new VertexData();
  1074. vertexData.indices = indices;
  1075. vertexData.positions = positions;
  1076. vertexData.normals = normals;
  1077. vertexData.uvs = uvs;
  1078. return vertexData;
  1079. };
  1080. VertexData.CreateGroundFromHeightMap = function (options) {
  1081. var indices = [];
  1082. var positions = [];
  1083. var normals = [];
  1084. var uvs = [];
  1085. var row, col;
  1086. // Vertices
  1087. for (row = 0; row <= options.subdivisions; row++) {
  1088. for (col = 0; col <= options.subdivisions; col++) {
  1089. var position = new BABYLON.Vector3((col * options.width) / options.subdivisions - (options.width / 2.0), 0, ((options.subdivisions - row) * options.height) / options.subdivisions - (options.height / 2.0));
  1090. // Compute height
  1091. var heightMapX = (((position.x + options.width / 2) / options.width) * (options.bufferWidth - 1)) | 0;
  1092. var heightMapY = ((1.0 - (position.z + options.height / 2) / options.height) * (options.bufferHeight - 1)) | 0;
  1093. var pos = (heightMapX + heightMapY * options.bufferWidth) * 4;
  1094. var r = options.buffer[pos] / 255.0;
  1095. var g = options.buffer[pos + 1] / 255.0;
  1096. var b = options.buffer[pos + 2] / 255.0;
  1097. var gradient = r * 0.3 + g * 0.59 + b * 0.11;
  1098. position.y = options.minHeight + (options.maxHeight - options.minHeight) * gradient;
  1099. // Add vertex
  1100. positions.push(position.x, position.y, position.z);
  1101. normals.push(0, 0, 0);
  1102. uvs.push(col / options.subdivisions, 1.0 - row / options.subdivisions);
  1103. }
  1104. }
  1105. // Indices
  1106. for (row = 0; row < options.subdivisions; row++) {
  1107. for (col = 0; col < options.subdivisions; col++) {
  1108. indices.push(col + 1 + (row + 1) * (options.subdivisions + 1));
  1109. indices.push(col + 1 + row * (options.subdivisions + 1));
  1110. indices.push(col + row * (options.subdivisions + 1));
  1111. indices.push(col + (row + 1) * (options.subdivisions + 1));
  1112. indices.push(col + 1 + (row + 1) * (options.subdivisions + 1));
  1113. indices.push(col + row * (options.subdivisions + 1));
  1114. }
  1115. }
  1116. // Normals
  1117. VertexData.ComputeNormals(positions, indices, normals);
  1118. // Result
  1119. var vertexData = new VertexData();
  1120. vertexData.indices = indices;
  1121. vertexData.positions = positions;
  1122. vertexData.normals = normals;
  1123. vertexData.uvs = uvs;
  1124. return vertexData;
  1125. };
  1126. VertexData.CreatePlane = function (options) {
  1127. var indices = [];
  1128. var positions = [];
  1129. var normals = [];
  1130. var uvs = [];
  1131. var width = options.width || options.size || 1;
  1132. var height = options.height || options.size || 1;
  1133. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  1134. // Vertices
  1135. var halfWidth = width / 2.0;
  1136. var halfHeight = height / 2.0;
  1137. positions.push(-halfWidth, -halfHeight, 0);
  1138. normals.push(0, 0, -1.0);
  1139. uvs.push(0.0, 0.0);
  1140. positions.push(halfWidth, -halfHeight, 0);
  1141. normals.push(0, 0, -1.0);
  1142. uvs.push(1.0, 0.0);
  1143. positions.push(halfWidth, halfHeight, 0);
  1144. normals.push(0, 0, -1.0);
  1145. uvs.push(1.0, 1.0);
  1146. positions.push(-halfWidth, halfHeight, 0);
  1147. normals.push(0, 0, -1.0);
  1148. uvs.push(0.0, 1.0);
  1149. // Indices
  1150. indices.push(0);
  1151. indices.push(1);
  1152. indices.push(2);
  1153. indices.push(0);
  1154. indices.push(2);
  1155. indices.push(3);
  1156. // Sides
  1157. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  1158. // Result
  1159. var vertexData = new VertexData();
  1160. vertexData.indices = indices;
  1161. vertexData.positions = positions;
  1162. vertexData.normals = normals;
  1163. vertexData.uvs = uvs;
  1164. return vertexData;
  1165. };
  1166. VertexData.CreateDisc = function (options) {
  1167. var positions = [];
  1168. var indices = [];
  1169. var normals = [];
  1170. var uvs = [];
  1171. var radius = options.radius || 0.5;
  1172. var tessellation = options.tessellation || 64;
  1173. var arc = (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
  1174. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  1175. // positions and uvs
  1176. positions.push(0, 0, 0); // disc center first
  1177. uvs.push(0.5, 0.5);
  1178. var theta = Math.PI * 2 * arc;
  1179. var step = theta / tessellation;
  1180. for (var a = 0; a < theta; a += step) {
  1181. var x = Math.cos(a);
  1182. var y = Math.sin(a);
  1183. var u = (x + 1) / 2;
  1184. var v = (1 - y) / 2;
  1185. positions.push(radius * x, radius * y, 0);
  1186. uvs.push(u, v);
  1187. }
  1188. if (arc === 1) {
  1189. positions.push(positions[3], positions[4], positions[5]); // close the circle
  1190. uvs.push(uvs[2], uvs[3]);
  1191. }
  1192. //indices
  1193. var vertexNb = positions.length / 3;
  1194. for (var i = 1; i < vertexNb - 1; i++) {
  1195. indices.push(i + 1, 0, i);
  1196. }
  1197. // result
  1198. VertexData.ComputeNormals(positions, indices, normals);
  1199. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  1200. var vertexData = new VertexData();
  1201. vertexData.indices = indices;
  1202. vertexData.positions = positions;
  1203. vertexData.normals = normals;
  1204. vertexData.uvs = uvs;
  1205. return vertexData;
  1206. };
  1207. VertexData.CreateIcoSphere = function (options) {
  1208. var sideOrientation = options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  1209. var radius = options.radius || 1;
  1210. var flat = (options.flat === undefined) ? true : options.flat;
  1211. var subdivisions = options.subdivisions || 4;
  1212. var radiusX = options.radiusX || radius;
  1213. var radiusY = options.radiusY || radius;
  1214. var radiusZ = options.radiusZ || radius;
  1215. var t = (1 + Math.sqrt(5)) / 2;
  1216. // 12 vertex x,y,z
  1217. var ico_vertices = [
  1218. -1, t, -0, 1, t, 0, -1, -t, 0, 1, -t, 0,
  1219. 0, -1, -t, 0, 1, -t, 0, -1, t, 0, 1, t,
  1220. t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0, -1 // v8-11
  1221. ];
  1222. // index of 3 vertex makes a face of icopshere
  1223. var ico_indices = [
  1224. 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 12, 22, 23,
  1225. 1, 5, 20, 5, 11, 4, 23, 22, 13, 22, 18, 6, 7, 1, 8,
  1226. 14, 21, 4, 14, 4, 2, 16, 13, 6, 15, 6, 19, 3, 8, 9,
  1227. 4, 21, 5, 13, 17, 23, 6, 13, 22, 19, 6, 18, 9, 8, 1
  1228. ];
  1229. // vertex for uv have aliased position, not for UV
  1230. var vertices_unalias_id = [
  1231. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
  1232. // vertex alias
  1233. 0,
  1234. 2,
  1235. 3,
  1236. 3,
  1237. 3,
  1238. 4,
  1239. 7,
  1240. 8,
  1241. 9,
  1242. 9,
  1243. 10,
  1244. 11 // 23: B + 12
  1245. ];
  1246. // uv as integer step (not pixels !)
  1247. var ico_vertexuv = [
  1248. 5, 1, 3, 1, 6, 4, 0, 0,
  1249. 5, 3, 4, 2, 2, 2, 4, 0,
  1250. 2, 0, 1, 1, 6, 0, 6, 2,
  1251. // vertex alias (for same vertex on different faces)
  1252. 0, 4,
  1253. 3, 3,
  1254. 4, 4,
  1255. 3, 1,
  1256. 4, 2,
  1257. 4, 4,
  1258. 0, 2,
  1259. 1, 1,
  1260. 2, 2,
  1261. 3, 3,
  1262. 1, 3,
  1263. 2, 4 // 23: B + 12
  1264. ];
  1265. // Vertices[0, 1, ...9, A, B] : position on UV plane
  1266. // '+' indicate duplicate position to be fixed (3,9:0,2,3,4,7,8,A,B)
  1267. // First island of uv mapping
  1268. // v = 4h 3+ 2
  1269. // v = 3h 9+ 4
  1270. // v = 2h 9+ 5 B
  1271. // v = 1h 9 1 0
  1272. // v = 0h 3 8 7 A
  1273. // u = 0 1 2 3 4 5 6 *a
  1274. // Second island of uv mapping
  1275. // v = 4h 0+ B+ 4+
  1276. // v = 3h A+ 2+
  1277. // v = 2h 7+ 6 3+
  1278. // v = 1h 8+ 3+
  1279. // v = 0h
  1280. // u = 0 1 2 3 4 5 6 *a
  1281. // Face layout on texture UV mapping
  1282. // ============
  1283. // \ 4 /\ 16 / ======
  1284. // \ / \ / /\ 11 /
  1285. // \/ 7 \/ / \ /
  1286. // ======= / 10 \/
  1287. // /\ 17 /\ =======
  1288. // / \ / \ \ 15 /\
  1289. // / 8 \/ 12 \ \ / \
  1290. // ============ \/ 6 \
  1291. // \ 18 /\ ============
  1292. // \ / \ \ 5 /\ 0 /
  1293. // \/ 13 \ \ / \ /
  1294. // ======= \/ 1 \/
  1295. // =============
  1296. // /\ 19 /\ 2 /\
  1297. // / \ / \ / \
  1298. // / 14 \/ 9 \/ 3 \
  1299. // ===================
  1300. // uv step is u:1 or 0.5, v:cos(30)=sqrt(3)/2, ratio approx is 84/97
  1301. var ustep = 138 / 1024;
  1302. var vstep = 239 / 1024;
  1303. var uoffset = 60 / 1024;
  1304. var voffset = 26 / 1024;
  1305. // Second island should have margin, not to touch the first island
  1306. // avoid any borderline artefact in pixel rounding
  1307. var island_u_offset = -40 / 1024;
  1308. var island_v_offset = +20 / 1024;
  1309. // face is either island 0 or 1 :
  1310. // second island is for faces : [4, 7, 8, 12, 13, 16, 17, 18]
  1311. var island = [
  1312. 0, 0, 0, 0, 1,
  1313. 0, 0, 1, 1, 0,
  1314. 0, 0, 1, 1, 0,
  1315. 0, 1, 1, 1, 0 // 15 - 19
  1316. ];
  1317. var indices = [];
  1318. var positions = [];
  1319. var normals = [];
  1320. var uvs = [];
  1321. var current_indice = 0;
  1322. // prepare array of 3 vector (empty) (to be worked in place, shared for each face)
  1323. var face_vertex_pos = new Array(3);
  1324. var face_vertex_uv = new Array(3);
  1325. var v012;
  1326. for (v012 = 0; v012 < 3; v012++) {
  1327. face_vertex_pos[v012] = BABYLON.Vector3.Zero();
  1328. face_vertex_uv[v012] = BABYLON.Vector2.Zero();
  1329. }
  1330. // create all with normals
  1331. for (var face = 0; face < 20; face++) {
  1332. // 3 vertex per face
  1333. for (v012 = 0; v012 < 3; v012++) {
  1334. // look up vertex 0,1,2 to its index in 0 to 11 (or 23 including alias)
  1335. var v_id = ico_indices[3 * face + v012];
  1336. // vertex have 3D position (x,y,z)
  1337. face_vertex_pos[v012].copyFromFloats(ico_vertices[3 * vertices_unalias_id[v_id]], ico_vertices[3 * vertices_unalias_id[v_id] + 1], ico_vertices[3 * vertices_unalias_id[v_id] + 2]);
  1338. // Normalize to get normal, then scale to radius
  1339. face_vertex_pos[v012].normalize().scaleInPlace(radius);
  1340. // uv Coordinates from vertex ID
  1341. face_vertex_uv[v012].copyFromFloats(ico_vertexuv[2 * v_id] * ustep + uoffset + island[face] * island_u_offset, ico_vertexuv[2 * v_id + 1] * vstep + voffset + island[face] * island_v_offset);
  1342. }
  1343. // Subdivide the face (interpolate pos, norm, uv)
  1344. // - pos is linear interpolation, then projected to sphere (converge polyhedron to sphere)
  1345. // - norm is linear interpolation of vertex corner normal
  1346. // (to be checked if better to re-calc from face vertex, or if approximation is OK ??? )
  1347. // - uv is linear interpolation
  1348. //
  1349. // Topology is as below for sub-divide by 2
  1350. // vertex shown as v0,v1,v2
  1351. // interp index is i1 to progress in range [v0,v1[
  1352. // interp index is i2 to progress in range [v0,v2[
  1353. // face index as (i1,i2) for /\ : (i1,i2),(i1+1,i2),(i1,i2+1)
  1354. // and (i1,i2)' for \/ : (i1+1,i2),(i1+1,i2+1),(i1,i2+1)
  1355. //
  1356. //
  1357. // i2 v2
  1358. // ^ ^
  1359. // / / \
  1360. // / / \
  1361. // / / \
  1362. // / / (0,1) \
  1363. // / #---------\
  1364. // / / \ (0,0)'/ \
  1365. // / / \ / \
  1366. // / / \ / \
  1367. // / / (0,0) \ / (1,0) \
  1368. // / #---------#---------\
  1369. // v0 v1
  1370. //
  1371. // --------------------> i1
  1372. //
  1373. // interp of (i1,i2):
  1374. // along i2 : x0=lerp(v0,v2, i2/S) <---> x1=lerp(v1,v2, i2/S)
  1375. // along i1 : lerp(x0,x1, i1/(S-i2))
  1376. //
  1377. // centroid of triangle is needed to get help normal computation
  1378. // (c1,c2) are used for centroid location
  1379. var interp_vertex = function (i1, i2, c1, c2) {
  1380. // vertex is interpolated from
  1381. // - face_vertex_pos[0..2]
  1382. // - face_vertex_uv[0..2]
  1383. var pos_x0 = BABYLON.Vector3.Lerp(face_vertex_pos[0], face_vertex_pos[2], i2 / subdivisions);
  1384. var pos_x1 = BABYLON.Vector3.Lerp(face_vertex_pos[1], face_vertex_pos[2], i2 / subdivisions);
  1385. var pos_interp = (subdivisions === i2) ? face_vertex_pos[2] : BABYLON.Vector3.Lerp(pos_x0, pos_x1, i1 / (subdivisions - i2));
  1386. pos_interp.normalize();
  1387. var vertex_normal;
  1388. if (flat) {
  1389. // in flat mode, recalculate normal as face centroid normal
  1390. var centroid_x0 = BABYLON.Vector3.Lerp(face_vertex_pos[0], face_vertex_pos[2], c2 / subdivisions);
  1391. var centroid_x1 = BABYLON.Vector3.Lerp(face_vertex_pos[1], face_vertex_pos[2], c2 / subdivisions);
  1392. vertex_normal = BABYLON.Vector3.Lerp(centroid_x0, centroid_x1, c1 / (subdivisions - c2));
  1393. }
  1394. else {
  1395. // in smooth mode, recalculate normal from each single vertex position
  1396. vertex_normal = new BABYLON.Vector3(pos_interp.x, pos_interp.y, pos_interp.z);
  1397. }
  1398. // Vertex normal need correction due to X,Y,Z radius scaling
  1399. vertex_normal.x /= radiusX;
  1400. vertex_normal.y /= radiusY;
  1401. vertex_normal.z /= radiusZ;
  1402. vertex_normal.normalize();
  1403. var uv_x0 = BABYLON.Vector2.Lerp(face_vertex_uv[0], face_vertex_uv[2], i2 / subdivisions);
  1404. var uv_x1 = BABYLON.Vector2.Lerp(face_vertex_uv[1], face_vertex_uv[2], i2 / subdivisions);
  1405. var uv_interp = (subdivisions === i2) ? face_vertex_uv[2] : BABYLON.Vector2.Lerp(uv_x0, uv_x1, i1 / (subdivisions - i2));
  1406. positions.push(pos_interp.x * radiusX, pos_interp.y * radiusY, pos_interp.z * radiusZ);
  1407. normals.push(vertex_normal.x, vertex_normal.y, vertex_normal.z);
  1408. uvs.push(uv_interp.x, uv_interp.y);
  1409. // push each vertex has member of a face
  1410. // Same vertex can bleong to multiple face, it is pushed multiple time (duplicate vertex are present)
  1411. indices.push(current_indice);
  1412. current_indice++;
  1413. };
  1414. for (var i2 = 0; i2 < subdivisions; i2++) {
  1415. for (var i1 = 0; i1 + i2 < subdivisions; i1++) {
  1416. // face : (i1,i2) for /\ :
  1417. // interp for : (i1,i2),(i1+1,i2),(i1,i2+1)
  1418. interp_vertex(i1, i2, i1 + 1.0 / 3, i2 + 1.0 / 3);
  1419. interp_vertex(i1 + 1, i2, i1 + 1.0 / 3, i2 + 1.0 / 3);
  1420. interp_vertex(i1, i2 + 1, i1 + 1.0 / 3, i2 + 1.0 / 3);
  1421. if (i1 + i2 + 1 < subdivisions) {
  1422. // face : (i1,i2)' for \/ :
  1423. // interp for (i1+1,i2),(i1+1,i2+1),(i1,i2+1)
  1424. interp_vertex(i1 + 1, i2, i1 + 2.0 / 3, i2 + 2.0 / 3);
  1425. interp_vertex(i1 + 1, i2 + 1, i1 + 2.0 / 3, i2 + 2.0 / 3);
  1426. interp_vertex(i1, i2 + 1, i1 + 2.0 / 3, i2 + 2.0 / 3);
  1427. }
  1428. }
  1429. }
  1430. }
  1431. // Sides
  1432. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  1433. // Result
  1434. var vertexData = new VertexData();
  1435. vertexData.indices = indices;
  1436. vertexData.positions = positions;
  1437. vertexData.normals = normals;
  1438. vertexData.uvs = uvs;
  1439. return vertexData;
  1440. };
  1441. // inspired from // http://stemkoski.github.io/Three.js/Polyhedra.html
  1442. VertexData.CreatePolyhedron = function (options) {
  1443. // provided polyhedron types :
  1444. // 0 : Tetrahedron, 1 : Octahedron, 2 : Dodecahedron, 3 : Icosahedron, 4 : Rhombicuboctahedron, 5 : Triangular Prism, 6 : Pentagonal Prism, 7 : Hexagonal Prism, 8 : Square Pyramid (J1)
  1445. // 9 : Pentagonal Pyramid (J2), 10 : Triangular Dipyramid (J12), 11 : Pentagonal Dipyramid (J13), 12 : Elongated Square Dipyramid (J15), 13 : Elongated Pentagonal Dipyramid (J16), 14 : Elongated Pentagonal Cupola (J20)
  1446. var polyhedra = [];
  1447. polyhedra[0] = { vertex: [[0, 0, 1.732051], [1.632993, 0, -0.5773503], [-0.8164966, 1.414214, -0.5773503], [-0.8164966, -1.414214, -0.5773503]], face: [[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 2]] };
  1448. polyhedra[1] = { vertex: [[0, 0, 1.414214], [1.414214, 0, 0], [0, 1.414214, 0], [-1.414214, 0, 0], [0, -1.414214, 0], [0, 0, -1.414214]], face: [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [3, 5, 4]] };
  1449. polyhedra[2] = {
  1450. vertex: [[0, 0, 1.070466], [0.7136442, 0, 0.7978784], [-0.3568221, 0.618034, 0.7978784], [-0.3568221, -0.618034, 0.7978784], [0.7978784, 0.618034, 0.3568221], [0.7978784, -0.618034, 0.3568221], [-0.9341724, 0.381966, 0.3568221], [0.1362939, 1, 0.3568221], [0.1362939, -1, 0.3568221], [-0.9341724, -0.381966, 0.3568221], [0.9341724, 0.381966, -0.3568221], [0.9341724, -0.381966, -0.3568221], [-0.7978784, 0.618034, -0.3568221], [-0.1362939, 1, -0.3568221], [-0.1362939, -1, -0.3568221], [-0.7978784, -0.618034, -0.3568221], [0.3568221, 0.618034, -0.7978784], [0.3568221, -0.618034, -0.7978784], [-0.7136442, 0, -0.7978784], [0, 0, -1.070466]],
  1451. face: [[0, 1, 4, 7, 2], [0, 2, 6, 9, 3], [0, 3, 8, 5, 1], [1, 5, 11, 10, 4], [2, 7, 13, 12, 6], [3, 9, 15, 14, 8], [4, 10, 16, 13, 7], [5, 8, 14, 17, 11], [6, 12, 18, 15, 9], [10, 11, 17, 19, 16], [12, 13, 16, 19, 18], [14, 15, 18, 19, 17]]
  1452. };
  1453. polyhedra[3] = {
  1454. vertex: [[0, 0, 1.175571], [1.051462, 0, 0.5257311], [0.3249197, 1, 0.5257311], [-0.8506508, 0.618034, 0.5257311], [-0.8506508, -0.618034, 0.5257311], [0.3249197, -1, 0.5257311], [0.8506508, 0.618034, -0.5257311], [0.8506508, -0.618034, -0.5257311], [-0.3249197, 1, -0.5257311], [-1.051462, 0, -0.5257311], [-0.3249197, -1, -0.5257311], [0, 0, -1.175571]],
  1455. face: [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 5, 7], [1, 7, 6], [1, 6, 2], [2, 6, 8], [2, 8, 3], [3, 8, 9], [3, 9, 4], [4, 9, 10], [4, 10, 5], [5, 10, 7], [6, 7, 11], [6, 11, 8], [7, 10, 11], [8, 11, 9], [9, 11, 10]]
  1456. };
  1457. polyhedra[4] = {
  1458. vertex: [[0, 0, 1.070722], [0.7148135, 0, 0.7971752], [-0.104682, 0.7071068, 0.7971752], [-0.6841528, 0.2071068, 0.7971752], [-0.104682, -0.7071068, 0.7971752], [0.6101315, 0.7071068, 0.5236279], [1.04156, 0.2071068, 0.1367736], [0.6101315, -0.7071068, 0.5236279], [-0.3574067, 1, 0.1367736], [-0.7888348, -0.5, 0.5236279], [-0.9368776, 0.5, 0.1367736], [-0.3574067, -1, 0.1367736], [0.3574067, 1, -0.1367736], [0.9368776, -0.5, -0.1367736], [0.7888348, 0.5, -0.5236279], [0.3574067, -1, -0.1367736], [-0.6101315, 0.7071068, -0.5236279], [-1.04156, -0.2071068, -0.1367736], [-0.6101315, -0.7071068, -0.5236279], [0.104682, 0.7071068, -0.7971752], [0.6841528, -0.2071068, -0.7971752], [0.104682, -0.7071068, -0.7971752], [-0.7148135, 0, -0.7971752], [0, 0, -1.070722]],
  1459. face: [[0, 2, 3], [1, 6, 5], [4, 9, 11], [7, 15, 13], [8, 16, 10], [12, 14, 19], [17, 22, 18], [20, 21, 23], [0, 1, 5, 2], [0, 3, 9, 4], [0, 4, 7, 1], [1, 7, 13, 6], [2, 5, 12, 8], [2, 8, 10, 3], [3, 10, 17, 9], [4, 11, 15, 7], [5, 6, 14, 12], [6, 13, 20, 14], [8, 12, 19, 16], [9, 17, 18, 11], [10, 16, 22, 17], [11, 18, 21, 15], [13, 15, 21, 20], [14, 20, 23, 19], [16, 19, 23, 22], [18, 22, 23, 21]]
  1460. };
  1461. polyhedra[5] = { vertex: [[0, 0, 1.322876], [1.309307, 0, 0.1889822], [-0.9819805, 0.8660254, 0.1889822], [0.1636634, -1.299038, 0.1889822], [0.3273268, 0.8660254, -0.9449112], [-0.8183171, -0.4330127, -0.9449112]], face: [[0, 3, 1], [2, 4, 5], [0, 1, 4, 2], [0, 2, 5, 3], [1, 3, 5, 4]] };
  1462. polyhedra[6] = { vertex: [[0, 0, 1.159953], [1.013464, 0, 0.5642542], [-0.3501431, 0.9510565, 0.5642542], [-0.7715208, -0.6571639, 0.5642542], [0.6633206, 0.9510565, -0.03144481], [0.8682979, -0.6571639, -0.3996071], [-1.121664, 0.2938926, -0.03144481], [-0.2348831, -1.063314, -0.3996071], [0.5181548, 0.2938926, -0.9953061], [-0.5850262, -0.112257, -0.9953061]], face: [[0, 1, 4, 2], [0, 2, 6, 3], [1, 5, 8, 4], [3, 6, 9, 7], [5, 7, 9, 8], [0, 3, 7, 5, 1], [2, 4, 8, 9, 6]] };
  1463. polyhedra[7] = { vertex: [[0, 0, 1.118034], [0.8944272, 0, 0.6708204], [-0.2236068, 0.8660254, 0.6708204], [-0.7826238, -0.4330127, 0.6708204], [0.6708204, 0.8660254, 0.2236068], [1.006231, -0.4330127, -0.2236068], [-1.006231, 0.4330127, 0.2236068], [-0.6708204, -0.8660254, -0.2236068], [0.7826238, 0.4330127, -0.6708204], [0.2236068, -0.8660254, -0.6708204], [-0.8944272, 0, -0.6708204], [0, 0, -1.118034]], face: [[0, 1, 4, 2], [0, 2, 6, 3], [1, 5, 8, 4], [3, 6, 10, 7], [5, 9, 11, 8], [7, 10, 11, 9], [0, 3, 7, 9, 5, 1], [2, 4, 8, 11, 10, 6]] };
  1464. polyhedra[8] = { vertex: [[-0.729665, 0.670121, 0.319155], [-0.655235, -0.29213, -0.754096], [-0.093922, -0.607123, 0.537818], [0.702196, 0.595691, 0.485187], [0.776626, -0.36656, -0.588064]], face: [[1, 4, 2], [0, 1, 2], [3, 0, 2], [4, 3, 2], [4, 1, 0, 3]] };
  1465. polyhedra[9] = { vertex: [[-0.868849, -0.100041, 0.61257], [-0.329458, 0.976099, 0.28078], [-0.26629, -0.013796, -0.477654], [-0.13392, -1.034115, 0.229829], [0.738834, 0.707117, -0.307018], [0.859683, -0.535264, -0.338508]], face: [[3, 0, 2], [5, 3, 2], [4, 5, 2], [1, 4, 2], [0, 1, 2], [0, 3, 5, 4, 1]] };
  1466. polyhedra[10] = { vertex: [[-0.610389, 0.243975, 0.531213], [-0.187812, -0.48795, -0.664016], [-0.187812, 0.9759, -0.664016], [0.187812, -0.9759, 0.664016], [0.798201, 0.243975, 0.132803]], face: [[1, 3, 0], [3, 4, 0], [3, 1, 4], [0, 2, 1], [0, 4, 2], [2, 4, 1]] };
  1467. polyhedra[11] = { vertex: [[-1.028778, 0.392027, -0.048786], [-0.640503, -0.646161, 0.621837], [-0.125162, -0.395663, -0.540059], [0.004683, 0.888447, -0.651988], [0.125161, 0.395663, 0.540059], [0.632925, -0.791376, 0.433102], [1.031672, 0.157063, -0.354165]], face: [[3, 2, 0], [2, 1, 0], [2, 5, 1], [0, 4, 3], [0, 1, 4], [4, 1, 5], [2, 3, 6], [3, 4, 6], [5, 2, 6], [4, 5, 6]] };
  1468. polyhedra[12] = { vertex: [[-0.669867, 0.334933, -0.529576], [-0.669867, 0.334933, 0.529577], [-0.4043, 1.212901, 0], [-0.334933, -0.669867, -0.529576], [-0.334933, -0.669867, 0.529577], [0.334933, 0.669867, -0.529576], [0.334933, 0.669867, 0.529577], [0.4043, -1.212901, 0], [0.669867, -0.334933, -0.529576], [0.669867, -0.334933, 0.529577]], face: [[8, 9, 7], [6, 5, 2], [3, 8, 7], [5, 0, 2], [4, 3, 7], [0, 1, 2], [9, 4, 7], [1, 6, 2], [9, 8, 5, 6], [8, 3, 0, 5], [3, 4, 1, 0], [4, 9, 6, 1]] };
  1469. polyhedra[13] = { vertex: [[-0.931836, 0.219976, -0.264632], [-0.636706, 0.318353, 0.692816], [-0.613483, -0.735083, -0.264632], [-0.326545, 0.979634, 0], [-0.318353, -0.636706, 0.692816], [-0.159176, 0.477529, -0.856368], [0.159176, -0.477529, -0.856368], [0.318353, 0.636706, 0.692816], [0.326545, -0.979634, 0], [0.613482, 0.735082, -0.264632], [0.636706, -0.318353, 0.692816], [0.931835, -0.219977, -0.264632]], face: [[11, 10, 8], [7, 9, 3], [6, 11, 8], [9, 5, 3], [2, 6, 8], [5, 0, 3], [4, 2, 8], [0, 1, 3], [10, 4, 8], [1, 7, 3], [10, 11, 9, 7], [11, 6, 5, 9], [6, 2, 0, 5], [2, 4, 1, 0], [4, 10, 7, 1]] };
  1470. polyhedra[14] = {
  1471. vertex: [[-0.93465, 0.300459, -0.271185], [-0.838689, -0.260219, -0.516017], [-0.711319, 0.717591, 0.128359], [-0.710334, -0.156922, 0.080946], [-0.599799, 0.556003, -0.725148], [-0.503838, -0.004675, -0.969981], [-0.487004, 0.26021, 0.48049], [-0.460089, -0.750282, -0.512622], [-0.376468, 0.973135, -0.325605], [-0.331735, -0.646985, 0.084342], [-0.254001, 0.831847, 0.530001], [-0.125239, -0.494738, -0.966586], [0.029622, 0.027949, 0.730817], [0.056536, -0.982543, -0.262295], [0.08085, 1.087391, 0.076037], [0.125583, -0.532729, 0.485984], [0.262625, 0.599586, 0.780328], [0.391387, -0.726999, -0.716259], [0.513854, -0.868287, 0.139347], [0.597475, 0.85513, 0.326364], [0.641224, 0.109523, 0.783723], [0.737185, -0.451155, 0.538891], [0.848705, -0.612742, -0.314616], [0.976075, 0.365067, 0.32976], [1.072036, -0.19561, 0.084927]],
  1472. face: [[15, 18, 21], [12, 20, 16], [6, 10, 2], [3, 0, 1], [9, 7, 13], [2, 8, 4, 0], [0, 4, 5, 1], [1, 5, 11, 7], [7, 11, 17, 13], [13, 17, 22, 18], [18, 22, 24, 21], [21, 24, 23, 20], [20, 23, 19, 16], [16, 19, 14, 10], [10, 14, 8, 2], [15, 9, 13, 18], [12, 15, 21, 20], [6, 12, 16, 10], [3, 6, 2, 0], [9, 3, 1, 7], [9, 15, 12, 6, 3], [22, 17, 11, 5, 4, 8, 14, 19, 23, 24]]
  1473. };
  1474. var type = (options.type < 0 || options.type >= polyhedra.length) ? 0 : options.type || 0;
  1475. var size = options.size;
  1476. var sizeX = options.sizeX || size || 1;
  1477. var sizeY = options.sizeY || size || 1;
  1478. var sizeZ = options.sizeZ || size || 1;
  1479. var data = options.custom || polyhedra[type];
  1480. var nbfaces = data.face.length;
  1481. var faceUV = options.faceUV || new Array(nbfaces);
  1482. var faceColors = options.faceColors;
  1483. var flat = (options.flat === undefined) ? true : options.flat;
  1484. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  1485. var positions = [];
  1486. var indices = [];
  1487. var normals = [];
  1488. var uvs = [];
  1489. var colors = [];
  1490. var index = 0;
  1491. var faceIdx = 0; // face cursor in the array "indexes"
  1492. var indexes = [];
  1493. var i = 0;
  1494. var f = 0;
  1495. var u, v, ang, x, y, tmp;
  1496. // default face colors and UV if undefined
  1497. if (flat) {
  1498. for (f = 0; f < nbfaces; f++) {
  1499. if (faceColors && faceColors[f] === undefined) {
  1500. faceColors[f] = new BABYLON.Color4(1, 1, 1, 1);
  1501. }
  1502. if (faceUV && faceUV[f] === undefined) {
  1503. faceUV[f] = new BABYLON.Vector4(0, 0, 1, 1);
  1504. }
  1505. }
  1506. }
  1507. if (!flat) {
  1508. for (i = 0; i < data.vertex.length; i++) {
  1509. positions.push(data.vertex[i][0] * sizeX, data.vertex[i][1] * sizeY, data.vertex[i][2] * sizeZ);
  1510. uvs.push(0, 0);
  1511. }
  1512. for (f = 0; f < nbfaces; f++) {
  1513. for (i = 0; i < data.face[f].length - 2; i++) {
  1514. indices.push(data.face[f][0], data.face[f][i + 2], data.face[f][i + 1]);
  1515. }
  1516. }
  1517. }
  1518. else {
  1519. for (f = 0; f < nbfaces; f++) {
  1520. var fl = data.face[f].length; // number of vertices of the current face
  1521. ang = 2 * Math.PI / fl;
  1522. x = 0.5 * Math.tan(ang / 2);
  1523. y = 0.5;
  1524. // positions, uvs, colors
  1525. for (i = 0; i < fl; i++) {
  1526. // positions
  1527. positions.push(data.vertex[data.face[f][i]][0] * sizeX, data.vertex[data.face[f][i]][1] * sizeY, data.vertex[data.face[f][i]][2] * sizeZ);
  1528. indexes.push(index);
  1529. index++;
  1530. // uvs
  1531. u = faceUV[f].x + (faceUV[f].z - faceUV[f].x) * (0.5 + x);
  1532. v = faceUV[f].y + (faceUV[f].w - faceUV[f].y) * (y - 0.5);
  1533. uvs.push(u, v);
  1534. tmp = x * Math.cos(ang) - y * Math.sin(ang);
  1535. y = x * Math.sin(ang) + y * Math.cos(ang);
  1536. x = tmp;
  1537. // colors
  1538. if (faceColors) {
  1539. colors.push(faceColors[f].r, faceColors[f].g, faceColors[f].b, faceColors[f].a);
  1540. }
  1541. }
  1542. // indices from indexes
  1543. for (i = 0; i < fl - 2; i++) {
  1544. indices.push(indexes[0 + faceIdx], indexes[i + 2 + faceIdx], indexes[i + 1 + faceIdx]);
  1545. }
  1546. faceIdx += fl;
  1547. }
  1548. }
  1549. VertexData.ComputeNormals(positions, indices, normals);
  1550. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  1551. var vertexData = new VertexData();
  1552. vertexData.positions = positions;
  1553. vertexData.indices = indices;
  1554. vertexData.normals = normals;
  1555. vertexData.uvs = uvs;
  1556. if (faceColors && flat) {
  1557. vertexData.colors = colors;
  1558. }
  1559. return vertexData;
  1560. };
  1561. // based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
  1562. VertexData.CreateTorusKnot = function (options) {
  1563. var indices = [];
  1564. var positions = [];
  1565. var normals = [];
  1566. var uvs = [];
  1567. var radius = options.radius || 2;
  1568. var tube = options.tube || 0.5;
  1569. var radialSegments = options.radialSegments || 32;
  1570. var tubularSegments = options.tubularSegments || 32;
  1571. var p = options.p || 2;
  1572. var q = options.q || 3;
  1573. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  1574. // Helper
  1575. var getPos = function (angle) {
  1576. var cu = Math.cos(angle);
  1577. var su = Math.sin(angle);
  1578. var quOverP = q / p * angle;
  1579. var cs = Math.cos(quOverP);
  1580. var tx = radius * (2 + cs) * 0.5 * cu;
  1581. var ty = radius * (2 + cs) * su * 0.5;
  1582. var tz = radius * Math.sin(quOverP) * 0.5;
  1583. return new BABYLON.Vector3(tx, ty, tz);
  1584. };
  1585. // Vertices
  1586. var i;
  1587. var j;
  1588. for (i = 0; i <= radialSegments; i++) {
  1589. var modI = i % radialSegments;
  1590. var u = modI / radialSegments * 2 * p * Math.PI;
  1591. var p1 = getPos(u);
  1592. var p2 = getPos(u + 0.01);
  1593. var tang = p2.subtract(p1);
  1594. var n = p2.add(p1);
  1595. var bitan = BABYLON.Vector3.Cross(tang, n);
  1596. n = BABYLON.Vector3.Cross(bitan, tang);
  1597. bitan.normalize();
  1598. n.normalize();
  1599. for (j = 0; j < tubularSegments; j++) {
  1600. var modJ = j % tubularSegments;
  1601. var v = modJ / tubularSegments * 2 * Math.PI;
  1602. var cx = -tube * Math.cos(v);
  1603. var cy = tube * Math.sin(v);
  1604. positions.push(p1.x + cx * n.x + cy * bitan.x);
  1605. positions.push(p1.y + cx * n.y + cy * bitan.y);
  1606. positions.push(p1.z + cx * n.z + cy * bitan.z);
  1607. uvs.push(i / radialSegments);
  1608. uvs.push(j / tubularSegments);
  1609. }
  1610. }
  1611. for (i = 0; i < radialSegments; i++) {
  1612. for (j = 0; j < tubularSegments; j++) {
  1613. var jNext = (j + 1) % tubularSegments;
  1614. var a = i * tubularSegments + j;
  1615. var b = (i + 1) * tubularSegments + j;
  1616. var c = (i + 1) * tubularSegments + jNext;
  1617. var d = i * tubularSegments + jNext;
  1618. indices.push(d);
  1619. indices.push(b);
  1620. indices.push(a);
  1621. indices.push(d);
  1622. indices.push(c);
  1623. indices.push(b);
  1624. }
  1625. }
  1626. // Normals
  1627. VertexData.ComputeNormals(positions, indices, normals);
  1628. // Sides
  1629. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  1630. // Result
  1631. var vertexData = new VertexData();
  1632. vertexData.indices = indices;
  1633. vertexData.positions = positions;
  1634. vertexData.normals = normals;
  1635. vertexData.uvs = uvs;
  1636. return vertexData;
  1637. };
  1638. // Tools
  1639. /**
  1640. * @param {any} - positions (number[] or Float32Array)
  1641. * @param {any} - indices (number[] or Uint16Array)
  1642. * @param {any} - normals (number[] or Float32Array)
  1643. */
  1644. VertexData.ComputeNormals = function (positions, indices, normals) {
  1645. var index = 0;
  1646. var p1p2x = 0.0;
  1647. var p1p2y = 0.0;
  1648. var p1p2z = 0.0;
  1649. var p3p2x = 0.0;
  1650. var p3p2y = 0.0;
  1651. var p3p2z = 0.0;
  1652. var faceNormalx = 0.0;
  1653. var faceNormaly = 0.0;
  1654. var faceNormalz = 0.0;
  1655. var length = 0.0;
  1656. var i1 = 0;
  1657. var i2 = 0;
  1658. var i3 = 0;
  1659. for (index = 0; index < positions.length; index++) {
  1660. normals[index] = 0.0;
  1661. }
  1662. // indice triplet = 1 face
  1663. var nbFaces = indices.length / 3;
  1664. for (index = 0; index < nbFaces; index++) {
  1665. i1 = indices[index * 3]; // get the indexes of each vertex of the face
  1666. i2 = indices[index * 3 + 1];
  1667. i3 = indices[index * 3 + 2];
  1668. p1p2x = positions[i1 * 3] - positions[i2 * 3]; // compute two vectors per face
  1669. p1p2y = positions[i1 * 3 + 1] - positions[i2 * 3 + 1];
  1670. p1p2z = positions[i1 * 3 + 2] - positions[i2 * 3 + 2];
  1671. p3p2x = positions[i3 * 3] - positions[i2 * 3];
  1672. p3p2y = positions[i3 * 3 + 1] - positions[i2 * 3 + 1];
  1673. p3p2z = positions[i3 * 3 + 2] - positions[i2 * 3 + 2];
  1674. faceNormalx = p1p2y * p3p2z - p1p2z * p3p2y; // compute the face normal with cross product
  1675. faceNormaly = p1p2z * p3p2x - p1p2x * p3p2z;
  1676. faceNormalz = p1p2x * p3p2y - p1p2y * p3p2x;
  1677. length = Math.sqrt(faceNormalx * faceNormalx + faceNormaly * faceNormaly + faceNormalz * faceNormalz);
  1678. length = (length === 0) ? 1.0 : length;
  1679. faceNormalx /= length; // normalize this normal
  1680. faceNormaly /= length;
  1681. faceNormalz /= length;
  1682. normals[i1 * 3] += faceNormalx; // accumulate all the normals per face
  1683. normals[i1 * 3 + 1] += faceNormaly;
  1684. normals[i1 * 3 + 2] += faceNormalz;
  1685. normals[i2 * 3] += faceNormalx;
  1686. normals[i2 * 3 + 1] += faceNormaly;
  1687. normals[i2 * 3 + 2] += faceNormalz;
  1688. normals[i3 * 3] += faceNormalx;
  1689. normals[i3 * 3 + 1] += faceNormaly;
  1690. normals[i3 * 3 + 2] += faceNormalz;
  1691. }
  1692. // last normalization of each normal
  1693. for (index = 0; index < normals.length / 3; index++) {
  1694. faceNormalx = normals[index * 3];
  1695. faceNormaly = normals[index * 3 + 1];
  1696. faceNormalz = normals[index * 3 + 2];
  1697. length = Math.sqrt(faceNormalx * faceNormalx + faceNormaly * faceNormaly + faceNormalz * faceNormalz);
  1698. length = (length === 0) ? 1.0 : length;
  1699. faceNormalx /= length;
  1700. faceNormaly /= length;
  1701. faceNormalz /= length;
  1702. normals[index * 3] = faceNormalx;
  1703. normals[index * 3 + 1] = faceNormaly;
  1704. normals[index * 3 + 2] = faceNormalz;
  1705. }
  1706. };
  1707. VertexData._ComputeSides = function (sideOrientation, positions, indices, normals, uvs) {
  1708. var li = indices.length;
  1709. var ln = normals.length;
  1710. var i;
  1711. var n;
  1712. sideOrientation = sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  1713. switch (sideOrientation) {
  1714. case BABYLON.Mesh.FRONTSIDE:
  1715. // nothing changed
  1716. break;
  1717. case BABYLON.Mesh.BACKSIDE:
  1718. var tmp;
  1719. // indices
  1720. for (i = 0; i < li; i += 3) {
  1721. tmp = indices[i];
  1722. indices[i] = indices[i + 2];
  1723. indices[i + 2] = tmp;
  1724. }
  1725. // normals
  1726. for (n = 0; n < ln; n++) {
  1727. normals[n] = -normals[n];
  1728. }
  1729. break;
  1730. case BABYLON.Mesh.DOUBLESIDE:
  1731. // positions
  1732. var lp = positions.length;
  1733. var l = lp / 3;
  1734. for (var p = 0; p < lp; p++) {
  1735. positions[lp + p] = positions[p];
  1736. }
  1737. // indices
  1738. for (i = 0; i < li; i += 3) {
  1739. indices[i + li] = indices[i + 2] + l;
  1740. indices[i + 1 + li] = indices[i + 1] + l;
  1741. indices[i + 2 + li] = indices[i] + l;
  1742. }
  1743. // normals
  1744. for (n = 0; n < ln; n++) {
  1745. normals[ln + n] = -normals[n];
  1746. }
  1747. // uvs
  1748. var lu = uvs.length;
  1749. for (var u = 0; u < lu; u++) {
  1750. uvs[u + lu] = uvs[u];
  1751. }
  1752. break;
  1753. }
  1754. };
  1755. VertexData.ImportVertexData = function (parsedVertexData, geometry) {
  1756. var vertexData = new VertexData();
  1757. // positions
  1758. var positions = parsedVertexData.positions;
  1759. if (positions) {
  1760. vertexData.set(positions, BABYLON.VertexBuffer.PositionKind);
  1761. }
  1762. // normals
  1763. var normals = parsedVertexData.normals;
  1764. if (normals) {
  1765. vertexData.set(normals, BABYLON.VertexBuffer.NormalKind);
  1766. }
  1767. // uvs
  1768. var uvs = parsedVertexData.uvs;
  1769. if (uvs) {
  1770. vertexData.set(uvs, BABYLON.VertexBuffer.UVKind);
  1771. }
  1772. // uv2s
  1773. var uv2s = parsedVertexData.uv2s;
  1774. if (uv2s) {
  1775. vertexData.set(uv2s, BABYLON.VertexBuffer.UV2Kind);
  1776. }
  1777. // uv3s
  1778. var uv3s = parsedVertexData.uv3s;
  1779. if (uv3s) {
  1780. vertexData.set(uv3s, BABYLON.VertexBuffer.UV3Kind);
  1781. }
  1782. // uv4s
  1783. var uv4s = parsedVertexData.uv4s;
  1784. if (uv4s) {
  1785. vertexData.set(uv4s, BABYLON.VertexBuffer.UV4Kind);
  1786. }
  1787. // uv5s
  1788. var uv5s = parsedVertexData.uv5s;
  1789. if (uv5s) {
  1790. vertexData.set(uv5s, BABYLON.VertexBuffer.UV5Kind);
  1791. }
  1792. // uv6s
  1793. var uv6s = parsedVertexData.uv6s;
  1794. if (uv6s) {
  1795. vertexData.set(uv6s, BABYLON.VertexBuffer.UV6Kind);
  1796. }
  1797. // colors
  1798. var colors = parsedVertexData.colors;
  1799. if (colors) {
  1800. vertexData.set(BABYLON.Color4.CheckColors4(colors, positions.length / 3), BABYLON.VertexBuffer.ColorKind);
  1801. }
  1802. // matricesIndices
  1803. var matricesIndices = parsedVertexData.matricesIndices;
  1804. if (matricesIndices) {
  1805. vertexData.set(matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind);
  1806. }
  1807. // matricesWeights
  1808. var matricesWeights = parsedVertexData.matricesWeights;
  1809. if (matricesWeights) {
  1810. vertexData.set(matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind);
  1811. }
  1812. // indices
  1813. var indices = parsedVertexData.indices;
  1814. if (indices) {
  1815. vertexData.indices = indices;
  1816. }
  1817. geometry.setAllVerticesData(vertexData, parsedVertexData.updatable);
  1818. };
  1819. return VertexData;
  1820. })();
  1821. BABYLON.VertexData = VertexData;
  1822. })(BABYLON || (BABYLON = {}));