geometry.js 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. import { Vector3 } from "../Maths/math.vector.js";
  2. import { Color4 } from "../Maths/math.color.js";
  3. import { VertexData } from "../Meshes/mesh.vertexData.js";
  4. import { VertexBuffer } from "../Buffers/buffer.js";
  5. import { SubMesh } from "../Meshes/subMesh.js";
  6. import { SceneLoaderFlags } from "../Loading/sceneLoaderFlags.js";
  7. import { BoundingInfo } from "../Culling/boundingInfo.js";
  8. import { Tools } from "../Misc/tools.js";
  9. import { Tags } from "../Misc/tags.js";
  10. import { extractMinAndMax } from "../Maths/math.functions.js";
  11. import { EngineStore } from "../Engines/engineStore.js";
  12. import { CompatibilityOptions } from "../Compat/compatibilityOptions.js";
  13. /**
  14. * Class used to store geometry data (vertex buffers + index buffer)
  15. */
  16. export class Geometry {
  17. /**
  18. * Gets or sets the Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
  19. */
  20. get boundingBias() {
  21. return this._boundingBias;
  22. }
  23. /**
  24. * Gets or sets the Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
  25. */
  26. set boundingBias(value) {
  27. if (this._boundingBias) {
  28. this._boundingBias.copyFrom(value);
  29. }
  30. else {
  31. this._boundingBias = value.clone();
  32. }
  33. this._updateBoundingInfo(true, null);
  34. }
  35. /**
  36. * Static function used to attach a new empty geometry to a mesh
  37. * @param mesh defines the mesh to attach the geometry to
  38. * @returns the new Geometry
  39. */
  40. static CreateGeometryForMesh(mesh) {
  41. const geometry = new Geometry(Geometry.RandomId(), mesh.getScene());
  42. geometry.applyToMesh(mesh);
  43. return geometry;
  44. }
  45. /** Get the list of meshes using this geometry */
  46. get meshes() {
  47. return this._meshes;
  48. }
  49. /**
  50. * Creates a new geometry
  51. * @param id defines the unique ID
  52. * @param scene defines the hosting scene
  53. * @param vertexData defines the VertexData used to get geometry data
  54. * @param updatable defines if geometry must be updatable (false by default)
  55. * @param mesh defines the mesh that will be associated with the geometry
  56. */
  57. constructor(id, scene, vertexData, updatable = false, mesh = null) {
  58. /**
  59. * Gets the delay loading state of the geometry (none by default which means not delayed)
  60. */
  61. this.delayLoadState = 0;
  62. this._totalVertices = 0;
  63. this._isDisposed = false;
  64. this._indexBufferIsUpdatable = false;
  65. this._positionsCache = [];
  66. /** @internal */
  67. this._parentContainer = null;
  68. /**
  69. * If set to true (false by default), the bounding info applied to the meshes sharing this geometry will be the bounding info defined at the class level
  70. * and won't be computed based on the vertex positions (which is what we get when useBoundingInfoFromGeometry = false)
  71. */
  72. this.useBoundingInfoFromGeometry = false;
  73. this._scene = scene || EngineStore.LastCreatedScene;
  74. if (!this._scene) {
  75. return;
  76. }
  77. this.id = id;
  78. this.uniqueId = this._scene.getUniqueId();
  79. this._engine = this._scene.getEngine();
  80. this._meshes = [];
  81. //Init vertex buffer cache
  82. this._vertexBuffers = {};
  83. this._indices = [];
  84. this._updatable = updatable;
  85. // vertexData
  86. if (vertexData) {
  87. this.setAllVerticesData(vertexData, updatable);
  88. }
  89. else {
  90. this._totalVertices = 0;
  91. }
  92. if (this._engine.getCaps().vertexArrayObject) {
  93. this._vertexArrayObjects = {};
  94. }
  95. // applyToMesh
  96. if (mesh) {
  97. this.applyToMesh(mesh);
  98. mesh.computeWorldMatrix(true);
  99. }
  100. }
  101. /**
  102. * Gets the current extend of the geometry
  103. */
  104. get extend() {
  105. return this._extend;
  106. }
  107. /**
  108. * Gets the hosting scene
  109. * @returns the hosting Scene
  110. */
  111. getScene() {
  112. return this._scene;
  113. }
  114. /**
  115. * Gets the hosting engine
  116. * @returns the hosting Engine
  117. */
  118. getEngine() {
  119. return this._engine;
  120. }
  121. /**
  122. * Defines if the geometry is ready to use
  123. * @returns true if the geometry is ready to be used
  124. */
  125. isReady() {
  126. return this.delayLoadState === 1 || this.delayLoadState === 0;
  127. }
  128. /**
  129. * Gets a value indicating that the geometry should not be serialized
  130. */
  131. get doNotSerialize() {
  132. for (let index = 0; index < this._meshes.length; index++) {
  133. if (!this._meshes[index].doNotSerialize) {
  134. return false;
  135. }
  136. }
  137. return true;
  138. }
  139. /** @internal */
  140. _rebuild() {
  141. if (this._vertexArrayObjects) {
  142. this._vertexArrayObjects = {};
  143. }
  144. // Index buffer
  145. if (this._meshes.length !== 0 && this._indices) {
  146. this._indexBuffer = this._engine.createIndexBuffer(this._indices, this._updatable, "Geometry_" + this.id + "_IndexBuffer");
  147. }
  148. // Vertex buffers
  149. const buffers = new Set();
  150. for (const key in this._vertexBuffers) {
  151. buffers.add(this._vertexBuffers[key].getWrapperBuffer());
  152. }
  153. buffers.forEach((buffer) => {
  154. buffer._rebuild();
  155. });
  156. }
  157. /**
  158. * Affects all geometry data in one call
  159. * @param vertexData defines the geometry data
  160. * @param updatable defines if the geometry must be flagged as updatable (false as default)
  161. */
  162. setAllVerticesData(vertexData, updatable) {
  163. vertexData.applyToGeometry(this, updatable);
  164. this._notifyUpdate();
  165. }
  166. /**
  167. * Set specific vertex data
  168. * @param kind defines the data kind (Position, normal, etc...)
  169. * @param data defines the vertex data to use
  170. * @param updatable defines if the vertex must be flagged as updatable (false as default)
  171. * @param stride defines the stride to use (0 by default). This value is deduced from the kind value if not specified
  172. */
  173. setVerticesData(kind, data, updatable = false, stride) {
  174. if (updatable && Array.isArray(data)) {
  175. // to avoid converting to Float32Array at each draw call in engine.updateDynamicVertexBuffer, we make the conversion a single time here
  176. data = new Float32Array(data);
  177. }
  178. const buffer = new VertexBuffer(this._engine, data, kind, {
  179. updatable,
  180. postponeInternalCreation: this._meshes.length === 0,
  181. stride,
  182. label: "Geometry_" + this.id + "_" + kind,
  183. });
  184. this.setVerticesBuffer(buffer);
  185. }
  186. /**
  187. * Removes a specific vertex data
  188. * @param kind defines the data kind (Position, normal, etc...)
  189. */
  190. removeVerticesData(kind) {
  191. if (this._vertexBuffers[kind]) {
  192. this._vertexBuffers[kind].dispose();
  193. delete this._vertexBuffers[kind];
  194. }
  195. if (this._vertexArrayObjects) {
  196. this._disposeVertexArrayObjects();
  197. }
  198. }
  199. /**
  200. * Affect a vertex buffer to the geometry. the vertexBuffer.getKind() function is used to determine where to store the data
  201. * @param buffer defines the vertex buffer to use
  202. * @param totalVertices defines the total number of vertices for position kind (could be null)
  203. * @param disposeExistingBuffer disposes the existing buffer, if any (default: true)
  204. */
  205. setVerticesBuffer(buffer, totalVertices = null, disposeExistingBuffer = true) {
  206. const kind = buffer.getKind();
  207. if (this._vertexBuffers[kind] && disposeExistingBuffer) {
  208. this._vertexBuffers[kind].dispose();
  209. }
  210. if (buffer._buffer) {
  211. buffer._buffer._increaseReferences();
  212. }
  213. this._vertexBuffers[kind] = buffer;
  214. const meshes = this._meshes;
  215. const numOfMeshes = meshes.length;
  216. if (kind === VertexBuffer.PositionKind) {
  217. this._totalVertices = totalVertices ?? buffer._maxVerticesCount;
  218. this._updateExtend(buffer.getFloatData(this._totalVertices));
  219. this._resetPointsArrayCache();
  220. // this._extend can be empty if buffer.getFloatData(this._totalVertices) returned null
  221. const minimum = (this._extend && this._extend.minimum) || new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
  222. const maximum = (this._extend && this._extend.maximum) || new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  223. for (let index = 0; index < numOfMeshes; index++) {
  224. const mesh = meshes[index];
  225. mesh.buildBoundingInfo(minimum, maximum);
  226. mesh._createGlobalSubMesh(mesh.isUnIndexed);
  227. mesh.computeWorldMatrix(true);
  228. mesh.synchronizeInstances();
  229. }
  230. }
  231. this._notifyUpdate(kind);
  232. }
  233. /**
  234. * Update a specific vertex buffer
  235. * This function will directly update the underlying DataBuffer according to the passed numeric array or Float32Array
  236. * It will do nothing if the buffer is not updatable
  237. * @param kind defines the data kind (Position, normal, etc...)
  238. * @param data defines the data to use
  239. * @param offset defines the offset in the target buffer where to store the data
  240. * @param useBytes set to true if the offset is in bytes
  241. */
  242. updateVerticesDataDirectly(kind, data, offset, useBytes = false) {
  243. const vertexBuffer = this.getVertexBuffer(kind);
  244. if (!vertexBuffer) {
  245. return;
  246. }
  247. vertexBuffer.updateDirectly(data, offset, useBytes);
  248. this._notifyUpdate(kind);
  249. }
  250. /**
  251. * Update a specific vertex buffer
  252. * This function will create a new buffer if the current one is not updatable
  253. * @param kind defines the data kind (Position, normal, etc...)
  254. * @param data defines the data to use
  255. * @param updateExtends defines if the geometry extends must be recomputed (false by default)
  256. */
  257. updateVerticesData(kind, data, updateExtends = false) {
  258. const vertexBuffer = this.getVertexBuffer(kind);
  259. if (!vertexBuffer) {
  260. return;
  261. }
  262. vertexBuffer.update(data);
  263. if (kind === VertexBuffer.PositionKind) {
  264. this._updateBoundingInfo(updateExtends, data);
  265. }
  266. this._notifyUpdate(kind);
  267. }
  268. _updateBoundingInfo(updateExtends, data) {
  269. if (updateExtends) {
  270. this._updateExtend(data);
  271. }
  272. this._resetPointsArrayCache();
  273. if (updateExtends) {
  274. const meshes = this._meshes;
  275. for (const mesh of meshes) {
  276. if (mesh.hasBoundingInfo) {
  277. mesh.getBoundingInfo().reConstruct(this._extend.minimum, this._extend.maximum);
  278. }
  279. else {
  280. mesh.buildBoundingInfo(this._extend.minimum, this._extend.maximum);
  281. }
  282. const subMeshes = mesh.subMeshes;
  283. for (const subMesh of subMeshes) {
  284. subMesh.refreshBoundingInfo();
  285. }
  286. }
  287. }
  288. }
  289. /**
  290. * @internal
  291. */
  292. _bind(effect, indexToBind, overrideVertexBuffers, overrideVertexArrayObjects) {
  293. if (!effect) {
  294. return;
  295. }
  296. if (indexToBind === undefined) {
  297. indexToBind = this._indexBuffer;
  298. }
  299. const vbs = this.getVertexBuffers();
  300. if (!vbs) {
  301. return;
  302. }
  303. if (indexToBind != this._indexBuffer || (!this._vertexArrayObjects && !overrideVertexArrayObjects)) {
  304. this._engine.bindBuffers(vbs, indexToBind, effect, overrideVertexBuffers);
  305. return;
  306. }
  307. const vaos = overrideVertexArrayObjects ? overrideVertexArrayObjects : this._vertexArrayObjects;
  308. const engine = this._engine;
  309. // Using VAO
  310. if (!vaos[effect.key]) {
  311. vaos[effect.key] = engine.recordVertexArrayObject(vbs, indexToBind, effect, overrideVertexBuffers);
  312. }
  313. engine.bindVertexArrayObject(vaos[effect.key], indexToBind);
  314. }
  315. /**
  316. * Gets total number of vertices
  317. * @returns the total number of vertices
  318. */
  319. getTotalVertices() {
  320. if (!this.isReady()) {
  321. return 0;
  322. }
  323. return this._totalVertices;
  324. }
  325. /**
  326. * Gets a specific vertex data attached to this geometry. Float data is constructed if the vertex buffer data cannot be returned directly.
  327. * @param kind defines the data kind (Position, normal, etc...)
  328. * @param copyWhenShared defines if the returned array must be cloned upon returning it if the current geometry is shared between multiple meshes
  329. * @param forceCopy defines a boolean indicating that the returned array must be cloned upon returning it
  330. * @returns a float array containing vertex data
  331. */
  332. getVerticesData(kind, copyWhenShared, forceCopy) {
  333. const vertexBuffer = this.getVertexBuffer(kind);
  334. if (!vertexBuffer) {
  335. return null;
  336. }
  337. return vertexBuffer.getFloatData(this._totalVertices, forceCopy || (copyWhenShared && this._meshes.length !== 1));
  338. }
  339. /**
  340. * Returns a boolean defining if the vertex data for the requested `kind` is updatable
  341. * @param kind defines the data kind (Position, normal, etc...)
  342. * @returns true if the vertex buffer with the specified kind is updatable
  343. */
  344. isVertexBufferUpdatable(kind) {
  345. const vb = this._vertexBuffers[kind];
  346. if (!vb) {
  347. return false;
  348. }
  349. return vb.isUpdatable();
  350. }
  351. /**
  352. * Gets a specific vertex buffer
  353. * @param kind defines the data kind (Position, normal, etc...)
  354. * @returns a VertexBuffer
  355. */
  356. getVertexBuffer(kind) {
  357. if (!this.isReady()) {
  358. return null;
  359. }
  360. return this._vertexBuffers[kind];
  361. }
  362. /**
  363. * Returns all vertex buffers
  364. * @returns an object holding all vertex buffers indexed by kind
  365. */
  366. getVertexBuffers() {
  367. if (!this.isReady()) {
  368. return null;
  369. }
  370. return this._vertexBuffers;
  371. }
  372. /**
  373. * Gets a boolean indicating if specific vertex buffer is present
  374. * @param kind defines the data kind (Position, normal, etc...)
  375. * @returns true if data is present
  376. */
  377. isVerticesDataPresent(kind) {
  378. if (!this._vertexBuffers) {
  379. if (this._delayInfo) {
  380. return this._delayInfo.indexOf(kind) !== -1;
  381. }
  382. return false;
  383. }
  384. return this._vertexBuffers[kind] !== undefined;
  385. }
  386. /**
  387. * Gets a list of all attached data kinds (Position, normal, etc...)
  388. * @returns a list of string containing all kinds
  389. */
  390. getVerticesDataKinds() {
  391. const result = [];
  392. let kind;
  393. if (!this._vertexBuffers && this._delayInfo) {
  394. for (kind in this._delayInfo) {
  395. result.push(kind);
  396. }
  397. }
  398. else {
  399. for (kind in this._vertexBuffers) {
  400. result.push(kind);
  401. }
  402. }
  403. return result;
  404. }
  405. /**
  406. * Update index buffer
  407. * @param indices defines the indices to store in the index buffer
  408. * @param offset defines the offset in the target buffer where to store the data
  409. * @param gpuMemoryOnly defines a boolean indicating that only the GPU memory must be updated leaving the CPU version of the indices unchanged (false by default)
  410. */
  411. updateIndices(indices, offset, gpuMemoryOnly = false) {
  412. if (!this._indexBuffer) {
  413. return;
  414. }
  415. if (!this._indexBufferIsUpdatable) {
  416. this.setIndices(indices, null, true);
  417. }
  418. else {
  419. const needToUpdateSubMeshes = indices.length !== this._indices.length;
  420. if (!gpuMemoryOnly) {
  421. this._indices = indices.slice();
  422. }
  423. this._engine.updateDynamicIndexBuffer(this._indexBuffer, indices, offset);
  424. if (needToUpdateSubMeshes) {
  425. for (const mesh of this._meshes) {
  426. mesh._createGlobalSubMesh(true);
  427. }
  428. }
  429. }
  430. }
  431. /**
  432. * Sets the index buffer for this geometry.
  433. * @param indexBuffer Defines the index buffer to use for this geometry
  434. * @param totalVertices Defines the total number of vertices used by the buffer
  435. * @param totalIndices Defines the total number of indices in the index buffer
  436. */
  437. setIndexBuffer(indexBuffer, totalVertices, totalIndices) {
  438. this._indices = [];
  439. this._indexBufferIsUpdatable = false;
  440. this._indexBuffer = indexBuffer;
  441. this._totalVertices = totalVertices;
  442. this._totalIndices = totalIndices;
  443. indexBuffer.is32Bits || (indexBuffer.is32Bits = this._totalIndices > 65535);
  444. for (const mesh of this._meshes) {
  445. mesh._createGlobalSubMesh(true);
  446. mesh.synchronizeInstances();
  447. }
  448. this._notifyUpdate();
  449. }
  450. /**
  451. * Creates a new index buffer
  452. * @param indices defines the indices to store in the index buffer
  453. * @param totalVertices defines the total number of vertices (could be null)
  454. * @param updatable defines if the index buffer must be flagged as updatable (false by default)
  455. */
  456. setIndices(indices, totalVertices = null, updatable = false) {
  457. if (this._indexBuffer) {
  458. this._engine._releaseBuffer(this._indexBuffer);
  459. }
  460. this._indices = indices;
  461. this._indexBufferIsUpdatable = updatable;
  462. if (this._meshes.length !== 0 && this._indices) {
  463. this._indexBuffer = this._engine.createIndexBuffer(this._indices, updatable, "Geometry_" + this.id + "_IndexBuffer");
  464. }
  465. if (totalVertices != undefined) {
  466. // including null and undefined
  467. this._totalVertices = totalVertices;
  468. }
  469. for (const mesh of this._meshes) {
  470. mesh._createGlobalSubMesh(true);
  471. mesh.synchronizeInstances();
  472. }
  473. this._notifyUpdate();
  474. }
  475. /**
  476. * Return the total number of indices
  477. * @returns the total number of indices
  478. */
  479. getTotalIndices() {
  480. if (!this.isReady()) {
  481. return 0;
  482. }
  483. return this._totalIndices !== undefined ? this._totalIndices : this._indices.length;
  484. }
  485. /**
  486. * Gets the index buffer array
  487. * @param copyWhenShared defines if the returned array must be cloned upon returning it if the current geometry is shared between multiple meshes
  488. * @param forceCopy defines a boolean indicating that the returned array must be cloned upon returning it
  489. * @returns the index buffer array
  490. */
  491. getIndices(copyWhenShared, forceCopy) {
  492. if (!this.isReady()) {
  493. return null;
  494. }
  495. const orig = this._indices;
  496. if (!forceCopy && (!copyWhenShared || this._meshes.length === 1)) {
  497. return orig;
  498. }
  499. else {
  500. return orig.slice();
  501. }
  502. }
  503. /**
  504. * Gets the index buffer
  505. * @returns the index buffer
  506. */
  507. getIndexBuffer() {
  508. if (!this.isReady()) {
  509. return null;
  510. }
  511. return this._indexBuffer;
  512. }
  513. /**
  514. * @internal
  515. */
  516. _releaseVertexArrayObject(effect = null) {
  517. if (!effect || !this._vertexArrayObjects) {
  518. return;
  519. }
  520. if (this._vertexArrayObjects[effect.key]) {
  521. this._engine.releaseVertexArrayObject(this._vertexArrayObjects[effect.key]);
  522. delete this._vertexArrayObjects[effect.key];
  523. }
  524. }
  525. /**
  526. * Release the associated resources for a specific mesh
  527. * @param mesh defines the source mesh
  528. * @param shouldDispose defines if the geometry must be disposed if there is no more mesh pointing to it
  529. */
  530. releaseForMesh(mesh, shouldDispose) {
  531. const meshes = this._meshes;
  532. const index = meshes.indexOf(mesh);
  533. if (index === -1) {
  534. return;
  535. }
  536. meshes.splice(index, 1);
  537. if (this._vertexArrayObjects) {
  538. mesh._invalidateInstanceVertexArrayObject();
  539. }
  540. mesh._geometry = null;
  541. if (meshes.length === 0 && shouldDispose) {
  542. this.dispose();
  543. }
  544. }
  545. /**
  546. * Apply current geometry to a given mesh
  547. * @param mesh defines the mesh to apply geometry to
  548. */
  549. applyToMesh(mesh) {
  550. if (mesh._geometry === this) {
  551. return;
  552. }
  553. const previousGeometry = mesh._geometry;
  554. if (previousGeometry) {
  555. previousGeometry.releaseForMesh(mesh);
  556. }
  557. if (this._vertexArrayObjects) {
  558. mesh._invalidateInstanceVertexArrayObject();
  559. }
  560. const meshes = this._meshes;
  561. // must be done before setting vertexBuffers because of mesh._createGlobalSubMesh()
  562. mesh._geometry = this;
  563. mesh._internalAbstractMeshDataInfo._positions = null;
  564. this._scene.pushGeometry(this);
  565. meshes.push(mesh);
  566. if (this.isReady()) {
  567. this._applyToMesh(mesh);
  568. }
  569. else if (this._boundingInfo) {
  570. mesh.setBoundingInfo(this._boundingInfo);
  571. }
  572. }
  573. _updateExtend(data = null) {
  574. if (this.useBoundingInfoFromGeometry && this._boundingInfo) {
  575. this._extend = {
  576. minimum: this._boundingInfo.minimum.clone(),
  577. maximum: this._boundingInfo.maximum.clone(),
  578. };
  579. }
  580. else {
  581. if (!data) {
  582. data = this.getVerticesData(VertexBuffer.PositionKind);
  583. // This can happen if the buffer comes from a Hardware Buffer where
  584. // The data have not been uploaded by Babylon. (ex: Compute Shaders and Storage Buffers)
  585. if (!data) {
  586. return;
  587. }
  588. }
  589. this._extend = extractMinAndMax(data, 0, this._totalVertices, this.boundingBias, 3);
  590. }
  591. }
  592. _applyToMesh(mesh) {
  593. const numOfMeshes = this._meshes.length;
  594. // vertexBuffers
  595. for (const kind in this._vertexBuffers) {
  596. if (numOfMeshes === 1) {
  597. this._vertexBuffers[kind].create();
  598. }
  599. if (kind === VertexBuffer.PositionKind) {
  600. if (!this._extend) {
  601. this._updateExtend();
  602. }
  603. mesh.buildBoundingInfo(this._extend.minimum, this._extend.maximum);
  604. mesh._createGlobalSubMesh(mesh.isUnIndexed);
  605. //bounding info was just created again, world matrix should be applied again.
  606. mesh._updateBoundingInfo();
  607. }
  608. }
  609. // indexBuffer
  610. if (numOfMeshes === 1 && this._indices && this._indices.length > 0) {
  611. this._indexBuffer = this._engine.createIndexBuffer(this._indices, this._updatable, "Geometry_" + this.id + "_IndexBuffer");
  612. }
  613. // morphTargets
  614. mesh._syncGeometryWithMorphTargetManager();
  615. // instances
  616. mesh.synchronizeInstances();
  617. }
  618. _notifyUpdate(kind) {
  619. if (this.onGeometryUpdated) {
  620. this.onGeometryUpdated(this, kind);
  621. }
  622. if (this._vertexArrayObjects) {
  623. this._disposeVertexArrayObjects();
  624. }
  625. for (const mesh of this._meshes) {
  626. mesh._markSubMeshesAsAttributesDirty();
  627. }
  628. }
  629. /**
  630. * Load the geometry if it was flagged as delay loaded
  631. * @param scene defines the hosting scene
  632. * @param onLoaded defines a callback called when the geometry is loaded
  633. */
  634. load(scene, onLoaded) {
  635. if (this.delayLoadState === 2) {
  636. return;
  637. }
  638. if (this.isReady()) {
  639. if (onLoaded) {
  640. onLoaded();
  641. }
  642. return;
  643. }
  644. this.delayLoadState = 2;
  645. this._queueLoad(scene, onLoaded);
  646. }
  647. _queueLoad(scene, onLoaded) {
  648. if (!this.delayLoadingFile) {
  649. return;
  650. }
  651. scene.addPendingData(this);
  652. scene._loadFile(this.delayLoadingFile, (data) => {
  653. if (!this._delayLoadingFunction) {
  654. return;
  655. }
  656. this._delayLoadingFunction(JSON.parse(data), this);
  657. this.delayLoadState = 1;
  658. this._delayInfo = [];
  659. scene.removePendingData(this);
  660. const meshes = this._meshes;
  661. const numOfMeshes = meshes.length;
  662. for (let index = 0; index < numOfMeshes; index++) {
  663. this._applyToMesh(meshes[index]);
  664. }
  665. if (onLoaded) {
  666. onLoaded();
  667. }
  668. }, undefined, true);
  669. }
  670. /**
  671. * Invert the geometry to move from a right handed system to a left handed one.
  672. */
  673. toLeftHanded() {
  674. // Flip faces
  675. const tIndices = this.getIndices(false);
  676. if (tIndices != null && tIndices.length > 0) {
  677. for (let i = 0; i < tIndices.length; i += 3) {
  678. const tTemp = tIndices[i + 0];
  679. tIndices[i + 0] = tIndices[i + 2];
  680. tIndices[i + 2] = tTemp;
  681. }
  682. this.setIndices(tIndices);
  683. }
  684. // Negate position.z
  685. const tPositions = this.getVerticesData(VertexBuffer.PositionKind, false);
  686. if (tPositions != null && tPositions.length > 0) {
  687. for (let i = 0; i < tPositions.length; i += 3) {
  688. tPositions[i + 2] = -tPositions[i + 2];
  689. }
  690. this.setVerticesData(VertexBuffer.PositionKind, tPositions, false);
  691. }
  692. // Negate normal.z
  693. const tNormals = this.getVerticesData(VertexBuffer.NormalKind, false);
  694. if (tNormals != null && tNormals.length > 0) {
  695. for (let i = 0; i < tNormals.length; i += 3) {
  696. tNormals[i + 2] = -tNormals[i + 2];
  697. }
  698. this.setVerticesData(VertexBuffer.NormalKind, tNormals, false);
  699. }
  700. }
  701. // Cache
  702. /** @internal */
  703. _resetPointsArrayCache() {
  704. this._positions = null;
  705. }
  706. /** @internal */
  707. _generatePointsArray() {
  708. if (this._positions) {
  709. return true;
  710. }
  711. const data = this.getVerticesData(VertexBuffer.PositionKind);
  712. if (!data || data.length === 0) {
  713. return false;
  714. }
  715. for (let index = this._positionsCache.length * 3, arrayIdx = this._positionsCache.length; index < data.length; index += 3, ++arrayIdx) {
  716. this._positionsCache[arrayIdx] = Vector3.FromArray(data, index);
  717. }
  718. for (let index = 0, arrayIdx = 0; index < data.length; index += 3, ++arrayIdx) {
  719. this._positionsCache[arrayIdx].set(data[0 + index], data[1 + index], data[2 + index]);
  720. }
  721. // just in case the number of positions was reduced, splice the array
  722. this._positionsCache.length = data.length / 3;
  723. this._positions = this._positionsCache;
  724. return true;
  725. }
  726. /**
  727. * Gets a value indicating if the geometry is disposed
  728. * @returns true if the geometry was disposed
  729. */
  730. isDisposed() {
  731. return this._isDisposed;
  732. }
  733. _disposeVertexArrayObjects() {
  734. if (this._vertexArrayObjects) {
  735. for (const kind in this._vertexArrayObjects) {
  736. this._engine.releaseVertexArrayObject(this._vertexArrayObjects[kind]);
  737. }
  738. this._vertexArrayObjects = {}; // Will trigger a rebuild of the VAO if supported
  739. const meshes = this._meshes;
  740. const numOfMeshes = meshes.length;
  741. for (let index = 0; index < numOfMeshes; index++) {
  742. meshes[index]._invalidateInstanceVertexArrayObject();
  743. }
  744. }
  745. }
  746. /**
  747. * Free all associated resources
  748. */
  749. dispose() {
  750. const meshes = this._meshes;
  751. const numOfMeshes = meshes.length;
  752. let index;
  753. for (index = 0; index < numOfMeshes; index++) {
  754. this.releaseForMesh(meshes[index]);
  755. }
  756. this._meshes.length = 0;
  757. this._disposeVertexArrayObjects();
  758. for (const kind in this._vertexBuffers) {
  759. this._vertexBuffers[kind].dispose();
  760. }
  761. this._vertexBuffers = {};
  762. this._totalVertices = 0;
  763. if (this._indexBuffer) {
  764. this._engine._releaseBuffer(this._indexBuffer);
  765. }
  766. this._indexBuffer = null;
  767. this._indices = [];
  768. this.delayLoadState = 0;
  769. this.delayLoadingFile = null;
  770. this._delayLoadingFunction = null;
  771. this._delayInfo = [];
  772. this._boundingInfo = null;
  773. this._scene.removeGeometry(this);
  774. if (this._parentContainer) {
  775. const index = this._parentContainer.geometries.indexOf(this);
  776. if (index > -1) {
  777. this._parentContainer.geometries.splice(index, 1);
  778. }
  779. this._parentContainer = null;
  780. }
  781. this._isDisposed = true;
  782. }
  783. /**
  784. * Clone the current geometry into a new geometry
  785. * @param id defines the unique ID of the new geometry
  786. * @returns a new geometry object
  787. */
  788. copy(id) {
  789. const vertexData = new VertexData();
  790. vertexData.indices = [];
  791. const indices = this.getIndices();
  792. if (indices) {
  793. for (let index = 0; index < indices.length; index++) {
  794. vertexData.indices.push(indices[index]);
  795. }
  796. }
  797. let updatable = false;
  798. let stopChecking = false;
  799. let kind;
  800. for (kind in this._vertexBuffers) {
  801. // using slice() to make a copy of the array and not just reference it
  802. const data = this.getVerticesData(kind);
  803. if (data) {
  804. if (data instanceof Float32Array) {
  805. vertexData.set(new Float32Array(data), kind);
  806. }
  807. else {
  808. vertexData.set(data.slice(0), kind);
  809. }
  810. if (!stopChecking) {
  811. const vb = this.getVertexBuffer(kind);
  812. if (vb) {
  813. updatable = vb.isUpdatable();
  814. stopChecking = !updatable;
  815. }
  816. }
  817. }
  818. }
  819. const geometry = new Geometry(id, this._scene, vertexData, updatable);
  820. geometry.delayLoadState = this.delayLoadState;
  821. geometry.delayLoadingFile = this.delayLoadingFile;
  822. geometry._delayLoadingFunction = this._delayLoadingFunction;
  823. for (kind in this._delayInfo) {
  824. geometry._delayInfo = geometry._delayInfo || [];
  825. geometry._delayInfo.push(kind);
  826. }
  827. // Bounding info
  828. geometry._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
  829. return geometry;
  830. }
  831. /**
  832. * Serialize the current geometry info (and not the vertices data) into a JSON object
  833. * @returns a JSON representation of the current geometry data (without the vertices data)
  834. */
  835. serialize() {
  836. const serializationObject = {};
  837. serializationObject.id = this.id;
  838. serializationObject.uniqueId = this.uniqueId;
  839. serializationObject.updatable = this._updatable;
  840. if (Tags && Tags.HasTags(this)) {
  841. serializationObject.tags = Tags.GetTags(this);
  842. }
  843. return serializationObject;
  844. }
  845. _toNumberArray(origin) {
  846. if (Array.isArray(origin)) {
  847. return origin;
  848. }
  849. else {
  850. return Array.prototype.slice.call(origin);
  851. }
  852. }
  853. /**
  854. * Release any memory retained by the cached data on the Geometry.
  855. *
  856. * Call this function to reduce memory footprint of the mesh.
  857. * Vertex buffers will not store CPU data anymore (this will prevent picking, collisions or physics to work correctly)
  858. */
  859. clearCachedData() {
  860. this._indices = [];
  861. this._resetPointsArrayCache();
  862. for (const vbName in this._vertexBuffers) {
  863. if (!Object.prototype.hasOwnProperty.call(this._vertexBuffers, vbName)) {
  864. continue;
  865. }
  866. this._vertexBuffers[vbName]._buffer._data = null;
  867. }
  868. }
  869. /**
  870. * Serialize all vertices data into a JSON object
  871. * @returns a JSON representation of the current geometry data
  872. */
  873. serializeVerticeData() {
  874. const serializationObject = this.serialize();
  875. if (this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
  876. serializationObject.positions = this._toNumberArray(this.getVerticesData(VertexBuffer.PositionKind));
  877. if (this.isVertexBufferUpdatable(VertexBuffer.PositionKind)) {
  878. serializationObject.positions._updatable = true;
  879. }
  880. }
  881. if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  882. serializationObject.normals = this._toNumberArray(this.getVerticesData(VertexBuffer.NormalKind));
  883. if (this.isVertexBufferUpdatable(VertexBuffer.NormalKind)) {
  884. serializationObject.normals._updatable = true;
  885. }
  886. }
  887. if (this.isVerticesDataPresent(VertexBuffer.TangentKind)) {
  888. serializationObject.tangents = this._toNumberArray(this.getVerticesData(VertexBuffer.TangentKind));
  889. if (this.isVertexBufferUpdatable(VertexBuffer.TangentKind)) {
  890. serializationObject.tangents._updatable = true;
  891. }
  892. }
  893. if (this.isVerticesDataPresent(VertexBuffer.UVKind)) {
  894. serializationObject.uvs = this._toNumberArray(this.getVerticesData(VertexBuffer.UVKind));
  895. if (this.isVertexBufferUpdatable(VertexBuffer.UVKind)) {
  896. serializationObject.uvs._updatable = true;
  897. }
  898. }
  899. if (this.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
  900. serializationObject.uvs2 = this._toNumberArray(this.getVerticesData(VertexBuffer.UV2Kind));
  901. if (this.isVertexBufferUpdatable(VertexBuffer.UV2Kind)) {
  902. serializationObject.uvs2._updatable = true;
  903. }
  904. }
  905. if (this.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
  906. serializationObject.uvs3 = this._toNumberArray(this.getVerticesData(VertexBuffer.UV3Kind));
  907. if (this.isVertexBufferUpdatable(VertexBuffer.UV3Kind)) {
  908. serializationObject.uvs3._updatable = true;
  909. }
  910. }
  911. if (this.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
  912. serializationObject.uvs4 = this._toNumberArray(this.getVerticesData(VertexBuffer.UV4Kind));
  913. if (this.isVertexBufferUpdatable(VertexBuffer.UV4Kind)) {
  914. serializationObject.uvs4._updatable = true;
  915. }
  916. }
  917. if (this.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
  918. serializationObject.uvs5 = this._toNumberArray(this.getVerticesData(VertexBuffer.UV5Kind));
  919. if (this.isVertexBufferUpdatable(VertexBuffer.UV5Kind)) {
  920. serializationObject.uvs5._updatable = true;
  921. }
  922. }
  923. if (this.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
  924. serializationObject.uvs6 = this._toNumberArray(this.getVerticesData(VertexBuffer.UV6Kind));
  925. if (this.isVertexBufferUpdatable(VertexBuffer.UV6Kind)) {
  926. serializationObject.uvs6._updatable = true;
  927. }
  928. }
  929. if (this.isVerticesDataPresent(VertexBuffer.ColorKind)) {
  930. serializationObject.colors = this._toNumberArray(this.getVerticesData(VertexBuffer.ColorKind));
  931. if (this.isVertexBufferUpdatable(VertexBuffer.ColorKind)) {
  932. serializationObject.colors._updatable = true;
  933. }
  934. }
  935. if (this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
  936. serializationObject.matricesIndices = this._toNumberArray(this.getVerticesData(VertexBuffer.MatricesIndicesKind));
  937. serializationObject.matricesIndices._isExpanded = true;
  938. if (this.isVertexBufferUpdatable(VertexBuffer.MatricesIndicesKind)) {
  939. serializationObject.matricesIndices._updatable = true;
  940. }
  941. }
  942. if (this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
  943. serializationObject.matricesWeights = this._toNumberArray(this.getVerticesData(VertexBuffer.MatricesWeightsKind));
  944. if (this.isVertexBufferUpdatable(VertexBuffer.MatricesWeightsKind)) {
  945. serializationObject.matricesWeights._updatable = true;
  946. }
  947. }
  948. serializationObject.indices = this._toNumberArray(this.getIndices());
  949. return serializationObject;
  950. }
  951. // Statics
  952. /**
  953. * Extracts a clone of a mesh geometry
  954. * @param mesh defines the source mesh
  955. * @param id defines the unique ID of the new geometry object
  956. * @returns the new geometry object
  957. */
  958. static ExtractFromMesh(mesh, id) {
  959. const geometry = mesh._geometry;
  960. if (!geometry) {
  961. return null;
  962. }
  963. return geometry.copy(id);
  964. }
  965. /**
  966. * You should now use Tools.RandomId(), this method is still here for legacy reasons.
  967. * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
  968. * Be aware Math.random() could cause collisions, but:
  969. * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
  970. * @returns a string containing a new GUID
  971. */
  972. static RandomId() {
  973. return Tools.RandomId();
  974. }
  975. static _GetGeometryByLoadedUniqueId(uniqueId, scene) {
  976. for (let index = 0; index < scene.geometries.length; index++) {
  977. if (scene.geometries[index]._loadedUniqueId === uniqueId) {
  978. return scene.geometries[index];
  979. }
  980. }
  981. return null;
  982. }
  983. /**
  984. * @internal
  985. */
  986. static _ImportGeometry(parsedGeometry, mesh) {
  987. const scene = mesh.getScene();
  988. // Geometry
  989. const geometryUniqueId = parsedGeometry.geometryUniqueId;
  990. const geometryId = parsedGeometry.geometryId;
  991. if (geometryUniqueId || geometryId) {
  992. const geometry = geometryUniqueId ? this._GetGeometryByLoadedUniqueId(geometryUniqueId, scene) : scene.getGeometryById(geometryId);
  993. if (geometry) {
  994. geometry.applyToMesh(mesh);
  995. }
  996. }
  997. else if (parsedGeometry instanceof ArrayBuffer) {
  998. const binaryInfo = mesh._binaryInfo;
  999. if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
  1000. const positionsData = new Float32Array(parsedGeometry, binaryInfo.positionsAttrDesc.offset, binaryInfo.positionsAttrDesc.count);
  1001. mesh.setVerticesData(VertexBuffer.PositionKind, positionsData, false);
  1002. }
  1003. if (binaryInfo.normalsAttrDesc && binaryInfo.normalsAttrDesc.count > 0) {
  1004. const normalsData = new Float32Array(parsedGeometry, binaryInfo.normalsAttrDesc.offset, binaryInfo.normalsAttrDesc.count);
  1005. mesh.setVerticesData(VertexBuffer.NormalKind, normalsData, false);
  1006. }
  1007. if (binaryInfo.tangetsAttrDesc && binaryInfo.tangetsAttrDesc.count > 0) {
  1008. const tangentsData = new Float32Array(parsedGeometry, binaryInfo.tangetsAttrDesc.offset, binaryInfo.tangetsAttrDesc.count);
  1009. mesh.setVerticesData(VertexBuffer.TangentKind, tangentsData, false);
  1010. }
  1011. if (binaryInfo.uvsAttrDesc && binaryInfo.uvsAttrDesc.count > 0) {
  1012. const uvsData = new Float32Array(parsedGeometry, binaryInfo.uvsAttrDesc.offset, binaryInfo.uvsAttrDesc.count);
  1013. if (CompatibilityOptions.UseOpenGLOrientationForUV) {
  1014. for (let index = 1; index < uvsData.length; index += 2) {
  1015. uvsData[index] = 1 - uvsData[index];
  1016. }
  1017. }
  1018. mesh.setVerticesData(VertexBuffer.UVKind, uvsData, false);
  1019. }
  1020. if (binaryInfo.uvs2AttrDesc && binaryInfo.uvs2AttrDesc.count > 0) {
  1021. const uvs2Data = new Float32Array(parsedGeometry, binaryInfo.uvs2AttrDesc.offset, binaryInfo.uvs2AttrDesc.count);
  1022. if (CompatibilityOptions.UseOpenGLOrientationForUV) {
  1023. for (let index = 1; index < uvs2Data.length; index += 2) {
  1024. uvs2Data[index] = 1 - uvs2Data[index];
  1025. }
  1026. }
  1027. mesh.setVerticesData(VertexBuffer.UV2Kind, uvs2Data, false);
  1028. }
  1029. if (binaryInfo.uvs3AttrDesc && binaryInfo.uvs3AttrDesc.count > 0) {
  1030. const uvs3Data = new Float32Array(parsedGeometry, binaryInfo.uvs3AttrDesc.offset, binaryInfo.uvs3AttrDesc.count);
  1031. if (CompatibilityOptions.UseOpenGLOrientationForUV) {
  1032. for (let index = 1; index < uvs3Data.length; index += 2) {
  1033. uvs3Data[index] = 1 - uvs3Data[index];
  1034. }
  1035. }
  1036. mesh.setVerticesData(VertexBuffer.UV3Kind, uvs3Data, false);
  1037. }
  1038. if (binaryInfo.uvs4AttrDesc && binaryInfo.uvs4AttrDesc.count > 0) {
  1039. const uvs4Data = new Float32Array(parsedGeometry, binaryInfo.uvs4AttrDesc.offset, binaryInfo.uvs4AttrDesc.count);
  1040. if (CompatibilityOptions.UseOpenGLOrientationForUV) {
  1041. for (let index = 1; index < uvs4Data.length; index += 2) {
  1042. uvs4Data[index] = 1 - uvs4Data[index];
  1043. }
  1044. }
  1045. mesh.setVerticesData(VertexBuffer.UV4Kind, uvs4Data, false);
  1046. }
  1047. if (binaryInfo.uvs5AttrDesc && binaryInfo.uvs5AttrDesc.count > 0) {
  1048. const uvs5Data = new Float32Array(parsedGeometry, binaryInfo.uvs5AttrDesc.offset, binaryInfo.uvs5AttrDesc.count);
  1049. if (CompatibilityOptions.UseOpenGLOrientationForUV) {
  1050. for (let index = 1; index < uvs5Data.length; index += 2) {
  1051. uvs5Data[index] = 1 - uvs5Data[index];
  1052. }
  1053. }
  1054. mesh.setVerticesData(VertexBuffer.UV5Kind, uvs5Data, false);
  1055. }
  1056. if (binaryInfo.uvs6AttrDesc && binaryInfo.uvs6AttrDesc.count > 0) {
  1057. const uvs6Data = new Float32Array(parsedGeometry, binaryInfo.uvs6AttrDesc.offset, binaryInfo.uvs6AttrDesc.count);
  1058. if (CompatibilityOptions.UseOpenGLOrientationForUV) {
  1059. for (let index = 1; index < uvs6Data.length; index += 2) {
  1060. uvs6Data[index] = 1 - uvs6Data[index];
  1061. }
  1062. }
  1063. mesh.setVerticesData(VertexBuffer.UV6Kind, uvs6Data, false);
  1064. }
  1065. if (binaryInfo.colorsAttrDesc && binaryInfo.colorsAttrDesc.count > 0) {
  1066. const colorsData = new Float32Array(parsedGeometry, binaryInfo.colorsAttrDesc.offset, binaryInfo.colorsAttrDesc.count);
  1067. mesh.setVerticesData(VertexBuffer.ColorKind, colorsData, false, binaryInfo.colorsAttrDesc.stride);
  1068. }
  1069. if (binaryInfo.matricesIndicesAttrDesc && binaryInfo.matricesIndicesAttrDesc.count > 0) {
  1070. const matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesAttrDesc.offset, binaryInfo.matricesIndicesAttrDesc.count);
  1071. const floatIndices = [];
  1072. for (let i = 0; i < matricesIndicesData.length; i++) {
  1073. const index = matricesIndicesData[i];
  1074. floatIndices.push(index & 0x000000ff);
  1075. floatIndices.push((index & 0x0000ff00) >> 8);
  1076. floatIndices.push((index & 0x00ff0000) >> 16);
  1077. floatIndices.push((index >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
  1078. }
  1079. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, false);
  1080. }
  1081. if (binaryInfo.matricesIndicesExtraAttrDesc && binaryInfo.matricesIndicesExtraAttrDesc.count > 0) {
  1082. const matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesExtraAttrDesc.offset, binaryInfo.matricesIndicesExtraAttrDesc.count);
  1083. const floatIndices = [];
  1084. for (let i = 0; i < matricesIndicesData.length; i++) {
  1085. const index = matricesIndicesData[i];
  1086. floatIndices.push(index & 0x000000ff);
  1087. floatIndices.push((index & 0x0000ff00) >> 8);
  1088. floatIndices.push((index & 0x00ff0000) >> 16);
  1089. floatIndices.push((index >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
  1090. }
  1091. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, false);
  1092. }
  1093. if (binaryInfo.matricesWeightsAttrDesc && binaryInfo.matricesWeightsAttrDesc.count > 0) {
  1094. const matricesWeightsData = new Float32Array(parsedGeometry, binaryInfo.matricesWeightsAttrDesc.offset, binaryInfo.matricesWeightsAttrDesc.count);
  1095. mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, matricesWeightsData, false);
  1096. }
  1097. if (binaryInfo.indicesAttrDesc && binaryInfo.indicesAttrDesc.count > 0) {
  1098. const indicesData = new Int32Array(parsedGeometry, binaryInfo.indicesAttrDesc.offset, binaryInfo.indicesAttrDesc.count);
  1099. mesh.setIndices(indicesData, null);
  1100. }
  1101. if (binaryInfo.subMeshesAttrDesc && binaryInfo.subMeshesAttrDesc.count > 0) {
  1102. const subMeshesData = new Int32Array(parsedGeometry, binaryInfo.subMeshesAttrDesc.offset, binaryInfo.subMeshesAttrDesc.count * 5);
  1103. mesh.subMeshes = [];
  1104. for (let i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
  1105. const materialIndex = subMeshesData[i * 5 + 0];
  1106. const verticesStart = subMeshesData[i * 5 + 1];
  1107. const verticesCount = subMeshesData[i * 5 + 2];
  1108. const indexStart = subMeshesData[i * 5 + 3];
  1109. const indexCount = subMeshesData[i * 5 + 4];
  1110. SubMesh.AddToMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh);
  1111. }
  1112. }
  1113. }
  1114. else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
  1115. mesh.setVerticesData(VertexBuffer.PositionKind, parsedGeometry.positions, parsedGeometry.positions._updatable);
  1116. mesh.setVerticesData(VertexBuffer.NormalKind, parsedGeometry.normals, parsedGeometry.normals._updatable);
  1117. if (parsedGeometry.tangents) {
  1118. mesh.setVerticesData(VertexBuffer.TangentKind, parsedGeometry.tangents, parsedGeometry.tangents._updatable);
  1119. }
  1120. if (parsedGeometry.uvs) {
  1121. mesh.setVerticesData(VertexBuffer.UVKind, parsedGeometry.uvs, parsedGeometry.uvs._updatable);
  1122. }
  1123. if (parsedGeometry.uvs2) {
  1124. mesh.setVerticesData(VertexBuffer.UV2Kind, parsedGeometry.uvs2, parsedGeometry.uvs2._updatable);
  1125. }
  1126. if (parsedGeometry.uvs3) {
  1127. mesh.setVerticesData(VertexBuffer.UV3Kind, parsedGeometry.uvs3, parsedGeometry.uvs3._updatable);
  1128. }
  1129. if (parsedGeometry.uvs4) {
  1130. mesh.setVerticesData(VertexBuffer.UV4Kind, parsedGeometry.uvs4, parsedGeometry.uvs4._updatable);
  1131. }
  1132. if (parsedGeometry.uvs5) {
  1133. mesh.setVerticesData(VertexBuffer.UV5Kind, parsedGeometry.uvs5, parsedGeometry.uvs5._updatable);
  1134. }
  1135. if (parsedGeometry.uvs6) {
  1136. mesh.setVerticesData(VertexBuffer.UV6Kind, parsedGeometry.uvs6, parsedGeometry.uvs6._updatable);
  1137. }
  1138. if (parsedGeometry.colors) {
  1139. mesh.setVerticesData(VertexBuffer.ColorKind, Color4.CheckColors4(parsedGeometry.colors, parsedGeometry.positions.length / 3), parsedGeometry.colors._updatable);
  1140. }
  1141. if (parsedGeometry.matricesIndices) {
  1142. if (!parsedGeometry.matricesIndices._isExpanded) {
  1143. const floatIndices = [];
  1144. for (let i = 0; i < parsedGeometry.matricesIndices.length; i++) {
  1145. const matricesIndex = parsedGeometry.matricesIndices[i];
  1146. floatIndices.push(matricesIndex & 0x000000ff);
  1147. floatIndices.push((matricesIndex & 0x0000ff00) >> 8);
  1148. floatIndices.push((matricesIndex & 0x00ff0000) >> 16);
  1149. floatIndices.push((matricesIndex >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
  1150. }
  1151. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, parsedGeometry.matricesIndices._updatable);
  1152. }
  1153. else {
  1154. delete parsedGeometry.matricesIndices._isExpanded;
  1155. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, parsedGeometry.matricesIndices._updatable);
  1156. }
  1157. }
  1158. if (parsedGeometry.matricesIndicesExtra) {
  1159. if (!parsedGeometry.matricesIndicesExtra._isExpanded) {
  1160. const floatIndices = [];
  1161. for (let i = 0; i < parsedGeometry.matricesIndicesExtra.length; i++) {
  1162. const matricesIndex = parsedGeometry.matricesIndicesExtra[i];
  1163. floatIndices.push(matricesIndex & 0x000000ff);
  1164. floatIndices.push((matricesIndex & 0x0000ff00) >> 8);
  1165. floatIndices.push((matricesIndex & 0x00ff0000) >> 16);
  1166. floatIndices.push((matricesIndex >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
  1167. }
  1168. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, parsedGeometry.matricesIndicesExtra._updatable);
  1169. }
  1170. else {
  1171. delete parsedGeometry.matricesIndices._isExpanded;
  1172. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, parsedGeometry.matricesIndicesExtra, parsedGeometry.matricesIndicesExtra._updatable);
  1173. }
  1174. }
  1175. if (parsedGeometry.matricesWeights) {
  1176. Geometry._CleanMatricesWeights(parsedGeometry, mesh);
  1177. mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, parsedGeometry.matricesWeights._updatable);
  1178. }
  1179. if (parsedGeometry.matricesWeightsExtra) {
  1180. mesh.setVerticesData(VertexBuffer.MatricesWeightsExtraKind, parsedGeometry.matricesWeightsExtra, parsedGeometry.matricesWeights._updatable);
  1181. }
  1182. mesh.setIndices(parsedGeometry.indices, null);
  1183. }
  1184. // SubMeshes
  1185. if (parsedGeometry.subMeshes) {
  1186. mesh.subMeshes = [];
  1187. for (let subIndex = 0; subIndex < parsedGeometry.subMeshes.length; subIndex++) {
  1188. const parsedSubMesh = parsedGeometry.subMeshes[subIndex];
  1189. SubMesh.AddToMesh(parsedSubMesh.materialIndex, parsedSubMesh.verticesStart, parsedSubMesh.verticesCount, parsedSubMesh.indexStart, parsedSubMesh.indexCount, mesh);
  1190. }
  1191. }
  1192. // Flat shading
  1193. if (mesh._shouldGenerateFlatShading) {
  1194. mesh.convertToFlatShadedMesh();
  1195. mesh._shouldGenerateFlatShading = false;
  1196. }
  1197. // Update
  1198. mesh.computeWorldMatrix(true);
  1199. scene.onMeshImportedObservable.notifyObservers(mesh);
  1200. }
  1201. static _CleanMatricesWeights(parsedGeometry, mesh) {
  1202. const epsilon = 1e-3;
  1203. if (!SceneLoaderFlags.CleanBoneMatrixWeights) {
  1204. return;
  1205. }
  1206. let noInfluenceBoneIndex = 0.0;
  1207. if (parsedGeometry.skeletonId > -1) {
  1208. const skeleton = mesh.getScene().getLastSkeletonById(parsedGeometry.skeletonId);
  1209. if (!skeleton) {
  1210. return;
  1211. }
  1212. noInfluenceBoneIndex = skeleton.bones.length;
  1213. }
  1214. else {
  1215. return;
  1216. }
  1217. const matricesIndices = mesh.getVerticesData(VertexBuffer.MatricesIndicesKind);
  1218. const matricesIndicesExtra = mesh.getVerticesData(VertexBuffer.MatricesIndicesExtraKind);
  1219. const matricesWeights = parsedGeometry.matricesWeights;
  1220. const matricesWeightsExtra = parsedGeometry.matricesWeightsExtra;
  1221. const influencers = parsedGeometry.numBoneInfluencer;
  1222. const size = matricesWeights.length;
  1223. for (let i = 0; i < size; i += 4) {
  1224. let weight = 0.0;
  1225. let firstZeroWeight = -1;
  1226. for (let j = 0; j < 4; j++) {
  1227. const w = matricesWeights[i + j];
  1228. weight += w;
  1229. if (w < epsilon && firstZeroWeight < 0) {
  1230. firstZeroWeight = j;
  1231. }
  1232. }
  1233. if (matricesWeightsExtra) {
  1234. for (let j = 0; j < 4; j++) {
  1235. const w = matricesWeightsExtra[i + j];
  1236. weight += w;
  1237. if (w < epsilon && firstZeroWeight < 0) {
  1238. firstZeroWeight = j + 4;
  1239. }
  1240. }
  1241. }
  1242. if (firstZeroWeight < 0 || firstZeroWeight > influencers - 1) {
  1243. firstZeroWeight = influencers - 1;
  1244. }
  1245. if (weight > epsilon) {
  1246. const mweight = 1.0 / weight;
  1247. for (let j = 0; j < 4; j++) {
  1248. matricesWeights[i + j] *= mweight;
  1249. }
  1250. if (matricesWeightsExtra) {
  1251. for (let j = 0; j < 4; j++) {
  1252. matricesWeightsExtra[i + j] *= mweight;
  1253. }
  1254. }
  1255. }
  1256. else {
  1257. if (firstZeroWeight >= 4) {
  1258. matricesWeightsExtra[i + firstZeroWeight - 4] = 1.0 - weight;
  1259. matricesIndicesExtra[i + firstZeroWeight - 4] = noInfluenceBoneIndex;
  1260. }
  1261. else {
  1262. matricesWeights[i + firstZeroWeight] = 1.0 - weight;
  1263. matricesIndices[i + firstZeroWeight] = noInfluenceBoneIndex;
  1264. }
  1265. }
  1266. }
  1267. mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, matricesIndices);
  1268. if (parsedGeometry.matricesWeightsExtra) {
  1269. mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, matricesIndicesExtra);
  1270. }
  1271. }
  1272. /**
  1273. * Create a new geometry from persisted data (Using .babylon file format)
  1274. * @param parsedVertexData defines the persisted data
  1275. * @param scene defines the hosting scene
  1276. * @param rootUrl defines the root url to use to load assets (like delayed data)
  1277. * @returns the new geometry object
  1278. */
  1279. static Parse(parsedVertexData, scene, rootUrl) {
  1280. const geometry = new Geometry(parsedVertexData.id, scene, undefined, parsedVertexData.updatable);
  1281. geometry._loadedUniqueId = parsedVertexData.uniqueId;
  1282. if (Tags) {
  1283. Tags.AddTagsTo(geometry, parsedVertexData.tags);
  1284. }
  1285. if (parsedVertexData.delayLoadingFile) {
  1286. geometry.delayLoadState = 4;
  1287. geometry.delayLoadingFile = rootUrl + parsedVertexData.delayLoadingFile;
  1288. geometry._boundingInfo = new BoundingInfo(Vector3.FromArray(parsedVertexData.boundingBoxMinimum), Vector3.FromArray(parsedVertexData.boundingBoxMaximum));
  1289. geometry._delayInfo = [];
  1290. if (parsedVertexData.hasUVs) {
  1291. geometry._delayInfo.push(VertexBuffer.UVKind);
  1292. }
  1293. if (parsedVertexData.hasUVs2) {
  1294. geometry._delayInfo.push(VertexBuffer.UV2Kind);
  1295. }
  1296. if (parsedVertexData.hasUVs3) {
  1297. geometry._delayInfo.push(VertexBuffer.UV3Kind);
  1298. }
  1299. if (parsedVertexData.hasUVs4) {
  1300. geometry._delayInfo.push(VertexBuffer.UV4Kind);
  1301. }
  1302. if (parsedVertexData.hasUVs5) {
  1303. geometry._delayInfo.push(VertexBuffer.UV5Kind);
  1304. }
  1305. if (parsedVertexData.hasUVs6) {
  1306. geometry._delayInfo.push(VertexBuffer.UV6Kind);
  1307. }
  1308. if (parsedVertexData.hasColors) {
  1309. geometry._delayInfo.push(VertexBuffer.ColorKind);
  1310. }
  1311. if (parsedVertexData.hasMatricesIndices) {
  1312. geometry._delayInfo.push(VertexBuffer.MatricesIndicesKind);
  1313. }
  1314. if (parsedVertexData.hasMatricesWeights) {
  1315. geometry._delayInfo.push(VertexBuffer.MatricesWeightsKind);
  1316. }
  1317. geometry._delayLoadingFunction = VertexData.ImportVertexData;
  1318. }
  1319. else {
  1320. VertexData.ImportVertexData(parsedVertexData, geometry);
  1321. }
  1322. scene.pushGeometry(geometry, true);
  1323. return geometry;
  1324. }
  1325. }
  1326. //# sourceMappingURL=geometry.js.map