ThorAILabs commited on
Commit
acf2d73
·
verified ·
1 Parent(s): 3607024

refactor again

Browse files
Files changed (1) hide show
  1. index.html +209 -195
index.html CHANGED
@@ -2,223 +2,237 @@
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
- <title>3D Scene Editor with Raytracing & Model Support</title>
6
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
7
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/controls/OrbitControls.js"></script>
8
- <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/jsm/loaders/OBJLoader.js"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/jsm/loaders/STLLoader.js"></script>
10
- <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/jsm/exporters/STLExporter.js"></script>
11
- <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/jsm/exporters/OBJExporter.js"></script>
12
  <script src="https://cdn.tailwindcss.com"></script>
 
 
13
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
 
 
 
 
 
 
 
 
 
14
  </head>
15
- <body class="bg-gray-900 text-white">
16
  <div class="flex h-screen">
17
  <!-- Sidebar -->
18
- <div class="w-64 bg-gray-800 p-4 space-y-4">
19
- <h2 class="text-xl font-bold mb-4">Scene Tools</h2>
20
 
21
- <div class="space-y-2">
22
- <select id="shapeType" class="w-full bg-gray-700 rounded p-2">
23
- <option value="sphere">Sphere</option>
24
- <option value="cube">Cube</option>
25
- <option value="torus">Torus</option>
26
- </select>
27
-
28
- <input type="color" id="objectColor" class="w-full h-10">
29
-
30
- <button onclick="addObject()" class="w-full bg-blue-600 hover:bg-blue-700 p-2 rounded">
31
- <i class="fas fa-plus mr-2"></i>Add Object
32
  </button>
33
-
34
- <button onclick="raytraceScene()" class="w-full bg-purple-600 hover:bg-purple-700 p-2 rounded">
35
- <i class="fas fa-magic mr-2"></i>Raytrace
36
  </button>
37
-
38
- <!-- File Import Section -->
39
- <div class="border-t pt-4">
40
- <input type="file" id="modelInput" accept=".stl,.obj" class="hidden"/>
41
- <label for="modelInput" class="w-full bg-green-600 hover:bg-green-700 p-2 rounded block text-center cursor-pointer">
42
- <i class="fas fa-file-import mr-2"></i>Import Model
43
- </label>
44
-
45
- <select id="exportFormat" class="w-full bg-gray-700 rounded p-2 mt-2">
46
- <option value="stl">STL</option>
47
- <option value="obj">OBJ</option>
48
- </select>
49
 
50
- <button onclick="exportScene()" class="w-full bg-orange-600 hover:bg-orange-700 p-2 rounded">
51
- <i class="fas fa-file-export mr-2"></i>Export Scene
52
  </button>
 
53
  </div>
54
- </div>
55
- </div>
56
 
57
- <!-- Main View -->
58
- <div class="flex-1 relative">
59
- <canvas id="sceneCanvas" class="w-full h-full"></canvas>
60
-
61
- <!-- Selected Object Controls -->
62
- <div id="objectControls" class="absolute top-4 right-4 bg-gray-800 p-4 rounded-lg hidden">
63
- <button onclick="deleteObject()" class="bg-red-600 hover:bg-red-700 p-2 rounded">
64
- <i class="fas fa-trash mr-2"></i>Delete
 
 
 
 
65
  </button>
66
  </div>
67
  </div>
 
 
 
68
  </div>
69
 
