diff --git a/public/index.html b/public/index.html index e254a13e765f22c80ca4ab8a03c7a4265df658ba..59d1326120502fe72468c136e2775fdfb0246fe6 100644 --- a/public/index.html +++ b/public/index.html @@ -2,188 +2,100 @@ <html lang="de"> <head> <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>GeoVis AR Projekt</title> - <style> body { margin: 0; font-family: Arial, sans-serif; background-color: #f0f0f0; color: #333; - display: flex; - justify-content: center; - align-items: center; height: 100vh; - background-image: url('https://www.hft-stuttgart.de/fileadmin/Dateien/Hochschule/-_R_Juergen_Pollak_HFT_18.04.18-0091.jpg'); - background-size: cover; - background-position: center; + overflow: hidden; } .container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); text-align: center; - background-color: rgba(0, 0, 0, 0.5); - padding: 50px; - border-radius: 10px; + background: rgba(0, 0, 0, 0.6); color: white; - max-width: 80%; - box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.5); - } - - h1 { - font-size: 3em; - margin-bottom: 20px; - } - - p { - font-size: 1.2em; - margin-bottom: 30px; + padding: 20px; + border-radius: 10px; } button { background-color: #4CAF50; color: white; - font-size: 1.5em; - padding: 15px 30px; + padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; - transition: background-color 0.3s; - margin: 10px; - } - - button:hover { - background-color: #45a049; - } - - button:active { - background-color: #387a39; - } - - .menu-bar { - position: fixed; - top: 0; - left: 0; - right: 0; - display: flex; - justify-content: center; - background-color: rgba(0, 0, 0, 0.7); - padding: 10px; - z-index: 10; - } - - .menu-bar button { - background-color: #2196F3; - } - - .menu-bar button:hover { - background-color: #1E88E5; } </style> - - <!-- three.js --> <script src="https://unpkg.com/three@0.126.0/build/three.js"></script> <script src="https://unpkg.com/three@0.126.0/examples/js/loaders/GLTFLoader.js"></script> </head> <body> - <!-- Menüleiste --> - <div class="menu-bar"> - <button onclick="selectModel('car')">Auto</button> - <button onclick="selectModel('lamp')">Laterne</button> - </div> - <div class="container"> <h1>GeoVis AR Projekt</h1> - <p>Mit Augmented Reality können Sie ihrer Fantasie freien Lauf lassen und ihre Stadt interaktiv gestalten!</p> - <button onclick="activateXR()">Start City Planning</button> + <p>Starte AR, um dein Menü zu sehen!</p> + <button onclick="activateXR()">Start AR</button> </div> <script> - let selectedModel = 'car'; // Standardmodell - - function selectModel(model) { - selectedModel = model; - console.log(`Ausgewähltes Modell: ${model}`); - } + let menu; // Menü-Objekt async function activateXR() { - document.querySelector('.container').style.display = 'none'; // Startseite ausblenden - const canvas = document.createElement("canvas"); - document.body.appendChild(canvas); - const gl = canvas.getContext("webgl", {xrCompatible: true}); - - const scene = new THREE.Scene(); - - const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3); - directionalLight.position.set(10, 15, 10); - scene.add(directionalLight); + // UI ausblenden + document.querySelector('.container').style.display = 'none'; - const renderer = new THREE.WebGLRenderer({ - alpha: true, - preserveDrawingBuffer: true, - canvas: canvas, - context: gl - }); + // WebGL-Renderer erstellen + const canvas = document.createElement('canvas'); + document.body.appendChild(canvas); + const gl = canvas.getContext('webgl', { xrCompatible: true }); + const renderer = new THREE.WebGLRenderer({ alpha: true, canvas, context: gl }); renderer.autoClear = false; + // Szene und Kamera + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(); camera.matrixAutoUpdate = false; - const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']}); - session.updateRenderState({ - baseLayer: new XRWebGLLayer(session, gl) - }); - - const referenceSpace = await session.requestReferenceSpace('local'); - const viewerSpace = await session.requestReferenceSpace('viewer'); - const hitTestSource = await session.requestHitTestSource({ space: viewerSpace }); + // Licht hinzufügen + const light = new THREE.DirectionalLight(0xffffff, 1); + light.position.set(10, 10, 10); + scene.add(light); - const loader = new THREE.GLTFLoader(); - let reticle; - loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/reticle/reticle.gltf", function(gltf) { - reticle = gltf.scene; - reticle.visible = false; - scene.add(reticle); - }); - - let models = { - car: null, - lamp: null - }; - - loader.load("https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb", function(gltf) { - models.car = gltf.scene; - }); + // Menü erstellen + const menuGeometry = new THREE.PlaneGeometry(0.5, 0.25); // Größe kleiner für AR + const menuMaterial = new THREE.MeshBasicMaterial({ color: 0x2196F3, side: THREE.DoubleSide }); + menu = new THREE.Mesh(menuGeometry, menuMaterial); + scene.add(menu); - loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/sunflower/sunflower.gltf", function(gltf) { - models.lamp = gltf.scene; + // AR-Session starten + const session = await navigator.xr.requestSession('immersive-ar', { requiredFeatures: ['local-floor'] }); + session.updateRenderState({ + baseLayer: new XRWebGLLayer(session, gl) }); + const referenceSpace = await session.requestReferenceSpace('local-floor'); - session.addEventListener("select", () => { - if (reticle && models[selectedModel]) { - const clone = models[selectedModel].clone(); - clone.position.copy(reticle.position); - scene.add(clone); - } - }); + session.requestAnimationFrame(onXRFrame); - // Menü vor der Kamera hinzufügen - let menu; - const menuGeometry = new THREE.PlaneGeometry(2, 0.5); - const menuMaterial = new THREE.MeshBasicMaterial({ color: 0x2196F3 }); - menu = new THREE.Mesh(menuGeometry, menuMaterial); - scene.add(menu); + function onXRFrame(time, frame) { + const pose = frame.getViewerPose(referenceSpace); - const onXRFrame = (time, frame) => { session.requestAnimationFrame(onXRFrame); gl.bindFramebuffer(gl.FRAMEBUFFER, session.renderState.baseLayer.framebuffer); - const pose = frame.getViewerPose(referenceSpace); if (pose) { const view = pose.views[0]; const viewport = session.renderState.baseLayer.getViewport(view); renderer.setSize(viewport.width, viewport.height); + // Kamera aktualisieren camera.matrix.fromArray(view.transform.matrix); camera.projectionMatrix.fromArray(view.projectionMatrix); camera.updateMatrixWorld(true); @@ -191,25 +103,18 @@ // Menü vor der Kamera platzieren const cameraPosition = new THREE.Vector3(); camera.getWorldPosition(cameraPosition); + const cameraDirection = new THREE.Vector3(); camera.getWorldDirection(cameraDirection); menu.position.copy(cameraPosition); - menu.position.add(cameraDirection.multiplyScalar(2)); // 2 Meter vor der Kamera + menu.position.add(cameraDirection.multiplyScalar(1)); // 1 Meter vor der Kamera menu.lookAt(cameraPosition); - const hitTestResults = frame.getHitTestResults(hitTestSource); - if (hitTestResults.length > 0 && reticle) { - const hitPose = hitTestResults[0].getPose(referenceSpace); - reticle.visible = true; - reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z); - reticle.updateMatrixWorld(true); - } - + // Szene rendern renderer.render(scene, camera); } - }; - session.requestAnimationFrame(onXRFrame); + } } </script> </body>