@xeokit/xeokit-sdk 2.6.85-renderers-refactor-v2 → 2.6.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/dist/xeokit-sdk.cjs.js +44618 -13007
  2. package/dist/xeokit-sdk.es.js +44617 -13008
  3. package/dist/xeokit-sdk.es5.js +3488 -1387
  4. package/dist/xeokit-sdk.min.cjs.js +8 -8
  5. package/dist/xeokit-sdk.min.es.js +8 -8
  6. package/dist/xeokit-sdk.min.es5.js +7 -7
  7. package/package.json +1 -1
  8. package/src/plugins/lib/html/MenuEvent.js +2 -2
  9. package/src/viewer/Viewer.js +103 -55
  10. package/src/viewer/scene/canvas/Canvas.js +43 -3
  11. package/src/viewer/scene/geometry/ReadableGeometry.js +25 -0
  12. package/src/viewer/scene/lights/CubeTexture.js +13 -0
  13. package/src/viewer/scene/lights/DirLight.js +1 -2
  14. package/src/viewer/scene/lights/PointLight.js +1 -2
  15. package/src/viewer/scene/materials/Texture.js +9 -0
  16. package/src/viewer/scene/math/rtcCoords.js +38 -1
  17. package/src/viewer/scene/mesh/Mesh.js +212 -454
  18. package/src/viewer/scene/mesh/draw/DrawRenderer.js +998 -0
  19. package/src/viewer/scene/mesh/draw/DrawShaderSource.js +1504 -305
  20. package/src/viewer/scene/mesh/emphasis/EmphasisEdgesRenderer.js +259 -0
  21. package/src/viewer/scene/mesh/emphasis/EmphasisEdgesShaderSource.js +160 -0
  22. package/src/viewer/scene/mesh/emphasis/EmphasisFillRenderer.js +286 -0
  23. package/src/viewer/scene/mesh/emphasis/EmphasisFillShaderSource.js +263 -0
  24. package/src/viewer/scene/mesh/occlusion/OcclusionRenderer.js +221 -0
  25. package/src/viewer/scene/mesh/occlusion/OcclusionShaderSource.js +158 -9
  26. package/src/viewer/scene/mesh/pick/PickMeshRenderer.js +223 -0
  27. package/src/viewer/scene/mesh/pick/PickMeshShaderSource.js +151 -21
  28. package/src/viewer/scene/mesh/pick/PickTriangleRenderer.js +200 -0
  29. package/src/viewer/scene/mesh/pick/PickTriangleShaderSource.js +124 -12
  30. package/src/viewer/scene/mesh/shadow/ShadowRenderer.js +214 -0
  31. package/src/viewer/scene/mesh/shadow/ShadowShaderSource.js +97 -22
  32. package/src/viewer/scene/model/RENDER_PASSES.js +34 -0
  33. package/src/viewer/scene/model/SceneModel.js +861 -245
  34. package/src/viewer/scene/model/SceneModelEntity.js +4 -4
  35. package/src/viewer/scene/model/SceneModelMesh.js +3 -3
  36. package/src/viewer/scene/model/dtx/BindableDataTexture.js +31 -0
  37. package/src/viewer/scene/model/dtx/lines/DTXLinesBuffer.js +27 -0
  38. package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +897 -0
  39. package/src/viewer/scene/model/dtx/lines/DTXLinesState.js +46 -0
  40. package/src/viewer/scene/model/dtx/lines/DTXLinesTextureFactory.js +411 -0
  41. package/src/viewer/scene/model/dtx/lines/dataTextureRamStats.js +49 -0
  42. package/src/viewer/scene/model/dtx/lines/rebucketPositions.js +208 -0
  43. package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesColorRenderer.js +389 -0
  44. package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesRenderers.js +65 -0
  45. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1399 -0
  46. package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesBuffer.js +46 -0
  47. package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesState.js +250 -0
  48. package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesTextureFactory.js +518 -0
  49. package/src/viewer/scene/model/dtx/triangles/lib/dataTextureRamStats.js +54 -0
  50. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +639 -0
  51. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesDepthRenderer.js +464 -0
  52. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesColorRenderer.js +423 -0
  53. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesRenderer.js +431 -0
  54. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesNormalsRenderer.js +345 -0
  55. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesOcclusionRenderer.js +436 -0
  56. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickDepthRenderer.js +466 -0
  57. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickMeshRenderer.js +437 -0
  58. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsFlatRenderer.js +460 -0
  59. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsRenderer.js +437 -0
  60. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesRenderers.js +307 -0
  61. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSilhouetteRenderer.js +472 -0
  62. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +474 -0
  63. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +435 -0
  64. package/src/viewer/scene/model/vbo/ScratchMemory.js +63 -0
  65. package/src/viewer/scene/model/vbo/VBORenderer.js +664 -0
  66. package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +704 -0
  67. package/src/viewer/scene/model/vbo/batching/lines/lib/VBOBatchingLinesBuffer.js +19 -0
  68. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLineSnapInitRenderer.js +318 -0
  69. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesColorRenderer.js +114 -0
  70. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesRenderers.js +99 -0
  71. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSilhouetteRenderer.js +124 -0
  72. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapInitRenderer.js +313 -0
  73. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +311 -0
  74. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOSceneModelLineBatchingRenderer.js +24 -0
  75. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +688 -0
  76. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsRenderer.js +24 -0
  77. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsColorRenderer.js +168 -0
  78. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsOcclusionRenderer.js +136 -0
  79. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickDepthRenderer.js +156 -0
  80. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickMeshRenderer.js +148 -0
  81. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsRenderers.js +144 -0
  82. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsShadowRenderer.js +107 -0
  83. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSilhouetteRenderer.js +146 -0
  84. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapInitRenderer.js +315 -0
  85. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapRenderer.js +305 -0
  86. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js +24 -0
  87. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +1346 -0
  88. package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesColorRenderer.js +131 -0
  89. package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesEmphasisRenderer.js +135 -0
  90. package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesRenderer.js +12 -0
  91. package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +403 -0
  92. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +35 -0
  93. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +252 -0
  94. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +294 -0
  95. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesDepthRenderer.js +115 -0
  96. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +246 -0
  97. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesNormalsRenderer.js +139 -0
  98. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesOcclusionRenderer.js +125 -0
  99. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPBRRenderer.js +561 -0
  100. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickDepthRenderer.js +144 -0
  101. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickMeshRenderer.js +130 -0
  102. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +121 -0
  103. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsRenderer.js +131 -0
  104. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesShadowRenderer.js +107 -0
  105. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSilhouetteRenderer.js +144 -0
  106. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapInitRenderer.js +313 -0
  107. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +312 -0
  108. package/src/viewer/scene/model/vbo/float16.js +760 -0
  109. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +711 -0
  110. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesColorRenderer.js +148 -0
  111. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderer.js +26 -0
  112. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderers.js +139 -0
  113. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSilhouetteRenderer.js +127 -0
  114. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapInitRenderer.js +308 -0
  115. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +299 -0
  116. package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +733 -0
  117. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsColorRenderer.js +174 -0
  118. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsDepthRenderer.js +156 -0
  119. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsOcclusionRenderer.js +149 -0
  120. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickDepthRenderer.js +170 -0
  121. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickMeshRenderer.js +152 -0
  122. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderer.js +26 -0
  123. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderers.js +174 -0
  124. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsShadowRenderer.js +119 -0
  125. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSilhouetteRenderer.js +154 -0
  126. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapInitRenderer.js +307 -0
  127. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapRenderer.js +293 -0
  128. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingTrianglesRenderer.js +150 -0
  129. package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +1289 -0
  130. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesColorRenderer.js +135 -0
  131. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesEmphasisRenderer.js +137 -0
  132. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesRenderer.js +12 -0
  133. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +403 -0
  134. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +267 -0
  135. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +299 -0
  136. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesDepthRenderer.js +126 -0
  137. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +255 -0
  138. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatNormalsRenderer.js +130 -0
  139. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +32 -0
  140. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesNormalsRenderer.js +138 -0
  141. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesOcclusionRenderer.js +128 -0
  142. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPBRRenderer.js +561 -0
  143. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickDepthRenderer.js +149 -0
  144. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickMeshRenderer.js +136 -0
  145. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +130 -0
  146. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsRenderer.js +145 -0
  147. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesShadowRenderer.js +113 -0
  148. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSilhouetteRenderer.js +148 -0
  149. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapInitRenderer.js +319 -0
  150. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +310 -0
  151. package/src/viewer/scene/scene/Scene.js +38 -21
  152. package/src/viewer/scene/webgl/ArrayBuf.js +20 -5
  153. package/src/viewer/scene/webgl/Attribute.js +23 -0
  154. package/src/viewer/scene/webgl/FrameContext.js +86 -14
  155. package/src/viewer/scene/webgl/Program.js +181 -0
  156. package/src/viewer/scene/webgl/RenderBuffer.js +262 -62
  157. package/src/viewer/scene/webgl/RenderBufferManager.js +34 -0
  158. package/src/viewer/scene/webgl/Renderer.js +843 -880
  159. package/src/viewer/scene/webgl/Sampler.js +18 -0
  160. package/src/viewer/scene/webgl/Shader.js +49 -0
  161. package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +132 -60
  162. package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +328 -167
  163. package/src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js +324 -0
  164. package/src/viewer/scene/webgl/sao/SAOOcclusionRenderer.js +384 -0
  165. package/src/viewer/utils/os.js +9 -0
  166. package/src/viewer/scene/mesh/draw/LambertShaderSource.js +0 -35
  167. package/src/viewer/scene/mesh/emphasis/EmphasisShaderSource.js +0 -34
  168. package/src/viewer/scene/model/layer/DTXLayer.js +0 -940
  169. package/src/viewer/scene/model/layer/Layer.js +0 -786
  170. package/src/viewer/scene/model/layer/VBOLayer.js +0 -1019
  171. package/src/viewer/scene/model/layer/programs/ColorProgram.js +0 -35
  172. package/src/viewer/scene/model/layer/programs/ColorTextureProgram.js +0 -46
  173. package/src/viewer/scene/model/layer/programs/DepthProgram.js +0 -11
  174. package/src/viewer/scene/model/layer/programs/EdgesProgram.js +0 -12
  175. package/src/viewer/scene/model/layer/programs/FlatColorProgram.js +0 -24
  176. package/src/viewer/scene/model/layer/programs/OcclusionProgram.js +0 -12
  177. package/src/viewer/scene/model/layer/programs/PBRProgram.js +0 -180
  178. package/src/viewer/scene/model/layer/programs/PickDepthProgram.js +0 -30
  179. package/src/viewer/scene/model/layer/programs/PickMeshProgram.js +0 -12
  180. package/src/viewer/scene/model/layer/programs/PickNormalsProgram.js +0 -18
  181. package/src/viewer/scene/model/layer/programs/ShadowProgram.js +0 -23
  182. package/src/viewer/scene/model/layer/programs/SilhouetteProgram.js +0 -15
  183. package/src/viewer/scene/model/layer/programs/SnapProgram.js +0 -28
  184. package/src/viewer/scene/webgl/WebGLRenderer.js +0 -612
