ThorAILabs commited on
Commit
4a7eadc
·
verified ·
1 Parent(s): 04fb0ab

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +157 -242
index.html CHANGED
@@ -1,252 +1,167 @@
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 Scene Editor with Raytracing</title>
7
- <!-- Tailwind CSS CDN -->
8
  <script src="https://cdn.tailwindcss.com"></script>
9
- <!-- FontAwesome CDN -->
10
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha512-yHzo+M3GtT8OqysHzf3R+KwV/B+8/7ICiwAdgZrmEMXn1x5slIYi9PNRbE2LkoOmnJ5cZtL7B5ZpCyVQV3K8kw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
11
- <!-- Three.js and Helpers -->
12
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/three.min.js"></script>
13
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/examples/js/controls/OrbitControls.js"></script>
14
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/examples/js/loaders/STLLoader.js"></script>
15
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/examples/js/loaders/OBJLoader.js"></script>
16
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/examples/js/exporters/STLExporter.js"></script>
17
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/examples/js/exporters/OBJExporter.js"></script>
18
- <style>
19
- /* Remove margin and set canvas to full screen */
20
- body, html {
21
- margin: 0;
22
- padding: 0;
23
- height: 100%;
24
- overflow: hidden;
25
- }
26
- #editorCanvas {
27
- display: block;
28
- }
29
- </style>
30
- </head>
31
- <body class="bg-gray-900">
32
- <!-- Toolbar -->
33
- <div class="absolute top-4 left-4 z-10 space-y-4">
34
- <div class="bg-gray-800 bg-opacity-80 rounded p-4 shadow-lg">
35
- <h1 class="text-white text-lg font-bold mb-2"><i class="fas fa-cube"></i> 3D Scene Editor</h1>
36
- <div class="space-x-2">
37
- <!-- Toggle Raytracing -->
38
- <button id="toggleRaytrace" class="bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded shadow">
39
- <i class="fas fa-lightbulb"></i> Toggle Raytrace
40
- </button>
41
- <!-- Add Light -->
42
- <select id="lightType" class="bg-gray-700 text-white rounded px-2 py-1">
43
- <option value="ambient">Ambient Light</option>
44
- <option value="point">Point Light</option>
45
- <option value="directional">Directional Light</option>
46
- </select>
47
- <button id="addLight" class="bg-green-500 hover:bg-green-600 text-white px-3 py-1 rounded shadow">
48
- <i class="fas fa-plus"></i> Add Light
49
- </button>
 
 
 
 
 
50
  </div>
51
- </div>
52
- <!-- File Operations -->
53
- <div class="bg-gray-800 bg-opacity-80 rounded p-4 shadow-lg">
54
- <h2 class="text-white text-md font-semibold mb-2"><i class="fas fa-file"></i> Load / Export Files</h2>
55
- <div class="mb-2">
56
- <input type="file" id="fileInput" class="bg-gray-700 text-white rounded px-2 py-1" accept=".stl,.obj" />
57
- </div>
58
- <div class="space-x-2">
59
- <select id="exportType" class="bg-gray-700 text-white rounded px-2 py-1">
60
- <option value="stl">Export as STL</option>
61
- <option value="obj">Export as OBJ</option>
62
- </select>
63
- <button id="exportScene" class="bg-purple-500 hover:bg-purple-600 text-white px-3 py-1 rounded shadow">
64
- <i class="fas fa-download"></i> Export
65
- </button>
66
- </div>
67
- </div>
68
  </div>
69
 
70
- <!-- Three.js Canvas -->
71
- <canvas id="editorCanvas"></canvas>
72
-
73
- <!-- Script -->
74
- <script>
75
- let scene, camera, renderer, controls;
76
- let raytraceOn = true; // state for raytrace mode
77
-
78
- // Store original materials to toggle between modes
79
- const originalMaterials = new Map();
80
-
81
- // Initialize scene, camera, renderer
82
- function init() {
83
- const canvas = document.getElementById('editorCanvas');
84
- renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
85
- renderer.setSize(window.innerWidth, window.innerHeight);
86
- renderer.setPixelRatio(window.devicePixelRatio);
87
- renderer.setClearColor(0x222222);
88
-
89
- scene = new THREE.Scene();
90
-
91
- camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
92
- camera.position.set(3, 3, 3);
93
- scene.add(camera);
94
-
95
- // Add a default ambient light
96
- const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
97
- scene.add(ambientLight);
98
-
99
- // Add grid helper to orient the scene
100
- const gridHelper = new THREE.GridHelper(10, 10);
101
- scene.add(gridHelper);
102
-
103
- // Add OrbitControls
104
- controls = new THREE.OrbitControls(camera, renderer.domElement);
105
-
106
- // Start render loop
107
- animate();
108
-
109
- // Window resize listener
110
- window.addEventListener('resize', onWindowResize, false);
111
- }
112
-
113
- function onWindowResize() {
114
- camera.aspect = window.innerWidth / window.innerHeight;
115
- camera.updateProjectionMatrix();
116
- renderer.setSize(window.innerWidth, window.innerHeight);
117
- }
118
-
119
- // Render loop
120
- function animate() {
121
- requestAnimationFrame(animate);
122
- controls.update();
123
- renderer.render(scene, camera);
124
- }
125
-
126
- // Toggle raytracing mode by switching materials.
127
- function toggleRaytrace() {
128
- raytraceOn = !raytraceOn;
129
- scene.traverse((child) => {
130
- if (child.isMesh) {
131
- if (raytraceOn) {
132
- // Store original material if not stored yet
133
- if (!originalMaterials.has(child)) {
134
- originalMaterials.set(child, child.material);
135
- }
136
- // Use a physical material to simulate raytraced appearance
137
- child.material = new THREE.MeshPhysicalMaterial({
138
- color: child.material.color ? child.material.color.getHex() : 0xffffff,
139
- metalness: 0.5,
140
- roughness: 0.1,
141
- clearcoat: 1.0,
142
- clearcoatRoughness: 0.1,
143
- });
144
- } else {
145
- // revert to original material
146
- if (originalMaterials.has(child)) {
147
- child.material = originalMaterials.get(child);
148
- }
149
- }
150
- }
151
- });
152
- }
153
-
154
- // Add light to scene from the select dropdown
155
- function addLight() {
156
- const type = document.getElementById('lightType').value;
157
- let light;
158
- switch (type) {
159
- case "ambient":
160
- light = new THREE.AmbientLight(0xffffff, 0.5);
161
- break;
162
- case "point":
163
- light = new THREE.PointLight(0xffffff, 1);
164
- light.position.set(2, 2, 2);
165
- break;
166
- case "directional":
167
- light = new THREE.DirectionalLight(0xffffff, 1);
168
- light.position.set(5, 5, 5);
169
- break;
170
- default:
171
- light = new THREE.AmbientLight(0xffffff, 0.5);
172
- }
173
- scene.add(light);
174
- }
175
-
176
- // Handle file loading for STL and OBJ files
177
- function handleFile(files) {
178
- if (files.length === 0) return;
179
- const file = files[0];
180
- const reader = new FileReader();
181
- reader.addEventListener("load", function (event) {
182
- const contents = event.target.result;
183
- let loader;
184
- const extension = file.name.split('.').pop().toLowerCase();
185
- if (extension === 'stl') {
186
- loader = new THREE.STLLoader();
187
- const geometry = loader.parse(contents);
188
- const material = new THREE.MeshStandardMaterial({ color: 0x606060 });
189
- const mesh = new THREE.Mesh(geometry, material);
190
- mesh.name = file.name;
191
- mesh.position.set(0, 0, 0);
192
- scene.add(mesh);
193
- } else if (extension === 'obj') {
194
- loader = new THREE.OBJLoader();
195
- const object = loader.parse(contents);
196
- object.name = file.name;
197
- scene.add(object);
198
- } else {
199
- alert("Unsupported file type. Please load an STL or OBJ file.");
200
- }
201
- }, false);
202
-
203
- // Read file as appropriate (for STL use arraybuffer; for OBJ use text)
204
- if (file.name.endsWith(".stl")) {
205
- reader.readAsArrayBuffer(file);
206
- } else {
207
- reader.readAsText(file);
208
- }
209
- }
210
-
211
- // Export scene objects as STL or OBJ
212
- function exportScene() {
213
- const exportType = document.getElementById("exportType").value;
214
- let exportedData;
215
- if (exportType === "stl") {
216
- const exporter = new THREE.STLExporter();
217
- // Export only mesh objects (ignoring helpers)
218
- const meshes = [];
219
- scene.traverse((child) => {
220
  if (child.isMesh) {
221
- meshes.push(child);
222
  }
223
- });
224
- exportedData = exporter.parse(meshes);
225
- downloadFile(exportedData, "scene.stl", "application/sla");
226
- } else if (exportType === "obj") {
227
- const exporter = new THREE.OBJExporter();
228
- exportedData = exporter.parse(scene);
229
- downloadFile(exportedData, "scene.obj", "text/plain");
230
- }
231
- }
232
-
233
- // Utility to force download
234
- function downloadFile(data, filename, type) {
235
- const blob = new Blob([data], { type: type });
236
- const link = document.createElement("a");
237
- link.href = window.URL.createObjectURL(blob);
238
- link.download = filename;
239
- link.click();
240
- }
241
-
242
- // Event listeners
243
- document.getElementById('toggleRaytrace').addEventListener('click', toggleRaytrace);
244
- document.getElementById('addLight').addEventListener('click', addLight);
245
- document.getElementById('fileInput').addEventListener('change', (e) => handleFile(e.target.files));
246
- document.getElementById('exportScene').addEventListener('click', exportScene);
247
-
248
- // Initialize the scene
249
- init();
250
- </script>
251
- </body>
 
 
 
 
 
 
 
 
 
 
 
