@configura/babylon-view 1.2.1 → 1.3.0-alpha.3

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 (115) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +1 -1
  3. package/dist/animation/AnimatableObject.d.ts +8 -8
  4. package/dist/animation/AnimatableObject.js +3 -3
  5. package/dist/animation/animator/Animator.d.ts +33 -33
  6. package/dist/animation/animator/Animator.js +58 -58
  7. package/dist/animation/animator/AnimatorEasing.d.ts +16 -16
  8. package/dist/animation/animator/AnimatorEasing.js +31 -31
  9. package/dist/animation/animator/AnimatorEasingMatrix.d.ts +14 -14
  10. package/dist/animation/animator/AnimatorEasingMatrix.js +16 -16
  11. package/dist/animation/animator/AnimatorHighlight.d.ts +16 -16
  12. package/dist/animation/animator/AnimatorHighlight.js +32 -32
  13. package/dist/animation/animator/AnimatorPointToPoint.d.ts +8 -8
  14. package/dist/animation/animator/AnimatorPointToPoint.js +14 -14
  15. package/dist/animation/animator/AnimatorQueue.d.ts +13 -13
  16. package/dist/animation/animator/AnimatorQueue.js +57 -57
  17. package/dist/animation/animator/AnimatorScale.d.ts +8 -8
  18. package/dist/animation/animator/AnimatorScale.js +13 -13
  19. package/dist/animation/animator/AnimatorSpin.d.ts +10 -10
  20. package/dist/animation/animator/AnimatorSpin.js +13 -13
  21. package/dist/animation/animator/EasingFunctions.d.ts +35 -35
  22. package/dist/animation/animator/EasingFunctions.js +137 -137
  23. package/dist/animation/coordinator/Coordinator.d.ts +28 -28
  24. package/dist/animation/coordinator/Coordinator.js +47 -47
  25. package/dist/animation/coordinator/CoordinatorDropAndSpin.d.ts +22 -22
  26. package/dist/animation/coordinator/CoordinatorDropAndSpin.js +133 -133
  27. package/dist/animation/coordinator/CoordinatorIdentity.d.ts +11 -11
  28. package/dist/animation/coordinator/CoordinatorIdentity.js +12 -12
  29. package/dist/animation/coordinator/CoordinatorNodeQueues.d.ts +18 -18
  30. package/dist/animation/coordinator/CoordinatorNodeQueues.js +50 -50
  31. package/dist/animation/coordinator/CoordinatorPulse.d.ts +21 -21
  32. package/dist/animation/coordinator/CoordinatorPulse.js +47 -47
  33. package/dist/animation/coordinator/CoordinatorPulseBounce.d.ts +14 -14
  34. package/dist/animation/coordinator/CoordinatorPulseBounce.js +40 -40
  35. package/dist/animation/coordinator/CoordinatorPulseHighlight.d.ts +13 -13
  36. package/dist/animation/coordinator/CoordinatorPulseHighlight.js +34 -34
  37. package/dist/animation/coordinator/CoordinatorPulseInflate.d.ts +14 -14
  38. package/dist/animation/coordinator/CoordinatorPulseInflate.js +30 -30
  39. package/dist/camera/CameraCreator.d.ts +5 -5
  40. package/dist/camera/CameraCreator.js +4 -4
  41. package/dist/camera/CfgArcRotateCameraPointersInput.d.ts +10 -10
  42. package/dist/camera/CfgArcRotateCameraPointersInput.js +262 -262
  43. package/dist/camera/CfgOrbitalCamera.d.ts +68 -64
  44. package/dist/camera/CfgOrbitalCamera.js +250 -233
  45. package/dist/camera/CfgOrbitalCameraControlProps.d.ts +6 -6
  46. package/dist/camera/CfgOrbitalCameraControlProps.js +3 -3
  47. package/dist/camera/GradingApplier.d.ts +3 -3
  48. package/dist/camera/GradingApplier.js +48 -48
  49. package/dist/engine/EngineCreator.d.ts +3 -3
  50. package/dist/engine/EngineCreator.js +10 -10
  51. package/dist/geometry/CfgGeometry.d.ts +12 -12
  52. package/dist/geometry/CfgGeometry.js +117 -117
  53. package/dist/geometry/CfgMesh.d.ts +7 -7
  54. package/dist/geometry/CfgMesh.js +8 -8
  55. package/dist/geometry/geoSplitter.d.ts +8 -8
  56. package/dist/geometry/geoSplitter.js +192 -192
  57. package/dist/index.d.ts +13 -13
  58. package/dist/index.js +13 -13
  59. package/dist/light/CfgDirectionalLight.d.ts +8 -8
  60. package/dist/light/CfgDirectionalLight.js +18 -18
  61. package/dist/light/CfgHemisphericLight.d.ts +7 -7
  62. package/dist/light/CfgHemisphericLight.js +17 -17
  63. package/dist/light/CfgPointLight.d.ts +8 -8
  64. package/dist/light/CfgPointLight.js +18 -18
  65. package/dist/light/DefaultLightRig.d.ts +19 -19
  66. package/dist/light/DefaultLightRig.js +77 -77
  67. package/dist/light/LightRigCreator.d.ts +9 -9
  68. package/dist/light/LightRigCreator.js +3 -3
  69. package/dist/material/CfgMaterial.d.ts +53 -53
  70. package/dist/material/CfgMaterial.js +454 -454
  71. package/dist/material/DummyMaterialCreator.d.ts +4 -4
  72. package/dist/material/DummyMaterialCreator.js +15 -15
  73. package/dist/material/material.d.ts +18 -18
  74. package/dist/material/material.js +128 -128
  75. package/dist/material/texture.d.ts +14 -14
  76. package/dist/material/texture.js +304 -304
  77. package/dist/nodes/CfgContentRootNode.d.ts +19 -19
  78. package/dist/nodes/CfgContentRootNode.js +75 -75
  79. package/dist/nodes/CfgDeferredMeshNode.d.ts +48 -48
  80. package/dist/nodes/CfgDeferredMeshNode.js +347 -347
  81. package/dist/nodes/CfgProductNode.d.ts +61 -61
  82. package/dist/nodes/CfgProductNode.js +486 -486
  83. package/dist/nodes/CfgSymNode.d.ts +42 -42
  84. package/dist/nodes/CfgSymNode.js +216 -216
  85. package/dist/nodes/CfgSymRootNode.d.ts +33 -33
  86. package/dist/nodes/CfgSymRootNode.js +175 -175
  87. package/dist/nodes/CfgTransformNode.d.ts +29 -29
  88. package/dist/nodes/CfgTransformNode.js +81 -81
  89. package/dist/scene/SceneCreator.d.ts +6 -6
  90. package/dist/scene/SceneCreator.js +22 -22
  91. package/dist/utilities/CfgBoundingBox.d.ts +16 -16
  92. package/dist/utilities/CfgBoundingBox.js +64 -64
  93. package/dist/utilities/utilities3D.d.ts +26 -26
  94. package/dist/utilities/utilities3D.js +187 -187
  95. package/dist/utilities/utilitiesColor.d.ts +18 -18
  96. package/dist/utilities/utilitiesColor.js +48 -48
  97. package/dist/utilities/utilitiesImage.d.ts +6 -6
  98. package/dist/utilities/utilitiesImage.js +107 -107
  99. package/dist/utilities/utilitiesSymRootIdentifier.d.ts +5 -5
  100. package/dist/utilities/utilitiesSymRootIdentifier.js +20 -20
  101. package/dist/view/BaseView.d.ts +70 -70
  102. package/dist/view/BaseView.js +291 -291
  103. package/dist/view/BaseViewConfiguration.d.ts +32 -32
  104. package/dist/view/BaseViewConfiguration.js +8 -8
  105. package/dist/view/RenderEnv.d.ts +38 -38
  106. package/dist/view/RenderEnv.js +7 -7
  107. package/dist/view/SingleProductDefaultCameraView.d.ts +33 -33
  108. package/dist/view/SingleProductDefaultCameraView.js +141 -140
  109. package/dist/view/SingleProductDefaultCameraViewConfiguration.d.ts +46 -44
  110. package/dist/view/SingleProductDefaultCameraViewConfiguration.js +11 -11
  111. package/dist/view/SingleProductView.d.ts +42 -42
  112. package/dist/view/SingleProductView.js +205 -205
  113. package/dist/view/SingleProductViewConfiguration.d.ts +32 -32
  114. package/dist/view/SingleProductViewConfiguration.js +19 -19
  115. package/package.json +5 -5
