@xeokit/xeokit-sdk 2.6.91-renderers-refactor-v9 → 2.6.91

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 (182) hide show
  1. package/dist/xeokit-sdk.cjs.js +44595 -13008
  2. package/dist/xeokit-sdk.es.js +44594 -13009
  3. package/dist/xeokit-sdk.es5.js +3485 -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/viewer/Viewer.js +103 -55
  9. package/src/viewer/scene/canvas/Canvas.js +43 -3
  10. package/src/viewer/scene/geometry/ReadableGeometry.js +25 -0
  11. package/src/viewer/scene/lights/CubeTexture.js +13 -0
  12. package/src/viewer/scene/lights/DirLight.js +1 -2
  13. package/src/viewer/scene/lights/PointLight.js +1 -2
  14. package/src/viewer/scene/materials/Texture.js +9 -0
  15. package/src/viewer/scene/math/rtcCoords.js +38 -1
  16. package/src/viewer/scene/mesh/Mesh.js +212 -454
  17. package/src/viewer/scene/mesh/draw/DrawRenderer.js +998 -0
  18. package/src/viewer/scene/mesh/draw/DrawShaderSource.js +1504 -305
  19. package/src/viewer/scene/mesh/emphasis/EmphasisEdgesRenderer.js +259 -0
  20. package/src/viewer/scene/mesh/emphasis/EmphasisEdgesShaderSource.js +160 -0
  21. package/src/viewer/scene/mesh/emphasis/EmphasisFillRenderer.js +286 -0
  22. package/src/viewer/scene/mesh/emphasis/EmphasisFillShaderSource.js +263 -0
  23. package/src/viewer/scene/mesh/occlusion/OcclusionRenderer.js +221 -0
  24. package/src/viewer/scene/mesh/occlusion/OcclusionShaderSource.js +158 -9
  25. package/src/viewer/scene/mesh/pick/PickMeshRenderer.js +223 -0
  26. package/src/viewer/scene/mesh/pick/PickMeshShaderSource.js +151 -21
  27. package/src/viewer/scene/mesh/pick/PickTriangleRenderer.js +200 -0
  28. package/src/viewer/scene/mesh/pick/PickTriangleShaderSource.js +124 -12
  29. package/src/viewer/scene/mesh/shadow/ShadowRenderer.js +214 -0
  30. package/src/viewer/scene/mesh/shadow/ShadowShaderSource.js +97 -22
  31. package/src/viewer/scene/model/RENDER_PASSES.js +34 -0
  32. package/src/viewer/scene/model/SceneModel.js +852 -248
  33. package/src/viewer/scene/model/SceneModelEntity.js +4 -4
  34. package/src/viewer/scene/model/SceneModelMesh.js +3 -3
  35. package/src/viewer/scene/model/dtx/BindableDataTexture.js +31 -0
  36. package/src/viewer/scene/model/dtx/lines/DTXLinesBuffer.js +27 -0
  37. package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +897 -0
  38. package/src/viewer/scene/model/dtx/lines/DTXLinesState.js +46 -0
  39. package/src/viewer/scene/model/dtx/lines/DTXLinesTextureFactory.js +411 -0
  40. package/src/viewer/scene/model/dtx/lines/dataTextureRamStats.js +49 -0
  41. package/src/viewer/scene/model/dtx/lines/rebucketPositions.js +208 -0
  42. package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesColorRenderer.js +389 -0
  43. package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesRenderers.js +65 -0
  44. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1399 -0
  45. package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesBuffer.js +46 -0
  46. package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesState.js +250 -0
  47. package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesTextureFactory.js +518 -0
  48. package/src/viewer/scene/model/dtx/triangles/lib/dataTextureRamStats.js +54 -0
  49. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +639 -0
  50. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesDepthRenderer.js +464 -0
  51. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesColorRenderer.js +423 -0
  52. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesRenderer.js +431 -0
  53. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesNormalsRenderer.js +345 -0
  54. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesOcclusionRenderer.js +436 -0
  55. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickDepthRenderer.js +466 -0
  56. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickMeshRenderer.js +437 -0
  57. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsFlatRenderer.js +460 -0
  58. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsRenderer.js +437 -0
  59. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesRenderers.js +307 -0
  60. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSilhouetteRenderer.js +472 -0
  61. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +474 -0
  62. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +435 -0
  63. package/src/viewer/scene/model/vbo/ScratchMemory.js +63 -0
  64. package/src/viewer/scene/model/vbo/VBORenderer.js +664 -0
  65. package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +704 -0
  66. package/src/viewer/scene/model/vbo/batching/lines/lib/VBOBatchingLinesBuffer.js +19 -0
  67. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLineSnapInitRenderer.js +318 -0
  68. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesColorRenderer.js +114 -0
  69. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesRenderers.js +99 -0
  70. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSilhouetteRenderer.js +124 -0
  71. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapInitRenderer.js +313 -0
  72. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +311 -0
  73. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOSceneModelLineBatchingRenderer.js +24 -0
  74. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +688 -0
  75. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsRenderer.js +24 -0
  76. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsColorRenderer.js +168 -0
  77. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsOcclusionRenderer.js +136 -0
  78. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickDepthRenderer.js +156 -0
  79. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickMeshRenderer.js +148 -0
  80. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsRenderers.js +144 -0
  81. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsShadowRenderer.js +107 -0
  82. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSilhouetteRenderer.js +146 -0
  83. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapInitRenderer.js +315 -0
  84. package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapRenderer.js +305 -0
  85. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js +24 -0
  86. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +1346 -0
  87. package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesColorRenderer.js +131 -0
  88. package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesEmphasisRenderer.js +135 -0
  89. package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesRenderer.js +12 -0
  90. package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +403 -0
  91. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +35 -0
  92. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +252 -0
  93. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +294 -0
  94. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesDepthRenderer.js +115 -0
  95. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +246 -0
  96. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesNormalsRenderer.js +139 -0
  97. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesOcclusionRenderer.js +125 -0
  98. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPBRRenderer.js +561 -0
  99. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickDepthRenderer.js +144 -0
  100. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickMeshRenderer.js +130 -0
  101. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +121 -0
  102. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsRenderer.js +131 -0
  103. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesShadowRenderer.js +107 -0
  104. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSilhouetteRenderer.js +144 -0
  105. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapInitRenderer.js +313 -0
  106. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +312 -0
  107. package/src/viewer/scene/model/vbo/float16.js +760 -0
  108. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +711 -0
  109. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesColorRenderer.js +148 -0
  110. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderer.js +26 -0
  111. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderers.js +139 -0
  112. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSilhouetteRenderer.js +127 -0
  113. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapInitRenderer.js +308 -0
  114. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +299 -0
  115. package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +733 -0
  116. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsColorRenderer.js +174 -0
  117. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsDepthRenderer.js +156 -0
  118. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsOcclusionRenderer.js +149 -0
  119. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickDepthRenderer.js +170 -0
  120. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickMeshRenderer.js +152 -0
  121. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderer.js +26 -0
  122. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderers.js +174 -0
  123. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsShadowRenderer.js +119 -0
  124. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSilhouetteRenderer.js +154 -0
  125. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapInitRenderer.js +307 -0
  126. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapRenderer.js +293 -0
  127. package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingTrianglesRenderer.js +150 -0
  128. package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +1289 -0
  129. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesColorRenderer.js +135 -0
  130. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesEmphasisRenderer.js +137 -0
  131. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesRenderer.js +12 -0
  132. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +403 -0
  133. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +267 -0
  134. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +299 -0
  135. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesDepthRenderer.js +126 -0
  136. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +255 -0
  137. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatNormalsRenderer.js +130 -0
  138. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +32 -0
  139. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesNormalsRenderer.js +138 -0
  140. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesOcclusionRenderer.js +128 -0
  141. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPBRRenderer.js +561 -0
  142. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickDepthRenderer.js +149 -0
  143. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickMeshRenderer.js +136 -0
  144. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +130 -0
  145. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsRenderer.js +145 -0
  146. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesShadowRenderer.js +113 -0
  147. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSilhouetteRenderer.js +148 -0
  148. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapInitRenderer.js +319 -0
  149. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +310 -0
  150. package/src/viewer/scene/scene/Scene.js +38 -21
  151. package/src/viewer/scene/webgl/ArrayBuf.js +20 -5
  152. package/src/viewer/scene/webgl/Attribute.js +23 -0
  153. package/src/viewer/scene/webgl/FrameContext.js +86 -14
  154. package/src/viewer/scene/webgl/Program.js +181 -0
  155. package/src/viewer/scene/webgl/RenderBuffer.js +262 -62
  156. package/src/viewer/scene/webgl/RenderBufferManager.js +34 -0
  157. package/src/viewer/scene/webgl/Renderer.js +843 -880
  158. package/src/viewer/scene/webgl/Sampler.js +18 -0
  159. package/src/viewer/scene/webgl/Shader.js +49 -0
  160. package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +132 -60
  161. package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +328 -167
  162. package/src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js +324 -0
  163. package/src/viewer/scene/webgl/sao/SAOOcclusionRenderer.js +384 -0
  164. package/src/viewer/scene/mesh/draw/LambertShaderSource.js +0 -35
  165. package/src/viewer/scene/mesh/emphasis/EmphasisShaderSource.js +0 -34
  166. package/src/viewer/scene/model/layer/DTXLayer.js +0 -940
  167. package/src/viewer/scene/model/layer/Layer.js +0 -788
  168. package/src/viewer/scene/model/layer/VBOLayer.js +0 -1019
  169. package/src/viewer/scene/model/layer/programs/ColorProgram.js +0 -35
  170. package/src/viewer/scene/model/layer/programs/ColorTextureProgram.js +0 -46
  171. package/src/viewer/scene/model/layer/programs/DepthProgram.js +0 -11
  172. package/src/viewer/scene/model/layer/programs/EdgesProgram.js +0 -12
  173. package/src/viewer/scene/model/layer/programs/FlatColorProgram.js +0 -24
  174. package/src/viewer/scene/model/layer/programs/OcclusionProgram.js +0 -12
  175. package/src/viewer/scene/model/layer/programs/PBRProgram.js +0 -180
  176. package/src/viewer/scene/model/layer/programs/PickDepthProgram.js +0 -30
  177. package/src/viewer/scene/model/layer/programs/PickMeshProgram.js +0 -12
  178. package/src/viewer/scene/model/layer/programs/PickNormalsProgram.js +0 -18
  179. package/src/viewer/scene/model/layer/programs/ShadowProgram.js +0 -23
  180. package/src/viewer/scene/model/layer/programs/SilhouetteProgram.js +0 -15
  181. package/src/viewer/scene/model/layer/programs/SnapProgram.js +0 -29
  182. 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,45 +3207,115 @@ 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 ? this._createHashStringFromMatrix(posDecode) : "-";
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
  }
