@combeenation/3d-viewer 12.0.0-alpha1 → 12.0.0-alpha3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combeenation/3d-viewer",
3
- "version": "12.0.0-alpha1",
3
+ "version": "12.0.0-alpha3",
4
4
  "description": "Combeenation 3D Viewer",
5
5
  "homepage": "https://github.com/Combeenation/3d-viewer#readme",
6
6
  "bugs": {
@@ -59,26 +59,31 @@ export class GltfExportManager {
59
59
  }
60
60
 
61
61
  protected async _exportPreProcess(excluded?: ExcludedGeometryList): Promise<void> {
62
+ this.viewer.pauseRendering();
63
+
62
64
  // handle materials
63
65
  this.viewer.scene.materials
64
66
  .filter(material => this._shouldReplaceMaterial(material))
65
67
  .forEach(material => this._createRefractionMaterialReplacement(material as PBRMaterial));
66
68
 
67
69
  // handle nodes
68
- this.viewer.scene.rootNodes.forEach(rootNode =>
69
- this._prepareNodeForExport(rootNode as TransformNode, null, excluded)
70
- );
70
+ this.viewer.scene.rootNodes.forEach(rootNode => this._prepareNodeForExport(rootNode, null, excluded));
71
+
72
+ // bake transformation of all meshes, so that no negative scalings are left
73
+ // it's important that this is done AFTER instanced meshes have been converted (_prepareNodeForExport)
74
+ this.viewer.scene.meshes
75
+ .filter(mesh => !!mesh.metadata?.[GltfExportManager._METADATA_PROPS.exportNode])
76
+ .forEach(mesh => bakeGeometryOfMesh(mesh as Mesh));
71
77
 
72
78
  // reset transformation of all "TransformNodes", which couldn't be handled by the geometry baking algorithm
73
79
  // it's important that this is done AFTER all geometries have been baked
74
- this.viewer.scene
75
- .getNodes()
80
+ [...this.viewer.scene.transformNodes, ...this.viewer.scene.meshes]
76
81
  .filter(node => !!node.metadata?.[GltfExportManager._METADATA_PROPS.exportNode])
77
82
  .forEach(node => resetTransformation(node as TransformNode));
78
83
  }
79
84
 
80
85
  protected async _exportPostProcess(): Promise<void> {
81
- // dispose all nodes and material that have only been created for the export
86
+ // dispose all nodes and materials that have only been created for the export
82
87
  this.viewer.scene.rootNodes
83
88
  .filter(rootNode => rootNode.metadata?.[GltfExportManager._METADATA_PROPS.deleteAfterExport])
84
89
  .forEach(rootNode => rootNode.dispose());
@@ -86,6 +91,8 @@ export class GltfExportManager {
86
91
  this.viewer.scene.materials
87
92
  .filter(mat => !!mat.metadata?.[GltfExportManager._METADATA_PROPS.deleteAfterExport])
88
93
  .forEach(material => material.dispose(false, false));
94
+
95
+ this.viewer.resumeRendering();
89
96
  }
90
97
 
91
98
  protected _gltfExportOptions(): IExportOptions {
@@ -95,13 +102,13 @@ export class GltfExportManager {
95
102
  },
96
103
  // keep root node(s)
97
104
  // this seems to be important due to the geometry baking and transformation resetting stuff
98
- // => root node has no transformation anymore, which seems to be problematic for the import
105
+ // => root node would have no transformation anymore, which seems to be problematic for the import
99
106
  removeNoopRootNodes: false,
100
107
  };
101
108
  }
102
109
 
103
110
  protected _prepareNodeForExport(
104
- node: TransformNode,
111
+ node: BjsNode,
105
112
  clonedParent: Nullable<TransformNode>,
106
113
  excluded?: ExcludedGeometryList
107
114
  ) {
@@ -109,17 +116,18 @@ export class GltfExportManager {
109
116
  return;
110
117
  }
111
118
 
119
+ // from here on we only have TransformNodes
120
+ const transformNode = node as TransformNode;
121
+
112
122
  // clone original node and create unique name (via uniqueId)
113
- const newNodeName = `${node.name}_${node.uniqueId}`;
123
+ const newNodeName = `${transformNode.name}_${transformNode.uniqueId}`;
114
124
  const clonedNode =
115
- node instanceof InstancedMesh
116
- ? createMeshFromInstancedMesh(node, newNodeName)
117
- : node.clone(newNodeName, clonedParent, true)!;
125
+ transformNode instanceof InstancedMesh
126
+ ? createMeshFromInstancedMesh(transformNode, newNodeName, clonedParent)
127
+ : transformNode.clone(newNodeName, clonedParent, true)!;
118
128
 
119
- // bake transformation, so that we won't get negative values anymore
120
- // also exchange material
129
+ // exchange material
121
130
  if (clonedNode instanceof Mesh) {
122
- bakeGeometryOfMesh(clonedNode);
123
131
  const exchangeWithMaterial =
124
132
  clonedNode.material?.metadata?.[GltfExportManager._METADATA_PROPS.exchangeMaterialWith];
125
133
  if (exchangeWithMaterial) {
@@ -133,8 +141,8 @@ export class GltfExportManager {
133
141
  [GltfExportManager._METADATA_PROPS.deleteAfterExport]: true,
134
142
  });
135
143
 
136
- // recourse into children
137
- const childs = node.getChildTransformNodes(true);
144
+ // handle children
145
+ const childs = transformNode.getChildTransformNodes(true);
138
146
  childs.forEach(child => this._prepareNodeForExport(child, clonedNode, excluded));
139
147
  }
140
148
 
@@ -172,12 +180,12 @@ export class GltfExportManager {
172
180
  /**
173
181
  * Create an export-friendly replacement material for a material using refraction.
174
182
  */
175
- protected _createRefractionMaterialReplacement(material: PBRMaterial): PBRMaterial {
183
+ protected _createRefractionMaterialReplacement(material: PBRMaterial) {
176
184
  const newName = `${material.name}_clone`;
177
- // change material according to https://www.notion.so/combeenation/Glas-materials-don-t-look-glasy-after-export-d5fda2c6515e4420a8772744d3e6b460
178
- const clonedMaterial = material.clone(newName); // clone material
185
+
186
+ const clonedMaterial = material.clone(newName);
179
187
  clonedMaterial.refractionTexture = null;
180
- clonedMaterial.metallicReflectanceTexture = null; // is this the correct one for metallic roughness?
188
+ clonedMaterial.metallicReflectanceTexture = null;
181
189
  clonedMaterial.alpha = 0.7;
182
190
  clonedMaterial.albedoColor = new Color3(0.3, 0.3, 0.3);
183
191
  clonedMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHABLEND;
@@ -186,7 +194,5 @@ export class GltfExportManager {
186
194
 
187
195
  injectMetadata(material, { [GltfExportManager._METADATA_PROPS.exchangeMaterialWith]: newName });
188
196
  injectMetadata(clonedMaterial, { [GltfExportManager._METADATA_PROPS.deleteAfterExport]: true });
189
-
190
- return clonedMaterial;
191
197
  }
192
198
  }
@@ -8,14 +8,24 @@ import type { MorphTarget } from '@babylonjs/core/Morph';
8
8
  import { MorphTargetManager } from '@babylonjs/core/Morph/morphTargetManager';
9
9
  import type { FloatArray } from '@babylonjs/core/types';
10
10
 
11
- const createMeshFromInstancedMesh = function (instancedMesh: InstancedMesh, newName: string) {
11
+ const createMeshFromInstancedMesh = function (
12
+ instancedMesh: InstancedMesh,
13
+ newName: string,
14
+ clonedParent: Nullable<TransformNode>
15
+ ) {
12
16
  // first create a clone of the source mesh
13
- const newMesh = instancedMesh.sourceMesh.clone(newName, instancedMesh.parent);
14
- // apply the transformation data
15
- newMesh.position = instancedMesh.position;
16
- newMesh.rotation = instancedMesh.rotation;
17
- newMesh.rotationQuaternion = instancedMesh.rotationQuaternion;
18
- newMesh.scaling = instancedMesh.scaling;
17
+ const newMesh = instancedMesh.sourceMesh.clone(newName, clonedParent, true);
18
+ // apply the transformation data, it's important to create clones of the transformations to not touch the original
19
+ // transformation when applying changes (eg: geometry baking)
20
+ newMesh.position = instancedMesh.position.clone();
21
+ newMesh.rotation = instancedMesh.rotation.clone();
22
+ newMesh.scaling = instancedMesh.scaling.clone();
23
+
24
+ // rotation quaternion is optional
25
+ if (instancedMesh.rotationQuaternion) {
26
+ newMesh.rotationQuaternion = instancedMesh.rotationQuaternion.clone();
27
+ }
28
+
19
29
  // also sync the enabled state from the original instanced mesh
20
30
  newMesh.setEnabled(instancedMesh.isEnabled(false));
21
31