70
- <script>
71
- let scene, camera, renderer, controls;
72
- let selectedObject = null;
73
-
74
- // Initialize Three.js Scene
75
- function initScene() {
76
- scene = new THREE.Scene();
77
- camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
78
- renderer = new THREE.WebGLRenderer({ antialias: true });
79
- renderer.setSize(window.innerWidth - 256, window.innerHeight);
80
- renderer.setClearColor(0x1a1a1a);
81
- document.getElementById('sceneCanvas').appendChild(renderer.domElement);
82
-
83
- // Lighting setup
84
- const ambientLight = new THREE.AmbientLight(0x404040);
85
- scene.add(ambientLight);
86
- const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
87
- directionalLight.position.set(5, 5, 5);
88
- scene.add(directionalLight);
89
-
90
- camera.position.z = 5;
91
- controls = new THREE.OrbitControls(camera, renderer.domElement);
92
-
93
- // Event listeners
94
- renderer.domElement.addEventListener('click', onCanvasClick);
95
- window.addEventListener('resize', onWindowResize);
96
- }
97
-
98
- // Model Import Handler
99
- document.getElementById('modelInput').addEventListener('change', (e) => {
100
- const file = e.target.files;
101
- const reader = new FileReader();
102
-
103
- reader.onload = (event) => {
104
- const loader = file.name.endsWith('.stl') ?
105
- new THREE.STLLoader() : new THREE.OBJLoader();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- loader.load(event.target.result, (object) => {
108
- object.traverse(child => {
109
  if (child.isMesh) {
110
- child.material = new THREE.MeshPhongMaterial({
111
- color: Math.random() * 0xffffff,
112
- shininess: 100
113
  });
114
- child.position.set(
115
- (Math.random() - 0.5) * 5,
116
- (Math.random() - 0.5) * 5,
117
- (Math.random() - 0.5) * 5
118
- );
119
  }
120
  });
121
- scene.add(object);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  });
123
- };
124
-
125
- reader.readAsDataURL(file);
126
- });
127
-
128
- // Scene Export Handler
129
- function exportScene() {
130
- const format = document.getElementById('exportFormat').value;
131
- const exporter = format === 'stl' ?
132
- new THREE.STLExporter() : new THREE.OBJExporter();
133
-
134
- const result = exporter.parse(scene);
135
- const blob = new Blob([result], {type: 'text/plain'});
136
- const link = document.createElement('a');
137
-
138
- link.href = URL.createObjectURL(blob);
139
- link.download = `scene.${format}`;
140
- link.click();
141
- }
142
-
143
- // Object Management
144
- function addObject() {
145
- const geometryType = document.getElementById('shapeType').value;
146
- const color = document.getElementById('objectColor').value;
147
-
148
- let geometry;
149
- switch(geometryType) {
150
- case 'sphere': geometry = new THREE.SphereGeometry(1, 32, 32); break;
151
- case 'cube': geometry = new THREE.BoxGeometry(1, 1, 1); break;
152
- case 'torus': geometry = new THREE.TorusGeometry(1, 0.4, 16, 100); break;
153
- }
154
-
155
- const material = new THREE.MeshPhongMaterial({
156
- color: color,
157
- shininess: 100
158
- });
159
-
160
- const mesh = new THREE.Mesh(geometry, material);
161
- mesh.position.set(
162
- (Math.random() - 0.5) * 5,
163
- (Math.random() - 0.5) * 5,
164
- (Math.random() - 0.5) * 5
165
- );
166
- scene.add(mesh);
167
- }
168
-
169
- // Raytracing Functionality
170
- function raytraceScene() {
171
- const raycaster = new THREE.Raycaster();
172
- const sceneBoundingBox = new THREE.Box3().setFromObject(scene);
173
-
174
- // Implementation placeholder for actual raytracing
175
- console.log("Raytracing initiated with scene bounds:", sceneBoundingBox);
176
- }
177
-
178
- // Event Handlers
179
- function onCanvasClick(event) {
180
- const raycaster = new THREE.Raycaster();
181
- const mouse = new THREE.Vector2();
182
-
183
- mouse.x = (event.clientX / renderer.domElement.width) * 2 - 1;
184
- mouse.y = -(event.clientY / renderer.domElement.height) * 2 + 1;
185
-
186
- raycaster.setFromCamera(mouse, camera);
187
- const intersects = raycaster.intersectObjects(scene.children);
188
-
189
- if(intersects.length > 0) {
190
- selectedObject = intersects.object;
191
- document.getElementById('objectControls').classList.remove('hidden');
192
- } else {
193
- selectedObject = null;
194
- document.getElementById('objectControls').classList.add('hidden');
195
- }
196
- }
197
-
198
- function deleteObject() {
199
- if(selectedObject) {
200
- scene.remove(selectedObject);
201
- selectedObject = null;
202
- document.getElementById('objectControls').classList.add('hidden');
203
- }
204
- }
205
-
206
- function onWindowResize() {
207
- camera.aspect = (window.innerWidth - 256) / window.innerHeight;
208
- camera.updateProjectionMatrix();
209
- renderer.setSize(window.innerWidth - 256, window.innerHeight);
210
- }
211
-
212
- // Animation Loop
213
- function animate() {
214
- requestAnimationFrame(animate);
215
- controls.update();
216
- renderer.render(scene, camera);
217
- }
218
-
219
- // Initialize Application
220
- initScene();
221
- animate();
222
- </script>
223
  </body>
224
  </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 Scene Editor with Raytracing & Import/Export</title>
7
+
8
+ <!-- Tailwind CSS -->
 
 
 
9
  <script src="https://cdn.tailwindcss.com"></script>
