| { | { | ||||
| "name": "threepipe", | "name": "threepipe", | ||||
| "version": "0.0.35-dev", | |||||
| "version": "0.0.35", | |||||
| "lockfileVersion": 3, | "lockfileVersion": 3, | ||||
| "requires": true, | "requires": true, | ||||
| "packages": { | "packages": { | ||||
| "": { | "": { | ||||
| "name": "threepipe", | "name": "threepipe", | ||||
| "version": "0.0.35-dev", | |||||
| "version": "0.0.35", | |||||
| "license": "Apache-2.0", | "license": "Apache-2.0", | ||||
| "dependencies": { | "dependencies": { | ||||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz", | "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz", |
| { | { | ||||
| "name": "threepipe", | "name": "threepipe", | ||||
| "version": "0.0.35-dev", | |||||
| "version": "0.0.35", | |||||
| "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", | "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", | ||||
| "main": "dist/index.js", | "main": "dist/index.js", | ||||
| "module": "dist/index.mjs", | "module": "dist/index.mjs", |
| import { | import { | ||||
| AssetExporterPlugin, | AssetExporterPlugin, | ||||
| AViewerPluginSync, | AViewerPluginSync, | ||||
| ClearcoatTintPlugin, | |||||
| CustomBumpMapPlugin, | |||||
| DRACOLoader2, | DRACOLoader2, | ||||
| generateUUID, | generateUUID, | ||||
| GLTFLightExtrasExtension, | GLTFLightExtrasExtension, | ||||
| GLTFMaterialsDisplacementMapExtension, | GLTFMaterialsDisplacementMapExtension, | ||||
| GLTFMaterialsLightMapExtension, | GLTFMaterialsLightMapExtension, | ||||
| GLTFObject3DExtrasExtension, | GLTFObject3DExtrasExtension, | ||||
| NoiseBumpMaterialPlugin, | |||||
| IExporter, | |||||
| ThreeViewer, | ThreeViewer, | ||||
| clearCoatTintGLTFExtension, | |||||
| customBumpMapGLTFExtension, | |||||
| noiseBumpMaterialGLTFExtension, | |||||
| fragmentClippingGLTFExtension, | |||||
| } from 'threepipe' | } from 'threepipe' | ||||
| import {GLTFDracoExporter} from './GLTFDracoExporter' | import {GLTFDracoExporter} from './GLTFDracoExporter' | ||||
| import {UiObjectConfig} from 'uiconfig.js' | import {UiObjectConfig} from 'uiconfig.js' | ||||
| public static readonly PluginType = 'GLTFDracoExportPlugin' | public static readonly PluginType = 'GLTFDracoExportPlugin' | ||||
| enabled = true | enabled = true | ||||
| /** | |||||
| * These are added here, but also added as plugins. Added here by default so that the data is not lost if some plugin is not added in an app. | |||||
| * To explicitly remove the data, use `removeExtension` with the name of the extension | |||||
| */ | |||||
| extraExtensions = [ | |||||
| [GLTFMaterialsBumpMapExtension.WebGiMaterialsBumpMapExtension, GLTFMaterialsBumpMapExtension.Textures], | |||||
| [GLTFMaterialsLightMapExtension.WebGiMaterialsLightMapExtension, GLTFMaterialsLightMapExtension.Textures], | |||||
| [GLTFMaterialsAlphaMapExtension.WebGiMaterialsAlphaMapExtension, GLTFMaterialsAlphaMapExtension.Textures], | |||||
| [GLTFMaterialsDisplacementMapExtension.WebGiMaterialsDisplacementMapExtension, GLTFMaterialsDisplacementMapExtension.Textures], | |||||
| [customBumpMapGLTFExtension.name, customBumpMapGLTFExtension.textures], | |||||
| [GLTFLightExtrasExtension.WebGiLightExtrasExtension, GLTFLightExtrasExtension.Textures], | |||||
| [GLTFObject3DExtrasExtension.WebGiObject3DExtrasExtension, GLTFObject3DExtrasExtension.Textures], | |||||
| [GLTFMaterialExtrasExtension.WebGiMaterialExtrasExtension, GLTFMaterialExtrasExtension.Textures], | |||||
| [clearCoatTintGLTFExtension.name, clearCoatTintGLTFExtension.textures], | |||||
| [noiseBumpMaterialGLTFExtension.name, noiseBumpMaterialGLTFExtension.textures], | |||||
| [fragmentClippingGLTFExtension.name, fragmentClippingGLTFExtension.textures], | |||||
| // extenal plugins | |||||
| // AnisotropyMaterialExtension | |||||
| ['WEBGI_materials_anisotropy', { | |||||
| anisotropyDirection: 'RGB', | |||||
| }], | |||||
| // todo port | |||||
| // DiamondMaterialExtension | |||||
| // AnimationMarkersExtension | |||||
| // ThinFilmLayerMaterialExtension | |||||
| // TriplanarMappingMaterialExtension | |||||
| // SSBevelMaterialExtension | |||||
| ] as [string, Record<string, string|number>|undefined][] | |||||
| addExtension(name: string, textures?: Record<string, string|number>) { | |||||
| const ext = this.extraExtensions.findIndex(e => e[0] === name) | |||||
| if (ext >= 0) this.extraExtensions[ext] = [name, textures] | |||||
| else this.extraExtensions.push([name, textures]) | |||||
| } | |||||
| /** | |||||
| * Note - don't remove an extension when removing a plugin. | |||||
| * | |||||
| * extensions can be removed if you don't want to save the data of some plugin when transforming glb. But since this is not desirable in most cases, it is not recommended. | |||||
| * @param name | |||||
| */ | |||||
| removeExtension(name: string) { | |||||
| const ext = this.extraExtensions.findIndex(e => e[0] === name) | |||||
| if (ext >= 0) this.extraExtensions.splice(ext, 1) | |||||
| } | |||||
| private _lastExporter?: IExporter['ctor'] = undefined | |||||
| protected _ctor: IExporter['ctor'] = (_, _exporter) => { | |||||
| if (!this._viewer) throw new Error('Viewer not set') | |||||
| const tempFile = generateUUID() + '.drc' // dummy | |||||
| const ex = new GLTFDracoExporter({}, | |||||
| // todo unregister on dispose | |||||
| this._viewer.assetManager.importer.registerFile(tempFile) as DRACOLoader2) | |||||
| ex.setup(this._viewer, _exporter.extensions) | |||||
| for (const [ext, config] of this.extraExtensions) { | |||||
| ex.createAndAddExtension(ext, config) | |||||
| } | |||||
| return ex | |||||
| } | |||||
| onAdded(viewer: ThreeViewer): void { | onAdded(viewer: ThreeViewer): void { | ||||
| super.onAdded(viewer) | super.onAdded(viewer) | ||||
| const importer = viewer.assetManager.importer | |||||
| const exporter = viewer.assetManager.exporter | const exporter = viewer.assetManager.exporter | ||||
| const glbExporter = exporter.getExporter('glb') | |||||
| if (glbExporter) exporter.removeExporter(glbExporter) | |||||
| // todo remove exporter and add back the old one on plugin remove. | |||||
| exporter.addExporter({ | |||||
| ...glbExporter || { | |||||
| let glbExporter = exporter.getExporter('glb') | |||||
| this._lastExporter = glbExporter?.ctor | |||||
| if (!glbExporter) { | |||||
| console.error('GLTFDracoExportPlugin: GLB exporter not found in AssetManager.exporter, creating a new one.') | |||||
| glbExporter = { | |||||
| ext: ['glb', 'gltf'], | ext: ['glb', 'gltf'], | ||||
| extensions: [], | extensions: [], | ||||
| }, // for extensions | |||||
| ctor: (_, _exporter) => { | |||||
| const tempFile = generateUUID() + '.drc' // dummy | |||||
| const ex = new GLTFDracoExporter({}, | |||||
| // todo unregister on dispose | |||||
| importer.registerFile(tempFile) as DRACOLoader2) | |||||
| ex.setup(viewer, _exporter.extensions) | |||||
| ex.createAndAddExtension(GLTFMaterialsBumpMapExtension.WebGiMaterialsBumpMapExtension, { | |||||
| bumpTexture: 'R', | |||||
| }) | |||||
| ex.createAndAddExtension(GLTFMaterialsLightMapExtension.WebGiMaterialsLightMapExtension, { | |||||
| lightMapTexture: 'RGB', | |||||
| }) | |||||
| ex.createAndAddExtension(GLTFMaterialsAlphaMapExtension.WebGiMaterialsAlphaMapExtension, { | |||||
| alphaTexture: 'G', | |||||
| }) | |||||
| ex.createAndAddExtension(GLTFMaterialsDisplacementMapExtension.WebGiMaterialsDisplacementMapExtension, { | |||||
| displacementTexture: 'R', | |||||
| }) | |||||
| ex.createAndAddExtension(CustomBumpMapPlugin.CUSTOM_BUMP_MAP_GLTF_EXTENSION, { | |||||
| customBumpMap: 'RGB', | |||||
| }) | |||||
| ex.createAndAddExtension(GLTFLightExtrasExtension.WebGiLightExtrasExtension) | |||||
| ex.createAndAddExtension(GLTFObject3DExtrasExtension.WebGiObject3DExtrasExtension) | |||||
| ex.createAndAddExtension(GLTFMaterialExtrasExtension.WebGiMaterialExtrasExtension) | |||||
| ex.createAndAddExtension(ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION) | |||||
| ex.createAndAddExtension(NoiseBumpMaterialPlugin.NOISE_BUMP_MATERIAL_GLTF_EXTENSION) | |||||
| // todo port | |||||
| // DiamondMaterialExtension | |||||
| // AnimationMarkersExtension | |||||
| // AnisotropyMaterialExtension | |||||
| // ThinFilmLayerMaterialExtension | |||||
| // TriplanarMappingMaterialExtension | |||||
| // SSBevelMaterialExtension | |||||
| return ex | |||||
| }, | |||||
| }) | |||||
| ctor: this._ctor, | |||||
| } | |||||
| exporter.addExporter(glbExporter) | |||||
| } else { | |||||
| glbExporter.ctor = this._ctor | |||||
| } | |||||
| // for ui | |||||
| // for ui. todo use viewer.forPlugin | |||||
| const exportPlugin = viewer.getPlugin(AssetExporterPlugin) | const exportPlugin = viewer.getPlugin(AssetExporterPlugin) | ||||
| if (exportPlugin) { | if (exportPlugin) { | ||||
| Object.assign(exportPlugin.exportOptions, { | Object.assign(exportPlugin.exportOptions, { | ||||
| } | } | ||||
| } | } | ||||
| onRemove(viewer: ThreeViewer) { | |||||
| const exporter = viewer.assetManager.exporter | |||||
| const glbExporter = exporter.getExporter('glb') | |||||
| if (glbExporter && this._lastExporter) { | |||||
| glbExporter.ctor = this._lastExporter | |||||
| } | |||||
| super.onRemove(viewer) | |||||
| } | |||||
| protected _makeUi = (exporter: AssetExporterPlugin)=>[ | protected _makeUi = (exporter: AssetExporterPlugin)=>[ | ||||
| { | { | ||||
| type: 'checkbox', | type: 'checkbox', |
| import {ILoader} from './IImporter' | import {ILoader} from './IImporter' | ||||
| import {AssetExporter} from './AssetExporter' | import {AssetExporter} from './AssetExporter' | ||||
| import {IExporter} from './IExporter' | import {IExporter} from './IExporter' | ||||
| import {GLTFExporter2} from './export' | |||||
| import {GLTFExporter2, GLTFWriter2} from './export' | |||||
| import {legacySeparateMapSamplerUVFix} from '../utils/legacy' | import {legacySeparateMapSamplerUVFix} from '../utils/legacy' | ||||
| import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | |||||
| import {GLTFExporterPlugin} from 'three/examples/jsm/exporters/GLTFExporter' | |||||
| export interface AssetManagerOptions{ | export interface AssetManagerOptions{ | ||||
| /** | /** | ||||
| this._sceneUpdated = this._sceneUpdated.bind(this) | this._sceneUpdated = this._sceneUpdated.bind(this) | ||||
| this.addAsset = this.addAsset.bind(this) | this.addAsset = this.addAsset.bind(this) | ||||
| this.addRaw = this.addRaw.bind(this) | this.addRaw = this.addRaw.bind(this) | ||||
| this._loaderCreate = this._loaderCreate.bind(this) | |||||
| this.addImported = this.addImported.bind(this) | this.addImported = this.addImported.bind(this) | ||||
| this.importer = new AssetImporter(!!viewer.getPlugin('debug')) | this.importer = new AssetImporter(!!viewer.getPlugin('debug')) | ||||
| this.viewer.scene.addEventListener('beforeDeserialize', this._sceneUpdated) | this.viewer.scene.addEventListener('beforeDeserialize', this._sceneUpdated) | ||||
| this._initCacheStorage(simpleCache, storage ?? true) | this._initCacheStorage(simpleCache, storage ?? true) | ||||
| this._setupGltfExtensions() | |||||
| this._setupObjectProcess() | this._setupObjectProcess() | ||||
| this._setupProcessState() | this._setupProcessState() | ||||
| this._addImporters() | this._addImporters() | ||||
| } | } | ||||
| private _gltfExporter = { | |||||
| ext: ['gltf', 'glb'], | |||||
| extensions: [] as (typeof GLTFExporter2.ExportExtensions)[number][], | |||||
| ctor: (_, exporter) => { | |||||
| const ex = new GLTFExporter2() | |||||
| // This should be added at the end. | |||||
| ex.setup(this.viewer, exporter.extensions) | |||||
| return ex | |||||
| }, | |||||
| } satisfies IExporter | |||||
| protected _addExporters() { | protected _addExporters() { | ||||
| const exporters: IExporter[] = [ | |||||
| { | |||||
| ext: ['gltf', 'glb'], extensions: [], ctor: (_, exporter) => { | |||||
| const ex = new GLTFExporter2() | |||||
| // This should be added at the end. | |||||
| ex.setup(this.viewer, exporter.extensions) | |||||
| return ex | |||||
| }, | |||||
| }, | |||||
| ] | |||||
| const exporters: IExporter[] = [this._gltfExporter] | |||||
| this.exporter.addExporter(...exporters) | this.exporter.addExporter(...exporters) | ||||
| } | } | ||||
| }) | }) | ||||
| } | } | ||||
| // region glTF extensions registration helpers | |||||
| gltfExtensions: { | |||||
| name: string | |||||
| import: (parser: GLTFParser) => GLTFLoaderPlugin, | |||||
| export: (parser: GLTFWriter2) => GLTFExporterPlugin, | |||||
| textures?: Record<string, string|number> // see GLTFDracoExportPlugin | |||||
| }[] = [] | |||||
| protected _setupGltfExtensions() { | |||||
| this.importer.addEventListener('loaderCreate', this._loaderCreate as any) | |||||
| this.viewer.forPlugin('GLTFDracoExportPlugin', (p)=> { | |||||
| if (!p.addExtension) return | |||||
| for (const gltfExtension of this.gltfExtensions) { | |||||
| p.addExtension(gltfExtension.name, gltfExtension.textures) | |||||
| } | |||||
| }) | |||||
| } | |||||
| protected _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||||
| if (!loader.isGLTFLoader2) return | |||||
| for (const gltfExtension of this.gltfExtensions) { | |||||
| loader.register(gltfExtension.import) | |||||
| } | |||||
| } | |||||
| registerGltfExtension(ext: AssetManager['gltfExtensions'][number]) { | |||||
| const ext1 = this.gltfExtensions.findIndex(e => e.name === ext.name) | |||||
| if (ext1 >= 0) this.gltfExtensions.splice(ext1, 1) | |||||
| this.gltfExtensions.push(ext) | |||||
| this._gltfExporter.extensions.push(ext.export) | |||||
| const exporter2 = this.exporter.getExporter('gltf', 'glb') | |||||
| if (exporter2 && exporter2 !== this._gltfExporter) | |||||
| exporter2.extensions?.push(ext.export) | |||||
| } | |||||
| unregisterGltfExtension(name: string) { | |||||
| const ind = this.gltfExtensions.findIndex(e => e.name === name) | |||||
| if (ind < 0) return | |||||
| this.gltfExtensions.splice(ind, 1) | |||||
| const ind1 = this._gltfExporter.extensions.findIndex(e => e.name === name) | |||||
| if (ind1 >= 0) this._gltfExporter.extensions.splice(ind1, 1) | |||||
| const exporter2 = this.exporter.getExporter('gltf', 'glb') | |||||
| if (exporter2?.extensions && exporter2 !== this._gltfExporter) { | |||||
| const ind2 = exporter2.extensions.findIndex(e => e.name === name) | |||||
| if (ind2 >= 0) exporter2.extensions?.splice(ind2, 1) | |||||
| } | |||||
| } | |||||
| // endregion | |||||
| // region deprecated | // region deprecated | ||||
| } | } | ||||
| }, | }, | ||||
| }) | }) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number>|undefined = undefined | |||||
| } | } |
| // console.log(w) | // console.log(w) | ||||
| }, | }, | ||||
| }) | }) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number>|undefined = undefined | |||||
| } | } |
| static readonly WebGiMaterialsAlphaMapExtension = 'WEBGI_materials_alphamap' | static readonly WebGiMaterialsAlphaMapExtension = 'WEBGI_materials_alphamap' | ||||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsAlphaMapExtensionImport(parser) | static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsAlphaMapExtensionImport(parser) | ||||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsAlphaMapExtensionExport(writer) | static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsAlphaMapExtensionExport(writer) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number> = { | |||||
| alphaTexture: 'G', | |||||
| } | |||||
| } | } | ||||
| class GLTFMaterialsAlphaMapExtensionImport { | class GLTFMaterialsAlphaMapExtensionImport { |
| static readonly WebGiMaterialsBumpMapExtension = 'WEBGI_materials_bumpmap' | static readonly WebGiMaterialsBumpMapExtension = 'WEBGI_materials_bumpmap' | ||||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsBumpMapExtensionImport(parser) | static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsBumpMapExtensionImport(parser) | ||||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsBumpMapExtensionExport(writer) | static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsBumpMapExtensionExport(writer) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number> = { | |||||
| bumpTexture: 'R', | |||||
| } | |||||
| } | } | ||||
| class GLTFMaterialsBumpMapExtensionImport { | class GLTFMaterialsBumpMapExtensionImport { |
| static readonly WebGiMaterialsDisplacementMapExtension = 'WEBGI_materials_displacementmap' | static readonly WebGiMaterialsDisplacementMapExtension = 'WEBGI_materials_displacementmap' | ||||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsDisplacementMapExtensionImport(parser) | static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsDisplacementMapExtensionImport(parser) | ||||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsDisplacementMapExtensionExport(writer) | static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsDisplacementMapExtensionExport(writer) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number> = { | |||||
| displacementTexture: 'R', | |||||
| } | |||||
| } | } | ||||
| class GLTFMaterialsDisplacementMapExtensionImport { | class GLTFMaterialsDisplacementMapExtensionImport { |
| static readonly WebGiMaterialsLightMapExtension = 'WEBGI_materials_lightmap' | static readonly WebGiMaterialsLightMapExtension = 'WEBGI_materials_lightmap' | ||||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsLightMapExtensionImport(parser) | static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsLightMapExtensionImport(parser) | ||||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsLightMapExtensionExport(writer) | static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsLightMapExtensionExport(writer) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number> = { | |||||
| lightMapTexture: 'RGB', | |||||
| } | |||||
| } | } | ||||
| class GLTFMaterialsLightMapExtensionImport { | class GLTFMaterialsLightMapExtensionImport { |
| } | } | ||||
| }, | }, | ||||
| }) | }) | ||||
| // see GLTFDracoExportPlugin | |||||
| static Textures: Record<string, string|number>|undefined = undefined | |||||
| } | } |
| @uiColor('Color', (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | @uiColor('Color', (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | ||||
| declare color: Color | declare color: Color | ||||
| @uiSlider('Intensity', [0, 30], 0.01) | |||||
| @uiSlider('Intensity', [0, 100], 0.01) | |||||
| @onChange3('setDirty') | @onChange3('setDirty') | ||||
| declare intensity: number | declare intensity: number | ||||
| @uiVector('Position', undefined, undefined, (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | @uiVector('Position', undefined, undefined, (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) |
| import {AViewerPluginSync, ThreeViewer} from '../../viewer' | import {AViewerPluginSync, ThreeViewer} from '../../viewer' | ||||
| import {GLTFLoader2} from '../../assetmanager' | |||||
| import {AssetManager} from '../../assetmanager' | |||||
| import {onChange, serialize} from 'ts-browser-helpers' | import {onChange, serialize} from 'ts-browser-helpers' | ||||
| import {IMaterial, IObject3D} from '../../core' | import {IMaterial, IObject3D} from '../../core' | ||||
| import {UiObjectConfig} from 'uiconfig.js' | import {UiObjectConfig} from 'uiconfig.js' | ||||
| constructor() { | constructor() { | ||||
| super() | super() | ||||
| this._loaderCreate = this._loaderCreate.bind(this) | |||||
| } | } | ||||
| onAdded(v: ThreeViewer): void { | onAdded(v: ThreeViewer): void { | ||||
| super.onAdded(v) | super.onAdded(v) | ||||
| // v.addEventListener('preRender', this._preRender) | // v.addEventListener('preRender', this._preRender) | ||||
| v.scene.addEventListener('addSceneObject', this._objectAdded) | v.scene.addEventListener('addSceneObject', this._objectAdded) | ||||
| v.assetManager.importer.addEventListener('loaderCreate', this._loaderCreate as any) | |||||
| v.assetManager.exporter.getExporter('gltf', 'glb')?.extensions?.push(gltfExporterMaterialsVariantsExtensionExport) | |||||
| } | |||||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||||
| if (!loader.isGLTFLoader2) return | |||||
| loader.register((p) => new GLTFMaterialsVariantsExtensionImport(p)) | |||||
| v.assetManager.registerGltfExtension(khrMaterialVariantsGLTFExtension) | |||||
| } | } | ||||
| onRemove(v: ThreeViewer): void { | onRemove(v: ThreeViewer): void { | ||||
| v.scene.removeEventListener('addSceneObject', this._objectAdded) | v.scene.removeEventListener('addSceneObject', this._objectAdded) | ||||
| v.assetManager.importer.removeEventListener('loaderCreate', this._loaderCreate as any) | |||||
| const exportExts = v.assetManager.exporter.getExporter('gltf', 'glb')?.extensions || [] | |||||
| const i = exportExts.indexOf(gltfExporterMaterialsVariantsExtensionExport) | |||||
| if (i !== -1) exportExts.splice(i, 1) | |||||
| v.assetManager.unregisterGltfExtension(khrMaterialVariantsGLTFExtension.name) | |||||
| this.variants = {} | this.variants = {} | ||||
| return super.onRemove(v) | return super.onRemove(v) | ||||
| } | } | ||||
| _originalMaterial?: IObject3D['material'] | _originalMaterial?: IObject3D['material'] | ||||
| } | } | ||||
| } | } | ||||
| export const khrMaterialVariantsGLTFExtension = { | |||||
| name: khrMaterialsVariantsGLTF, | |||||
| import: (p) => new GLTFMaterialsVariantsExtensionImport(p), | |||||
| export: gltfExporterMaterialsVariantsExtensionExport, | |||||
| // textures: undefined, | |||||
| } satisfies AssetManager['gltfExtensions'][number] |
| export {CameraViewPlugin, type CameraViewPluginOptions} from './animation/CameraViewPlugin' | export {CameraViewPlugin, type CameraViewPluginOptions} from './animation/CameraViewPlugin' | ||||
| // material | // material | ||||
| export {ClearcoatTintPlugin} from './material/ClearcoatTintPlugin' | |||||
| export {NoiseBumpMaterialPlugin} from './material/NoiseBumpMaterialPlugin' | |||||
| export {CustomBumpMapPlugin} from './material/CustomBumpMapPlugin' | |||||
| export {ClearcoatTintPlugin, clearCoatTintGLTFExtension} from './material/ClearcoatTintPlugin' | |||||
| export {NoiseBumpMaterialPlugin, noiseBumpMaterialGLTFExtension} from './material/NoiseBumpMaterialPlugin' | |||||
| export {CustomBumpMapPlugin, customBumpMapGLTFExtension} from './material/CustomBumpMapPlugin' | |||||
| export {ParallaxMappingPlugin} from './material/ParallaxMappingPlugin' | export {ParallaxMappingPlugin} from './material/ParallaxMappingPlugin' | ||||
| export {FragmentClippingExtensionPlugin, FragmentClippingMode} from './material/FragmentClippingExtensionPlugin' | |||||
| export {FragmentClippingExtensionPlugin, FragmentClippingMode, fragmentClippingGLTFExtension} from './material/FragmentClippingExtensionPlugin' | |||||
| // rendering | // rendering | ||||
| export {VirtualCamerasPlugin, type VirtualCamera} from './rendering/VirtualCamerasPlugin' | export {VirtualCamerasPlugin, type VirtualCamera} from './rendering/VirtualCamerasPlugin' |
| import {IMaterialUserData, PhysicalMaterial} from '../../core' | import {IMaterialUserData, PhysicalMaterial} from '../../core' | ||||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | import {MaterialExtension, updateMaterialDefines} from '../../materials' | ||||
| import {shaderReplaceString, ThreeSerialization} from '../../utils' | import {shaderReplaceString, ThreeSerialization} from '../../utils' | ||||
| import {GLTFLoader2, GLTFWriter2} from '../../assetmanager' | |||||
| import {AssetManager, GLTFWriter2} from '../../assetmanager' | |||||
| import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | ||||
| /** | /** | ||||
| this._viewer?.setDirty() | this._viewer?.setDirty() | ||||
| } | } | ||||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||||
| if (!loader.isGLTFLoader2) return | |||||
| loader.register((p) => new GLTFMaterialsClearcoatTintExtensionImport(p)) | |||||
| } | |||||
| constructor() { | constructor() { | ||||
| super() | super() | ||||
| this._loaderCreate = this._loaderCreate.bind(this) | |||||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | ||||
| } | } | ||||
| onAdded(v: ThreeViewer) { | onAdded(v: ThreeViewer) { | ||||
| super.onAdded(v) | super.onAdded(v) | ||||
| // v.addEventListener('preRender', this._preRender) | |||||
| v.assetManager.materials.registerMaterialExtension(this.materialExtension) | v.assetManager.materials.registerMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer.addEventListener('loaderCreate', this._loaderCreate as any) | |||||
| v.assetManager.exporter.getExporter('gltf', 'glb')?.extensions?.push(glTFMaterialsClearcoatTintExtensionExport) | |||||
| v.assetManager.registerGltfExtension(clearCoatTintGLTFExtension) | |||||
| } | } | ||||
| onRemove(v: ThreeViewer) { | onRemove(v: ThreeViewer) { | ||||
| v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer?.removeEventListener('loaderCreate', this._loaderCreate as any) | |||||
| const exporter = v.assetManager.exporter.getExporter('gltf', 'glb') | |||||
| if (exporter) { | |||||
| const index = exporter.extensions?.indexOf(glTFMaterialsClearcoatTintExtensionExport) | |||||
| if (index !== undefined && index >= 0) exporter.extensions?.splice(index, 1) | |||||
| } | |||||
| v.assetManager.unregisterGltfExtension(clearCoatTintGLTFExtension.name) | |||||
| return super.onRemove(v) | return super.onRemove(v) | ||||
| } | } | ||||
| /** | |||||
| * @deprecated - use {@link clearCoatTintGLTFExtension} | |||||
| */ | |||||
| public static readonly CLEARCOAT_TINT_GLTF_EXTENSION = 'WEBGI_materials_clearcoat_tint' | public static readonly CLEARCOAT_TINT_GLTF_EXTENSION = 'WEBGI_materials_clearcoat_tint' | ||||
| } | } | ||||
| /** | /** | ||||
| * ClearcoatTint Materials Extension | * ClearcoatTint Materials Extension | ||||
| * | * | ||||
| * Specification: https://webgi.xyz/docs/gltf-extensions/WEBGI_materials_clearcoat_tint.html | |||||
| * Specification: https://webgi.xyz/docs/gltf-extensions/WEBGI_materials_clearcoat_tint.html (todo - fix link) | |||||
| */ | */ | ||||
| class GLTFMaterialsClearcoatTintExtensionImport implements GLTFLoaderPlugin { | class GLTFMaterialsClearcoatTintExtensionImport implements GLTFLoaderPlugin { | ||||
| public name: string | public name: string | ||||
| constructor(parser: GLTFParser) { | constructor(parser: GLTFParser) { | ||||
| this.parser = parser | this.parser = parser | ||||
| this.name = ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION | |||||
| this.name = clearCoatTintGLTFExtension.name | |||||
| } | } | ||||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | async extendMaterialParams(materialIndex: number, materialParams: any) { | ||||
| const extensionDef: any = ThreeSerialization.Serialize(material.userData._clearcoatTint) | const extensionDef: any = ThreeSerialization.Serialize(material.userData._clearcoatTint) | ||||
| materialDef.extensions[ ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION ] = extensionDef | |||||
| w.extensionsUsed[ ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION ] = true | |||||
| materialDef.extensions[ clearCoatTintGLTFExtension.name ] = extensionDef | |||||
| w.extensionsUsed[ clearCoatTintGLTFExtension.name ] = true | |||||
| }, | }, | ||||
| }) | }) | ||||
| export const clearCoatTintGLTFExtension = { | |||||
| name: 'WEBGI_materials_clearcoat_tint', | |||||
| import: (p) => new GLTFMaterialsClearcoatTintExtensionImport(p), | |||||
| export: glTFMaterialsClearcoatTintExtensionExport, | |||||
| textures: undefined, | |||||
| } satisfies AssetManager['gltfExtensions'][number] |
| import {IMaterial, IObject3D, ITexture, PhysicalMaterial} from '../../core' | import {IMaterial, IObject3D, ITexture, PhysicalMaterial} from '../../core' | ||||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | import {MaterialExtension, updateMaterialDefines} from '../../materials' | ||||
| import {shaderReplaceString} from '../../utils' | import {shaderReplaceString} from '../../utils' | ||||
| import {GLTFLoader2, GLTFWriter2} from '../../assetmanager' | |||||
| import {AssetManager, GLTFWriter2} from '../../assetmanager' | |||||
| import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | ||||
| import CustomBumpMapPluginShader from './shaders/CustomBumpMapPlugin.glsl' | import CustomBumpMapPluginShader from './shaders/CustomBumpMapPlugin.glsl' | ||||
| import {matDefine} from '../../three' | import {matDefine} from '../../three' | ||||
| if (v === state._hasCustomBump) return | if (v === state._hasCustomBump) return | ||||
| if (v) { | if (v) { | ||||
| if (!enableCustomBump(material)) | if (!enableCustomBump(material)) | ||||
| viewer.dialog.alert('Cannot add CustomBumpMap.') | |||||
| viewer.dialog.alert('CustomBumpMapPlugin - Cannot add CustomBumpMap.') | |||||
| } else { | } else { | ||||
| state._hasCustomBump = false | state._hasCustomBump = false | ||||
| if (material.setDirty) material.setDirty() | if (material.setDirty) material.setDirty() | ||||
| bounds: [-1, 1], | bounds: [-1, 1], | ||||
| hidden: () => !state._hasCustomBump, | hidden: () => !state._hasCustomBump, | ||||
| property: [state, '_customBumpScale'], | property: [state, '_customBumpScale'], | ||||
| onChange: this.setDirty, | |||||
| // onChange: this.setDirty, | |||||
| }, | }, | ||||
| { | { | ||||
| type: 'image', | type: 'image', | ||||
| hidden: () => !state._hasCustomBump, | hidden: () => !state._hasCustomBump, | ||||
| property: [state, '_customBumpMap'], | property: [state, '_customBumpMap'], | ||||
| onChange: ()=>{ | onChange: ()=>{ | ||||
| material.setDirty() | |||||
| if (material.setDirty) material.setDirty() | |||||
| }, | }, | ||||
| }, | }, | ||||
| makeSamplerUi(state as any, '_customBumpMap'), | |||||
| makeSamplerUi(state as any, '_customBumpMap', 'Sampler', ()=>!state._hasCustomBump, ()=>material.setDirty && material.setDirty()), | |||||
| ], | ], | ||||
| } | } | ||||
| return config | return config | ||||
| this._viewer?.setDirty() | this._viewer?.setDirty() | ||||
| } | } | ||||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||||
| if (!loader.isGLTFLoader2) return | |||||
| loader.register((p) => new GLTFMaterialsCustomBumpMapImport(p)) | |||||
| } | |||||
| constructor() { | constructor() { | ||||
| super() | super() | ||||
| this._loaderCreate = this._loaderCreate.bind(this) | |||||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | ||||
| } | } | ||||
| super.onAdded(v) | super.onAdded(v) | ||||
| // v.addEventListener('preRender', this._preRender) | // v.addEventListener('preRender', this._preRender) | ||||
| v.assetManager.materials.registerMaterialExtension(this.materialExtension) | v.assetManager.materials.registerMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer.addEventListener('loaderCreate', this._loaderCreate as any) | |||||
| v.assetManager.exporter.getExporter('gltf', 'glb')?.extensions?.push(glTFMaterialsCustomBumpMapExport) | |||||
| v.assetManager.registerGltfExtension(customBumpMapGLTFExtension) | |||||
| // v.getPlugin(GBufferPlugin)?.material?.registerMaterialExtensions([this.materialExtension]) | // v.getPlugin(GBufferPlugin)?.material?.registerMaterialExtensions([this.materialExtension]) | ||||
| } | } | ||||
| onRemove(v: ThreeViewer) { | onRemove(v: ThreeViewer) { | ||||
| v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer?.removeEventListener('loaderCreate', this._loaderCreate as any) | |||||
| const exporter = v.assetManager.exporter.getExporter('gltf', 'glb') | |||||
| if (exporter) { | |||||
| const index = exporter.extensions?.indexOf(glTFMaterialsCustomBumpMapExport) | |||||
| if (index !== undefined && index >= 0) exporter.extensions?.splice(index, 1) | |||||
| } | |||||
| v.assetManager.unregisterGltfExtension(customBumpMapGLTFExtension.name) | |||||
| // v.getPlugin(GBufferPlugin)?.material?.unregisterMaterialExtensions([this.materialExtension]) | // v.getPlugin(GBufferPlugin)?.material?.unregisterMaterialExtensions([this.materialExtension]) | ||||
| return super.onRemove(v) | return super.onRemove(v) | ||||
| } | } | ||||
| /** | |||||
| * @deprecated use {@link customBumpMapGLTFExtension} | |||||
| */ | |||||
| public static readonly CUSTOM_BUMP_MAP_GLTF_EXTENSION = 'WEBGI_materials_custom_bump_map' | public static readonly CUSTOM_BUMP_MAP_GLTF_EXTENSION = 'WEBGI_materials_custom_bump_map' | ||||
| } | } | ||||
| constructor(parser: GLTFParser) { | constructor(parser: GLTFParser) { | ||||
| this.parser = parser | this.parser = parser | ||||
| this.name = CustomBumpMapPlugin.CUSTOM_BUMP_MAP_GLTF_EXTENSION | |||||
| this.name = customBumpMapGLTFExtension.name | |||||
| } | } | ||||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | async extendMaterialParams(materialIndex: number, materialParams: any) { | ||||
| } | } | ||||
| materialDef.extensions[ CustomBumpMapPlugin.CUSTOM_BUMP_MAP_GLTF_EXTENSION ] = extensionDef | |||||
| w.extensionsUsed[ CustomBumpMapPlugin.CUSTOM_BUMP_MAP_GLTF_EXTENSION ] = true | |||||
| materialDef.extensions[ customBumpMapGLTFExtension.name ] = extensionDef | |||||
| w.extensionsUsed[ customBumpMapGLTFExtension.name ] = true | |||||
| }, | }, | ||||
| }) | }) | ||||
| export const customBumpMapGLTFExtension = { | |||||
| name: 'WEBGI_materials_custom_bump_map', | |||||
| import: (p) => new GLTFMaterialsCustomBumpMapImport(p), | |||||
| export: glTFMaterialsCustomBumpMapExport, | |||||
| textures: { | |||||
| customBumpMap: 'RGB', | |||||
| }, | |||||
| } satisfies AssetManager['gltfExtensions'][number] |
| import {IMaterial, IMaterialUserData, IObject3D, PhysicalMaterial} from '../../core' | import {IMaterial, IMaterialUserData, IObject3D, PhysicalMaterial} from '../../core' | ||||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | import {MaterialExtension, updateMaterialDefines} from '../../materials' | ||||
| import {shaderReplaceString, ThreeSerialization} from '../../utils' | import {shaderReplaceString, ThreeSerialization} from '../../utils' | ||||
| import {GLTFLoader2, GLTFWriter2} from '../../assetmanager' | |||||
| import {AssetManager, GLTFWriter2} from '../../assetmanager' | |||||
| import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | ||||
| import FragmentClippingExtensionPluginPars from './shaders/FragmentClippingExtensionPlugin.pars.glsl' | import FragmentClippingExtensionPluginPars from './shaders/FragmentClippingExtensionPlugin.pars.glsl' | ||||
| import FragmentClippingExtensionPluginPatch from './shaders/FragmentClippingExtensionPlugin.patch.glsl' | import FragmentClippingExtensionPluginPatch from './shaders/FragmentClippingExtensionPlugin.patch.glsl' | ||||
| this._viewer?.setDirty() | this._viewer?.setDirty() | ||||
| } | } | ||||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||||
| if (!loader.isGLTFLoader2) return | |||||
| loader.register((p) => new GLTFMaterialsFragmentClippingExtensionImport(p)) | |||||
| } | |||||
| constructor() { | constructor() { | ||||
| super() | super() | ||||
| this._loaderCreate = this._loaderCreate.bind(this) | |||||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | ||||
| } | } | ||||
| super.onAdded(v) | super.onAdded(v) | ||||
| // v.addEventListener('preRender', this._preRender) | // v.addEventListener('preRender', this._preRender) | ||||
| v.assetManager.materials.registerMaterialExtension(this.materialExtension) | v.assetManager.materials.registerMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer.addEventListener('loaderCreate', this._loaderCreate as any) | |||||
| v.assetManager.exporter.getExporter('gltf', 'glb')?.extensions?.push(glTFMaterialsFragmentClippingExtensionExport) | |||||
| v.assetManager.registerGltfExtension(fragmentClippingGLTFExtension) | |||||
| // v.getPlugin(GBufferPlugin)?.material?.registerMaterialExtensions([this.materialExtension]) | // v.getPlugin(GBufferPlugin)?.material?.registerMaterialExtensions([this.materialExtension]) | ||||
| } | } | ||||
| onRemove(v: ThreeViewer) { | onRemove(v: ThreeViewer) { | ||||
| v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer?.removeEventListener('loaderCreate', this._loaderCreate as any) | |||||
| const exporter = v.assetManager.exporter.getExporter('gltf', 'glb') | |||||
| if (exporter) { | |||||
| const index = exporter.extensions?.indexOf(glTFMaterialsFragmentClippingExtensionExport) | |||||
| if (index !== undefined && index >= 0) exporter.extensions?.splice(index, 1) | |||||
| } | |||||
| v.assetManager.unregisterGltfExtension(fragmentClippingGLTFExtension.name) | |||||
| // v.getPlugin(GBufferPlugin)?.material?.unregisterMaterialExtensions([this.materialExtension]) | // v.getPlugin(GBufferPlugin)?.material?.unregisterMaterialExtensions([this.materialExtension]) | ||||
| return super.onRemove(v) | return super.onRemove(v) | ||||
| } | } | ||||
| /** | |||||
| * @deprecated use - use {@link fragmentClippingGLTFExtension} | |||||
| */ | |||||
| public static readonly FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION = 'WEBGI_materials_fragment_clipping_extension' | public static readonly FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION = 'WEBGI_materials_fragment_clipping_extension' | ||||
| } | } | ||||
| constructor(parser: GLTFParser) { | constructor(parser: GLTFParser) { | ||||
| this.parser = parser | this.parser = parser | ||||
| this.name = FragmentClippingExtensionPlugin.FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION | |||||
| this.name = fragmentClippingGLTFExtension.name | |||||
| } | } | ||||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | async extendMaterialParams(materialIndex: number, materialParams: any) { | ||||
| const extensionDef: any = ThreeSerialization.Serialize(material.userData._fragmentClippingExt) | const extensionDef: any = ThreeSerialization.Serialize(material.userData._fragmentClippingExt) | ||||
| materialDef.extensions[ FragmentClippingExtensionPlugin.FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION ] = extensionDef | |||||
| w.extensionsUsed[ FragmentClippingExtensionPlugin.FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION ] = true | |||||
| materialDef.extensions[ fragmentClippingGLTFExtension.name ] = extensionDef | |||||
| w.extensionsUsed[ fragmentClippingGLTFExtension.name ] = true | |||||
| }, | }, | ||||
| }) | }) | ||||
| export const fragmentClippingGLTFExtension = { | |||||
| name: 'WEBGI_materials_fragment_clipping', | |||||
| import: (p) => new GLTFMaterialsFragmentClippingExtensionImport(p), | |||||
| export: glTFMaterialsFragmentClippingExtensionExport, | |||||
| textures: undefined, | |||||
| } satisfies AssetManager['gltfExtensions'][number] |
| import {IMaterial, IMaterialUserData, IObject3D, PhysicalMaterial} from '../../core' | import {IMaterial, IMaterialUserData, IObject3D, PhysicalMaterial} from '../../core' | ||||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | import {MaterialExtension, updateMaterialDefines} from '../../materials' | ||||
| import {shaderReplaceString, ThreeSerialization} from '../../utils' | import {shaderReplaceString, ThreeSerialization} from '../../utils' | ||||
| import {GLTFLoader2, GLTFWriter2} from '../../assetmanager' | |||||
| import {AssetManager, GLTFWriter2} from '../../assetmanager' | |||||
| import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | import type {GLTFLoaderPlugin, GLTFParser} from 'three/examples/jsm/loaders/GLTFLoader' | ||||
| import NoiseBumpMaterialPluginPars from './shaders/NoiseBumpMaterialPlugin.pars.glsl' | import NoiseBumpMaterialPluginPars from './shaders/NoiseBumpMaterialPlugin.pars.glsl' | ||||
| import NoiseBumpMaterialPluginPatch from './shaders/NoiseBumpMaterialPlugin.patch.glsl' | import NoiseBumpMaterialPluginPatch from './shaders/NoiseBumpMaterialPlugin.patch.glsl' | ||||
| this._viewer?.setDirty() | this._viewer?.setDirty() | ||||
| } | } | ||||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||||
| if (!loader.isGLTFLoader2) return | |||||
| loader.register((p) => new GLTFMaterialsNoiseBumpMaterialImport(p)) | |||||
| } | |||||
| constructor() { | constructor() { | ||||
| super() | super() | ||||
| this._loaderCreate = this._loaderCreate.bind(this) | |||||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | ||||
| } | } | ||||
| onAdded(v: ThreeViewer) { | onAdded(v: ThreeViewer) { | ||||
| super.onAdded(v) | super.onAdded(v) | ||||
| v.assetManager.materials.registerMaterialExtension(this.materialExtension) | v.assetManager.materials.registerMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer.addEventListener('loaderCreate', this._loaderCreate as any) | |||||
| v.assetManager.exporter.getExporter('gltf', 'glb')?.extensions?.push(glTFMaterialsNoiseBumpMaterialExport) | |||||
| v.assetManager.registerGltfExtension(noiseBumpMaterialGLTFExtension) | |||||
| } | } | ||||
| onRemove(v: ThreeViewer) { | onRemove(v: ThreeViewer) { | ||||
| v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | v.assetManager.materials?.unregisterMaterialExtension(this.materialExtension) | ||||
| v.assetManager.importer?.removeEventListener('loaderCreate', this._loaderCreate as any) | |||||
| const exporter = v.assetManager.exporter.getExporter('gltf', 'glb') | |||||
| if (exporter) { | |||||
| const index = exporter.extensions?.indexOf(glTFMaterialsNoiseBumpMaterialExport) | |||||
| if (index !== undefined && index >= 0) exporter.extensions?.splice(index, 1) | |||||
| } | |||||
| v.assetManager.unregisterGltfExtension(noiseBumpMaterialGLTFExtension.name) | |||||
| return super.onRemove(v) | return super.onRemove(v) | ||||
| } | } | ||||
| /** | |||||
| * @deprecated - use {@link noiseBumpMaterialGLTFExtension} | |||||
| */ | |||||
| public static readonly NOISE_BUMP_MATERIAL_GLTF_EXTENSION = 'WEBGI_materials_noise_bump' | public static readonly NOISE_BUMP_MATERIAL_GLTF_EXTENSION = 'WEBGI_materials_noise_bump' | ||||
| } | } | ||||
| /** | /** | ||||
| * FragmentClipping Materials Extension | * FragmentClipping Materials Extension | ||||
| * | * | ||||
| * Specification: https://webgi.xyz/docs/gltf-extensions/WEBGI_materials_fragment_clipping_extension.html | |||||
| * Specification: https://webgi.xyz/docs/gltf-extensions/WEBGI_materials_fragment_clipping_extension.html (todo - fix link) | |||||
| */ | */ | ||||
| class GLTFMaterialsNoiseBumpMaterialImport implements GLTFLoaderPlugin { | class GLTFMaterialsNoiseBumpMaterialImport implements GLTFLoaderPlugin { | ||||
| public name: string | public name: string | ||||
| constructor(parser: GLTFParser) { | constructor(parser: GLTFParser) { | ||||
| this.parser = parser | this.parser = parser | ||||
| this.name = NoiseBumpMaterialPlugin.NOISE_BUMP_MATERIAL_GLTF_EXTENSION | |||||
| this.name = noiseBumpMaterialGLTFExtension.name | |||||
| } | } | ||||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | async extendMaterialParams(materialIndex: number, materialParams: any) { | ||||
| const extensionDef: any = ThreeSerialization.Serialize(material.userData._noiseBumpMat) | const extensionDef: any = ThreeSerialization.Serialize(material.userData._noiseBumpMat) | ||||
| materialDef.extensions[ NoiseBumpMaterialPlugin.NOISE_BUMP_MATERIAL_GLTF_EXTENSION ] = extensionDef | |||||
| w.extensionsUsed[ NoiseBumpMaterialPlugin.NOISE_BUMP_MATERIAL_GLTF_EXTENSION ] = true | |||||
| materialDef.extensions[ noiseBumpMaterialGLTFExtension.name ] = extensionDef | |||||
| w.extensionsUsed[ noiseBumpMaterialGLTFExtension.name ] = true | |||||
| }, | }, | ||||
| }) | }) | ||||
| export const noiseBumpMaterialGLTFExtension = { | |||||
| name: 'WEBGI_materials_noise_bump', | |||||
| import: (p) => new GLTFMaterialsNoiseBumpMaterialImport(p), | |||||
| export: glTFMaterialsNoiseBumpMaterialExport, | |||||
| textures: undefined, | |||||
| } satisfies AssetManager['gltfExtensions'][number] | |||||