diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_visibility.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_visibility.ts new file mode 100644 index 00000000000..c1a738b7e9a --- /dev/null +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_visibility.ts @@ -0,0 +1,68 @@ +import type { AbstractMesh } from "core/Meshes/abstractMesh"; +import type { GLTFLoader } from "../glTFLoader"; +import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; +import { registerGLTFExtension, unregisterGLTFExtension } from "../glTFLoaderExtensionRegistry"; + +const NAME = "KHR_node_visibility"; + +declare module "../../glTFFileLoader" { + // eslint-disable-next-line jsdoc/require-jsdoc + export interface GLTFLoaderExtensionOptions { + /** + * Defines options for the KHR_node_visibility extension. + */ + // NOTE: Don't use NAME here as it will break the UMD type declarations. + ["KHR_node_visibility"]: {}; + } +} + +/** + * Loader extension for KHR_node_visibility + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export class KHR_node_visibility implements IGLTFLoaderExtension { + /** + * The name of this extension. + */ + public readonly name = NAME; + /** + * Defines whether this extension is enabled. + */ + public enabled: boolean; + + private _loader: GLTFLoader; + + /** + * @internal + */ + constructor(loader: GLTFLoader) { + this._loader = loader; + this.enabled = loader.isExtensionUsed(NAME); + } + + public async onReady(): Promise { + this._loader.gltf.nodes?.forEach((node) => { + node._primitiveBabylonMeshes?.forEach((mesh) => { + mesh.inheritVisibility = true; + }); + // When the JSON Pointer is used we need to change both the transform node and the primitive meshes to the new value. + if (node.extensions?.KHR_node_visibility) { + if (node.extensions?.KHR_node_visibility.visible === false) { + if (node._babylonTransformNode) { + (node._babylonTransformNode as AbstractMesh).isVisible = false; + } + node._primitiveBabylonMeshes?.forEach((mesh) => { + mesh.isVisible = false; + }); + } + } + }); + } + + public dispose() { + (this._loader as any) = null; + } +} + +unregisterGLTFExtension(NAME); +registerGLTFExtension(NAME, true, (loader) => new KHR_node_visibility(loader)); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/dynamic.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/dynamic.ts index 810ba0bf2a9..f7b405abc39 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/dynamic.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/dynamic.ts @@ -165,4 +165,9 @@ export function registerBuiltInGLTFExtensions() { const { MSFT_sRGBFactors } = await import("./MSFT_sRGBFactors"); return new MSFT_sRGBFactors(loader); }); + + registerGLTFExtension("KHR_node_visibility", true, async (loader) => { + const { KHR_node_visibility } = await import("./KHR_node_visibility"); + return new KHR_node_visibility(loader); + }); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts index 1cd54557d92..81af328b07a 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts @@ -29,4 +29,5 @@ export * from "./MSFT_lod"; export * from "./MSFT_minecraftMesh"; export * from "./MSFT_sRGBFactors"; export * from "./KHR_interactivity"; +export * from "./KHR_node_visibility"; export * from "./ExtrasAsMetadata"; diff --git a/packages/tools/tests/test/visualization/ReferenceImages/gltfNodeVisibility.png b/packages/tools/tests/test/visualization/ReferenceImages/gltfNodeVisibility.png new file mode 100644 index 00000000000..2adc8d298e0 Binary files /dev/null and b/packages/tools/tests/test/visualization/ReferenceImages/gltfNodeVisibility.png differ diff --git a/packages/tools/tests/test/visualization/config.json b/packages/tools/tests/test/visualization/config.json index 23a6943d29a..cb5ec65b820 100644 --- a/packages/tools/tests/test/visualization/config.json +++ b/packages/tools/tests/test/visualization/config.json @@ -960,6 +960,11 @@ "playgroundId": "#WGZLGJ#3009", "referenceImage": "gltfTextureLinearInterpolation.png" }, + { + "title": "GLTF Node visibility test", + "playgroundId": "#80DN99#3", + "referenceImage": "gltfNodeVisibility.png" + }, { "title": "Asset Containers", "playgroundId": "#P3U079#19",