252
  </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 Scene Editor with Raytracing</title>
 
7
  <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/STLLoader.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/OBJLoader.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/exporters/STLExporter.js"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/exporters/OBJExporter.js"></script>
14
+ </head>
15
+ <body class="bg-gray-900">
16
+ <div class="flex h-screen">
17
+ <!-- Sidebar -->
18
+ <div class="w-64 bg-gray-800 p-4 space-y-4">
19
+ <div class="space-y-2">
20
+ <input type="file" id="file-input" class="hidden" accept=".stl,.obj">
21
+ <button onclick="document.getElementById('file-input').click()"
22
+ class="w-full bg-blue-600 hover:bg-blue-700 text-white p-2 rounded-lg">
23
+ <i class="fas fa-upload mr-2"></i>Load Model
24
+ </button>
25
+
26
+ <button onclick="exportSTL()"
27
+ class="w-full bg-green-600 hover:bg-green-700 text-white p-2 rounded-lg">
28
+ <i class="fas fa-file-export mr-2"></i>Export STL
29
+ </button>
30
+
31
+ <button onclick="exportOBJ()"
32
+ class="w-full bg-green-600 hover:bg-green-700 text-white p-2 rounded-lg">
33
+ <i class="fas fa-file-export mr-2"></i>Export OBJ
34
+ </button>
35
+
36
+ <button onclick="toggleRaytracing()"
37
+ id="raytrace-btn"
38
+ class="w-full bg-purple-600 hover:bg-purple-700 text-white p-2 rounded-lg">
39
+ <i class="fas fa-raygun mr-2"></i>Raytracing: On
40
+ </button>
41
+ </div>
42
+
43
+ <div class="border-t border-gray-700 pt-4">
44
+ <h3 class="text-white mb-2">Lights</h3>
45
+ <button onclick="addLight('point')"
46
+ class="w-full bg-yellow-600 hover:bg-yellow-700 text-white p-2 rounded-lg mb-2">
47
+ <i class="fas fa-lightbulb mr-2"></i>Add Point Light
48
+ </button>
49
+ <button onclick="addLight('directional')"
50
+ class="w-full bg-yellow-600 hover:bg-yellow-700 text-white p-2 rounded-lg">
51
+ <i class="fas fa-sun mr-2"></i>Add Directional Light
52
+ </button>
53
+ </div>
54
  </div>
