From e85bd4f9599772dad867559ba610b0daa6b7bc4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20P=2E?= Date: Wed, 14 Jan 2026 16:42:39 +0100 Subject: [PATCH] Restructure to use separate scenes Uses pseudo-router logic... --- .gitignore | 1 + assets/icons/section_z.png | Bin 0 -> 42819 bytes config.js | 18 +++-- css/app.css | 26 +++++++ index.html | 97 +----------------------- js/main.js | 21 ------ js/map.js | 11 ++- js/scene.js | 149 +++++++++++++++++-------------------- js/state.js | 4 +- scenes/salvador/index.html | 89 ++++++++++++++++++++++ scenes/salvador/index.js | 4 + scenes/ssgp/index.html | 89 ++++++++++++++++++++++ scenes/ssgp/index.js | 4 + 13 files changed, 307 insertions(+), 206 deletions(-) create mode 100755 assets/icons/section_z.png create mode 100644 css/app.css create mode 100644 scenes/salvador/index.html create mode 100644 scenes/salvador/index.js create mode 100644 scenes/ssgp/index.html create mode 100644 scenes/ssgp/index.js diff --git a/.gitignore b/.gitignore index 3968edc..0f13413 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.obj vendor/ +.vscode diff --git a/assets/icons/section_z.png b/assets/icons/section_z.png new file mode 100755 index 0000000000000000000000000000000000000000..0d6700df648c148e10da27944c67e60a02fdb123 GIT binary patch literal 42819 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

m`!=`u5J#|8iIAkpH8S5}$cz1So5KPE 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

Teatro San Salvador, Venezia

@@ -30,24 +32,28 @@ export const config = { { id : "salvador", label : "Teatro San Salvador, Venezia", + uri : `${BASE_URI}/scenes/salvador/`, popup: theater1Popup, coords: [45.4363, 12.3352], model: "teatro_san_salvador_20250926.gltf", - pano: "pano/defsky-grass.jpg", + //pano: `${BASE_URI}/assets/pano/defsky-grass.jpg`, + pano: `pano/defsky-grass.jpg`, }, { id : "ssgp", label : "Teatro Santi Giovanni e Paolo, Venezia", + uri : `${BASE_URI}/scenes/ssgp/`, popup: theater2Popup, coords: [45.4401, 12.3408], - model: "SSGP.glb", - pano: "pano/defsky-grass.jpg", + model: `SSGP.glb`, + //pano: `${BASE_URI}/assets/pano/defsky-grass.jpg`, + pano: `pano/defsky-grass.jpg`, } ], map : { - center: [43.570833, 12.140278], - initialZoom : 8, + center: [45.30833, 12.240278], + initialZoom : 12, minZoom : 6, - maxZoom : 16 + maxZoom : 18 } } diff --git a/css/app.css b/css/app.css new file mode 100644 index 0000000..be5ad61 --- /dev/null +++ b/css/app.css @@ -0,0 +1,26 @@ +body { + height: 100vh; +} +.c-hand { + cursor: pointer; +} +input[type="checkbox"] { + cursor: pointer; +} +#clipper-bar .btn { + background-repeat: no-repeat; + background-position: center; + background-size: 80%; +} +#map { + height: 100%; +} +#clipX { + background-image: url('/a/scaenae/assets/icons/section_x.png'); +} +#clipY { + background-image: url('/a/scaenae/assets/icons/section_y.png'); +} +#clipZ { + background-image: url('/a/scaenae/assets/icons/section_z.png'); +} \ No newline at end of file diff --git a/index.html b/index.html index 6c166ea..0e3bc2c 100644 --- a/index.html +++ b/index.html @@ -27,10 +27,10 @@ - + - + @@ -39,6 +39,7 @@ + @@ -46,103 +47,13 @@ - - - -
-
-
- - - - - - - - - -
- Sezionamento - - - -
- - - -
- - - -
Disabilitare le ombre può migliorare le prestazioni
- -
- -
-
- - - +
diff --git a/js/main.js b/js/main.js index f889089..aa13d0c 100644 --- a/js/main.js +++ b/js/main.js @@ -1,5 +1,4 @@ import Map from "./map.js"; -import Scene from "./scene.js"; /* Main js entry for ATON web-app @@ -7,30 +6,10 @@ import Scene from "./scene.js"; // Realize our app let APP = ATON.App.realize(); -APP.UI = {}; - -/** - * - * @param {String} triggerSelector - Usually, the close modal trigger element(s) selector - */ -APP.UI.pauseAudio = function(triggerSelector) { - // What if more than one audio element is playing? - const audio = document.querySelector('audio'); - document.querySelectorAll(triggerSelector).forEach(el => { - el.addEventListener('click', () => audio.pause()); - }); - document.querySelector('.modal').addEventListener('blur', () => { - audio.pause(); - }); -} - - // APP.setup() is required for web-app initialization // You can place here UI setup (HTML), events handling, etc. APP.setup = ()=>{ Map.init('map'); - APP.UI.pauseAudio('[data-bs-dismiss="modal"'); - //APP.UI.showClipper('#clipper'); }; /* If you plan to use an update routine (executed continuously), you can place its logic here. diff --git a/js/map.js b/js/map.js index 05db3cc..1addfcc 100644 --- a/js/map.js +++ b/js/map.js @@ -1,7 +1,6 @@ // Global Leaflet and ATON import {config} from '../config.js'; -import Scene from './scene.js'; import AppState from './state.js'; const Map = {}; @@ -29,7 +28,7 @@ Map.init = function(mapContainerId) { const popup = this.domParser.parseFromString(marker.popup, 'text/html') .querySelector('div'); popup.querySelector('button').onclick = () => { - Scene.openScene(marker); + this.goToScene(marker.uri); map.getContainer().classList.toggle('d-none'); }; @@ -41,4 +40,12 @@ Map.init = function(mapContainerId) { AppState.map = map; } +/** + * + * @param {String} uri The scene's absolute URI (from config) + */ +Map.goToScene = function (uri) { + location.href = uri; +} + export default Map; \ No newline at end of file diff --git a/js/scene.js b/js/scene.js index 5789467..1ad4a5d 100644 --- a/js/scene.js +++ b/js/scene.js @@ -8,6 +8,20 @@ const Scene = {}; Scene.UI = {}; Scene.UI.domParser = new DOMParser; +/** + * + * @param {String} triggerSelector - Usually, the close modal trigger element(s) selector + */ +Scene.UI.pauseAudio = function(triggerSelector) { + // What if more than one audio element is playing? + const audio = document.querySelector('audio'); + document.querySelectorAll(triggerSelector).forEach(el => { + el.addEventListener('click', () => audio.pause()); + }); + document.querySelector('.modal').addEventListener('blur', () => { + audio.pause(); + }); +} /** * Resets the UI state (essentially hides the clipper toolbar if visible...) @@ -32,10 +46,11 @@ Scene.UI.toggleClipper = function(triggerSelector, targetSelector) { () => { toolbar.classList.toggle('d-none'); const aoCurrentState = AppState.ambientOcclusion; - if (!AppState.clipping.enabled) { + + if (!toolbar.classList.contains('d-none')) { AppState.clipping.enabled = true; - if (AppState.clipping.controls) AppState.clipping.controls.enabled = true; + //if (AppState.clipping.controls) AppState.clipping.controls.enabled = true; Scene.toggleAmbientOcclusion(false); @@ -46,7 +61,6 @@ Scene.UI.toggleClipper = function(triggerSelector, targetSelector) { trigger.className += ' border border-2 border-white'; toolbar.addEventListener('click', event => { - console.log('Clipping target:', event.target); if (event.target.id === 'clipX') { // Clip along X... Scene.addClippingPlane('x', -1); @@ -80,7 +94,6 @@ Scene.UI.toggleClipper = function(triggerSelector, targetSelector) { } }); } else { - AppState.clipping.enabled = false; Scene.resetClipping(); let noBorder = trigger.className.replace(/ border.*$/g, ''); trigger.className = noBorder; @@ -155,37 +168,40 @@ Scene.createClippingPlaneMesh = function (boundingSphere) { /** * * @param {THREE.Mesh} planeMesh + * @param {THREE.ArrowHelper} arrowHelper * @param {String} axis */ Scene.dragClipper = function(planeMesh, axis) { const controls = new THREE.DragControls( [planeMesh], - AppState.camera, - AppState.renderer.domElement, + ATON.Nav._camera, + ATON._renderer.domElement, ); const startPosition = new THREE.Vector3(); // Only move along the selected axis (exlude the others) const excludedAxes = ['x', 'y', 'z'].filter(a => a != axis); - controls.addEventListener('dragstart', function (event) { - startPosition.copy(event.object.position); - ATON.Nav.setUserControl(false); - }); + if (AppState.clipping.enabled && AppState.clipping.vector) { + controls.addEventListener('dragstart', function (event) { + startPosition.copy(event.object.position); + ATON.Nav.setUserControl(false); + }); - controls.addEventListener('drag', function(event) { - const point = event.object.position; - Scene.updateClipper(AppState.clipping.vector, point); - for (const a of excludedAxes) { - event.object.position[a] = startPosition[a]; - } - }); + controls.addEventListener('drag', function(event) { + const point = event.object.position; + Scene.updateClipper(AppState.clipping.vector, point); + for (const a of excludedAxes) { + event.object.position[a] = startPosition[a]; + } + }); - controls.addEventListener('dragend', function (event) { - ATON.Nav.setUserControl(true); - }); + controls.addEventListener('dragend', function (event) { + ATON.Nav.setUserControl(true); + }); - AppState.clipping.controls = controls; + AppState.clipping.controls = controls; + } } /** @@ -221,6 +237,7 @@ Scene.addClippingPlane = function(axis, orientation = -1) { * @param {?THREE.Vector3} point - The queried scene point */ Scene.activateClipper = function(vector, axis, point = null) { + ATON.enableClipPlanes(); Scene.updateClipper(vector, point); Scene.dragClipper(AppState.clipping.helper, axis); } @@ -231,22 +248,25 @@ Scene.activateClipper = function(vector, axis, point = null) { * @param {THREE.Vector3} point */ Scene.updateClipper = function(vector, point) { - // Normal of the clipping plane along the Y axis facing down - const normal = new THREE.Vector3(...vector).normalize(); - const plane = AppState.clipping.plane ?? ATON.addClipPlane(normal, point); - // Add a visible plane helper for the clipping plane - const visiblePlane = AppState.clipping.helper ?? Scene.createClippingPlaneMesh(AppState.clipping.boundingSphere); + // Useless guard... + if (vector) { + // Normal of the clipping plane along the axis facing down + const normal = new THREE.Vector3(...vector).normalize(); + const plane = AppState.clipping.plane ?? ATON.addClipPlane(normal, point); + // Add a visible plane helper for the clipping plane + const visiblePlane = AppState.clipping.helper ?? Scene.createClippingPlaneMesh(AppState.clipping.boundingSphere); - if (!AppState.clipping.helper) { - AppState.root.add(visiblePlane); - AppState.clipping.helper = visiblePlane; - } + if (!AppState.clipping.helper) { + AppState.root.add(visiblePlane); + AppState.clipping.helper = visiblePlane; + } - visiblePlane.position.copy(point); - visiblePlane.lookAt(point.clone().add(normal)); + visiblePlane.position.copy(point); + visiblePlane.lookAt(point.clone().add(normal)); - plane.setFromNormalAndCoplanarPoint(normal, point); - AppState.clipping.plane = plane; + plane.setFromNormalAndCoplanarPoint(normal, point); + AppState.clipping.plane = plane; + } } /** @@ -402,7 +422,7 @@ Scene.init = function() { ATON.UI.addBasicEvents(); ATON.UI.init(); // All assets for this app are stored here - ATON.setPathCollection('./assets/'); + ATON.setPathCollection('/a/scaenae/assets/'); // Initial light direction ATON.setMainLightDirection(new THREE.Vector3(0.2,-0.3,-0.7)); ATON.toggleShadows(true); @@ -416,37 +436,21 @@ Scene.init = function() { ATON.Nav.setUserControl(true); } -/** - * @param {String} btnId - The back-to-map button id - */ -Scene.closeScene = function() { - const scene = document.querySelector('#scene'); - scene.classList.toggle('d-none'); - - const canvas = ATON._renderer?.domElement; - Scene.resetClipping(); - AppState.root.clear(); - // Ensure GPU resources are freed... - ATON.renderPause(); - AppState.renderer.dispose(); - ATON._renderer.dispose(); - ATON.Nav._camera = undefined; - - Scene.UI.reset(); - document.querySelector('#map').classList.toggle('d-none'); - AppState.map.invalidateSize(); - AppState.resetSceneState(AppState.map); - // Remove ATON's canvas from the DOM - if (canvas && canvas.parentElement) { - canvas.parentElement.removeChild(canvas); - } -} Scene.resetClipping = function () { - AppState.clipping.controls?.dispose(); - AppState.clipping.controls = null; - ATON.disableClipPlanes(); + + console.warn('Resetting clipping!!'); + AppState.clipping.enabled = false; + ATON.disableClipPlanes(); + AppState.clipping.controls.deactivate(); + // Manually remove event listeners from DragControls!! + AppState.renderer.domElement.removeEventListener( 'pointermove', AppState.clipping.controls.onPointerMove ); + AppState.renderer.domElement.removeEventListener( 'pointerdown', AppState.clipping.controls.onPointerDown ); + AppState.renderer.domElement.removeEventListener( 'pointerup', AppState.clipping.controls.onPointerCancel ); + AppState.renderer.domElement.removeEventListener( 'pointerleave', AppState.clipping.controls.onPointerCancel ) + AppState.clipping.controls = null; + AppState.clipping.helper.removeFromParent(); AppState.root.remove(AppState.clipping.helper); AppState.clipping.helper = null; AppState.clipping.plane = null; @@ -458,27 +462,10 @@ Scene.resetClipping = function () { * @param {Object} marker - The marker object from config */ Scene.openScene = function(marker) { - //let canvas = document.querySelector('canvas'); - let scene = document.querySelector('#scene'); - Scene.init(); - // Button to go back to the map... - const btn = document.querySelector('#back'); - btn.addEventListener('click', () => { - Scene.closeScene('back'); - }); - Scene.UI.toggleClipper('#clipper', '#clipper-bar'); - scene.classList.toggle('d-none'); - ATON.renderResume(); - - if (!AppState.scenes.find(s => s.id === marker.id)) { - const newScene = {id: marker.id, active: false, current: true}; - AppState.scenes.push(newScene); - } - // Load 3D model then let mainNode = ATON.createSceneNode(marker.label); mainNode.load(marker.model); @@ -501,8 +488,6 @@ Scene.openScene = function(marker) { AppState.root = ATON.getRootScene(); // ATON.Node.getBound() returns a THREE.Sphere object AppState.clipping.boundingSphere = mainNode.getBound(); - - console.log(ATON.Nav._camera); } export default Scene; \ No newline at end of file diff --git a/js/state.js b/js/state.js index 1c4e00d..c4e6c0c 100644 --- a/js/state.js +++ b/js/state.js @@ -8,7 +8,6 @@ let AppState = { initialRotation: null, camera: null, renderer: null, - scenes : [], ambientOcclusion : true, shadows : true, lightProbe : false, @@ -19,6 +18,7 @@ let AppState = { controls: null, onDrag: null, helper : null, + arrow : null, boundingSphere: null, listeners: { button: false, @@ -39,7 +39,6 @@ let AppState = { initialRotation: null, camera: null, renderer: null, - scenes : [], ambientOcclusion : true, shadows : true, lightProbe : false, @@ -50,6 +49,7 @@ let AppState = { controls: null, onDrag: null, helper : null, + arrow : null, boundingSphere: null, listeners: { button: false, diff --git a/scenes/salvador/index.html b/scenes/salvador/index.html new file mode 100644 index 0000000..18b0938 --- /dev/null +++ b/scenes/salvador/index.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SCAENE + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ Sezionamento + + + +
+ + + +
+ + + +
Disabilitare le ombre può migliorare le prestazioni
+ +
+ +
+ diff --git a/scenes/salvador/index.js b/scenes/salvador/index.js new file mode 100644 index 0000000..12bb985 --- /dev/null +++ b/scenes/salvador/index.js @@ -0,0 +1,4 @@ +import Scene from "../../js/scene.js"; +import { config } from "../../config.js"; + +Scene.openScene(config.markers.find(m => m.id === 'salvador')); \ No newline at end of file diff --git a/scenes/ssgp/index.html b/scenes/ssgp/index.html new file mode 100644 index 0000000..18b0938 --- /dev/null +++ b/scenes/ssgp/index.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SCAENE + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ Sezionamento + + + +
+ + + +
+ + + +
Disabilitare le ombre può migliorare le prestazioni
+ +
+ +
+ diff --git a/scenes/ssgp/index.js b/scenes/ssgp/index.js new file mode 100644 index 0000000..01809df --- /dev/null +++ b/scenes/ssgp/index.js @@ -0,0 +1,4 @@ +import Scene from "../../js/scene.js"; +import { config } from "../../config.js"; + +Scene.openScene(config.markers.find(m => m.id === 'ssgp')); \ No newline at end of file