@xeokit/xeokit-sdk 2.6.28 → 2.6.30

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 (58) hide show
  1. package/README.md +1 -0
  2. package/dist/xeokit-sdk.cjs.js +1425 -649
  3. package/dist/xeokit-sdk.es.js +1420 -650
  4. package/dist/xeokit-sdk.es5.js +629 -552
  5. package/dist/xeokit-sdk.min.cjs.js +5 -5
  6. package/dist/xeokit-sdk.min.es.js +5 -5
  7. package/dist/xeokit-sdk.min.es5.js +4 -4
  8. package/package.json +1 -1
  9. package/src/extras/PointerCircle/PointerCircle.js +1 -1
  10. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +22 -41
  11. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +3 -18
  12. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +20 -41
  13. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +4 -20
  14. package/src/plugins/DistanceMeasurementsPlugin/index.js +1 -1
  15. package/src/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js +2 -110
  16. package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +252 -222
  17. package/src/plugins/StoreyViewsPlugin/StoreyViewsPlugin.js +31 -1
  18. package/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js +20 -8
  19. package/src/plugins/ZonesPlugin/ZonesPlugin.js +1939 -0
  20. package/src/plugins/ZonesPlugin/index.js +1 -1875
  21. package/src/viewer/Viewer.js +2 -2
  22. package/src/viewer/metadata/MetaScene.js +0 -2
  23. package/src/viewer/scene/math/MeshSurfaceArea.js +90 -0
  24. package/src/viewer/scene/math/MeshVolume.js +102 -0
  25. package/src/viewer/scene/math/index.js +3 -0
  26. package/src/viewer/scene/math/isTriangleMeshSolid.js +162 -0
  27. package/src/viewer/scene/math/math.js +8 -0
  28. package/src/viewer/scene/model/SceneModel.js +73 -34
  29. package/src/viewer/scene/model/SceneModelEntity.js +46 -1
  30. package/src/viewer/scene/model/SceneModelMesh.js +74 -1
  31. package/src/viewer/scene/model/SceneModelTextureSet.js +5 -0
  32. package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +7 -1
  33. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +77 -1
  34. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +8 -0
  35. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +8 -0
  36. package/src/viewer/scene/model/vbo/VBORenderer.js +10 -1
  37. package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +6 -1
  38. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +1 -1
  39. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +6 -1
  40. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +59 -18
  41. package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +40 -12
  42. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +2 -3
  43. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +25 -7
  44. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +1 -1
  45. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +6 -1
  46. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +1 -1
  47. package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +6 -1
  48. package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +48 -14
  49. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +74 -47
  50. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +29 -14
  51. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +5 -4
  52. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +1 -1
  53. package/src/viewer/scene/scene/Scene.js +16 -5
  54. package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +1 -1
  55. package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +1 -5
  56. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +7 -0
  57. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.d.ts +26 -1
  58. package/types/plugins/DistanceMeasurementsPlugin/index.d.ts +3 -1