3011
-
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;
3026
- }
3027
- return this._vboLayers[layerId];
3311
+ this._vboBatchingLayers[layerId] = vboBatchingLayer;
3312
+ this.layerList.push(vboBatchingLayer);
3313
+ this._layersToFinalize.push(vboBatchingLayer);
3314
+ return vboBatchingLayer;
3028
3315
  }
3029
3316
 
3030
3317
  _createHashStringFromMatrix(matrix) {
3031
- const matrixString = matrix.join(";");
3318
+ const matrixString = matrix.join('');
3032
3319
  let hash = 0;
3033
3320
  for (let i = 0; i < matrixString.length; i++) {
3034
3321
  const char = matrixString.charCodeAt(i);
@@ -3039,6 +3326,87 @@ export class SceneModel extends Component {
3039
3326
  return hashString;
3040
3327
  }
3041
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;
3408
+ }
3409
+
3042
3410
  /**
3043
3411
  * Creates a {@link SceneModelEntity} within this SceneModel.
3044
3412
  *
@@ -3076,22 +3444,41 @@ export class SceneModel extends Component {
3076
3444
  }
3077
3445
  if (cfg.meshIds === undefined) {
3078
3446
  this.error("Config missing: meshIds");
3079
- return null;
3447
+ return;
3080
3448
  }
3081
-
3082
- const notFalse = v => v !== false;
3083
3449
  let flags = 0;
3084
- flags |= (this._visible && notFalse(cfg.visible) && ENTITY_FLAGS.VISIBLE);
3085
- flags |= (this._pickable && notFalse(cfg.pickable) && ENTITY_FLAGS.PICKABLE);
3086
- flags |= (this._culled && notFalse(cfg.culled) && ENTITY_FLAGS.CULLED);
3087
- flags |= (this._clippable && notFalse(cfg.clippable) && ENTITY_FLAGS.CLIPPABLE);
3088
- flags |= (this._collidable && notFalse(cfg.collidable) && ENTITY_FLAGS.COLLIDABLE);
3089
- flags |= (this._xrayed && notFalse(cfg.xrayed) && ENTITY_FLAGS.XRAYED);
3090
- flags |= (this._highlighted && notFalse(cfg.highlighted) && ENTITY_FLAGS.HIGHLIGHTED);
3091
- flags |= (this._selected && notFalse(cfg.selected) && ENTITY_FLAGS.SELECTED);
3092
- 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
+ }
3093
3477
  cfg.flags = flags;
3478
+ return this._createEntity(cfg);
3479
+ }
3094
3480
 
3481
+ _createEntity(cfg) {
3095
3482
  let meshes = [];
3096
3483
  for (let i = 0, len = cfg.meshIds.length; i < len; i++) {
3097
3484
  const meshId = cfg.meshIds[i];
@@ -3139,7 +3526,8 @@ export class SceneModel extends Component {
3139
3526
  const layer = this._layersToFinalize[i];
3140
3527
  layer.finalize();
3141
3528
  }
3142
- this._vboLayers = {};
3529
+ this._vboBatchingLayers = {};
3530
+ this._vboInstancingLayers = {};
3143
3531
  this._dtxLayers = {};
3144
3532
  this._layersToFinalize = [];
3145
3533
  for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
@@ -3333,48 +3721,263 @@ export class SceneModel extends Component {
3333
3721
 
3334
3722
  // -------------- RENDERING ---------------------------------------------------------------------------------------
3335
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
+ }
3336
3831
 
3337
3832
  /**
3338
3833
  * @private
3339
3834
  */
3340
- _withEachVisibleLayer(testNumVisibleLayerPortions, cb) {
3341
- if (testNumVisibleLayerPortions && (this.numVisibleLayerPortions === 0)) {
3835
+ drawOcclusion(frameCtx) {
3836
+ if (this.numVisibleLayerPortions === 0) {
3342
3837
  return;
3343
3838
  }
3344
3839
  const renderFlags = this.renderFlags;
3345
3840
  for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3346
3841
  const layerIndex = renderFlags.visibleLayers[i];
3347
- cb(this.layerList[layerIndex]);
3842
+ this.layerList[layerIndex].drawOcclusion(renderFlags, frameCtx);
3348
3843
  }
3349
3844
  }
3350
3845
 
3351
- drawColorOpaque (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawColorOpaque (this.renderFlags, frameCtx)); }
3352
- drawColorTransparent (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawColorTransparent (this.renderFlags, frameCtx)); }
3353
- drawDepth (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawDepth (this.renderFlags, frameCtx)); } // Dedicated to SAO because it skips transparent objects
3354
- drawSilhouetteXRayed (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteXRayed (this.renderFlags, frameCtx)); }
3355
- drawSilhouetteHighlighted(frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteHighlighted(this.renderFlags, frameCtx)); }
3356
- drawSilhouetteSelected (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteSelected (this.renderFlags, frameCtx)); }
3357
- drawEdgesColorOpaque (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesColorOpaque (this.renderFlags, frameCtx)); }
3358
- drawEdgesColorTransparent(frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesColorTransparent(this.renderFlags, frameCtx)); }
3359
- drawEdgesXRayed (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesXRayed (this.renderFlags, frameCtx)); }
3360
- drawEdgesHighlighted (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesHighlighted (this.renderFlags, frameCtx)); }
3361
- drawEdgesSelected (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesSelected (this.renderFlags, frameCtx)); }
3362
- drawOcclusion (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawOcclusion (this.renderFlags, frameCtx)); }
3363
- drawShadow (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawShadow (this.renderFlags, frameCtx)); }
3364
- drawPickMesh (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickMesh (this.renderFlags, frameCtx)); }
3365
- drawPickDepths (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickDepths (this.renderFlags, frameCtx)); }
3366
- drawPickNormals (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickNormals (this.renderFlags, frameCtx)); }
3367
- _drawSnap (frameCtx, isSnapInit) { this._withEachVisibleLayer(true, layer => layer.drawSnap (this.renderFlags, frameCtx, isSnapInit)); }
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
+ }
3368
3859
 