55
+
56
+ <!-- Main Viewport -->
57
+ <div id="viewport" class="flex-1"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  </div>
59
 
60
+ <script>
61
+ let scene, camera, renderer, raytracingEnabled = true;
62
+ let objects = [];
63
+
64
+ function init() {
65
+ // Scene setup
66
+ scene = new THREE.Scene();
67
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
68
+ renderer = new THREE.WebGLRenderer({ antialias: true });
69
+ renderer.setSize(window.innerWidth-256, window.innerHeight);
70
+ document.getElementById('viewport').appendChild(renderer.domElement);
71
+
72
+ // Basic lighting
73
+ const ambientLight = new THREE.AmbientLight(0x404040);
74
+ scene.add(ambientLight);
75
+
76
+ // Camera position
77
+ camera.position.z = 5;
78
+
79
+ // File input handler
80
+ document.getElementById('file-input').addEventListener('change', handleFileUpload);
81
+
82
+ // Animation loop
83
+ animate();
84
+ }
85
+
86
+ function handleFileUpload(event) {
87
+ const file = event.target.files[0];
88
+ const reader = new FileReader();
89
+
90
+ reader.onload = function(e) {
91
+ const loader = file.name.endsWith('.stl') ?
92
+ new THREE.STLLoader() : new THREE.OBJLoader();
93
+
94
+ const model = loader.parse(e.target.result);
95
+ model.scale.set(0.1, 0.1, 0.1);
96
+ scene.add(model);
97
+ objects.push(model);
98
+ };
99
+
100
+ reader.readAsArrayBuffer(file);
101
+ }
102
+
103
+ function exportSTL() {
104
+ const exporter = new THREE.STLExporter();
105
+ const stlString = exporter.parse(scene);
106
+ const blob = new Blob([stlString], {type: 'text/plain'});
107
+ saveAs(blob, 'scene.stl');
108
+ }
109
+
110
+ function exportOBJ() {
111
+ const exporter = new THREE.OBJExporter();
112
+ const objString = exporter.parse(scene);
113
+ const blob = new Blob([objString], {type: 'text/plain'});
114
+ saveAs(blob, 'scene.obj');
115
+ }
116
+
117
+ function toggleRaytracing() {
118
+ raytracingEnabled = !raytracingEnabled;
119
+ document.getElementById('raytrace-btn').innerHTML =
120
+ `<i class="fas fa-raygun mr-2"></i>Raytracing: ${raytracingEnabled ? 'On' : 'Off'}`;
121
+
122
+ objects.forEach(obj => {
123
+ obj.traverse(child => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  if (child.isMesh) {
125
+ child.material.wireframe = !raytracingEnabled;
126
  }
127
+ });
128
+ });
129
+ }
130
+
131
+ function addLight(type) {
132
+ let light;
133
+ if (type === 'point') {
134
+ light = new THREE.PointLight(0xffffff, 1, 100);
135
+ light.position.set(5, 5, 5);
136
+ } else {
137
+ light = new THREE.DirectionalLight(0xffffff, 1);
138
+ light.position.set(5, 5, 5);
139
+ }
140
+ scene.add(light);
141
+ }
142
+
143
+ function animate() {
144
+ requestAnimationFrame(animate);
145
+ renderer.render(scene, camera);
146
+ }
147
+
148
+ // Start the application
149
+ init();
150
+
151
+ // Helper function to save files
152
+ function saveAs(blob, filename) {
153
+ const link = document.createElement('a');
154
+ link.href = URL.createObjectURL(blob);
155
+ link.download = filename;
156
+ link.click();
157
+ }
158
+
159
+ // Window resize handler
160
+ window.addEventListener('resize', () => {
161
+ camera.aspect = (window.innerWidth-256) / window.innerHeight;
162
+ camera.updateProjectionMatrix();
163
+ renderer.setSize(window.innerWidth-256, window.innerHeight);
164
+ });
165
+ </script>
166
+ </body>
167
  </html>