@xeokit/xeokit-sdk 2.6.27 → 2.6.29
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.
- package/README.md +1 -0
- package/dist/xeokit-sdk.cjs.js +916 -221
- package/dist/xeokit-sdk.es.js +911 -222
- package/dist/xeokit-sdk.es5.js +577 -487
- package/dist/xeokit-sdk.min.cjs.js +5 -5
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +4 -4
- package/package.json +1 -1
- package/src/extras/PointerCircle/PointerCircle.js +1 -1
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +22 -41
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +3 -18
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +20 -41
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +4 -20
- package/src/plugins/DistanceMeasurementsPlugin/index.js +1 -1
- package/src/plugins/StoreyViewsPlugin/StoreyViewsPlugin.js +31 -1
- package/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js +20 -8
- package/src/plugins/ZonesPlugin/ZonesPlugin.js +1939 -0
- package/src/plugins/ZonesPlugin/index.js +1 -1875
- package/src/viewer/Viewer.js +2 -2
- package/src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js +1 -1
- package/src/viewer/scene/math/MeshSurfaceArea.js +90 -0
- package/src/viewer/scene/math/MeshVolume.js +102 -0
- package/src/viewer/scene/math/index.js +3 -0
- package/src/viewer/scene/math/isTriangleMeshSolid.js +162 -0
- package/src/viewer/scene/math/math.js +8 -0
- package/src/viewer/scene/model/SceneModel.js +64 -34
- package/src/viewer/scene/model/SceneModelEntity.js +46 -1
- package/src/viewer/scene/model/SceneModelMesh.js +74 -1
- package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +7 -1
- package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +77 -1
- package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +6 -1
- package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +6 -1
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +33 -12
- package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +6 -1
- package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +6 -1
- package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +31 -10
- package/src/viewer/scene/scene/Scene.js +16 -5
- package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +0 -1
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +7 -0
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.d.ts +26 -1
- package/types/plugins/DistanceMeasurementsPlugin/index.d.ts +3 -1
package/src/viewer/Viewer.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
119
|
+
readableGeometryEnabled: (!!cfg.readableGeometryEnabled),
|
|
120
120
|
logarithmicDepthBufferEnabled: (!!cfg.logarithmicDepthBufferEnabled),
|
|
121
121
|
pbrEnabled: (!!cfg.pbrEnabled),
|
|
122
122
|
colorTextureEnabled: (cfg.colorTextureEnabled !== false),
|
|
@@ -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();
|
|
@@ -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
|
|
|
@@ -3172,7 +3176,7 @@ export class SceneModel extends Component {
|
|
|
3172
3176
|
let dtxLayer = this._dtxLayers[layerId];
|
|
3173
3177
|
if (dtxLayer) {
|
|
3174
3178
|
if (!dtxLayer.canCreatePortion(cfg)) {
|
|
3175
|
-
dtxLayer.finalize();
|
|
3179
|
+
// dtxLayer.finalize();
|
|
3176
3180
|
delete this._dtxLayers[layerId];
|
|
3177
3181
|
dtxLayer = null;
|
|
3178
3182
|
} else {
|
|
@@ -3183,16 +3187,17 @@ export class SceneModel extends Component {
|
|
|
3183
3187
|
case "triangles":
|
|
3184
3188
|
case "solid":
|
|
3185
3189
|
case "surface":
|
|
3186
|
-
dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
|
|
3190
|
+
dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
|
|
3187
3191
|
break;
|
|
3188
3192
|
case "lines":
|
|
3189
|
-
dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
|
|
3193
|
+
dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
|
|
3190
3194
|
break;
|
|
3191
3195
|
default:
|
|
3192
3196
|
return;
|
|
3193
3197
|
}
|
|
3194
3198
|
this._dtxLayers[layerId] = dtxLayer;
|
|
3195
3199
|
this.layerList.push(dtxLayer);
|
|
3200
|
+
this._layersToFinalize.push(dtxLayer);
|
|
3196
3201
|
return dtxLayer;
|
|
3197
3202
|
}
|
|
3198
3203
|
|
|
@@ -3224,7 +3229,8 @@ export class SceneModel extends Component {
|
|
|
3224
3229
|
origin,
|
|
3225
3230
|
maxGeometryBatchSize: this._maxGeometryBatchSize,
|
|
3226
3231
|
solid: (cfg.primitive === "solid"),
|
|
3227
|
-
autoNormals: true
|
|
3232
|
+
autoNormals: true,
|
|
3233
|
+
primitive: cfg.primitive
|
|
3228
3234
|
});
|
|
3229
3235
|
break;
|
|
3230
3236
|
case "solid":
|
|
@@ -3239,7 +3245,8 @@ export class SceneModel extends Component {
|
|
|
3239
3245
|
origin,
|
|
3240
3246
|
maxGeometryBatchSize: this._maxGeometryBatchSize,
|
|
3241
3247
|
solid: (cfg.primitive === "solid"),
|
|
3242
|
-
autoNormals: true
|
|
3248
|
+
autoNormals: true,
|
|
3249
|
+
primitive: cfg.primitive
|
|
3243
3250
|
});
|
|
3244
3251
|
break;
|
|
3245
3252
|
case "surface":
|
|
@@ -3254,7 +3261,8 @@ export class SceneModel extends Component {
|
|
|
3254
3261
|
origin,
|
|
3255
3262
|
maxGeometryBatchSize: this._maxGeometryBatchSize,
|
|
3256
3263
|
solid: (cfg.primitive === "solid"),
|
|
3257
|
-
autoNormals: true
|
|
3264
|
+
autoNormals: true,
|
|
3265
|
+
primitive: cfg.primitive
|
|
3258
3266
|
});
|
|
3259
3267
|
break;
|
|
3260
3268
|
case "lines":
|
|
@@ -3266,7 +3274,8 @@ export class SceneModel extends Component {
|
|
|
3266
3274
|
positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
|
|
3267
3275
|
uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
|
|
3268
3276
|
origin,
|
|
3269
|
-
maxGeometryBatchSize: this._maxGeometryBatchSize
|
|
3277
|
+
maxGeometryBatchSize: this._maxGeometryBatchSize,
|
|
3278
|
+
primitive: cfg.primitive
|
|
3270
3279
|
});
|
|
3271
3280
|
break;
|
|
3272
3281
|
case "points":
|
|
@@ -3278,7 +3287,8 @@ export class SceneModel extends Component {
|
|
|
3278
3287
|
positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
|
|
3279
3288
|
uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
|
|
3280
3289
|
origin,
|
|
3281
|
-
maxGeometryBatchSize: this._maxGeometryBatchSize
|
|
3290
|
+
maxGeometryBatchSize: this._maxGeometryBatchSize,
|
|
3291
|
+
primitive: cfg.primitive
|
|
3282
3292
|
});
|
|
3283
3293
|
break;
|
|
3284
3294
|
}
|
|
@@ -3294,6 +3304,7 @@ export class SceneModel extends Component {
|
|
|
3294
3304
|
}
|
|
3295
3305
|
this._vboBatchingLayers[layerId] = vboBatchingLayer;
|
|
3296
3306
|
this.layerList.push(vboBatchingLayer);
|
|
3307
|
+
this._layersToFinalize.push(vboBatchingLayer);
|
|
3297
3308
|
return vboBatchingLayer;
|
|
3298
3309
|
}
|
|
3299
3310
|
|
|
@@ -3386,6 +3397,7 @@ export class SceneModel extends Component {
|
|
|
3386
3397
|
}
|
|
3387
3398
|
this._vboInstancingLayers[layerId] = vboInstancingLayer;
|
|
3388
3399
|
this.layerList.push(vboInstancingLayer);
|
|
3400
|
+
this._layersToFinalize.push(vboInstancingLayer);
|
|
3389
3401
|
return vboInstancingLayer;
|
|
3390
3402
|
}
|
|
3391
3403
|
|
|
@@ -3486,38 +3498,47 @@ export class SceneModel extends Component {
|
|
|
3486
3498
|
lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel
|
|
3487
3499
|
this._entityList.push(entity);
|
|
3488
3500
|
this._entities[cfg.id] = entity;
|
|
3501
|
+
this._entitiesToFinalize.push(entity);
|
|
3489
3502
|
this.numEntities++;
|
|
3490
3503
|
}
|
|
3491
3504
|
|
|
3492
3505
|
/**
|
|
3493
|
-
*
|
|
3494
|
-
*
|
|
3495
|
-
*
|
|
3506
|
+
* Pre-renders all meshes that have been added, even if the SceneModel has not bee finalized yet.
|
|
3507
|
+
* This is use for progressively showing the SceneModel while it is being loaded or constructed.
|
|
3508
|
+
* @returns {boolean}
|
|
3496
3509
|
*/
|
|
3497
|
-
|
|
3510
|
+
preFinalize() {
|
|
3498
3511
|
if (this.destroyed) {
|
|
3499
|
-
return;
|
|
3512
|
+
return false;
|
|
3513
|
+
}
|
|
3514
|
+
if (this._layersToFinalize.length === 0) {
|
|
3515
|
+
return false;
|
|
3500
3516
|
}
|
|
3501
3517
|
this._createDummyEntityForUnusedMeshes();
|
|
3502
|
-
for (let i = 0, len = this.
|
|
3503
|
-
const layer = this.
|
|
3518
|
+
for (let i = 0, len = this._layersToFinalize.length; i < len; i++) {
|
|
3519
|
+
const layer = this._layersToFinalize[i];
|
|
3504
3520
|
layer.finalize();
|
|
3505
3521
|
}
|
|
3506
|
-
this._geometries = {};
|
|
3507
|
-
this._dtxBuckets = {};
|
|
3508
|
-
this._textures = {};
|
|
3509
|
-
this._textureSets = {};
|
|
3510
|
-
this._dtxLayers = {};
|
|
3511
|
-
this._vboInstancingLayers = {};
|
|
3512
3522
|
this._vboBatchingLayers = {};
|
|
3513
|
-
|
|
3514
|
-
|
|
3523
|
+
this._vboInstancingLayers = {};
|
|
3524
|
+
this._dtxLayers = {};
|
|
3525
|
+
this._layersToFinalize = [];
|
|
3526
|
+
for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
|
|
3527
|
+
const entity = this._entitiesToFinalize[i];
|
|
3515
3528
|
entity._finalize();
|
|
3516
3529
|
}
|
|
3517
|
-
for (let i = 0, len = this.
|
|
3518
|
-
const entity = this.
|
|
3530
|
+
for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
|
|
3531
|
+
const entity = this._entitiesToFinalize[i];
|
|
3519
3532
|
entity._finalize2();
|
|
3520
3533
|
}
|
|
3534
|
+
this._entitiesToFinalize = [];
|
|
3535
|
+
this.scene._aabbDirty = true;
|
|
3536
|
+
this._viewMatrixDirty = true;
|
|
3537
|
+
this._matrixDirty = true;
|
|
3538
|
+
this._aabbDirty = true;
|
|
3539
|
+
this._setWorldMatrixDirty();
|
|
3540
|
+
this._sceneModelDirty();
|
|
3541
|
+
this.position = this._position;
|
|
3521
3542
|
// Sort layers to reduce WebGL shader switching when rendering them
|
|
3522
3543
|
this.layerList.sort((a, b) => {
|
|
3523
3544
|
if (a.sortId < b.sortId) {
|
|
@@ -3533,15 +3554,23 @@ export class SceneModel extends Component {
|
|
|
3533
3554
|
layer.layerIndex = i;
|
|
3534
3555
|
}
|
|
3535
3556
|
this.glRedraw();
|
|
3536
|
-
this.
|
|
3537
|
-
|
|
3538
|
-
this._matrixDirty = true;
|
|
3539
|
-
this._aabbDirty = true;
|
|
3540
|
-
|
|
3541
|
-
this._setWorldMatrixDirty();
|
|
3542
|
-
this._sceneModelDirty();
|
|
3557
|
+
this._layersFinalized = true;
|
|
3558
|
+
}
|
|
3543
3559
|
|
|
3544
|
-
|
|
3560
|
+
/**
|
|
3561
|
+
* Finalizes this SceneModel.
|
|
3562
|
+
*
|
|
3563
|
+
* Once finalized, you can't add anything more to this SceneModel.
|
|
3564
|
+
*/
|
|
3565
|
+
finalize() {
|
|
3566
|
+
if (this.destroyed) {
|
|
3567
|
+
return;
|
|
3568
|
+
}
|
|
3569
|
+
this.preFinalize();
|
|
3570
|
+
this._geometries = {};
|
|
3571
|
+
this._dtxBuckets = {};
|
|
3572
|
+
this._textures = {};
|
|
3573
|
+
this._textureSets = {};
|
|
3545
3574
|
}
|
|
3546
3575
|
|
|
3547
3576
|
/** @private */
|
|
@@ -3579,7 +3608,7 @@ export class SceneModel extends Component {
|
|
|
3579
3608
|
_createDummyEntityForUnusedMeshes() {
|
|
3580
3609
|
const unusedMeshIds = Object.keys(this._unusedMeshes);
|
|
3581
3610
|
if (unusedMeshIds.length > 0) {
|
|
3582
|
-
const entityId = `${this.id}
|
|
3611
|
+
const entityId = `${this.id}-${math.createUUID()}`;
|
|
3583
3612
|
this.warn(`Creating dummy SceneModelEntity "${entityId}" for unused SceneMeshes: [${unusedMeshIds.join(",")}]`)
|
|
3584
3613
|
this.createEntity({
|
|
3585
3614
|
id: entityId,
|
|
@@ -3951,6 +3980,7 @@ export class SceneModel extends Component {
|
|
|
3951
3980
|
for (let i = 0, len = this._entityList.length; i < len; i++) {
|
|
3952
3981
|
this._entityList[i]._destroy();
|
|
3953
3982
|
}
|
|
3983
|
+
this._layersToFinalize = {};
|
|
3954
3984
|
// Object.entries(this._geometries).forEach(([id, geometry]) => {
|
|
3955
3985
|
// geometry.destroy();
|
|
3956
3986
|
// });
|
|
@@ -633,7 +633,7 @@ export class SceneModelEntity {
|
|
|
633
633
|
for (let i = 0, len = this.meshes.length; i < len; i++) {
|
|
634
634
|
this.meshes[i]._setOffset(this._offset);
|
|
635
635
|
}
|
|
636
|
-
this._aabbDirty
|
|
636
|
+
this._aabbDirty = true;
|
|
637
637
|
this.model._aabbDirty = true;
|
|
638
638
|
this.scene._aabbDirty = true;
|
|
639
639
|
this.scene._objectOffsetUpdated(this, offset);
|
|
@@ -650,6 +650,51 @@ export class SceneModelEntity {
|
|
|
650
650
|
}
|
|
651
651
|
}
|
|
652
652
|
|
|
653
|
+
getEachIndex(callback) {
|
|
654
|
+
for (let i = 0, len = this.meshes.length; i < len; i++) {
|
|
655
|
+
this.meshes[i].getEachIndex(callback)
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Returns the volume of this SceneModelEntity.
|
|
661
|
+
*
|
|
662
|
+
* Only works when {@link Scene.readableGeometryEnabled | Scene.readableGeometryEnabled} is `true` and the
|
|
663
|
+
* SceneModelEntity contains solid triangle meshes; returns `0` otherwise.
|
|
664
|
+
*
|
|
665
|
+
* @returns {number}
|
|
666
|
+
*/
|
|
667
|
+
get volume() {
|
|
668
|
+
let volume = 0;
|
|
669
|
+
for (let i = 0, len = this.meshes.length; i < len; i++) {
|
|
670
|
+
const meshVolume = this.meshes[i].volume;
|
|
671
|
+
if (meshVolume < 0) {
|
|
672
|
+
return -1;
|
|
673
|
+
}
|
|
674
|
+
volume += meshVolume;
|
|
675
|
+
}
|
|
676
|
+
return volume;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Returns the surface area of this SceneModelEntity.
|
|
681
|
+
*
|
|
682
|
+
* Only works when {@link Scene.readableGeometryEnabled | Scene.readableGeometryEnabled} is `true` and the
|
|
683
|
+
* SceneModelEntity contains triangle meshes; returns `0` otherwise.
|
|
684
|
+
*
|
|
685
|
+
* @returns {number}
|
|
686
|
+
*/
|
|
687
|
+
get surfaceArea() {
|
|
688
|
+
let surfaceArea = 0;
|
|
689
|
+
for (let i = 0, len = this.meshes.length; i < len; i++) {
|
|
690
|
+
const meshSurfaceArea = this.meshes[i].surfaceArea;
|
|
691
|
+
if (meshSurfaceArea >= 0) {
|
|
692
|
+
surfaceArea += meshSurfaceArea;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return surfaceArea > 0 ? surfaceArea : -1;
|
|
696
|
+
}
|
|
697
|
+
|
|
653
698
|
_getFlag(flag) {
|
|
654
699
|
return !!(this._flags & flag);
|
|
655
700
|
}
|