@@ -2,8 +2,15 @@ import {Component} from "../Component.js";
2
2
  import {math} from "../math/math.js";
3
3
  import {buildEdgeIndices} from '../math/buildEdgeIndices.js';
4
4
  import {SceneModelMesh} from './SceneModelMesh.js';
5
- import {DTXLayer} from './layer/DTXLayer.js';
6
- import {VBOLayer} from './layer/VBOLayer.js';
5
+ import {getScratchMemory, putScratchMemory} from "./vbo/ScratchMemory.js";
6
+ import {VBOBatchingTrianglesLayer} from './vbo/batching/triangles/VBOBatchingTrianglesLayer.js';
7
+ import {VBOInstancingTrianglesLayer} from './vbo/instancing/triangles/VBOInstancingTrianglesLayer.js';
8
+ import {VBOBatchingLinesLayer} from './vbo/batching/lines/VBOBatchingLinesLayer.js';
9
+ import {VBOInstancingLinesLayer} from './vbo/instancing/lines/VBOInstancingLinesLayer.js';
10
+ import {VBOBatchingPointsLayer} from './vbo/batching/points/VBOBatchingPointsLayer.js';
11
+ import {VBOInstancingPointsLayer} from './vbo/instancing/points/VBOInstancingPointsLayer.js';
12
+ import {DTXLinesLayer} from "./dtx/lines/DTXLinesLayer.js";
13
+ import {DTXTrianglesLayer} from "./dtx/triangles/DTXTrianglesLayer.js";
7
14
  import {ENTITY_FLAGS} from './ENTITY_FLAGS.js';
8
15
  import {RenderFlags} from "../webgl/RenderFlags.js";
9
16
  import {worldToRTCPositions} from "../math/rtcCoords.js";
@@ -1131,16 +1138,18 @@ export class SceneModel extends Component {
1131
1138
  this._enableVertexWelding = false; // Not needed for most objects, and very expensive, so disabled
1132
1139
  this._enableIndexBucketing = false; // Until fixed: https://github.com/xeokit/xeokit-sdk/issues/1204
1133
1140
 
1141
+ this._vboBatchingLayerScratchMemory = getScratchMemory();
1134
1142
  this._textureTranscoder = cfg.textureTranscoder || getKTX2TextureTranscoder(this.scene.viewer);
1135
1143
 
1136
- this._maxGeometryBatchSize = cfg.maxGeometryBatchSize ?? 5000000;
1144
+ this._maxGeometryBatchSize = cfg.maxGeometryBatchSize;
1137
1145
 
1138
1146
  this._aabb = math.collapseAABB3();
1139
1147
  this._aabbDirty = true;
1140
1148
 
1141
1149
  this._quantizationRanges = {};
1142
1150
 
1143
- this._vboLayers = {};
1151
+ this._vboInstancingLayers = {};
1152
+ this._vboBatchingLayers = {};
1144
1153
  this._dtxLayers = {};
1145
1154
 
1146
1155
  this._meshList = [];
@@ -1285,26 +1294,7 @@ export class SceneModel extends Component {
1285
1294
  }
1286
1295
  });
1287
1296
 
1288
- // Every SceneModelMesh gets at least the default TextureSet,
1289
- // which contains empty default textures filled with color
1290
- const defineTex = (texId, preloadColor) => {
1291
- return this._textures[texId] = new SceneModelTexture({
1292
- id: texId,
1293
- texture: new Texture2D({
1294
- gl: this.scene.canvas.gl,
1295
- preloadColor: preloadColor
1296
- })
1297
- });
1298
- };
1299
-
1300
- this._textureSets[DEFAULT_TEXTURE_SET_ID] = new SceneModelTextureSet({
1301
- id: DEFAULT_TEXTURE_SET_ID,
1302
- colorTexture: defineTex(DEFAULT_COLOR_TEXTURE_ID, [1, 1, 1, 1]), // [r, g, b, a]}),
1303
- metallicRoughnessTexture: defineTex(DEFAULT_METAL_ROUGH_TEXTURE_ID, [0, 1, 1, 1]), // [_, roughness, metalness, _],
1304
- normalsTexture: defineTex(DEFAULT_NORMALS_TEXTURE_ID, [0, 0, 0, 0]), // [x, y, z, _] - these must be zeros
1305
- emissiveTexture: defineTex(DEFAULT_EMISSIVE_TEXTURE_ID, [0, 0, 0, 1]), // [x, y, z, _]
1306
- occlusionTexture: defineTex(DEFAULT_OCCLUSION_TEXTURE_ID, [1, 1, 1, 1]) // [x, y, z, _]
1307
- });
1297
+ this._createDefaultTextureSet();
1308
1298
 
1309
1299
  this.visible = cfg.visible;
1310
1300
  this.culled = cfg.culled;
@@ -1326,6 +1316,60 @@ export class SceneModel extends Component {
1326
1316
  this._meshesWithDirtyMatrices[this._numMeshesWithDirtyMatrices++] = mesh;
1327
1317
  }
1328
1318
 
1319
+ _createDefaultTextureSet() {
1320
+ // Every SceneModelMesh gets at least the default TextureSet,
1321
+ // which contains empty default textures filled with color
1322
+ const defaultColorTexture = new SceneModelTexture({
1323
+ id: DEFAULT_COLOR_TEXTURE_ID,
1324
+ texture: new Texture2D({
1325
+ gl: this.scene.canvas.gl,
1326
+ preloadColor: [1, 1, 1, 1] // [r, g, b, a]})
1327
+ })
1328
+ });
1329
+ const defaultMetalRoughTexture = new SceneModelTexture({
1330
+ id: DEFAULT_METAL_ROUGH_TEXTURE_ID,
1331
+ texture: new Texture2D({
1332
+ gl: this.scene.canvas.gl,
1333
+ preloadColor: [0, 1, 1, 1] // [unused, roughness, metalness, unused]
1334
+ })
1335
+ });
1336
+ const defaultNormalsTexture = new SceneModelTexture({
1337
+ id: DEFAULT_NORMALS_TEXTURE_ID,
1338
+ texture: new Texture2D({
1339
+ gl: this.scene.canvas.gl,
1340
+ preloadColor: [0, 0, 0, 0] // [x, y, z, unused] - these must be zeros
1341
+ })
1342
+ });
1343
+ const defaultEmissiveTexture = new SceneModelTexture({
1344
+ id: DEFAULT_EMISSIVE_TEXTURE_ID,
1345
+ texture: new Texture2D({
1346
+ gl: this.scene.canvas.gl,
1347
+ preloadColor: [0, 0, 0, 1] // [x, y, z, unused]
1348
+ })
1349
+ });
1350
+ const defaultOcclusionTexture = new SceneModelTexture({
1351
+ id: DEFAULT_OCCLUSION_TEXTURE_ID,
1352
+ texture: new Texture2D({
1353
+ gl: this.scene.canvas.gl,
1354
+ preloadColor: [1, 1, 1, 1] // [x, y, z, unused]
1355
+ })
1356
+ });
1357
+ this._textures[DEFAULT_COLOR_TEXTURE_ID] = defaultColorTexture;
1358
+ this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID] = defaultMetalRoughTexture;
1359
+ this._textures[DEFAULT_NORMALS_TEXTURE_ID] = defaultNormalsTexture;
1360
+ this._textures[DEFAULT_EMISSIVE_TEXTURE_ID] = defaultEmissiveTexture;
1361
+ this._textures[DEFAULT_OCCLUSION_TEXTURE_ID] = defaultOcclusionTexture;
1362
+ this._textureSets[DEFAULT_TEXTURE_SET_ID] = new SceneModelTextureSet({
1363
+ id: DEFAULT_TEXTURE_SET_ID,
1364
+ model: this,
1365
+ colorTexture: defaultColorTexture,
1366
+ metallicRoughnessTexture: defaultMetalRoughTexture,
1367
+ normalsTexture: defaultNormalsTexture,
1368
+ emissiveTexture: defaultEmissiveTexture,
1369
+ occlusionTexture: defaultOcclusionTexture
1370
+ });
1371
+ }
1372
+
1329
1373
  //------------------------------------------------------------------------------------------------------------------
1330
1374
  // SceneModel members
