Reaperxxxx commited on
Commit
5dad437
·
verified ·
1 Parent(s): e82e5a4

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +230 -89
index.html CHANGED
@@ -3,12 +3,13 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
6
- <title>3D Map Viewer</title>
7
  <style>
8
  body {
9
  margin: 0;
10
  overflow: hidden;
11
  background: #000;
 
12
  }
13
  canvas {
14
  display: block;
@@ -28,10 +29,113 @@
28
  z-index: 100;
29
  font-size: 18px;
30
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  </style>
32
  </head>
33
  <body>
34
- <div id="loading">Loading...</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  <script type="importmap">
37
  {
@@ -46,13 +150,17 @@
46
  import * as THREE from 'three';
47
  import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
48
 
49
- let scene, camera, renderer, modelLoaded = false;
50
- let rotation = { x: 0, y: 0 };
51
- let zoom = 5;
 
 
 
52
 
53
  function init() {
54
  scene = new THREE.Scene();
55
- scene.background = new THREE.Color(0x111111);
 
56
 
57
  camera = new THREE.PerspectiveCamera(
58
  75,
@@ -60,121 +168,154 @@
60
  0.1,
61
  1000
62
  );
63
- camera.position.z = zoom;
64
 
65
  renderer = new THREE.WebGLRenderer({ antialias: true });
66
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
67
  renderer.setSize(window.innerWidth, window.innerHeight);
 
68
  document.body.appendChild(renderer.domElement);
69
 
70
  // Lighting
71
- scene.add(new THREE.AmbientLight(0xffffff, 1.2));
72
  const dirLight = new THREE.DirectionalLight(0xffffff, 1);
73
- dirLight.position.set(10, 10, 10);
 
74
  scene.add(dirLight);
75
 
76
- // Load map.glb
 
 
 
 
 
 
 
 
77
  const loader = new GLTFLoader();
78
  loader.load('./map.glb', (gltf) => {
79
- const model = gltf.scene;
80
- scene.add(model);
81
- modelLoaded = true;
 
 
 
82
  document.getElementById('loading').style.display = 'none';
83
- console.log('✅ Map loaded!');
84
  }, undefined, (error) => {
85
- console.error('Error loading map:', error);
86
- // Fallback: create test cube
87
- const geometry = new THREE.BoxGeometry(2, 2, 2);
88
- const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
89
- const cube = new THREE.Mesh(geometry, material);
90
- scene.add(cube);
91
- modelLoaded = true;
92
- document.getElementById('loading').textContent = 'Test Cube (map.glb not found)';
 
 
 
93
  });
 
94
 
95
- // Mouse/touch controls
96
- let isDragging = false;
97
- let previousMousePosition = { x: 0, y: 0 };
 
 
98
 
99
- renderer.domElement.addEventListener('mousedown', (e) => {
100
- isDragging = true;
101
- previousMousePosition = { x: e.clientX, y: e.clientY };
102
  });
103
 
104
- renderer.domElement.addEventListener('mousemove', (e) => {
105
- if (isDragging && modelLoaded) {
106
- const deltaX = e.clientX - previousMousePosition.x;
107
- const deltaY = e.clientY - previousMousePosition.y;
108
- rotation.y += deltaX * 0.01;
109
- rotation.x += deltaY * 0.01;
110
- previousMousePosition = { x: e.clientX, y: e.clientY };
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
  });
113
 
114
- renderer.domElement.addEventListener('mouseup', () => {
115
- isDragging = false;
 
 
 
116
  });
117
 
118
- renderer.domElement.addEventListener('wheel', (e) => {
119
- e.preventDefault();
120
- zoom += e.deltaY * 0.01;
121
- zoom = Math.max(1, Math.min(20, zoom));
122
  });
123
 
124
- // Touch pinch to zoom
125
- let lastDistance = 0;
126
- renderer.domElement.addEventListener('touchmove', (e) => {
127
- if (e.touches.length === 2) {
128
- e.preventDefault();
129
- const touch1 = e.touches[0];
130
- const touch2 = e.touches[1];
131
- const dx = touch1.clientX - touch2.clientX;
132
- const dy = touch1.clientY - touch2.clientY;
133
- const distance = Math.sqrt(dx * dx + dy * dy);
134
-
135
- if (lastDistance > 0) {
136
- const delta = distance - lastDistance;
137
- zoom -= delta * 0.02;
138
- zoom = Math.max(1, Math.min(20, zoom));
139
- }
140
- lastDistance = distance;
141
- } else if (e.touches.length === 1) {
142
- // Single finger drag
143
- const touch = e.touches[0];
144
- const deltaX = touch.clientX - previousMousePosition.x;
145
- const deltaY = touch.clientY - previousMousePosition.y;
146
- rotation.y += deltaX * 0.01;
147
- rotation.x += deltaY * 0.01;
148
- previousMousePosition = { x: touch.clientX, y: touch.clientY };
149
- }
150
- }, false);
151
-
152
- renderer.domElement.addEventListener('touchend', () => {
153
- lastDistance = 0;
154
  });
 
155
 
156
- function animate() {
157
- requestAnimationFrame(animate);
158
-
159
- if (modelLoaded) {
160
- camera.position.x = zoom * Math.sin(rotation.y);
161
- camera.position.y = zoom * Math.sin(rotation.x);
162
- camera.position.z = zoom * Math.cos(rotation.y);
163
- camera.lookAt(0, 0, 0);
164
- }
165
-
166
- renderer.render(scene, camera);
167
- }
168
 
169
- animate();
 
170
 
171
- window.addEventListener('resize', () => {
172
- camera.aspect = window.innerWidth / window.innerHeight;
173
- camera.updateProjectionMatrix();
174
- renderer.setSize(window.innerWidth, window.innerHeight);
175
- });
 
 
 
 
 
 
 
 
 
176
  }
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  init();
179
  </script>
180
  </body>
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
6
+ <title>3D Garage Explorer</title>
7
  <style>
8
  body {
9
  margin: 0;
10
  overflow: hidden;
11
  background: #000;
12
+ font-family: Arial, sans-serif;
13
  }
14
  canvas {
15
  display: block;
 
29
  z-index: 100;
30
  font-size: 18px;
31
  }
32
+
33
+ #joystick {
34
+ position: fixed;
35
+ bottom: 30px;
36
+ left: 30px;
37
+ width: 120px;
38
+ height: 120px;
39
+ background: rgba(100, 100, 100, 0.3);
40
+ border: 2px solid #fff;
41
+ border-radius: 50%;
42
+ z-index: 50;
43
+ }
44
+
45
+ #joystickHandle {
46
+ position: absolute;
47
+ width: 50px;
48
+ height: 50px;
49
+ background: rgba(255, 255, 255, 0.5);
50
+ border-radius: 50%;
51
+ top: 50%;
52
+ left: 50%;
53
+ transform: translate(-50%, -50%);
54
+ cursor: grab;
55
+ }
56
+
57
+ .button-group {
58
+ position: fixed;
59
+ right: 30px;
60
+ bottom: 30px;
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 10px;
64
+ z-index: 50;
65
+ }
66
+
67
+ .control-btn {
68
+ padding: 12px 20px;
69
+ background: rgba(0, 150, 255, 0.7);
70
+ border: 2px solid #0096ff;
71
+ color: white;
72
+ border-radius: 8px;
73
+ cursor: pointer;
74
+ font-weight: bold;
75
+ font-size: 16px;
76
+ min-width: 80px;
77
+ }
78
+
79
+ .control-btn:active {
80
+ background: rgba(0, 150, 255, 1);
81
+ }
82
+
83
+ #coordinates {
84
+ position: fixed;
85
+ top: 20px;
86
+ left: 20px;
87
+ background: rgba(0, 0, 0, 0.8);
88
+ color: #0f0;
89
+ padding: 15px;
90
+ border-radius: 8px;
91
+ font-family: monospace;
92
+ font-size: 12px;
93
+ z-index: 50;
94
+ max-width: 300px;
95
+ }
96
+
97
+ .coord-input {
98
+ background: rgba(0, 50, 0, 0.8);
99
+ border: 1px solid #0f0;
100
+ color: #0f0;
101
+ padding: 8px;
102
+ border-radius: 4px;
103
+ font-family: monospace;
104
+ margin-top: 8px;
105
+ width: 100%;
106
+ }
107
+
108
+ .spawn-btn {
109
+ background: rgba(0, 150, 0, 0.7);
110
+ border: 1px solid #0f0;
111
+ color: #0f0;
112
+ padding: 8px;
113
+ border-radius: 4px;
114
+ margin-top: 8px;
115
+ cursor: pointer;
116
+ }
117
  </style>