3369
- drawSnapInit(frameCtx) { this._drawSnap(frameCtx, true ); }
3370
- drawSnap (frameCtx) { this._drawSnap(frameCtx, false); }
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
+ }
3901
+
3902
+ /**
3903
+ * Called by SceneModelMesh.drawPickNormals()
3904
+ * @private
3905
+ */
3906
+ drawPickNormals(frameCtx) {
3907
+ if (this.numVisibleLayerPortions === 0) {
3908
+ return;
3909
+ }
3910
+ const renderFlags = this.renderFlags;
3911
+ for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3912
+ const layerIndex = renderFlags.visibleLayers[i];
3913
+ this.layerList[layerIndex].drawPickNormals(renderFlags, frameCtx);
3914
+ }
3915
+ }
3916
+
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
+ }
3940
+
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
+ }
3371
3964
 
3372
3965
  /**
3373
3966
  * Destroys this SceneModel.
3374
3967
  */
3375
3968
  destroy() {
3376
- Object.values(this._vboLayers).forEach(l => l.destroy());
3377
- 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 = {};
3378
3981
  this.scene.camera.off(this._onCameraViewMatrix);
3379
3982
  this.scene.off(this._onTick);
3380
3983
  for (let i = 0, len = this.layerList.length; i < len; i++) {
@@ -3384,7 +3987,7 @@ export class SceneModel extends Component {
3384
3987
  for (let i = 0, len = this._entityList.length; i < len; i++) {
3385
3988
  this._entityList[i]._destroy();
3386
3989
  }
3387
- this._layersToFinalize = [];
3990
+ this._layersToFinalize = {};
3388
3991
  // Object.entries(this._geometries).forEach(([id, geometry]) => {
3389
3992
  // geometry.destroy();
3390
3993
  // });
@@ -3398,6 +4001,7 @@ export class SceneModel extends Component {
3398
4001
  if (this._isModel) {
3399
4002
  this.scene._deregisterModel(this);
3400
4003
  }
4004
+ putScratchMemory();
3401
4005
  super.destroy();
3402
4006
  }
3403
4007
  }