1331
1375
  //------------------------------------------------------------------------------------------------------------------
@@ -2228,14 +2272,6 @@ export class SceneModel extends Component {
2228
2272
  }
2229
2273
  }
2230
2274
 
2231
- _createDefaultIndices(numIndices) {
2232
- const indices = [];
2233
- for (let i = 0; i < numIndices; i++) {
2234
- indices.push(i);
2235
- }
2236
- return indices;
2237
- }
2238
-
2239
2275
  /**
2240
2276
  * Creates a reusable geometry within this SceneModel.
2241
2277
  *
@@ -2291,7 +2327,8 @@ export class SceneModel extends Component {
2291
2327
  return null;
2292
2328
  }
2293
2329
  if (!cfg.buckets && !cfg.indices && (cfg.primitive === "triangles" || cfg.primitive === "solid" || cfg.primitive === "surface")) {
2294
- cfg.indices = this._createDefaultIndices((cfg.positions || cfg.positionsCompressed).length / 3);
2330
+ const numPositions = (cfg.positions || cfg.positionsCompressed).length / 3;
2331
+ cfg.indices = this._createDefaultIndices(numPositions);
2295
2332
  }
2296
2333
  if (!cfg.buckets && !cfg.indices && cfg.primitive !== "points") {
2297
2334
  this.error(`[createGeometry] Param expected: indices (required for '${cfg.primitive}' primitive type)`);
@@ -2543,39 +2580,74 @@ export class SceneModel extends Component {
2543
2580
  const textureSetId = cfg.id;
2544
2581
  if (textureSetId === undefined || textureSetId === null) {
2545
2582
  this.error("[createTextureSet] Config missing: id");
2546
- return false;
2583
+ return;
2547
2584
  }
2548
2585
  if (this._textureSets[textureSetId]) {
2549
2586
  this.error(`[createTextureSet] Texture set already created: ${textureSetId}`);
2550
- return false;
2587
+ return;
2551
2588
  }
2552
-
2553
- const getTexture = (cfgId, defaultKey) => {
2554
- const id = cfgId ?? defaultKey;
2555
- if (id in this._textures) {
2556
- return this._textures[id];
2557
- } else {
2558
- throw cfgId;
2589
+ let colorTexture;
2590
+ if (cfg.colorTextureId !== undefined && cfg.colorTextureId !== null) {
2591
+ colorTexture = this._textures[cfg.colorTextureId];
2592
+ if (!colorTexture) {
2593
+ this.error(`[createTextureSet] Texture not found: ${cfg.colorTextureId} - ensure that you create it first with createTexture()`);
2594
+ return;
2559
2595
  }
2560
- };
2561
-
2562
- try {
2563
- const textureSet = new SceneModelTextureSet({
2564
- id: textureSetId,
2565
- model: this,
2566
- alphaCutoff: cfg.alphaCutoff,
2567
- colorTexture: getTexture(cfg.colorTextureId, DEFAULT_COLOR_TEXTURE_ID),
2568
- metallicRoughnessTexture: getTexture(cfg.metallicRoughnessTextureId, DEFAULT_METAL_ROUGH_TEXTURE_ID),
2569
- normalsTexture: getTexture(cfg.normalsTextureId, DEFAULT_NORMALS_TEXTURE_ID),
2570
- emissiveTexture: getTexture(cfg.emissiveTextureId, DEFAULT_EMISSIVE_TEXTURE_ID),
2571
- occlusionTexture: getTexture(cfg.occlusionTextureId, DEFAULT_OCCLUSION_TEXTURE_ID)
2572
- });
2573
- this._textureSets[textureSetId] = textureSet;
2574
- return textureSet;
2575
- } catch (id) {
2576
- this.error(`[createTextureSet] Texture not found: ${id} - ensure that you create it first with createTexture()`);
2577
- return false;
2596
+ } else {
2597
+ colorTexture = this._textures[DEFAULT_COLOR_TEXTURE_ID];
2598
+ }
2599
+ let metallicRoughnessTexture;
2600
+ if (cfg.metallicRoughnessTextureId !== undefined && cfg.metallicRoughnessTextureId !== null) {
2601
+ metallicRoughnessTexture = this._textures[cfg.metallicRoughnessTextureId];
2602
+ if (!metallicRoughnessTexture) {
2603
+ this.error(`[createTextureSet] Texture not found: ${cfg.metallicRoughnessTextureId} - ensure that you create it first with createTexture()`);
2604
+ return;
2605
+ }
2606
+ } else {
2607
+ metallicRoughnessTexture = this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID];
2608
+ }
2609
+ let normalsTexture;
2610
+ if (cfg.normalsTextureId !== undefined && cfg.normalsTextureId !== null) {
2611
+ normalsTexture = this._textures[cfg.normalsTextureId];
2612
+ if (!normalsTexture) {
2613
+ this.error(`[createTextureSet] Texture not found: ${cfg.normalsTextureId} - ensure that you create it first with createTexture()`);
2614
+ return;
2615
+ }
2616
+ } else {
2617
+ normalsTexture = this._textures[DEFAULT_NORMALS_TEXTURE_ID];
2578
2618
  }
2619
+ let emissiveTexture;
2620
+ if (cfg.emissiveTextureId !== undefined && cfg.emissiveTextureId !== null) {
2621
+ emissiveTexture = this._textures[cfg.emissiveTextureId];
2622
+ if (!emissiveTexture) {
2623
+ this.error(`[createTextureSet] Texture not found: ${cfg.emissiveTextureId} - ensure that you create it first with createTexture()`);
2624
+ return;
2625
+ }
2626
+ } else {
2627
+ emissiveTexture = this._textures[DEFAULT_EMISSIVE_TEXTURE_ID];
2628
+ }
2629
+ let occlusionTexture;
2630
+ if (cfg.occlusionTextureId !== undefined && cfg.occlusionTextureId !== null) {
2631
+ occlusionTexture = this._textures[cfg.occlusionTextureId];
2632
+ if (!occlusionTexture) {
2633
+ this.error(`[createTextureSet] Texture not found: ${cfg.occlusionTextureId} - ensure that you create it first with createTexture()`);
2634
+ return;
2635
+ }
2636
+ } else {
2637
+ occlusionTexture = this._textures[DEFAULT_OCCLUSION_TEXTURE_ID];
2638
+ }
2639
+ const textureSet = new SceneModelTextureSet({
2640
+ id: textureSetId,
2641
+ model: this,
2642
+ colorTexture,
2643
+ alphaCutoff: cfg.alphaCutoff,
2644
+ metallicRoughnessTexture,
2645
+ normalsTexture,
2646
+ emissiveTexture,
2647
+ occlusionTexture
2648
+ });
2649
+ this._textureSets[textureSetId] = textureSet;
2650
+ return textureSet;
2579
2651
  }
2580
2652
 
2581
2653
  /**
@@ -2678,36 +2750,17 @@ export class SceneModel extends Component {
2678
2750
  return false;
2679
2751
  }
2680
2752
 
2681
- const geometryId = cfg.geometryId;
2682
- const instancing = geometryId !== undefined;
2683
-
2684
- if (instancing) {
2685
- if (cfg.positions || cfg.positionsCompressed || cfg.indices || cfg.edgeIndices || cfg.normals || cfg.normalsCompressed || cfg.uv || cfg.uvCompressed || cfg.positionsDecodeMatrix) {
2686
- this.error(`Mesh geometry parameters not expected when instancing a geometry (not expected: positions, positionsCompressed, indices, edgeIndices, normals, normalsCompressed, uv, uvCompressed, positionsDecodeMatrix)`);
2687
- return false;
2688
- }
2689
-
2690
- cfg.geometry = this._geometries[geometryId];
2691
- if (!cfg.geometry) {
2692
- this.error(`[createMesh] Geometry not found: ${geometryId} - ensure that you create it first with createGeometry()`);
2693
- return false;
2694
- }
2695
- } else {
2696
- cfg.primitive ??= "triangles";
2697
- }
2698
-
2699
- const primitive = instancing ? cfg.geometry.primitive : cfg.primitive;
2700
- const isTriangular = (primitive === "triangles") || (primitive === "solid") || (primitive === "surface");
2701
- const textureSetId = cfg.textureSetId;
2702
- const useDTX = this._dtxEnabled && isTriangular && (! textureSetId);
2703
-
2704
- cfg.origin = cfg.origin ? math.addVec3(this._origin, cfg.origin, math.vec3()) : this._origin;
2753
+ const instancing = (cfg.geometryId !== undefined);
2754
+ const batching = !instancing;
2705
2755
 
2706
- if (! instancing) {
2756
+ if (batching) {
2707
2757
 
2708
2758
  // Batched geometry
2709
2759
 
2710
- if (primitive !== "points" && primitive !== "lines" && primitive !== "triangles" && primitive !== "solid" && primitive !== "surface") {
2760
+ if (cfg.primitive === undefined || cfg.primitive === null) {
2761
+ cfg.primitive = "triangles";
2762
+ }
2763
+ if (cfg.primitive !== "points" && cfg.primitive !== "lines" && cfg.primitive !== "triangles" && cfg.primitive !== "solid" && cfg.primitive !== "surface") {
2711
2764
  this.error(`Unsupported value for 'primitive': '${primitive}' ('geometryId' is absent) - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'.`);
2712
2765
  return false;
2713
2766
  }
@@ -2727,19 +2780,27 @@ export class SceneModel extends Component {
2727
2780
  this.error("Param expected: 'uvCompressed' should be accompanied by `uvDecodeMatrix` ('geometryId' is absent)");
2728
2781
  return false;
2729
2782
  }
2730
- if (!cfg.buckets && !cfg.indices) {
2731
- if (isTriangular) {
2732
- cfg.indices = this._createDefaultIndices((cfg.positions || cfg.positionsCompressed).length / 3);
2733
- } else if (primitive === "lines") {
2734
- this.error(`Param expected: indices (required for '${primitive}' primitive type)`);
2735
- return false;
2736
- }
2783
+ if (!cfg.buckets && !cfg.indices && (cfg.primitive === "triangles" || cfg.primitive === "solid" || cfg.primitive === "surface")) {
2784
+ const numPositions = (cfg.positions || cfg.positionsCompressed).length / 3;
2785
+ cfg.indices = this._createDefaultIndices(numPositions);
2786
+ }
2787
+ if (!cfg.buckets && !cfg.indices && cfg.primitive !== "points") {
2788
+ cfg.indices = this._createDefaultIndices(numIndices)
2789
+ this.error(`Param expected: indices (required for '${cfg.primitive}' primitive type)`);
2790
+ return false;
2737
2791
  }
2738
2792
  if ((cfg.matrix || cfg.position || cfg.rotation || cfg.scale) && (cfg.positionsCompressed || cfg.positionsDecodeBoundary)) {
2739
2793
  this.error("Unexpected params: 'matrix', 'rotation', 'scale', 'position' not allowed with 'positionsCompressed'");
2740
2794
  return false;
2741
2795
  }
2742
2796
 
2797
+ const useDTX = (!!this._dtxEnabled && (cfg.primitive === "triangles"
2798
+ || cfg.primitive === "solid"
2799
+ || cfg.primitive === "surface"))
2800
+ && (!cfg.textureSetId);
2801
+
2802
+ cfg.origin = cfg.origin ? math.addVec3(this._origin, cfg.origin, math.vec3()) : this._origin;
2803
+
2743
2804
  // MATRIX - optional for batching
2744
2805
 
2745
2806
  if (cfg.matrix) {
@@ -2747,86 +2808,194 @@ export class SceneModel extends Component {
2747
2808
  } else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
2748
2809
  const scale = cfg.scale || DEFAULT_SCALE;
2749
2810
  const position = cfg.position || DEFAULT_POSITION;
2750
- const quaternion = (cfg.rotation
2751
- ? math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion)
2752
- : cfg.quaternion || DEFAULT_QUATERNION);
2753
- cfg.meshMatrix = math.composeMat4(position, quaternion, scale, math.mat4());
2811
+ if (cfg.rotation) {
2812
+ math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
2813
+ cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
2814
+ } else {
2815
+ cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
2816
+ }
2754
2817
  }
2755
2818
 
2756
2819
  if (cfg.positionsDecodeBoundary) {
2757
2820
  cfg.positionsDecodeMatrix = createPositionsDecodeMatrix(cfg.positionsDecodeBoundary, math.mat4());
2758
2821
  }
2759
2822
 
2760
- // RTC && COMPRESSION
2823
+ if (useDTX) {
2761
2824
 
2762
- if (cfg.positions) {
2763
- const rtcPositions = [];
2764
- const rtcNeeded = worldToRTCPositions(cfg.positions, rtcPositions, tempVec3a);
2765
- if (rtcNeeded) {
2766
- cfg.positions = rtcPositions;
2767
- cfg.origin = math.addVec3(cfg.origin, tempVec3a, math.vec3());
2825
+ // DTX
2826
+
2827
+ cfg.type = DTX;
2828
+
2829
+ // NPR
2830
+
2831
+ cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;
2832
+ cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;
2833
+
2834
+ // RTC
2835
+
2836
+ if (cfg.positions) {
2837
+ const rtcCenter = math.vec3();
2838
+ const rtcPositions = [];
2839
+ const rtcNeeded = worldToRTCPositions(cfg.positions, rtcPositions, rtcCenter);
2840
+ if (rtcNeeded) {
2841
+ cfg.positions = rtcPositions;
2842
+ cfg.origin = math.addVec3(cfg.origin, rtcCenter, rtcCenter);
2843
+ }
2768
2844
  }
2769
2845
 
2770
- const aabb = math.collapseAABB3();
2771
- if (useDTX) {
2846
+ // COMPRESSION
2847
+
2848
+ if (cfg.positions) {
2849
+ const aabb = math.collapseAABB3();
2772
2850
  cfg.positionsDecodeMatrix = math.mat4();
2773
2851
  math.expandAABB3Points3(aabb, cfg.positions);
2774
2852
  cfg.positionsCompressed = quantizePositions(cfg.positions, aabb, cfg.positionsDecodeMatrix);
2775
- } else {
2853
+ cfg.aabb = aabb;
2854
+
2855
+ } else if (cfg.positionsCompressed) {
2856
+ const aabb = math.collapseAABB3();
2857
+ math.expandAABB3Points3(aabb, cfg.positionsCompressed);
2858
+ geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);
2859
+ cfg.aabb = aabb;
2860
+
2861
+ }
2862
+ if (cfg.buckets) {
2863
+ const aabb = math.collapseAABB3();
2864
+ for (let i = 0, len = cfg.buckets.length; i < len; i++) {
2865
+ const bucket = cfg.buckets[i];
2866
+ if (bucket.positions) {
2867
+ math.expandAABB3Points3(aabb, bucket.positions);
2868
+ } else if (bucket.positionsCompressed) {
2869
+ math.expandAABB3Points3(aabb, bucket.positionsCompressed);
2870
+ }
2871
+ }
2872
+ if (cfg.positionsDecodeMatrix) {
2873
+ geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);
2874
+ }
2875
+ cfg.aabb = aabb;
2876
+ }
2877
+
2878
+ if (cfg.meshMatrix) {
2879
+ math.AABB3ToOBB3(cfg.aabb, tempOBB3);
2880
+ math.transformOBB3(cfg.meshMatrix, tempOBB3);
2881
+ math.OBB3ToAABB3(tempOBB3, cfg.aabb);
2882
+ }
2883
+
2884
+ // EDGES
2885
+
2886
+ if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === "triangles" || cfg.primitive === "solid" || cfg.primitive === "surface")) {
2887
+ if (cfg.positions) { // Faster
2888
+ cfg.edgeIndices = buildEdgeIndices(cfg.positions, cfg.indices, null, 2.0);
2889
+ } else {
2890
+ cfg.edgeIndices = buildEdgeIndices(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);
2891
+ }
2892
+ }
2893
+
2894
+ // BUCKETING
2895
+
2896
+ if (!cfg.buckets) {
2897
+ cfg.buckets = createDTXBuckets(cfg, this._enableVertexWelding && this._enableIndexBucketing);
2898
+ }
2899
+
2900
+ } else {
2901
+
2902
+ // VBO
2903
+
2904
+ cfg.type = VBO_BATCHED;
2905
+
2906
+ // PBR
2907
+
2908
+ cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : [255, 255, 255];
2909
+ cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;
2910
+ cfg.metallic = (cfg.metallic !== undefined && cfg.metallic !== null) ? Math.floor(cfg.metallic * 255) : 0;
2911
+ cfg.roughness = (cfg.roughness !== undefined && cfg.roughness !== null) ? Math.floor(cfg.roughness * 255) : 255;
2912
+
2913
+ // RTC
2914
+
2915
+ if (cfg.positions) {
2916
+ const rtcPositions = [];
2917
+ const rtcNeeded = worldToRTCPositions(cfg.positions, rtcPositions, tempVec3a);
2918
+ if (rtcNeeded) {
2919
+ cfg.positions = rtcPositions;
2920
+ cfg.origin = math.addVec3(cfg.origin, tempVec3a, math.vec3());
2921
+ }
2922
+ }
2923
+
2924
+ if (cfg.positions) {
2925
+ const aabb = math.collapseAABB3();
2776
2926
  if (cfg.meshMatrix) {
2777
2927
  math.transformPositions3(cfg.meshMatrix, cfg.positions, cfg.positions);
2778
2928
  cfg.meshMatrix = null; // Positions now baked, don't need any more
2779
2929
  }
2780
2930
  math.expandAABB3Points3(aabb, cfg.positions);
2931
+ cfg.aabb = aabb;
2932
+
2933
+ } else {
2934
+ const aabb = math.collapseAABB3();
2935
+ math.expandAABB3Points3(aabb, cfg.positionsCompressed);
2936
+ geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);
2937
+ cfg.aabb = aabb;
2781
2938
  }
2782
- cfg.aabb = aabb;
2783
- } else if (cfg.positionsCompressed) {
2784
- const aabb = math.collapseAABB3();
2785
- math.expandAABB3Points3(aabb, cfg.positionsCompressed);
2786
- geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);
2787
- cfg.aabb = aabb;
2788
- }
2789
2939
 
2790
- if (useDTX && cfg.buckets) {
2791
- const aabb = math.collapseAABB3();
2792
- cfg.buckets.forEach(bucket => {
2793
- const positions = bucket.positions || bucket.positionsCompressed;
2794
- if (positions) {
2795
- math.expandAABB3Points3(aabb, positions);
2940
+ if (cfg.meshMatrix) {
2941
+ math.AABB3ToOBB3(cfg.aabb, tempOBB3);
2942
+ math.transformOBB3(cfg.meshMatrix, tempOBB3);
2943
+ math.OBB3ToAABB3(tempOBB3, cfg.aabb);
2944
+ }
2945
+
2946
+ // EDGES
2947
+
2948
+ if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === "triangles" || cfg.primitive === "solid" || cfg.primitive === "surface")) {
2949
+ if (cfg.positions) {
2950
+ cfg.edgeIndices = buildEdgeIndices(cfg.positions, cfg.indices, null, 2.0);
2951
+ } else {
2952
+ cfg.edgeIndices = buildEdgeIndices(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);
2796
2953
  }
2797
- });
2798
- if (cfg.positionsDecodeMatrix) {
2799
- geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);
2800
2954
  }
2801
- cfg.aabb = aabb;
2802
- }
2803
2955
 
2804
- // EDGES
2956
+ // TEXTURE
2805
2957
 
2806
- if (isTriangular && (! cfg.buckets)) {
2807
- cfg.edgeIndices ||= buildEdgeIndices(cfg.positions || cfg.positionsCompressed, cfg.indices, cfg.positions ? null : cfg.positionsDecodeMatrix, 2.0);
2958
+ // cfg.textureSetId = cfg.textureSetId || DEFAULT_TEXTURE_SET_ID;
2959
+ if (cfg.textureSetId) {
2960
+ cfg.textureSet = this._textureSets[cfg.textureSetId];
2961
+ if (!cfg.textureSet) {
2962
+ this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);
2963
+ return false;
2964
+ }
2965
+ }
2808
2966
  }
2809
2967
 
2810
2968
  } else {
2811
2969
 
2812
2970
  // INSTANCING
2813
2971
 
2814
- cfg.positionsDecodeMatrix = cfg.geometry.positionsDecodeMatrix;
2972
+ if (cfg.positions || cfg.positionsCompressed || cfg.indices || cfg.edgeIndices || cfg.normals || cfg.normalsCompressed || cfg.uv || cfg.uvCompressed || cfg.positionsDecodeMatrix) {
2973
+ this.error(`Mesh geometry parameters not expected when instancing a geometry (not expected: positions, positionsCompressed, indices, edgeIndices, normals, normalsCompressed, uv, uvCompressed, positionsDecodeMatrix)`);
2974
+ return false;
2975
+ }
2976
+
2977
+ cfg.geometry = this._geometries[cfg.geometryId];
2978
+ if (!cfg.geometry) {
2979
+ this.error(`[createMesh] Geometry not found: ${cfg.geometryId} - ensure that you create it first with createGeometry()`);
2980
+ return false;
2981
+ }
2815
2982
 
2816
- cfg.aabb = math.AABB3(cfg.geometry.aabb);
2983
+ cfg.origin = cfg.origin ? math.addVec3(this._origin, cfg.origin, math.vec3()) : this._origin;
2984
+ cfg.positionsDecodeMatrix = cfg.geometry.positionsDecodeMatrix;
2817
2985
 
2818
- const transformId = cfg.transformId;
2819
- if (transformId) {
2986
+ if (cfg.transformId) {
2820
2987
 
2821
2988
  // TRANSFORM
2822
2989
 
2823
- cfg.transform = this._transforms[transformId];
2990
+ cfg.transform = this._transforms[cfg.transformId];
2824
2991
 
2825
2992
  if (!cfg.transform) {
2826
- this.error(`[createMesh] Transform not found: ${transformId} - ensure that you create it first with createTransform()`);
2993
+ this.error(`[createMesh] Transform not found: ${cfg.transformId} - ensure that you create it first with createTransform()`);
2827
2994
  return false;
2828
2995
  }
2829
2996
 
2997
+ cfg.aabb = cfg.geometry.aabb;
2998
+
2830
2999
  } else {
2831
3000
 
2832
3001
  // MATRIX
@@ -2836,66 +3005,111 @@ export class SceneModel extends Component {
2836
3005
  } else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
2837
3006
  const scale = cfg.scale || DEFAULT_SCALE;
2838
3007
  const position = cfg.position || DEFAULT_POSITION;
2839
- const quaternion = (cfg.rotation
2840
- ? math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion)
2841
- : cfg.quaternion || DEFAULT_QUATERNION);
2842
- cfg.meshMatrix = math.composeMat4(position, quaternion, scale, math.mat4());
3008
+ if (cfg.rotation) {
3009
+ math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
3010
+ cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
3011
+ } else {
3012
+ cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
3013
+ }
2843
3014
  }
3015
+
3016
+ math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);
3017
+ math.transformOBB3(cfg.meshMatrix, tempOBB3);
3018
+ cfg.aabb = math.OBB3ToAABB3(tempOBB3, math.AABB3());
2844
3019
  }
2845
- }
2846
3020
 
2847
- if (cfg.meshMatrix) {
2848
- math.AABB3ToOBB3(cfg.aabb, tempOBB3);
2849
- math.transformOBB3(cfg.meshMatrix, tempOBB3, tempOBB3);
2850
- math.OBB3ToAABB3(tempOBB3, cfg.aabb);
2851
- }
3021
+ const useDTX = (!!this._dtxEnabled
3022
+ && (cfg.geometry.primitive === "triangles"
3023
+ || cfg.geometry.primitive === "solid"
3024
+ || cfg.geometry.primitive === "surface"))
3025
+ && (!cfg.textureSetId);
2852
3026
 
2853
- cfg.color = cfg.color ? new Uint8Array(cfg.color.slice(0, 3).map(v => Math.floor(v * 255))) : defaultCompressedColor;
2854
- cfg.opacity = Math.floor((cfg.opacity ?? 1) * 255);
3027
+ if (useDTX) {
2855
3028
 
2856
- if (useDTX) {
2857
- cfg.type = DTX;
3029
+ // DTX
2858
3030
 
2859
- // BUCKETING
2860
- if (instancing) {
2861
- cfg.buckets = this._dtxBuckets[geometryId]; // lazy generated, reused
2862
- }
2863
- if (!cfg.buckets) {
2864
- cfg.buckets = createDTXBuckets(instancing ? cfg.geometry : cfg, this._enableVertexWelding, this._enableIndexBucketing);
2865
- if (instancing) {
2866
- this._dtxBuckets[geometryId] = cfg.buckets;
3031
+ cfg.type = DTX;
3032
+
3033
+ // NPR
3034
+
3035
+ cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;
3036
+ cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;
3037
+
3038
+ // BUCKETING - lazy generated, reused
3039
+
3040
+ let buckets = this._dtxBuckets[cfg.geometryId];
3041
+ if (!buckets) {
3042
+ buckets = createDTXBuckets(cfg.geometry, this._enableVertexWelding, this._enableIndexBucketing);
3043
+ this._dtxBuckets[cfg.geometryId] = buckets;
2867
3044
  }
2868
- }
3045
+ cfg.buckets = buckets;
2869
3046
 
2870
- } else {
2871
- cfg.type = instancing ? VBO_INSTANCED : VBO_BATCHED;
2872
-
2873
- // PBR
2874
- cfg.metallic = Math.floor((cfg.metallic ?? 0) * 255);
2875
- cfg.roughness = Math.floor((cfg.roughness ?? 1) * 255);
2876
-
2877
- // TEXTURE
2878
- // cfg.textureSetId = cfg.textureSetId || DEFAULT_TEXTURE_SET_ID;
2879
- if (textureSetId) {
2880
- cfg.textureSet = this._textureSets[textureSetId];
2881
- if ((! instancing) && (!cfg.textureSet)) {
2882
- this.error(`[createMesh] Texture set not found: ${textureSetId} - ensure that you create it first with createTextureSet()`);
2883
- return false;
3047
+ } else {
3048
+
3049
+ // VBO
3050
+
3051
+ cfg.type = VBO_INSTANCED;
3052
+
3053
+ // PBR
3054
+
3055
+ cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;
3056
+ cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;
3057
+ cfg.metallic = (cfg.metallic !== undefined && cfg.metallic !== null) ? Math.floor(cfg.metallic * 255) : 0;
3058
+ cfg.roughness = (cfg.roughness !== undefined && cfg.roughness !== null) ? Math.floor(cfg.roughness * 255) : 255;
3059
+
3060
+ // TEXTURE
3061
+
3062
+ if (cfg.textureSetId) {
3063
+ cfg.textureSet = this._textureSets[cfg.textureSetId];
3064
+ // if (!cfg.textureSet) {
3065
+ // this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);
3066
+ // return false;
3067
+ // }
2884
3068
  }
2885
3069
  }
2886
3070
  }
2887
3071
 
2888
3072
  cfg.numPrimitives = this._getNumPrimitives(cfg);
2889
3073
 
3074
+ return this._createMesh(cfg);
3075
+ }
3076
+
3077
+ _createDefaultIndices(numIndices) {
3078
+ const indices = [];
3079
+ for (let i = 0; i < numIndices; i++) {
3080
+ indices.push(i);
3081
+ }
3082
+ return indices;
3083
+ }
3084
+
3085
+ _createMesh(cfg) {
2890
3086
  const mesh = new SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);
2891
- const pickId = this.scene._renderer.getPickID(mesh);
2892
- mesh.pickId = pickId;
2893
- mesh.origin = math.vec3(cfg.origin);
2894
- mesh.layer = (cfg.type === DTX) ? this._getDTXLayer(cfg) : this._getVBOLayer(cfg.type === VBO_INSTANCED, cfg);
2895
- mesh.aabb = cfg.aabb;
2896
- cfg.pickColor = new Uint8Array([pickId & 0xFF, pickId >> 8 & 0xFF, pickId >> 16 & 0xFF, pickId >> 24 & 0xFF]); // Quantized pick color
3087
+ mesh.pickId = this.scene._renderer.getPickID(mesh);
3088
+ const pickId = mesh.pickId;
3089
+ const a = pickId >> 24 & 0xFF;
3090
+ const b = pickId >> 16 & 0xFF;
3091
+ const g = pickId >> 8 & 0xFF;
3092
+ const r = pickId & 0xFF;
3093
+ cfg.pickColor = new Uint8Array([r, g, b, a]); // Quantized pick color
2897
3094
  cfg.solid = (cfg.primitive === "solid");
2898
- cfg.meshMatrix = cfg.transform ? cfg.transform.worldMatrix : cfg.meshMatrix;
3095
+ mesh.origin = math.vec3(cfg.origin);
3096
+ switch (cfg.type) {
3097
+ case DTX:
3098
+ mesh.layer = this._getDTXLayer(cfg);
3099
+ mesh.aabb = cfg.aabb;
3100
+ break;
3101
+ case VBO_BATCHED:
3102
+ mesh.layer = this._getVBOBatchingLayer(cfg);
3103
+ mesh.aabb = cfg.aabb;
3104
+ break;
3105
+ case VBO_INSTANCED:
3106
+ mesh.layer = this._getVBOInstancingLayer(cfg);
3107
+ mesh.aabb = cfg.aabb;
3108
+ break;
3109
+ }
3110
+ if (cfg.transform) {
3111
+ cfg.meshMatrix = cfg.transform.worldMatrix;
3112
+ }
2899
3113
  mesh.portionId = mesh.layer.createPortion(mesh, cfg);
2900
3114
  mesh.numPrimitives = cfg.numPrimitives;
2901
3115
  this._meshes[cfg.id] = mesh;
@@ -2979,7 +3193,10 @@ export class SceneModel extends Component {
2979
3193
  case "triangles":
2980
3194
  case "solid":
2981
3195
  case "surface":
2982
- dtxLayer = new DTXLayer(this, primitive, origin);
3196
+ dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
3197
+ break;
3198
+ case "lines":
3199
+ dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
2983
3200
  break;
2984
3201
  default:
2985
3202
  return;
@@ -2990,41 +3207,204 @@ export class SceneModel extends Component {
2990
3207
  return dtxLayer;
2991
3208
  }
2992
3209
 
2993
- _getVBOLayer(instancing, cfg) {
2994
- const geometry = instancing && cfg.geometry;
2995
- const primitive = instancing ? geometry.primitive : cfg.primitive;
3210
+ _getVBOBatchingLayer(cfg) {
3211
+ const model = this;
2996
3212
  const origin = cfg.origin;
2997
- const posDecode = (! instancing) && (cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary);
2998
- const positionsDecodeHash = posDecode ? (JSON.stringify(posDecode).split("").reduce((hash, char) => (((hash << 5) - hash + char.charCodeAt(0)) | 0), 0) >>> 0).toString(16) : "-";
3213
+ const renderLayer = cfg.renderLayer || 0;
3214
+ const positionsDecodeHash = cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary ?
3215
+ this._createHashStringFromMatrix(cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)
3216
+ : "-";
2999
3217
  const textureSetId = cfg.textureSetId || "-";
3000
- const geometryId = instancing ? cfg.geometryId : "-";
3001
- const layerId = (instancing ? "instancing" : "batching") + `.${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${primitive}.${positionsDecodeHash}.${textureSetId}.${geometryId}`;
3002
-
3003
- if ((! instancing) && (layerId in this._vboLayers)) {
3004
- const layer = this._vboLayers[layerId];
3218
+ const layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${cfg.primitive}.${positionsDecodeHash}.${textureSetId}`;
3219
+ let vboBatchingLayer = this._vboBatchingLayers[layerId];
3220
+ if (vboBatchingLayer) {
3221
+ return vboBatchingLayer;
3222
+ }
3223
+ let textureSet = cfg.textureSet;
3224
+ while (!vboBatchingLayer) {
3225
+ switch (cfg.primitive) {
3226
+ case "triangles":
3227
+ // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);
3228
+ vboBatchingLayer = new VBOBatchingTrianglesLayer({
3229
+ model,
3230
+ textureSet,
3231
+ layerIndex: 0, // This is set in #finalize()
3232
+ scratchMemory: this._vboBatchingLayerScratchMemory,
3233
+ positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3234
+ uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3235
+ origin,
3236
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3237
+ solid: (cfg.primitive === "solid"),
3238
+ autoNormals: true,
3239
+ primitive: cfg.primitive
3240
+ });
3241
+ break;
3242
+ case "solid":
3243
+ // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);
3244
+ vboBatchingLayer = new VBOBatchingTrianglesLayer({
3245
+ model,
3246
+ textureSet,
3247
+ layerIndex: 0, // This is set in #finalize()
3248
+ scratchMemory: this._vboBatchingLayerScratchMemory,
3249
+ positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3250
+ uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3251
+ origin,
3252
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3253
+ solid: (cfg.primitive === "solid"),
3254
+ autoNormals: true,
3255
+ primitive: cfg.primitive
3256
+ });
3257
+ break;
3258
+ case "surface":
3259
+ // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);
3260
+ vboBatchingLayer = new VBOBatchingTrianglesLayer({
3261
+ model,
3262
+ textureSet,
3263
+ layerIndex: 0, // This is set in #finalize()
3264
+ scratchMemory: this._vboBatchingLayerScratchMemory,
3265
+ positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3266
+ uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3267
+ origin,
3268
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3269
+ solid: (cfg.primitive === "solid"),
3270
+ autoNormals: true,
3271
+ primitive: cfg.primitive
3272
+ });
3273
+ break;
3274
+ case "lines":
3275
+ // console.info(`[SceneModel ${this.id}]: creating VBOBatchingLinesLayer`);
3276
+ vboBatchingLayer = new VBOBatchingLinesLayer({
3277
+ model,
3278
+ layerIndex: 0, // This is set in #finalize()
3279
+ scratchMemory: this._vboBatchingLayerScratchMemory,
3280
+ positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3281
+ uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3282
+ origin,
3283
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3284
+ primitive: cfg.primitive
3285
+ });
3286
+ break;
3287
+ case "points":
3288
+ // console.info(`[SceneModel ${this.id}]: creating VBOBatchingPointsLayer`);
3289
+ vboBatchingLayer = new VBOBatchingPointsLayer({
3290
+ model,
3291
+ layerIndex: 0, // This is set in #finalize()
3292
+ scratchMemory: this._vboBatchingLayerScratchMemory,
3293
+ positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3294
+ uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3295
+ origin,
3296
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3297
+ primitive: cfg.primitive
3298
+ });
3299
+ break;
3300
+ }
3005
3301
  const lenPositions = cfg.positionsCompressed ? cfg.positionsCompressed.length : cfg.positions.length;
3006
- if (! layer.canCreatePortion(lenPositions, (primitive === "points") ? 0 : cfg.indices.length)) {
3007
- layer.finalize();
3008
- delete this._vboLayers[layerId];
3302
+ const canCreatePortion = (cfg.primitive === "points")
3303
+ ? vboBatchingLayer.canCreatePortion(lenPositions)
3304
+ : vboBatchingLayer.canCreatePortion(lenPositions, cfg.indices.length);
3305
+ if (!canCreatePortion) {
3306
+ vboBatchingLayer.finalize();
3307
+ delete this._vboBatchingLayers[layerId];
3308
+ vboBatchingLayer = null;
3009
3309
  }
3010
3310
  }
3311
+ this._vboBatchingLayers[layerId] = vboBatchingLayer;
3312
+ this.layerList.push(vboBatchingLayer);
3313
+ this._layersToFinalize.push(vboBatchingLayer);
3314
+ return vboBatchingLayer;
3315
+ }
3011
3316
 
3012
- if (! (layerId in this._vboLayers)) {
3013
- const layer = new VBOLayer(this, primitive, origin, {
3014
- textureSet: cfg.textureSet,
3015
- ...(instancing ? {
3016
- geometry: geometry,
3017
- } : {
3018
- maxGeometryBatchSize: this._maxGeometryBatchSize,
3019
- positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3020
- uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3021
- })
3022
- });
3023
- this.layerList.push(layer);
3024
- this._layersToFinalize.push(layer);
3025
- this._vboLayers[layerId] = layer;
3317
+ _createHashStringFromMatrix(matrix) {
3318
+ const matrixString = matrix.join('');
3319
+ let hash = 0;
3320
+ for (let i = 0; i < matrixString.length; i++) {
3321
+ const char = matrixString.charCodeAt(i);
3322
+ hash = (hash << 5) - hash + char;
3323
+ hash |= 0; // Convert to 32-bit integer
3026
3324
  }
3027
- return this._vboLayers[layerId];
3325
+ const hashString = (hash >>> 0).toString(16);
3326
+ return hashString;
3327
+ }
3328
+
3329
+ _getVBOInstancingLayer(cfg) {
3330
+ const model = this;
3331
+ const origin = cfg.origin;
3332
+ const textureSetId = cfg.textureSetId || "-";
3333
+ const geometryId = cfg.geometryId;
3334
+ const layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${textureSetId}.${geometryId}`;
3335
+ let vboInstancingLayer = this._vboInstancingLayers[layerId];
3336
+ if (vboInstancingLayer) {
3337
+ return vboInstancingLayer;
3338
+ }
3339
+ let textureSet = cfg.textureSet;
3340
+ const geometry = cfg.geometry;
3341
+ while (!vboInstancingLayer) {
3342
+ switch (geometry.primitive) {
3343
+ case "triangles":
3344
+ // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);
3345
+ vboInstancingLayer = new VBOInstancingTrianglesLayer({
3346
+ model,
3347
+ textureSet,
3348
+ geometry,
3349
+ origin,
3350
+ layerIndex: 0,
3351
+ solid: false
3352
+ });
3353
+ break;
3354
+ case "solid":
3355
+ // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);
3356
+ vboInstancingLayer = new VBOInstancingTrianglesLayer({
3357
+ model,
3358
+ textureSet,
3359
+ geometry,
3360
+ origin,
3361
+ layerIndex: 0,
3362
+ solid: true
3363
+ });
3364
+ break;
3365
+ case "surface":
3366
+ // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);
3367
+ vboInstancingLayer = new VBOInstancingTrianglesLayer({
3368
+ model,
3369
+ textureSet,
3370
+ geometry,
3371
+ origin,
3372
+ layerIndex: 0,
3373
+ solid: false
3374
+ });
3375
+ break;
3376
+ case "lines":
3377
+ // console.info(`[SceneModel ${this.id}]: creating VBOInstancingLinesLayer`);
3378
+ vboInstancingLayer = new VBOInstancingLinesLayer({
3379
+ model,
3380
+ textureSet,
3381
+ geometry,
3382
+ origin,
3383
+ layerIndex: 0
3384
+ });
3385
+ break;
3386
+ case "points":
3387
+ // console.info(`[SceneModel ${this.id}]: creating PointsInstancingLayer`);
3388
+ vboInstancingLayer = new VBOInstancingPointsLayer({
3389
+ model,
3390
+ textureSet,
3391
+ geometry,
3392
+ origin,
3393
+ layerIndex: 0
3394
+ });
3395
+ break;
3396
+ }
3397
+ // const lenPositions = geometry.positionsCompressed.length;
3398
+ // if (!vboInstancingLayer.canCreatePortion(lenPositions, geometry.indices.length)) { // FIXME: indices should be optional
3399
+ // vboInstancingLayer.finalize();
3400
+ // delete this._vboInstancingLayers[layerId];
3401
+ // vboInstancingLayer = null;
3402
+ // }
3403
+ }
3404
+ this._vboInstancingLayers[layerId] = vboInstancingLayer;
3405
+ this.layerList.push(vboInstancingLayer);
3406
+ this._layersToFinalize.push(vboInstancingLayer);
3407
+ return vboInstancingLayer;
3028
3408
  }
3029
3409
 
3030
3410
  /**
@@ -3064,22 +3444,41 @@ export class SceneModel extends Component {
3064
3444
  }
3065
3445
  if (cfg.meshIds === undefined) {
3066
3446
  this.error("Config missing: meshIds");
3067
- return null;
3447
+ return;
3068
3448
  }
3069
-
3070
- const notFalse = v => v !== false;
3071
3449
  let flags = 0;
3072
- flags |= (this._visible && notFalse(cfg.visible) && ENTITY_FLAGS.VISIBLE);
3073
- flags |= (this._pickable && notFalse(cfg.pickable) && ENTITY_FLAGS.PICKABLE);
3074
- flags |= (this._culled && notFalse(cfg.culled) && ENTITY_FLAGS.CULLED);
3075
- flags |= (this._clippable && notFalse(cfg.clippable) && ENTITY_FLAGS.CLIPPABLE);
3076
- flags |= (this._collidable && notFalse(cfg.collidable) && ENTITY_FLAGS.COLLIDABLE);
3077
- flags |= (this._xrayed && notFalse(cfg.xrayed) && ENTITY_FLAGS.XRAYED);
3078
- flags |= (this._highlighted && notFalse(cfg.highlighted) && ENTITY_FLAGS.HIGHLIGHTED);
3079
- flags |= (this._selected && notFalse(cfg.selected) && ENTITY_FLAGS.SELECTED);
3080
- flags |= (this._edges && notFalse(cfg.edges) && ENTITY_FLAGS.EDGES);
3450
+ if (this._visible && cfg.visible !== false) {
3451
+ flags = flags | ENTITY_FLAGS.VISIBLE;
3452
+ }
3453
+ if (this._pickable && cfg.pickable !== false) {
3454
+ flags = flags | ENTITY_FLAGS.PICKABLE;
3455
+ }
3456
+ if (this._culled && cfg.culled !== false) {
3457
+ flags = flags | ENTITY_FLAGS.CULLED;
3458
+ }
3459
+ if (this._clippable && cfg.clippable !== false) {
3460
+ flags = flags | ENTITY_FLAGS.CLIPPABLE;
3461
+ }
3462
+ if (this._collidable && cfg.collidable !== false) {
3463
+ flags = flags | ENTITY_FLAGS.COLLIDABLE;
3464
+ }
3465
+ if (this._edges && cfg.edges !== false) {
3466
+ flags = flags | ENTITY_FLAGS.EDGES;
3467
+ }
3468
+ if (this._xrayed && cfg.xrayed !== false) {
3469
+ flags = flags | ENTITY_FLAGS.XRAYED;
3470
+ }
3471
+ if (this._highlighted && cfg.highlighted !== false) {
3472
+ flags = flags | ENTITY_FLAGS.HIGHLIGHTED;
3473
+ }
3474
+ if (this._selected && cfg.selected !== false) {
3475
+ flags = flags | ENTITY_FLAGS.SELECTED;
3476
+ }
3081
3477
  cfg.flags = flags;
3478
+ return this._createEntity(cfg);
3479
+ }
3082
3480
 
3481
+ _createEntity(cfg) {
3083
3482
  let meshes = [];
3084
3483
  for (let i = 0, len = cfg.meshIds.length; i < len; i++) {
3085
3484
  const meshId = cfg.meshIds[i];
@@ -3127,7 +3526,8 @@ export class SceneModel extends Component {
3127
3526
  const layer = this._layersToFinalize[i];
3128
3527
  layer.finalize();
3129
3528
  }
3130
- this._vboLayers = {};
3529
+ this._vboBatchingLayers = {};
3530
+ this._vboInstancingLayers = {};
3131
3531
  this._dtxLayers = {};
3132
3532
  this._layersToFinalize = [];
3133
3533
  for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
@@ -3321,48 +3721,263 @@ export class SceneModel extends Component {
3321
3721
 
3322
3722
  // -------------- RENDERING ---------------------------------------------------------------------------------------
3323
3723
 
3724
+ /** @private */
3725
+ drawColorOpaque(frameCtx, layerList) {
3726
+ const renderFlags = this.renderFlags;
3727
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3728
+ const layerIndex = renderFlags.visibleLayers[i];
3729
+ this.layerList[layerIndex].drawColorOpaque(renderFlags, frameCtx);
3730
+ }
3731
+ }
3732
+
3733
+ /** @private */
3734
+ drawColorTransparent(frameCtx) {
3735
+ const renderFlags = this.renderFlags;
3736
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3737
+ const layerIndex = renderFlags.visibleLayers[i];
3738
+ this.layerList[layerIndex].drawColorTransparent(renderFlags, frameCtx);
3739
+ }
3740
+ }
3741
+
3742
+ /** @private */
3743
+ drawDepth(frameCtx) { // Dedicated to SAO because it skips transparent objects
3744
+ const renderFlags = this.renderFlags;
3745
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3746
+ const layerIndex = renderFlags.visibleLayers[i];
3747
+ this.layerList[layerIndex].drawDepth(renderFlags, frameCtx);
3748
+ }
3749
+ }
3750
+
3751
+ /** @private */
3752
+ drawNormals(frameCtx) { // Dedicated to SAO because it skips transparent objects
3753
+ const renderFlags = this.renderFlags;
3754
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3755
+ const layerIndex = renderFlags.visibleLayers[i];
3756
+ this.layerList[layerIndex].drawNormals(renderFlags, frameCtx);
3757
+ }
3758
+ }
3759
+
3760
+ /** @private */
3761
+ drawSilhouetteXRayed(frameCtx) {
3762
+ const renderFlags = this.renderFlags;
3763
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3764
+ const layerIndex = renderFlags.visibleLayers[i];
3765
+ this.layerList[layerIndex].drawSilhouetteXRayed(renderFlags, frameCtx);
3766
+ }
3767
+ }
3768
+
3769
+ /** @private */
3770
+ drawSilhouetteHighlighted(frameCtx) {
3771
+ const renderFlags = this.renderFlags;
3772
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3773
+ const layerIndex = renderFlags.visibleLayers[i];
3774
+ this.layerList[layerIndex].drawSilhouetteHighlighted(renderFlags, frameCtx);
3775
+ }
3776
+ }
3777
+
3778
+ /** @private */
3779
+ drawSilhouetteSelected(frameCtx) {
3780
+ const renderFlags = this.renderFlags;
3781
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3782
+ const layerIndex = renderFlags.visibleLayers[i];
3783
+ this.layerList[layerIndex].drawSilhouetteSelected(renderFlags, frameCtx);
3784
+ }
3785
+ }
3786
+
3787
+ /** @private */
3788
+ drawEdgesColorOpaque(frameCtx) {
3789
+ const renderFlags = this.renderFlags;
3790
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3791
+ const layerIndex = renderFlags.visibleLayers[i];
3792
+ this.layerList[layerIndex].drawEdgesColorOpaque(renderFlags, frameCtx);
3793
+ }
3794
+ }
3795
+
3796
+ /** @private */
3797
+ drawEdgesColorTransparent(frameCtx) {
3798
+ const renderFlags = this.renderFlags;
3799
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3800
+ const layerIndex = renderFlags.visibleLayers[i];
3801
+ this.layerList[layerIndex].drawEdgesColorTransparent(renderFlags, frameCtx);
3802
+ }
3803
+ }
3804
+
3805
+ /** @private */
3806
+ drawEdgesXRayed(frameCtx) {
3807
+ const renderFlags = this.renderFlags;
3808
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3809
+ const layerIndex = renderFlags.visibleLayers[i];
3810
+ this.layerList[layerIndex].drawEdgesXRayed(renderFlags, frameCtx);
3811
+ }
3812
+ }
3813
+
3814
+ /** @private */
3815
+ drawEdgesHighlighted(frameCtx) {
3816
+ const renderFlags = this.renderFlags;
3817
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3818
+ const layerIndex = renderFlags.visibleLayers[i];
3819
+ this.layerList[layerIndex].drawEdgesHighlighted(renderFlags, frameCtx);
3820
+ }
3821
+ }
3822
+
3823
+ /** @private */
3824
+ drawEdgesSelected(frameCtx) {
3825
+ const renderFlags = this.renderFlags;
3826
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3827
+ const layerIndex = renderFlags.visibleLayers[i];
3828
+ this.layerList[layerIndex].drawEdgesSelected(renderFlags, frameCtx);
3829
+ }
3830
+ }
3831
+
3832
+ /**
3833
+ * @private
3834
+ */
3835
+ drawOcclusion(frameCtx) {
3836
+ if (this.numVisibleLayerPortions === 0) {
3837
+ return;
3838
+ }
3839
+ const renderFlags = this.renderFlags;
3840
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3841
+ const layerIndex = renderFlags.visibleLayers[i];
3842
+ this.layerList[layerIndex].drawOcclusion(renderFlags, frameCtx);
3843
+ }
3844
+ }
3845
+
3846
+ /**
3847
+ * @private
3848
+ */
3849
+ drawShadow(frameCtx) {
3850
+ if (this.numVisibleLayerPortions === 0) {
3851
+ return;
3852
+ }
3853
+ const renderFlags = this.renderFlags;
3854
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3855
+ const layerIndex = renderFlags.visibleLayers[i];
3856
+ this.layerList[layerIndex].drawShadow(renderFlags, frameCtx);
3857
+ }
3858
+ }
3859
+
3860
+ /** @private */
3861
+ setPickMatrices(pickViewMatrix, pickProjMatrix) {
3862
+ if (this._numVisibleLayerPortions === 0) {
3863
+ return;
3864
+ }
3865
+ const renderFlags = this.renderFlags;
3866
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3867
+ const layerIndex = renderFlags.visibleLayers[i];
3868
+ const layer = this.layerList[layerIndex];
3869
+ if (layer.setPickMatrices) {
3870
+ layer.setPickMatrices(pickViewMatrix, pickProjMatrix);
3871
+ }
3872
+ }
3873
+ }
3874
+
3875
+ /** @private */
3876
+ drawPickMesh(frameCtx) {
3877
+ if (this.numVisibleLayerPortions === 0) {
3878
+ return;
3879
+ }
3880
+ const renderFlags = this.renderFlags;
3881
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3882
+ const layerIndex = renderFlags.visibleLayers[i];
3883
+ this.layerList[layerIndex].drawPickMesh(renderFlags, frameCtx);
3884
+ }
3885
+ }
3886
+
3887
+ /**
3888
+ * Called by SceneModelMesh.drawPickDepths()
3889
+ * @private
3890
+ */
3891
+ drawPickDepths(frameCtx) {
3892
+ if (this.numVisibleLayerPortions === 0) {
3893
+ return;
3894
+ }
3895
+ const renderFlags = this.renderFlags;
3896
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3897
+ const layerIndex = renderFlags.visibleLayers[i];
3898
+ this.layerList[layerIndex].drawPickDepths(renderFlags, frameCtx);
3899
+ }
3900
+ }
3324
3901
 