118
  </head>
119
  <body>
120
+ <div id="loading">Loading Garage...</div>
121
+
122
+ <div id="joystick">
123
+ <div id="joystickHandle"></div>
124
+ </div>
125
+
126
+ <div class="button-group">
127
+ <button class="control-btn" id="upBtn">↑ Up</button>
128
+ <button class="control-btn" id="downBtn">↓ Down</button>
129
+ </div>
130
+
131
+ <div id="coordinates">
132
+ <div>Cube Position:</div>
133
+ <div>X: <span id="coordX">0.00</span></div>
134
+ <div>Y: <span id="coordY">0.00</span></div>
135
+ <div>Z: <span id="coordZ">0.00</span></div>
136
+ <input type="text" class="coord-input" id="spawnInput" placeholder="Paste spawn coord JSON">
137
+ <button class="spawn-btn" onclick="loadSpawn()">Set Spawn</button>
138
+ </div>
139
 
140
  <script type="importmap">
141
  {
 
150
  import * as THREE from 'three';
151
  import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
152
 
153
+ let scene, camera, renderer, playerCube, garage;
154
+ let playerPos = { x: 0, y: 1, z: 0 };
155
+ let cameraDistance = 8;
156
+ let cameraHeight = 3;
157
+ let moveDirection = { x: 0, z: 0 };
158
+ let moveSpeed = 0.3;
159
 
160
  function init() {
161
  scene = new THREE.Scene();
162
+ scene.background = new THREE.Color(0x1a1a2e);
163
+ scene.fog = new THREE.Fog(0x1a1a2e, 100, 300);
164
 
165
  camera = new THREE.PerspectiveCamera(
166
  75,
 
168
  0.1,
169
  1000
170
  );
 
171
 
172
  renderer = new THREE.WebGLRenderer({ antialias: true });
173
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
174
  renderer.setSize(window.innerWidth, window.innerHeight);
175
+ renderer.shadowMap.enabled = true;
176
  document.body.appendChild(renderer.domElement);
177
 
178
  // Lighting
179
+ scene.add(new THREE.AmbientLight(0xffffff, 0.6));
180
  const dirLight = new THREE.DirectionalLight(0xffffff, 1);
181
+ dirLight.position.set(20, 20, 20);
182
+ dirLight.castShadow = true;
183
  scene.add(dirLight);
184
 
185
+ // Create player cube
186
+ const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
187
+ const cubeMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000 });
188
+ playerCube = new THREE.Mesh(cubeGeometry, cubeMaterial);
189
+ playerCube.position.set(playerPos.x, playerPos.y, playerPos.z);
190
+ playerCube.castShadow = true;
191
+ scene.add(playerCube);
192
+
193
+ // Load garage
194
  const loader = new GLTFLoader();