@@ -46,7 +46,7 @@ class Viewer {
46
46
  * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.
47
47
  * @param {Boolean} [cfg.alphaDepthMask=true] Whether writing into the depth buffer is enabled or disabled when rendering transparent objects.
48
48
  * @param {Boolean} [cfg.entityOffsetsEnabled=false] Whether to enable {@link Entity#offset}. For best performance, only set this ````true```` when you need to use {@link Entity#offset}.
49
- * @param {Boolean} [cfg.pickSurfacePrecisionEnabled=false] Whether to enable full-precision accuracy when surface picking with {@link Scene#pick}. Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer. The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.
49
+ * @param {Boolean} [cfg.readableGeometryEnabled=false] Whether to enable full-precision accuracy when surface picking with {@link Scene#pick}. Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer. The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.
50
50
  * @param {Boolean} [cfg.logarithmicDepthBufferEnabled=false] Whether to enable logarithmic depth buffer. When this is true,
51
51
  * you can set huge values for {@link Perspective#far} and {@link Ortho#far}, to push the far clipping plane back so
52
52
  * that it does not clip huge models.
@@ -116,7 +116,7 @@ class Viewer {
116
116
  saoEnabled: cfg.saoEnabled,
117
117
  alphaDepthMask: (cfg.alphaDepthMask !== false),
118
118
  entityOffsetsEnabled: (!!cfg.entityOffsetsEnabled),
119
- pickSurfacePrecisionEnabled: (!!cfg.pickSurfacePrecisionEnabled),
119
+ readableGeometryEnabled: (!!cfg.readableGeometryEnabled),
120
120
  logarithmicDepthBufferEnabled: (!!cfg.logarithmicDepthBufferEnabled),
121
121
  pbrEnabled: (!!cfg.pbrEnabled),
122
122
  colorTextureEnabled: (cfg.colorTextureEnabled !== false),
@@ -126,8 +126,6 @@ class MetaScene {
126
126
  * @param {String} modelId ID for the new {@link MetaModel}, which will have {@link MetaModel#id} set to this value.
127
127
  * @param {Object} metaModelData Data for the {@link MetaModel}.
128
128
  * @param {Object} [options] Options for creating the {@link MetaModel}.
129
- * @param {Object} [options.includeTypes] When provided, only create {@link MetaObject}s with types in this list.
130
- * @param {Object} [options.excludeTypes] When provided, never create {@link MetaObject}s with types in this list.
131
129
  * @param {Boolean} [options.globalizeObjectIds=false] Whether to globalize each {@link MetaObject#id}. Set this ````true```` when you need to load multiple instances of the same meta model, to avoid ID clashes between the meta objects in the different instances.
132
130
  * @returns {MetaModel} The new MetaModel.
133
131
  */
@@ -0,0 +1,90 @@
1
+ import {math} from "./math.js";
2
+
3
+ const v1 = math.vec3();
4
+ const v2 = math.vec3();
5
+ const v3 = math.vec3();
6
+ const v4 = math.vec3();
7
+ const v5 = math.vec3();
8
+ const v6 = math.vec3();
9
+
10
+ /**
11
+ * Calculates the surface area of triangle meshes.
12
+ */
13
+ export class MeshSurfaceArea {
14
+ constructor() {
15
+ this.vertices = [];
16
+ this.indices = [];
17
+ this.reset();
18
+ }
19
+
20
+ /**
21
+ * Resets, ready to add vertices and indices for a new mesh.
22
+ */
23
+ reset() {
24
+ this.lenVertices = 0;
25
+ this.lenIndices = 0;
26
+ }
27
+
28
+ /**
29
+ * Adds a vertex.
30
+ * @param vertex
31
+ */
32
+ addVertex(vertex) {
33
+ this.vertices[this.lenVertices++] = vertex[0];
34
+ this.vertices[this.lenVertices++] = vertex[1];
35
+ this.vertices[this.lenVertices++] = vertex[2];
36
+ }
37
+
38
+ /**
39
+ * Adds an index.
40
+ * @param index
41
+ */
42
+ addIndex(index) {
43
+ this.indices[this.lenIndices++] = index;
44
+ }
45
+
46
+ /**
47
+ * Gets the surface area of the mesh.
48
+ *
49
+ * @returns {number}
50
+ */
51
+ get surfaceArea() {
52
+
53
+ const vertices = this.vertices;
54
+ const indices = this.indices;
55
+
56
+ let surfaceArea = 0;
57
+
58
+ for (let i = 0; i < this.lenIndices; i += 3) {
59
+
60
+ const index1 = indices[i] * 3;
61
+ const index2 = indices[i + 1] * 3;
62
+ const index3 = indices[i + 2] * 3;
63
+
64
+ v1[0] = vertices[index1];
65
+ v1[1] = vertices[index1 + 1];
66
+ v1[2] = vertices[index1 + 2];
67
+
68
+ v2[0] = vertices[index2];
69
+ v2[1] = vertices[index2 + 1];
70
+ v2[2] = vertices[index2 + 2];
71
+
72
+ v3[0] = vertices[index3];
73
+ v3[1] = vertices[index3 + 1];
74
+ v3[2] = vertices[index3 + 2];
75
+
76
+ math.subVec3(v1, v2, v4);
77
+ math.subVec3(v3, v2, v5);
78
+
79
+ surfaceArea += math.lenVec3(math.cross3Vec3(v4, v5, v6)) * 0.5;
80
+ }
81
+
82
+ return surfaceArea;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Singleton instance of {@link MeshSurfaceArea}.
88
+ * @type {MeshSurfaceArea}
89
+ */
90
+ export const meshSurfaceArea = new MeshSurfaceArea();
@@ -0,0 +1,102 @@
1
+ import {math} from "./math.js";
2
+ import {isTriangleMeshSolid} from "./isTriangleMeshSolid.js";
3
+
4
+ const v1 = math.vec3();
5
+ const v2 = math.vec3();
6
+ const v3 = math.vec3();
7
+
8
+ /**
9
+ * Calculates the volume of triangle meshes.
10
+ */
11
+ export class MeshVolume {
12
+ constructor() {
13
+ this.vertices = [];
14
+ this.indices = [];
15
+ this.reset();
16
+ }
17
+
18
+ /**
19
+ * Resets, ready to add vertices and indices for a new mesh.
20
+ */
21
+ reset() {
22
+ this.lenVertices = 0;
23
+ this.lenIndices = 0;
24
+ this.primitive = null;
25
+ }
26
+
27
+ setPrimitive(primitive) {
28
+ this.primitive = primitive;
29
+ }
30
+
31
+ /**
32
+ * Adds a vertex.
33
+ * @param vertex
34
+ */
35
+ addVertex(vertex) {
36
+ this.vertices[this.lenVertices++] = vertex[0];
37
+ this.vertices[this.lenVertices++] = vertex[1];
38
+ this.vertices[this.lenVertices++] = vertex[2];
39
+ }
40
+
41
+ /**
42
+ * Adds an index.
43
+ * @param index
44
+ */
45
+ addIndex(index) {
46
+ this.indices[this.lenIndices++] = index;
47
+ }
48
+
49
+ /**
50
+ * Gets the volume of the mesh.
51
+ *
52
+ * The mesh must be a closed solid.
53
+ *
54
+ * @returns {number} The volume of the mesh, or -1 if the mesh is not solid, in which case volume cannot be determined.
55
+ */
56
+ get volume() {
57
+
58
+ const vertices = this.vertices;
59
+ const indices = this.indices;
60
+
61
+ if (this.primitive !== "solid" && this.primitive !== "surface" && this.primitive !== "triangles") {
62
+ return -1;
63
+ }
64
+
65
+ if (this.primitive !== "solid" && !isTriangleMeshSolid(indices, vertices)) {
66
+ return -1;
67
+ }
68
+
69
+ let volume = 0;
70
+
71
+ for (let i = 0; i < this.lenIndices; i += 3) {
72
+
73
+ const index1 = indices[i] * 3;
74
+ const index2 = indices[i + 1] * 3;
75
+ const index3 = indices[i + 2] * 3;
76
+
77
+ v1[0] = vertices[index1];
78
+ v1[1] = vertices[index1 + 1];
79
+ v1[2] = vertices[index1 + 2];
80
+
81
+ v2[0] = vertices[index2];
82
+ v2[1] = vertices[index2 + 1];
83
+ v2[2] = vertices[index2 + 2];
84
+
85
+ v3[0] = vertices[index3];
86
+ v3[1] = vertices[index3 + 1];
87
+ v3[2] = vertices[index3 + 2];
88
+
89
+ math.cross3Vec3(v1, v2, v1);
90
+
91
+ volume += math.dotVec3(v1, v3);
92
+ }
93
+
94
+ return volume;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Singleton instance of {@link MeshVolume}.
100
+ * @type {MeshVolume}
101
+ */
102
+ export const meshVolume = new MeshVolume();
@@ -1,3 +1,6 @@
1
1
  export * from "./math.js";
2
2
  export * from "./Frustum.js";
3
3
  export * from "./rtcCoords.js";
4
+ export * from "./MeshVolume.js";
5
+ export * from "./MeshSurfaceArea.js";
6
+ export * from "./isTriangleMeshSolid.js";
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Uses edge adjacency counts to identify if the given triangle mesh can be rendered with backface culling enabled.
3
+ *
4
+ * If all edges are connected to exactly two triangles, then the mesh will likely be a closed solid, and we can safely
5
+ * render it with backface culling enabled.
6
+ *
7
+ * Otherwise, the mesh is a surface, and we must render it with backface culling disabled.
8
+ *
9
+ * @private
10
+ */
11
+ const isTriangleMeshSolid = (indices, positions) => {
12
+
13
+ const vertexIndexMapping = [];
14
+ let edges = [];
15
+
16
+ function compareIndexPositions(a, b) {
17
+ let posA, posB;
18
+
19
+ for (let i = 0; i < 3; i++) {
20
+ posA = positions [a * 3 + i];
21
+ posB = positions [b * 3 + i];
22
+
23
+ if (posA !== posB) {
24
+ return posB - posA;
25
+ }
26
+ }
27
+
28
+ return 0;
29
+ };
30
+
31
+ // Group together indices corresponding to same position coordinates
32
+ let newIndices = indices.slice().sort(compareIndexPositions);
33
+
34
+ // Calculate the mapping:
35
+ // - from original index in indices array
36
+ // - to indices-for-unique-positions
37
+ let uniqueVertexIndex = null;
38
+
39
+ for (let i = 0, len = newIndices.length; i < len; i++) {
40
+ if (i === 0 || 0 !== compareIndexPositions(
41
+ newIndices[i],
42
+ newIndices[i - 1],
43
+ )) {
44
+ // different position
45
+ uniqueVertexIndex = newIndices [i];
46
+ }
47
+
48
+ vertexIndexMapping [
49
+ newIndices[i]
50
+ ] = uniqueVertexIndex;
51
+ }
52
+
53
+ // Generate the list of edges
54
+ for (let i = 0, len = indices.length; i < len; i += 3) {
55
+
56
+ const a = vertexIndexMapping[indices[i]];
57
+ const b = vertexIndexMapping[indices[i + 1]];
58
+ const c = vertexIndexMapping[indices[i + 2]];
59
+
60
+ let a2 = a;
61
+ let b2 = b;
62
+ let c2 = c;
63
+
64
+ if (a > b && a > c) {
65
+ if (b > c) {
66
+ a2 = a;
67
+ b2 = b;
68
+ c2 = c;
69
+ } else {
70
+ a2 = a;
71
+ b2 = c;
72
+ c2 = b;
73
+ }
74
+ } else if (b > a && b > c) {
75
+ if (a > c) {
76
+ a2 = b;
77
+ b2 = a;
78
+ c2 = c;
79
+ } else {
80
+ a2 = b;
81
+ b2 = c;
82
+ c2 = a;
83
+ }
84
+ } else if (c > a && c > b) {
85
+ if (a > b) {
86
+ a2 = c;
87
+ b2 = a;
88
+ c2 = b;
89
+ } else {
90
+ a2 = c;
91
+ b2 = b;
92
+ c2 = a;
93
+ }
94
+ }
95
+
96
+ edges[i + 0] = [
97
+ a2, b2
98
+ ];
99
+ edges[i + 1] = [
100
+ b2, c2
101
+ ];
102
+
103
+ if (a2 > c2) {
104
+ const temp = c2;
105
+ c2 = a2;
106
+ a2 = temp;
107
+ }
108
+
109
+ edges[i + 2] = [
110
+ c2, a2
111
+ ];
112
+ }
113
+
114
+ // Group semantically equivalent edgdes together
115
+ function compareEdges(e1, e2) {
116
+ let a, b;
117
+
118
+ for (let i = 0; i < 2; i++) {
119
+ a = e1[i];
120
+ b = e2[i];
121
+
122
+ if (b !== a) {
123
+ return b - a;
124
+ }
125
+ }
126
+
127
+ return 0;
128
+ }
129
+
130
+ edges = edges.slice(0, indices.length);
131
+
132
+ edges.sort(compareEdges);
133
+
134
+ // Make sure each edge is used exactly twice
135
+ let sameEdgeCount = 0;
136
+
137
+ for (let i = 0; i < edges.length; i++) {
138
+ if (i === 0 || 0 !== compareEdges(
139
+ edges[i], edges[i - 1]
140
+ )) {
141
+ // different edge
142
+ if (0 !== i && sameEdgeCount !== 2) {
143
+ return false;
144
+ }
145
+
146
+ sameEdgeCount = 1;
147
+ } else {
148
+ // same edge
149
+ sameEdgeCount++;
150
+ }
151
+ }
152
+
153
+ if (edges.length > 0 && sameEdgeCount !== 2) {
154
+ return false;
155
+ }
156
+
157
+ // Each edge is used exactly twice, this is a
158
+ // watertight surface and hence a solid geometry.
159
+ return true;
160
+ };
161
+
162
+ export {isTriangleMeshSolid};
@@ -3998,6 +3998,14 @@ const math = {
3998
3998
  return aabb[0] > p[0] || aabb[3] < p[0] || aabb[1] > p[1] || aabb[4] < p[1] || aabb[2] > p[2] || aabb[5] < p[2];
3999
3999
  },
4000
4000
 
4001
+ point3AABB3AbsoluteIntersect(aabb, p) {
4002
+ return (
4003
+ aabb[0] <= p[0] && aabb[3] >= p[0] &&
4004
+ aabb[1] <= p[1] && aabb[4] >= p[1] &&
4005
+ aabb[2] <= p[2] && aabb[5] >= p[2]
4006
+ );
4007
+ },
4008
+
4001
4009
  /**
4002
4010
  *
4003
4011
  * @param dir
@@ -1155,7 +1155,10 @@ export class SceneModel extends Component {
1155
1155
  this._meshList = [];
1156
1156
 
1157
1157
  this.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second
1158
+ this._layersToFinalize = [];
1159
+
1158
1160
  this._entityList = [];
1161
+ this._entitiesToFinalize = [];
1159
1162
 
1160
1163
  this._geometries = {};
1161
1164
  this._dtxBuckets = {}; // Geometries with optimizations used for data texture representation
@@ -1231,6 +1234,7 @@ export class SceneModel extends Component {
1231
1234
  this._numTriangles = 0;
1232
1235
  this._numLines = 0;
1233
1236
  this._numPoints = 0;
1237
+ this._layersFinalized = false;
1234
1238
 
1235
1239
  this._edgeThreshold = cfg.edgeThreshold || 10;
1236
1240
 
@@ -2640,6 +2644,7 @@ export class SceneModel extends Component {
2640
2644
  id: textureSetId,
2641
2645
  model: this,
2642
2646
  colorTexture,
2647
+ alphaCutoff: cfg.alphaCutoff,
2643
2648
  metallicRoughnessTexture,
2644
2649
  normalsTexture,
2645
2650
  emissiveTexture,
@@ -3073,6 +3078,14 @@ export class SceneModel extends Component {
3073
3078
  return this._createMesh(cfg);
3074
3079
  }
3075
3080
 
3081
+ _createDefaultIndices(numIndices) {
3082
+ const indices = [];
3083
+ for (let i = 0; i < numIndices; i++) {
3084
+ indices.push(i);
3085
+ }
3086
+ return indices;
3087
+ }
3088
+
3076
3089
  _createMesh(cfg) {
3077
3090
  const mesh = new SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);
3078
3091
  mesh.pickId = this.scene._renderer.getPickID(mesh);
@@ -3172,7 +3185,7 @@ export class SceneModel extends Component {
3172
3185
  let dtxLayer = this._dtxLayers[layerId];
3173
3186
  if (dtxLayer) {
3174
3187
  if (!dtxLayer.canCreatePortion(cfg)) {
3175
- dtxLayer.finalize();
3188
+ // dtxLayer.finalize();
3176
3189
  delete this._dtxLayers[layerId];
3177
3190
  dtxLayer = null;
3178
3191
  } else {
@@ -3183,16 +3196,17 @@ export class SceneModel extends Component {
3183
3196
  case "triangles":
3184
3197
  case "solid":
3185
3198
  case "surface":
3186
- dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
3199
+ dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
3187
3200
  break;
3188
3201
  case "lines":
3189
- dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
3202
+ dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
3190
3203
  break;
3191
3204
  default:
3192
3205
  return;
3193
3206
  }
3194
3207
  this._dtxLayers[layerId] = dtxLayer;
3195
3208
  this.layerList.push(dtxLayer);
3209
+ this._layersToFinalize.push(dtxLayer);
3196
3210
  return dtxLayer;
3197
3211
  }
3198
3212
 
@@ -3224,7 +3238,8 @@ export class SceneModel extends Component {
3224
3238
  origin,
3225
3239
  maxGeometryBatchSize: this._maxGeometryBatchSize,
3226
3240
  solid: (cfg.primitive === "solid"),
3227
- autoNormals: true
3241
+ autoNormals: true,
3242
+ primitive: cfg.primitive
3228
3243
  });
3229
3244
  break;
3230
3245
  case "solid":
@@ -3239,7 +3254,8 @@ export class SceneModel extends Component {
3239
3254
  origin,
3240
3255
  maxGeometryBatchSize: this._maxGeometryBatchSize,
3241
3256
  solid: (cfg.primitive === "solid"),
3242
- autoNormals: true
3257
+ autoNormals: true,
3258
+ primitive: cfg.primitive
3243
3259
  });
3244
3260
  break;
3245
3261
  case "surface":
@@ -3254,7 +3270,8 @@ export class SceneModel extends Component {
3254
3270
  origin,
3255
3271
  maxGeometryBatchSize: this._maxGeometryBatchSize,
3256
3272
  solid: (cfg.primitive === "solid"),
3257
- autoNormals: true
3273
+ autoNormals: true,
3274
+ primitive: cfg.primitive
3258
3275
  });
3259
3276
  break;
3260
3277
  case "lines":
@@ -3266,7 +3283,8 @@ export class SceneModel extends Component {
3266
3283
  positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3267
3284
  uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3268
3285
  origin,
3269
- maxGeometryBatchSize: this._maxGeometryBatchSize
3286
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3287
+ primitive: cfg.primitive
3270
3288
  });
3271
3289
  break;
3272
3290
  case "points":
@@ -3278,7 +3296,8 @@ export class SceneModel extends Component {
3278
3296
  positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
3279
3297
  uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
3280
3298
  origin,
3281
- maxGeometryBatchSize: this._maxGeometryBatchSize
3299
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
3300
+ primitive: cfg.primitive
3282
3301
  });
3283
3302
  break;
3284
3303
  }
@@ -3294,6 +3313,7 @@ export class SceneModel extends Component {
3294
3313
  }
3295
3314
  this._vboBatchingLayers[layerId] = vboBatchingLayer;
3296
3315
  this.layerList.push(vboBatchingLayer);
3316
+ this._layersToFinalize.push(vboBatchingLayer);
3297
3317
  return vboBatchingLayer;
3298
3318
  }
3299
3319
 
@@ -3386,6 +3406,7 @@ export class SceneModel extends Component {
3386
3406
  }
3387
3407
  this._vboInstancingLayers[layerId] = vboInstancingLayer;
3388
3408
  this.layerList.push(vboInstancingLayer);
3409
+ this._layersToFinalize.push(vboInstancingLayer);
3389
3410
  return vboInstancingLayer;
3390
3411
  }
3391
3412
 
@@ -3486,38 +3507,47 @@ export class SceneModel extends Component {
3486
3507
  lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel
3487
3508
  this._entityList.push(entity);
3488
3509
  this._entities[cfg.id] = entity;
3510
+ this._entitiesToFinalize.push(entity);
3489
3511
  this.numEntities++;
3490
3512
  }
3491
3513
 
3492
3514
  /**
3493
- * Finalizes this SceneModel.
3494
- *
3495
- * Once finalized, you can't add anything more to this SceneModel.
3515
+ * Pre-renders all meshes that have been added, even if the SceneModel has not bee finalized yet.
3516
+ * This is use for progressively showing the SceneModel while it is being loaded or constructed.
3517
+ * @returns {boolean}
3496
3518
  */
3497
- finalize() {
3519
+ preFinalize() {
3498
3520
  if (this.destroyed) {
3499
- return;
3521
+ return false;
3522
+ }
3523
+ if (this._layersToFinalize.length === 0) {
3524
+ return false;
3500
3525
  }
3501
3526
  this._createDummyEntityForUnusedMeshes();
3502
- for (let i = 0, len = this.layerList.length; i < len; i++) {
3503
- const layer = this.layerList[i];
3527
+ for (let i = 0, len = this._layersToFinalize.length; i < len; i++) {
3528
+ const layer = this._layersToFinalize[i];
3504
3529
  layer.finalize();
3505
3530
  }
3506
- this._geometries = {};
3507
- this._dtxBuckets = {};
3508
- this._textures = {};
3509
- this._textureSets = {};
3510
- this._dtxLayers = {};
3511
- this._vboInstancingLayers = {};
3512
3531
  this._vboBatchingLayers = {};
3513
- for (let i = 0, len = this._entityList.length; i < len; i++) {
3514
- const entity = this._entityList[i];
3532
+ this._vboInstancingLayers = {};
3533
+ this._dtxLayers = {};
3534
+ this._layersToFinalize = [];
3535
+ for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
3536
+ const entity = this._entitiesToFinalize[i];
3515
3537
  entity._finalize();
3516
3538
  }
3517
- for (let i = 0, len = this._entityList.length; i < len; i++) {
3518
- const entity = this._entityList[i];
3539
+ for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
3540
+ const entity = this._entitiesToFinalize[i];
3519
3541
  entity._finalize2();
3520
3542
  }
3543
+ this._entitiesToFinalize = [];
3544
+ this.scene._aabbDirty = true;
3545
+ this._viewMatrixDirty = true;
3546
+ this._matrixDirty = true;
3547
+ this._aabbDirty = true;
3548
+ this._setWorldMatrixDirty();
3549
+ this._sceneModelDirty();
3550
+ this.position = this._position;
3521
3551
  // Sort layers to reduce WebGL shader switching when rendering them
3522
3552
  this.layerList.sort((a, b) => {
3523
3553
  if (a.sortId < b.sortId) {
@@ -3533,15 +3563,23 @@ export class SceneModel extends Component {
3533
3563
  layer.layerIndex = i;
3534
3564
  }
3535
3565
  this.glRedraw();
3536
- this.scene._aabbDirty = true;
3537
- this._viewMatrixDirty = true;
3538
- this._matrixDirty = true;
3539
- this._aabbDirty = true;
3540
-
3541
- this._setWorldMatrixDirty();
3542
- this._sceneModelDirty();
3566
+ this._layersFinalized = true;
3567
+ }
3543
3568
 
3544
- this.position = this._position;
3569
+ /**
3570
+ * Finalizes this SceneModel.
3571
+ *
3572
+ * Once finalized, you can't add anything more to this SceneModel.
3573
+ */
3574
+ finalize() {
3575
+ if (this.destroyed) {
3576
+ return;
3577
+ }
3578
+ this.preFinalize();
3579
+ this._geometries = {};
3580
+ this._dtxBuckets = {};
3581
+ this._textures = {};
3582
+ this._textureSets = {};
3545
3583
  }
3546
3584
 
3547
3585
  /** @private */
@@ -3579,7 +3617,7 @@ export class SceneModel extends Component {
3579
3617
  _createDummyEntityForUnusedMeshes() {
3580
3618
  const unusedMeshIds = Object.keys(this._unusedMeshes);
3581
3619
  if (unusedMeshIds.length > 0) {
3582
- const entityId = `${this.id}-dummyEntityForUnusedMeshes`;
3620
+ const entityId = `${this.id}-${math.createUUID()}`;
3583
3621
  this.warn(`Creating dummy SceneModelEntity "${entityId}" for unused SceneMeshes: [${unusedMeshIds.join(",")}]`)
3584
3622
  this.createEntity({
3585
3623
  id: entityId,
@@ -3951,6 +3989,7 @@ export class SceneModel extends Component {
3951
3989
  for (let i = 0, len = this._entityList.length; i < len; i++) {
3952
3990
  this._entityList[i]._destroy();
3953
3991
  }
3992
+ this._layersToFinalize = {};
3954
3993
  // Object.entries(this._geometries).forEach(([id, geometry]) => {
3955
3994
  // geometry.destroy();
3956
3995
  // });