babylon.meshBuilder.js 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. var BABYLON;
  2. (function (BABYLON) {
  3. var MeshBuilder = (function () {
  4. function MeshBuilder() {
  5. }
  6. /**
  7. * Creates a box mesh.
  8. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#box
  9. * The parameter `size` sets the size (float) of each box side (default 1).
  10. * You can set some different box dimensions by using the parameters `width`, `height` and `depth` (all by default have the same value than `size`).
  11. * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of 6 Color3 elements) and `faceUV` (an array of 6 Vector4 elements).
  12. * Please read this tutorial : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors
  13. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  14. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  15. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  16. */
  17. MeshBuilder.CreateBox = function (name, options, scene) {
  18. var box = new BABYLON.Mesh(name, scene);
  19. var vertexData = BABYLON.VertexData.CreateBox(options);
  20. vertexData.applyToMesh(box, options.updatable);
  21. return box;
  22. };
  23. /**
  24. * Creates a sphere mesh.
  25. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#sphere
  26. * The parameter `diameter` sets the diameter size (float) of the sphere (default 1).
  27. * You can set some different sphere dimensions, for instance to build an ellipsoid, by using the parameters `diameterX`, `diameterY` and `diameterZ` (all by default have the same value than `diameter`).
  28. * The parameter `segments` sets the sphere number of horizontal stripes (positive integer, default 32).
  29. * You can create an unclosed sphere with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference (latitude) : 2 x PI x ratio
  30. * You can create an unclosed sphere on its height with the parameter `slice` (positive float, default1), valued between 0 and 1, what is the height ratio (longitude).
  31. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  32. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  33. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  34. */
  35. MeshBuilder.CreateSphere = function (name, options, scene) {
  36. var sphere = new BABYLON.Mesh(name, scene);
  37. var vertexData = BABYLON.VertexData.CreateSphere(options);
  38. vertexData.applyToMesh(sphere, options.updatable);
  39. return sphere;
  40. };
  41. /**
  42. * Creates a plane polygonal mesh. By default, this is a disc.
  43. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#disc
  44. * The parameter `radius` sets the radius size (float) of the polygon (default 0.5).
  45. * The parameter `tessellation` sets the number of polygon sides (positive integer, default 64). So a tessellation valued to 3 will build a triangle, to 4 a square, etc.
  46. * You can create an unclosed polygon with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference : 2 x PI x ratio
  47. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  48. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  49. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  50. */
  51. MeshBuilder.CreateDisc = function (name, options, scene) {
  52. var disc = new BABYLON.Mesh(name, scene);
  53. var vertexData = BABYLON.VertexData.CreateDisc(options);
  54. vertexData.applyToMesh(disc, options.updatable);
  55. return disc;
  56. };
  57. /**
  58. * Creates a sphere based upon an icosahedron with 20 triangular faces which can be subdivided.
  59. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#icosphere
  60. * The parameter `radius` sets the radius size (float) of the icosphere (default 1).
  61. * You can set some different icosphere dimensions, for instance to build an ellipsoid, by using the parameters `radiusX`, `radiusY` and `radiusZ` (all by default have the same value than `radius`).
  62. * The parameter `subdivisions` sets the number of subdivisions (postive integer, default 4). The more subdivisions, the more faces on the icosphere whatever its size.
  63. * The parameter `flat` (boolean, default true) gives each side its own normals. Set it to false to get a smooth continuous light reflection on the surface.
  64. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  65. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  66. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  67. */
  68. MeshBuilder.CreateIcoSphere = function (name, options, scene) {
  69. var sphere = new BABYLON.Mesh(name, scene);
  70. var vertexData = BABYLON.VertexData.CreateIcoSphere(options);
  71. vertexData.applyToMesh(sphere, options.updatable);
  72. return sphere;
  73. };
  74. ;
  75. /**
  76. * Creates a ribbon mesh.
  77. * The ribbon is a parametric shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes. It has no predefined shape. Its final shape will depend on the input parameters.
  78. *
  79. * Please read this full tutorial to understand how to design a ribbon : http://doc.babylonjs.com/tutorials/Ribbon_Tutorial
  80. * The parameter `pathArray` is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.
  81. * The parameter `closeArray` (boolean, default false) creates a seam between the first and the last paths of the path array.
  82. * The parameter `closePath` (boolean, default false) creates a seam between the first and the last points of each path of the path array.
  83. * The parameter `offset` (positive integer, default : rounded half size of the pathArray length), is taken in account only if the `pathArray` is containing a single path.
  84. * It's the offset to join the points from the same path. Ex : offset = 10 means the point 1 is joined to the point 11.
  85. * The optional parameter `instance` is an instance of an existing Ribbon object to be updated with the passed `pathArray` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#ribbon
  86. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  87. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  88. * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.
  89. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  90. */
  91. MeshBuilder.CreateRibbon = function (name, options, scene) {
  92. var pathArray = options.pathArray;
  93. var closeArray = options.closeArray;
  94. var closePath = options.closePath;
  95. var offset = options.offset;
  96. var sideOrientation = options.sideOrientation;
  97. var instance = options.instance;
  98. var updatable = options.updatable;
  99. if (instance) {
  100. // positionFunction : ribbon case
  101. // only pathArray and sideOrientation parameters are taken into account for positions update
  102. BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, BABYLON.Tmp.Vector3[0]); // minimum
  103. BABYLON.Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, BABYLON.Tmp.Vector3[1]);
  104. var positionFunction = function (positions) {
  105. var minlg = pathArray[0].length;
  106. var i = 0;
  107. var ns = (instance.sideOrientation === BABYLON.Mesh.DOUBLESIDE) ? 2 : 1;
  108. for (var si = 1; si <= ns; si++) {
  109. for (var p = 0; p < pathArray.length; p++) {
  110. var path = pathArray[p];
  111. var l = path.length;
  112. minlg = (minlg < l) ? minlg : l;
  113. var j = 0;
  114. while (j < minlg) {
  115. positions[i] = path[j].x;
  116. positions[i + 1] = path[j].y;
  117. positions[i + 2] = path[j].z;
  118. if (path[j].x < BABYLON.Tmp.Vector3[0].x) {
  119. BABYLON.Tmp.Vector3[0].x = path[j].x;
  120. }
  121. if (path[j].x > BABYLON.Tmp.Vector3[1].x) {
  122. BABYLON.Tmp.Vector3[1].x = path[j].x;
  123. }
  124. if (path[j].y < BABYLON.Tmp.Vector3[0].y) {
  125. BABYLON.Tmp.Vector3[0].y = path[j].y;
  126. }
  127. if (path[j].y > BABYLON.Tmp.Vector3[1].y) {
  128. BABYLON.Tmp.Vector3[1].y = path[j].y;
  129. }
  130. if (path[j].z < BABYLON.Tmp.Vector3[0].z) {
  131. BABYLON.Tmp.Vector3[0].z = path[j].z;
  132. }
  133. if (path[j].z > BABYLON.Tmp.Vector3[1].z) {
  134. BABYLON.Tmp.Vector3[1].z = path[j].z;
  135. }
  136. j++;
  137. i += 3;
  138. }
  139. if (instance._closePath) {
  140. positions[i] = path[0].x;
  141. positions[i + 1] = path[0].y;
  142. positions[i + 2] = path[0].z;
  143. i += 3;
  144. }
  145. }
  146. }
  147. };
  148. var positions = instance.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  149. positionFunction(positions);
  150. instance._boundingInfo = new BABYLON.BoundingInfo(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Vector3[1]);
  151. instance._boundingInfo.update(instance._worldMatrix);
  152. instance.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
  153. if (!(instance.areNormalsFrozen)) {
  154. var indices = instance.getIndices();
  155. var normals = instance.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  156. BABYLON.VertexData.ComputeNormals(positions, indices, normals);
  157. if (instance._closePath) {
  158. var indexFirst = 0;
  159. var indexLast = 0;
  160. for (var p = 0; p < pathArray.length; p++) {
  161. indexFirst = instance._idx[p] * 3;
  162. if (p + 1 < pathArray.length) {
  163. indexLast = (instance._idx[p + 1] - 1) * 3;
  164. }
  165. else {
  166. indexLast = normals.length - 3;
  167. }
  168. normals[indexFirst] = (normals[indexFirst] + normals[indexLast]) * 0.5;
  169. normals[indexFirst + 1] = (normals[indexFirst + 1] + normals[indexLast + 1]) * 0.5;
  170. normals[indexFirst + 2] = (normals[indexFirst + 2] + normals[indexLast + 2]) * 0.5;
  171. normals[indexLast] = normals[indexFirst];
  172. normals[indexLast + 1] = normals[indexFirst + 1];
  173. normals[indexLast + 2] = normals[indexFirst + 2];
  174. }
  175. }
  176. instance.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false, false);
  177. }
  178. return instance;
  179. }
  180. else {
  181. var ribbon = new BABYLON.Mesh(name, scene);
  182. ribbon.sideOrientation = sideOrientation;
  183. var vertexData = BABYLON.VertexData.CreateRibbon(options);
  184. if (closePath) {
  185. ribbon._idx = vertexData._idx;
  186. }
  187. ribbon._closePath = closePath;
  188. ribbon._closeArray = closeArray;
  189. vertexData.applyToMesh(ribbon, updatable);
  190. return ribbon;
  191. }
  192. };
  193. /**
  194. * Creates a cylinder or a cone mesh.
  195. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#cylinder-or-cone
  196. * The parameter `height` sets the height size (float) of the cylinder/cone (float, default 2).
  197. * The parameter `diameter` sets the diameter of the top and bottom cap at once (float, default 1).
  198. * The parameters `diameterTop` and `diameterBottom` overwrite the parameter `diameter` and set respectively the top cap and bottom cap diameter (floats, default 1). The parameter "diameterBottom" can't be zero.
  199. * The parameter `tessellation` sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance.
  200. * The parameter `subdivisions` sets the number of rings along the cylinder height (positive integer, default 1).
  201. * The parameter `hasRings` (boolean, default false) makes the subdivisions independent from each other, so they become different faces.
  202. * The parameter `enclose` (boolean, default false) adds two extra faces per subdivision to a sliced cylinder to close it around its height axis.
  203. * The parameter `arc` (float, default 1) is the ratio (max 1) to apply to the circumference to slice the cylinder.
  204. * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of n Color3 elements) and `faceUV` (an array of n Vector4 elements).
  205. * The value of n is the number of cylinder faces. If the cylinder has only 1 subdivisions, n equals : top face + cylinder surface + bottom face = 3
  206. * Now, if the cylinder has 5 independent subdivisions (hasRings = true), n equals : top face + 5 stripe surfaces + bottom face = 2 + 5 = 7
  207. * Finally, if the cylinder has 5 independent subdivisions and is enclose, n equals : top face + 5 x (stripe surface + 2 closing faces) + bottom face = 2 + 5 * 3 = 17
  208. * Each array (color or UVs) is always ordered the same way : the first element is the bottom cap, the last element is the top cap. The other elements are each a ring surface.
  209. * If `enclose` is false, a ring surface is one element.
  210. * If `enclose` is true, a ring surface is 3 successive elements in the array : the tubular surface, then the two closing faces.
  211. * Example how to set colors and textures on a sliced cylinder : http://www.html5gamedevs.com/topic/17945-creating-a-closed-slice-of-a-cylinder/#comment-106379
  212. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  213. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  214. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  215. */
  216. MeshBuilder.CreateCylinder = function (name, options, scene) {
  217. var cylinder = new BABYLON.Mesh(name, scene);
  218. var vertexData = BABYLON.VertexData.CreateCylinder(options);
  219. vertexData.applyToMesh(cylinder, options.updatable);
  220. return cylinder;
  221. };
  222. /**
  223. * Creates a torus mesh.
  224. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#torus
  225. * The parameter `diameter` sets the diameter size (float) of the torus (default 1).
  226. * The parameter `thickness` sets the diameter size of the tube of the torus (float, default 0.5).
  227. * The parameter `tessellation` sets the number of torus sides (postive integer, default 16).
  228. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  229. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  230. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  231. */
  232. MeshBuilder.CreateTorus = function (name, options, scene) {
  233. var torus = new BABYLON.Mesh(name, scene);
  234. var vertexData = BABYLON.VertexData.CreateTorus(options);
  235. vertexData.applyToMesh(torus, options.updatable);
  236. return torus;
  237. };
  238. /**
  239. * Creates a torus knot mesh.
  240. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#torus-knot
  241. * The parameter `radius` sets the global radius size (float) of the torus knot (default 2).
  242. * The parameter `radialSegments` sets the number of sides on each tube segments (positive integer, default 32).
  243. * The parameter `tubularSegments` sets the number of tubes to decompose the knot into (positive integer, default 32).
  244. * The parameters `p` and `q` are the number of windings on each axis (positive integers, default 2 and 3).
  245. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  246. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  247. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  248. */
  249. MeshBuilder.CreateTorusKnot = function (name, options, scene) {
  250. var torusKnot = new BABYLON.Mesh(name, scene);
  251. var vertexData = BABYLON.VertexData.CreateTorusKnot(options);
  252. vertexData.applyToMesh(torusKnot, options.updatable);
  253. return torusKnot;
  254. };
  255. /**
  256. * Creates a line system mesh.
  257. * A line system is a pool of many lines gathered in a single mesh.
  258. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#linesystem
  259. * A line system mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of lines as an input parameter.
  260. * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function.
  261. * The parameter `lines` is an array of lines, each line being an array of successive Vector3.
  262. * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter. The way to update it is the same than for
  263. * updating a simple Line mesh, you just need to update every line in the `lines` array : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
  264. * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines.
  265. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  266. */
  267. MeshBuilder.CreateLineSystem = function (name, options, scene) {
  268. var instance = options.instance;
  269. var lines = options.lines;
  270. if (instance) {
  271. var positionFunction = function (positions) {
  272. var i = 0;
  273. for (var l = 0; l < lines.length; l++) {
  274. var points = lines[l];
  275. for (var p = 0; p < points.length; p++) {
  276. positions[i] = points[p].x;
  277. positions[i + 1] = points[p].y;
  278. positions[i + 2] = points[p].z;
  279. i += 3;
  280. }
  281. }
  282. };
  283. instance.updateMeshPositions(positionFunction, false);
  284. return instance;
  285. }
  286. // line system creation
  287. var lineSystem = new BABYLON.LinesMesh(name, scene);
  288. var vertexData = BABYLON.VertexData.CreateLineSystem(options);
  289. vertexData.applyToMesh(lineSystem, options.updatable);
  290. return lineSystem;
  291. };
  292. /**
  293. * Creates a line mesh.
  294. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#lines
  295. * A line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.
  296. * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
  297. * The parameter `points` is an array successive Vector3.
  298. * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
  299. * When updating an instance, remember that only point positions can change, not the number of points.
  300. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  301. */
  302. MeshBuilder.CreateLines = function (name, options, scene) {
  303. var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance }, scene);
  304. return lines;
  305. };
  306. /**
  307. * Creates a dashed line mesh.
  308. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#dashed-lines
  309. * A dashed line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.
  310. * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
  311. * The parameter `points` is an array successive Vector3.
  312. * The parameter `dashNb` is the intended total number of dashes (positive integer, default 200).
  313. * The parameter `dashSize` is the size of the dashes relatively the dash number (positive float, default 3).
  314. * The parameter `gapSize` is the size of the gap between two successive dashes relatively the dash number (positive float, default 1).
  315. * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
  316. * When updating an instance, remember that only point positions can change, not the number of points.
  317. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  318. */
  319. MeshBuilder.CreateDashedLines = function (name, options, scene) {
  320. var points = options.points;
  321. var instance = options.instance;
  322. var gapSize = options.gapSize;
  323. var dashNb = options.dashNb;
  324. var dashSize = options.dashSize;
  325. if (instance) {
  326. var positionFunction = function (positions) {
  327. var curvect = BABYLON.Vector3.Zero();
  328. var nbSeg = positions.length / 6;
  329. var lg = 0;
  330. var nb = 0;
  331. var shft = 0;
  332. var dashshft = 0;
  333. var curshft = 0;
  334. var p = 0;
  335. var i = 0;
  336. var j = 0;
  337. for (i = 0; i < points.length - 1; i++) {
  338. points[i + 1].subtractToRef(points[i], curvect);
  339. lg += curvect.length();
  340. }
  341. shft = lg / nbSeg;
  342. dashshft = instance.dashSize * shft / (instance.dashSize + instance.gapSize);
  343. for (i = 0; i < points.length - 1; i++) {
  344. points[i + 1].subtractToRef(points[i], curvect);
  345. nb = Math.floor(curvect.length() / shft);
  346. curvect.normalize();
  347. j = 0;
  348. while (j < nb && p < positions.length) {
  349. curshft = shft * j;
  350. positions[p] = points[i].x + curshft * curvect.x;
  351. positions[p + 1] = points[i].y + curshft * curvect.y;
  352. positions[p + 2] = points[i].z + curshft * curvect.z;
  353. positions[p + 3] = points[i].x + (curshft + dashshft) * curvect.x;
  354. positions[p + 4] = points[i].y + (curshft + dashshft) * curvect.y;
  355. positions[p + 5] = points[i].z + (curshft + dashshft) * curvect.z;
  356. p += 6;
  357. j++;
  358. }
  359. }
  360. while (p < positions.length) {
  361. positions[p] = points[i].x;
  362. positions[p + 1] = points[i].y;
  363. positions[p + 2] = points[i].z;
  364. p += 3;
  365. }
  366. };
  367. instance.updateMeshPositions(positionFunction, false);
  368. return instance;
  369. }
  370. // dashed lines creation
  371. var dashedLines = new BABYLON.LinesMesh(name, scene);
  372. var vertexData = BABYLON.VertexData.CreateDashedLines(options);
  373. vertexData.applyToMesh(dashedLines, options.updatable);
  374. dashedLines.dashSize = dashSize;
  375. dashedLines.gapSize = gapSize;
  376. return dashedLines;
  377. };
  378. /**
  379. * Creates an extruded shape mesh.
  380. * The extrusion is a parametric shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes. It has no predefined shape. Its final shape will depend on the input parameters.
  381. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#extruded-shapes
  382. *
  383. * Please read this full tutorial to understand how to design an extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion
  384. * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
  385. * extruded along the Z axis.
  386. * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.
  387. * The parameter `rotation` (float, default 0 radians) is the angle value to rotate the shape each step (each path point), from the former step (so rotation added each step) along the curve.
  388. * The parameter `scale` (float, default 1) is the value to scale the shape.
  389. * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
  390. * The optional parameter `instance` is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#extruded-shape
  391. * Remember you can only change the shape or path point positions, not their number when updating an extruded shape.
  392. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  393. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  394. * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.
  395. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  396. */
  397. MeshBuilder.ExtrudeShape = function (name, options, scene) {
  398. var path = options.path;
  399. var shape = options.shape;
  400. var scale = options.scale || 1;
  401. var rotation = options.rotation || 0;
  402. var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
  403. var updatable = options.updatable;
  404. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  405. var instance = options.instance;
  406. var invertUV = options.invertUV || false;
  407. return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable, sideOrientation, instance, invertUV);
  408. };
  409. /**
  410. * Creates an custom extruded shape mesh.
  411. * The custom extrusion is a parametric shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes. It has no predefined shape. Its final shape will depend on the input parameters.
  412. * tuto :http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#custom-extruded-shapes
  413. *
  414. * Please read this full tutorial to understand how to design a custom extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion
  415. * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
  416. * extruded along the Z axis.
  417. * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.
  418. * The parameter `rotationFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
  419. * and the distance of this point from the begining of the path :
  420. * ```javascript
  421. * var rotationFunction = function(i, distance) {
  422. * // do things
  423. * return rotationValue; }
  424. * ```
  425. * It must returns a float value that will be the rotation in radians applied to the shape on each path point.
  426. * The parameter `scaleFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
  427. * and the distance of this point from the begining of the path :
  428. * ```javascript
  429. * var scaleFunction = function(i, distance) {
  430. * // do things
  431. * return scaleValue;}
  432. * ```
  433. * It must returns a float value that will be the scale value applied to the shape on each path point.
  434. * The parameter `ribbonClosePath` (boolean, default false) forces the extrusion underlying ribbon to close all the paths in its `pathArray`.
  435. * The parameter `ribbonCloseArray` (boolean, default false) forces the extrusion underlying ribbon to close its `pathArray`.
  436. * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
  437. * The optional parameter `instance` is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#extruded-shape
  438. * Remember you can only change the shape or path point positions, not their number when updating an extruded shape.
  439. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  440. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  441. * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.
  442. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  443. */
  444. MeshBuilder.ExtrudeShapeCustom = function (name, options, scene) {
  445. var path = options.path;
  446. var shape = options.shape;
  447. var scaleFunction = options.scaleFunction || (function () { return 1; });
  448. var rotationFunction = options.rotationFunction || (function () { return 0; });
  449. var ribbonCloseArray = options.ribbonCloseArray || false;
  450. var ribbonClosePath = options.ribbonClosePath || false;
  451. var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
  452. var updatable = options.updatable;
  453. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  454. var instance = options.instance;
  455. var invertUV = options.invertUV || false;
  456. return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable, sideOrientation, instance, invertUV);
  457. };
  458. /**
  459. * Creates lathe mesh.
  460. * The lathe is a shape with a symetry axis : a 2D model shape is rotated around this axis to design the lathe.
  461. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#lathe
  462. *
  463. * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be rotated in its local space : the shape must be designed in the xOy plane and will be
  464. * rotated around the Y axis. It's usually a 2D shape, so the Vector3 z coordinates are often set to zero.
  465. * The parameter `radius` (positive float, default 1) is the radius value of the lathe.
  466. * The parameter `tessellation` (positive integer, default 64) is the side number of the lathe.
  467. * The parameter `arc` (positive float, default 1) is the ratio of the lathe. 0.5 builds for instance half a lathe, so an opened shape.
  468. * The parameter `closed` (boolean, default true) opens/closes the lathe circumference. This should be set to false when used with the parameter "arc".
  469. * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
  470. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  471. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  472. * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.
  473. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  474. */
  475. MeshBuilder.CreateLathe = function (name, options, scene) {
  476. var arc = (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
  477. var closed = (options.closed === undefined) ? true : options.closed;
  478. var shape = options.shape;
  479. var radius = options.radius || 1;
  480. var tessellation = options.tessellation || 64;
  481. var updatable = options.updatable;
  482. var sideOrientation = (options.sideOrientation === 0) ? 0 : options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  483. var cap = options.cap || BABYLON.Mesh.NO_CAP;
  484. var pi2 = Math.PI * 2;
  485. var paths = new Array();
  486. var invertUV = options.invertUV || false;
  487. var i = 0;
  488. var p = 0;
  489. var step = pi2 / tessellation * arc;
  490. var rotated;
  491. var path = new Array();
  492. ;
  493. for (i = 0; i <= tessellation; i++) {
  494. var path = [];
  495. if (cap == BABYLON.Mesh.CAP_START || cap == BABYLON.Mesh.CAP_ALL) {
  496. path.push(new BABYLON.Vector3(0, shape[0].y, 0));
  497. path.push(new BABYLON.Vector3(Math.cos(i * step) * shape[0].x * radius, shape[0].y, Math.sin(i * step) * shape[0].x * radius));
  498. }
  499. for (p = 0; p < shape.length; p++) {
  500. rotated = new BABYLON.Vector3(Math.cos(i * step) * shape[p].x * radius, shape[p].y, Math.sin(i * step) * shape[p].x * radius);
  501. path.push(rotated);
  502. }
  503. if (cap == BABYLON.Mesh.CAP_END || cap == BABYLON.Mesh.CAP_ALL) {
  504. path.push(new BABYLON.Vector3(Math.cos(i * step) * shape[shape.length - 1].x * radius, shape[shape.length - 1].y, Math.sin(i * step) * shape[shape.length - 1].x * radius));
  505. path.push(new BABYLON.Vector3(0, shape[shape.length - 1].y, 0));
  506. }
  507. paths.push(path);
  508. }
  509. // lathe ribbon
  510. var lathe = MeshBuilder.CreateRibbon(name, { pathArray: paths, closeArray: closed, sideOrientation: sideOrientation, updatable: updatable, invertUV: invertUV }, scene);
  511. return lathe;
  512. };
  513. /**
  514. * Creates a plane mesh.
  515. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane
  516. * The parameter `size` sets the size (float) of both sides of the plane at once (default 1).
  517. * You can set some different plane dimensions by using the parameters `width` and `height` (both by default have the same value than `size`).
  518. * The parameter `sourcePlane` is a Plane instance. It builds a mesh plane from a Math plane.
  519. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  520. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  521. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  522. */
  523. MeshBuilder.CreatePlane = function (name, options, scene) {
  524. var plane = new BABYLON.Mesh(name, scene);
  525. var vertexData = BABYLON.VertexData.CreatePlane(options);
  526. vertexData.applyToMesh(plane, options.updatable);
  527. if (options.sourcePlane) {
  528. plane.translate(options.sourcePlane.normal, options.sourcePlane.d);
  529. var product = Math.acos(BABYLON.Vector3.Dot(options.sourcePlane.normal, BABYLON.Axis.Z));
  530. var vectorProduct = BABYLON.Vector3.Cross(BABYLON.Axis.Z, options.sourcePlane.normal);
  531. plane.rotate(vectorProduct, product);
  532. }
  533. return plane;
  534. };
  535. /**
  536. * Creates a ground mesh.
  537. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane
  538. * The parameters `width` and `height` (floats, default 1) set the width and height sizes of the ground.
  539. * The parameter `subdivisions` (positive integer) sets the number of subdivisions per side.
  540. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  541. */
  542. MeshBuilder.CreateGround = function (name, options, scene) {
  543. var ground = new BABYLON.GroundMesh(name, scene);
  544. ground._setReady(false);
  545. ground._subdivisionsX = options.subdivisionsX || options.subdivisions || 1;
  546. ground._subdivisionsY = options.subdivisionsY || options.subdivisions || 1;
  547. ground._width = options.width || 1;
  548. ground._height = options.height || 1;
  549. ground._maxX = ground._width / 2;
  550. ground._maxZ = ground._height / 2;
  551. ground._minX = -ground._maxX;
  552. ground._minZ = -ground._maxZ;
  553. var vertexData = BABYLON.VertexData.CreateGround(options);
  554. vertexData.applyToMesh(ground, options.updatable);
  555. ground._setReady(true);
  556. return ground;
  557. };
  558. /**
  559. * Creates a tiled ground mesh.
  560. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#tiled-ground
  561. * The parameters `xmin` and `xmax` (floats, default -1 and 1) set the ground minimum and maximum X coordinates.
  562. * The parameters `zmin` and `zmax` (floats, default -1 and 1) set the ground minimum and maximum Z coordinates.
  563. * The parameter `subdivisions` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 6, h: 6}`). `w` and `h` are the
  564. * numbers of subdivisions on the ground width and height. Each subdivision is called a tile.
  565. * The parameter `precision` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 2, h: 2}`). `w` and `h` are the
  566. * numbers of subdivisions on the ground width and height of each tile.
  567. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  568. */
  569. MeshBuilder.CreateTiledGround = function (name, options, scene) {
  570. var tiledGround = new BABYLON.Mesh(name, scene);
  571. var vertexData = BABYLON.VertexData.CreateTiledGround(options);
  572. vertexData.applyToMesh(tiledGround, options.updatable);
  573. return tiledGround;
  574. };
  575. /**
  576. * Creates a ground mesh from a height map.
  577. * tuto : http://doc.babylonjs.com/tutorials/14._Height_Map
  578. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#ground-from-a-height-map
  579. * The parameter `url` sets the URL of the height map image resource.
  580. * The parameters `width` and `height` (positive floats, default 10) set the ground width and height sizes.
  581. * The parameter `subdivisions` (positive integer, default 1) sets the number of subdivision per side.
  582. * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.
  583. * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.
  584. * The parameter `onReady` is a javascript callback function that will be called once the mesh is just built (the height map download can last some time).
  585. * This function is passed the newly built mesh :
  586. * ```javascript
  587. * function(mesh) { // do things
  588. * return; }
  589. * ```
  590. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  591. */
  592. MeshBuilder.CreateGroundFromHeightMap = function (name, url, options, scene) {
  593. var width = options.width || 10.0;
  594. var height = options.height || 10.0;
  595. var subdivisions = options.subdivisions || 1 | 0;
  596. var minHeight = options.minHeight || 0.0;
  597. var maxHeight = options.maxHeight || 10.0;
  598. var updatable = options.updatable;
  599. var onReady = options.onReady;
  600. var ground = new BABYLON.GroundMesh(name, scene);
  601. ground._subdivisionsX = subdivisions;
  602. ground._subdivisionsY = subdivisions;
  603. ground._width = width;
  604. ground._height = height;
  605. ground._maxX = ground._width / 2.0;
  606. ground._maxZ = ground._height / 2.0;
  607. ground._minX = -ground._maxX;
  608. ground._minZ = -ground._maxZ;
  609. ground._setReady(false);
  610. var onload = function (img) {
  611. // Getting height map data
  612. var canvas = document.createElement("canvas");
  613. var context = canvas.getContext("2d");
  614. var bufferWidth = img.width;
  615. var bufferHeight = img.height;
  616. canvas.width = bufferWidth;
  617. canvas.height = bufferHeight;
  618. context.drawImage(img, 0, 0);
  619. // Create VertexData from map data
  620. // Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
  621. var buffer = context.getImageData(0, 0, bufferWidth, bufferHeight).data;
  622. var vertexData = BABYLON.VertexData.CreateGroundFromHeightMap({
  623. width: width, height: height,
  624. subdivisions: subdivisions,
  625. minHeight: minHeight, maxHeight: maxHeight,
  626. buffer: buffer, bufferWidth: bufferWidth, bufferHeight: bufferHeight
  627. });
  628. vertexData.applyToMesh(ground, updatable);
  629. ground._setReady(true);
  630. //execute ready callback, if set
  631. if (onReady) {
  632. onReady(ground);
  633. }
  634. };
  635. BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
  636. return ground;
  637. };
  638. /**
  639. * Creates a tube mesh.
  640. * The tube is a parametric shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes. It has no predefined shape. Its final shape will depend on the input parameters.
  641. *
  642. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#tube
  643. * The parameter `path` is a required array of successive Vector3. It is the curve used as the axis of the tube.
  644. * The parameter `radius` (positive float, default 1) sets the tube radius size.
  645. * The parameter `tessellation` (positive float, default 64) is the number of sides on the tubular surface.
  646. * The parameter `radiusFunction` (javascript function, default null) is a vanilla javascript function. If it is not null, it overwrittes the parameter `radius`.
  647. * This function is called on each point of the tube path and is passed the index `i` of the i-th point and the distance of this point from the first point of the path.
  648. * It must return a radius value (positive float) :
  649. * ```javascript
  650. * var radiusFunction = function(i, distance) {
  651. * // do things
  652. * return radius; }
  653. * ```
  654. * The parameter `arc` (positive float, maximum 1, default 1) is the ratio to apply to the tube circumference : 2 x PI x arc.
  655. * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
  656. * The optional parameter `instance` is an instance of an existing Tube object to be updated with the passed `pathArray` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#tube
  657. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  658. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  659. * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.
  660. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  661. */
  662. MeshBuilder.CreateTube = function (name, options, scene) {
  663. var path = options.path;
  664. var radius = options.radius || 1.0;
  665. var tessellation = options.tessellation || 64 | 0;
  666. var radiusFunction = options.radiusFunction;
  667. var cap = options.cap || BABYLON.Mesh.NO_CAP;
  668. var invertUV = options.invertUV || false;
  669. var updatable = options.updatable;
  670. var sideOrientation = options.sideOrientation || BABYLON.Mesh.DEFAULTSIDE;
  671. var instance = options.instance;
  672. options.arc = (options.arc <= 0.0 || options.arc > 1.0) ? 1.0 : options.arc || 1.0;
  673. // tube geometry
  674. var tubePathArray = function (path, path3D, circlePaths, radius, tessellation, radiusFunction, cap, arc) {
  675. var tangents = path3D.getTangents();
  676. var normals = path3D.getNormals();
  677. var distances = path3D.getDistances();
  678. var pi2 = Math.PI * 2;
  679. var step = pi2 / tessellation * arc;
  680. var returnRadius = function () { return radius; };
  681. var radiusFunctionFinal = radiusFunction || returnRadius;
  682. var circlePath;
  683. var rad;
  684. var normal;
  685. var rotated;
  686. var rotationMatrix = BABYLON.Tmp.Matrix[0];
  687. var index = (cap === BABYLON.Mesh._NO_CAP || cap === BABYLON.Mesh.CAP_END) ? 0 : 2;
  688. for (var i = 0; i < path.length; i++) {
  689. rad = radiusFunctionFinal(i, distances[i]); // current radius
  690. circlePath = Array(); // current circle array
  691. normal = normals[i]; // current normal
  692. for (var t = 0; t < tessellation; t++) {
  693. BABYLON.Matrix.RotationAxisToRef(tangents[i], step * t, rotationMatrix);
  694. rotated = circlePath[t] ? circlePath[t] : BABYLON.Vector3.Zero();
  695. BABYLON.Vector3.TransformCoordinatesToRef(normal, rotationMatrix, rotated);
  696. rotated.scaleInPlace(rad).addInPlace(path[i]);
  697. circlePath[t] = rotated;
  698. }
  699. circlePaths[index] = circlePath;
  700. index++;
  701. }
  702. // cap
  703. var capPath = function (nbPoints, pathIndex) {
  704. var pointCap = Array();
  705. for (var i = 0; i < nbPoints; i++) {
  706. pointCap.push(path[pathIndex]);
  707. }
  708. return pointCap;
  709. };
  710. switch (cap) {
  711. case BABYLON.Mesh.NO_CAP:
  712. break;
  713. case BABYLON.Mesh.CAP_START:
  714. circlePaths[0] = capPath(tessellation, 0);
  715. circlePaths[1] = circlePaths[2].slice(0);
  716. break;
  717. case BABYLON.Mesh.CAP_END:
  718. circlePaths[index] = circlePaths[index - 1].slice(0);
  719. circlePaths[index + 1] = capPath(tessellation, path.length - 1);
  720. break;
  721. case BABYLON.Mesh.CAP_ALL:
  722. circlePaths[0] = capPath(tessellation, 0);
  723. circlePaths[1] = circlePaths[2].slice(0);
  724. circlePaths[index] = circlePaths[index - 1].slice(0);
  725. circlePaths[index + 1] = capPath(tessellation, path.length - 1);
  726. break;
  727. default:
  728. break;
  729. }
  730. return circlePaths;
  731. };
  732. var path3D;
  733. var pathArray;
  734. if (instance) {
  735. var arc = options.arc || instance.arc;
  736. path3D = (instance.path3D).update(path);
  737. pathArray = tubePathArray(path, path3D, instance.pathArray, radius, instance.tessellation, radiusFunction, instance.cap, arc);
  738. instance = MeshBuilder.CreateRibbon(null, { pathArray: pathArray, instance: instance });
  739. instance.path3D = path3D;
  740. instance.pathArray = pathArray;
  741. instance.arc = arc;
  742. return instance;
  743. }
  744. // tube creation
  745. path3D = new BABYLON.Path3D(path);
  746. var newPathArray = new Array();
  747. cap = (cap < 0 || cap > 3) ? 0 : cap;
  748. pathArray = tubePathArray(path, path3D, newPathArray, radius, tessellation, radiusFunction, cap, options.arc);
  749. var tube = MeshBuilder.CreateRibbon(name, { pathArray: pathArray, closePath: true, closeArray: false, updatable: updatable, sideOrientation: sideOrientation, invertUV: invertUV }, scene);
  750. tube.pathArray = pathArray;
  751. tube.path3D = path3D;
  752. tube.tessellation = tessellation;
  753. tube.cap = cap;
  754. tube.arc = options.arc;
  755. return tube;
  756. };
  757. /**
  758. * Creates a polyhedron mesh.
  759. *
  760. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#polyhedron
  761. * The parameter `type` (positive integer, max 14, default 0) sets the polyhedron type to build among the 15 embbeded types. Please refer to the type sheet in the tutorial
  762. * to choose the wanted type.
  763. * The parameter `size` (positive float, default 1) sets the polygon size.
  764. * You can overwrite the `size` on each dimension bu using the parameters `sizeX`, `sizeY` or `sizeZ` (positive floats, default to `size` value).
  765. * You can build other polyhedron types than the 15 embbeded ones by setting the parameter `custom` (`polyhedronObject`, default null). If you set the parameter `custom`, this overwrittes the parameter `type`.
  766. * A `polyhedronObject` is a formatted javascript object. You'll find a full file with pre-set polyhedra here : https://github.com/BabylonJS/Extensions/tree/master/Polyhedron
  767. * You can set the color and the UV of each side of the polyhedron with the parameters `faceColors` (Color4, default `(1, 1, 1, 1)`) and faceUV (Vector4, default `(0, 0, 1, 1)`).
  768. * To understand how to set `faceUV` or `faceColors`, please read this by considering the right number of faces of your polyhedron, instead of only 6 for the box : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors
  769. * The parameter `flat` (boolean, default true). If set to false, it gives the polyhedron a single global face, so less vertices and shared normals. In this case, `faceColors` and `faceUV` are ignored.
  770. * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
  771. * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
  772. * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
  773. */
  774. MeshBuilder.CreatePolyhedron = function (name, options, scene) {
  775. var polyhedron = new BABYLON.Mesh(name, scene);
  776. var vertexData = BABYLON.VertexData.CreatePolyhedron(options);
  777. vertexData.applyToMesh(polyhedron, options.updatable);
  778. return polyhedron;
  779. };
  780. /**
  781. * Creates a decal mesh.
  782. * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#decals
  783. * A decal is a mesh usually applied as a model onto the surface of another mesh. So don't forget the parameter `sourceMesh` depicting the decal.
  784. * The parameter `position` (Vector3, default `(0, 0, 0)`) sets the position of the decal in World coordinates.
  785. * The parameter `normal` (Vector3, default `Vector3.Up`) sets the normal of the mesh where the decal is applied onto in World coordinates.
  786. * The parameter `size` (Vector3, default `(1, 1, 1)`) sets the decal scaling.
  787. * The parameter `angle` (float in radian, default 0) sets the angle to rotate the decal.
  788. */
  789. MeshBuilder.CreateDecal = function (name, sourceMesh, options) {
  790. var indices = sourceMesh.getIndices();
  791. var positions = sourceMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  792. var normals = sourceMesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
  793. var position = options.position || BABYLON.Vector3.Zero();
  794. var normal = options.normal || BABYLON.Vector3.Up();
  795. var size = options.size || new BABYLON.Vector3(1, 1, 1);
  796. var angle = options.angle || 0;
  797. // Getting correct rotation
  798. if (!normal) {
  799. var target = new BABYLON.Vector3(0, 0, 1);
  800. var camera = sourceMesh.getScene().activeCamera;
  801. var cameraWorldTarget = BABYLON.Vector3.TransformCoordinates(target, camera.getWorldMatrix());
  802. normal = camera.globalPosition.subtract(cameraWorldTarget);
  803. }
  804. var yaw = -Math.atan2(normal.z, normal.x) - Math.PI / 2;
  805. var len = Math.sqrt(normal.x * normal.x + normal.z * normal.z);
  806. var pitch = Math.atan2(normal.y, len);
  807. // Matrix
  808. var decalWorldMatrix = BABYLON.Matrix.RotationYawPitchRoll(yaw, pitch, angle).multiply(BABYLON.Matrix.Translation(position.x, position.y, position.z));
  809. var inverseDecalWorldMatrix = BABYLON.Matrix.Invert(decalWorldMatrix);
  810. var meshWorldMatrix = sourceMesh.getWorldMatrix();
  811. var transformMatrix = meshWorldMatrix.multiply(inverseDecalWorldMatrix);
  812. var vertexData = new BABYLON.VertexData();
  813. vertexData.indices = [];
  814. vertexData.positions = [];
  815. vertexData.normals = [];
  816. vertexData.uvs = [];
  817. var currentVertexDataIndex = 0;
  818. var extractDecalVector3 = function (indexId) {
  819. var vertexId = indices[indexId];
  820. var result = new BABYLON.PositionNormalVertex();
  821. result.position = new BABYLON.Vector3(positions[vertexId * 3], positions[vertexId * 3 + 1], positions[vertexId * 3 + 2]);
  822. // Send vector to decal local world
  823. result.position = BABYLON.Vector3.TransformCoordinates(result.position, transformMatrix);
  824. // Get normal
  825. result.normal = new BABYLON.Vector3(normals[vertexId * 3], normals[vertexId * 3 + 1], normals[vertexId * 3 + 2]);
  826. return result;
  827. }; // Inspired by https://github.com/mrdoob/three.js/blob/eee231960882f6f3b6113405f524956145148146/examples/js/geometries/DecalGeometry.js
  828. var clip = function (vertices, axis) {
  829. if (vertices.length === 0) {
  830. return vertices;
  831. }
  832. var clipSize = 0.5 * Math.abs(BABYLON.Vector3.Dot(size, axis));
  833. var clipVertices = function (v0, v1) {
  834. var clipFactor = BABYLON.Vector3.GetClipFactor(v0.position, v1.position, axis, clipSize);
  835. return new BABYLON.PositionNormalVertex(BABYLON.Vector3.Lerp(v0.position, v1.position, clipFactor), BABYLON.Vector3.Lerp(v0.normal, v1.normal, clipFactor));
  836. };
  837. var result = new Array();
  838. for (var index = 0; index < vertices.length; index += 3) {
  839. var v1Out;
  840. var v2Out;
  841. var v3Out;
  842. var total = 0;
  843. var nV1, nV2, nV3, nV4;
  844. var d1 = BABYLON.Vector3.Dot(vertices[index].position, axis) - clipSize;
  845. var d2 = BABYLON.Vector3.Dot(vertices[index + 1].position, axis) - clipSize;
  846. var d3 = BABYLON.Vector3.Dot(vertices[index + 2].position, axis) - clipSize;
  847. v1Out = d1 > 0;
  848. v2Out = d2 > 0;
  849. v3Out = d3 > 0;
  850. total = (v1Out ? 1 : 0) + (v2Out ? 1 : 0) + (v3Out ? 1 : 0);
  851. switch (total) {
  852. case 0:
  853. result.push(vertices[index]);
  854. result.push(vertices[index + 1]);
  855. result.push(vertices[index + 2]);
  856. break;
  857. case 1:
  858. if (v1Out) {
  859. nV1 = vertices[index + 1];
  860. nV2 = vertices[index + 2];
  861. nV3 = clipVertices(vertices[index], nV1);
  862. nV4 = clipVertices(vertices[index], nV2);
  863. }
  864. if (v2Out) {
  865. nV1 = vertices[index];
  866. nV2 = vertices[index + 2];
  867. nV3 = clipVertices(vertices[index + 1], nV1);
  868. nV4 = clipVertices(vertices[index + 1], nV2);
  869. result.push(nV3);
  870. result.push(nV2.clone());
  871. result.push(nV1.clone());
  872. result.push(nV2.clone());
  873. result.push(nV3.clone());
  874. result.push(nV4);
  875. break;
  876. }
  877. if (v3Out) {
  878. nV1 = vertices[index];
  879. nV2 = vertices[index + 1];
  880. nV3 = clipVertices(vertices[index + 2], nV1);
  881. nV4 = clipVertices(vertices[index + 2], nV2);
  882. }
  883. result.push(nV1.clone());
  884. result.push(nV2.clone());
  885. result.push(nV3);
  886. result.push(nV4);
  887. result.push(nV3.clone());
  888. result.push(nV2.clone());
  889. break;
  890. case 2:
  891. if (!v1Out) {
  892. nV1 = vertices[index].clone();
  893. nV2 = clipVertices(nV1, vertices[index + 1]);
  894. nV3 = clipVertices(nV1, vertices[index + 2]);
  895. result.push(nV1);
  896. result.push(nV2);
  897. result.push(nV3);
  898. }
  899. if (!v2Out) {
  900. nV1 = vertices[index + 1].clone();
  901. nV2 = clipVertices(nV1, vertices[index + 2]);
  902. nV3 = clipVertices(nV1, vertices[index]);
  903. result.push(nV1);
  904. result.push(nV2);
  905. result.push(nV3);
  906. }
  907. if (!v3Out) {
  908. nV1 = vertices[index + 2].clone();
  909. nV2 = clipVertices(nV1, vertices[index]);
  910. nV3 = clipVertices(nV1, vertices[index + 1]);
  911. result.push(nV1);
  912. result.push(nV2);
  913. result.push(nV3);
  914. }
  915. break;
  916. case 3:
  917. break;
  918. }
  919. }
  920. return result;
  921. };
  922. for (var index = 0; index < indices.length; index += 3) {
  923. var faceVertices = new Array();
  924. faceVertices.push(extractDecalVector3(index));
  925. faceVertices.push(extractDecalVector3(index + 1));
  926. faceVertices.push(extractDecalVector3(index + 2));
  927. // Clip
  928. faceVertices = clip(faceVertices, new BABYLON.Vector3(1, 0, 0));
  929. faceVertices = clip(faceVertices, new BABYLON.Vector3(-1, 0, 0));
  930. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, 1, 0));
  931. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, -1, 0));
  932. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, 0, 1));
  933. faceVertices = clip(faceVertices, new BABYLON.Vector3(0, 0, -1));
  934. if (faceVertices.length === 0) {
  935. continue;
  936. }
  937. // Add UVs and get back to world
  938. for (var vIndex = 0; vIndex < faceVertices.length; vIndex++) {
  939. var vertex = faceVertices[vIndex];
  940. //TODO check for Int32Array
  941. vertexData.indices.push(currentVertexDataIndex);
  942. vertex.position.toArray(vertexData.positions, currentVertexDataIndex * 3);
  943. vertex.normal.toArray(vertexData.normals, currentVertexDataIndex * 3);
  944. vertexData.uvs.push(0.5 + vertex.position.x / size.x);
  945. vertexData.uvs.push(0.5 + vertex.position.y / size.y);
  946. currentVertexDataIndex++;
  947. }
  948. }
  949. // Return mesh
  950. var decal = new BABYLON.Mesh(name, sourceMesh.getScene());
  951. vertexData.applyToMesh(decal);
  952. decal.position = position.clone();
  953. decal.rotation = new BABYLON.Vector3(pitch, yaw, angle);
  954. return decal;
  955. };
  956. // Privates
  957. MeshBuilder._ExtrudeShapeGeneric = function (name, shape, curve, scale, rotation, scaleFunction, rotateFunction, rbCA, rbCP, cap, custom, scene, updtbl, side, instance, invertUV) {
  958. // extrusion geometry
  959. var extrusionPathArray = function (shape, curve, path3D, shapePaths, scale, rotation, scaleFunction, rotateFunction, cap, custom) {
  960. var tangents = path3D.getTangents();
  961. var normals = path3D.getNormals();
  962. var binormals = path3D.getBinormals();
  963. var distances = path3D.getDistances();
  964. var angle = 0;
  965. var returnScale = function () { return scale; };
  966. var returnRotation = function () { return rotation; };
  967. var rotate = custom ? rotateFunction : returnRotation;
  968. var scl = custom ? scaleFunction : returnScale;
  969. var index = (cap === BABYLON.Mesh.NO_CAP || cap === BABYLON.Mesh.CAP_END) ? 0 : 2;
  970. var rotationMatrix = BABYLON.Tmp.Matrix[0];
  971. for (var i = 0; i < curve.length; i++) {
  972. var shapePath = new Array();
  973. var angleStep = rotate(i, distances[i]);
  974. var scaleRatio = scl(i, distances[i]);
  975. for (var p = 0; p < shape.length; p++) {
  976. BABYLON.Matrix.RotationAxisToRef(tangents[i], angle, rotationMatrix);
  977. var planed = ((tangents[i].scale(shape[p].z)).add(normals[i].scale(shape[p].x)).add(binormals[i].scale(shape[p].y)));
  978. var rotated = shapePath[p] ? shapePath[p] : BABYLON.Vector3.Zero();
  979. BABYLON.Vector3.TransformCoordinatesToRef(planed, rotationMatrix, rotated);
  980. rotated.scaleInPlace(scaleRatio).addInPlace(curve[i]);
  981. shapePath[p] = rotated;
  982. }
  983. shapePaths[index] = shapePath;
  984. angle += angleStep;
  985. index++;
  986. }
  987. // cap
  988. var capPath = function (shapePath) {
  989. var pointCap = Array();
  990. var barycenter = BABYLON.Vector3.Zero();
  991. var i;
  992. for (i = 0; i < shapePath.length; i++) {
  993. barycenter.addInPlace(shapePath[i]);
  994. }
  995. barycenter.scaleInPlace(1 / shapePath.length);
  996. for (i = 0; i < shapePath.length; i++) {
  997. pointCap.push(barycenter);
  998. }
  999. return pointCap;
  1000. };
  1001. switch (cap) {
  1002. case BABYLON.Mesh.NO_CAP:
  1003. break;
  1004. case BABYLON.Mesh.CAP_START:
  1005. shapePaths[0] = capPath(shapePaths[2]);
  1006. shapePaths[1] = shapePaths[2].slice(0);
  1007. break;
  1008. case BABYLON.Mesh.CAP_END:
  1009. shapePaths[index] = shapePaths[index - 1];
  1010. shapePaths[index + 1] = capPath(shapePaths[index - 1]);
  1011. break;
  1012. case BABYLON.Mesh.CAP_ALL:
  1013. shapePaths[0] = capPath(shapePaths[2]);
  1014. shapePaths[1] = shapePaths[2].slice(0);
  1015. shapePaths[index] = shapePaths[index - 1];
  1016. shapePaths[index + 1] = capPath(shapePaths[index - 1]);
  1017. break;
  1018. default:
  1019. break;
  1020. }
  1021. return shapePaths;
  1022. };
  1023. var path3D;
  1024. var pathArray;
  1025. if (instance) {
  1026. path3D = (instance.path3D).update(curve);
  1027. pathArray = extrusionPathArray(shape, curve, instance.path3D, instance.pathArray, scale, rotation, scaleFunction, rotateFunction, instance.cap, custom);
  1028. instance = BABYLON.Mesh.CreateRibbon(null, pathArray, null, null, null, null, null, null, instance);
  1029. return instance;
  1030. }
  1031. // extruded shape creation
  1032. path3D = new BABYLON.Path3D(curve);
  1033. var newShapePaths = new Array();
  1034. cap = (cap < 0 || cap > 3) ? 0 : cap;
  1035. pathArray = extrusionPathArray(shape, curve, path3D, newShapePaths, scale, rotation, scaleFunction, rotateFunction, cap, custom);
  1036. var extrudedGeneric = MeshBuilder.CreateRibbon(name, { pathArray: pathArray, closeArray: rbCA, closePath: rbCP, updatable: updtbl, sideOrientation: side, invertUV: invertUV }, scene);
  1037. extrudedGeneric.pathArray = pathArray;
  1038. extrudedGeneric.path3D = path3D;
  1039. extrudedGeneric.cap = cap;
  1040. return extrudedGeneric;
  1041. };
  1042. return MeshBuilder;
  1043. }());
  1044. BABYLON.MeshBuilder = MeshBuilder;
  1045. })(BABYLON || (BABYLON = {}));