|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>3D Creation Studio</title> |
|
<script src="https://cdn.tailwindcss.com"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script> |
|
<script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> |
|
<style> |
|
#scene-container { |
|
width: 100%; |
|
height: 100%; |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
z-index: 0; |
|
} |
|
|
|
.sidebar-slide { |
|
transition: transform 0.3s ease-in-out; |
|
} |
|
|
|
.tool-icon { |
|
transition: all 0.2s ease; |
|
} |
|
|
|
.tool-icon:hover { |
|
transform: scale(1.1); |
|
filter: drop-shadow(0 0 8px rgba(59, 130, 246, 0.5)); |
|
} |
|
|
|
.scene-overlay { |
|
pointer-events: none; |
|
} |
|
|
|
.grid-toggle.active { |
|
background-color: #3b82f6; |
|
color: white; |
|
} |
|
</style> |
|
</head> |
|
<body class="bg-gray-900 text-gray-200 overflow-hidden"> |
|
|
|
<header class="bg-gray-800 bg-opacity-90 border-b border-gray-700 fixed top-0 left-0 right-0 z-50 h-14 flex items-center px-4 shadow-lg"> |
|
<div class="flex items-center space-x-2"> |
|
<div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center"> |
|
<i class="fas fa-cube text-white"></i> |
|
</div> |
|
<h1 class="text-xl font-bold text-blue-400">3D Creation Studio</h1> |
|
</div> |
|
|
|
<div class="ml-auto flex items-center space-x-4"> |
|
<button class="px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded-md text-sm flex items-center space-x-1"> |
|
<i class="fas fa-save"></i> |
|
<span>Save</span> |
|
</button> |
|
<button class="px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded-md text-sm flex items-center space-x-1"> |
|
<i class="fas fa-share-alt"></i> |
|
<span>Export</span> |
|
</button> |
|
<div class="w-px h-6 bg-gray-600"></div> |
|
<button class="w-8 h-8 rounded-full bg-gray-700 hover:bg-gray-600 flex items-center justify-center"> |
|
<i class="fas fa-user"></i> |
|
</button> |
|
</div> |
|
</header> |
|
|
|
|
|
<aside class="fixed right-0 top-14 bottom-0 w-64 bg-gray-800 bg-opacity-90 border-l border-gray-700 z-40 flex flex-col shadow-xl"> |
|
<div class="p-4 border-b border-gray-700"> |
|
<h2 class="font-semibold text-lg flex items-center justify-between"> |
|
<span>Scene Properties</span> |
|
<i class="fas fa-cog text-blue-400"></i> |
|
</h2> |
|
</div> |
|
|
|
<div class="flex-1 overflow-y-auto p-4 space-y-6"> |
|
|
|
<div> |
|
<h3 class="font-medium text-sm uppercase text-gray-400 mb-2">Selected Object</h3> |
|
<div class="space-y-3"> |
|
<div class="flex justify-between items-center"> |
|
<span>Position</span> |
|
<div class="flex space-x-2"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" placeholder="X"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" placeholder="Y"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" placeholder="Z"> |
|
</div> |
|
</div> |
|
<div class="flex justify-between items-center"> |
|
<span>Rotation</span> |
|
<div class="flex space-x-2"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" placeholder="X"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" placeholder="Y"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" placeholder="Z"> |
|
</div> |
|
</div> |
|
<div class="flex justify-between items-center"> |
|
<span>Scale</span> |
|
<div class="flex space-x-2"> |
|
<input type="number" class="w-16 bg-gray-700 rounded px-2 py-1 text-sm" value="1"> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div> |
|
<h3 class="font-medium text-sm uppercase text-gray-400 mb-2">Material</h3> |
|
<div class="space-y-3"> |
|
<div class="flex justify-between items-center"> |
|
<span>Color</span> |
|
<input type="color" class="w-8 h-8 bg-gray-700 rounded cursor-pointer" value="#3b82f6"> |
|
</div> |
|
<div class="flex justify-between items-center"> |
|
<span>Metalness</span> |
|
<input type="range" min="0" max="1" step="0.1" class="w-24" value="0"> |
|
</div> |
|
<div class="flex justify-between items-center"> |
|
<span>Roughness</span> |
|
<input type="range" min="0" max="1" step="0.1" class="w-24" value="1"> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div> |
|
<h3 class="font-medium text-sm uppercase text-gray-400 mb-2">Lighting</h3> |
|
<div class="space-y-2"> |
|
<div class="flex justify-between items-center"> |
|
<span>Intensity</span> |
|
<input type="range" min="0" max="2" step="0.1" class="w-24" value="1"> |
|
</div> |
|
<div class="flex justify-between items-center"> |
|
<span>Ambient Light</span> |
|
<input type="range" min="0" max="1" step="0.1" class="w-24" value="0.2"> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</aside> |
|
|
|
|
|
<div class="fixed right-4 bottom-4 z-50 flex flex-col space-y-2"> |
|
<button id="grid-toggle" class="grid-toggle w-12 h-12 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center shadow-lg tool-icon"> |
|
<i class="fas fa-th"></i> |
|
</button> |
|
<button class="w-12 h-12 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center shadow-lg tool-icon"> |
|
<i class="fas fa-ruler-combined"></i> |
|
</button> |
|
<button class="w-12 h-12 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center shadow-lg tool-icon"> |
|
<i class="fas fa-lightbulb"></i> |
|
</button> |
|
<button class="w-12 h-12 bg-blue-600 hover:bg-blue-500 rounded-full flex items-center justify-center shadow-lg tool-icon"> |
|
<i class="fas fa-question"></i> |
|
</button> |
|
</div> |
|
|
|
|
|
<div id="scene-container"></div> |
|
|
|
|
|
<div class="scene-overlay fixed top-14 left-0 right-64 bottom-0 flex items-center justify-center pointer-events-none"> |
|
<div class="absolute top-4 left-4 bg-gray-800 bg-opacity-70 px-3 py-1 rounded-md text-sm"> |
|
<span class="text-blue-400">Perspective</span> | <span>FPS: <span id="fps-counter">60</span></span> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="fixed left-4 top-20 bg-gray-800 bg-opacity-90 rounded-lg shadow-xl p-2 z-40"> |
|
<h3 class="text-sm font-medium mb-2 px-2">Create Object</h3> |
|
<div class="grid grid-cols-3 gap-2"> |
|
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded flex flex-col items-center tool-icon"> |
|
<i class="fas fa-cube mb-1"></i> |
|
<span class="text-xs">Cube</span> |
|
</button> |
|
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded flex flex-col items-center tool-icon"> |
|
<i class="fas fa-circle mb-1"></i> |
|
<span class="text-xs">Sphere</span> |
|
</button> |
|
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded flex flex-col items-center tool-icon"> |
|
<i class="fas fa-cylinder mb-1"></i> |
|
<span class="text-xs">Cylinder</span> |
|
</button> |
|
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded flex flex-col items-center tool-icon"> |
|
<i class="fas fa-cone mb-1"></i> |
|
<span class="text-xs">Cone</span> |
|
</button> |
|
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded flex flex-col items-center tool-icon"> |
|
<i class="fas fa-torus mb-1"></i> |
|
<span class="text-xs">Torus</span> |
|
</button> |
|
<button class="p-2 bg-gray-700 hover:bg-gray-600 rounded flex flex-col items-center tool-icon"> |
|
<i class="fas fa-lightbulb mb-1"></i> |
|
<span class="text-xs">Light</span> |
|
</button> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
|
|
let scene, camera, renderer, controls; |
|
|
|
function initThreeJS() { |
|
const container = document.getElementById('scene-container'); |
|
|
|
|
|
scene = new THREE.Scene(); |
|
scene.background = new THREE.Color(0x1a1a1a); |
|
|
|
|
|
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); |
|
camera.position.set(5, 5, 5); |
|
|
|
|
|
renderer = new THREE.WebGLRenderer({ antialias: true }); |
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
renderer.shadowMap.enabled = true; |
|
container.appendChild(renderer.domElement); |
|
|
|
|
|
controls = new THREE.OrbitControls(camera, renderer.domElement); |
|
controls.enableDamping = true; |
|
controls.dampingFactor = 0.05; |
|
|
|
|
|
const ambientLight = new THREE.AmbientLight(0x404040, 0.5); |
|
scene.add(ambientLight); |
|
|
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); |
|
directionalLight.position.set(5, 10, 7); |
|
directionalLight.castShadow = true; |
|
scene.add(directionalLight); |
|
|
|
|
|
const gridHelper = new THREE.GridHelper(20, 20, 0x555555, 0x333333); |
|
scene.add(gridHelper); |
|
|
|
|
|
const axesHelper = new THREE.AxesHelper(5); |
|
scene.add(axesHelper); |
|
|
|
|
|
const geometry = new THREE.BoxGeometry(); |
|
const material = new THREE.MeshStandardMaterial({ |
|
color: 0x3b82f6, |
|
metalness: 0.1, |
|
roughness: 0.5 |
|
}); |
|
const cube = new THREE.Mesh(geometry, material); |
|
cube.castShadow = true; |
|
scene.add(cube); |
|
|
|
|
|
const planeGeometry = new THREE.PlaneGeometry(20, 20); |
|
const planeMaterial = new THREE.MeshStandardMaterial({ |
|
color: 0x222222, |
|
side: THREE.DoubleSide |
|
}); |
|
const plane = new THREE.Mesh(planeGeometry, planeMaterial); |
|
plane.rotation.x = -Math.PI / 2; |
|
plane.receiveShadow = true; |
|
scene.add(plane); |
|
|
|
|
|
window.addEventListener('resize', () => { |
|
camera.aspect = window.innerWidth / window.innerHeight; |
|
camera.updateProjectionMatrix(); |
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
}); |
|
|
|
|
|
let lastTime = performance.now(); |
|
let frames = 0; |
|
|
|
|
|
function animate() { |
|
requestAnimationFrame(animate); |
|
|
|
controls.update(); |
|
renderer.render(scene, camera); |
|
|
|
|
|
frames++; |
|
const now = performance.now(); |
|
if (now >= lastTime + 1000) { |
|
document.getElementById('fps-counter').textContent = frames; |
|
frames = 0; |
|
lastTime = now; |
|
} |
|
} |
|
|
|
animate(); |
|
} |
|
|
|
|
|
function initUI() { |
|
|
|
document.getElementById('grid-toggle').addEventListener('click', function() { |
|
this.classList.toggle('active'); |
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
initThreeJS(); |
|
initUI(); |
|
}); |
|
</script> |
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=DK9/3d-viewer" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
</html> |