10
+
11
+ <!-- Font Awesome -->
12
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
13
+
14
+ <!-- Three.js -->
15
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
17
+
18
+ <!-- Loaders & Exporters -->
19
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/STLLoader.js"></script>
20
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/OBJLoader.js"></script>
21
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/exporters/STLExporter.js"></script>
22
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/exporters/OBJExporter.js"></script>
23
  </head>
24
+ <body class="bg-gray-900 h-screen overflow-hidden">
25
  <div class="flex h-screen">
26
  <!-- Sidebar -->
27
+ <div class="w-64 bg-gray-800 p-4 text-white flex flex-col gap-4">
28
+ <h2 class="text-xl font-bold mb-4"><i class="fas fa-cube mr-2"></i>Scene Controls</h2>
29
 
30
+ <div class="flex flex-col gap-2">
31
+ <button onclick="addCube()" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded">
32
+ <i class="fas fa-cube mr-2"></i>Add Cube
 
 
 
 
 
 
 
 
33
  </button>
34
+ <button onclick="addSphere()" class="bg-green-600 hover:bg-green-700 px-4 py-2 rounded">
35
+ <i class="fas fa-globe mr-2"></i>Add Sphere
 
36
  </button>
37
+
38
+ <!-- Import Section -->
39
+ <div class="mt-4 pt-4 border-t border-gray-700">
40
+ <button onclick="document.getElementById('stlInput').click()" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded w-full">
41
+ <i class="fas fa-file-import mr-2"></i>Import STL
42
+ </button>
43
+ <input type="file" id="stlInput" accept=".stl" hidden>
 
 
 
 
 
44
 
45
+ <button onclick="document.getElementById('objInput').click()" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded w-full mt-2">
46
+ <i class="fas fa-file-import mr-2"></i>Import OBJ
47
  </button>
48
+ <input type="file" id="objInput" accept=".obj" hidden>
49
  </div>
 
 
50
 
51
+ <!-- Export Section -->
52
+ <div class="mt-4 pt-4 border-t border-gray-700">
53
+ <button onclick="exportSTL()" class="bg-pink-600 hover:bg-pink-700 px-4 py-2 rounded w-full">
54
+ <i class="fas fa-file-export mr-2"></i>Export STL
55
+ </button>
56
+ <button onclick="exportOBJ()" class="bg-pink-600 hover:bg-pink-700 px-4 py-2 rounded w-full mt-2">
57
+ <i class="fas fa-file-export mr-2"></i>Export OBJ
58
+ </button>
59
+ </div>
60
+
61
+ <button onclick="raytrace()" class="bg-indigo-600 hover:bg-indigo-700 px-4 py-2 rounded mt-4">
62
+ <i class="fas fa-raygun mr-2"></i>Raytrace Scene
63
  </button>
64
  </div>
65
  </div>
66
+
67
+ <!-- 3D Viewport -->
68
+ <div id="viewport" class="flex-1"></div>
69
  </div>
70
 
