babylon.mesh.vertexData.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. "use strict";
  2. var BABYLON = BABYLON || {};
  3. (function () {
  4. BABYLON.VertexData = function () {
  5. };
  6. // Methods
  7. BABYLON.VertexData.prototype.applyToMesh = function(mesh, updatable) {
  8. if (this.positions) {
  9. mesh.setVerticesData(this.positions, BABYLON.VertexBuffer.PositionKind, updatable);
  10. }
  11. if (this.normals) {
  12. mesh.setVerticesData(this.normals, BABYLON.VertexBuffer.NormalKind, updatable);
  13. }
  14. if (this.uvs) {
  15. mesh.setVerticesData(this.uvs, BABYLON.VertexBuffer.UVKind, updatable);
  16. }
  17. if (this.indices) {
  18. mesh.setIndices(this.indices);
  19. }
  20. };
  21. BABYLON.VertexData.prototype.transform = function (matrix) {
  22. var transformed = BABYLON.Vector3.Zero();
  23. if (this.positions) {
  24. var position = BABYLON.Vector3.Zero();
  25. for (var index = 0; index < this.positions.length; index += 3) {
  26. BABYLON.Vector3.FromArrayToRef(this.positions, index, position);
  27. BABYLON.Vector3.TransformCoordinatesToRef(position, matrix, transformed);
  28. this.positions[index] = transformed.x;
  29. this.positions[index + 1] = transformed.y;
  30. this.positions[index + 2] = transformed.z;
  31. }
  32. }
  33. if (this.normals) {
  34. var normal = BABYLON.Vector3.Zero();
  35. for (index = 0; index < this.normals.length; index += 3) {
  36. BABYLON.Vector3.FromArrayToRef(this.normals, index, normal);
  37. BABYLON.Vector3.TransformNormalToRef(normal, matrix, transformed);
  38. this.normals[index] = transformed.x;
  39. this.normals[index + 1] = transformed.y;
  40. this.normals[index + 2] = transformed.z;
  41. }
  42. }
  43. };
  44. BABYLON.VertexData.prototype.merge = function (other) {
  45. if (other.indices) {
  46. if (!this.indices) {
  47. this.indices = [];
  48. }
  49. var offset = this.positions ? this.positions.length / 3 : 0;
  50. for (var index = 0; index < other.indices.length; index++) {
  51. this.indices.push(other.indices[index] + offset);
  52. }
  53. }
  54. if (other.positions) {
  55. if (!this.positions) {
  56. this.positions = [];
  57. }
  58. for (index = 0; index < other.positions.length; index++) {
  59. this.positions.push(other.positions[index]);
  60. }
  61. }
  62. if (other.normals) {
  63. if (!this.normals) {
  64. this.normals = [];
  65. }
  66. for (index = 0; index < other.normals.length; index++) {
  67. this.normals.push(other.normals[index]);
  68. }
  69. }
  70. if (other.uvs) {
  71. if (!this.uvs) {
  72. this.uvs = [];
  73. }
  74. for (index = 0; index < other.uvs.length; index++) {
  75. this.uvs.push(other.uvs[index]);
  76. }
  77. }
  78. };
  79. // Statics
  80. BABYLON.VertexData.CreateBox = function(size) {
  81. var normalsSource = [
  82. new BABYLON.Vector3(0, 0, 1),
  83. new BABYLON.Vector3(0, 0, -1),
  84. new BABYLON.Vector3(1, 0, 0),
  85. new BABYLON.Vector3(-1, 0, 0),
  86. new BABYLON.Vector3(0, 1, 0),
  87. new BABYLON.Vector3(0, -1, 0)
  88. ];
  89. var indices = [];
  90. var positions = [];
  91. var normals = [];
  92. var uvs = [];
  93. // Create each face in turn.
  94. for (var index = 0; index < normalsSource.length; index++) {
  95. var normal = normalsSource[index];
  96. // Get two vectors perpendicular to the face normal and to each other.
  97. var side1 = new BABYLON.Vector3(normal.y, normal.z, normal.x);
  98. var side2 = BABYLON.Vector3.Cross(normal, side1);
  99. // Six indices (two triangles) per face.
  100. var verticesLength = positions.length / 3;
  101. indices.push(verticesLength);
  102. indices.push(verticesLength + 1);
  103. indices.push(verticesLength + 2);
  104. indices.push(verticesLength);
  105. indices.push(verticesLength + 2);
  106. indices.push(verticesLength + 3);
  107. // Four vertices per face.
  108. var vertex = normal.subtract(side1).subtract(side2).scale(size / 2);
  109. positions.push(vertex.x, vertex.y, vertex.z);
  110. normals.push(normal.x, normal.y, normal.z);
  111. uvs.push(1.0, 1.0);
  112. vertex = normal.subtract(side1).add(side2).scale(size / 2);
  113. positions.push(vertex.x, vertex.y, vertex.z);
  114. normals.push(normal.x, normal.y, normal.z);
  115. uvs.push(0.0, 1.0);
  116. vertex = normal.add(side1).add(side2).scale(size / 2);
  117. positions.push(vertex.x, vertex.y, vertex.z);
  118. normals.push(normal.x, normal.y, normal.z);
  119. uvs.push(0.0, 0.0);
  120. vertex = normal.add(side1).subtract(side2).scale(size / 2);
  121. positions.push(vertex.x, vertex.y, vertex.z);
  122. normals.push(normal.x, normal.y, normal.z);
  123. uvs.push(1.0, 0.0);
  124. }
  125. // Result
  126. var vertexData = new BABYLON.VertexData();
  127. vertexData.indices = indices;
  128. vertexData.positions = positions;
  129. vertexData.normals = normals;
  130. vertexData.uvs = uvs;
  131. return vertexData;
  132. };
  133. BABYLON.VertexData.CreateSphere = function (segments, diameter) {
  134. var radius = diameter / 2;
  135. var totalZRotationSteps = 2 + segments;
  136. var totalYRotationSteps = 2 * totalZRotationSteps;
  137. var indices = [];
  138. var positions = [];
  139. var normals = [];
  140. var uvs = [];
  141. for (var zRotationStep = 0; zRotationStep <= totalZRotationSteps; zRotationStep++) {
  142. var normalizedZ = zRotationStep / totalZRotationSteps;
  143. var angleZ = (normalizedZ * Math.PI);
  144. for (var yRotationStep = 0; yRotationStep <= totalYRotationSteps; yRotationStep++) {
  145. var normalizedY = yRotationStep / totalYRotationSteps;
  146. var angleY = normalizedY * Math.PI * 2;
  147. var rotationZ = BABYLON.Matrix.RotationZ(-angleZ);
  148. var rotationY = BABYLON.Matrix.RotationY(angleY);
  149. var afterRotZ = BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.Up(), rotationZ);
  150. var complete = BABYLON.Vector3.TransformCoordinates(afterRotZ, rotationY);
  151. var vertex = complete.scale(radius);
  152. var normal = BABYLON.Vector3.Normalize(vertex);
  153. positions.push(vertex.x, vertex.y, vertex.z);
  154. normals.push(normal.x, normal.y, normal.z);
  155. uvs.push(normalizedZ, normalizedY);
  156. }
  157. if (zRotationStep > 0) {
  158. var verticesCount = positions.length / 3;
  159. for (var firstIndex = verticesCount - 2 * (totalYRotationSteps + 1) ; (firstIndex + totalYRotationSteps + 2) < verticesCount; firstIndex++) {
  160. indices.push((firstIndex));
  161. indices.push((firstIndex + 1));
  162. indices.push(firstIndex + totalYRotationSteps + 1);
  163. indices.push((firstIndex + totalYRotationSteps + 1));
  164. indices.push((firstIndex + 1));
  165. indices.push((firstIndex + totalYRotationSteps + 2));
  166. }
  167. }
  168. }
  169. // Result
  170. var vertexData = new BABYLON.VertexData();
  171. vertexData.indices = indices;
  172. vertexData.positions = positions;
  173. vertexData.normals = normals;
  174. vertexData.uvs = uvs;
  175. return vertexData;
  176. };
  177. BABYLON.VertexData.CreateCylinder = function (height, diameterTop, diameterBottom, tessellation) {
  178. var radiusTop = diameterTop / 2;
  179. var radiusBottom = diameterBottom / 2;
  180. var indices = [];
  181. var positions = [];
  182. var normals = [];
  183. var uvs = [];
  184. var getCircleVector = function (i) {
  185. var angle = (i * 2.0 * Math.PI / tessellation);
  186. var dx = Math.sin(angle);
  187. var dz = Math.cos(angle);
  188. return new BABYLON.Vector3(dx, 0, dz);
  189. };
  190. var createCylinderCap = function (isTop) {
  191. var radius = isTop ? radiusTop : radiusBottom;
  192. if (radius == 0) {
  193. return;
  194. }
  195. // Create cap indices.
  196. for (var i = 0; i < tessellation - 2; i++) {
  197. var i1 = (i + 1) % tessellation;
  198. var i2 = (i + 2) % tessellation;
  199. if (!isTop) {
  200. var tmp = i1;
  201. var i1 = i2;
  202. i2 = tmp;
  203. }
  204. var vbase = positions.length / 3;
  205. indices.push(vbase);
  206. indices.push(vbase + i1);
  207. indices.push(vbase + i2);
  208. }
  209. // Which end of the cylinder is this?
  210. var normal = new BABYLON.Vector3(0, -1, 0);
  211. var textureScale = new BABYLON.Vector2(-0.5, -0.5);
  212. if (!isTop) {
  213. normal = normal.scale(-1);
  214. textureScale.x = -textureScale.x;
  215. }
  216. // Create cap vertices.
  217. for (var i = 0; i < tessellation; i++) {
  218. var circleVector = getCircleVector(i);
  219. var position = circleVector.scale(radius).add(normal.scale(height));
  220. var textureCoordinate = new BABYLON.Vector2(circleVector.x * textureScale.x + 0.5, circleVector.z * textureScale.y + 0.5);
  221. positions.push(position.x, position.y, position.z);
  222. normals.push(normal.x, normal.y, normal.z);
  223. uvs.push(textureCoordinate.x, textureCoordinate.y);
  224. }
  225. };
  226. height /= 2;
  227. var topOffset = new BABYLON.Vector3(0, 1, 0).scale(height);
  228. var stride = tessellation + 1;
  229. // Create a ring of triangles around the outside of the cylinder.
  230. for (var i = 0; i <= tessellation; i++) {
  231. var normal = getCircleVector(i);
  232. var sideOffsetBottom = normal.scale(radiusBottom);
  233. var sideOffsetTop = normal.scale(radiusTop);
  234. var textureCoordinate = new BABYLON.Vector2(i / tessellation, 0);
  235. var position = sideOffsetBottom.add(topOffset);
  236. positions.push(position.x, position.y, position.z);
  237. normals.push(normal.x, normal.y, normal.z);
  238. uvs.push(textureCoordinate.x, textureCoordinate.y);
  239. position = sideOffsetTop.subtract(topOffset);
  240. textureCoordinate.y += 1;
  241. positions.push(position.x, position.y, position.z);
  242. normals.push(normal.x, normal.y, normal.z);
  243. uvs.push(textureCoordinate.x, textureCoordinate.y);
  244. indices.push(i * 2);
  245. indices.push((i * 2 + 2) % (stride * 2));
  246. indices.push(i * 2 + 1);
  247. indices.push(i * 2 + 1);
  248. indices.push((i * 2 + 2) % (stride * 2));
  249. indices.push((i * 2 + 3) % (stride * 2));
  250. }
  251. // Create flat triangle fan caps to seal the top and bottom.
  252. createCylinderCap(true);
  253. createCylinderCap(false);
  254. // Result
  255. var vertexData = new BABYLON.VertexData();
  256. vertexData.indices = indices;
  257. vertexData.positions = positions;
  258. vertexData.normals = normals;
  259. vertexData.uvs = uvs;
  260. return vertexData;
  261. };
  262. BABYLON.VertexData.CreateTorus = function (diameter, thickness, tessellation) {
  263. var indices = [];
  264. var positions = [];
  265. var normals = [];
  266. var uvs = [];
  267. var stride = tessellation + 1;
  268. for (var i = 0; i <= tessellation; i++) {
  269. var u = i / tessellation;
  270. var outerAngle = i * Math.PI * 2.0 / tessellation - Math.PI / 2.0;
  271. var transform = BABYLON.Matrix.Translation(diameter / 2.0, 0, 0).multiply(BABYLON.Matrix.RotationY(outerAngle));
  272. for (var j = 0; j <= tessellation; j++) {
  273. var v = 1 - j / tessellation;
  274. var innerAngle = j * Math.PI * 2.0 / tessellation + Math.PI;
  275. var dx = Math.cos(innerAngle);
  276. var dy = Math.sin(innerAngle);
  277. // Create a vertex.
  278. var normal = new BABYLON.Vector3(dx, dy, 0);
  279. var position = normal.scale(thickness / 2);
  280. var textureCoordinate = new BABYLON.Vector2(u, v);
  281. position = BABYLON.Vector3.TransformCoordinates(position, transform);
  282. normal = BABYLON.Vector3.TransformNormal(normal, transform);
  283. positions.push(position.x, position.y, position.z);
  284. normals.push(normal.x, normal.y, normal.z);
  285. uvs.push(textureCoordinate.x, textureCoordinate.y);
  286. // And create indices for two triangles.
  287. var nextI = (i + 1) % stride;
  288. var nextJ = (j + 1) % stride;
  289. indices.push(i * stride + j);
  290. indices.push(i * stride + nextJ);
  291. indices.push(nextI * stride + j);
  292. indices.push(i * stride + nextJ);
  293. indices.push(nextI * stride + nextJ);
  294. indices.push(nextI * stride + j);
  295. }
  296. }
  297. // Result
  298. var vertexData = new BABYLON.VertexData();
  299. vertexData.indices = indices;
  300. vertexData.positions = positions;
  301. vertexData.normals = normals;
  302. vertexData.uvs = uvs;
  303. return vertexData;
  304. };
  305. BABYLON.VertexData.CreateGround = function (width, height, subdivisions) {
  306. var indices = [];
  307. var positions = [];
  308. var normals = [];
  309. var uvs = [];
  310. var row, col;
  311. for (row = 0; row <= subdivisions; row++) {
  312. for (col = 0; col <= subdivisions; col++) {
  313. var position = new BABYLON.Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));
  314. var normal = new BABYLON.Vector3(0, 1.0, 0);
  315. positions.push(position.x, position.y, position.z);
  316. normals.push(normal.x, normal.y, normal.z);
  317. uvs.push(col / subdivisions, 1.0 - row / subdivisions);
  318. }
  319. }
  320. for (row = 0; row < subdivisions; row++) {
  321. for (col = 0; col < subdivisions; col++) {
  322. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  323. indices.push(col + 1 + row * (subdivisions + 1));
  324. indices.push(col + row * (subdivisions + 1));
  325. indices.push(col + (row + 1) * (subdivisions + 1));
  326. indices.push(col + 1 + (row + 1) * (subdivisions + 1));
  327. indices.push(col + row * (subdivisions + 1));
  328. }
  329. }
  330. // Result
  331. var vertexData = new BABYLON.VertexData();
  332. vertexData.indices = indices;
  333. vertexData.positions = positions;
  334. vertexData.normals = normals;
  335. vertexData.uvs = uvs;
  336. return vertexData;
  337. };
  338. BABYLON.VertexData.CreatePlane = function (size) {
  339. var indices = [];
  340. var positions = [];
  341. var normals = [];
  342. var uvs = [];
  343. // Vertices
  344. var halfSize = size / 2.0;
  345. positions.push(-halfSize, -halfSize, 0);
  346. normals.push(0, 0, -1.0);
  347. uvs.push(0.0, 0.0);
  348. positions.push(halfSize, -halfSize, 0);
  349. normals.push(0, 0, -1.0);
  350. uvs.push(1.0, 0.0);
  351. positions.push(halfSize, halfSize, 0);
  352. normals.push(0, 0, -1.0);
  353. uvs.push(1.0, 1.0);
  354. positions.push(-halfSize, halfSize, 0);
  355. normals.push(0, 0, -1.0);
  356. uvs.push(0.0, 1.0);
  357. // Indices
  358. indices.push(0);
  359. indices.push(1);
  360. indices.push(2);
  361. indices.push(0);
  362. indices.push(2);
  363. indices.push(3);
  364. // Result
  365. var vertexData = new BABYLON.VertexData();
  366. vertexData.indices = indices;
  367. vertexData.positions = positions;
  368. vertexData.normals = normals;
  369. vertexData.uvs = uvs;
  370. return vertexData;
  371. };
  372. })();