An error occurred while loading the file. Please try again.
-
Percen authored30a90c4b
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<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;
}
</style>
<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>
<script>
let selectedModel = 'robot'; // Standardauswahl
let models = {};
let reticle;
let currentModel = null;
let scene;
let camera;
let hitTestSource;
let hitTestResults = [];
async function activateXR() {
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;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
camera.matrixAutoUpdate = false;
// Licht hinzufügen
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10, 10, 10);
scene.add(light);
// Reticle (Cursor)
const loader = new THREE.GLTFLoader();
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/reticle/reticle.gltf", (gltf) => {
reticle = gltf.scene;
reticle.visible = false;
scene.add(reticle);
});
// Modelle laden
loader.load("https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb", (gltf) => {
models.robot = gltf.scene;
});
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/sunflower/sunflower.gltf", (gltf) => {
models.flower = gltf.scene;
});
// AR-Session starten
const session = await navigator.xr.requestSession('immersive-ar', { requiredFeatures: ['hit-test'] });
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
const referenceSpace = await session.requestReferenceSpace('local');
const viewerSpace = await session.requestReferenceSpace('viewer');
hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
session.requestAnimationFrame(onXRFrame);
// AR-Rendering
function 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);
camera.matrix.fromArray(view.transform.matrix);
camera.projectionMatrix.fromArray(view.projectionMatrix);
camera.updateMatrixWorld(true);
hitTestResults = frame.getHitTestResults(hitTestSource);
if (hitTestResults.length > 0) {
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);
// Das Modell an der Reticle-Position platzieren
if (currentModel) {
currentModel.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z);
}
}
renderer.render(scene, camera);
}
}
}
// Touch Events für Swipe-Geste
let startX = 0;
let startY = 0;
let endX = 0;
let endY = 0;
const threshold = 50; // Mindestdistanz für die Swipe-Erkennung
// Event Listener für Touch-Ereignisse
document.body.addEventListener('touchstart', (event) => {
// Die Startposition der Geste speichern
startX = event.touches[0].clientX;
startY = event.touches[0].clientY;
});
document.body.addEventListener('touchend', (event) => {
// Berechne die Distanz in der X- und Y-Richtung
endX = event.changedTouches[0].clientX;
endY = event.changedTouches[0].clientY;
let deltaX = endX - startX;
let deltaY = endY - startY;
// Wenn der Swipe horizontal ist (Links oder Rechts)
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > threshold) {
if (deltaX > 0) {
// Swipe nach rechts -> Wechseln zum nächsten Modell
switchModel('next');
} else {
// Swipe nach links -> Wechseln zum vorherigen Modell
switchModel('previous');
}
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
}
});
// Funktion zum Modellwechsel
function switchModel(direction) {
// Entferne das aktuelle Modell nur, wenn es bereits in der Szene ist
if (currentModel) {
scene.remove(currentModel);
}
// Bestimmen, welches Modell ausgewählt wird
if (direction === 'next') {
selectedModel = selectedModel === 'robot' ? 'flower' : 'robot';
} else if (direction === 'previous') {
selectedModel = selectedModel === 'robot' ? 'flower' : 'robot';
}
// Das ausgewählte Modell hinzufügen
currentModel = models[selectedModel].clone(); // Erstelle eine Kopie des Modells
scene.add(currentModel);
}
// AR starten
if (navigator.xr) {
const startButton = document.createElement('button');
startButton.textContent = 'Start AR';
startButton.style.cssText = "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 15px; font-size: 18px;";
document.body.appendChild(startButton);
startButton.onclick = () => {
startButton.remove();
activateXR();
};
} else {
alert('WebXR wird nicht unterstützt.');
}
</script>
</body>
</html>