From 09487b9c60adc9dd44b028a5301e4b8a4af0433a Mon Sep 17 00:00:00 2001 From: Jim Eckerlein Date: Wed, 10 Apr 2024 15:51:09 +0200 Subject: [PATCH 1/7] Fetch models remotely --- app_web/src/main.js | 669 +++++++++++++++++------------ app_web/src/model_path_provider.js | 13 +- 2 files changed, 390 insertions(+), 292 deletions(-) diff --git a/app_web/src/main.js b/app_web/src/main.js index e390ca80..38f1de25 100644 --- a/app_web/src/main.js +++ b/app_web/src/main.js @@ -1,295 +1,396 @@ +import { GltfView } from "gltf-viewer-source"; -import { GltfView } from 'gltf-viewer-source'; - -import { UIModel } from './logic/uimodel.js'; -import { app } from './ui/ui.js'; -import { EMPTY, from, merge } from 'rxjs'; -import { mergeMap, map, share, catchError } from 'rxjs/operators'; -import { GltfModelPathProvider, fillEnvironmentWithPaths } from './model_path_provider.js'; +import { UIModel } from "./logic/uimodel.js"; +import { app } from "./ui/ui.js"; +import { EMPTY, from, merge } from "rxjs"; +import { mergeMap, map, share, catchError } from "rxjs/operators"; +import { + GltfModelPathProvider, + fillEnvironmentWithPaths, +} from "./model_path_provider.js"; export default async () => { - const canvas = document.getElementById("canvas"); - const context = canvas.getContext("webgl2", { alpha: false, antialias: true }); - const view = new GltfView(context); - const resourceLoader = view.createResourceLoader(); - const state = view.createState(); - state.renderingParameters.useDirectionalLightsWithDisabledIBL = true; - - const pathProvider = new GltfModelPathProvider('assets/models/Models/model-index.json'); - await pathProvider.initialize(); - const environmentPaths = fillEnvironmentWithPaths({ - "Cannon_Exterior": "Cannon Exterior", - "footprint_court": "Footprint Court", - "pisa": "Pisa", - "doge2": "Doge's palace", - "ennis": "Dining room", - "field": "Field", - "helipad": "Helipad Goldenhour", - "papermill": "Papermill Ruins", - "neutral": "Studio Neutral", - "Colorful_Studio": "Colorful Studio", - "Wide_Street" : "Wide Street", - }, "assets/environments/"); - - const uiModel = new UIModel(app, pathProvider, environmentPaths); - - // whenever a new model is selected, load it and when complete pass the loaded gltf - // into a stream back into the UI - const gltfLoaded = uiModel.model.pipe( - mergeMap(model => { - uiModel.goToLoadingState(); - - // Workaround for errors in ktx lib after loading an asset with ktx2 files for the second time: - resourceLoader.initKtxLib(); - - return from(resourceLoader.loadGltf(model.mainFile, model.additionalFiles).then(gltf => { - state.gltf = gltf; - const defaultScene = state.gltf.scene; - state.sceneIndex = defaultScene === undefined ? 0 : defaultScene; - state.cameraIndex = undefined; - - if (state.gltf.scenes.length != 0) { - if (state.sceneIndex > state.gltf.scenes.length - 1) { - state.sceneIndex = 0; - } - const scene = state.gltf.scenes[state.sceneIndex]; - scene.applyTransformHierarchy(state.gltf); - state.userCamera.aspectRatio = canvas.width / canvas.height; - state.userCamera.fitViewToScene(state.gltf, state.sceneIndex); - - // Try to start as many animations as possible without generating conficts. - state.animationIndices = []; - for (let i = 0; i < gltf.animations.length; i++) { - if (!gltf.nonDisjointAnimations(state.animationIndices).includes(i)) { - state.animationIndices.push(i); - } - } - state.animationTimer.start(); - } - - uiModel.exitLoadingState(); - - return state; - })); - }), - catchError(error => { - console.error(error); - uiModel.exitLoadingState(); - return EMPTY; - }), - share() - ); - - // Disable all animations which are not disjoint to the current selection of animations. - uiModel.disabledAnimations(uiModel.activeAnimations.pipe(map(animationIndices => state.gltf.nonDisjointAnimations(animationIndices)))); - - const sceneChangedObservable = uiModel.scene.pipe( - map(sceneIndex => { - state.sceneIndex = sceneIndex; + const canvas = document.getElementById("canvas"); + const context = canvas.getContext("webgl2", { + alpha: false, + antialias: true, + }); + const view = new GltfView(context); + const resourceLoader = view.createResourceLoader(); + const state = view.createState(); + state.renderingParameters.useDirectionalLightsWithDisabledIBL = true; + + const pathProvider = new GltfModelPathProvider( + "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main", + "Models/model-index.json", + ); + await pathProvider.initialize(); + const environmentPaths = fillEnvironmentWithPaths( + { + Cannon_Exterior: "Cannon Exterior", + footprint_court: "Footprint Court", + pisa: "Pisa", + doge2: "Doge's palace", + ennis: "Dining room", + field: "Field", + helipad: "Helipad Goldenhour", + papermill: "Papermill Ruins", + neutral: "Studio Neutral", + Colorful_Studio: "Colorful Studio", + Wide_Street: "Wide Street", + }, + "assets/environments/", + ); + + const uiModel = new UIModel(app, pathProvider, environmentPaths); + + // whenever a new model is selected, load it and when complete pass the loaded gltf + // into a stream back into the UI + const gltfLoaded = uiModel.model.pipe( + mergeMap((model) => { + uiModel.goToLoadingState(); + + // Workaround for errors in ktx lib after loading an asset with ktx2 files for the second time: + resourceLoader.initKtxLib(); + + return from( + resourceLoader + .loadGltf(model.mainFile, model.additionalFiles) + .then((gltf) => { + state.gltf = gltf; + const defaultScene = state.gltf.scene; + state.sceneIndex = defaultScene === undefined ? 0 : defaultScene; state.cameraIndex = undefined; - const scene = state.gltf.scenes[state.sceneIndex]; - if (scene !== undefined) - { - scene.applyTransformHierarchy(state.gltf); - state.userCamera.fitViewToScene(state.gltf, state.sceneIndex); - } - }), - share() - ); - - const statisticsUpdateObservable = merge(sceneChangedObservable, gltfLoaded).pipe(map(() => view.gatherStatistics(state))); - - const cameraExportChangedObservable = uiModel.cameraValuesExport.pipe(map(() => { - const camera = state.cameraIndex === undefined - ? state.userCamera - : state.gltf.cameras[state.cameraIndex]; - return camera.getDescription(state.gltf); - })); - - const downloadDataURL = (filename, dataURL) => { - const element = document.createElement('a'); - element.setAttribute('href', dataURL); - element.setAttribute('download', filename); - element.style.display = 'none'; - document.body.appendChild(element); - element.click(); - document.body.removeChild(element); - }; - - cameraExportChangedObservable.subscribe(cameraDesc => { - const gltf = JSON.stringify(cameraDesc, undefined, 4); - const dataURL = 'data:text/plain;charset=utf-8,' + encodeURIComponent(gltf); - downloadDataURL("camera.gltf", dataURL); - }); - - uiModel.captureCanvas.subscribe(() => { - view.renderFrame(state, canvas.width, canvas.height); - const dataURL = canvas.toDataURL(); - downloadDataURL("capture.png", dataURL); - }); - - // Only redraw glTF view upon user inputs, or when an animation is playing. - let redraw = false; - const listenForRedraw = stream => stream.subscribe(() => redraw = true); - - uiModel.scene.subscribe(scene => state.sceneIndex = scene !== -1 ? scene : undefined); - listenForRedraw(uiModel.scene); - - uiModel.camera.subscribe(camera => state.cameraIndex = camera !== -1 ? camera : undefined); - listenForRedraw(uiModel.camera); - - uiModel.variant.subscribe(variant => state.variant = variant); - listenForRedraw(uiModel.variant); - - uiModel.tonemap.subscribe(tonemap => state.renderingParameters.toneMap = tonemap); - listenForRedraw(uiModel.tonemap); - - uiModel.debugchannel.subscribe(debugchannel => state.renderingParameters.debugOutput = debugchannel); - listenForRedraw(uiModel.debugchannel); - - uiModel.skinningEnabled.subscribe(skinningEnabled => state.renderingParameters.skinning = skinningEnabled); - listenForRedraw(uiModel.skinningEnabled); - - uiModel.exposure.subscribe(exposure => state.renderingParameters.exposure = (1.0 / Math.pow(2.0, exposure))); - listenForRedraw(uiModel.exposure); - - uiModel.morphingEnabled.subscribe(morphingEnabled => state.renderingParameters.morphing = morphingEnabled); - listenForRedraw(uiModel.morphingEnabled); - - uiModel.clearcoatEnabled.subscribe(clearcoatEnabled => state.renderingParameters.enabledExtensions.KHR_materials_clearcoat = clearcoatEnabled); - listenForRedraw(uiModel.clearcoatEnabled); - - uiModel.sheenEnabled.subscribe(sheenEnabled => state.renderingParameters.enabledExtensions.KHR_materials_sheen = sheenEnabled); - listenForRedraw(uiModel.sheenEnabled); - - uiModel.transmissionEnabled.subscribe(transmissionEnabled => state.renderingParameters.enabledExtensions.KHR_materials_transmission = transmissionEnabled); - listenForRedraw(uiModel.transmissionEnabled); - - uiModel.volumeEnabled.subscribe(volumeEnabled => state.renderingParameters.enabledExtensions.KHR_materials_volume = volumeEnabled); - listenForRedraw(uiModel.volumeEnabled); - - uiModel.iorEnabled.subscribe(iorEnabled => state.renderingParameters.enabledExtensions.KHR_materials_ior = iorEnabled); - listenForRedraw(uiModel.iorEnabled); - uiModel.iridescenceEnabled.subscribe(iridescenceEnabled => state.renderingParameters.enabledExtensions.KHR_materials_iridescence = iridescenceEnabled); - listenForRedraw(uiModel.iridescenceEnabled); - - uiModel.anisotropyEnabled.subscribe(anisotropyEnabled => state.renderingParameters.enabledExtensions.KHR_materials_anisotropy = anisotropyEnabled); - listenForRedraw(uiModel.anisotropyEnabled); - - uiModel.dispersionEnabled.subscribe(dispersionEnabled => state.renderingParameters.enabledExtensions.KHR_materials_dispersion = dispersionEnabled); - listenForRedraw(uiModel.dispersionEnabled); - - uiModel.specularEnabled.subscribe(specularEnabled => state.renderingParameters.enabledExtensions.KHR_materials_specular = specularEnabled); - listenForRedraw(uiModel.specularEnabled); - - uiModel.emissiveStrengthEnabled.subscribe(enabled => state.renderingParameters.enabledExtensions.KHR_materials_emissive_strength = enabled); - listenForRedraw(uiModel.emissiveStrengthEnabled); - - uiModel.iblEnabled.subscribe(iblEnabled => state.renderingParameters.useIBL = iblEnabled); - listenForRedraw(uiModel.iblEnabled); - - uiModel.iblIntensity.subscribe(iblIntensity => state.renderingParameters.iblIntensity = Math.pow(10, iblIntensity)); - listenForRedraw(uiModel.iblIntensity); - - uiModel.renderEnvEnabled.subscribe(renderEnvEnabled => state.renderingParameters.renderEnvironmentMap = renderEnvEnabled); - listenForRedraw(uiModel.renderEnvEnabled); - - uiModel.blurEnvEnabled.subscribe(blurEnvEnabled => state.renderingParameters.blurEnvironmentMap = blurEnvEnabled); - listenForRedraw(uiModel.blurEnvEnabled); - - uiModel.punctualLightsEnabled.subscribe(punctualLightsEnabled => state.renderingParameters.usePunctual = punctualLightsEnabled); - listenForRedraw(uiModel.punctualLightsEnabled); - - uiModel.environmentRotation.subscribe(environmentRotation => { - switch (environmentRotation) { - case "+Z": - state.renderingParameters.environmentRotation = 90.0; - break; - case "-X": - state.renderingParameters.environmentRotation = 180.0; - break; - case "-Z": - state.renderingParameters.environmentRotation = 270.0; - break; - case "+X": - state.renderingParameters.environmentRotation = 0.0; - break; - } - }); - listenForRedraw(uiModel.environmentRotation); - - - uiModel.clearColor.subscribe(clearColor => state.renderingParameters.clearColor = clearColor); - listenForRedraw(uiModel.clearColor); - - uiModel.animationPlay.subscribe(animationPlay => { - if(animationPlay) { - state.animationTimer.unpause(); - } - else { - state.animationTimer.pause(); - } - }); - - uiModel.activeAnimations.subscribe(animations => state.animationIndices = animations); - listenForRedraw(uiModel.activeAnimations); - - uiModel.hdr.subscribe(hdrFile => { - resourceLoader.loadEnvironment(hdrFile).then( (environment) => { - state.environment = environment; - // We need to wait until the environment is loaded to redraw - redraw = true; - }); - }); - - uiModel.attachGltfLoaded(gltfLoaded); - uiModel.updateStatistics(statisticsUpdateObservable); - const sceneChangedStateObservable = uiModel.scene.pipe(map(() => state)); - uiModel.attachCameraChangeObservable(sceneChangedStateObservable); + if (state.gltf.scenes.length != 0) { + if (state.sceneIndex > state.gltf.scenes.length - 1) { + state.sceneIndex = 0; + } + const scene = state.gltf.scenes[state.sceneIndex]; + scene.applyTransformHierarchy(state.gltf); + state.userCamera.aspectRatio = canvas.width / canvas.height; + state.userCamera.fitViewToScene(state.gltf, state.sceneIndex); + + // Try to start as many animations as possible without generating conficts. + state.animationIndices = []; + for (let i = 0; i < gltf.animations.length; i++) { + if ( + !gltf + .nonDisjointAnimations(state.animationIndices) + .includes(i) + ) { + state.animationIndices.push(i); + } + } + state.animationTimer.start(); + } - uiModel.orbit.subscribe( orbit => { - if (state.cameraIndex === undefined) { - state.userCamera.orbit(orbit.deltaPhi, orbit.deltaTheta); - } - }); - listenForRedraw(uiModel.orbit); + uiModel.exitLoadingState(); - uiModel.pan.subscribe( pan => { - if (state.cameraIndex === undefined) { - state.userCamera.pan(pan.deltaX, -pan.deltaY); - } + return state; + }), + ); + }), + catchError((error) => { + console.error(error); + uiModel.exitLoadingState(); + return EMPTY; + }), + share(), + ); + + // Disable all animations which are not disjoint to the current selection of animations. + uiModel.disabledAnimations( + uiModel.activeAnimations.pipe( + map((animationIndices) => + state.gltf.nonDisjointAnimations(animationIndices), + ), + ), + ); + + const sceneChangedObservable = uiModel.scene.pipe( + map((sceneIndex) => { + state.sceneIndex = sceneIndex; + state.cameraIndex = undefined; + const scene = state.gltf.scenes[state.sceneIndex]; + if (scene !== undefined) { + scene.applyTransformHierarchy(state.gltf); + state.userCamera.fitViewToScene(state.gltf, state.sceneIndex); + } + }), + share(), + ); + + const statisticsUpdateObservable = merge( + sceneChangedObservable, + gltfLoaded, + ).pipe(map(() => view.gatherStatistics(state))); + + const cameraExportChangedObservable = uiModel.cameraValuesExport.pipe( + map(() => { + const camera = + state.cameraIndex === undefined + ? state.userCamera + : state.gltf.cameras[state.cameraIndex]; + return camera.getDescription(state.gltf); + }), + ); + + const downloadDataURL = (filename, dataURL) => { + const element = document.createElement("a"); + element.setAttribute("href", dataURL); + element.setAttribute("download", filename); + element.style.display = "none"; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + }; + + cameraExportChangedObservable.subscribe((cameraDesc) => { + const gltf = JSON.stringify(cameraDesc, undefined, 4); + const dataURL = "data:text/plain;charset=utf-8," + encodeURIComponent(gltf); + downloadDataURL("camera.gltf", dataURL); + }); + + uiModel.captureCanvas.subscribe(() => { + view.renderFrame(state, canvas.width, canvas.height); + const dataURL = canvas.toDataURL(); + downloadDataURL("capture.png", dataURL); + }); + + // Only redraw glTF view upon user inputs, or when an animation is playing. + let redraw = false; + const listenForRedraw = (stream) => stream.subscribe(() => (redraw = true)); + + uiModel.scene.subscribe( + (scene) => (state.sceneIndex = scene !== -1 ? scene : undefined), + ); + listenForRedraw(uiModel.scene); + + uiModel.camera.subscribe( + (camera) => (state.cameraIndex = camera !== -1 ? camera : undefined), + ); + listenForRedraw(uiModel.camera); + + uiModel.variant.subscribe((variant) => (state.variant = variant)); + listenForRedraw(uiModel.variant); + + uiModel.tonemap.subscribe( + (tonemap) => (state.renderingParameters.toneMap = tonemap), + ); + listenForRedraw(uiModel.tonemap); + + uiModel.debugchannel.subscribe( + (debugchannel) => (state.renderingParameters.debugOutput = debugchannel), + ); + listenForRedraw(uiModel.debugchannel); + + uiModel.skinningEnabled.subscribe( + (skinningEnabled) => (state.renderingParameters.skinning = skinningEnabled), + ); + listenForRedraw(uiModel.skinningEnabled); + + uiModel.exposure.subscribe( + (exposure) => + (state.renderingParameters.exposure = 1.0 / Math.pow(2.0, exposure)), + ); + listenForRedraw(uiModel.exposure); + + uiModel.morphingEnabled.subscribe( + (morphingEnabled) => (state.renderingParameters.morphing = morphingEnabled), + ); + listenForRedraw(uiModel.morphingEnabled); + + uiModel.clearcoatEnabled.subscribe( + (clearcoatEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_clearcoat = + clearcoatEnabled), + ); + listenForRedraw(uiModel.clearcoatEnabled); + + uiModel.sheenEnabled.subscribe( + (sheenEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_sheen = + sheenEnabled), + ); + listenForRedraw(uiModel.sheenEnabled); + + uiModel.transmissionEnabled.subscribe( + (transmissionEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_transmission = + transmissionEnabled), + ); + listenForRedraw(uiModel.transmissionEnabled); + + uiModel.volumeEnabled.subscribe( + (volumeEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_volume = + volumeEnabled), + ); + listenForRedraw(uiModel.volumeEnabled); + + uiModel.iorEnabled.subscribe( + (iorEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_ior = + iorEnabled), + ); + listenForRedraw(uiModel.iorEnabled); + + uiModel.iridescenceEnabled.subscribe( + (iridescenceEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_iridescence = + iridescenceEnabled), + ); + listenForRedraw(uiModel.iridescenceEnabled); + + uiModel.anisotropyEnabled.subscribe( + (anisotropyEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_anisotropy = + anisotropyEnabled), + ); + listenForRedraw(uiModel.anisotropyEnabled); + + uiModel.dispersionEnabled.subscribe( + (dispersionEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_dispersion = + dispersionEnabled), + ); + listenForRedraw(uiModel.dispersionEnabled); + + uiModel.specularEnabled.subscribe( + (specularEnabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_specular = + specularEnabled), + ); + listenForRedraw(uiModel.specularEnabled); + + uiModel.emissiveStrengthEnabled.subscribe( + (enabled) => + (state.renderingParameters.enabledExtensions.KHR_materials_emissive_strength = + enabled), + ); + listenForRedraw(uiModel.emissiveStrengthEnabled); + + uiModel.iblEnabled.subscribe( + (iblEnabled) => (state.renderingParameters.useIBL = iblEnabled), + ); + listenForRedraw(uiModel.iblEnabled); + + uiModel.iblIntensity.subscribe( + (iblIntensity) => + (state.renderingParameters.iblIntensity = Math.pow(10, iblIntensity)), + ); + listenForRedraw(uiModel.iblIntensity); + + uiModel.renderEnvEnabled.subscribe( + (renderEnvEnabled) => + (state.renderingParameters.renderEnvironmentMap = renderEnvEnabled), + ); + listenForRedraw(uiModel.renderEnvEnabled); + + uiModel.blurEnvEnabled.subscribe( + (blurEnvEnabled) => + (state.renderingParameters.blurEnvironmentMap = blurEnvEnabled), + ); + listenForRedraw(uiModel.blurEnvEnabled); + + uiModel.punctualLightsEnabled.subscribe( + (punctualLightsEnabled) => + (state.renderingParameters.usePunctual = punctualLightsEnabled), + ); + listenForRedraw(uiModel.punctualLightsEnabled); + + uiModel.environmentRotation.subscribe((environmentRotation) => { + switch (environmentRotation) { + case "+Z": + state.renderingParameters.environmentRotation = 90.0; + break; + case "-X": + state.renderingParameters.environmentRotation = 180.0; + break; + case "-Z": + state.renderingParameters.environmentRotation = 270.0; + break; + case "+X": + state.renderingParameters.environmentRotation = 0.0; + break; + } + }); + listenForRedraw(uiModel.environmentRotation); + + uiModel.clearColor.subscribe( + (clearColor) => (state.renderingParameters.clearColor = clearColor), + ); + listenForRedraw(uiModel.clearColor); + + uiModel.animationPlay.subscribe((animationPlay) => { + if (animationPlay) { + state.animationTimer.unpause(); + } else { + state.animationTimer.pause(); + } + }); + + uiModel.activeAnimations.subscribe( + (animations) => (state.animationIndices = animations), + ); + listenForRedraw(uiModel.activeAnimations); + + uiModel.hdr.subscribe((hdrFile) => { + resourceLoader.loadEnvironment(hdrFile).then((environment) => { + state.environment = environment; + // We need to wait until the environment is loaded to redraw + redraw = true; }); - listenForRedraw(uiModel.pan); + }); + + uiModel.attachGltfLoaded(gltfLoaded); + uiModel.updateStatistics(statisticsUpdateObservable); + const sceneChangedStateObservable = uiModel.scene.pipe(map(() => state)); + uiModel.attachCameraChangeObservable(sceneChangedStateObservable); + + uiModel.orbit.subscribe((orbit) => { + if (state.cameraIndex === undefined) { + state.userCamera.orbit(orbit.deltaPhi, orbit.deltaTheta); + } + }); + listenForRedraw(uiModel.orbit); + + uiModel.pan.subscribe((pan) => { + if (state.cameraIndex === undefined) { + state.userCamera.pan(pan.deltaX, -pan.deltaY); + } + }); + listenForRedraw(uiModel.pan); + + uiModel.zoom.subscribe((zoom) => { + if (state.cameraIndex === undefined) { + state.userCamera.zoomBy(zoom.deltaZoom); + } + }); + listenForRedraw(uiModel.zoom); + + // configure the animation loop + const past = {}; + const update = () => { + const devicePixelRatio = window.devicePixelRatio || 1; + + // set the size of the drawingBuffer based on the size it's displayed. + canvas.width = Math.floor(canvas.clientWidth * devicePixelRatio); + canvas.height = Math.floor(canvas.clientHeight * devicePixelRatio); + redraw |= !state.animationTimer.paused && state.animationIndices.length > 0; + redraw |= past.width != canvas.width || past.height != canvas.height; + past.width = canvas.width; + past.height = canvas.height; + + if (redraw) { + view.renderFrame(state, canvas.width, canvas.height); + redraw = false; + } - uiModel.zoom.subscribe( zoom => { - if (state.cameraIndex === undefined) { - state.userCamera.zoomBy(zoom.deltaZoom); - } - }); - listenForRedraw(uiModel.zoom); - - // configure the animation loop - const past = {}; - const update = () => { - const devicePixelRatio = window.devicePixelRatio || 1; - - // set the size of the drawingBuffer based on the size it's displayed. - canvas.width = Math.floor(canvas.clientWidth * devicePixelRatio); - canvas.height = Math.floor(canvas.clientHeight * devicePixelRatio); - redraw |= !state.animationTimer.paused && state.animationIndices.length > 0; - redraw |= past.width != canvas.width || past.height != canvas.height; - past.width = canvas.width; - past.height = canvas.height; - - if (redraw) { - view.renderFrame(state, canvas.width, canvas.height); - redraw = false; - } - - window.requestAnimationFrame(update); - }; - - // After this start executing animation loop. window.requestAnimationFrame(update); + }; + + // After this start executing animation loop. + window.requestAnimationFrame(update); }; diff --git a/app_web/src/model_path_provider.js b/app_web/src/model_path_provider.js index d85dea19..0bb42d6e 100644 --- a/app_web/src/model_path_provider.js +++ b/app_web/src/model_path_provider.js @@ -1,17 +1,15 @@ -import path from 'path'; - export class GltfModelPathProvider { - constructor(modelIndexerPath, ignoredVariants = ["glTF-Embedded"]) + constructor(url, ignoredVariants = ["glTF-Embedded"]) { - this.modelIndexerPath = modelIndexerPath; + this.url = url; this.ignoredVariants = ignoredVariants; this.modelsDictionary = undefined; } async initialize() { - const response = await fetch(this.modelIndexerPath); + const response = await fetch(this.url + "/Models/model-index.json"); this.populateDictionary(await response.json()); } @@ -27,7 +25,7 @@ export class GltfModelPathProvider populateDictionary(modelIndexer) { - const modelsFolder = path.dirname(this.modelIndexerPath); + const modelsFolder = this.url + "/Models"; this.modelsDictionary = {}; for (const entry of modelIndexer) { @@ -46,8 +44,7 @@ export class GltfModelPathProvider } const fileName = entry.variants[variant]; - const modelPath = path.join(modelsFolder, entry.name, variant, fileName); - variants[variant] = modelPath; + variants[variant] = modelsFolder + "/" + entry.name + "/" + variant + "/" + fileName; } this.modelsDictionary[entry.name] = variants; } From 5ff846c7013d74b120c4080f6d32e019de4a4578 Mon Sep 17 00:00:00 2001 From: Jim Eckerlein Date: Wed, 10 Apr 2024 15:55:15 +0200 Subject: [PATCH 2/7] Remove assets submodule --- .gitmodules | 3 --- assets/models | 1 - 2 files changed, 4 deletions(-) delete mode 160000 assets/models diff --git a/.gitmodules b/.gitmodules index 616e0e5e..9656f223 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "assets/models"] - path = assets/models - url = https://github.com/KhronosGroup/glTF-Sample-Assets.git [submodule "assets/environments"] path = assets/environments url = https://github.com/KhronosGroup/glTF-Sample-Environments.git diff --git a/assets/models b/assets/models deleted file mode 160000 index 8ae63f17..00000000 --- a/assets/models +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8ae63f170dbb46778f63cb082e8f735c86a2c2ea From 007787e5ea3dd4adb450e289309a3c73aa37cc47 Mon Sep 17 00:00:00 2001 From: Jim Eckerlein Date: Wed, 10 Apr 2024 15:55:49 +0200 Subject: [PATCH 3/7] Fix wrong argument --- app_web/src/main.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app_web/src/main.js b/app_web/src/main.js index 38f1de25..a5ee340a 100644 --- a/app_web/src/main.js +++ b/app_web/src/main.js @@ -20,10 +20,7 @@ export default async () => { const state = view.createState(); state.renderingParameters.useDirectionalLightsWithDisabledIBL = true; - const pathProvider = new GltfModelPathProvider( - "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main", - "Models/model-index.json", - ); + const pathProvider = new GltfModelPathProvider("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main"); await pathProvider.initialize(); const environmentPaths = fillEnvironmentWithPaths( { From 223693c7c0943ccf9dd9b13ac5f059c623fc0ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Wed, 19 Jun 2024 12:08:14 +0200 Subject: [PATCH 4/7] Fix merge --- app_web/src/main.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/app_web/src/main.js b/app_web/src/main.js index 33af611b..ed12f496 100644 --- a/app_web/src/main.js +++ b/app_web/src/main.js @@ -1,5 +1,3 @@ -import { GltfView } from "gltf-viewer-source"; - import { GltfView } from '@khronosgroup/gltf-viewer'; import { UIModel } from './logic/uimodel.js'; From c38f0752bb5b6b94e02743d4b00019d477d20243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Wed, 19 Jun 2024 12:10:18 +0200 Subject: [PATCH 5/7] Cleanup dependencies --- app_web/package.json | 2 -- app_web/rollup.config.js | 5 ----- 2 files changed, 7 deletions(-) diff --git a/app_web/package.json b/app_web/package.json index 041db29f..4a85b5e8 100644 --- a/app_web/package.json +++ b/app_web/package.json @@ -39,7 +39,6 @@ }, "devDependencies": { "@rollup/plugin-commonjs": "^26.0.1", - "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.7", "@rollup/plugin-wasm": "^6.2.2", @@ -48,7 +47,6 @@ "rollup": "^4.18.0", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-glslify": "^1.3.1", - "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-scss": "^3.0.0", "sass": "^1.77.5", "serve": "^14.2.3" diff --git a/app_web/rollup.config.js b/app_web/rollup.config.js index df03775c..6cb095e0 100644 --- a/app_web/rollup.config.js +++ b/app_web/rollup.config.js @@ -1,11 +1,9 @@ import glslify from 'rollup-plugin-glslify'; import resolve from '@rollup/plugin-node-resolve'; -import builtins from 'rollup-plugin-node-builtins'; import scss from 'rollup-plugin-scss'; import commonjs from '@rollup/plugin-commonjs'; import copy from 'rollup-plugin-copy'; import replace from '@rollup/plugin-replace'; -import json from '@rollup/plugin-json'; import {wasm} from "@rollup/plugin-wasm"; export default { @@ -21,7 +19,6 @@ export default { ], plugins: [ wasm(), - json(), // To include model json file glslify({ include: ['../source/Renderer/shaders/*', '../source/shaders/*'], compress: false @@ -31,12 +28,10 @@ export default { preferBuiltins: true, dedupe: ['gl-matrix', 'jpeg-js', 'fast-png'] }), - builtins(), // Needed for loading assets scss(), // Version 4 is not working copy({ targets: [ { src: ["index.html", "main.js"], dest: "dist/" }, - { src: ["../assets/models/Models", "!../asset/models/.git"], dest: "dist/assets/models" }, { src: ["../assets/environments/*.hdr", "../assets/environments/*.jpg", "!../asset/environments/.git"], dest: "dist/assets/environments" }, { src: ["../assets/images"], dest: "dist/assets" }, { src: ["../assets/ui"], dest: "dist/assets" }, From 8a32b48c0d01f15f4376f2498705048f9370a389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Wed, 10 Jul 2024 16:37:18 +0200 Subject: [PATCH 6/7] Fix merge --- app_web/src/main.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app_web/src/main.js b/app_web/src/main.js index ed12f496..46b9ccf5 100644 --- a/app_web/src/main.js +++ b/app_web/src/main.js @@ -364,6 +364,8 @@ export default async () => { }); listenForRedraw(uiModel.zoom); + listenForRedraw(gltfLoaded); + // configure the animation loop const past = {}; const update = () => { From 98207e5eadc019ce44cb65e45ffcdeb3707734e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Wed, 10 Jul 2024 16:47:39 +0200 Subject: [PATCH 7/7] Format file --- app_web/src/main.js | 85 ++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/app_web/src/main.js b/app_web/src/main.js index 46b9ccf5..a586f8ec 100644 --- a/app_web/src/main.js +++ b/app_web/src/main.js @@ -1,10 +1,13 @@ -import { GltfView } from '@khronosgroup/gltf-viewer'; +import { GltfView } from "@khronosgroup/gltf-viewer"; -import { UIModel } from './logic/uimodel.js'; -import { app } from './ui/ui.js'; -import { EMPTY, from, merge } from 'rxjs'; -import { mergeMap, map, share, catchError } from 'rxjs/operators'; -import { GltfModelPathProvider, fillEnvironmentWithPaths } from './model_path_provider.js'; +import { UIModel } from "./logic/uimodel.js"; +import { app } from "./ui/ui.js"; +import { EMPTY, from, merge } from "rxjs"; +import { mergeMap, map, share, catchError } from "rxjs/operators"; +import { + GltfModelPathProvider, + fillEnvironmentWithPaths, +} from "./model_path_provider.js"; export default async () => { const canvas = document.getElementById("canvas"); @@ -17,7 +20,9 @@ export default async () => { const state = view.createState(); state.renderingParameters.useDirectionalLightsWithDisabledIBL = true; - const pathProvider = new GltfModelPathProvider("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main"); + const pathProvider = new GltfModelPathProvider( + "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main" + ); await pathProvider.initialize(); const environmentPaths = fillEnvironmentWithPaths( { @@ -33,7 +38,7 @@ export default async () => { Colorful_Studio: "Colorful Studio", Wide_Street: "Wide Street", }, - "assets/environments/", + "assets/environments/" ); const uiModel = new UIModel(app, pathProvider, environmentPaths); @@ -82,7 +87,7 @@ export default async () => { uiModel.exitLoadingState(); return state; - }), + }) ); }), catchError((error) => { @@ -90,16 +95,16 @@ export default async () => { uiModel.exitLoadingState(); return EMPTY; }), - share(), + share() ); // Disable all animations which are not disjoint to the current selection of animations. uiModel.disabledAnimations( uiModel.activeAnimations.pipe( map((animationIndices) => - state.gltf.nonDisjointAnimations(animationIndices), - ), - ), + state.gltf.nonDisjointAnimations(animationIndices) + ) + ) ); const sceneChangedObservable = uiModel.scene.pipe( @@ -112,12 +117,12 @@ export default async () => { state.userCamera.fitViewToScene(state.gltf, state.sceneIndex); } }), - share(), + share() ); const statisticsUpdateObservable = merge( sceneChangedObservable, - gltfLoaded, + gltfLoaded ).pipe(map(() => view.gatherStatistics(state))); const cameraExportChangedObservable = uiModel.cameraValuesExport.pipe( @@ -127,7 +132,7 @@ export default async () => { ? state.userCamera : state.gltf.cameras[state.cameraIndex]; return camera.getDescription(state.gltf); - }), + }) ); const downloadDataURL = (filename, dataURL) => { @@ -157,12 +162,12 @@ export default async () => { const listenForRedraw = (stream) => stream.subscribe(() => (redraw = true)); uiModel.scene.subscribe( - (scene) => (state.sceneIndex = scene !== -1 ? scene : undefined), + (scene) => (state.sceneIndex = scene !== -1 ? scene : undefined) ); listenForRedraw(uiModel.scene); uiModel.camera.subscribe( - (camera) => (state.cameraIndex = camera !== -1 ? camera : undefined), + (camera) => (state.cameraIndex = camera !== -1 ? camera : undefined) ); listenForRedraw(uiModel.camera); @@ -170,127 +175,127 @@ export default async () => { listenForRedraw(uiModel.variant); uiModel.tonemap.subscribe( - (tonemap) => (state.renderingParameters.toneMap = tonemap), + (tonemap) => (state.renderingParameters.toneMap = tonemap) ); listenForRedraw(uiModel.tonemap); uiModel.debugchannel.subscribe( - (debugchannel) => (state.renderingParameters.debugOutput = debugchannel), + (debugchannel) => (state.renderingParameters.debugOutput = debugchannel) ); listenForRedraw(uiModel.debugchannel); uiModel.skinningEnabled.subscribe( - (skinningEnabled) => (state.renderingParameters.skinning = skinningEnabled), + (skinningEnabled) => (state.renderingParameters.skinning = skinningEnabled) ); listenForRedraw(uiModel.skinningEnabled); uiModel.exposure.subscribe( (exposure) => - (state.renderingParameters.exposure = 1.0 / Math.pow(2.0, exposure)), + (state.renderingParameters.exposure = 1.0 / Math.pow(2.0, exposure)) ); listenForRedraw(uiModel.exposure); uiModel.morphingEnabled.subscribe( - (morphingEnabled) => (state.renderingParameters.morphing = morphingEnabled), + (morphingEnabled) => (state.renderingParameters.morphing = morphingEnabled) ); listenForRedraw(uiModel.morphingEnabled); uiModel.clearcoatEnabled.subscribe( (clearcoatEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_clearcoat = - clearcoatEnabled), + clearcoatEnabled) ); listenForRedraw(uiModel.clearcoatEnabled); uiModel.sheenEnabled.subscribe( (sheenEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_sheen = - sheenEnabled), + sheenEnabled) ); listenForRedraw(uiModel.sheenEnabled); uiModel.transmissionEnabled.subscribe( (transmissionEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_transmission = - transmissionEnabled), + transmissionEnabled) ); listenForRedraw(uiModel.transmissionEnabled); uiModel.volumeEnabled.subscribe( (volumeEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_volume = - volumeEnabled), + volumeEnabled) ); listenForRedraw(uiModel.volumeEnabled); uiModel.iorEnabled.subscribe( (iorEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_ior = - iorEnabled), + iorEnabled) ); listenForRedraw(uiModel.iorEnabled); uiModel.iridescenceEnabled.subscribe( (iridescenceEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_iridescence = - iridescenceEnabled), + iridescenceEnabled) ); listenForRedraw(uiModel.iridescenceEnabled); uiModel.anisotropyEnabled.subscribe( (anisotropyEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_anisotropy = - anisotropyEnabled), + anisotropyEnabled) ); listenForRedraw(uiModel.anisotropyEnabled); uiModel.dispersionEnabled.subscribe( (dispersionEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_dispersion = - dispersionEnabled), + dispersionEnabled) ); listenForRedraw(uiModel.dispersionEnabled); uiModel.specularEnabled.subscribe( (specularEnabled) => (state.renderingParameters.enabledExtensions.KHR_materials_specular = - specularEnabled), + specularEnabled) ); listenForRedraw(uiModel.specularEnabled); uiModel.emissiveStrengthEnabled.subscribe( (enabled) => (state.renderingParameters.enabledExtensions.KHR_materials_emissive_strength = - enabled), + enabled) ); listenForRedraw(uiModel.emissiveStrengthEnabled); uiModel.iblEnabled.subscribe( - (iblEnabled) => (state.renderingParameters.useIBL = iblEnabled), + (iblEnabled) => (state.renderingParameters.useIBL = iblEnabled) ); listenForRedraw(uiModel.iblEnabled); uiModel.iblIntensity.subscribe( (iblIntensity) => - (state.renderingParameters.iblIntensity = Math.pow(10, iblIntensity)), + (state.renderingParameters.iblIntensity = Math.pow(10, iblIntensity)) ); listenForRedraw(uiModel.iblIntensity); uiModel.renderEnvEnabled.subscribe( (renderEnvEnabled) => - (state.renderingParameters.renderEnvironmentMap = renderEnvEnabled), + (state.renderingParameters.renderEnvironmentMap = renderEnvEnabled) ); listenForRedraw(uiModel.renderEnvEnabled); uiModel.blurEnvEnabled.subscribe( (blurEnvEnabled) => - (state.renderingParameters.blurEnvironmentMap = blurEnvEnabled), + (state.renderingParameters.blurEnvironmentMap = blurEnvEnabled) ); listenForRedraw(uiModel.blurEnvEnabled); uiModel.punctualLightsEnabled.subscribe( (punctualLightsEnabled) => - (state.renderingParameters.usePunctual = punctualLightsEnabled), + (state.renderingParameters.usePunctual = punctualLightsEnabled) ); listenForRedraw(uiModel.punctualLightsEnabled); @@ -313,7 +318,7 @@ export default async () => { listenForRedraw(uiModel.environmentRotation); uiModel.clearColor.subscribe( - (clearColor) => (state.renderingParameters.clearColor = clearColor), + (clearColor) => (state.renderingParameters.clearColor = clearColor) ); listenForRedraw(uiModel.clearColor); @@ -326,7 +331,7 @@ export default async () => { }); uiModel.activeAnimations.subscribe( - (animations) => (state.animationIndices = animations), + (animations) => (state.animationIndices = animations) ); listenForRedraw(uiModel.activeAnimations);