aaurelions commited on
Commit
ba416c3
·
verified ·
1 Parent(s): 10d21c8

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +215 -19
index.html CHANGED
@@ -1,19 +1,215 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>3D Panorama and Model Viewer</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ body {
10
+ font-family: 'Inter', sans-serif;
11
+ overflow: hidden;
12
+ }
13
+ .gallery-thumbnail {
14
+ cursor: pointer;
15
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
16
+ }
17
+ .gallery-thumbnail:hover {
18
+ transform: scale(1.05);
19
+ box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
20
+ }
21
+ .model-button {
22
+ transition: background-color 0.2s, transform 0.2s;
23
+ }
24
+ .model-button:hover {
25
+ transform: translateY(-2px);
26
+ }
27
+ .active-thumbnail, .active-model {
28
+ border-color: #3b82f6; /* blue-500 */
29
+ box-shadow: 0 0 15px rgba(59, 130, 246, 0.5);
30
+ }
31
+ </style>
32
+ <link rel="stylesheet" href="https://rsms.me/inter/inter.css">
33
+ </head>
34
+ <body class="bg-gray-900 text-white">
35
+
36
+ <div id="loader" class="absolute inset-0 bg-gray-900 bg-opacity-80 flex items-center justify-center z-50 flex-col">
37
+ <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-blue-500"></div>
38
+ <p class="mt-4 text-lg">Loading 3D Environment...</p>
39
+ </div>
40
+
41
+ <canvas id="bg-canvas" class="absolute top-0 left-0 w-full h-full"></canvas>
42
+
43
+ <div class="absolute top-0 left-0 p-6 md:p-8 w-full md:w-auto">
44
+ <h1 class="text-2xl md:text-3xl font-bold text-white shadow-lg">3D Viewer</h1>
45
+ </div>
46
+
47
+ <div class="absolute bottom-0 left-0 right-0 p-4 bg-gray-900 bg-opacity-50 backdrop-blur-sm">
48
+ <div class="max-w-7xl mx-auto">
49
+ <div>
50
+ <h2 class="text-lg font-semibold mb-3 px-2">Select Panorama</h2>
51
+ <div id="panorama-gallery" class="flex space-x-3 overflow-x-auto pb-3">
52
+ <!-- Panorama thumbnails will be injected here -->
53
+ </div>
54
+ </div>
55
+ <div class="mt-4">
56
+ <h2 class="text-lg font-semibold mb-3 px-2">Select Model</h2>
57
+ <div id="model-selector" class="flex flex-wrap gap-2">
58
+ <!-- Model buttons will be injected here -->
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+
64
+ <script type="importmap">
65
+ {
66
+ "imports": {
67
+ "three": "https://unpkg.com/three@0.160.0/build/three.module.js",
68
+ "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
69
+ }
70
+ }
71
+ </script>
72
+
73
+ <script type="module">
74
+ import * as THREE from 'three';
75
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
76
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
77
+
78
+ const panoramaFiles = Array.from({ length: 10 }, (_, i) => `/jpg/bg${i + 1}.jpg`);
79
+ const modelFiles = [
80
+ 'gerbera.glb', 'shahed1.glb', 'shahed2.glb', 'shahed3.glb',
81
+ 'supercam.glb', 'zala.glb', 'beaver.glb'
82
+ ];
83
+
84
+ let scene, camera, renderer, controls;
85
+ let currentModel = null;
86
+ const loadedModels = new Map();
87
+
88
+ const textureLoader = new THREE.TextureLoader();
89
+ const gltfLoader = new GLTFLoader();
90
+ const loaderElement = document.getElementById('loader');
91
+
92
+ function init() {
93
+ scene = new THREE.Scene();
94
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
95
+ camera.position.z = 5;
96
+
97
+ renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('bg-canvas'), antialias: true });
98
+ renderer.setSize(window.innerWidth, window.innerHeight);
99
+ renderer.setPixelRatio(window.devicePixelRatio);
100
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
101
+ renderer.outputEncoding = THREE.sRGBEncoding;
102
+
103
+ controls = new OrbitControls(camera, renderer.domElement);
104
+ controls.enableDamping = true;
105
+ controls.dampingFactor = 0.05;
106
+ controls.screenSpacePanning = false;
107
+ controls.minDistance = 1;
108
+ controls.maxDistance = 100;
109
+
110
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
111
+ scene.add(ambientLight);
112
+
113
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
114
+ directionalLight.position.set(5, 10, 7.5);
115
+ scene.add(directionalLight);
116
+
117
+ setupUI();
118
+ setPanorama(panoramaFiles[0]);
119
+ loadModel(modelFiles[0]);
120
+
121
+ window.addEventListener('resize', onWindowResize, false);
122
+ animate();
123
+ loaderElement.style.display = 'none';
124
+ }
125
+
126
+ function setPanorama(imagePath) {
127
+ textureLoader.load(imagePath, (texture) => {
128
+ texture.mapping = THREE.EquirectangularReflectionMapping;
129
+ scene.background = texture;
130
+ scene.environment = texture;
131
+ updateActiveThumbnail(imagePath);
132
+ });
133
+ }
134
+
135
+ function loadModel(modelName) {
136
+ if (currentModel) {
137
+ currentModel.visible = false;
138
+ }
139
+
140
+ if (loadedModels.has(modelName)) {
141
+ currentModel = loadedModels.get(modelName);
142
+ currentModel.visible = true;
143
+ updateActiveModelButton(modelName);
144
+ } else {
145
+ loaderElement.style.display = 'flex';
146
+ gltfLoader.load(`/glb/${modelName}`, (gltf) => {
147
+ const model = gltf.scene;
148
+ const box = new THREE.Box3().setFromObject(model);
149
+ const center = box.getCenter(new THREE.Vector3());
150
+ model.position.sub(center);
151
+ scene.add(model);
152
+ loadedModels.set(modelName, model);
153
+ currentModel = model;
154
+ updateActiveModelButton(modelName);
155
+ loaderElement.style.display = 'none';
156
+ }, undefined, (error) => {
157
+ console.error('An error happened while loading the model:', error);
158
+ loaderElement.style.display = 'none';
159
+ });
160
+ }
161
+ }
162
+
163
+ function setupUI() {
164
+ const panoramaGallery = document.getElementById('panorama-gallery');
165
+ panoramaFiles.forEach(file => {
166
+ const thumb = document.createElement('img');
167
+ thumb.src = file;
168
+ thumb.className = 'gallery-thumbnail h-20 w-32 object-cover rounded-lg border-2 border-transparent';
169
+ thumb.dataset.path = file;
170
+ thumb.onclick = () => setPanorama(file);
171
+ panoramaGallery.appendChild(thumb);
172
+ });
173
+
174
+ const modelSelector = document.getElementById('model-selector');
175
+ modelFiles.forEach(file => {
176
+ const btn = document.createElement('button');
177
+ btn.innerText = file.replace('.glb', '');
178
+ btn.className = 'model-button px-4 py-2 bg-gray-700 text-white rounded-md font-semibold border-2 border-transparent';
179
+ btn.dataset.model = file;
180
+ btn.onclick = () => loadModel(file);
181
+ modelSelector.appendChild(btn);
182
+ });
183
+ }
184
+
185
+ function updateActiveThumbnail(activePath) {
186
+ document.querySelectorAll('.gallery-thumbnail').forEach(thumb => {
187
+ thumb.classList.toggle('active-thumbnail', thumb.dataset.path === activePath);
188
+ });
189
+ }
190
+
191
+ function updateActiveModelButton(activeModel) {
192
+ document.querySelectorAll('.model-button').forEach(btn => {
193
+ btn.classList.toggle('active-model', btn.dataset.model === activeModel);
194
+ btn.classList.toggle('bg-blue-600', btn.dataset.model === activeModel);
195
+ btn.classList.toggle('bg-gray-700', btn.dataset.model !== activeModel);
196
+ });
197
+ }
198
+
199
+ function onWindowResize() {
200
+ camera.aspect = window.innerWidth / window.innerHeight;
201
+ camera.updateProjectionMatrix();
202
+ renderer.setSize(window.innerWidth, window.innerHeight);
203
+ }
204
+
205
+ function animate() {
206
+ requestAnimationFrame(animate);
207
+ controls.update();
208
+ renderer.render(scene, camera);
209
+ }
210
+
211
+ init();
212
+
213
+ </script>
214
+ </body>
215
+ </html>