| @@ -1,12 +1,12 @@ | |||
| { | |||
| "name": "threepipe", | |||
| "version": "0.0.35-dev", | |||
| "version": "0.0.35", | |||
| "lockfileVersion": 3, | |||
| "requires": true, | |||
| "packages": { | |||
| "": { | |||
| "name": "threepipe", | |||
| "version": "0.0.35-dev", | |||
| "version": "0.0.35", | |||
| "license": "Apache-2.0", | |||
| "dependencies": { | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz", | |||
| @@ -1,6 +1,6 @@ | |||
| { | |||
| "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.", | |||
| "main": "dist/index.js", | |||
| "module": "dist/index.mjs", | |||
| @@ -1,8 +1,6 @@ | |||
| import { | |||
| AssetExporterPlugin, | |||
| AViewerPluginSync, | |||
| ClearcoatTintPlugin, | |||
| CustomBumpMapPlugin, | |||
| DRACOLoader2, | |||
| generateUUID, | |||
| GLTFLightExtrasExtension, | |||
| @@ -12,8 +10,12 @@ import { | |||
| GLTFMaterialsDisplacementMapExtension, | |||
| GLTFMaterialsLightMapExtension, | |||
| GLTFObject3DExtrasExtension, | |||
| NoiseBumpMaterialPlugin, | |||
| IExporter, | |||
| ThreeViewer, | |||
| clearCoatTintGLTFExtension, | |||
| customBumpMapGLTFExtension, | |||
| noiseBumpMaterialGLTFExtension, | |||
| fragmentClippingGLTFExtension, | |||
| } from 'threepipe' | |||
| import {GLTFDracoExporter} from './GLTFDracoExporter' | |||
| import {UiObjectConfig} from 'uiconfig.js' | |||
| @@ -36,58 +38,88 @@ export class GLTFDracoExportPlugin extends AViewerPluginSync<''> { | |||
| public static readonly PluginType = 'GLTFDracoExportPlugin' | |||
| 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 { | |||
| super.onAdded(viewer) | |||
| const importer = viewer.assetManager.importer | |||
| 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'], | |||
| 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) | |||
| if (exportPlugin) { | |||
| Object.assign(exportPlugin.exportOptions, { | |||
| @@ -114,6 +146,15 @@ export class GLTFDracoExportPlugin extends AViewerPluginSync<''> { | |||
| } | |||
| } | |||
| 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)=>[ | |||
| { | |||
| type: 'checkbox', | |||
| @@ -47,8 +47,10 @@ import {Class, ValOrArr} from 'ts-browser-helpers' | |||
| import {ILoader} from './IImporter' | |||
| import {AssetExporter} from './AssetExporter' | |||
| import {IExporter} from './IExporter' | |||
| import {GLTFExporter2} from './export' | |||
| import {GLTFExporter2, GLTFWriter2} from './export' | |||
| 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{ | |||
| /** | |||
| @@ -99,6 +101,7 @@ export class AssetManager extends EventDispatcher<BaseEvent&{data?: ImportResult | |||
| this._sceneUpdated = this._sceneUpdated.bind(this) | |||
| this.addAsset = this.addAsset.bind(this) | |||
| this.addRaw = this.addRaw.bind(this) | |||
| this._loaderCreate = this._loaderCreate.bind(this) | |||
| this.addImported = this.addImported.bind(this) | |||
| this.importer = new AssetImporter(!!viewer.getPlugin('debug')) | |||
| @@ -110,6 +113,7 @@ export class AssetManager extends EventDispatcher<BaseEvent&{data?: ImportResult | |||
| this.viewer.scene.addEventListener('beforeDeserialize', this._sceneUpdated) | |||
| this._initCacheStorage(simpleCache, storage ?? true) | |||
| this._setupGltfExtensions() | |||
| this._setupObjectProcess() | |||
| this._setupProcessState() | |||
| this._addImporters() | |||
| @@ -309,17 +313,19 @@ export class AssetManager extends EventDispatcher<BaseEvent&{data?: ImportResult | |||
| } | |||
| 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() { | |||
| 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) | |||
| } | |||
| @@ -494,6 +500,57 @@ export class AssetManager extends EventDispatcher<BaseEvent&{data?: ImportResult | |||
| }) | |||
| } | |||
| // 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 | |||
| @@ -59,4 +59,7 @@ export class GLTFLightExtrasExtension { | |||
| } | |||
| }, | |||
| }) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number>|undefined = undefined | |||
| } | |||
| @@ -283,4 +283,7 @@ export class GLTFMaterialExtrasExtension { | |||
| // console.log(w) | |||
| }, | |||
| }) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number>|undefined = undefined | |||
| } | |||
| @@ -14,6 +14,11 @@ export class GLTFMaterialsAlphaMapExtension { | |||
| static readonly WebGiMaterialsAlphaMapExtension = 'WEBGI_materials_alphamap' | |||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsAlphaMapExtensionImport(parser) | |||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsAlphaMapExtensionExport(writer) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number> = { | |||
| alphaTexture: 'G', | |||
| } | |||
| } | |||
| class GLTFMaterialsAlphaMapExtensionImport { | |||
| @@ -13,6 +13,11 @@ export class GLTFMaterialsBumpMapExtension { | |||
| static readonly WebGiMaterialsBumpMapExtension = 'WEBGI_materials_bumpmap' | |||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsBumpMapExtensionImport(parser) | |||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsBumpMapExtensionExport(writer) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number> = { | |||
| bumpTexture: 'R', | |||
| } | |||
| } | |||
| class GLTFMaterialsBumpMapExtensionImport { | |||
| @@ -13,6 +13,11 @@ export class GLTFMaterialsDisplacementMapExtension { | |||
| static readonly WebGiMaterialsDisplacementMapExtension = 'WEBGI_materials_displacementmap' | |||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsDisplacementMapExtensionImport(parser) | |||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsDisplacementMapExtensionExport(writer) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number> = { | |||
| displacementTexture: 'R', | |||
| } | |||
| } | |||
| class GLTFMaterialsDisplacementMapExtensionImport { | |||
| @@ -13,6 +13,11 @@ export class GLTFMaterialsLightMapExtension { | |||
| static readonly WebGiMaterialsLightMapExtension = 'WEBGI_materials_lightmap' | |||
| static Import = (parser: GLTFParser): GLTFLoaderPlugin=> new GLTFMaterialsLightMapExtensionImport(parser) | |||
| static Export = (writer: GLTFWriter): GLTFExporterPlugin => new GLTFMaterialsLightMapExtensionExport(writer) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number> = { | |||
| lightMapTexture: 'RGB', | |||
| } | |||
| } | |||
| class GLTFMaterialsLightMapExtensionImport { | |||
| @@ -69,4 +69,7 @@ export class GLTFObject3DExtrasExtension { | |||
| } | |||
| }, | |||
| }) | |||
| // see GLTFDracoExportPlugin | |||
| static Textures: Record<string, string|number>|undefined = undefined | |||
| } | |||
| @@ -24,7 +24,7 @@ export class DirectionalLight2< | |||
| @uiColor('Color', (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | |||
| declare color: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @uiSlider('Intensity', [0, 100], 0.01) | |||
| @onChange3('setDirty') | |||
| declare intensity: number | |||
| @uiVector('Position', undefined, undefined, (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | |||
| @@ -1,5 +1,5 @@ | |||
| import {AViewerPluginSync, ThreeViewer} from '../../viewer' | |||
| import {GLTFLoader2} from '../../assetmanager' | |||
| import {AssetManager} from '../../assetmanager' | |||
| import {onChange, serialize} from 'ts-browser-helpers' | |||
| import {IMaterial, IObject3D} from '../../core' | |||
| import {UiObjectConfig} from 'uiconfig.js' | |||
| @@ -23,28 +23,18 @@ export class GLTFKHRMaterialVariantsPlugin extends AViewerPluginSync<''> { | |||
| constructor() { | |||
| super() | |||
| this._loaderCreate = this._loaderCreate.bind(this) | |||
| } | |||
| onAdded(v: ThreeViewer): void { | |||
| super.onAdded(v) | |||
| // v.addEventListener('preRender', this._preRender) | |||
| 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 { | |||
| 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 = {} | |||
| return super.onRemove(v) | |||
| } | |||
| @@ -152,3 +142,10 @@ declare module './../../core/IObject'{ | |||
| _originalMaterial?: IObject3D['material'] | |||
| } | |||
| } | |||
| export const khrMaterialVariantsGLTFExtension = { | |||
| name: khrMaterialsVariantsGLTF, | |||
| import: (p) => new GLTFMaterialsVariantsExtensionImport(p), | |||
| export: gltfExporterMaterialsVariantsExtensionExport, | |||
| // textures: undefined, | |||
| } satisfies AssetManager['gltfExtensions'][number] | |||
| @@ -65,11 +65,11 @@ export {TransformAnimationPlugin, type TSavedTransform} from './animation/Transf | |||
| export {CameraViewPlugin, type CameraViewPluginOptions} from './animation/CameraViewPlugin' | |||
| // 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 {FragmentClippingExtensionPlugin, FragmentClippingMode} from './material/FragmentClippingExtensionPlugin' | |||
| export {FragmentClippingExtensionPlugin, FragmentClippingMode, fragmentClippingGLTFExtension} from './material/FragmentClippingExtensionPlugin' | |||
| // rendering | |||
| export {VirtualCamerasPlugin, type VirtualCamera} from './rendering/VirtualCamerasPlugin' | |||
| @@ -5,7 +5,7 @@ import {glsl, serialize} from 'ts-browser-helpers' | |||
| import {IMaterialUserData, PhysicalMaterial} from '../../core' | |||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | |||
| 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' | |||
| /** | |||
| @@ -161,37 +161,26 @@ vec3 clearcoatTint(const in float dotNV, const in float dotNL, const in float cl | |||
| this._viewer?.setDirty() | |||
| } | |||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||
| if (!loader.isGLTFLoader2) return | |||
| loader.register((p) => new GLTFMaterialsClearcoatTintExtensionImport(p)) | |||
| } | |||
| constructor() { | |||
| super() | |||
| this._loaderCreate = this._loaderCreate.bind(this) | |||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | |||
| } | |||
| onAdded(v: ThreeViewer) { | |||
| super.onAdded(v) | |||
| // v.addEventListener('preRender', this._preRender) | |||
| 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) { | |||
| 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) | |||
| } | |||
| /** | |||
| * @deprecated - use {@link clearCoatTintGLTFExtension} | |||
| */ | |||
| public static readonly CLEARCOAT_TINT_GLTF_EXTENSION = 'WEBGI_materials_clearcoat_tint' | |||
| } | |||
| @@ -210,7 +199,7 @@ declare module '../../core/IMaterial' { | |||
| /** | |||
| * 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 { | |||
| public name: string | |||
| @@ -218,7 +207,7 @@ class GLTFMaterialsClearcoatTintExtensionImport implements GLTFLoaderPlugin { | |||
| constructor(parser: GLTFParser) { | |||
| this.parser = parser | |||
| this.name = ClearcoatTintPlugin.CLEARCOAT_TINT_GLTF_EXTENSION | |||
| this.name = clearCoatTintGLTFExtension.name | |||
| } | |||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | |||
| @@ -239,7 +228,14 @@ const glTFMaterialsClearcoatTintExtensionExport = (w: GLTFWriter2)=> ({ | |||
| 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] | |||
| @@ -5,7 +5,7 @@ import {serialize} from 'ts-browser-helpers' | |||
| import {IMaterial, IObject3D, ITexture, PhysicalMaterial} from '../../core' | |||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | |||
| 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 CustomBumpMapPluginShader from './shaders/CustomBumpMapPlugin.glsl' | |||
| import {matDefine} from '../../three' | |||
| @@ -147,7 +147,7 @@ export class CustomBumpMapPlugin extends AViewerPluginSync<''> { | |||
| if (v === state._hasCustomBump) return | |||
| if (v) { | |||
| if (!enableCustomBump(material)) | |||
| viewer.dialog.alert('Cannot add CustomBumpMap.') | |||
| viewer.dialog.alert('CustomBumpMapPlugin - Cannot add CustomBumpMap.') | |||
| } else { | |||
| state._hasCustomBump = false | |||
| if (material.setDirty) material.setDirty() | |||
| @@ -161,7 +161,7 @@ export class CustomBumpMapPlugin extends AViewerPluginSync<''> { | |||
| bounds: [-1, 1], | |||
| hidden: () => !state._hasCustomBump, | |||
| property: [state, '_customBumpScale'], | |||
| onChange: this.setDirty, | |||
| // onChange: this.setDirty, | |||
| }, | |||
| { | |||
| type: 'image', | |||
| @@ -169,10 +169,10 @@ export class CustomBumpMapPlugin extends AViewerPluginSync<''> { | |||
| hidden: () => !state._hasCustomBump, | |||
| property: [state, '_customBumpMap'], | |||
| 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 | |||
| @@ -185,14 +185,8 @@ export class CustomBumpMapPlugin extends AViewerPluginSync<''> { | |||
| this._viewer?.setDirty() | |||
| } | |||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||
| if (!loader.isGLTFLoader2) return | |||
| loader.register((p) => new GLTFMaterialsCustomBumpMapImport(p)) | |||
| } | |||
| constructor() { | |||
| super() | |||
| this._loaderCreate = this._loaderCreate.bind(this) | |||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | |||
| } | |||
| @@ -200,24 +194,20 @@ export class CustomBumpMapPlugin extends AViewerPluginSync<''> { | |||
| super.onAdded(v) | |||
| // v.addEventListener('preRender', this._preRender) | |||
| 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]) | |||
| } | |||
| onRemove(v: ThreeViewer) { | |||
| 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]) | |||
| return super.onRemove(v) | |||
| } | |||
| /** | |||
| * @deprecated use {@link customBumpMapGLTFExtension} | |||
| */ | |||
| public static readonly CUSTOM_BUMP_MAP_GLTF_EXTENSION = 'WEBGI_materials_custom_bump_map' | |||
| } | |||
| @@ -242,7 +232,7 @@ class GLTFMaterialsCustomBumpMapImport implements GLTFLoaderPlugin { | |||
| constructor(parser: GLTFParser) { | |||
| this.parser = parser | |||
| this.name = CustomBumpMapPlugin.CUSTOM_BUMP_MAP_GLTF_EXTENSION | |||
| this.name = customBumpMapGLTFExtension.name | |||
| } | |||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | |||
| @@ -299,7 +289,16 @@ const glTFMaterialsCustomBumpMapExport = (w: GLTFWriter2)=> ({ | |||
| } | |||
| 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] | |||
| @@ -5,7 +5,7 @@ import {serialize} from 'ts-browser-helpers' | |||
| import {IMaterial, IMaterialUserData, IObject3D, PhysicalMaterial} from '../../core' | |||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | |||
| 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 FragmentClippingExtensionPluginPars from './shaders/FragmentClippingExtensionPlugin.pars.glsl' | |||
| import FragmentClippingExtensionPluginPatch from './shaders/FragmentClippingExtensionPlugin.patch.glsl' | |||
| @@ -186,14 +186,8 @@ export class FragmentClippingExtensionPlugin extends AViewerPluginSync<''> { | |||
| this._viewer?.setDirty() | |||
| } | |||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||
| if (!loader.isGLTFLoader2) return | |||
| loader.register((p) => new GLTFMaterialsFragmentClippingExtensionImport(p)) | |||
| } | |||
| constructor() { | |||
| super() | |||
| this._loaderCreate = this._loaderCreate.bind(this) | |||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | |||
| } | |||
| @@ -201,24 +195,21 @@ export class FragmentClippingExtensionPlugin extends AViewerPluginSync<''> { | |||
| super.onAdded(v) | |||
| // v.addEventListener('preRender', this._preRender) | |||
| 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]) | |||
| } | |||
| onRemove(v: ThreeViewer) { | |||
| 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]) | |||
| return super.onRemove(v) | |||
| } | |||
| /** | |||
| * @deprecated use - use {@link fragmentClippingGLTFExtension} | |||
| */ | |||
| public static readonly FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION = 'WEBGI_materials_fragment_clipping_extension' | |||
| } | |||
| @@ -255,7 +246,7 @@ class GLTFMaterialsFragmentClippingExtensionImport implements GLTFLoaderPlugin { | |||
| constructor(parser: GLTFParser) { | |||
| this.parser = parser | |||
| this.name = FragmentClippingExtensionPlugin.FRAGMENT_CLIPPING_EXTENSION_GLTF_EXTENSION | |||
| this.name = fragmentClippingGLTFExtension.name | |||
| } | |||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | |||
| @@ -276,7 +267,14 @@ const glTFMaterialsFragmentClippingExtensionExport = (w: GLTFWriter2)=> ({ | |||
| 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] | |||
| @@ -5,7 +5,7 @@ import {serialize} from 'ts-browser-helpers' | |||
| import {IMaterial, IMaterialUserData, IObject3D, PhysicalMaterial} from '../../core' | |||
| import {MaterialExtension, updateMaterialDefines} from '../../materials' | |||
| 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 NoiseBumpMaterialPluginPars from './shaders/NoiseBumpMaterialPlugin.pars.glsl' | |||
| import NoiseBumpMaterialPluginPatch from './shaders/NoiseBumpMaterialPlugin.patch.glsl' | |||
| @@ -241,35 +241,26 @@ export class NoiseBumpMaterialPlugin extends AViewerPluginSync<''> { | |||
| this._viewer?.setDirty() | |||
| } | |||
| private _loaderCreate({loader}: {loader: GLTFLoader2}) { | |||
| if (!loader.isGLTFLoader2) return | |||
| loader.register((p) => new GLTFMaterialsNoiseBumpMaterialImport(p)) | |||
| } | |||
| constructor() { | |||
| super() | |||
| this._loaderCreate = this._loaderCreate.bind(this) | |||
| Object.assign(this.materialExtension.extraUniforms!, this._uniforms) | |||
| } | |||
| onAdded(v: ThreeViewer) { | |||
| super.onAdded(v) | |||
| 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) { | |||
| 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) | |||
| } | |||
| /** | |||
| * @deprecated - use {@link noiseBumpMaterialGLTFExtension} | |||
| */ | |||
| public static readonly NOISE_BUMP_MATERIAL_GLTF_EXTENSION = 'WEBGI_materials_noise_bump' | |||
| } | |||
| @@ -293,7 +284,7 @@ declare module '../../core/IMaterial' { | |||
| /** | |||
| * 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 { | |||
| public name: string | |||
| @@ -301,7 +292,7 @@ class GLTFMaterialsNoiseBumpMaterialImport implements GLTFLoaderPlugin { | |||
| constructor(parser: GLTFParser) { | |||
| this.parser = parser | |||
| this.name = NoiseBumpMaterialPlugin.NOISE_BUMP_MATERIAL_GLTF_EXTENSION | |||
| this.name = noiseBumpMaterialGLTFExtension.name | |||
| } | |||
| async extendMaterialParams(materialIndex: number, materialParams: any) { | |||
| @@ -322,7 +313,15 @@ const glTFMaterialsNoiseBumpMaterialExport = (w: GLTFWriter2)=> ({ | |||
| 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] | |||