three-cad-viewer 4.3.2 → 4.3.5
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/dist/core/types.d.ts +10 -11
- package/dist/rendering/material-factory.d.ts +3 -5
- package/dist/scene/clipping.d.ts +6 -0
- package/dist/three-cad-viewer.esm.js +62 -45
- package/dist/three-cad-viewer.esm.js.map +1 -1
- package/dist/three-cad-viewer.esm.min.js +2 -2
- package/dist/three-cad-viewer.js +62 -45
- package/dist/three-cad-viewer.min.js +2 -2
- package/package.json +2 -1
- package/src/_version.ts +1 -1
- package/src/core/studio-manager.ts +1 -1
- package/src/core/types.ts +11 -9
- package/src/rendering/material-factory.ts +26 -31
- package/src/rendering/studio-floor.ts +1 -1
- package/src/scene/clipping.ts +10 -0
- package/src/scene/nestedgroup.ts +25 -9
package/dist/three-cad-viewer.js
CHANGED
|
@@ -83127,10 +83127,12 @@ void main() {
|
|
|
83127
83127
|
}
|
|
83128
83128
|
}
|
|
83129
83129
|
// --- Anisotropy (brushed metal) ---
|
|
83130
|
-
|
|
83131
|
-
|
|
83132
|
-
|
|
83133
|
-
|
|
83130
|
+
if (def.anisotropy !== undefined && def.anisotropy > 0) {
|
|
83131
|
+
material.anisotropy = def.anisotropy;
|
|
83132
|
+
if (def.anisotropyRotation !== undefined) {
|
|
83133
|
+
material.anisotropyRotation = def.anisotropyRotation;
|
|
83134
|
+
}
|
|
83135
|
+
}
|
|
83134
83136
|
// --- Textures ---
|
|
83135
83137
|
// Resolve all texture references via TextureCache.
|
|
83136
83138
|
// The TextureCache determines colorSpace internally from the texture role name.
|
|
@@ -83147,13 +83149,14 @@ void main() {
|
|
|
83147
83149
|
* "roughness", "normal") where each entry has an optional `value` (scalar or
|
|
83148
83150
|
* [r,g,b] array in **linear RGB**) and/or `texture` (inline data URI).
|
|
83149
83151
|
*
|
|
83150
|
-
* @param
|
|
83152
|
+
* @param values - Scalar PBR values from threejs-materials
|
|
83153
|
+
* @param textures - Texture map references from threejs-materials
|
|
83151
83154
|
* @param textureRepeat - Optional [u, v] texture tiling applied to all loaded textures
|
|
83152
83155
|
* @param textureCache - TextureCache for resolving data URI textures
|
|
83153
83156
|
* @param label - Optional label for GPU tracking
|
|
83154
83157
|
* @returns Configured MeshPhysicalMaterial
|
|
83155
83158
|
*/
|
|
83156
|
-
async createStudioMaterialFromMaterialX(
|
|
83159
|
+
async createStudioMaterialFromMaterialX(values, textures, textureRepeat, textureCache, label) {
|
|
83157
83160
|
// --- Build material options from scalar values ---
|
|
83158
83161
|
const matOptions = {
|
|
83159
83162
|
flatShading: false,
|
|
@@ -83164,37 +83167,32 @@ void main() {
|
|
|
83164
83167
|
depthTest: true,
|
|
83165
83168
|
};
|
|
83166
83169
|
// Warn once if displacement data is present (not supported in Studio)
|
|
83167
|
-
if (
|
|
83170
|
+
if (textures.displacement || values.displacementScale !== undefined) {
|
|
83168
83171
|
logger.warn("Displacement not supported by the Studio");
|
|
83169
83172
|
}
|
|
83170
|
-
for (const [key,
|
|
83171
|
-
if (prop.value === undefined)
|
|
83172
|
-
continue;
|
|
83173
|
+
for (const [key, value] of Object.entries(values)) {
|
|
83173
83174
|
// Skip displacement properties (not supported, would waste GPU memory)
|
|
83174
83175
|
if (key === "displacement" || key === "displacementScale" || key === "displacementBias")
|
|
83175
83176
|
continue;
|
|
83176
|
-
// Skip anisotropy — requires tangent vectors that CAD meshes don't have
|
|
83177
|
-
if (key === "anisotropy" || key === "anisotropyRotation")
|
|
83178
|
-
continue;
|
|
83179
83177
|
// Color arrays → THREE.Color (already linear, no sRGB conversion)
|
|
83180
|
-
if (COLOR_ARRAY_KEYS.has(key) && Array.isArray(
|
|
83181
|
-
const [r, g, b] =
|
|
83178
|
+
if (COLOR_ARRAY_KEYS.has(key) && Array.isArray(value)) {
|
|
83179
|
+
const [r, g, b] = value;
|
|
83182
83180
|
matOptions[key] = new Color(r, g, b);
|
|
83183
83181
|
}
|
|
83184
|
-
else if ((key === "normalScale" || key === "clearcoatNormalScale") && Array.isArray(
|
|
83185
|
-
matOptions[key] = new Vector2(
|
|
83182
|
+
else if ((key === "normalScale" || key === "clearcoatNormalScale") && Array.isArray(value)) {
|
|
83183
|
+
matOptions[key] = new Vector2(value[0], value[1]);
|
|
83186
83184
|
}
|
|
83187
|
-
else if (key === "iridescenceThicknessRange" && Array.isArray(
|
|
83188
|
-
matOptions[key] =
|
|
83185
|
+
else if (key === "iridescenceThicknessRange" && Array.isArray(value)) {
|
|
83186
|
+
matOptions[key] = value;
|
|
83189
83187
|
}
|
|
83190
83188
|
else {
|
|
83191
|
-
matOptions[key] =
|
|
83189
|
+
matOptions[key] = value;
|
|
83192
83190
|
}
|
|
83193
83191
|
}
|
|
83194
83192
|
// --- Handle transmission ---
|
|
83195
|
-
const transmissionVal =
|
|
83196
|
-
const opacityVal =
|
|
83197
|
-
const transparentVal =
|
|
83193
|
+
const transmissionVal = values.transmission;
|
|
83194
|
+
const opacityVal = values.opacity;
|
|
83195
|
+
const transparentVal = values.transparent;
|
|
83198
83196
|
if (typeof transmissionVal === "number" && transmissionVal > 0) {
|
|
83199
83197
|
matOptions.transparent = false;
|
|
83200
83198
|
matOptions.opacity = 1.0;
|
|
@@ -83212,9 +83210,7 @@ void main() {
|
|
|
83212
83210
|
// --- Resolve textures ---
|
|
83213
83211
|
let hasTextures = false;
|
|
83214
83212
|
if (textureCache) {
|
|
83215
|
-
for (const [key,
|
|
83216
|
-
if (!prop.texture)
|
|
83217
|
-
continue;
|
|
83213
|
+
for (const [key, textureRef] of Object.entries(textures)) {
|
|
83218
83214
|
const mapName = PROPERTY_TO_MAP[key];
|
|
83219
83215
|
if (!mapName)
|
|
83220
83216
|
continue;
|
|
@@ -83225,7 +83221,7 @@ void main() {
|
|
|
83225
83221
|
const roleForCache = colorSpace === SRGBColorSpace
|
|
83226
83222
|
? "baseColorTexture"
|
|
83227
83223
|
: "normalTexture";
|
|
83228
|
-
const tex = await textureCache.get(
|
|
83224
|
+
const tex = await textureCache.get(textureRef, roleForCache);
|
|
83229
83225
|
if (tex) {
|
|
83230
83226
|
if (textureRepeat) {
|
|
83231
83227
|
tex.repeat.set(textureRepeat[0], textureRepeat[1]);
|
|
@@ -83346,9 +83342,9 @@ void main() {
|
|
|
83346
83342
|
const sheenRoughnessTex = await resolve(def.sheenRoughnessMap, "sheenRoughnessTexture");
|
|
83347
83343
|
if (sheenRoughnessTex)
|
|
83348
83344
|
material.sheenRoughnessMap = sheenRoughnessTex;
|
|
83349
|
-
|
|
83350
|
-
|
|
83351
|
-
|
|
83345
|
+
const anisotropyTex = await resolve(def.anisotropyMap, "anisotropyTexture");
|
|
83346
|
+
if (anisotropyTex)
|
|
83347
|
+
material.anisotropyMap = anisotropyTex;
|
|
83352
83348
|
}
|
|
83353
83349
|
/**
|
|
83354
83350
|
* Update global settings.
|
|
@@ -83386,10 +83382,10 @@ void main() {
|
|
|
83386
83382
|
})(exports.CollapseState || (exports.CollapseState = {}));
|
|
83387
83383
|
/**
|
|
83388
83384
|
* Type guard to check if a material entry is a threejs-materials format dict.
|
|
83389
|
-
* Detected by the presence of the `
|
|
83385
|
+
* Detected by the presence of the `values` key.
|
|
83390
83386
|
*/
|
|
83391
83387
|
function isMaterialXMaterial(m) {
|
|
83392
|
-
return typeof m === "object" && m !== null && "
|
|
83388
|
+
return typeof m === "object" && m !== null && "values" in m;
|
|
83393
83389
|
}
|
|
83394
83390
|
/**
|
|
83395
83391
|
* Check if shape uses binary format (has triangles_per_face).
|
|
@@ -84007,13 +84003,9 @@ float metalnessFactor = metalness;
|
|
|
84007
84003
|
}
|
|
84008
84004
|
return false;
|
|
84009
84005
|
}
|
|
84010
|
-
/** Check whether a threejs-materials entry has texture references
|
|
84006
|
+
/** Check whether a threejs-materials entry has texture references. */
|
|
84011
84007
|
function materialXHasTextures(entry) {
|
|
84012
|
-
|
|
84013
|
-
if (prop.texture)
|
|
84014
|
-
return true;
|
|
84015
|
-
}
|
|
84016
|
-
return false;
|
|
84008
|
+
return Object.keys(entry.textures).length > 0;
|
|
84017
84009
|
}
|
|
84018
84010
|
class NestedGroup {
|
|
84019
84011
|
/**
|
|
@@ -84131,7 +84123,7 @@ float metalnessFactor = metalness;
|
|
|
84131
84123
|
logger.warn(`Invalid material string '${entry}' for tag '${tag}' (expected "builtin:" prefix)`);
|
|
84132
84124
|
return null;
|
|
84133
84125
|
}
|
|
84134
|
-
// MaterialXMaterial entry: object with `
|
|
84126
|
+
// MaterialXMaterial entry: object with `values` key
|
|
84135
84127
|
if (isMaterialXMaterial(entry)) {
|
|
84136
84128
|
this.resolvedMaterialX.set(tag, entry);
|
|
84137
84129
|
return entry;
|
|
@@ -84145,11 +84137,15 @@ float metalnessFactor = metalness;
|
|
|
84145
84137
|
logger.warn(`Unknown builtin preset '${presetName}' referenced by '${tag}' on '${objectPath}'`);
|
|
84146
84138
|
return null;
|
|
84147
84139
|
}
|
|
84148
|
-
|
|
84140
|
+
// Strip preset color unless the user explicitly provides one,
|
|
84141
|
+
// so the leaf node's CAD color is used as fallback.
|
|
84142
|
+
const { color: presetColor, ...presetRest } = preset;
|
|
84143
|
+
const resolved = "color" in appearance
|
|
84144
|
+
? { ...preset, ...appearance }
|
|
84145
|
+
: { ...presetRest, ...appearance };
|
|
84149
84146
|
this.resolvedMaterials.set(tag, resolved);
|
|
84150
84147
|
return resolved;
|
|
84151
84148
|
}
|
|
84152
|
-
// Should not happen with current type, but guard anyway
|
|
84153
84149
|
logger.warn(`Unrecognised material entry for tag '${tag}' on '${objectPath}'`);
|
|
84154
84150
|
return null;
|
|
84155
84151
|
}
|
|
@@ -84763,7 +84759,7 @@ float metalnessFactor = metalness;
|
|
|
84763
84759
|
try {
|
|
84764
84760
|
if (resolved && isMaterialXMaterial(resolved)) {
|
|
84765
84761
|
// --- threejs-materials path ---
|
|
84766
|
-
studioMaterial = await this.materialFactory.createStudioMaterialFromMaterialX(resolved.
|
|
84762
|
+
studioMaterial = await this.materialFactory.createStudioMaterialFromMaterialX(resolved.values, resolved.textures, resolved.textureRepeat, this._textureCache);
|
|
84767
84763
|
if (materialXHasTextures(resolved)) {
|
|
84768
84764
|
this._texturedMaterialKeys.add(sharingKey);
|
|
84769
84765
|
}
|
|
@@ -84840,6 +84836,18 @@ float metalnessFactor = metalness;
|
|
|
84840
84836
|
}
|
|
84841
84837
|
studioBack = cachedBack;
|
|
84842
84838
|
}
|
|
84839
|
+
// Compute tangents for anisotropic materials (required by Three.js)
|
|
84840
|
+
if (studioMaterial instanceof MeshPhysicalMaterial &&
|
|
84841
|
+
studioMaterial.anisotropy > 0 &&
|
|
84842
|
+
obj.shapeGeometry?.getAttribute("uv") != null &&
|
|
84843
|
+
obj.shapeGeometry.getAttribute("tangent") == null) {
|
|
84844
|
+
try {
|
|
84845
|
+
obj.shapeGeometry.computeTangents();
|
|
84846
|
+
}
|
|
84847
|
+
catch {
|
|
84848
|
+
logger.debug(`Studio "${path}": tangent computation failed, anisotropy may have artifacts`);
|
|
84849
|
+
}
|
|
84850
|
+
}
|
|
84843
84851
|
// Apply to ObjectGroup
|
|
84844
84852
|
obj.enterStudioMode(studioMaterial instanceof MeshPhysicalMaterial ? studioMaterial : null, studioBack);
|
|
84845
84853
|
}
|
|
@@ -87476,6 +87484,15 @@ float metalnessFactor = metalness;
|
|
|
87476
87484
|
const z = this.distanceToPoint(new Vector3(0, 0, 0));
|
|
87477
87485
|
this.constant = z - c + value;
|
|
87478
87486
|
}
|
|
87487
|
+
/**
|
|
87488
|
+
* Clone this CenteredPlane.
|
|
87489
|
+
* Overrides THREE.Plane.clone() which calls `new this.constructor()` without
|
|
87490
|
+
* arguments, causing `center` to be undefined during shadow map generation.
|
|
87491
|
+
*/
|
|
87492
|
+
// @ts-expect-error -- THREE.Plane.clone() returns `this`, but we need a concrete CenteredPlane
|
|
87493
|
+
clone() {
|
|
87494
|
+
return new CenteredPlane(this.normal.clone(), this.centeredConstant, [...this.center]);
|
|
87495
|
+
}
|
|
87479
87496
|
}
|
|
87480
87497
|
// ============================================================================
|
|
87481
87498
|
// PlaneMesh - Visual representation of a clipping plane
|
|
@@ -94290,7 +94307,7 @@ float metalnessFactor = metalness;
|
|
|
94290
94307
|
}
|
|
94291
94308
|
}
|
|
94292
94309
|
|
|
94293
|
-
const version = "4.3.
|
|
94310
|
+
const version = "4.3.5";
|
|
94294
94311
|
|
|
94295
94312
|
/**
|
|
94296
94313
|
* Clean room environment for Studio mode PMREM generation.
|
|
@@ -95915,7 +95932,7 @@ float metalnessFactor = metalness;
|
|
|
95915
95932
|
* Create a shadow-receiving plane at the floor position.
|
|
95916
95933
|
*/
|
|
95917
95934
|
_createShadowPlane(zPosition, sceneSize) {
|
|
95918
|
-
const floorSize = sceneSize *
|
|
95935
|
+
const floorSize = sceneSize * 6;
|
|
95919
95936
|
const geometry = new PlaneGeometry(floorSize, floorSize);
|
|
95920
95937
|
const material = new ShadowMaterial({ opacity: 0.5, depthWrite: false });
|
|
95921
95938
|
const plane = new Mesh(geometry, material);
|
|
@@ -104762,7 +104779,7 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, const in float depth,
|
|
|
104762
104779
|
light.position.copy(bboxCenter).addScaledVector(dir, maxExtent * 3);
|
|
104763
104780
|
light.target.position.copy(bboxCenter);
|
|
104764
104781
|
light.castShadow = true;
|
|
104765
|
-
const frustumSize = maxExtent *
|
|
104782
|
+
const frustumSize = maxExtent * 6.0;
|
|
104766
104783
|
light.shadow.camera.left = -frustumSize;
|
|
104767
104784
|
light.shadow.camera.right = frustumSize;
|
|
104768
104785
|
light.shadow.camera.top = frustumSize;
|