linesBuilder.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* eslint-disable @typescript-eslint/naming-convention */
  2. import { Vector3 } from "../../Maths/math.vector.js";
  3. import { _CreationDataStorage, Mesh } from "../mesh.js";
  4. import { VertexData } from "../mesh.vertexData.js";
  5. import { LinesMesh } from "../../Meshes/linesMesh.js";
  6. import { VertexBuffer } from "../../Buffers/buffer.js";
  7. import { Logger } from "../../Misc/logger.js";
  8. /**
  9. * Creates the VertexData of the LineSystem
  10. * @param options an object used to set the following optional parameters for the LineSystem, required but can be empty
  11. * - lines an array of lines, each line being an array of successive Vector3
  12. * - colors an array of line colors, each of the line colors being an array of successive Color4, one per line point
  13. * @returns the VertexData of the LineSystem
  14. */
  15. export function CreateLineSystemVertexData(options) {
  16. const indices = [];
  17. const positions = [];
  18. const lines = options.lines;
  19. const colors = options.colors;
  20. const vertexColors = [];
  21. let idx = 0;
  22. for (let l = 0; l < lines.length; l++) {
  23. const points = lines[l];
  24. for (let index = 0; index < points.length; index++) {
  25. const { x, y, z } = points[index];
  26. positions.push(x, y, z);
  27. if (colors) {
  28. const color = colors[l];
  29. const { r, g, b, a } = color[index];
  30. vertexColors.push(r, g, b, a);
  31. }
  32. if (index > 0) {
  33. indices.push(idx - 1);
  34. indices.push(idx);
  35. }
  36. idx++;
  37. }
  38. }
  39. const vertexData = new VertexData();
  40. vertexData.indices = indices;
  41. vertexData.positions = positions;
  42. if (colors) {
  43. vertexData.colors = vertexColors;
  44. }
  45. return vertexData;
  46. }
  47. /**
  48. * Create the VertexData for a DashedLines
  49. * @param options an object used to set the following optional parameters for the DashedLines, required but can be empty
  50. * - points an array successive Vector3
  51. * - dashSize the size of the dashes relative to the dash number, optional, default 3
  52. * - gapSize the size of the gap between two successive dashes relative to the dash number, optional, default 1
  53. * - dashNb the intended total number of dashes, optional, default 200
  54. * @returns the VertexData for the DashedLines
  55. */
  56. export function CreateDashedLinesVertexData(options) {
  57. const dashSize = options.dashSize || 3;
  58. const gapSize = options.gapSize || 1;
  59. const dashNb = options.dashNb || 200;
  60. const points = options.points;
  61. const positions = [];
  62. const indices = [];
  63. const curvect = Vector3.Zero();
  64. let lg = 0;
  65. let nb = 0;
  66. let shft = 0;
  67. let dashshft = 0;
  68. let curshft = 0;
  69. let idx = 0;
  70. let i = 0;
  71. for (i = 0; i < points.length - 1; i++) {
  72. points[i + 1].subtractToRef(points[i], curvect);
  73. lg += curvect.length();
  74. }
  75. shft = lg / dashNb;
  76. dashshft = (dashSize * shft) / (dashSize + gapSize);
  77. for (i = 0; i < points.length - 1; i++) {
  78. points[i + 1].subtractToRef(points[i], curvect);
  79. nb = Math.floor(curvect.length() / shft);
  80. curvect.normalize();
  81. for (let j = 0; j < nb; j++) {
  82. curshft = shft * j;
  83. positions.push(points[i].x + curshft * curvect.x, points[i].y + curshft * curvect.y, points[i].z + curshft * curvect.z);
  84. positions.push(points[i].x + (curshft + dashshft) * curvect.x, points[i].y + (curshft + dashshft) * curvect.y, points[i].z + (curshft + dashshft) * curvect.z);
  85. indices.push(idx, idx + 1);
  86. idx += 2;
  87. }
  88. }
  89. // Result
  90. const vertexData = new VertexData();
  91. vertexData.positions = positions;
  92. vertexData.indices = indices;
  93. return vertexData;
  94. }
  95. /**
  96. * Creates a line system mesh. A line system is a pool of many lines gathered in a single mesh
  97. * * 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
  98. * * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function
  99. * * The parameter `lines` is an array of lines, each line being an array of successive Vector3
  100. * * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter
  101. * * The optional parameter `colors` is an array of line colors, each line colors being an array of successive Color4, one per line point
  102. * * The optional parameter `useVertexAlpha` is to be set to `false` (default `true`) when you don't need the alpha blending (faster)
  103. * * The optional parameter `material` is the material to use to draw the lines if provided. If not, a default material will be created
  104. * * Updating a simple Line mesh, you just need to update every line in the `lines` array : https://doc.babylonjs.com/features/featuresDeepDive/mesh/dynamicMeshMorph#lines-and-dashedlines
  105. * * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines
  106. * * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created
  107. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/param#line-system
  108. * @param name defines the name of the new line system
  109. * @param options defines the options used to create the line system
  110. * @param scene defines the hosting scene
  111. * @returns a new line system mesh
  112. */
  113. export function CreateLineSystem(name, options, scene = null) {
  114. const instance = options.instance;
  115. const lines = options.lines;
  116. const colors = options.colors;
  117. if (instance) {
  118. // lines update
  119. const positions = instance.getVerticesData(VertexBuffer.PositionKind);
  120. let vertexColor;
  121. let lineColors;
  122. if (colors) {
  123. vertexColor = instance.getVerticesData(VertexBuffer.ColorKind);
  124. }
  125. let i = 0;
  126. let c = 0;
  127. for (let l = 0; l < lines.length; l++) {
  128. const points = lines[l];
  129. for (let p = 0; p < points.length; p++) {
  130. positions[i] = points[p].x;
  131. positions[i + 1] = points[p].y;
  132. positions[i + 2] = points[p].z;
  133. if (colors && vertexColor) {
  134. lineColors = colors[l];
  135. vertexColor[c] = lineColors[p].r;
  136. vertexColor[c + 1] = lineColors[p].g;
  137. vertexColor[c + 2] = lineColors[p].b;
  138. vertexColor[c + 3] = lineColors[p].a;
  139. c += 4;
  140. }
  141. i += 3;
  142. }
  143. }
  144. instance.updateVerticesData(VertexBuffer.PositionKind, positions, false, false);
  145. if (colors && vertexColor) {
  146. instance.updateVerticesData(VertexBuffer.ColorKind, vertexColor, false, false);
  147. }
  148. return instance;
  149. }
  150. // line system creation
  151. const useVertexColor = colors ? true : false;
  152. const lineSystem = new LinesMesh(name, scene, null, undefined, undefined, useVertexColor, options.useVertexAlpha, options.material);
  153. const vertexData = CreateLineSystemVertexData(options);
  154. vertexData.applyToMesh(lineSystem, options.updatable);
  155. return lineSystem;
  156. }
  157. /**
  158. * Creates a line mesh
  159. * 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
  160. * * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function
  161. * * The parameter `points` is an array successive Vector3
  162. * * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : https://doc.babylonjs.com/features/featuresDeepDive/mesh/dynamicMeshMorph#lines-and-dashedlines
  163. * * The optional parameter `colors` is an array of successive Color4, one per line point
  164. * * The optional parameter `useVertexAlpha` is to be set to `false` (default `true`) when you don't need alpha blending (faster)
  165. * * The optional parameter `material` is the material to use to draw the lines if provided. If not, a default material will be created
  166. * * When updating an instance, remember that only point positions can change, not the number of points
  167. * * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created
  168. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/param#lines
  169. * @param name defines the name of the new line system
  170. * @param options defines the options used to create the line system
  171. * @param scene defines the hosting scene
  172. * @returns a new line mesh
  173. */
  174. export function CreateLines(name, options, scene = null) {
  175. const colors = options.colors ? [options.colors] : null;
  176. const lines = CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance, colors: colors, useVertexAlpha: options.useVertexAlpha, material: options.material }, scene);
  177. return lines;
  178. }
  179. /**
  180. * Creates a dashed line mesh
  181. * * 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
  182. * * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function
  183. * * The parameter `points` is an array successive Vector3
  184. * * The parameter `dashNb` is the intended total number of dashes (positive integer, default 200)
  185. * * The parameter `dashSize` is the size of the dashes relatively the dash number (positive float, default 3)
  186. * * The parameter `gapSize` is the size of the gap between two successive dashes relatively the dash number (positive float, default 1)
  187. * * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : https://doc.babylonjs.com/features/featuresDeepDive/mesh/dynamicMeshMorph#lines-and-dashedlines
  188. * * The optional parameter `useVertexAlpha` is to be set to `false` (default `true`) when you don't need the alpha blending (faster)
  189. * * The optional parameter `material` is the material to use to draw the lines if provided. If not, a default material will be created
  190. * * When updating an instance, remember that only point positions can change, not the number of points
  191. * * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created
  192. * @param name defines the name of the mesh
  193. * @param options defines the options used to create the mesh
  194. * @param scene defines the hosting scene
  195. * @returns the dashed line mesh
  196. * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/param#dashed-lines
  197. */
  198. export function CreateDashedLines(name, options, scene = null) {
  199. const points = options.points;
  200. const instance = options.instance;
  201. const gapSize = options.gapSize || 1;
  202. const dashSize = options.dashSize || 3;
  203. if (instance) {
  204. // dashed lines update
  205. const positionFunction = (positions) => {
  206. const curvect = Vector3.Zero();
  207. const nbSeg = positions.length / 6;
  208. let lg = 0;
  209. let nb = 0;
  210. let shft = 0;
  211. let dashshft = 0;
  212. let curshft = 0;
  213. let p = 0;
  214. let i = 0;
  215. let j = 0;
  216. for (i = 0; i < points.length - 1; i++) {
  217. points[i + 1].subtractToRef(points[i], curvect);
  218. lg += curvect.length();
  219. }
  220. shft = lg / nbSeg;
  221. const dashSize = instance._creationDataStorage.dashSize;
  222. const gapSize = instance._creationDataStorage.gapSize;
  223. dashshft = (dashSize * shft) / (dashSize + gapSize);
  224. for (i = 0; i < points.length - 1; i++) {
  225. points[i + 1].subtractToRef(points[i], curvect);
  226. nb = Math.floor(curvect.length() / shft);
  227. curvect.normalize();
  228. j = 0;
  229. while (j < nb && p < positions.length) {
  230. curshft = shft * j;
  231. positions[p] = points[i].x + curshft * curvect.x;
  232. positions[p + 1] = points[i].y + curshft * curvect.y;
  233. positions[p + 2] = points[i].z + curshft * curvect.z;
  234. positions[p + 3] = points[i].x + (curshft + dashshft) * curvect.x;
  235. positions[p + 4] = points[i].y + (curshft + dashshft) * curvect.y;
  236. positions[p + 5] = points[i].z + (curshft + dashshft) * curvect.z;
  237. p += 6;
  238. j++;
  239. }
  240. }
  241. while (p < positions.length) {
  242. positions[p] = points[i].x;
  243. positions[p + 1] = points[i].y;
  244. positions[p + 2] = points[i].z;
  245. p += 3;
  246. }
  247. };
  248. if (options.dashNb || options.dashSize || options.gapSize || options.useVertexAlpha || options.material) {
  249. Logger.Warn("You have used an option other than points with the instance option. Please be aware that these other options will be ignored.");
  250. }
  251. instance.updateMeshPositions(positionFunction, false);
  252. return instance;
  253. }
  254. // dashed lines creation
  255. const dashedLines = new LinesMesh(name, scene, null, undefined, undefined, undefined, options.useVertexAlpha, options.material);
  256. const vertexData = CreateDashedLinesVertexData(options);
  257. vertexData.applyToMesh(dashedLines, options.updatable);
  258. dashedLines._creationDataStorage = new _CreationDataStorage();
  259. dashedLines._creationDataStorage.dashSize = dashSize;
  260. dashedLines._creationDataStorage.gapSize = gapSize;
  261. return dashedLines;
  262. }
  263. /**
  264. * Class containing static functions to help procedurally build meshes
  265. * @deprecated use the functions directly from the module
  266. */
  267. export const LinesBuilder = {
  268. CreateDashedLines,
  269. CreateLineSystem,
  270. CreateLines,
  271. };
  272. VertexData.CreateLineSystem = CreateLineSystemVertexData;
  273. VertexData.CreateDashedLines = CreateDashedLinesVertexData;
  274. Mesh.CreateLines = (name, points, scene = null, updatable = false, instance = null) => {
  275. const options = {
  276. points,
  277. updatable,
  278. instance,
  279. };
  280. return CreateLines(name, options, scene);
  281. };
  282. Mesh.CreateDashedLines = (name, points, dashSize, gapSize, dashNb, scene = null, updatable, instance) => {
  283. const options = {
  284. points,
  285. dashSize,
  286. gapSize,
  287. dashNb,
  288. updatable,
  289. instance,
  290. };
  291. return CreateDashedLines(name, options, scene);
  292. };
  293. //# sourceMappingURL=linesBuilder.js.map