@combeenation/3d-viewer 18.5.1 → 19.0.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.
Files changed (38) hide show
  1. package/dist/lib-cjs/buildinfo.json +1 -1
  2. package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -1
  3. package/dist/lib-cjs/index.d.ts +4 -3
  4. package/dist/lib-cjs/index.js +4 -3
  5. package/dist/lib-cjs/index.js.map +1 -1
  6. package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js +1 -1
  7. package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js.map +1 -1
  8. package/dist/lib-cjs/internal/export-helper.js +1 -77
  9. package/dist/lib-cjs/internal/export-helper.js.map +1 -1
  10. package/dist/lib-cjs/manager/export-manager.d.ts +82 -0
  11. package/dist/lib-cjs/manager/export-manager.js +224 -0
  12. package/dist/lib-cjs/manager/export-manager.js.map +1 -0
  13. package/dist/lib-cjs/{helper/decals-helper.d.ts → utils/decal-utils.d.ts} +5 -1
  14. package/dist/lib-cjs/{helper/decals-helper.js → utils/decal-utils.js} +6 -3
  15. package/dist/lib-cjs/utils/decal-utils.js.map +1 -0
  16. package/dist/lib-cjs/utils/node-utils.d.ts +17 -0
  17. package/dist/lib-cjs/utils/node-utils.js +92 -0
  18. package/dist/lib-cjs/utils/node-utils.js.map +1 -0
  19. package/dist/lib-cjs/viewer.d.ts +3 -5
  20. package/dist/lib-cjs/viewer.js +3 -7
  21. package/dist/lib-cjs/viewer.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/index.ts +4 -3
  24. package/src/internal/cbn-custom-babylon-loader-plugin.ts +2 -2
  25. package/src/internal/export-helper.ts +2 -100
  26. package/src/manager/export-manager.ts +273 -0
  27. package/src/{helper/decals-helper.ts → utils/decal-utils.ts} +6 -1
  28. package/src/utils/node-utils.ts +112 -0
  29. package/src/viewer.ts +5 -11
  30. package/dist/lib-cjs/helper/decals-helper.js.map +0 -1
  31. package/dist/lib-cjs/manager/dxf-export-manager.d.ts +0 -39
  32. package/dist/lib-cjs/manager/dxf-export-manager.js +0 -116
  33. package/dist/lib-cjs/manager/dxf-export-manager.js.map +0 -1
  34. package/dist/lib-cjs/manager/gltf-export-manager.d.ts +0 -54
  35. package/dist/lib-cjs/manager/gltf-export-manager.js +0 -124
  36. package/dist/lib-cjs/manager/gltf-export-manager.js.map +0 -1
  37. package/src/manager/dxf-export-manager.ts +0 -123
  38. package/src/manager/gltf-export-manager.ts +0 -139
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NodeUtils = void 0;
4
+ const __1 = require("..");
5
+ /**
6
+ * Removes transformation data from the mesh and stores it in the geometry, which is called "baking".
7
+ * Also considers the geometry change from morph targets and skeletons.
8
+ *
9
+ * @param settings Optionally avoid baking the transformation, as this only works conveniently if the parent structure
10
+ * is baked as well. Baking morph targets only is a use case when preparing a mesh for CSG operations,
11
+ * which doesn't consider morph targets (yet).
12
+ */
13
+ function bakeGeometryOfMesh(mesh, settings) {
14
+ const { keepTransformation } = settings !== null && settings !== void 0 ? settings : {};
15
+ if (!mesh.geometry) {
16
+ // no geometry available, nothing to do
17
+ return;
18
+ }
19
+ // geometries can be shared across multiple meshes, first make them unique to avoid side-effects
20
+ mesh.makeGeometryUnique();
21
+ // Babylon.js already provides a function for baking the current skeleton changes into the geometry
22
+ if (mesh.skeleton) {
23
+ mesh.applySkeleton(mesh.skeleton);
24
+ mesh.skeleton = null;
25
+ }
26
+ // NOTE: in difference to skeletons and transformations there is no baking function for morph targets (yet)
27
+ // however another approach could be to re-apply the position and normals data, as there are nice functions for it
28
+ // - `getPositionData(applySkeleton: boolean = false, applyMorph: boolean = false)`
29
+ // - `getNormalsData(applySkeleton: boolean = false, applyMorph: boolean = false)`
30
+ // you can decide if skeletons and morph targets can be added, which is exactly what we want
31
+ // I'm still hesitant to use it because "tangent" and "UV" kinds are not supported, whereas I'm not sure if it's
32
+ // required
33
+ // => try it out when there is enough time for detailed regression tests!
34
+ const morphTargetManager = mesh.morphTargetManager;
35
+ const geometry = mesh.geometry;
36
+ if (morphTargetManager === null || morphTargetManager === void 0 ? void 0 : morphTargetManager.numTargets) {
37
+ // apply morph target vertices data to mesh geometry
38
+ // mostly only the "PositionKind" is implemented
39
+ _bakeMorphTargetManagerIntoVertices(__1.VertexBuffer.PositionKind, morphTargetManager, geometry);
40
+ _bakeMorphTargetManagerIntoVertices(__1.VertexBuffer.NormalKind, morphTargetManager, geometry);
41
+ _bakeMorphTargetManagerIntoVertices(__1.VertexBuffer.TangentKind, morphTargetManager, geometry);
42
+ _bakeMorphTargetManagerIntoVertices(__1.VertexBuffer.UVKind, morphTargetManager, geometry);
43
+ // remove morph target manager with all it's morph targets
44
+ mesh.morphTargetManager = null;
45
+ }
46
+ // bake the transformation data in the mesh geometry, fortunately there is already a help function from Babylon.js
47
+ if (!keepTransformation) {
48
+ mesh.bakeCurrentTransformIntoVertices();
49
+ }
50
+ }
51
+ /**
52
+ * @param kind morph targets can affect various vertices kinds, whereas "position" is the most common one
53
+ * still other kinds (like normals or tangents) can be affected as well and can be provided on this input
54
+ */
55
+ function _bakeMorphTargetManagerIntoVertices(kind, morphTargetManager, geometry) {
56
+ const origVerticesData = geometry.getVerticesData(kind);
57
+ if (!origVerticesData) {
58
+ // no vertices data for this kind availabe on the mesh geometry
59
+ return;
60
+ }
61
+ let verticesData = [...origVerticesData];
62
+ for (let i = 0; i < morphTargetManager.numTargets; i++) {
63
+ const target = morphTargetManager.getTarget(i);
64
+ const targetVerticesData = _getVerticesDataFromMorphTarget(kind, target);
65
+ if (targetVerticesData) {
66
+ // vertices data of this kind are implemented on the morph target
67
+ // add the influence of this morph target to the vertices data
68
+ // formula is taken from: https://doc.babylonjs.com/features/featuresDeepDive/mesh/morphTargets#basics
69
+ verticesData = verticesData.map((oldVal, idx) => oldVal + (targetVerticesData[idx] - origVerticesData[idx]) * target.influence);
70
+ }
71
+ }
72
+ // apply the updated vertices data
73
+ geometry.setVerticesData(kind, verticesData);
74
+ }
75
+ function _getVerticesDataFromMorphTarget(kind, morphTarget) {
76
+ switch (kind) {
77
+ case __1.VertexBuffer.PositionKind:
78
+ return morphTarget.getPositions();
79
+ case __1.VertexBuffer.NormalKind:
80
+ return morphTarget.getNormals();
81
+ case __1.VertexBuffer.TangentKind:
82
+ return morphTarget.getTangents();
83
+ case __1.VertexBuffer.UVKind:
84
+ return morphTarget.getUVs();
85
+ }
86
+ return null;
87
+ }
88
+ // export functions under "namespace", so that they can found easier in consuming code
89
+ exports.NodeUtils = {
90
+ bakeGeometryOfMesh,
91
+ };
92
+ //# sourceMappingURL=node-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-utils.js","sourceRoot":"","sources":["../../../src/utils/node-utils.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import * as Index from './index';
2
- import { AbstractEngine, CameraManager, DebugManager, DefaultSceneSettings, DimensionLineManager, DxfExportManager, EngineOptions, EventManager, GltfExportManager, HtmlAnchorManager, MaterialManager, ModelManager, NodeParameterSubject, ParameterManager, Scene, SceneManager, TagParameterSubject, TextureManager, TransformNode } from './index';
2
+ import { AbstractEngine, CameraManager, DebugManager, DefaultSceneSettings, DimensionLineManager, EngineOptions, EventManager, ExportManager, HtmlAnchorManager, MaterialManager, ModelManager, NodeParameterSubject, ParameterManager, Scene, SceneManager, TagParameterSubject, TextureManager, TransformNode } from './index';
3
3
  /**
4
4
  * Use this type to select nodes directly or via node or tag name.\
5
5
  * This pattern is used for excluding nodes from autofocus, GLB export, etc.
@@ -52,9 +52,8 @@ export declare class Viewer {
52
52
  protected _cameraManager: CameraManager;
53
53
  protected _debugManager: DebugManager;
54
54
  protected _dimensionLineManager: DimensionLineManager;
55
- protected _dxfExportManager: DxfExportManager;
56
55
  protected _eventManager: EventManager;
57
- protected _gltfExportManager: GltfExportManager;
56
+ protected _exportManager: ExportManager;
58
57
  protected _htmlAnchorManager: HtmlAnchorManager;
59
58
  protected _materialManager: MaterialManager;
60
59
  protected _modelManager: ModelManager;
@@ -68,9 +67,8 @@ export declare class Viewer {
68
67
  get cameraManager(): CameraManager;
69
68
  get debugManager(): DebugManager;
70
69
  get dimensionLineManager(): DimensionLineManager;
71
- get dxfExportManager(): DxfExportManager;
72
70
  get eventManager(): EventManager;
73
- get gltfExportManager(): GltfExportManager;
71
+ get exportManager(): ExportManager;
74
72
  get htmlAnchorManager(): HtmlAnchorManager;
75
73
  get materialManager(): MaterialManager;
76
74
  get modelManager(): ModelManager;
@@ -87,14 +87,11 @@ class Viewer {
87
87
  get dimensionLineManager() {
88
88
  return this._dimensionLineManager;
89
89
  }
90
- get dxfExportManager() {
91
- return this._dxfExportManager;
92
- }
93
90
  get eventManager() {
94
91
  return this._eventManager;
95
92
  }
96
- get gltfExportManager() {
97
- return this._gltfExportManager;
93
+ get exportManager() {
94
+ return this._exportManager;
98
95
  }
99
96
  get htmlAnchorManager() {
100
97
  return this._htmlAnchorManager;
@@ -181,9 +178,8 @@ class Viewer {
181
178
  this._cameraManager = new index_1.CameraManager(this);
182
179
  this._debugManager = new index_1.DebugManager(this);
183
180
  this._dimensionLineManager = new index_1.DimensionLineManager(this);
184
- this._dxfExportManager = new index_1.DxfExportManager(this);
185
181
  this._eventManager = new index_1.EventManager(this);
186
- this._gltfExportManager = new index_1.GltfExportManager(this);
182
+ this._exportManager = new index_1.ExportManager(this);
187
183
  this._htmlAnchorManager = new index_1.HtmlAnchorManager(this);
188
184
  this._materialManager = new index_1.MaterialManager(this);
189
185
  this._modelManager = new index_1.ModelManager(this);
@@ -1 +1 @@
1
- {"version":3,"file":"viewer.js","sourceRoot":"","sources":["../../src/viewer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"viewer.js","sourceRoot":"","sources":["../../src/viewer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combeenation/3d-viewer",
3
- "version": "18.5.1",
3
+ "version": "19.0.0",
4
4
  "description": "Combeenation 3D Viewer",
5
5
  "homepage": "https://github.com/Combeenation/3d-viewer#readme",
6
6
  "bugs": {
package/src/index.ts CHANGED
@@ -52,6 +52,7 @@ export * from '@babylonjs/gui/2D/advancedDynamicTexture';
52
52
  export * from '@babylonjs/gui/2D/controls/textBlock';
53
53
  export * from '@babylonjs/loaders/glTF/2.0/glTFLoader';
54
54
  export * from '@babylonjs/serializers/glTF/2.0/glTFSerializer';
55
+ export * from '@babylonjs/serializers/OBJ';
55
56
 
56
57
  // Additional Babylon.js modules
57
58
  // These are not used in the "@combeenation/3d-viewer" repository directly, but required in consuming code for various
@@ -72,13 +73,13 @@ export * from './viewer-error';
72
73
  export * from './manager/camera-manager';
73
74
  export * from './manager/dimension-line-manager';
74
75
  export * from './manager/debug-manager';
75
- export * from './manager/dxf-export-manager';
76
76
  export * from './manager/event-manager';
77
- export * from './manager/gltf-export-manager';
77
+ export * from './manager/export-manager';
78
78
  export * from './manager/html-anchor-manager';
79
79
  export * from './manager/material-manager';
80
80
  export * from './manager/model-manager';
81
81
  export * from './manager/parameter-manager';
82
82
  export * from './manager/scene-manager';
83
83
  export * from './manager/texture-manager';
84
- export * from './helper/decals-helper';
84
+ export * from './utils/decal-utils';
85
+ export * from './utils/node-utils';
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AssetContainer,
3
3
  Color4,
4
+ DecalUtils,
4
5
  ISceneLoaderPlugin,
5
6
  InstancedMesh,
6
7
  ParsedDecalConfiguration,
@@ -8,7 +9,6 @@ import {
8
9
  SceneLoader,
9
10
  ViewerError,
10
11
  ViewerErrorIds,
11
- createDecalMesh,
12
12
  } from '../index';
13
13
  import { setInternalMetadataValue } from './metadata-helper';
14
14
  import { deleteAllTags, getTagsAsStrArr, setTagsAsString } from './tags-helper';
@@ -226,7 +226,7 @@ function _createDecals(dataParsed: unknown, container: AssetContainer): void {
226
226
 
227
227
  validatedDecals.forEach(decalConfig => {
228
228
  const { materialId, tags, ...decalMeshConfig } = decalConfig;
229
- const decalMesh = createDecalMesh(decalMeshConfig, container, false);
229
+ const decalMesh = DecalUtils.createDecalMesh(decalMeshConfig, container, false);
230
230
 
231
231
  // optionally set material and tags directly
232
232
  if (materialId) {
@@ -1,18 +1,14 @@
1
1
  import {
2
2
  DynamicTexture,
3
- FloatArray,
4
- Geometry,
5
3
  InstancedMesh,
6
4
  Material,
7
5
  Mesh,
8
- MorphTarget,
9
- MorphTargetManager,
10
6
  Node,
11
7
  NodeDescription,
8
+ NodeUtils,
12
9
  RenderTargetTexture,
13
10
  TransformNode,
14
11
  Vector3,
15
- VertexBuffer,
16
12
  Viewer,
17
13
  } from '../index';
18
14
  import { getIsScaledDownDevice } from './device-helper';
@@ -71,7 +67,7 @@ export async function exportPreProcess(viewer: Viewer, settings?: ExportPreProce
71
67
  // bake transformation of all meshes, so that no negative scalings are left
72
68
  // it's important that this is done AFTER instanced meshes have been converted (`_prepareNodeForExport`)
73
69
  nodesForExport.forEach(node => {
74
- if (node instanceof Mesh) _bakeGeometryOfMesh(node);
70
+ if (node instanceof Mesh) NodeUtils.bakeGeometryOfMesh(node);
75
71
  });
76
72
 
77
73
  // reset transformation of all "TransformNodes", as transform nodes are not considered by the `_bakeGeometryOfMesh`
@@ -273,52 +269,6 @@ function _createMeshFromInstancedMesh(
273
269
  return newMesh;
274
270
  }
275
271
 
276
- /**
277
- * Removes transformation data from the mesh and stores it in the geometry, which is called "baking".
278
- * Also considers the geometry change from morph targets.
279
- */
280
- function _bakeGeometryOfMesh(mesh: Mesh): void {
281
- if (!mesh.geometry) {
282
- // no geometry available, nothing to do
283
- return;
284
- }
285
-
286
- // geometries can be shared across multiple meshes, first make them unique to avoid side-effects
287
- mesh.makeGeometryUnique();
288
-
289
- // Babylon.js already provides a function for baking the current skeleton changes into the geometry
290
- if (mesh.skeleton) {
291
- mesh.applySkeleton(mesh.skeleton);
292
- mesh.skeleton = null;
293
- }
294
-
295
- // NOTE: in difference to skeletons and transformations there is no baking function for morph targets (yet)
296
- // however another approach could be to re-apply the position and normals data, as there are nice functions for it
297
- // - `getPositionData(applySkeleton: boolean = false, applyMorph: boolean = false)`
298
- // - `getNormalsData(applySkeleton: boolean = false, applyMorph: boolean = false)`
299
- // you can decide if skeletons and morph targets can be added, which is exactly what we want
300
- // I'm still hesitant to use it because "tangent" and "UV" kinds are not supported, whereas I'm not sure if it's
301
- // required
302
- // => try it out when there is enough time for detailed regression tests!
303
- const morphTargetManager = mesh.morphTargetManager;
304
- const geometry = mesh.geometry;
305
-
306
- if (morphTargetManager?.numTargets) {
307
- // apply morph target vertices data to mesh geometry
308
- // mostly only the "PositionKind" is implemented
309
- _bakeMorphTargetManagerIntoVertices(VertexBuffer.PositionKind, morphTargetManager, geometry);
310
- _bakeMorphTargetManagerIntoVertices(VertexBuffer.NormalKind, morphTargetManager, geometry);
311
- _bakeMorphTargetManagerIntoVertices(VertexBuffer.TangentKind, morphTargetManager, geometry);
312
- _bakeMorphTargetManagerIntoVertices(VertexBuffer.UVKind, morphTargetManager, geometry);
313
-
314
- // remove morph target manager with all it's morph targets
315
- mesh.morphTargetManager = null;
316
- }
317
-
318
- // bake the transformation data in the mesh geometry, fortunately there is already a help function from Babylon.js
319
- mesh.bakeCurrentTransformIntoVertices();
320
- }
321
-
322
272
  /**
323
273
  * Resets transformation to initial state
324
274
  */
