| @@ -8,6 +8,7 @@ import { | |||
| LinearFilter, | |||
| LinearMipmapLinearFilter, | |||
| LoadingManager, | |||
| Object3D, | |||
| PerspectiveCamera, | |||
| TextureLoader, | |||
| } from 'three' | |||
| @@ -47,6 +48,7 @@ import {ILoader} from './IImporter' | |||
| import {AssetExporter} from './AssetExporter' | |||
| import {IExporter} from './IExporter' | |||
| import {GLTFExporter2} from './export' | |||
| import {legacySeparateMapSamplerUVFix} from '../utils/legacy' | |||
| export interface AssetManagerOptions{ | |||
| /** | |||
| @@ -137,6 +139,11 @@ export class AssetManager extends EventDispatcher<BaseEvent&{data?: ImportResult | |||
| const arr: (ImportResult | undefined)[] = Array.isArray(imported) ? imported : [imported] | |||
| let ret: T = Array.isArray(imported) ? [] : undefined as any | |||
| if (options?.importConfig !== false) { | |||
| const config = arr.find(v => v?.assetType === 'config') || arr.find(v=>v && !!v.importedViewerConfig)?.importedViewerConfig | |||
| if (config) legacySeparateMapSamplerUVFix(config, arr.filter(a=>a?.isObject3D) as Object3D[]) | |||
| } | |||
| for (const obj of arr) { | |||
| if (!obj) { | |||
| if (Array.isArray(ret)) ret.push(undefined) | |||
| @@ -210,7 +210,6 @@ export class GLTFExporter2 extends GLTFExporter implements IExportParser { | |||
| // should be last | |||
| this.register(this.gltfViewerWriter(viewer)) | |||
| return this | |||
| } | |||
| gltfViewerWriter(viewer: ThreeViewer): (parser: GLTFWriter2) => GLTFExporterPlugin { | |||
| @@ -1,5 +1,5 @@ | |||
| import {ShaderMaterial2} from './ShaderMaterial2' | |||
| import {getTexelDecoding2} from '../../three' | |||
| import {getTexelDecoding} from '../../three' | |||
| import { | |||
| BufferGeometry, | |||
| Camera, | |||
| @@ -49,7 +49,7 @@ export class ExtendedShaderMaterial extends ShaderMaterial2 { | |||
| } | |||
| onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D): void { | |||
| this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget() ?? renderer.getSize(new Vector2())) | |||
| this.uniforms.screenSize && this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget() ?? renderer.getSize(new Vector2())) | |||
| for (const item of this.textures) { | |||
| const textureID = item.id | |||
| @@ -69,7 +69,7 @@ export class ExtendedShaderMaterial extends ShaderMaterial2 { | |||
| onBeforeCompile(s: Shader, renderer: WebGLRenderer) { | |||
| const pars = '\n' + this.textures | |||
| .map(t=>`uniform sampler2D ${t.id}; \n` | |||
| + getTexelDecoding2(t.id ?? 'input', t.colorSpace ?? LinearSRGBColorSpace)).join('\n') | |||
| + getTexelDecoding(t.id ?? 'input', t, renderer.capabilities.isWebGL2)).join('\n') | |||
| if (s.fragmentShader.includes('#include <encodings_pars_fragment>')) { | |||
| s.fragmentShader = shaderReplaceString(s.fragmentShader, '#include <encodings_pars_fragment>', pars, {append: true}) | |||
| @@ -51,26 +51,14 @@ export class AssetExporterPlugin extends AViewerPluginSync<''> { | |||
| return super.onRemove(viewer) | |||
| } | |||
| @serialize() exportOptions: ExportAssetOptions = { | |||
| // readonly because bound to ui | |||
| @serialize() readonly exportOptions: ExportAssetOptions = { | |||
| name: 'scene', | |||
| viewerConfig: true, | |||
| encodeUint16Rgbe: false, | |||
| convertMeshToIndexed: false, | |||
| embedUrlImagePreviews: false, | |||
| embedUrlImages: false, | |||
| // compress: false, | |||
| // dracoOptions: { | |||
| // encodeSpeed: 5, | |||
| // method: EncoderMethod.EDGEBREAKER, | |||
| // quantizationVolume: 'mesh', | |||
| // quantizationBits: { | |||
| // ['POSITION']: 14, | |||
| // ['NORMAL']: 10, | |||
| // ['COLOR']: 8, | |||
| // ['TEX_COORD']: 12, | |||
| // ['GENERIC']: 12, | |||
| // }, | |||
| // } as EncoderOptions, | |||
| encrypt: false, | |||
| encryptKey: '', | |||
| } | |||
| @@ -107,48 +95,6 @@ export class AssetExporterPlugin extends AViewerPluginSync<''> { | |||
| type: 'folder', | |||
| label: 'GLB Export', | |||
| children: [ | |||
| // compress ? { | |||
| // type: 'checkbox', | |||
| // label: 'DRACO Compress', | |||
| // property: [this.exportOptions, 'compress'], | |||
| // onChange: ()=>this.uiConfig.uiRefresh?.(true), | |||
| // } : {}, | |||
| // compress && this.exportOptions.dracoOptions ? { | |||
| // type: 'folder', | |||
| // hidden: ()=>!this.exportOptions.compress, | |||
| // label: 'DRACO Options', | |||
| // children: [ | |||
| // { | |||
| // type: 'slider', | |||
| // label: 'Encode Speed', | |||
| // bounds: [1, 10], | |||
| // property: [this.exportOptions.dracoOptions, 'encodeSpeed'], | |||
| // }, | |||
| // { | |||
| // type: 'dropdown', | |||
| // label: 'Encoder Method', | |||
| // property: [this.exportOptions.dracoOptions, 'method'], | |||
| // children: Object.entries(EncoderMethod).map(([k, v]) => ({label: k, value: v})), | |||
| // }, | |||
| // { | |||
| // type: 'dropdown', | |||
| // label: 'Quantization Volume', | |||
| // property: [this.exportOptions.dracoOptions, 'quantizationVolume'], | |||
| // children: ['mesh', 'scene', 'bbox'].map(v => ({label: v})), | |||
| // }, | |||
| // { | |||
| // type: 'folder', | |||
| // label: 'Quantization Bits', | |||
| // children: Object.keys(this.exportOptions.dracoOptions.quantizationBits!).map(k => ({ | |||
| // type: 'slider', | |||
| // label: k, | |||
| // bounds: [1, 16], | |||
| // stepSize: 1, | |||
| // property: [this.exportOptions.dracoOptions.quantizationBits, k], | |||
| // })), | |||
| // }, | |||
| // ], | |||
| // } : {}, | |||
| { | |||
| type: 'checkbox', | |||
| label: 'Viewer Config (All Settings)', | |||
| @@ -164,8 +164,11 @@ export class LoadingScreenPlugin extends AAssetManagerProcessStatePlugin { | |||
| this.loadingElement.style.display = '' | |||
| } | |||
| private _temp = document.createElement('template') | |||
| private _setHTML(elem: HTMLElement, html:string) { | |||
| if (elem.innerHTML !== html) elem.innerHTML = html | |||
| this._temp.innerHTML = html | |||
| // Compare the parsed content instead of raw strings, as browsers might change html after setting. | |||
| if (this._temp.innerHTML.trim() !== elem.innerHTML.trim()) elem.innerHTML = html | |||
| } | |||
| protected _updateMainDiv(processState: Map<string, {state: string, progress?: number|undefined}>, updateVisibility = true) { | |||
| @@ -0,0 +1,35 @@ | |||
| import {MeshStandardMaterial2, PhysicalMaterial} from '../core' | |||
| import {Object3D, Texture} from 'three' | |||
| // todo needs testing with some more files maybe | |||
| export function legacySeparateMapSamplerUVFix(config: any, objs: Object3D[]) { | |||
| const version = (config.version ? config.version as string : '0.0.0').split('.').map(v => parseInt(v)) | |||
| // separate texture map sampler properties added for materials in this version. | |||
| if (!(config.type === 'ViewerApp' && version[0] === 0 && (version[1] < 7 || version[1] === 7 && version[2].toString()[0] < '6'))) { | |||
| return | |||
| } | |||
| const materials = new Set<any>() | |||
| objs.forEach(o1 => o1.traverse((o: any) => { | |||
| if (o.material) materials.add(o.material) | |||
| })) | |||
| materials.forEach(material => { | |||
| const map = material.map as Texture | |||
| if (!map) return | |||
| const repeat = map.repeat | |||
| const offset = map.offset | |||
| const center = map.center | |||
| const rotation = map.rotation | |||
| const others: ((keyof MeshStandardMaterial2) | (keyof PhysicalMaterial))[] = ['alphaMap', 'aoMap', 'bumpMap', 'displacementMap', 'emissiveMap', 'lightMap', 'metalnessMap', 'normalMap', 'roughnessMap', 'transmissionMap'] | |||
| others.forEach(k => { | |||
| const m = material[k] as Texture | |||
| if (m) { | |||
| m.repeat.copy(repeat) | |||
| m.offset.copy(offset) | |||
| m.center.copy(center) | |||
| m.rotation = rotation | |||
| m.needsUpdate = true | |||
| } | |||
| }) | |||
| material.needsUpdate = true | |||
| }) | |||
| } | |||
| @@ -30,7 +30,7 @@ | |||
| "plugins": [{ "name": "typescript-plugin-css-modules" }] | |||
| }, | |||
| "include": [ | |||
| "src/**/*", | |||
| "./src/**/*", | |||
| "node_modules/@types/wicg-file-system-access/index.d.ts" | |||
| ], | |||
| "exclude": [ | |||