3325
3902
  /**
3903
+ * Called by SceneModelMesh.drawPickNormals()
3326
3904
  * @private
3327
3905
  */
3328
- _withEachVisibleLayer(testNumVisibleLayerPortions, cb) {
3329
- if (testNumVisibleLayerPortions && (this.numVisibleLayerPortions === 0)) {
3906
+ drawPickNormals(frameCtx) {
3907
+ if (this.numVisibleLayerPortions === 0) {
3330
3908
  return;
3331
3909
  }
3332
3910
  const renderFlags = this.renderFlags;
3333
3911
  for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3334
3912
  const layerIndex = renderFlags.visibleLayers[i];
3335
- cb(this.layerList[layerIndex]);
3913
+ this.layerList[layerIndex].drawPickNormals(renderFlags, frameCtx);
3336
3914
  }
3337
3915
  }
3338
3916
 
3339
- drawColorOpaque (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawColorOpaque (this.renderFlags, frameCtx)); }
3340
- drawColorTransparent (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawColorTransparent (this.renderFlags, frameCtx)); }
3341
- drawDepth (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawDepth (this.renderFlags, frameCtx)); } // Dedicated to SAO because it skips transparent objects
3342
- drawSilhouetteXRayed (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteXRayed (this.renderFlags, frameCtx)); }
3343
- drawSilhouetteHighlighted(frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteHighlighted(this.renderFlags, frameCtx)); }
3344
- drawSilhouetteSelected (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteSelected (this.renderFlags, frameCtx)); }
3345
- drawEdgesColorOpaque (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesColorOpaque (this.renderFlags, frameCtx)); }
3346
- drawEdgesColorTransparent(frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesColorTransparent(this.renderFlags, frameCtx)); }
3347
- drawEdgesXRayed (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesXRayed (this.renderFlags, frameCtx)); }
3348
- drawEdgesHighlighted (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesHighlighted (this.renderFlags, frameCtx)); }
3349
- drawEdgesSelected (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesSelected (this.renderFlags, frameCtx)); }
3350
- drawOcclusion (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawOcclusion (this.renderFlags, frameCtx)); }
3351
- drawShadow (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawShadow (this.renderFlags, frameCtx)); }
3352
- drawPickMesh (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickMesh (this.renderFlags, frameCtx)); }
3353
- drawPickDepths (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickDepths (this.renderFlags, frameCtx)); }
3354
- drawPickNormals (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickNormals (this.renderFlags, frameCtx)); }
3355
- _drawSnap (frameCtx, isSnapInit) { this._withEachVisibleLayer(true, layer => layer.drawSnap (this.renderFlags, frameCtx, isSnapInit)); }
3917
+ /**
3918
+ * @private
3919
+ */
3920
+ drawSnapInit(frameCtx) {
3921
+ if (this.numVisibleLayerPortions === 0) {
3922
+ return;
3923
+ }
3924
+ const renderFlags = this.renderFlags;
3925
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3926
+ const layerIndex = renderFlags.visibleLayers[i];
3927
+ const layer = this.layerList[layerIndex];
3928
+ if (layer.drawSnapInit) {
3929
+ frameCtx.snapPickOrigin = [0, 0, 0];
3930
+ frameCtx.snapPickCoordinateScale = [1, 1, 1];
3931
+ frameCtx.snapPickLayerNumber++;
3932
+ layer.drawSnapInit(renderFlags, frameCtx);
3933
+ frameCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {
3934
+ origin: frameCtx.snapPickOrigin.slice(),
3935
+ coordinateScale: frameCtx.snapPickCoordinateScale.slice(),
3936
+ };
3937
+ }
3938
+ }
3939
+ }
3356
3940
 