@@ -1,347 +1,347 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { Matrix } from "@babylonjs/core/Maths/math.vector.js";
11
- import { InspectableType } from "@babylonjs/core/Misc/iInspectable.js";
12
- import { logMtrlSourceWithMetaDataToConsole } from "@configura/web-api";
13
- import { SymBox } from "@configura/web-core/dist/cm/format/cmsym/components/SymBox.js";
14
- import { SymGfxMode } from "@configura/web-core/dist/cm/format/cmsym/components/SymComponent.js";
15
- import { SymMesh } from "@configura/web-core/dist/cm/format/cmsym/components/SymMesh.js";
16
- import { SymReps } from "@configura/web-core/dist/cm/format/cmsym/components/SymReps.js";
17
- import { SymSphere } from "@configura/web-core/dist/cm/format/cmsym/components/SymSphere.js";
18
- import { DetailMask } from "@configura/web-core/dist/cm/geometry/DetailMask.js";
19
- import { LogObservable } from "@configura/web-utilities";
20
- import { CfgGeometry } from "../geometry/CfgGeometry.js";
21
- import { CfgMesh } from "../geometry/CfgMesh.js";
22
- import { splitIndexComplete, splitIndexQuick } from "../geometry/geoSplitter.js";
23
- import { gMaterialToCfgMaterial, mtrlSourceToCfgMaterial, } from "../material/material.js";
24
- import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
25
- import { aTriMeshBox, aTriMeshSphere } from "../utilities/utilities3D.js";
26
- import { GeometryCacheEntry } from "../view/RenderEnv.js";
27
- import { CfgTransformNode } from "./CfgTransformNode.js";
28
- const QUICK_SPLIT_INDEX_SIZE_LIMIT = 20000;
29
- const COMPLETE_SPLIT_INDEX_SIZE_LIMIT = 5000;
30
- const COMPLETE_SPLIT_FINAL_GROUPS_COUNT_LIMIT = 20;
31
- const COMPLETE_SPLIT_PROGRESS_GROUPS_COUNT_LIMIT = 100;
32
- var SplitGeoStatus;
33
- (function (SplitGeoStatus) {
34
- SplitGeoStatus["Idle"] = "Idle";
35
- SplitGeoStatus["Splitting"] = "Splitting";
36
- SplitGeoStatus["Unapplied"] = "Unapplied";
37
- SplitGeoStatus["Done"] = "Done";
38
- })(SplitGeoStatus || (SplitGeoStatus = {}));
39
- function getDetailMask(symNode) {
40
- const symReps = symNode.symReps();
41
- if (!(symReps instanceof SymReps)) {
42
- return;
43
- }
44
- if (symReps._details === undefined) {
45
- return;
46
- }
47
- const lod = symReps._details.get(SymGfxMode.x3D);
48
- if (!(lod instanceof DetailMask)) {
49
- return;
50
- }
51
- return lod;
52
- }
53
- function symComponentToGeometry(logger, renderEnvironment, component) {
54
- return __awaiter(this, void 0, void 0, function* () {
55
- return renderEnvironment.geometryCache.get(component, () => __awaiter(this, void 0, void 0, function* () {
56
- let mesh = undefined;
57
- if (component instanceof SymMesh) {
58
- mesh = component.mesh(logger, renderEnvironment.symMeshEnv);
59
- }
60
- else if (component instanceof SymSphere) {
61
- mesh = aTriMeshSphere(component.radius, component.center, component.segments);
62
- }
63
- else if (component instanceof SymBox) {
64
- mesh = aTriMeshBox(component.p0, component.p1);
65
- }
66
- if (mesh === undefined) {
67
- logger.error("SymComponent did not return a mesh", component);
68
- return undefined;
69
- }
70
- return new GeometryCacheEntry(new CfgGeometry("(Geo) " + component.id, mesh, renderEnvironment.scene), mesh.doubleSided, mesh.lowerLeftTextureOrigin);
71
- }));
72
- });
73
- }
74
- export class CfgDeferredMeshNode extends CfgTransformNode {
75
- constructor(renderEnvironment, name, lod, _gMaterial, _meshDoubleSided, _lowerLeftTextureOrigin, _geo) {
76
- super(renderEnvironment, name);
77
- this.lod = lod;
78
- this._gMaterial = _gMaterial;
79
- this._meshDoubleSided = _meshDoubleSided;
80
- this._lowerLeftTextureOrigin = _lowerLeftTextureOrigin;
81
- this._geo = _geo;
82
- this._materialIsDirty = false;
83
- this._mtrlSourceWithMetaData = null;
84
- this._splitGeoStatus = SplitGeoStatus.Idle;
85
- this.logger = new LogObservable();
86
- this.applyMaterial = () => {
87
- if (this._material === undefined ||
88
- (!this._materialIsDirty && this._splitGeoStatus !== SplitGeoStatus.Unapplied)) {
89
- return;
90
- }
91
- this._materialIsDirty = false;
92
- if (this._splitGeoStatus === SplitGeoStatus.Unapplied) {
93
- this._splitGeoStatus = SplitGeoStatus.Done;
94
- }
95
- let geos = [this._geo];
96
- let labelSuffix = this.name;
97
- if (this._splitGeos !== undefined) {
98
- geos = this._splitGeos;
99
- labelSuffix += " (geo split)";
100
- }
101
- let doubleSided = false;
102
- let backToFront = false;
103
- let flipTexture = !this._lowerLeftTextureOrigin;
104
- if (this._meshDoubleSided || this._material.isDoubleSided()) {
105
- // Double sided can be set both by the mesh and the material, but only the material
106
- // controls it during rendering. Ensure we are using a material that is double sided.
107
- doubleSided = true;
108
- if (this._material.isTransparent) {
109
- // Mesh will render double sided with possible transparent parts, this is tricky.
110
- //
111
- // Since we don't depth sort all triangles in the mesh relative to the camera (which
112
- // is not doable in the general case) we need to employ a trick to make sure the
113
- // inside of the object gets rendered before the outside skin.
114
- //
115
- // Otherwise, semi-transparent pixels in the outer skin would fully occlude pixels
116
- // from the inside of the object if they happen to be rendered first. That means
117
- // that sometimes your would not see the inside of the object through the "holes"
118
- // in it.
119
- //
120
- // A good workaround for correctly made objects (where "correct" is mostly related
121
- // to the normals) is to render the mesh twice, first the back sides ("inside"),
122
- // then the front sides ("outside") of the triangles. Babylon.js has such a feature
123
- // built in called separateCullingPass (or "back then front" below).
124
- backToFront = true;
125
- }
126
- }
127
- const material = this._material.getPBRMaterial(doubleSided, backToFront, flipTexture);
128
- this.clear(true);
129
- for (const geo of geos) {
130
- const mesh = new CfgMesh(labelSuffix, this._renderEnvironment, geo, material);
131
- this.add(mesh);
132
- }
133
- };
134
- this.isAllMeshMaterialsReady = () => this.getChildMeshes().reduce((a, m) => a && (m.material === null || m.material.isReady(m)), true);
135
- this.startSplitGeo = (force = false) => __awaiter(this, void 0, void 0, function* () {
136
- if (!force && this._splitGeoStatus !== SplitGeoStatus.Idle) {
137
- return;
138
- }
139
- this._splitGeoStatus = SplitGeoStatus.Splitting;
140
- const geo = this._geo;
141
- const indexCount = geo.getTotalIndices();
142
- if (!force && QUICK_SPLIT_INDEX_SIZE_LIMIT < indexCount) {
143
- return;
144
- }
145
- const splitStart = performance.now();
146
- const doCompleteSplit = indexCount < COMPLETE_SPLIT_INDEX_SIZE_LIMIT || force;
147
- let groups;
148
- if (doCompleteSplit) {
149
- groups = splitIndexComplete(this.logger, geo, {
150
- maxFinalGroups: force ? Number.MAX_VALUE : COMPLETE_SPLIT_FINAL_GROUPS_COUNT_LIMIT,
151
- maxProgressGroups: force
152
- ? Number.MAX_VALUE
153
- : COMPLETE_SPLIT_PROGRESS_GROUPS_COUNT_LIMIT,
154
- acceptCoordinateMatch: true,
155
- });
156
- }
157
- else {
158
- groups = splitIndexQuick(this.logger, geo);
159
- }
160
- if (groups === undefined || groups.length === 1) {
161
- this._splitGeoStatus = SplitGeoStatus.Done;
162
- return;
163
- }
164
- const splitEnd = performance.now();
165
- this._splitGeos = groups.map((group) => geo.cloneWithSubset(group));
166
- const repackEnd = performance.now();
167
- this._splitGeoStatus = SplitGeoStatus.Unapplied;
168
- this.logger.info(`${doCompleteSplit ? "Complete" : "Quick"}-split`, `of ${indexCount / 3} triangles into ${groups.length} disjoint groups took ${(splitEnd - splitStart).toFixed(1)} ms, repack took ${(repackEnd - splitEnd).toFixed(1)} ms.`);
169
- // If material is dirty someone else is responsible for calling applyMaterial
170
- // at a later point
171
- if (!this._materialIsDirty) {
172
- this.applyMaterial();
173
- }
174
- });
175
- this._dummyMaterial = renderEnvironment.dummyMaterial;
176
- this.resetMaterial();
177
- }
178
- static makeCfgDeferredMesh(logger, renderEnvironment, detailLevel, symNode, gMaterial) {
179
- var _a, _b;
180
- return __awaiter(this, void 0, void 0, function* () {
181
- const lod = getDetailMask(symNode);
182
- if (lod === undefined || !lod.includes(detailLevel)) {
183
- return;
184
- }
185
- const component = (_b = (_a = symNode.symMesh()) !== null && _a !== void 0 ? _a : symNode.symSphere()) !== null && _b !== void 0 ? _b : symNode.symBox();
186
- if (component === undefined) {
187
- return;
188
- }
189
- const entry = yield symComponentToGeometry(logger, renderEnvironment, component);
190
- if ((entry === null || entry === void 0 ? void 0 : entry.geometry) === undefined) {
191
- return undefined;
192
- }
193
- return new CfgDeferredMeshNode(renderEnvironment, "(Deferred Mesh) " + symNode.id, lod, gMaterial, entry.doubleSided, entry.lowerLeftTextureOrigin, entry.geometry);
194
- });
195
- }
196
- get cfgClassName() {
197
- return "CfgDeferredMeshNode";
198
- }
199
- resetMaterial() {
200
- this._material = this._dummyMaterial;
201
- this._materialMetaData = undefined;
202
- this._materialIsDirty = true;
203
- this.applyMaterial();
204
- }
205
- get originalMatrix() {
206
- return Matrix.Identity();
207
- }
208
- setMaterialAndLoad(mtrlWithMetaData, animatorCoordinator) {
209
- return __awaiter(this, void 0, void 0, function* () {
210
- if (this._materialLoadedPromise !== undefined &&
211
- mtrlWithMetaData !== undefined &&
212
- this._mtrlSourceWithMetaData !== undefined &&
213
- this._mtrlSourceWithMetaData !== null &&
214
- mtrlWithMetaData.mtrl.isSame(this._mtrlSourceWithMetaData.mtrl)) {
215
- return this._materialLoadedPromise;
216
- }
217
- this._mtrlSourceWithMetaData = mtrlWithMetaData;
218
- this._materialLoadedPromise = this.loadMaterial();
219
- if (animatorCoordinator !== undefined && mtrlWithMetaData !== undefined) {
220
- const c = animatorCoordinator.coordinator;
221
- c.prepareForMaterialChange.bind(c)(this, animatorCoordinator.isNewProduct);
222
- }
223
- return this._materialLoadedPromise;
224
- });
225
- }
226
- loadMaterial() {
227
- return __awaiter(this, void 0, void 0, function* () {
228
- let material;
229
- const meta = {
230
- logger: this.logger,
231
- sourcePath: ["loadMaterial"],
232
- };
233
- if (this._mtrlSourceWithMetaData === null) {
234
- // null === has not yet been set
235
- return;
236
- }
237
- try {
238
- if (this._mtrlSourceWithMetaData !== undefined) {
239
- material = yield mtrlSourceToCfgMaterial(meta, this._mtrlSourceWithMetaData, this._renderEnvironment);
240
- if (material === undefined) {
241
- this.logger.error("Failed to load material from mtrlSource");
242
- }
243
- }
244
- else if (this._gMaterial !== undefined && this._gMaterial.gm !== undefined) {
245
- meta.sourcePath.push("embedded");
246
- material = yield gMaterialToCfgMaterial(meta, this._renderEnvironment, this._gMaterial.gm);
247
- if (material === undefined) {
248
- this.logger.error("Failed to load material from fallback gMaterial");
249
- }
250
- }
251
- }
252
- catch (e) {
253
- this._renderEnvironment.notifyError("Failed to load material. Will show default material.");
254
- this.logger.errorFromCaught(e);
255
- }
256
- if (material === undefined) {
257
- this.logger.warn("No material, not even fallback-material");
258
- }
259
- this._material = material;
260
- this._materialMetaData = meta;
261
- this._materialIsDirty = true;
262
- if (material && material.isTransparent) {
263
- this.startSplitGeo();
264
- }
265
- });
266
- }
267
- get boundingBox() {
268
- return this.getChildMeshes().reduce((a, m) => {
269
- const bb = m.getBoundingInfo().boundingBox;
270
- // Here we strip away the world matrix as we handle the transforms
271
- // manually, and the world matrix changes depending on if the has
272
- // been rendered to screen yet
273
- a.expand(new CfgBoundingBox(bb.minimum, bb.maximum));
274
- return a;
275
- }, new CfgBoundingBox());
276
- }
277
- addInspectorProperties() {
278
- super.addInspectorProperties();
279
- this.addInspectableCustomProperty({
280
- label: "Available lod levels",
281
- propertyName: "_inspectorLodLevels",
282
- type: InspectableType.String,
283
- });
284
- this.addInspectableCustomProperty({
285
- label: "Mtrl Source path",
286
- propertyName: "_inspectorSourcePath",
287
- type: InspectableType.String,
288
- });
289
- this.addInspectableCustomProperty({
290
- label: "log mtrlSourceWithMetaData",
291
- propertyName: "_inspectorLogMtrlSourceWithMetaData",
292
- type: InspectableType.Checkbox,
293
- });
294
- this.addInspectableCustomProperty({
295
- label: "log GMaterial",
296
- propertyName: "_inspectorLogGMaterial",
297
- type: InspectableType.Checkbox,
298
- });
299
- this.addInspectableCustomProperty({
300
- label: "log MultiGMaterial",
301
- propertyName: "_inspectorLogMultiGMaterial",
302
- type: InspectableType.Checkbox,
303
- });
304
- }
305
- get _inspectorLodLevels() {
306
- return Array.from(this.lod.detailSet().values()).join(", ");
307
- }
308
- get _inspectorSourcePath() {
309
- if (this._materialMetaData === undefined) {
310
- return "-";
311
- }
312
- return this._materialMetaData.sourcePath.join(" ");
313
- }
314
- get _inspectorLogMtrlSourceWithMetaData() {
315
- return this._mtrlSourceWithMetaData === undefined || this._mtrlSourceWithMetaData === null;
316
- }
317
- set _inspectorLogMtrlSourceWithMetaData(x) {
318
- if (this._mtrlSourceWithMetaData === undefined || this._mtrlSourceWithMetaData === null) {
319
- return;
320
- }
321
- logMtrlSourceWithMetaDataToConsole(this._mtrlSourceWithMetaData);
322
- }
323
- get _inspectorLogGMaterial() {
324
- var _a;
325
- return ((_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.gMaterial) === undefined;
326
- }
327
- set _inspectorLogGMaterial(x) {
328
- var _a;
329
- const m = (_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.gMaterial;
330
- if (m === undefined) {
331
- return;
332
- }
333
- console.log(m);
334
- }
335
- get _inspectorLogMultiGMaterial() {
336
- var _a;
337
- return ((_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.multiGMaterial) === undefined;
338
- }
339
- set _inspectorLogMultiGMaterial(x) {
340
- var _a;
341
- const m = (_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.multiGMaterial;
342
- if (m === undefined) {
343
- return;
344
- }
345
- console.log(m);
346
- }
347
- }
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Matrix } from "@babylonjs/core/Maths/math.vector.js";
11
+ import { InspectableType } from "@babylonjs/core/Misc/iInspectable.js";
12
+ import { logMtrlSourceWithMetaDataToConsole } from "@configura/web-api";
13
+ import { SymBox } from "@configura/web-core/dist/cm/format/cmsym/components/SymBox.js";
14
+ import { SymGfxMode } from "@configura/web-core/dist/cm/format/cmsym/components/SymComponent.js";
15
+ import { SymMesh } from "@configura/web-core/dist/cm/format/cmsym/components/SymMesh.js";
16
+ import { SymReps } from "@configura/web-core/dist/cm/format/cmsym/components/SymReps.js";
17
+ import { SymSphere } from "@configura/web-core/dist/cm/format/cmsym/components/SymSphere.js";
18
+ import { DetailMask } from "@configura/web-core/dist/cm/geometry/DetailMask.js";
19
+ import { LogObservable } from "@configura/web-utilities";
20
+ import { CfgGeometry } from "../geometry/CfgGeometry.js";
21
+ import { CfgMesh } from "../geometry/CfgMesh.js";
22
+ import { splitIndexComplete, splitIndexQuick } from "../geometry/geoSplitter.js";
23
+ import { gMaterialToCfgMaterial, mtrlSourceToCfgMaterial, } from "../material/material.js";
24
+ import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
25
+ import { aTriMeshBox, aTriMeshSphere } from "../utilities/utilities3D.js";
26
+ import { GeometryCacheEntry } from "../view/RenderEnv.js";
27
+ import { CfgTransformNode } from "./CfgTransformNode.js";
28
+ const QUICK_SPLIT_INDEX_SIZE_LIMIT = 20000;
29
+ const COMPLETE_SPLIT_INDEX_SIZE_LIMIT = 5000;
30
+ const COMPLETE_SPLIT_FINAL_GROUPS_COUNT_LIMIT = 20;
31
+ const COMPLETE_SPLIT_PROGRESS_GROUPS_COUNT_LIMIT = 100;
32
+ var SplitGeoStatus;
33
+ (function (SplitGeoStatus) {
34
+ SplitGeoStatus["Idle"] = "Idle";
35
+ SplitGeoStatus["Splitting"] = "Splitting";
36
+ SplitGeoStatus["Unapplied"] = "Unapplied";
37
+ SplitGeoStatus["Done"] = "Done";
38
+ })(SplitGeoStatus || (SplitGeoStatus = {}));
39
+ function getDetailMask(symNode) {
40
+ const symReps = symNode.symReps();
41
+ if (!(symReps instanceof SymReps)) {
42
+ return;
43
+ }
44
+ if (symReps._details === undefined) {
45
+ return;
46
+ }
47
+ const lod = symReps._details.get(SymGfxMode.x3D);
48
+ if (!(lod instanceof DetailMask)) {
49
+ return;
50
+ }
51
+ return lod;
52
+ }
53
+ function symComponentToGeometry(logger, renderEnvironment, component) {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ return renderEnvironment.geometryCache.get(component, () => __awaiter(this, void 0, void 0, function* () {
56
+ let mesh = undefined;
57
+ if (component instanceof SymMesh) {
58
+ mesh = component.mesh(logger, renderEnvironment.symMeshEnv);
59
+ }
60
+ else if (component instanceof SymSphere) {
61
+ mesh = aTriMeshSphere(component.radius, component.center, component.segments);
62
+ }
63
+ else if (component instanceof SymBox) {
64
+ mesh = aTriMeshBox(component.p0, component.p1);
65
+ }
66
+ if (mesh === undefined) {
67
+ logger.error("SymComponent did not return a mesh", component);
68
+ return undefined;
69
+ }
70
+ return new GeometryCacheEntry(new CfgGeometry("(Geo) " + component.id, mesh, renderEnvironment.scene), mesh.doubleSided, mesh.lowerLeftTextureOrigin);
71
+ }));
72
+ });
73
+ }
74
+ export class CfgDeferredMeshNode extends CfgTransformNode {
75
+ constructor(renderEnvironment, name, lod, _gMaterial, _meshDoubleSided, _lowerLeftTextureOrigin, _geo) {
76
+ super(renderEnvironment, name);
77
+ this.lod = lod;
78
+ this._gMaterial = _gMaterial;
79
+ this._meshDoubleSided = _meshDoubleSided;
80
+ this._lowerLeftTextureOrigin = _lowerLeftTextureOrigin;
81
+ this._geo = _geo;
82
+ this._materialIsDirty = false;
83
+ this._mtrlSourceWithMetaData = null;
84
+ this._splitGeoStatus = SplitGeoStatus.Idle;
85
+ this.logger = new LogObservable();
86
+ this.applyMaterial = () => {
87
+ if (this._material === undefined ||
88
+ (!this._materialIsDirty && this._splitGeoStatus !== SplitGeoStatus.Unapplied)) {
89
+ return;
90
+ }
91
+ this._materialIsDirty = false;
92
+ if (this._splitGeoStatus === SplitGeoStatus.Unapplied) {
93
+ this._splitGeoStatus = SplitGeoStatus.Done;
94
+ }
95
+ let geos = [this._geo];
96
+ let labelSuffix = this.name;
97
+ if (this._splitGeos !== undefined) {
98
+ geos = this._splitGeos;
99
+ labelSuffix += " (geo split)";
100
+ }
101
+ let doubleSided = false;
102
+ let backToFront = false;
103
+ let flipTexture = !this._lowerLeftTextureOrigin;
104
+ if (this._meshDoubleSided || this._material.isDoubleSided()) {
105
+ // Double sided can be set both by the mesh and the material, but only the material
106
+ // controls it during rendering. Ensure we are using a material that is double sided.
107
+ doubleSided = true;
108
+ if (this._material.isTransparent) {
109
+ // Mesh will render double sided with possible transparent parts, this is tricky.
110
+ //
111
+ // Since we don't depth sort all triangles in the mesh relative to the camera (which
112
+ // is not doable in the general case) we need to employ a trick to make sure the
113
+ // inside of the object gets rendered before the outside skin.
114
+ //
115
+ // Otherwise, semi-transparent pixels in the outer skin would fully occlude pixels
116
+ // from the inside of the object if they happen to be rendered first. That means
117
+ // that sometimes your would not see the inside of the object through the "holes"
118
+ // in it.
119
+ //
120
+ // A good workaround for correctly made objects (where "correct" is mostly related
121
+ // to the normals) is to render the mesh twice, first the back sides ("inside"),
122
+ // then the front sides ("outside") of the triangles. Babylon.js has such a feature
123
+ // built in called separateCullingPass (or "back then front" below).
124
+ backToFront = true;
125
+ }
126
+ }
127
+ const material = this._material.getPBRMaterial(doubleSided, backToFront, flipTexture);
128
+ this.clear(true);
129
+ for (const geo of geos) {
130
+ const mesh = new CfgMesh(labelSuffix, this._renderEnvironment, geo, material);
131
+ this.add(mesh);
132
+ }
133
+ };
134
+ this.isAllMeshMaterialsReady = () => this.getChildMeshes().reduce((a, m) => a && (m.material === null || m.material.isReady(m)), true);
135
+ this.startSplitGeo = (force = false) => __awaiter(this, void 0, void 0, function* () {
136
+ if (!force && this._splitGeoStatus !== SplitGeoStatus.Idle) {
137
+ return;
138
+ }
139
+ this._splitGeoStatus = SplitGeoStatus.Splitting;
140
+ const geo = this._geo;
141
+ const indexCount = geo.getTotalIndices();
142
+ if (!force && QUICK_SPLIT_INDEX_SIZE_LIMIT < indexCount) {
143
+ return;
144
+ }
145
+ const splitStart = performance.now();
146
+ const doCompleteSplit = indexCount < COMPLETE_SPLIT_INDEX_SIZE_LIMIT || force;
147
+ let groups;
148
+ if (doCompleteSplit) {
149
+ groups = splitIndexComplete(this.logger, geo, {
150
+ maxFinalGroups: force ? Number.MAX_VALUE : COMPLETE_SPLIT_FINAL_GROUPS_COUNT_LIMIT,
151
+ maxProgressGroups: force
152
+ ? Number.MAX_VALUE
153
+ : COMPLETE_SPLIT_PROGRESS_GROUPS_COUNT_LIMIT,
154
+ acceptCoordinateMatch: true,
155
+ });
156
+ }
157
+ else {
158
+ groups = splitIndexQuick(this.logger, geo);
159
+ }
160
+ if (groups === undefined || groups.length === 1) {
161
+ this._splitGeoStatus = SplitGeoStatus.Done;
162
+ return;
163
+ }
164
+ const splitEnd = performance.now();
165
+ this._splitGeos = groups.map((group) => geo.cloneWithSubset(group));
166
+ const repackEnd = performance.now();
167
+ this._splitGeoStatus = SplitGeoStatus.Unapplied;
168
+ this.logger.info(`${doCompleteSplit ? "Complete" : "Quick"}-split`, `of ${indexCount / 3} triangles into ${groups.length} disjoint groups took ${(splitEnd - splitStart).toFixed(1)} ms, repack took ${(repackEnd - splitEnd).toFixed(1)} ms.`);
169
+ // If material is dirty someone else is responsible for calling applyMaterial
170
+ // at a later point
171
+ if (!this._materialIsDirty) {
172
+ this.applyMaterial();
173
+ }
174
+ });
175
+ this._dummyMaterial = renderEnvironment.dummyMaterial;
176
+ this.resetMaterial();
177
+ }
178
+ static makeCfgDeferredMesh(logger, renderEnvironment, detailLevel, symNode, gMaterial) {
179
+ var _a, _b;
180
+ return __awaiter(this, void 0, void 0, function* () {
181
+ const lod = getDetailMask(symNode);
182
+ if (lod === undefined || !lod.includes(detailLevel)) {
183
+ return;
184
+ }
185
+ const component = (_b = (_a = symNode.symMesh()) !== null && _a !== void 0 ? _a : symNode.symSphere()) !== null && _b !== void 0 ? _b : symNode.symBox();
186
+ if (component === undefined) {
187
+ return;
188
+ }
189
+ const entry = yield symComponentToGeometry(logger, renderEnvironment, component);
190
+ if ((entry === null || entry === void 0 ? void 0 : entry.geometry) === undefined) {
191
+ return undefined;
192
+ }
193
+ return new CfgDeferredMeshNode(renderEnvironment, "(Deferred Mesh) " + symNode.id, lod, gMaterial, entry.doubleSided, entry.lowerLeftTextureOrigin, entry.geometry);
194
+ });
195
+ }
196
+ get cfgClassName() {
197
+ return "CfgDeferredMeshNode";
198
+ }
199
+ resetMaterial() {
200
+ this._material = this._dummyMaterial;
201
+ this._materialMetaData = undefined;
202
+ this._materialIsDirty = true;
203
+ this.applyMaterial();
204
+ }
205
+ get originalMatrix() {
206
+ return Matrix.Identity();
207
+ }
208
+ setMaterialAndLoad(mtrlWithMetaData, animatorCoordinator) {
209
+ return __awaiter(this, void 0, void 0, function* () {
210
+ if (this._materialLoadedPromise !== undefined &&
211
+ mtrlWithMetaData !== undefined &&
212
+ this._mtrlSourceWithMetaData !== undefined &&
213
+ this._mtrlSourceWithMetaData !== null &&
214
+ mtrlWithMetaData.mtrl.isSame(this._mtrlSourceWithMetaData.mtrl)) {
215
+ return this._materialLoadedPromise;
216
+ }
217
+ this._mtrlSourceWithMetaData = mtrlWithMetaData;
218
+ this._materialLoadedPromise = this.loadMaterial();
219
+ if (animatorCoordinator !== undefined && mtrlWithMetaData !== undefined) {
220
+ const c = animatorCoordinator.coordinator;
221
+ c.prepareForMaterialChange.bind(c)(this, animatorCoordinator.isNewProduct);
222
+ }
223
+ return this._materialLoadedPromise;
224
+ });
225
+ }
226
+ loadMaterial() {
227
+ return __awaiter(this, void 0, void 0, function* () {
228
+ let material;
229
+ const meta = {
230
+ logger: this.logger,
231
+ sourcePath: ["loadMaterial"],
232
+ };
233
+ if (this._mtrlSourceWithMetaData === null) {
234
+ // null === has not yet been set
235
+ return;
236
+ }
237
+ try {
238
+ if (this._mtrlSourceWithMetaData !== undefined) {
239
+ material = yield mtrlSourceToCfgMaterial(meta, this._mtrlSourceWithMetaData, this._renderEnvironment);
240
+ if (material === undefined) {
241
+ this.logger.error("Failed to load material from mtrlSource");
242
+ }
243
+ }
244
+ else if (this._gMaterial !== undefined && this._gMaterial.gm !== undefined) {
245
+ meta.sourcePath.push("embedded");
246
+ material = yield gMaterialToCfgMaterial(meta, this._renderEnvironment, this._gMaterial.gm);
247
+ if (material === undefined) {
248
+ this.logger.error("Failed to load material from fallback gMaterial");
249
+ }
250
+ }
251
+ }
252
+ catch (e) {
253
+ this._renderEnvironment.notifyError("Failed to load material. Will show default material.");
254
+ this.logger.errorFromCaught(e);
255
+ }
256
+ if (material === undefined) {
257
+ this.logger.warn("No material, not even fallback-material");
258
+ }
259
+ this._material = material;
260
+ this._materialMetaData = meta;
261
+ this._materialIsDirty = true;
262
+ if (material && material.isTransparent) {
263
+ this.startSplitGeo();
264
+ }
265
+ });
266
+ }
267
+ get boundingBox() {
268
+ return this.getChildMeshes().reduce((a, m) => {
269
+ const bb = m.getBoundingInfo().boundingBox;
270
+ // Here we strip away the world matrix as we handle the transforms
271
+ // manually, and the world matrix changes depending on if the has
272
+ // been rendered to screen yet
273
+ a.expand(new CfgBoundingBox(bb.minimum, bb.maximum));
274
+ return a;
275
+ }, new CfgBoundingBox());
276
+ }
277
+ addInspectorProperties() {
278
+ super.addInspectorProperties();
279
+ this.addInspectableCustomProperty({
280
+ label: "Available lod levels",
281
+ propertyName: "_inspectorLodLevels",
282
+ type: InspectableType.String,
283
+ });
284
+ this.addInspectableCustomProperty({
285
+ label: "Mtrl Source path",
286
+ propertyName: "_inspectorSourcePath",
287
+ type: InspectableType.String,
288
+ });
289
+ this.addInspectableCustomProperty({
290
+ label: "log mtrlSourceWithMetaData",
291
+ propertyName: "_inspectorLogMtrlSourceWithMetaData",
292
+ type: InspectableType.Checkbox,
293
+ });
294
+ this.addInspectableCustomProperty({
295
+ label: "log GMaterial",
296
+ propertyName: "_inspectorLogGMaterial",
297
+ type: InspectableType.Checkbox,
298
+ });
299
+ this.addInspectableCustomProperty({
300
+ label: "log MultiGMaterial",
301
+ propertyName: "_inspectorLogMultiGMaterial",
302
+ type: InspectableType.Checkbox,
303
+ });
304
+ }
305
+ get _inspectorLodLevels() {
306
+ return Array.from(this.lod.detailSet().values()).join(", ");
307
+ }
308
+ get _inspectorSourcePath() {
309
+ if (this._materialMetaData === undefined) {
310
+ return "-";
311
+ }
312
+ return this._materialMetaData.sourcePath.join(" ");
313
+ }
314
+ get _inspectorLogMtrlSourceWithMetaData() {
315
+ return this._mtrlSourceWithMetaData === undefined || this._mtrlSourceWithMetaData === null;
316
+ }
317
+ set _inspectorLogMtrlSourceWithMetaData(x) {
318
+ if (this._mtrlSourceWithMetaData === undefined || this._mtrlSourceWithMetaData === null) {
319
+ return;
320
+ }
321
+ logMtrlSourceWithMetaDataToConsole(this._mtrlSourceWithMetaData);
322
+ }
323
+ get _inspectorLogGMaterial() {
324
+ var _a;
325
+ return ((_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.gMaterial) === undefined;
326
+ }
327
+ set _inspectorLogGMaterial(x) {
328
+ var _a;
329
+ const m = (_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.gMaterial;
330
+ if (m === undefined) {
331
+ return;
332
+ }
333
+ console.log(m);
334
+ }
335
+ get _inspectorLogMultiGMaterial() {
336
+ var _a;
337
+ return ((_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.multiGMaterial) === undefined;
338
+ }
339
+ set _inspectorLogMultiGMaterial(x) {
340
+ var _a;
341
+ const m = (_a = this._materialMetaData) === null || _a === void 0 ? void 0 : _a.multiGMaterial;
342
+ if (m === undefined) {
343
+ return;
344
+ }
345
+ console.log(m);
346
+ }
347
+ }