babylon.mesh.vertexData.ts 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334
  1. module BABYLON {
  2. export interface IGetSetVerticesData {
  3. isVerticesDataPresent(kind: string): boolean;
  4. getVerticesData(kind: string, copyWhenShared?: boolean): number[];
  5. getIndices(copyWhenShared?: boolean): number[];
  6. setVerticesData(kind: string, data: number[], updatable?: boolean): void;
  7. updateVerticesData(kind: string, data: number[], updateExtends?: boolean, makeItUnique?: boolean): void;
  8. setIndices(indices: number[]): void;
  9. }
  10. export class VertexData {
  11. public positions: number[];
  12. public normals: number[];
  13. public uvs: number[];
  14. public uv2s: number[];
  15. public colors: number[];
  16. public matricesIndices: number[];
  17. public matricesWeights: number[];
  18. public indices: number[];
  19. public set(data: number[], kind: string) {
  20. switch (kind) {
  21. case VertexBuffer.PositionKind:
  22. this.positions = data;
  23. break;
  24. case VertexBuffer.NormalKind:
  25. this.normals = data;
  26. break;
  27. case VertexBuffer.UVKind:
  28. this.uvs = data;
  29. break;
  30. case VertexBuffer.UV2Kind:
  31. this.uv2s = data;
  32. break;
  33. case VertexBuffer.ColorKind:
  34. this.colors = data;
  35. break;
  36. case VertexBuffer.MatricesIndicesKind:
  37. this.matricesIndices = data;
  38. break;
  39. case VertexBuffer.MatricesWeightsKind:
  40. this.matricesWeights = data;
  41. break;
  42. }
  43. }
  44. public applyToMesh(mesh: Mesh, updatable?: boolean): void {
  45. this._applyTo(mesh, updatable);
  46. }
  47. public applyToGeometry(geometry: Geometry, updatable?: boolean): void {
  48. this._applyTo(geometry, updatable);
  49. }
  50. public updateMesh(mesh: Mesh, updateExtends?: boolean, makeItUnique?: boolean): void {
  51. this._update(mesh);
  52. }
  53. public updateGeometry(geometry: Geometry, updateExtends?: boolean, makeItUnique?: boolean): void {
  54. this._update(geometry);
  55. }
  56. private _applyTo(meshOrGeometry: IGetSetVerticesData, updatable?: boolean) {
  57. if (this.positions) {
  58. meshOrGeometry.setVerticesData(VertexBuffer.PositionKind, this.positions, updatable);
  59. }
  60. if (this.normals) {
  61. meshOrGeometry.setVerticesData(VertexBuffer.NormalKind, this.normals, updatable);
  62. }
  63. if (this.uvs) {
  64. meshOrGeometry.setVerticesData(VertexBuffer.UVKind, this.uvs, updatable);
  65. }
  66. if (this.uv2s) {
  67. meshOrGeometry.setVerticesData(VertexBuffer.UV2Kind, this.uv2s, updatable);
  68. }
  69. if (this.colors) {
  70. meshOrGeometry.setVerticesData(VertexBuffer.ColorKind, this.colors, updatable);
  71. }
  72. if (this.matricesIndices) {
  73. meshOrGeometry.setVerticesData(VertexBuffer.MatricesIndicesKind, this.matricesIndices, updatable);
  74. }
  75. if (this.matricesWeights) {
  76. meshOrGeometry.setVerticesData(VertexBuffer.MatricesWeightsKind, this.matricesWeights, updatable);
  77. }
  78. if (this.indices) {
  79. meshOrGeometry.setIndices(this.indices);
  80. }
  81. }
  82. private _update(meshOrGeometry: IGetSetVerticesData, updateExtends?: boolean, makeItUnique?: boolean) {
  83. if (this.positions) {
  84. meshOrGeometry.updateVerticesData(VertexBuffer.PositionKind, this.positions, updateExtends, makeItUnique);
  85. }
  86. if (this.normals) {
  87. meshOrGeometry.updateVerticesData(VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
  88. }
  89. if (this.uvs) {
  90. meshOrGeometry.updateVerticesData(VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
  91. }
  92. if (this.uv2s) {
  93. meshOrGeometry.updateVerticesData(VertexBuffer.UV2Kind, this.uv2s, updateExtends, makeItUnique);
  94. }
  95. if (this.colors) {
  96. meshOrGeometry.updateVerticesData(VertexBuffer.ColorKind, this.colors, updateExtends, makeItUnique);
  97. }
  98. if (this.matricesIndices) {
  99. meshOrGeometry.updateVerticesData(VertexBuffer.MatricesIndicesKind, this.matricesIndices, updateExtends, makeItUnique);
  100. }
  101. if (this.matricesWeights) {
  102. meshOrGeometry.updateVerticesData(VertexBuffer.MatricesWeightsKind, this.matricesWeights, updateExtends, makeItUnique);
  103. }
  104. if (this.indices) {
  105. meshOrGeometry.setIndices(this.indices);
  106. }
  107. }
  108. public transform(matrix: Matrix): void {
  109. var transformed = Vector3.Zero();
  110. if (this.positions) {
  111. var position = Vector3.Zero();
  112. for (var index = 0; index < this.positions.length; index += 3) {
  113. Vector3.FromArrayToRef(this.positions, index, position);
  114. Vector3.TransformCoordinatesToRef(position, matrix, transformed);
  115. this.positions[index] = transformed.x;
  116. this.positions[index + 1] = transformed.y;
  117. this.positions[index + 2] = transformed.z;
  118. }
  119. }
  120. if (this.normals) {
  121. var normal = Vector3.Zero();
  122. for (index = 0; index < this.normals.length; index += 3) {
  123. Vector3.FromArrayToRef(this.normals, index, normal);
  124. Vector3.TransformNormalToRef(normal, matrix, transformed);
  125. this.normals[index] = transformed.x;
  126. this.normals[index + 1] = transformed.y;
  127. this.normals[index + 2] = transformed.z;
  128. }
  129. }
  130. }
  131. public merge(other: VertexData): void {
  132. if (other.indices) {
  133. if (!this.indices) {
  134. this.indices = [];
  135. }
  136. var offset = this.positions ? this.positions.length / 3 : 0;
  137. for (var index = 0; index < other.indices.length; index++) {
  138. this.indices.push(other.indices[index] + offset);
  139. }
  140. }
  141. if (other.positions) {
  142. if (!this.positions) {
  143. this.positions = [];
  144. }
  145. for (index = 0; index < other.positions.length; index++) {
  146. this.positions.push(other.positions[index]);
  147. }
  148. }
  149. if (other.normals) {
  150. if (!this.normals) {
  151. this.normals = [];
  152. }
  153. for (index = 0; index < other.normals.length; index++) {
  154. this.normals.push(other.normals[index]);
  155. }
  156. }
  157. if (other.uvs) {
  158. if (!this.uvs) {
  159. this.uvs = [];
  160. }
  161. for (index = 0; index < other.uvs.length; index++) {
  162. this.uvs.push(other.uvs[index]);
  163. }
  164. }
  165. if (other.uv2s) {
  166. if (!this.uv2s) {
  167. this.uv2s = [];
  168. }
  169. for (index = 0; index < other.uv2s.length; index++) {
  170. this.uv2s.push(other.uv2s[index]);
  171. }
  172. }
  173. if (other.matricesIndices) {
  174. if (!this.matricesIndices) {
  175. this.matricesIndices = [];
  176. }
  177. for (index = 0; index < other.matricesIndices.length; index++) {
  178. this.matricesIndices.push(other.matricesIndices[index]);
  179. }
  180. }
  181. if (other.matricesWeights) {
  182. if (!this.matricesWeights) {
  183. this.matricesWeights = [];
  184. }
  185. for (index = 0; index < other.matricesWeights.length; index++) {
  186. this.matricesWeights.push(other.matricesWeights[index]);
  187. }
  188. }
  189. if (other.colors) {
  190. if (!this.colors) {
  191. this.colors = [];
  192. }
  193. for (index = 0; index < other.colors.length; index++) {
  194. this.colors.push(other.colors[index]);
  195. }
  196. }
  197. }
  198. // Statics
  199. public static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean): VertexData {
  200. return VertexData._ExtractFrom(mesh, copyWhenShared);
  201. }
  202. public static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean): VertexData {
  203. return VertexData._ExtractFrom(geometry, copyWhenShared);
  204. }
  205. private static _ExtractFrom(meshOrGeometry: IGetSetVerticesData, copyWhenShared?: boolean): VertexData {
  206. var result = new VertexData();
  207. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.PositionKind)) {
  208. result.positions = meshOrGeometry.getVerticesData(VertexBuffer.PositionKind, copyWhenShared);
  209. }
  210. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  211. result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared);
  212. }
  213. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UVKind)) {
  214. result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared);
  215. }
  216. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
  217. result.uv2s = meshOrGeometry.getVerticesData(VertexBuffer.UV2Kind, copyWhenShared);
  218. }
  219. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.ColorKind)) {
  220. result.colors = meshOrGeometry.getVerticesData(VertexBuffer.ColorKind, copyWhenShared);
  221. }
  222. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
  223. result.matricesIndices = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesKind, copyWhenShared);
  224. }
  225. if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
  226. result.matricesWeights = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsKind, copyWhenShared);
  227. }
  228. result.indices = meshOrGeometry.getIndices(copyWhenShared);
  229. return result;
  230. }
  231. public static CreateRibbon(pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  232. closeArray = closeArray || false;
  233. closePath = closePath || false;
  234. var defaultOffset = Math.floor(pathArray[0].length / 2);
  235. offset = offset || defaultOffset;
  236. offset = offset > defaultOffset ? defaultOffset : Math.floor(offset); // offset max allowed : defaultOffset
  237. var positions: number[] = [];
  238. var indices: number[] = [];
  239. var normals: number[] = [];
  240. var uvs: number[] = [];
  241. var us: number[][] = []; // us[path_id] = [uDist1, uDist2, uDist3 ... ] distances between points on path path_id
  242. var vs: number[][] = []; // vs[i] = [vDist1, vDist2, vDist3, ... ] distances between points i of consecutives paths from pathArray
  243. var uTotalDistance: number[] = []; // uTotalDistance[p] : total distance of path p
  244. var vTotalDistance: number[] = []; // vTotalDistance[i] : total distance between points i of first and last path from pathArray
  245. var minlg: number; // minimal length among all paths from pathArray
  246. var lg: number[] = []; // array of path lengths : nb of vertex per path
  247. var idx: number[] = []; // array of path indexes : index of each path (first vertex) in positions array
  248. var p: number; // path iterator
  249. var i: number; // point iterator
  250. var j: number; // point iterator
  251. // if single path in pathArray
  252. if (pathArray.length < 2) {
  253. var ar1: Vector3[] = [];
  254. var ar2: Vector3[] = [];
  255. for (i = 0; i < pathArray[0].length - offset; i++) {
  256. ar1.push(pathArray[0][i]);
  257. ar2.push(pathArray[0][i + offset]);
  258. }
  259. pathArray = [ar1, ar2];
  260. }
  261. // positions and horizontal distances (u)
  262. var idc: number = 0;
  263. minlg = pathArray[0].length;
  264. for (p = 0; p < pathArray.length; p++) {
  265. uTotalDistance[p] = 0;
  266. us[p] = [0];
  267. var path: Vector3[] = pathArray[p];
  268. var l: number = path.length;
  269. minlg = (minlg < l) ? minlg : l;
  270. lg[p] = l;
  271. idx[p] = idc;
  272. j = 0;
  273. while (j < l) {
  274. positions.push(path[j].x, path[j].y, path[j].z);
  275. if (j > 0) {
  276. var vectlg: number = path[j].subtract(path[j - 1]).length();
  277. var dist: number = vectlg + uTotalDistance[p];
  278. us[p].push(dist);
  279. uTotalDistance[p] = dist;
  280. }
  281. j++;
  282. }
  283. if (closePath) {
  284. vectlg = path[0].subtract(path[j - 1]).length();
  285. dist = vectlg + uTotalDistance[p];
  286. uTotalDistance[p] = dist;
  287. }
  288. idc += l;
  289. }
  290. // vertical distances (v)
  291. for (i = 0; i < minlg; i++) {
  292. vTotalDistance[i] = 0;
  293. vs[i] = [0];
  294. var path1: Vector3[];
  295. var path2: Vector3[];
  296. for (p = 0; p < pathArray.length - 1; p++) {
  297. path1 = pathArray[p];
  298. path2 = pathArray[p + 1];
  299. vectlg = path2[i].subtract(path1[i]).length();
  300. dist = vectlg + vTotalDistance[i];
  301. vs[i].push(dist);
  302. vTotalDistance[i] = dist;
  303. }
  304. if (closeArray) {
  305. path1 = pathArray[p];
  306. path2 = pathArray[0];
  307. vectlg = path2[i].subtract(path1[i]).length();
  308. dist = vectlg + vTotalDistance[i];
  309. vTotalDistance[i] = dist;
  310. }
  311. }
  312. // uvs
  313. var u: number;
  314. var v: number;
  315. for (p = 0; p < pathArray.length; p++) {
  316. for (i = 0; i < minlg; i++) {
  317. u = us[p][i] / uTotalDistance[p];
  318. v = vs[i][p] / vTotalDistance[i];
  319. uvs.push(u, v);
  320. }
  321. }
  322. // indices
  323. p = 0; // path index
  324. var pi: number = 0; // positions array index
  325. var l1: number = lg[p] - 1; // path1 length
  326. var l2: number = lg[p + 1] - 1; // path2 length
  327. var min: number = (l1 < l2) ? l1 : l2; // current path stop index
  328. var shft: number = idx[1] - idx[0]; // shift
  329. var path1nb: number = closeArray ? lg.length : lg.length - 1; // number of path1 to iterate
  330. var t1: number; // two consecutive triangles, so 4 points : point1
  331. var t2: number; // point2
  332. var t3: number; // point3
  333. var t4: number; // point4
  334. while (pi <= min && p < path1nb) { // stay under min and don't go over next to last path
  335. // 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
  336. t1 = pi;
  337. t2 = pi + shft;
  338. t3 = pi + 1;
  339. t4 = pi + shft + 1;
  340. indices.push(pi, pi + shft, pi + 1);
  341. indices.push(pi + shft + 1, pi + 1, pi + shft);
  342. pi += 1;
  343. if (pi === min) { // if end of one of two consecutive paths reached, go next existing path
  344. if (closePath) { // if closePath, add last triangles between start and end of the paths
  345. indices.push(pi, pi + shft, idx[p]);
  346. indices.push(idx[p] + shft, idx[p], pi + shft);
  347. t3 = idx[p];
  348. t4 = idx[p] + shft;
  349. }
  350. p++;
  351. if (p === lg.length - 1) { // last path of pathArray reached <=> closeArray == true
  352. shft = idx[0] - idx[p];
  353. l1 = lg[p] - 1;
  354. l2 = lg[0] - 1;
  355. }
  356. else {
  357. shft = idx[p + 1] - idx[p];
  358. l1 = lg[p] - 1;
  359. l2 = lg[p + 1] - 1;
  360. }
  361. pi = idx[p];
  362. min = (l1 < l2) ? l1 + pi : l2 + pi;
  363. }
  364. }
  365. // normals
  366. VertexData.ComputeNormals(positions, indices, normals);
  367. // sides
  368. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  369. // Result
  370. var vertexData = new VertexData();
  371. vertexData.indices = indices;
  372. vertexData.positions = positions;
  373. vertexData.normals = normals;
  374. vertexData.uvs = uvs;
  375. return vertexData;
  376. }
  377. public static CreateBox(size: number, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  378. var normalsSource = [
  379. new Vector3(0, 0, 1),
  380. new Vector3(0, 0, -1),
  381. new Vector3(1, 0, 0),
  382. new Vector3(-1, 0, 0),
  383. new Vector3(0, 1, 0),
  384. new Vector3(0, -1, 0)
  385. ];
  386. var indices = [];
  387. var positions = [];
  388. var normals = [];
  389. var uvs = [];
  390. size = size || 1;
  391. // Create each face in turn.
  392. for (var index = 0; index < normalsSource.length; index++) {
  393. var normal = normalsSource[index];
  394. // Get two vectors perpendicular to the face normal and to each other.
  395. var side1 = new Vector3(normal.y, normal.z, normal.x);
  396. var side2 = Vector3.Cross(normal, side1);
  397. // Six indices (two triangles) per face.
  398. var verticesLength = positions.length / 3;
  399. indices.push(verticesLength);
  400. indices.push(verticesLength + 1);
  401. indices.push(verticesLength + 2);
  402. indices.push(verticesLength);
  403. indices.push(verticesLength + 2);
  404. indices.push(verticesLength + 3);
  405. // Four vertices per face.
  406. var vertex = normal.subtract(side1).subtract(side2).scale(size / 2);
  407. positions.push(vertex.x, vertex.y, vertex.z);
  408. normals.push(normal.x, normal.y, normal.z);
  409. uvs.push(1.0, 1.0);
  410. vertex = normal.subtract(side1).add(side2).scale(size / 2);
  411. positions.push(vertex.x, vertex.y, vertex.z);
  412. normals.push(normal.x, normal.y, normal.z);
  413. uvs.push(0.0, 1.0);
  414. vertex = normal.add(side1).add(side2).scale(size / 2);
  415. positions.push(vertex.x, vertex.y, vertex.z);
  416. normals.push(normal.x, normal.y, normal.z);
  417. uvs.push(0.0, 0.0);
  418. vertex = normal.add(side1).subtract(side2).scale(size / 2);
  419. positions.push(vertex.x, vertex.y, vertex.z);
  420. normals.push(normal.x, normal.y, normal.z);
  421. uvs.push(1.0, 0.0);
  422. }
  423. // sides
  424. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  425. // Result
  426. var vertexData = new VertexData();
  427. vertexData.indices = indices;
  428. vertexData.positions = positions;
  429. vertexData.normals = normals;
  430. vertexData.uvs = uvs;
  431. return vertexData;
  432. }
  433. public static CreateSphere(segments: number, diameter: number, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  434. segments = segments || 32;
  435. diameter = diameter || 1;
  436. var radius = diameter / 2;
  437. var totalZRotationSteps = 2 + segments;
  438. var totalYRotationSteps = 2 * totalZRotationSteps;
  439. var indices = [];
  440. var positions = [];
  441. var normals = [];
  442. var uvs = [];
  443. for (var zRotationStep = 0; zRotationStep <= totalZRotationSteps; zRotationStep++) {
  444. var normalizedZ = zRotationStep / totalZRotationSteps;
  445. var angleZ = (normalizedZ * Math.PI);
  446. for (var yRotationStep = 0; yRotationStep <= totalYRotationSteps; yRotationStep++) {
  447. var normalizedY = yRotationStep / totalYRotationSteps;
  448. var angleY = normalizedY * Math.PI * 2;
  449. var rotationZ = Matrix.RotationZ(-angleZ);
  450. var rotationY = Matrix.RotationY(angleY);
  451. var afterRotZ = Vector3.TransformCoordinates(Vector3.Up(), rotationZ);
  452. var complete = Vector3.TransformCoordinates(afterRotZ, rotationY);
  453. var vertex = complete.scale(radius);
  454. var normal = Vector3.Normalize(vertex);
  455. positions.push(vertex.x, vertex.y, vertex.z);
  456. normals.push(normal.x, normal.y, normal.z);
  457. uvs.push(normalizedZ, normalizedY);
  458. }
  459. if (zRotationStep > 0) {
  460. var verticesCount = positions.length / 3;
  461. for (var firstIndex = verticesCount - 2 * (totalYRotationSteps + 1); (firstIndex + totalYRotationSteps + 2) < verticesCount; firstIndex++) {
  462. indices.push((firstIndex));
  463. indices.push((firstIndex + 1));
  464. indices.push(firstIndex + totalYRotationSteps + 1);
  465. indices.push((firstIndex + totalYRotationSteps + 1));
  466. indices.push((firstIndex + 1));
  467. indices.push((firstIndex + totalYRotationSteps + 2));
  468. }
  469. }
  470. }
  471. // Sides
  472. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  473. // Result
  474. var vertexData = new VertexData();
  475. vertexData.indices = indices;
  476. vertexData.positions = positions;
  477. vertexData.normals = normals;
  478. vertexData.uvs = uvs;
  479. return vertexData;
  480. }
  481. public static CreateCylinder(height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: number = 1, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  482. var radiusTop = diameterTop / 2;
  483. var radiusBottom = diameterBottom / 2;
  484. var indices = [];
  485. var positions = [];
  486. var normals = [];
  487. var uvs = [];
  488. height = height || 1;
  489. diameterTop = diameterTop || 0.5;
  490. diameterBottom = diameterBottom || 1;
  491. tessellation = tessellation || 16;
  492. subdivisions = subdivisions || 1;
  493. subdivisions = (subdivisions < 1) ? 1 : subdivisions;
  494. var getCircleVector = i => {
  495. var angle = (i * 2.0 * Math.PI / tessellation);
  496. var dx = Math.cos(angle);
  497. var dz = Math.sin(angle);
  498. return new Vector3(dx, 0, dz);
  499. };
  500. var createCylinderCap = isTop => {
  501. var radius = isTop ? radiusTop : radiusBottom;
  502. if (radius === 0) {
  503. return;
  504. }
  505. var vbase = positions.length / 3;
  506. var offset = new Vector3(0, height / 2, 0);
  507. var textureScale = new Vector2(0.5, 0.5);
  508. if (!isTop) {
  509. offset.scaleInPlace(-1);
  510. textureScale.x = -textureScale.x;
  511. }
  512. // Positions, normals & uvs
  513. for (var i = 0; i < tessellation; i++) {
  514. var circleVector = getCircleVector(i);
  515. var position = circleVector.scale(radius).add(offset);
  516. var textureCoordinate = new Vector2(
  517. circleVector.x * textureScale.x + 0.5,
  518. circleVector.z * textureScale.y + 0.5
  519. );
  520. positions.push(position.x, position.y, position.z);
  521. uvs.push(textureCoordinate.x, textureCoordinate.y);
  522. }
  523. // Indices
  524. for (i = 0; i < tessellation - 2; i++) {
  525. if (!isTop) {
  526. indices.push(vbase);
  527. indices.push(vbase + (i + 2) % tessellation);
  528. indices.push(vbase + (i + 1) % tessellation);
  529. } else {
  530. indices.push(vbase);
  531. indices.push(vbase + (i + 1) % tessellation);
  532. indices.push(vbase + (i + 2) % tessellation);
  533. }
  534. }
  535. };
  536. var base = new Vector3(0, -1, 0).scale(height / 2);
  537. var offset = new Vector3(0, 1, 0).scale(height / subdivisions);
  538. var stride = tessellation + 1;
  539. // Positions, normals & uvs
  540. for (var i = 0; i <= tessellation; i++) {
  541. var circleVector = getCircleVector(i);
  542. var textureCoordinate = new Vector2(i / tessellation, 0);
  543. var position: Vector3, radius = radiusBottom;
  544. for (var s = 0; s <= subdivisions; s++) {
  545. // Update variables
  546. position = circleVector.scale(radius);
  547. position.addInPlace(base.add(offset.scale(s)));
  548. textureCoordinate.y += 1 / subdivisions;
  549. radius += (radiusTop - radiusBottom) / subdivisions;
  550. // Push in arrays
  551. positions.push(position.x, position.y, position.z);
  552. uvs.push(textureCoordinate.x, textureCoordinate.y);
  553. }
  554. }
  555. subdivisions += 1;
  556. // Indices
  557. for (s = 0; s < subdivisions - 1; s++) {
  558. for (i = 0; i <= tessellation; i++) {
  559. indices.push(i * subdivisions + s);
  560. indices.push((i * subdivisions + (s + subdivisions)) % (stride * subdivisions));
  561. indices.push(i * subdivisions + (s + 1));
  562. indices.push(i * subdivisions + (s + 1));
  563. indices.push((i * subdivisions + (s + subdivisions)) % (stride * subdivisions));
  564. indices.push((i * subdivisions + (s + subdivisions + 1)) % (stride * subdivisions));
  565. }
  566. }
  567. // Create flat triangle fan caps to seal the top and bottom.
  568. createCylinderCap(true);
  569. createCylinderCap(false);
  570. // Normals
  571. VertexData.ComputeNormals(positions, indices, normals);
  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. return vertexData;
  581. }
  582. public static CreateTorus(diameter, thickness, tessellation, sideOrientation: number = Mesh.DEFAULTSIDE) {
  583. var indices = [];
  584. var positions = [];
  585. var normals = [];
  586. var uvs = [];
  587. diameter = diameter || 1;
  588. thickness = thickness || 0.5;
  589. tessellation = tessellation || 16;
  590. var stride = tessellation + 1;
  591. for (var i = 0; i <= tessellation; i++) {
  592. var u = i / tessellation;
  593. var outerAngle = i * Math.PI * 2.0 / tessellation - Math.PI / 2.0;
  594. var transform = Matrix.Translation(diameter / 2.0, 0, 0).multiply(Matrix.RotationY(outerAngle));
  595. for (var j = 0; j <= tessellation; j++) {
  596. var v = 1 - j / tessellation;
  597. var innerAngle = j * Math.PI * 2.0 / tessellation + Math.PI;
  598. var dx = Math.cos(innerAngle);
  599. var dy = Math.sin(innerAngle);
  600. // Create a vertex.
  601. var normal = new Vector3(dx, dy, 0);
  602. var position = normal.scale(thickness / 2);
  603. var textureCoordinate = new Vector2(u, v);
  604. position = Vector3.TransformCoordinates(position, transform);
  605. normal = Vector3.TransformNormal(normal, transform);
  606. positions.push(position.x, position.y, position.z);
  607. normals.push(normal.x, normal.y, normal.z);
  608. uvs.push(textureCoordinate.x, textureCoordinate.y);
  609. // And create indices for two triangles.
  610. var nextI = (i + 1) % stride;
  611. var nextJ = (j + 1) % stride;
  612. indices.push(i * stride + j);
  613. indices.push(i * stride + nextJ);
  614. indices.push(nextI * stride + j);
  615. indices.push(i * stride + nextJ);
  616. indices.push(nextI * stride + nextJ);
  617. indices.push(nextI * stride + j);
  618. }
  619. }
  620. // Sides
  621. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  622. // Result
  623. var vertexData = new VertexData();
  624. vertexData.indices = indices;
  625. vertexData.positions = positions;
  626. vertexData.normals = normals;
  627. vertexData.uvs = uvs;
  628. return vertexData;
  629. }
  630. public static CreateLines(points: Vector3[]): VertexData {
  631. var indices = [];
  632. var positions = [];
  633. for (var index = 0; index < points.length; index++) {
  634. positions.push(points[index].x, points[index].y, points[index].z);
  635. if (index > 0) {
  636. indices.push(index - 1);
  637. indices.push(index);
  638. }
  639. }
  640. // Result
  641. var vertexData = new VertexData();
  642. vertexData.indices = indices;
  643. vertexData.positions = positions;
  644. return vertexData;
  645. }
  646. public static CreateDashedLines(points: Vector3[], dashSize: number, gapSize: number, dashNb: number): VertexData {
  647. dashSize = dashSize || 3;
  648. gapSize = gapSize || 1;
  649. dashNb = dashNb || 200;
  650. var positions = new Array<number>();
  651. var indices = new Array<number>();
  652. var curvect = Vector3.Zero();
  653. var lg = 0;
  654. var nb = 0;
  655. var shft = 0;
  656. var dashshft = 0;
  657. var curshft = 0;
  658. var idx = 0;
  659. var i = 0;
  660. for (i = 0; i < points.length - 1; i++) {
  661. points[i + 1].subtractToRef(points[i], curvect);
  662. lg += curvect.length();
  663. }
  664. shft = lg / dashNb;
  665. dashshft = dashSize * shft / (dashSize + gapSize);
  666. for (i = 0; i < points.length - 1; i++) {
  667. points[i + 1].subtractToRef(points[i], curvect);
  668. nb = Math.floor(curvect.length() / shft);
  669. curvect.normalize();
  670. for (var j = 0; j < nb; j++) {
  671. curshft = shft * j;
  672. positions.push(points[i].x + curshft * curvect.x, points[i].y + curshft * curvect.y, points[i].z + curshft * curvect.z);
  673. positions.push(points[i].x + (curshft + dashshft) * curvect.x, points[i].y + (curshft + dashshft) * curvect.y, points[i].z + (curshft + dashshft) * curvect.z);
  674. indices.push(idx, idx + 1);
  675. idx += 2;
  676. }
  677. }
  678. // Result
  679. var vertexData = new VertexData();
  680. vertexData.positions = positions;
  681. vertexData.indices = indices;
  682. return vertexData;
  683. }
  684. public static CreateGround(width: number, height: number, subdivisions: number): VertexData {
  685. var indices = [];
  686. var positions = [];
  687. var normals = [];
  688. var uvs = [];
  689. var row: number, col: number;
  690. width = width || 1;
  691. height = height || 1;
  692. subdivisions = subdivisions || 1;
  693. for (row = 0; row <= subdivisions; row++) {
  694. for (col = 0; col <= subdivisions; col++) {
  695. var position = new Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));
  696. var normal = new Vector3(0, 1.0, 0);
  697. positions.push(position.x, position.y, position.z);
  698. normals.push(normal.x, normal.y, normal.z);
  699. uvs.push(col / subdivisions, 1.0 - row / subdivisions);
  700. }
  701. }
  702. for (row = 0; row < subdivisions; row++) {
  703. for (col = 0; col < subdivisions; col++) {
  704. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  705. indices.push(col + 1 + row * (subdivisions + 1));
  706. indices.push(col + row * (subdivisions + 1));
  707. indices.push(col + (row + 1) * (subdivisions + 1));
  708. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  709. indices.push(col + row * (subdivisions + 1));
  710. }
  711. }
  712. // Result
  713. var vertexData = new VertexData();
  714. vertexData.indices = indices;
  715. vertexData.positions = positions;
  716. vertexData.normals = normals;
  717. vertexData.uvs = uvs;
  718. return vertexData;
  719. }
  720. public static CreateTiledGround(xmin: number, zmin: number, xmax: number, zmax: number, subdivisions = { w: 1, h: 1 }, precision = { w: 1, h: 1 }): VertexData {
  721. var indices = [];
  722. var positions = [];
  723. var normals = [];
  724. var uvs = [];
  725. var row: number, col: number, tileRow: number, tileCol: number;
  726. subdivisions.h = (subdivisions.w < 1) ? 1 : subdivisions.h;
  727. subdivisions.w = (subdivisions.w < 1) ? 1 : subdivisions.w;
  728. precision.w = (precision.w < 1) ? 1 : precision.w;
  729. precision.h = (precision.h < 1) ? 1 : precision.h;
  730. var tileSize = {
  731. 'w': (xmax - xmin) / subdivisions.w,
  732. 'h': (zmax - zmin) / subdivisions.h
  733. };
  734. function applyTile(xTileMin: number, zTileMin: number, xTileMax: number, zTileMax: number) {
  735. // Indices
  736. var base = positions.length / 3;
  737. var rowLength = precision.w + 1;
  738. for (row = 0; row < precision.h; row++) {
  739. for (col = 0; col < precision.w; col++) {
  740. var square = [
  741. base + col + row * rowLength,
  742. base + (col + 1) + row * rowLength,
  743. base + (col + 1) + (row + 1) * rowLength,
  744. base + col + (row + 1) * rowLength
  745. ];
  746. indices.push(square[1]);
  747. indices.push(square[2]);
  748. indices.push(square[3]);
  749. indices.push(square[0]);
  750. indices.push(square[1]);
  751. indices.push(square[3]);
  752. }
  753. }
  754. // Position, normals and uvs
  755. var position = Vector3.Zero();
  756. var normal = new Vector3(0, 1.0, 0);
  757. for (row = 0; row <= precision.h; row++) {
  758. position.z = (row * (zTileMax - zTileMin)) / precision.h + zTileMin;
  759. for (col = 0; col <= precision.w; col++) {
  760. position.x = (col * (xTileMax - xTileMin)) / precision.w + xTileMin;
  761. position.y = 0;
  762. positions.push(position.x, position.y, position.z);
  763. normals.push(normal.x, normal.y, normal.z);
  764. uvs.push(col / precision.w, row / precision.h);
  765. }
  766. }
  767. }
  768. for (tileRow = 0; tileRow < subdivisions.h; tileRow++) {
  769. for (tileCol = 0; tileCol < subdivisions.w; tileCol++) {
  770. applyTile(
  771. xmin + tileCol * tileSize.w,
  772. zmin + tileRow * tileSize.h,
  773. xmin + (tileCol + 1) * tileSize.w,
  774. zmin + (tileRow + 1) * tileSize.h
  775. );
  776. }
  777. }
  778. // Result
  779. var vertexData = new VertexData();
  780. vertexData.indices = indices;
  781. vertexData.positions = positions;
  782. vertexData.normals = normals;
  783. vertexData.uvs = uvs;
  784. return vertexData;
  785. }
  786. public static CreateGroundFromHeightMap(width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, buffer: Uint8Array, bufferWidth: number, bufferHeight: number): VertexData {
  787. var indices = [];
  788. var positions = [];
  789. var normals = [];
  790. var uvs = [];
  791. var row, col;
  792. // Vertices
  793. for (row = 0; row <= subdivisions; row++) {
  794. for (col = 0; col <= subdivisions; col++) {
  795. var position = new Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));
  796. // Compute height
  797. var heightMapX = (((position.x + width / 2) / width) * (bufferWidth - 1)) | 0;
  798. var heightMapY = ((1.0 - (position.z + height / 2) / height) * (bufferHeight - 1)) | 0;
  799. var pos = (heightMapX + heightMapY * bufferWidth) * 4;
  800. var r = buffer[pos] / 255.0;
  801. var g = buffer[pos + 1] / 255.0;
  802. var b = buffer[pos + 2] / 255.0;
  803. var gradient = r * 0.3 + g * 0.59 + b * 0.11;
  804. position.y = minHeight + (maxHeight - minHeight) * gradient;
  805. // Add vertex
  806. positions.push(position.x, position.y, position.z);
  807. normals.push(0, 0, 0);
  808. uvs.push(col / subdivisions, 1.0 - row / subdivisions);
  809. }
  810. }
  811. // Indices
  812. for (row = 0; row < subdivisions; row++) {
  813. for (col = 0; col < subdivisions; col++) {
  814. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  815. indices.push(col + 1 + row * (subdivisions + 1));
  816. indices.push(col + row * (subdivisions + 1));
  817. indices.push(col + (row + 1) * (subdivisions + 1));
  818. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  819. indices.push(col + row * (subdivisions + 1));
  820. }
  821. }
  822. // Normals
  823. VertexData.ComputeNormals(positions, indices, normals);
  824. // Result
  825. var vertexData = new VertexData();
  826. vertexData.indices = indices;
  827. vertexData.positions = positions;
  828. vertexData.normals = normals;
  829. vertexData.uvs = uvs;
  830. return vertexData;
  831. }
  832. public static CreatePlane(size: number, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  833. var indices = [];
  834. var positions = [];
  835. var normals = [];
  836. var uvs = [];
  837. size = size || 1;
  838. // Vertices
  839. var halfSize = size / 2.0;
  840. positions.push(-halfSize, -halfSize, 0);
  841. normals.push(0, 0, -1.0);
  842. uvs.push(0.0, 0.0);
  843. positions.push(halfSize, -halfSize, 0);
  844. normals.push(0, 0, -1.0);
  845. uvs.push(1.0, 0.0);
  846. positions.push(halfSize, halfSize, 0);
  847. normals.push(0, 0, -1.0);
  848. uvs.push(1.0, 1.0);
  849. positions.push(-halfSize, halfSize, 0);
  850. normals.push(0, 0, -1.0);
  851. uvs.push(0.0, 1.0);
  852. // Indices
  853. indices.push(0);
  854. indices.push(1);
  855. indices.push(2);
  856. indices.push(0);
  857. indices.push(2);
  858. indices.push(3);
  859. // Sides
  860. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  861. // Result
  862. var vertexData = new VertexData();
  863. vertexData.indices = indices;
  864. vertexData.positions = positions;
  865. vertexData.normals = normals;
  866. vertexData.uvs = uvs;
  867. return vertexData;
  868. }
  869. public static CreateDisc(radius: number, tessellation: number, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  870. var positions = [];
  871. var indices = [];
  872. var normals = [];
  873. var uvs = [];
  874. // positions and uvs
  875. positions.push(0, 0, 0); // disc center first
  876. uvs.push(0.5, 0.5);
  877. var step = Math.PI * 2 / tessellation;
  878. for (var a = 0; a < Math.PI * 2; a += step) {
  879. var x = Math.cos(a);
  880. var y = Math.sin(a);
  881. var u = (x + 1) / 2;
  882. var v = (1 - y) / 2;
  883. positions.push(radius * x, radius * y, 0);
  884. uvs.push(u, v);
  885. }
  886. positions.push(positions[3], positions[4], positions[5]); // close the circle
  887. uvs.push(uvs[2], uvs[3]);
  888. //indices
  889. var vertexNb = positions.length / 3;
  890. for (var i = 1; i < vertexNb - 1; i++) {
  891. indices.push(i + 1, 0, i);
  892. }
  893. // result
  894. VertexData.ComputeNormals(positions, indices, normals);
  895. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  896. var vertexData = new VertexData();
  897. vertexData.indices = indices;
  898. vertexData.positions = positions;
  899. vertexData.normals = normals;
  900. vertexData.uvs = uvs;
  901. return vertexData;
  902. }
  903. // based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
  904. public static CreateTorusKnot(radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, sideOrientation: number = Mesh.DEFAULTSIDE): VertexData {
  905. var indices = [];
  906. var positions = [];
  907. var normals = [];
  908. var uvs = [];
  909. radius = radius || 2;
  910. tube = tube || 0.5;
  911. radialSegments = radialSegments || 32;
  912. tubularSegments = tubularSegments || 32;
  913. p = p || 2;
  914. q = q || 3;
  915. // Helper
  916. var getPos = (angle) => {
  917. var cu = Math.cos(angle);
  918. var su = Math.sin(angle);
  919. var quOverP = q / p * angle;
  920. var cs = Math.cos(quOverP);
  921. var tx = radius * (2 + cs) * 0.5 * cu;
  922. var ty = radius * (2 + cs) * su * 0.5;
  923. var tz = radius * Math.sin(quOverP) * 0.5;
  924. return new Vector3(tx, ty, tz);
  925. };
  926. // Vertices
  927. for (var i = 0; i <= radialSegments; i++) {
  928. var modI = i % radialSegments;
  929. var u = modI / radialSegments * 2 * p * Math.PI;
  930. var p1 = getPos(u);
  931. var p2 = getPos(u + 0.01);
  932. var tang = p2.subtract(p1);
  933. var n = p2.add(p1);
  934. var bitan = Vector3.Cross(tang, n);
  935. n = Vector3.Cross(bitan, tang);
  936. bitan.normalize();
  937. n.normalize();
  938. for (var j = 0; j < tubularSegments; j++) {
  939. var modJ = j % tubularSegments;
  940. var v = modJ / tubularSegments * 2 * Math.PI;
  941. var cx = -tube * Math.cos(v);
  942. var cy = tube * Math.sin(v);
  943. positions.push(p1.x + cx * n.x + cy * bitan.x);
  944. positions.push(p1.y + cx * n.y + cy * bitan.y);
  945. positions.push(p1.z + cx * n.z + cy * bitan.z);
  946. uvs.push(i / radialSegments);
  947. uvs.push(j / tubularSegments);
  948. }
  949. }
  950. for (i = 0; i < radialSegments; i++) {
  951. for (j = 0; j < tubularSegments; j++) {
  952. var jNext = (j + 1) % tubularSegments;
  953. var a = i * tubularSegments + j;
  954. var b = (i + 1) * tubularSegments + j;
  955. var c = (i + 1) * tubularSegments + jNext;
  956. var d = i * tubularSegments + jNext;
  957. indices.push(d); indices.push(b); indices.push(a);
  958. indices.push(d); indices.push(c); indices.push(b);
  959. }
  960. }
  961. // Normals
  962. VertexData.ComputeNormals(positions, indices, normals);
  963. // Sides
  964. VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs);
  965. // Result
  966. var vertexData = new VertexData();
  967. vertexData.indices = indices;
  968. vertexData.positions = positions;
  969. vertexData.normals = normals;
  970. vertexData.uvs = uvs;
  971. return vertexData;
  972. }
  973. // Tools
  974. /**
  975. * @param {any} - positions (number[] or Float32Array)
  976. * @param {any} - indices (number[] or Uint16Array)
  977. * @param {any} - normals (number[] or Float32Array)
  978. */
  979. public static ComputeNormals(positions: any, indices: any, normals: any) {
  980. var index = 0;
  981. // temp Vector3
  982. var p1 = Vector3.Zero();
  983. var p2 = Vector3.Zero();
  984. var p3 = Vector3.Zero();
  985. var p1p2 = Vector3.Zero();
  986. var p3p2 = Vector3.Zero();
  987. var faceNormal = Vector3.Zero();
  988. var vertexNormali1 = Vector3.Zero();
  989. var vertexNormali2 = Vector3.Zero();
  990. var vertexNormali3 = Vector3.Zero();
  991. // indice triplet = 1 face
  992. var nbFaces = indices.length / 3;
  993. for (index = 0; index < nbFaces; index++) {
  994. var i1 = indices[index * 3];
  995. var i2 = indices[index * 3 + 1];
  996. var i3 = indices[index * 3 + 2];
  997. // setting the temp V3
  998. Vector3.FromFloatsToRef(positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2], p1);
  999. Vector3.FromFloatsToRef(positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2], p2);
  1000. Vector3.FromFloatsToRef(positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2], p3);
  1001. p1.subtractToRef(p2, p1p2);
  1002. p3.subtractToRef(p2, p3p2);
  1003. Vector3.CrossToRef(p1p2, p3p2, faceNormal);
  1004. faceNormal.normalize();
  1005. // All intermediate results are stored in the normals array :
  1006. // get the normals at i1, i2 and i3 indexes
  1007. normals[i1 * 3] = normals[i1 * 3] || 0.0;
  1008. normals[i1 * 3 + 1] = normals[i1 * 3 + 1] || 0.0;
  1009. normals[i1 * 3 + 2] = normals[i1 * 3 + 2] || 0.0;
  1010. normals[i2 * 3] = normals[i2 * 3] || 0.0;
  1011. normals[i2 * 3 + 1] = normals[i2 * 3 + 1] || 0.0;
  1012. normals[i2 * 3 + 2] = normals[i2 * 3 + 2] || 0.0;
  1013. normals[i3 * 3] = normals[i3 * 3] || 0.0;
  1014. normals[i3 * 3 + 1] = normals[i3 * 3 + 1] || 0.0;
  1015. normals[i3 * 3 + 2] = normals[i3 * 3 + 2] || 0.0;
  1016. // make intermediate vectors3 from normals values
  1017. Vector3.FromFloatsToRef(normals[i1 * 3], normals[i1 * 3 + 1], normals[i1 * 3 + 2], vertexNormali1);
  1018. Vector3.FromFloatsToRef(normals[i2 * 3], normals[i2 * 3 + 1], normals[i2 * 3 + 2], vertexNormali2);
  1019. Vector3.FromFloatsToRef(normals[i3 * 3], normals[i3 * 3 + 1], normals[i3 * 3 + 2], vertexNormali3);
  1020. // add the current face normals to these intermediate vectors3
  1021. vertexNormali1 = vertexNormali1.addInPlace(faceNormal);
  1022. vertexNormali2 = vertexNormali2.addInPlace(faceNormal);
  1023. vertexNormali3 = vertexNormali3.addInPlace(faceNormal);
  1024. // store back intermediate vectors3 into the normals array
  1025. normals[i1 * 3] = vertexNormali1.x;
  1026. normals[i1 * 3 + 1] = vertexNormali1.y;
  1027. normals[i1 * 3 + 2] = vertexNormali1.z;
  1028. normals[i2 * 3] = vertexNormali2.x;
  1029. normals[i2 * 3 + 1] = vertexNormali2.y;
  1030. normals[i2 * 3 + 2] = vertexNormali2.z;
  1031. normals[i3 * 3] = vertexNormali3.x;
  1032. normals[i3 * 3 + 1] = vertexNormali3.y;
  1033. normals[i3 * 3 + 2] = vertexNormali3.z;
  1034. }
  1035. // last normalization
  1036. for (index = 0; index < normals.length / 3; index++) {
  1037. Vector3.FromFloatsToRef(normals[index * 3], normals[index * 3 + 1], normals[index * 3 + 2], vertexNormali1);
  1038. vertexNormali1.normalize();
  1039. normals[index * 3] = vertexNormali1.x;
  1040. normals[index * 3 + 1] = vertexNormali1.y;
  1041. normals[index * 3 + 2] = vertexNormali1.z;
  1042. }
  1043. }
  1044. private static _ComputeSides(sideOrientation: number, positions: number[], indices: number[], normals: number[], uvs: number[]) {
  1045. var li: number = indices.length;
  1046. var ln: number = normals.length;
  1047. var i: number;
  1048. var n: number;
  1049. sideOrientation = sideOrientation || Mesh.DEFAULTSIDE;
  1050. switch (sideOrientation) {
  1051. case Mesh.FRONTSIDE:
  1052. // nothing changed
  1053. break;
  1054. case Mesh.BACKSIDE:
  1055. var tmp: number;
  1056. // indices
  1057. for (i = 0; i < li; i += 3) {
  1058. tmp = indices[i];
  1059. indices[i] = indices[i + 2];
  1060. indices[i + 2] = tmp;
  1061. }
  1062. // normals
  1063. for (n = 0; n < ln; n++) {
  1064. normals[n] = -normals[n];
  1065. }
  1066. break;
  1067. case Mesh.DOUBLESIDE:
  1068. // positions
  1069. var lp: number = positions.length;
  1070. var l: number = lp / 3;
  1071. for (var p = 0; p < lp; p++) {
  1072. positions[lp + p] = positions[p];
  1073. }
  1074. // indices
  1075. for (i = 0; i < li; i += 3) {
  1076. indices[i + li] = indices[i + 2] + l;
  1077. indices[i + 1 + li] = indices[i + 1] + l;
  1078. indices[i + 2 + li] = indices[i] + l;
  1079. }
  1080. // normals
  1081. for (n = 0; n < ln; n++) {
  1082. normals[ln + n] = -normals[n];
  1083. }
  1084. // uvs
  1085. var lu: number = uvs.length;
  1086. for (var u: number = 0; u < lu; u++) {
  1087. uvs[u + lu] = uvs[u];
  1088. }
  1089. break;
  1090. }
  1091. }
  1092. }
  1093. }