3357
- drawSnapInit(frameCtx) { this._drawSnap(frameCtx, true ); }
3358
- drawSnap (frameCtx) { this._drawSnap(frameCtx, false); }
3941
+ /**
3942
+ * @private
3943
+ */
3944
+ drawSnap(frameCtx) {
3945
+ if (this.numVisibleLayerPortions === 0) {
3946
+ return;
3947
+ }
3948
+ const renderFlags = this.renderFlags;
3949
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3950
+ const layerIndex = renderFlags.visibleLayers[i];
3951
+ const layer = this.layerList[layerIndex];
3952
+ if (layer.drawSnap) {
3953
+ frameCtx.snapPickOrigin = [0, 0, 0];
3954
+ frameCtx.snapPickCoordinateScale = [1, 1, 1];
3955
+ frameCtx.snapPickLayerNumber++;
3956
+ layer.drawSnap(renderFlags, frameCtx);
3957
+ frameCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {
3958
+ origin: frameCtx.snapPickOrigin.slice(),
3959
+ coordinateScale: frameCtx.snapPickCoordinateScale.slice(),
3960
+ };
3961
+ }
3962
+ }
3963
+ }
3359
3964
 
3360
3965
  /**
3361
3966
  * Destroys this SceneModel.
3362
3967
  */