195
  loader.load('./map.glb', (gltf) => {
196
+ garage = gltf.scene;
197
+ scene.add(garage);
198
+ garage.traverse((child) => {
199
+ child.castShadow = true;
200
+ child.receiveShadow = true;
201
+ });
202
  document.getElementById('loading').style.display = 'none';
203
+ console.log('✅ Garage loaded!');
204
  }, undefined, (error) => {
205
+ console.error('Error loading garage:', error);
206
+ document.getElementById('loading').textContent = 'Error loading map.glb';
207
+ });
208
+
209
+ setupControls();
210
+ animate();
211
+
212
+ window.addEventListener('resize', () => {
213
+ camera.aspect = window.innerWidth / window.innerHeight;
214
+ camera.updateProjectionMatrix();
215
+ renderer.setSize(window.innerWidth, window.innerHeight);
216
  });
217
+ }
218
 
219
+ function setupControls() {
220
+ // Joystick
221
+ const joystick = document.getElementById('joystick');
222
+ const joystickHandle = document.getElementById('joystickHandle');
223
+ let isJoystickActive = false;
224
 
225
+ joystick.addEventListener('touchstart', (e) => {
226
+ isJoystickActive = true;
 
227
  });
228
 
229
+ joystick.addEventListener('touchmove', (e) => {
230
+ if (!isJoystickActive) return;
231
+ const touch = e.touches[0];
232
+ const rect = joystick.getBoundingClientRect();
233
+ const centerX = rect.left + rect.width / 2;
234
+ const centerY = rect.top + rect.height / 2;
235
+ const dx = touch.clientX - centerX;
236
+ const dy = touch.clientY - centerY;
237
+ const distance = Math.sqrt(dx * dx + dy * dy);
238
+ const maxDistance = 50;
239
+
240
+ if (distance > 0) {
241
+ const angle = Math.atan2(dy, dx);
242
+ const limitedDistance = Math.min(distance, maxDistance);
243
+ joystickHandle.style.transform = `translate(calc(-50% + ${Math.cos(angle) * limitedDistance}px), calc(-50% + ${Math.sin(angle) * limitedDistance}px))`;
244
+
245
+ moveDirection.x = Math.cos(angle);
246
+ moveDirection.z = Math.sin(angle);
247
  }
248
  });
249
 
250
+ joystick.addEventListener('touchend', () => {
251
+ isJoystickActive = false;
252
+ joystickHandle.style.transform = 'translate(-50%, -50%)';
253
+ moveDirection.x = 0;
254
+ moveDirection.z = 0;
255
  });
256
 
257
+ // Up/Down buttons
258
+ document.getElementById('upBtn').addEventListener('touchstart', () => {
259
+ playerPos.y += 0.5;
 
260
  });
261
 
262
+ document.getElementById('downBtn').addEventListener('touchstart', () => {
263
+ playerPos.y = Math.max(0.5, playerPos.y - 0.5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  });
265
+ }
266
 
267
+ function updateCoordinates() {
268
+ document.getElementById('coordX').textContent = playerPos.x.toFixed(2);
269
+ document.getElementById('coordY').textContent = playerPos.y.toFixed(2);
270
+ document.getElementById('coordZ').textContent = playerPos.z.toFixed(2);
271
+ }
 
 
 
 
 
 
 
272
 
273
+ function animate() {
274
+ requestAnimationFrame(animate);
275
 
276
+ // Update player position
277
+ playerPos.x += moveDirection.x * moveSpeed;
278
+ playerPos.z += moveDirection.z * moveSpeed;
279
+
280
+ playerCube.position.set(playerPos.x, playerPos.y, playerPos.z);
281
+
282
+ // Update camera (third person)
283
+ const cameraX = playerPos.x - moveDirection.x * cameraDistance;
284
+ const cameraZ = playerPos.z - moveDirection.z * cameraDistance;
285
+ camera.position.set(cameraX, playerPos.y + cameraHeight, cameraZ);
286
+ camera.lookAt(playerPos.x, playerPos.y + 0.5, playerPos.z);
287
+
288
+ updateCoordinates();
289
+ renderer.render(scene, camera);
290
  }
291
 
292
+ window.loadSpawn = function() {
293
+ try {
294
+ const input = document.getElementById('spawnInput').value;
295
+ const coords = JSON.parse(input);
296
+ playerPos.x = coords.x || 0;
297
+ playerPos.y = coords.y || 1;
298
+ playerPos.z = coords.z || 0;
299
+ alert('✅ Spawn point set!');
300
+ } catch (e) {
301
+ alert('❌ Invalid JSON format');
302
+ }
303
+ };
304
+
305
+ window.copySpawn = function() {
306
+ const spawnData = JSON.stringify(playerPos);
307
+ navigator.clipboard.writeText(spawnData);
308
+ alert('✅ Copied to clipboard: ' + spawnData);
309
+ };
310
+
311
+ // Add copy button functionality
312
+ const coordsDiv = document.getElementById('coordinates');
313
+ const copyBtn = document.createElement('button');
314
+ copyBtn.className = 'spawn-btn';
315
+ copyBtn.textContent = 'Copy Spawn';
316
+ copyBtn.onclick = window.copySpawn;
317
+ coordsDiv.appendChild(copyBtn);
318
+
319
  init();
320
  </script>
321
  </body>