@configura/babylon-view 1.3.0-alpha.3 → 1.3.0
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/LICENSE +201 -201
- package/README.md +1 -1
- package/dist/animation/AnimatableObject.d.ts +8 -8
- package/dist/animation/AnimatableObject.js +3 -3
- package/dist/animation/animator/Animator.d.ts +33 -33
- package/dist/animation/animator/Animator.js +58 -58
- package/dist/animation/animator/AnimatorEasing.d.ts +16 -16
- package/dist/animation/animator/AnimatorEasing.js +31 -31
- package/dist/animation/animator/AnimatorEasingMatrix.d.ts +14 -14
- package/dist/animation/animator/AnimatorEasingMatrix.js +16 -16
- package/dist/animation/animator/AnimatorHighlight.d.ts +16 -16
- package/dist/animation/animator/AnimatorHighlight.js +32 -32
- package/dist/animation/animator/AnimatorPointToPoint.d.ts +8 -8
- package/dist/animation/animator/AnimatorPointToPoint.js +14 -14
- package/dist/animation/animator/AnimatorQueue.d.ts +13 -13
- package/dist/animation/animator/AnimatorQueue.js +57 -57
- package/dist/animation/animator/AnimatorScale.d.ts +8 -8
- package/dist/animation/animator/AnimatorScale.js +13 -13
- package/dist/animation/animator/AnimatorSpin.d.ts +10 -10
- package/dist/animation/animator/AnimatorSpin.js +13 -13
- package/dist/animation/animator/EasingFunctions.d.ts +35 -35
- package/dist/animation/animator/EasingFunctions.js +137 -137
- package/dist/animation/coordinator/Coordinator.d.ts +28 -28
- package/dist/animation/coordinator/Coordinator.js +47 -47
- package/dist/animation/coordinator/CoordinatorDropAndSpin.d.ts +22 -22
- package/dist/animation/coordinator/CoordinatorDropAndSpin.js +133 -133
- package/dist/animation/coordinator/CoordinatorIdentity.d.ts +11 -11
- package/dist/animation/coordinator/CoordinatorIdentity.js +12 -12
- package/dist/animation/coordinator/CoordinatorNodeQueues.d.ts +18 -18
- package/dist/animation/coordinator/CoordinatorNodeQueues.js +50 -50
- package/dist/animation/coordinator/CoordinatorPulse.d.ts +21 -21
- package/dist/animation/coordinator/CoordinatorPulse.js +47 -47
- package/dist/animation/coordinator/CoordinatorPulseBounce.d.ts +14 -14
- package/dist/animation/coordinator/CoordinatorPulseBounce.js +40 -40
- package/dist/animation/coordinator/CoordinatorPulseHighlight.d.ts +13 -13
- package/dist/animation/coordinator/CoordinatorPulseHighlight.js +34 -34
- package/dist/animation/coordinator/CoordinatorPulseInflate.d.ts +14 -14
- package/dist/animation/coordinator/CoordinatorPulseInflate.js +30 -30
- package/dist/camera/CameraCreator.d.ts +5 -5
- package/dist/camera/CameraCreator.js +4 -4
- package/dist/camera/CfgArcRotateCameraPointersInput.d.ts +26 -10
- package/dist/camera/CfgArcRotateCameraPointersInput.js +264 -262
- package/dist/camera/CfgOrbitalCamera.d.ts +68 -68
- package/dist/camera/CfgOrbitalCamera.js +250 -250
- package/dist/camera/CfgOrbitalCameraControlProps.d.ts +6 -6
- package/dist/camera/CfgOrbitalCameraControlProps.js +3 -3
- package/dist/camera/GradingApplier.d.ts +3 -3
- package/dist/camera/GradingApplier.js +48 -48
- package/dist/engine/EngineCreator.d.ts +3 -3
- package/dist/engine/EngineCreator.js +10 -10
- package/dist/geometry/CfgGeometry.d.ts +29 -12
- package/dist/geometry/CfgGeometry.js +146 -117
- package/dist/geometry/CfgMesh.d.ts +10 -7
- package/dist/geometry/CfgMesh.js +38 -8
- package/dist/geometry/geoSplitter.d.ts +8 -8
- package/dist/geometry/geoSplitter.js +192 -192
- package/dist/geometry/stretch/CfgMorphTarget.d.ts +16 -0
- package/dist/geometry/stretch/CfgMorphTarget.js +65 -0
- package/dist/geometry/stretch/CfgStretchData.d.ts +115 -0
- package/dist/geometry/stretch/CfgStretchData.js +340 -0
- package/dist/geometry/stretch/CfgStretchMorphGeometry.d.ts +17 -0
- package/dist/geometry/stretch/CfgStretchMorphGeometry.js +95 -0
- package/dist/index.d.ts +13 -13
- package/dist/index.js +13 -13
- package/dist/light/CfgDirectionalLight.d.ts +8 -8
- package/dist/light/CfgDirectionalLight.js +18 -18
- package/dist/light/CfgHemisphericLight.d.ts +7 -7
- package/dist/light/CfgHemisphericLight.js +17 -17
- package/dist/light/CfgPointLight.d.ts +8 -8
- package/dist/light/CfgPointLight.js +18 -18
- package/dist/light/DefaultLightRig.d.ts +19 -19
- package/dist/light/DefaultLightRig.js +77 -77
- package/dist/light/LightRigCreator.d.ts +9 -9
- package/dist/light/LightRigCreator.js +3 -3
- package/dist/material/CfgMaterial.d.ts +68 -53
- package/dist/material/CfgMaterial.js +482 -454
- package/dist/material/DummyMaterialCreator.d.ts +4 -4
- package/dist/material/DummyMaterialCreator.js +15 -15
- package/dist/material/material.d.ts +18 -18
- package/dist/material/material.js +128 -128
- package/dist/material/texture.d.ts +14 -14
- package/dist/material/texture.js +306 -304
- package/dist/nodes/CfgContentRootNode.d.ts +19 -19
- package/dist/nodes/CfgContentRootNode.js +75 -75
- package/dist/nodes/CfgDeferredMeshNode.d.ts +55 -48
- package/dist/nodes/CfgDeferredMeshNode.js +377 -347
- package/dist/nodes/CfgProductNode.d.ts +126 -61
- package/dist/nodes/CfgProductNode.js +578 -486
- package/dist/nodes/CfgSymNode.d.ts +50 -42
- package/dist/nodes/CfgSymNode.js +249 -216
- package/dist/nodes/CfgSymRootNode.d.ts +45 -33
- package/dist/nodes/CfgSymRootNode.js +220 -175
- package/dist/nodes/CfgTransformNode.d.ts +33 -29
- package/dist/nodes/CfgTransformNode.js +83 -81
- package/dist/scene/SceneCreator.d.ts +6 -6
- package/dist/scene/SceneCreator.js +22 -22
- package/dist/utilities/CfgBoundingBox.d.ts +21 -16
- package/dist/utilities/CfgBoundingBox.js +81 -64
- package/dist/utilities/anchor/anchor.d.ts +52 -0
- package/dist/utilities/anchor/anchor.js +136 -0
- package/dist/utilities/anchor/anchorMap.d.ts +21 -0
- package/dist/utilities/anchor/anchorMap.js +111 -0
- package/dist/utilities/utilities3D.d.ts +70 -26
- package/dist/utilities/utilities3D.js +265 -187
- package/dist/utilities/utilitiesColor.d.ts +18 -18
- package/dist/utilities/utilitiesColor.js +48 -48
- package/dist/utilities/utilitiesImage.d.ts +6 -6
- package/dist/utilities/utilitiesImage.js +107 -107
- package/dist/utilities/utilitiesSymRootIdentifier.d.ts +7 -5
- package/dist/utilities/utilitiesSymRootIdentifier.js +26 -20
- package/dist/view/BaseView.d.ts +78 -70
- package/dist/view/BaseView.js +297 -291
- package/dist/view/BaseViewConfiguration.d.ts +32 -32
- package/dist/view/BaseViewConfiguration.js +8 -8
- package/dist/view/RenderEnv.d.ts +43 -38
- package/dist/view/RenderEnv.js +7 -7
- package/dist/view/SingleProductDefaultCameraView.d.ts +33 -33
- package/dist/view/SingleProductDefaultCameraView.js +141 -141
- package/dist/view/SingleProductDefaultCameraViewConfiguration.d.ts +46 -46
- package/dist/view/SingleProductDefaultCameraViewConfiguration.js +11 -11
- package/dist/view/SingleProductView.d.ts +49 -42
- package/dist/view/SingleProductView.js +206 -205
- package/dist/view/SingleProductViewConfiguration.d.ts +32 -32
- package/dist/view/SingleProductViewConfiguration.js +19 -19
- package/package.json +5 -5
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
import { VertexBuffer } from "@babylonjs/core/Meshes/buffer.js";
|
|
2
|
-
// Will try to split the geometry along planes on the xy, yz and xz-planes for
|
|
3
|
-
// a total of maximum 8 groups. If a triangle straddles a plane those groups
|
|
4
|
-
// will be merged
|
|
5
|
-
export function splitIndexQuick(logger, geo) {
|
|
6
|
-
const indexArray = geo.getIndices();
|
|
7
|
-
if (!indexArray) {
|
|
8
|
-
logger.info("No index array, could not try split geo");
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
const indexCount = geo.getTotalIndices();
|
|
12
|
-
if (indexCount === 0) {
|
|
13
|
-
logger.warn("Empty geo index");
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const positionArray = geo.getVerticesData(VertexBuffer.PositionKind);
|
|
17
|
-
if (!positionArray) {
|
|
18
|
-
logger.info("No position array, could not try split geo");
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
// Three axis, so max potential resultGroups 2^3
|
|
22
|
-
const resultGroups = [[], [], [], [], [], [], [], []];
|
|
23
|
-
for (let triIndex = 0; triIndex < indexCount; triIndex += 3) {
|
|
24
|
-
const belongsInGroups = [];
|
|
25
|
-
// For each triangle
|
|
26
|
-
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
27
|
-
const offset = indexArray[i] * 3;
|
|
28
|
-
let belongsIndex = 0;
|
|
29
|
-
for (let c = 0; c < 3; c++) {
|
|
30
|
-
belongsIndex += 0 <= positionArray[offset + c] ? 1 << c : 0;
|
|
31
|
-
}
|
|
32
|
-
if (!belongsInGroups.some((g) => g === belongsIndex)) {
|
|
33
|
-
belongsInGroups.push(belongsIndex);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
const targetGroup = resultGroups[belongsInGroups[0]];
|
|
37
|
-
// Merge groups straddled by this triangle (if needed)
|
|
38
|
-
for (let i = 1; i < belongsInGroups.length; i++) {
|
|
39
|
-
const resultGroupIndex = belongsInGroups[i];
|
|
40
|
-
const otherGroup = resultGroups[resultGroupIndex];
|
|
41
|
-
// Let this position in the result groups array point to the same group as they share
|
|
42
|
-
// at least one triangle
|
|
43
|
-
if (targetGroup !== otherGroup) {
|
|
44
|
-
// The group can be in multiple positions
|
|
45
|
-
let j = resultGroups.length;
|
|
46
|
-
while (j--) {
|
|
47
|
-
if (otherGroup === resultGroups[j]) {
|
|
48
|
-
resultGroups[j] = targetGroup;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const otherGroupLength = otherGroup.length;
|
|
52
|
-
for (let j = 0; j < otherGroupLength; j++) {
|
|
53
|
-
targetGroup.push(otherGroup[j]);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
58
|
-
targetGroup.push(indexArray[i]);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// Filter so that we only get one instance of each group and no empty groups
|
|
62
|
-
let i = resultGroups.length;
|
|
63
|
-
while (i--) {
|
|
64
|
-
const group = resultGroups[i];
|
|
65
|
-
if (group.length === 0) {
|
|
66
|
-
resultGroups.splice(i, 1);
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
let j = i;
|
|
70
|
-
while (j--) {
|
|
71
|
-
if (group === resultGroups[j]) {
|
|
72
|
-
resultGroups.splice(i, 1);
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return resultGroups;
|
|
78
|
-
}
|
|
79
|
-
export function splitIndexComplete(logger, geo, conf) {
|
|
80
|
-
const { maxProgressGroups, maxFinalGroups, acceptCoordinateMatch } = conf;
|
|
81
|
-
const indexArray = geo.getIndices();
|
|
82
|
-
if (!indexArray) {
|
|
83
|
-
logger.info("No index array, could not try split geo");
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
const indexCount = geo.getTotalIndices();
|
|
87
|
-
if (indexCount === 0) {
|
|
88
|
-
logger.warn("Empty geo index");
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const positionArray = geo.getVerticesData(VertexBuffer.PositionKind);
|
|
92
|
-
if (!positionArray) {
|
|
93
|
-
logger.info("No position array, could not try split geo");
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const resultGroups = [];
|
|
97
|
-
let targetGroup;
|
|
98
|
-
// Loop over each triangle in the index
|
|
99
|
-
for (let triIndex = 0; triIndex < indexCount; triIndex += 3) {
|
|
100
|
-
// Groups that neighbor this triangle
|
|
101
|
-
const intersectingGroupIndices = [];
|
|
102
|
-
const resultGroupsCount = resultGroups.length;
|
|
103
|
-
if (maxProgressGroups < resultGroupsCount) {
|
|
104
|
-
logger.info(`Geo split into too many groups while in progress`, `(max allowed ${maxProgressGroups})`);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// Loop over each group.
|
|
108
|
-
for (let resultGroupIndex = 0; resultGroupIndex < resultGroupsCount; resultGroupIndex++) {
|
|
109
|
-
const group = resultGroups[resultGroupIndex];
|
|
110
|
-
const groupLength = group.length;
|
|
111
|
-
let found = false;
|
|
112
|
-
// For nodes in the current triangle
|
|
113
|
-
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
114
|
-
let j = groupLength;
|
|
115
|
-
// Loop backwards through indices in the group. Backwards since it's likely new
|
|
116
|
-
// nodes will be close to previous ones
|
|
117
|
-
while (j--) {
|
|
118
|
-
if (indexArray[i] === group[j]) {
|
|
119
|
-
intersectingGroupIndices.push(resultGroupIndex);
|
|
120
|
-
found = true;
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (found) {
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (!found && acceptCoordinateMatch) {
|
|
129
|
-
// For nodes in the current triangle
|
|
130
|
-
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
131
|
-
let j = groupLength;
|
|
132
|
-
// Loop backwards through indices in the group. Backwards since it's likely new
|
|
133
|
-
// nodes will be close to previous ones
|
|
134
|
-
while (j--) {
|
|
135
|
-
const offset1 = indexArray[i] * 3;
|
|
136
|
-
const offset2 = group[j] * 3;
|
|
137
|
-
let c = 3;
|
|
138
|
-
while (c--) {
|
|
139
|
-
if (positionArray[offset1 + c] !== positionArray[offset2 + c]) {
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (c === -1) {
|
|
144
|
-
intersectingGroupIndices.push(resultGroupIndex);
|
|
145
|
-
found = true;
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (found) {
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
targetGroup = undefined;
|
|
156
|
-
const intersectingGroupIndicesCount = intersectingGroupIndices.length;
|
|
157
|
-
if (intersectingGroupIndicesCount === 0) {
|
|
158
|
-
// The triangle is not adjacent to any existing node in any group
|
|
159
|
-
targetGroup = [];
|
|
160
|
-
resultGroups.push(targetGroup);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
let i = intersectingGroupIndicesCount - 1;
|
|
164
|
-
// Pick one (probably not important which one) to merge the other groups into. If this
|
|
165
|
-
// was the only one it will skip the loop
|
|
166
|
-
targetGroup = resultGroups[intersectingGroupIndices[i]];
|
|
167
|
-
// The nodes are sorted in ascending order. So we back through to nodes to allow us to
|
|
168
|
-
// use splice without disturbing unbroken ground.
|
|
169
|
-
while (i--) {
|
|
170
|
-
// Move all nodes to the target group and remove this one, as the latest triangle
|
|
171
|
-
// is adjacent to both
|
|
172
|
-
const resultGroupIndex = intersectingGroupIndices[i];
|
|
173
|
-
const group = resultGroups[resultGroupIndex];
|
|
174
|
-
resultGroups.splice(resultGroupIndex, 1);
|
|
175
|
-
const resultGroupCount = group.length;
|
|
176
|
-
for (let j = 0; j < resultGroupCount; j++) {
|
|
177
|
-
targetGroup.push(group[j]);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// Add the latest triangle to the target group
|
|
182
|
-
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
183
|
-
targetGroup.push(indexArray[i]);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const resultGroupsCount = resultGroups.length;
|
|
187
|
-
if (resultGroupsCount > maxFinalGroups) {
|
|
188
|
-
logger.info(`Geo split into too many final groups`, `(actual ${resultGroupsCount}, max allowed ${maxFinalGroups})`);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
return resultGroups;
|
|
192
|
-
}
|
|
1
|
+
import { VertexBuffer } from "@babylonjs/core/Meshes/buffer.js";
|
|
2
|
+
// Will try to split the geometry along planes on the xy, yz and xz-planes for
|
|
3
|
+
// a total of maximum 8 groups. If a triangle straddles a plane those groups
|
|
4
|
+
// will be merged
|
|
5
|
+
export function splitIndexQuick(logger, geo) {
|
|
6
|
+
const indexArray = geo.getIndices();
|
|
7
|
+
if (!indexArray) {
|
|
8
|
+
logger.info("No index array, could not try split geo");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const indexCount = geo.getTotalIndices();
|
|
12
|
+
if (indexCount === 0) {
|
|
13
|
+
logger.warn("Empty geo index");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const positionArray = geo.getVerticesData(VertexBuffer.PositionKind);
|
|
17
|
+
if (!positionArray) {
|
|
18
|
+
logger.info("No position array, could not try split geo");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Three axis, so max potential resultGroups 2^3
|
|
22
|
+
const resultGroups = [[], [], [], [], [], [], [], []];
|
|
23
|
+
for (let triIndex = 0; triIndex < indexCount; triIndex += 3) {
|
|
24
|
+
const belongsInGroups = [];
|
|
25
|
+
// For each triangle
|
|
26
|
+
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
27
|
+
const offset = indexArray[i] * 3;
|
|
28
|
+
let belongsIndex = 0;
|
|
29
|
+
for (let c = 0; c < 3; c++) {
|
|
30
|
+
belongsIndex += 0 <= positionArray[offset + c] ? 1 << c : 0;
|
|
31
|
+
}
|
|
32
|
+
if (!belongsInGroups.some((g) => g === belongsIndex)) {
|
|
33
|
+
belongsInGroups.push(belongsIndex);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const targetGroup = resultGroups[belongsInGroups[0]];
|
|
37
|
+
// Merge groups straddled by this triangle (if needed)
|
|
38
|
+
for (let i = 1; i < belongsInGroups.length; i++) {
|
|
39
|
+
const resultGroupIndex = belongsInGroups[i];
|
|
40
|
+
const otherGroup = resultGroups[resultGroupIndex];
|
|
41
|
+
// Let this position in the result groups array point to the same group as they share
|
|
42
|
+
// at least one triangle
|
|
43
|
+
if (targetGroup !== otherGroup) {
|
|
44
|
+
// The group can be in multiple positions
|
|
45
|
+
let j = resultGroups.length;
|
|
46
|
+
while (j--) {
|
|
47
|
+
if (otherGroup === resultGroups[j]) {
|
|
48
|
+
resultGroups[j] = targetGroup;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const otherGroupLength = otherGroup.length;
|
|
52
|
+
for (let j = 0; j < otherGroupLength; j++) {
|
|
53
|
+
targetGroup.push(otherGroup[j]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
58
|
+
targetGroup.push(indexArray[i]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Filter so that we only get one instance of each group and no empty groups
|
|
62
|
+
let i = resultGroups.length;
|
|
63
|
+
while (i--) {
|
|
64
|
+
const group = resultGroups[i];
|
|
65
|
+
if (group.length === 0) {
|
|
66
|
+
resultGroups.splice(i, 1);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
let j = i;
|
|
70
|
+
while (j--) {
|
|
71
|
+
if (group === resultGroups[j]) {
|
|
72
|
+
resultGroups.splice(i, 1);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return resultGroups;
|
|
78
|
+
}
|
|
79
|
+
export function splitIndexComplete(logger, geo, conf) {
|
|
80
|
+
const { maxProgressGroups, maxFinalGroups, acceptCoordinateMatch } = conf;
|
|
81
|
+
const indexArray = geo.getIndices();
|
|
82
|
+
if (!indexArray) {
|
|
83
|
+
logger.info("No index array, could not try split geo");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const indexCount = geo.getTotalIndices();
|
|
87
|
+
if (indexCount === 0) {
|
|
88
|
+
logger.warn("Empty geo index");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const positionArray = geo.getVerticesData(VertexBuffer.PositionKind);
|
|
92
|
+
if (!positionArray) {
|
|
93
|
+
logger.info("No position array, could not try split geo");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const resultGroups = [];
|
|
97
|
+
let targetGroup;
|
|
98
|
+
// Loop over each triangle in the index
|
|
99
|
+
for (let triIndex = 0; triIndex < indexCount; triIndex += 3) {
|
|
100
|
+
// Groups that neighbor this triangle
|
|
101
|
+
const intersectingGroupIndices = [];
|
|
102
|
+
const resultGroupsCount = resultGroups.length;
|
|
103
|
+
if (maxProgressGroups < resultGroupsCount) {
|
|
104
|
+
logger.info(`Geo split into too many groups while in progress`, `(max allowed ${maxProgressGroups})`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// Loop over each group.
|
|
108
|
+
for (let resultGroupIndex = 0; resultGroupIndex < resultGroupsCount; resultGroupIndex++) {
|
|
109
|
+
const group = resultGroups[resultGroupIndex];
|
|
110
|
+
const groupLength = group.length;
|
|
111
|
+
let found = false;
|
|
112
|
+
// For nodes in the current triangle
|
|
113
|
+
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
114
|
+
let j = groupLength;
|
|
115
|
+
// Loop backwards through indices in the group. Backwards since it's likely new
|
|
116
|
+
// nodes will be close to previous ones
|
|
117
|
+
while (j--) {
|
|
118
|
+
if (indexArray[i] === group[j]) {
|
|
119
|
+
intersectingGroupIndices.push(resultGroupIndex);
|
|
120
|
+
found = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (found) {
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!found && acceptCoordinateMatch) {
|
|
129
|
+
// For nodes in the current triangle
|
|
130
|
+
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
131
|
+
let j = groupLength;
|
|
132
|
+
// Loop backwards through indices in the group. Backwards since it's likely new
|
|
133
|
+
// nodes will be close to previous ones
|
|
134
|
+
while (j--) {
|
|
135
|
+
const offset1 = indexArray[i] * 3;
|
|
136
|
+
const offset2 = group[j] * 3;
|
|
137
|
+
let c = 3;
|
|
138
|
+
while (c--) {
|
|
139
|
+
if (positionArray[offset1 + c] !== positionArray[offset2 + c]) {
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (c === -1) {
|
|
144
|
+
intersectingGroupIndices.push(resultGroupIndex);
|
|
145
|
+
found = true;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (found) {
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
targetGroup = undefined;
|
|
156
|
+
const intersectingGroupIndicesCount = intersectingGroupIndices.length;
|
|
157
|
+
if (intersectingGroupIndicesCount === 0) {
|
|
158
|
+
// The triangle is not adjacent to any existing node in any group
|
|
159
|
+
targetGroup = [];
|
|
160
|
+
resultGroups.push(targetGroup);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
let i = intersectingGroupIndicesCount - 1;
|
|
164
|
+
// Pick one (probably not important which one) to merge the other groups into. If this
|
|
165
|
+
// was the only one it will skip the loop
|
|
166
|
+
targetGroup = resultGroups[intersectingGroupIndices[i]];
|
|
167
|
+
// The nodes are sorted in ascending order. So we back through to nodes to allow us to
|
|
168
|
+
// use splice without disturbing unbroken ground.
|
|
169
|
+
while (i--) {
|
|
170
|
+
// Move all nodes to the target group and remove this one, as the latest triangle
|
|
171
|
+
// is adjacent to both
|
|
172
|
+
const resultGroupIndex = intersectingGroupIndices[i];
|
|
173
|
+
const group = resultGroups[resultGroupIndex];
|
|
174
|
+
resultGroups.splice(resultGroupIndex, 1);
|
|
175
|
+
const resultGroupCount = group.length;
|
|
176
|
+
for (let j = 0; j < resultGroupCount; j++) {
|
|
177
|
+
targetGroup.push(group[j]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Add the latest triangle to the target group
|
|
182
|
+
for (let i = triIndex; i < triIndex + 3; i++) {
|
|
183
|
+
targetGroup.push(indexArray[i]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const resultGroupsCount = resultGroups.length;
|
|
187
|
+
if (resultGroupsCount > maxFinalGroups) {
|
|
188
|
+
logger.info(`Geo split into too many final groups`, `(actual ${resultGroupsCount}, max allowed ${maxFinalGroups})`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
return resultGroups;
|
|
192
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MorphTarget } from "@babylonjs/core/Morph/morphTarget.js";
|
|
2
|
+
import { CfgProductNode } from "../../nodes/CfgProductNode.js";
|
|
3
|
+
import { CfgStretchData } from "./CfgStretchData.js";
|
|
4
|
+
import { CfgMorphTwiceStretchedGeometry } from "./CfgStretchMorphGeometry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Contains geometry which when added to the original geometry will move the vertices to where
|
|
7
|
+
* they should be when the stretchReference length doubles.
|
|
8
|
+
*/
|
|
9
|
+
export declare class CfgMorphTarget extends MorphTarget {
|
|
10
|
+
private _morphGeometry;
|
|
11
|
+
readonly cfgProductNodeParent: CfgProductNode;
|
|
12
|
+
constructor(_morphGeometry: CfgMorphTwiceStretchedGeometry, cfgProductNodeParent: CfgProductNode);
|
|
13
|
+
get stretchData(): CfgStretchData;
|
|
14
|
+
refreshStretch(): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=CfgMorphTarget.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { MorphTarget } from "@babylonjs/core/Morph/morphTarget.js";
|
|
2
|
+
/**
|
|
3
|
+
* Contains geometry which when added to the original geometry will move the vertices to where
|
|
4
|
+
* they should be when the stretchReference length doubles.
|
|
5
|
+
*/
|
|
6
|
+
export class CfgMorphTarget extends MorphTarget {
|
|
7
|
+
constructor(_morphGeometry, cfgProductNodeParent) {
|
|
8
|
+
super(_morphGeometry.id);
|
|
9
|
+
this._morphGeometry = _morphGeometry;
|
|
10
|
+
this.cfgProductNodeParent = cfgProductNodeParent;
|
|
11
|
+
const { pos, uvs } = _morphGeometry;
|
|
12
|
+
this.setPositions(pos);
|
|
13
|
+
if (uvs !== undefined) {
|
|
14
|
+
this.setUVs(uvs);
|
|
15
|
+
}
|
|
16
|
+
this.refreshStretch();
|
|
17
|
+
}
|
|
18
|
+
get stretchData() {
|
|
19
|
+
return this._morphGeometry.stretchData;
|
|
20
|
+
}
|
|
21
|
+
refreshStretch() {
|
|
22
|
+
const stretchReferenceLengthsByMeasureParamCode = this.cfgProductNodeParent.product.configuration._internal
|
|
23
|
+
.stretchReferenceLengthsByMeasureParamCode;
|
|
24
|
+
const referenceLength = stretchReferenceLengthsByMeasureParamCode.get(this.stretchData.measureParam);
|
|
25
|
+
const influence = referenceLength === undefined
|
|
26
|
+
? 0
|
|
27
|
+
: this.stretchData.calculateInfluenceGivenTwiceMorphTarget(referenceLength.current);
|
|
28
|
+
if (this.influence === influence) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
/* WORKAROUND for render failure
|
|
32
|
+
*
|
|
33
|
+
* Setting an influence to 0 (zero) will actually remove the MorphTarget from the list of
|
|
34
|
+
* "active" MorphTargets in the MorphTargetManager in Babylon.js.
|
|
35
|
+
*
|
|
36
|
+
* This is probably an performance optimization since it means less calculations has to be
|
|
37
|
+
* done the shaders. Another reason could be a workaround for a technical limitation in
|
|
38
|
+
* WebGL1 that limits the maximum number of MorphTargets in Babylon.js:
|
|
39
|
+
* https://doc.babylonjs.com/divingDeeper/mesh/morphTargets#limitations
|
|
40
|
+
*
|
|
41
|
+
* For some reason this causes problems for us, at least with the combination of Windows 10
|
|
42
|
+
* + Chromium + Babylon 4.2, in where disabling a previous active MorphTarget (i.e. setting
|
|
43
|
+
* influence to 0) will cause the first frame in BaseView.BrowserTick to fail to render,
|
|
44
|
+
* ending up an empty frame with the following error in the console:
|
|
45
|
+
*
|
|
46
|
+
* WebGL: INVALID_OPERATION: drawElements: no buffer is bound to enabled attribute
|
|
47
|
+
* ThinEngine.drawElementsType @ thinEngine.ts:1995
|
|
48
|
+
* Mesh._draw @ mesh.ts:1542
|
|
49
|
+
* Mesh._processRendering @ mesh.ts:1740
|
|
50
|
+
* Mesh.render @ mesh.ts:1930
|
|
51
|
+
* [...]
|
|
52
|
+
*
|
|
53
|
+
* The theory we have is that the change of active MorphTargets needs some time or other
|
|
54
|
+
* event to properly settle in, perhaps due to it changing the shaders. Digging in the
|
|
55
|
+
* Babylon.js source code has not reveled anything useful so far.
|
|
56
|
+
*
|
|
57
|
+
* As a workaround, set the influence to Number.MIN_VALUE (smallest non-zero value) instead
|
|
58
|
+
* of 0. This keeps it the actual influence as zero in practice, but keeps the MorphTarget
|
|
59
|
+
* active and no longer triggers the render failure.
|
|
60
|
+
*
|
|
61
|
+
* TODO: Revisit this when we switch to a new major release of Babylon.js, 5.0 is next.
|
|
62
|
+
*/
|
|
63
|
+
this.influence = influence === 0 ? Number.MIN_VALUE : influence;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Matrix, Vector3 } from "@babylonjs/core/Maths/math.vector.js";
|
|
2
|
+
import { LengthValue, StretchMap } from "@configura/web-api";
|
|
3
|
+
import { SymNode } from "@configura/web-core/dist/cm/format/cmsym/SymNode.js";
|
|
4
|
+
import { DetailLevel } from "@configura/web-core/dist/cm/geometry/DetailMask.js";
|
|
5
|
+
import { Logger } from "@configura/web-utilities";
|
|
6
|
+
/**
|
|
7
|
+
* How far along from sp to ep is a point on a plane crossing the sp to ep line?
|
|
8
|
+
* 1 means at ep, 0 means at sp.
|
|
9
|
+
*/
|
|
10
|
+
export declare function calculateAlongness(p: Vector3, sp: Vector3, spToEpLength: number, normalizedNormal: Vector3): number;
|
|
11
|
+
/**
|
|
12
|
+
* Where does the point p end up given the CfgStretchDatas and the StretchMap.
|
|
13
|
+
* This is the same equations that Babylon uses for stretching, only Babylon does it in the
|
|
14
|
+
* shaders during rendering and is thus GPU accelerated.
|
|
15
|
+
* This version is much slower, but that is okay as long as this function is sparingly used.
|
|
16
|
+
*/
|
|
17
|
+
export declare const toStretchedPoint: (p: Vector3, stretchDatas: CfgStretchData[], stretchReferenceLengthsByMeasureParamCode: StretchMap) => Vector3;
|
|
18
|
+
/**
|
|
19
|
+
* The end of a section is the beginning of the next.
|
|
20
|
+
* Start/end are redundant, but both are kept for ease of access.
|
|
21
|
+
* The first section will have startAlongness 0. This does not mean that things can't be outside.
|
|
22
|
+
* The start section should be thought of as endless in the sp-direction.
|
|
23
|
+
* The last section will have endAlongness 0. This does not mean that things can't be outside.
|
|
24
|
+
* The end section should be thought of as endless in the ep-direction.
|
|
25
|
+
*/
|
|
26
|
+
export declare type StretchSection = {
|
|
27
|
+
last: boolean;
|
|
28
|
+
sizeChange: number;
|
|
29
|
+
move: boolean;
|
|
30
|
+
startAlongness: number;
|
|
31
|
+
endAlongness: number;
|
|
32
|
+
atTwiceTranslation: number;
|
|
33
|
+
atTwiceScale: number;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Please note that stretch is not bound to be contained between sp and ep.
|
|
37
|
+
*
|
|
38
|
+
* The thinking in the equations in CfgStretchData is that we want to support MorphTargets in an as
|
|
39
|
+
* efficient manner as possible. As MorphTargets work by morphing between pre-compiled meshes we
|
|
40
|
+
* calculate what happens if you stretch to twice the referenceLength, to make MorphTargets for
|
|
41
|
+
* twice the referenceLength, and then calculate how these MorphTargets should be applied to
|
|
42
|
+
* achieve to requested referenceLength.
|
|
43
|
+
*
|
|
44
|
+
* This adaption to MorphTargets might make the code for stretching points for other purposes look
|
|
45
|
+
* (be) a bit complicated. However, as a mesh often contains millions of vertices that needs to be
|
|
46
|
+
* moved and calculating for bounding boxes, and anchor points and such moves very few vertices,
|
|
47
|
+
* this is okay.
|
|
48
|
+
*
|
|
49
|
+
* Using "Twice" as the precomputed target is arbitrarily, we just chose it because it makes
|
|
50
|
+
* equations simple.
|
|
51
|
+
*/
|
|
52
|
+
export declare class CfgStretchData {
|
|
53
|
+
readonly detailLevel: DetailLevel;
|
|
54
|
+
readonly measureParam: string;
|
|
55
|
+
readonly originalReferenceLength: number | undefined;
|
|
56
|
+
readonly sp: Vector3;
|
|
57
|
+
readonly ep: Vector3;
|
|
58
|
+
readonly spToEpLength: number;
|
|
59
|
+
readonly originalSpToEpLength: number;
|
|
60
|
+
readonly normal: Vector3;
|
|
61
|
+
readonly normalNormalized: Vector3;
|
|
62
|
+
readonly sections: StretchSection[];
|
|
63
|
+
static make(logger: Logger, symNode: SymNode, detailLevel: DetailLevel): CfgStretchData;
|
|
64
|
+
private static processSections;
|
|
65
|
+
/**
|
|
66
|
+
* It is assumed that the symNode passed really is stretch (symNodeIsStretch has been run)
|
|
67
|
+
* so any data missing for stretch will be an Exception.
|
|
68
|
+
*
|
|
69
|
+
* @param detailLevel
|
|
70
|
+
* @param measureParam Name of the parameter controlling the stretch
|
|
71
|
+
* @param originalReferenceLength Server-side calculated original referenceLength. We do not
|
|
72
|
+
* actually use this for anything, but it can be handy for debug.
|
|
73
|
+
* @param sp Start Point, the start anchor of the stretch line.
|
|
74
|
+
* @param ep End Point, the end anchor of the stretch line.
|
|
75
|
+
* @param spToEpLength Distance from sp to ep.
|
|
76
|
+
* @param originalSpToEpLength spToEpLength before transforms.
|
|
77
|
+
* @param normal The normal is from sp to ep and is the normal of every plane that divides this
|
|
78
|
+
* stretch.
|
|
79
|
+
* @param normalNormalized Normalized version of normal
|
|
80
|
+
* @param sections The slices the model is sliced into
|
|
81
|
+
*/
|
|
82
|
+
private constructor();
|
|
83
|
+
private _hash;
|
|
84
|
+
get hash(): number;
|
|
85
|
+
/** How far along between sp and ep is p? */
|
|
86
|
+
getAlongness: (p: Vector3) => number;
|
|
87
|
+
/**
|
|
88
|
+
* If the Matrix is identity the original CfgStretchData is returned.
|
|
89
|
+
* If not a new CfgStretchData will be created.
|
|
90
|
+
* sp, ep, spToEpLength, normal, normalNormalized, scale will be cloned and transformed
|
|
91
|
+
* The rest will still reference the original objects
|
|
92
|
+
*/
|
|
93
|
+
applyMatrix(matrix: Matrix): CfgStretchData;
|
|
94
|
+
/**
|
|
95
|
+
* Calculates the translation of a point which moves it from its original position to where it
|
|
96
|
+
* would be if we stretched to twice the reference length. Please note: this gives the
|
|
97
|
+
* translation, not the new location. The new location will be p.add(stretchPointToTwice(p))
|
|
98
|
+
*/
|
|
99
|
+
stretchPointToTwice(p: Vector3): Vector3;
|
|
100
|
+
/**
|
|
101
|
+
* Given a reference length calculates the influence that should be applied to a MorphTarget to
|
|
102
|
+
* achieve the requested length, given that these MorphTargets are constructed so that they
|
|
103
|
+
* will double the length when the influence 1 is applied.
|
|
104
|
+
*
|
|
105
|
+
* Please note that the referenceLength is the wanted length between sp and ep, that is, the
|
|
106
|
+
* stretch line. This line does not have to be span the entire model. Also, there can be
|
|
107
|
+
* multiple stretch lines that are not orthogonal to this, and the will also affect the actual
|
|
108
|
+
* size. Finally there can be transforms applied in the tree. So, the referenceLength will only
|
|
109
|
+
* be the actual length of the model in specific cases. However, we believe that models with
|
|
110
|
+
* stretch are often constructed in such a way that in real use cases the referenceLength is
|
|
111
|
+
* the actual real length.
|
|
112
|
+
*/
|
|
113
|
+
calculateInfluenceGivenTwiceMorphTarget(referenceLength: LengthValue): number;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=CfgStretchData.d.ts.map
|