3363
3968
  destroy() {
3364
- Object.values(this._vboLayers).forEach(l => l.destroy());
3365
- this._vboLayers = {};
3969
+ for (let layerId in this._vboBatchingLayers) {
3970
+ if (this._vboBatchingLayers.hasOwnProperty(layerId)) {
3971
+ this._vboBatchingLayers[layerId].destroy();
3972
+ }
3973
+ }
3974
+ this._vboBatchingLayers = {};
3975
+ for (let layerId in this._vboInstancingLayers) {
3976
+ if (this._vboInstancingLayers.hasOwnProperty(layerId)) {
3977
+ this._vboInstancingLayers[layerId].destroy();
3978
+ }
3979
+ }
3980
+ this._vboInstancingLayers = {};
3366
3981
  this.scene.camera.off(this._onCameraViewMatrix);
3367
3982
  this.scene.off(this._onTick);
3368
3983
  for (let i = 0, len = this.layerList.length; i < len; i++) {
@@ -3372,7 +3987,7 @@ export class SceneModel extends Component {
3372
3987
  for (let i = 0, len = this._entityList.length; i < len; i++) {
3373
3988
  this._entityList[i]._destroy();
3374
3989
  }
3375
- this._layersToFinalize = [];
3990
+ this._layersToFinalize = {};
3376
3991
  // Object.entries(this._geometries).forEach(([id, geometry]) => {
3377
3992
  // geometry.destroy();
3378
3993
  // });
@@ -3386,6 +4001,7 @@ export class SceneModel extends Component {
3386
4001
  if (this._isModel) {
3387
4002
  this.scene._deregisterModel(this);
3388
4003
  }
4004
+ putScratchMemory();
3389
4005
  super.destroy();
3390
4006
  }
3391
4007
  }