71
+ <script>
72
+ let scene, camera, renderer, controls;
73
+ let raytraceMode = false;
74
+
75
+ function init() {
76
+ // Main scene setup
77
+ scene = new THREE.Scene();
78
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
79
+ renderer = new THREE.WebGLRenderer({ antialias: true });
80
+ renderer.setSize(window.innerWidth - 256, window.innerHeight);
81
+ renderer.setPixelRatio(window.devicePixelRatio);
82
+ document.getElementById('viewport').appendChild(renderer.domElement);
83
+
84
+ // Lighting
85
+ const ambientLight = new THREE.AmbientLight(0x404040);
86
+ scene.add(ambientLight);
87
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
88
+ directionalLight.position.set(5, 5, 5);
89
+ scene.add(directionalLight);
90
+
91
+ // Controls
92
+ controls = new THREE.OrbitControls(camera, renderer.domElement);
93
+ camera.position.z = 5;
94
+
95
+ // Ground plane
96
+ const planeGeometry = new THREE.PlaneGeometry(10, 10);
97
+ const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x444444 });
98
+ const plane = new THREE.Mesh(planeGeometry, planeMaterial);
99
+ plane.rotation.x = -Math.PI / 2;
100
+ scene.add(plane);
101
+
102
+ animate();
103
+ }
104
+
105
+ function animate() {
106
+ requestAnimationFrame(animate);
107
+ controls.update();
108
+ renderer.render(scene, camera);
109
+ }
110
+
111
+ function addCube() {
112
+ const geometry = new THREE.BoxGeometry();
113
+ const material = new THREE.MeshStandardMaterial({
114
+ color: new THREE.Color(Math.random(), Math.random(), Math.random()),
115
+ metalness: 0.3,
116
+ roughness: 0.8
117
+ });
118
+ const cube = new THREE.Mesh(geometry, material);
119
+ cube.position.set(Math.random() * 5 - 2.5, 0.5, Math.random() * 5 - 2.5);
120
+ scene.add(cube);
121
+ }
122
+
123
+ function addSphere() {
124
+ const geometry = new THREE.SphereGeometry(0.5, 32, 32);
125
+ const material = new THREE.MeshStandardMaterial({
126
+ color: new THREE.Color(Math.random(), Math.random(), Math.random()),
127
+ metalness: 0.8,
128
+ roughness: 0.2
129
+ });
130
+ const sphere = new THREE.Mesh(geometry, material);
131
+ sphere.position.set(Math.random() * 5 - 2.5, 0.5, Math.random() * 5 - 2.5);
132
+ scene.add(sphere);
133
+ }
134
+
135
+ function handleSTLUpload(event) {
136
+ const file = event.target.files[0];
137
+ if (!file) return;
138
+
139
+ const reader = new FileReader();
140
+ reader.onload = function(e) {
141
+ const loader = new THREE.STLLoader();
142
+ const geometry = loader.parse(e.target.result);
143
+ const material = new THREE.MeshStandardMaterial({
144
+ color: new THREE.Color(Math.random(), Math.random(), Math.random()),
145
+ metalness: 0.3,
146
+ roughness: 0.8
147
+ });
148
+ const mesh = new THREE.Mesh(geometry, material);
149
+ mesh.position.set(0, 0, 0);
150
+ scene.add(mesh);
151
+ };
152
+ reader.readAsArrayBuffer(file);
153
+ }
154
+
155
+ function handleOBJUpload(event) {
156
+ const file = event.target.files[0];
157
+ if (!file) return;
158
+
159
+ const reader = new FileReader();
160
+ reader.onload = function(e) {
161
+ const loader = new THREE.OBJLoader();
162
+ const obj = loader.parse(e.target.result);
163
+
164
+ obj.traverse(child => {
165
+ if (child.isMesh) {
166
+ child.material = new THREE.MeshStandardMaterial({
167
+ color: new THREE.Color(Math.random(), Math.random(), Math.random()),
168
+ metalness: 0.3,
169
+ roughness: 0.8
170
+ });
171
+ }
172
+ });
173
+
174
+ scene.add(obj);
175
+ };
176
+ reader.readAsText(file);
177
+ }
178
+
179
+ function exportSTL() {
180
+ const exporter = new THREE.STLExporter();
181
+ const result = exporter.parse(scene);
182
+
183
+ const blob = new Blob([result], { type: 'text/plain' });
184
+ const link = document.createElement('a');
185
+ link.href = URL.createObjectURL(blob);
186
+ link.download = 'scene.stl';
187
+ link.click();
188
+ }
189
+
190
+ function exportOBJ() {
191
+ const exporter = new THREE.OBJExporter();
192
+ const result = exporter.parse(scene);
193
+
194
+ const blob = new Blob([result], { type: 'text/plain' });
195
+ const link = document.createElement('a');
196
+ link.href = URL.createObjectURL(blob);
197
+ link.download = 'scene.obj';
198
+ link.click();
199
+ }
200
+
201
+ function raytrace() {
202
+ const raytracer = new THREE.WebGLRenderer();
203
+ const rtCanvas = raytracer.domElement;
204
+
205
+ const clonedScene = scene.clone();
206
+ const clonedCamera = camera.clone();
207
 
208
+ clonedScene.traverse(child => {
 
209
  if (child.isMesh) {
210
+ child.material = new THREE.MeshBasicMaterial({
211
+ color: child.material.color,
212
+ wireframe: false
213
  });
 
 
 
 
 
214
  }
215
  });
216
+
217
+ raytracer.setSize(window.innerWidth - 256, window.innerHeight);
218
+ raytracer.render(clonedScene, clonedCamera);
219
+
220
+ document.getElementById('viewport').replaceChild(rtCanvas, renderer.domElement);
221
+ renderer = raytracer;
222
+ }
223
+
224
+ // Initialize on load
225
+ window.onload = function() {
226
+ init();
227
+ document.getElementById('stlInput').addEventListener('change', handleSTLUpload);
228
+ document.getElementById('objInput').addEventListener('change', handleOBJUpload);
229
+ };
230
+
231
+ window.addEventListener('resize', () => {
232
+ camera.aspect = (window.innerWidth - 256) / window.innerHeight;
233
+ camera.updateProjectionMatrix();
234
+ renderer.setSize(window.innerWidth - 256, window.innerHeight);
235
  });
236
+ </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  </body>
238
  </html>