@@ -328,51 +278,3 @@ function _resetTransformation(node: TransformNode): void {
328
278
  node.rotationQuaternion = null;
329
279
  node.scaling = new Vector3(1, 1, 1);
330
280
  }
331
-
332
- /**
333
- * @param kind morph targets can affect various vertices kinds, whereas "position" is the most common one
334
- * still other kinds (like normals or tangents) can be affected as well and can be provided on this input
335
- */
336
- function _bakeMorphTargetManagerIntoVertices(
337
- kind: string,
338
- morphTargetManager: MorphTargetManager,
339
- geometry: Geometry
340
- ): void {
341
- const origVerticesData = geometry.getVerticesData(kind);
342
- if (!origVerticesData) {
343
- // no vertices data for this kind availabe on the mesh geometry
344
- return;
345
- }
346
-
347
- let verticesData = [...origVerticesData];
348
- for (let i = 0; i < morphTargetManager.numTargets; i++) {
349
- const target = morphTargetManager.getTarget(i);
350
- const targetVerticesData = _getVerticesDataFromMorphTarget(kind, target);
351
- if (targetVerticesData) {
352
- // vertices data of this kind are implemented on the morph target
353
- // add the influence of this morph target to the vertices data
354
- // formula is taken from: https://doc.babylonjs.com/features/featuresDeepDive/mesh/morphTargets#basics
355
- verticesData = verticesData.map(
356
- (oldVal, idx) => oldVal + (targetVerticesData[idx] - origVerticesData[idx]) * target.influence
357
- );
358
- }
359
- }
360
-
361
- // apply the updated vertices data
362
- geometry.setVerticesData(kind, verticesData);
363
- }
364
-
365
- function _getVerticesDataFromMorphTarget(kind: string, morphTarget: MorphTarget): FloatArray | null {
366
- switch (kind) {
367
- case VertexBuffer.PositionKind:
368
- return morphTarget.getPositions();
369
- case VertexBuffer.NormalKind:
370
- return morphTarget.getNormals();
371
- case VertexBuffer.TangentKind:
372
- return morphTarget.getTangents();
373
- case VertexBuffer.UVKind:
374
- return morphTarget.getUVs();
375
- }
376
-
377
- return null;
378
- }
@@ -0,0 +1,273 @@
1
+ import {
2
+ Animation,
3
+ GLTF2Export,
4
+ IExportOptions,
5
+ Mesh,
6
+ Node,
7
+ NodeDescription,
8
+ OBJExport,
9
+ Vector3,
10
+ VertexBuffer,
11
+ Viewer,
12
+ } from '../index';
13
+ import {
14
+ downloadFile,
15
+ exportPostProcess,
16
+ exportPreProcess,
17
+ isExportableTransformNode,
18
+ normalizeFileName,
19
+ } from '../internal/export-helper';
20
+ import { getInternalMetadataValue } from '../internal/metadata-helper';
21
+ import { nodeMatchesAnyCriteria } from '../internal/node-helper';
22
+ import DRAWING, { Unit } from 'dxf-writer';
23
+
24
+ export type GltfExportSettings = {
25
+ fileName?: string;
26
+ /** List of nodes that should be excluded from the DXF export */
27
+ excludeNodes?: NodeDescription[];
28
+ /**
29
+ * Adjusts the exported GLB so that known issues get automatically fixed, this is mostly targeting Apples .usdz format
30
+ */
31
+ optimizeForAR?: boolean;
32
+ };
33
+
34
+ export type DxfUnit = Unit;
35
+
36
+ export type DxfExportSettings = {
37
+ fileName?: string;
38
+ /** List of nodes that should be excluded from the DXF export */
39
+ excludeNodes?: NodeDescription[];
40
+ /**
41
+ * Unit of the 3d model.\
42
+ * If a unit is set, CAD tools are able to convert the values from the DXF into the configured unit of the CAD tool.
43
+ */
44
+ unit?: DxfUnit;
45
+ };
46
+
47
+ export type ObjExportSettings = {
48
+ fileName?: string;
49
+ /** List of nodes that should be excluded from the DXF export */
50
+ excludeNodes?: NodeDescription[];
51
+ };
52
+
53
+ /**
54
+ * Manager for creating exports for glTF, DXF and OBJ of the current viewer scene
55
+ */
56
+ export class ExportManager {
57
+ protected _maxTextureSize: number;
58
+
59
+ /**
60
+ * Defines options for the export.
61
+ * We don't allow the user to overwrite certain settings, since we rely on properties like `removeNoopRootNodes` to
62
+ * stay `true` in order to make the AR export work.
63
+ * We could theoretically allow it if AR optimization is not desired, but this may confuse the user.
64
+ */
65
+ protected static _gltfExportOptions(settings?: GltfExportSettings): IExportOptions {
66
+ const { excludeNodes, optimizeForAR } = settings ?? {};
67
+
68
+ return {
69
+ shouldExportNode: function (node: Node): boolean {
70
+ if (optimizeForAR) {
71
+ // we explicitely marked nodes, that should be exported in AR mode
72
+ return !!getInternalMetadataValue(node, 'exportNode');
73
+ } else {
74
+ // use the default export node check (enabled state, exclusion list, etc...)
75
+ return isExportableTransformNode(node, excludeNodes);
76
+ }
77
+ },
78
+
79
+ shouldExportAnimation: (animation: Animation) => !optimizeForAR,
80
+ };
81
+ }
82
+
83
+ /** @internal */
84
+ public constructor(protected viewer: Viewer) {
85
+ // store initial max texture size, so that we can restore it in the post processing
86
+ this._maxTextureSize = viewer.engine.getCaps().maxTextureSize;
87
+ }
88
+
89
+ /**
90
+ * Return GLB export of current scene as `File` for further processing. (e.g. upload on AR endpoint)
91
+ */
92
+ public async createGlb(settings?: GltfExportSettings): Promise<File | undefined> {
93
+ const { fileName, excludeNodes, optimizeForAR } = settings ?? {};
94
+
95
+ if (optimizeForAR) await exportPreProcess(this.viewer, { excludeNodes, scaleDownTextures: true });
96
+ const glbData = await GLTF2Export.GLBAsync(this.viewer.scene, 'dummy', ExportManager._gltfExportOptions(settings));
97
+ if (optimizeForAR) await exportPostProcess(this.viewer, { initialTextureSize: this._maxTextureSize });
98
+
99
+ const resBlob = glbData.glTFFiles['dummy.glb'];
100
+ // check if result is valid, according to the typings this could also be a string
101
+ if (resBlob instanceof Blob) {
102
+ const normalizedFileName = normalizeFileName(fileName, 'glb', 'glb-export');
103
+ return new File([resBlob], normalizedFileName);
104
+ } else {
105
+ // result was not a valid blob
106
+ return undefined;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Exports and downloads current scene to GLB
112
+ */
113
+ public async downloadGlb(settings?: GltfExportSettings): Promise<void> {
114
+ const { fileName = 'glb-export', excludeNodes, optimizeForAR } = settings ?? {};
115
+
116
+ if (optimizeForAR) await exportPreProcess(this.viewer, { excludeNodes, scaleDownTextures: true });
117
+ const glb = await GLTF2Export.GLBAsync(this.viewer.scene, fileName, ExportManager._gltfExportOptions(settings));
118
+ glb.downloadFiles();
119
+ if (optimizeForAR) await exportPostProcess(this.viewer, { initialTextureSize: this._maxTextureSize });
120
+ }
121
+
122
+ /**
123
+ * Exports and downloads current scene to glTF.\
124
+ * This may result in more than one file, since textures are exported seperately.
125
+ */
126
+ public async downloadGltf(settings?: GltfExportSettings): Promise<void> {
127
+ const { fileName = 'gltf-export', excludeNodes, optimizeForAR } = settings ?? {};
128
+
129
+ if (optimizeForAR) await exportPreProcess(this.viewer, { excludeNodes, scaleDownTextures: true });
130
+ const gltf = await GLTF2Export.GLTFAsync(
131
+ this.viewer.scene,
132
+ // no need to add .glb, as Babylon.js does that internally
133
+ fileName,
134
+ ExportManager._gltfExportOptions(settings)
135
+ );
136
+ gltf.downloadFiles();
137
+ if (optimizeForAR) await exportPostProcess(this.viewer, { initialTextureSize: this._maxTextureSize });
138
+ }
139
+
140
+ /**
141
+ * Returns DXF export of current scene as `File` for further processing. (e.g upload as Cfgn file)
142
+ */
143
+ public async createDxf(settings?: DxfExportSettings): Promise<File> {
144
+ const normalizedFileName = normalizeFileName(settings?.fileName, 'dxf', 'dxf-export');
145
+
146
+ const dxfBlob = await this._createDxfBlob(settings);
147
+ const dxfFile = new File([dxfBlob], normalizedFileName, { type: 'application/dxf' });
148
+
149
+ return dxfFile;
150
+ }
151
+
152
+ /**
153
+ * Creates DXF export of current scene and downloads the resulting file right away
154
+ */
155
+ public async downloadDxf(settings?: DxfExportSettings): Promise<void> {
156
+ const normalizedFileName = normalizeFileName(settings?.fileName, 'dxf', 'dxf-export');
157
+
158
+ const dxfBlob = await this._createDxfBlob(settings);
159
+
160
+ const url = URL.createObjectURL(dxfBlob);
161
+ downloadFile(url, normalizedFileName);
162
+ URL.revokeObjectURL(url);
163
+ }
164
+
165
+ /**
166
+ * Creates OBJ export of current scene and downloads the resulting file right away
167
+ */
168
+ // TODO 1: (optionally) create a MTL file as well
169
+ // TODO 2: add `createObj` function if required, for usage as cfgn file etc...
170
+ public async downloadObj(settings?: ObjExportSettings): Promise<void> {
171
+ const { fileName, excludeNodes } = settings ?? {};
172
+ const normalizedFileName = normalizeFileName(fileName, 'obj', 'obj-export');
173
+
174
+ await exportPreProcess(this.viewer, { excludeNodes });
175
+ const objString = this._createObj();
176
+ await exportPostProcess(this.viewer);
177
+
178
+ const objBlob = new Blob([objString], { type: 'text/plain' });
179
+ const url = URL.createObjectURL(objBlob);
180
+ downloadFile(url, normalizedFileName);
181
+ URL.revokeObjectURL(url);
182
+ }
183
+
184
+ /**
185
+ * Help function for creating a blob with the DXF string, as this is needed for both public interface functions
186
+ * (`exportDxf` & `exportDxfToFile`)
187
+ */
188
+ protected async _createDxfBlob(settings?: DxfExportSettings): Promise<Blob> {
189
+ const { excludeNodes, unit } = settings ?? {};
190
+
191
+ // Transformation baking pre process is required for DXF exports, as we take the plain vertex information for the
192
+ // DXF conversion, therefore the vertices need to be located in world already
193
+ await exportPreProcess(this.viewer, { excludeNodes });
194
+ const dxfString = this._createDxf(unit);
195
+ await exportPostProcess(this.viewer);
196
+
197
+ const dxfBlob = new Blob([dxfString], { type: 'application/dxf' });
198
+ return dxfBlob;
199
+ }
200
+
201
+ /**
202
+ * DXF creation process.\
203
+ * We go through all vertices of all meshes and create DXF 3d faces accordingly.
204
+ */
205
+ protected _createDxf(unit?: DxfUnit): string {
206
+ const DXF = new DRAWING();
207
+ if (unit) {
208
+ DXF.setUnits(unit);
209
+ }
210
+
211
+ const meshesToExport = this.viewer.scene.meshes.filter(
212
+ mesh =>
213
+ getInternalMetadataValue(mesh, 'exportNode') &&
214
+ // NOTE: can't add this criteria in pre export process, as pre export process works recursively and childs of
215
+ // transforms nodes or meshes without geometry can still have geometries and therefore be valid for the export
216
+ !nodeMatchesAnyCriteria(mesh, { hasInvalidBoundingInfo: true })
217
+ );
218
+
219
+ meshesToExport.forEach(mesh => {
220
+ const positions = mesh.getVerticesData(VertexBuffer.PositionKind);
221
+ const indices = mesh.getIndices();
222
+ if (!positions || !indices) {
223
+ console.warn(`Can't create DXF export of mesh "${mesh.name}", as there is no vertex data available`);
224
+ return;
225
+ }
226
+
227
+ for (let i = 0; i < indices.length; i += 3) {
228
+ // A face always consists of 3 vertices.
229
+ // First we need to get the indizes of the vertices.
230
+ const idx1 = indices[i];
231
+ const idx2 = indices[i + 1];
232
+ const idx3 = indices[i + 2];
233
+
234
+ // Now get the x, y, z data of the associated index.
235
+ // One index stores 3 vertices, thats why the index is multiplied with 3 before accessing the actual vertex
236
+ // position.
237
+ // > and z components have dedicated offsets 1 and 2.
238
+ // ===============
239
+ // Important NOTE:
240
+ // ===============
241
+ // DXF is right-handed, according to tests in AutoDesk it seems like y and z components are just switched.
242
+ // So we use offset 2 for y and offset 1 for z.
243
+ const p1 = new Vector3(positions[idx1 * 3], positions[idx1 * 3 + 2], positions[idx1 * 3 + 1]);
244
+ const p2 = new Vector3(positions[idx2 * 3], positions[idx2 * 3 + 2], positions[idx2 * 3 + 1]);
245
+ const p3 = new Vector3(positions[idx3 * 3], positions[idx3 * 3 + 2], positions[idx3 * 3 + 1]);
246
+
247
+ // Add a 3D face to the DXF (3DFACE entity).
248
+ // The library works with 4 points per face, but we only have 3.
249
+ // Using the last point 3 times is fine though.
250
+ DXF.drawFace(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, p3.x, p3.y, p3.z);
251
+ }
252
+ });
253
+
254
+ const dxfString = DXF.toDxfString();
255
+ return dxfString;
256
+ }
257
+
258
+ /**
259
+ * Creates OBJ export string from meshes, which are marked for the export
260
+ */
261
+ protected _createObj(): string {
262
+ const meshesToExport = this.viewer.scene.meshes.filter(
263
+ mesh =>
264
+ getInternalMetadataValue(mesh, 'exportNode') &&
265
+ // NOTE: can't add this criteria in pre export process, as pre export process works recursively and childs of
266
+ // transforms nodes or meshes without geometry can still have geometries and therefore be valid for the export
267
+ !nodeMatchesAnyCriteria(mesh, { hasInvalidBoundingInfo: true })
268
+ ) as Mesh[];
269
+
270
+ const objString = OBJExport.OBJ(meshesToExport, true, 'materials', false);
271
+ return objString;
272
+ }
273
+ }
@@ -78,7 +78,7 @@ export type DecalConfiguration = {
78
78
  * - overwrite decal mesh side orientation (important for glTF models)
79
79
  * - move decal along the "normal" to avoid clipping
80
80
  */
81
- export function createDecalMesh(config: DecalConfiguration, assetContainer: IAssetContainer, addToScene = true): Mesh {
81
+ function createDecalMesh(config: DecalConfiguration, assetContainer: IAssetContainer, addToScene = true): Mesh {
82
82
  const sourceMesh = assetContainer.meshes.find(mesh => mesh.name === config.sourceMeshName);
83
83
  if (!sourceMesh) {
84
84
  throw new ViewerError({
@@ -127,3 +127,8 @@ export function createDecalMesh(config: DecalConfiguration, assetContainer: IAss
127
127
 
128
128
  return decalMesh;
129
129
  }
130
+
131
+ // export functions under "namespace", so that they can found easier in consuming code
132
+ export const DecalUtils = {
133
+ createDecalMesh,
134
+ };