122 lines
4.4 KiB
HTML
122 lines
4.4 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>TRELLIS 3D Preview</title>
|
|
<style>
|
|
body { margin: 0; background: #1a1a1a; }
|
|
#container {
|
|
width: 100vw;
|
|
height: 100vh;
|
|
}
|
|
#model-view {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
}
|
|
.loading {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
color: white;
|
|
font-family: Arial, sans-serif;
|
|
z-index: 101;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div class="loading">Loading...</div>
|
|
<div id="model-view"></div>
|
|
</div>
|
|
|
|
<script type="module">
|
|
import * as THREE from 'https://unpkg.com/three@0.157.0/build/three.module.js';
|
|
import { GLTFLoader } from 'https://unpkg.com/three@0.157.0/examples/jsm/loaders/GLTFLoader.js';
|
|
import { OrbitControls } from 'https://unpkg.com/three@0.157.0/examples/jsm/controls/OrbitControls.js';
|
|
|
|
// Get URL parameters
|
|
const params = new URLSearchParams(window.location.search);
|
|
const glbPath = params.get('glb');
|
|
|
|
// Setup Three.js viewer
|
|
const container = document.getElementById('model-view');
|
|
const scene = new THREE.Scene();
|
|
const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
|
|
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
|
renderer.setSize(container.clientWidth, container.clientHeight);
|
|
container.appendChild(renderer.domElement);
|
|
|
|
const controls = new OrbitControls(camera, renderer.domElement);
|
|
controls.enableDamping = true;
|
|
controls.dampingFactor = 0.05;
|
|
controls.target.set(0, 0, 0); // Orbit around the origin
|
|
|
|
camera.position.z = 5;
|
|
|
|
// Add lights
|
|
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
|
|
scene.add(ambientLight);
|
|
|
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
directionalLight.position.set(1, 1, 1);
|
|
scene.add(directionalLight);
|
|
|
|
// Loading indicator
|
|
const loadingText = document.querySelector('.loading');
|
|
|
|
// Load model if path provided
|
|
if (glbPath) {
|
|
const loader = new GLTFLoader();
|
|
loader.load(
|
|
glbPath,
|
|
(gltf) => {
|
|
scene.add(gltf.scene);
|
|
|
|
// Center and scale model
|
|
const box = new THREE.Box3().setFromObject(gltf.scene);
|
|
const center = box.getCenter(new THREE.Vector3());
|
|
const size = box.getSize(new THREE.Vector3());
|
|
|
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
const scale = 2.0 / maxDim;
|
|
gltf.scene.scale.multiplyScalar(scale);
|
|
|
|
gltf.scene.position.sub(center.multiplyScalar(scale));
|
|
|
|
// Hide loading text
|
|
loadingText.style.display = 'none';
|
|
},
|
|
(xhr) => {
|
|
// Called while loading is progressing
|
|
const percent = (xhr.loaded / xhr.total * 100).toFixed(0);
|
|
loadingText.textContent = `Loading model... ${percent}%`;
|
|
},
|
|
(error) => {
|
|
console.error('Error loading model:', error);
|
|
loadingText.textContent = 'Error loading model';
|
|
}
|
|
);
|
|
}
|
|
|
|
// Animation loop
|
|
function animate() {
|
|
requestAnimationFrame(animate);
|
|
controls.update();
|
|
renderer.render(scene, camera);
|
|
}
|
|
animate();
|
|
|
|
// Handle window resize
|
|
window.addEventListener('resize', () => {
|
|
const width = container.clientWidth;
|
|
const height = container.clientHeight;
|
|
|
|
camera.aspect = width / height;
|
|
camera.updateProjectionMatrix();
|
|
renderer.setSize(width, height);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |