WEBLEB
Home
Editor
Accedi
Pro
Italiano
English
Français
Español
Português
Deutsch
Italiano
हिंदी
HTML
CSS
JS
3D Physics Cube Room
3D Physics Cube Room
Spawn Cube
Reset Scene
body { background: #181c20; color: #fff; font-family: sans-serif; text-align: center; margin: 0; padding: 0; } #viewer-container { width: 100vw; height: 80vh; display: flex; justify-content: center; align-items: center; background: #111; } #controls { margin: 20px 0; } button { margin: 0 10px; padding: 12px 24px; font-size: 1.1em; border: none; border-radius: 6px; background: #61dafb; color: #222; cursor: pointer; transition: background 0.2s; } button:hover { background: #21a1f3; color: #fff; }
// --- SCENE, CAMERA, RENDERER, CONTROLS --- let scene, camera, renderer, controls; // --- CANNON PHYSICS WORLD --- let world; // --- CUBES: Arrays of {mesh, body} --- let cubes = []; // --- ROOM SIZE --- const ROOM_SIZE = 10; const HALF_ROOM = ROOM_SIZE / 2; // --- PHYSICS MATERIALS --- let cubeMaterial, groundMaterial, contactMaterial; function init() { // Scene & Camera scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / (window.innerHeight * 0.8), 0.1, 1000 ); camera.position.set(8, 8, 8); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight * 0.8); document.getElementById("viewer-container").appendChild(renderer.domElement); controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.1; // Lighting scene.add(new THREE.AmbientLight(0xffffff, 0.8)); let dirLight = new THREE.DirectionalLight(0xffffff, 0.5); dirLight.position.set(10, 20, 10); scene.add(dirLight); // Physics world world = new CANNON.World(); world.gravity.set(0, -9.82, 0); world.broadphase = new CANNON.NaiveBroadphase(); world.solver.iterations = 12; // Materials for realistic collision cubeMaterial = new CANNON.Material("cubeMaterial"); groundMaterial = new CANNON.Material("groundMaterial"); contactMaterial = new CANNON.ContactMaterial( cubeMaterial, groundMaterial, { friction: 0.4, restitution: 0.5, } ); world.addContactMaterial(contactMaterial); // --- ROOM: Walls, Floor, Ceiling in Three.js and Cannon.js --- createRoom(); // --- BUTTONS --- document.getElementById("spawn-cube").onclick = spawnCube; document.getElementById("reset-scene").onclick = resetScene; // --- RENDER LOOP --- animate(); } // --- ROOM CREATION: Visual and Physics Walls --- function createRoom() { // Floor (THREE) let floorGeo = new THREE.PlaneGeometry(ROOM_SIZE, ROOM_SIZE); let floorMat = new THREE.MeshStandardMaterial({ color: 0x888888 }); let floorMesh = new THREE.Mesh(floorGeo, floorMat); floorMesh.rotation.x = -Math.PI / 2; floorMesh.position.y = 0; scene.add(floorMesh); // Floor (CANNON) let floorBody = new CANNON.Body({ mass: 0, material: groundMaterial, shape: new CANNON.Plane() }); floorBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0); floorBody.position.set(0, 0, 0); world.addBody(floorBody); // Ceiling (visual only) let ceilGeo = new THREE.PlaneGeometry(ROOM_SIZE, ROOM_SIZE); let ceilMat = new THREE.MeshStandardMaterial({ color: 0x444444, side: THREE.BackSide, transparent: true, opacity: 0.4 }); let ceilMesh = new THREE.Mesh(ceilGeo, ceilMat); ceilMesh.rotation.x = Math.PI / 2; ceilMesh.position.y = ROOM_SIZE; scene.add(ceilMesh); // Walls (THREE + CANNON) addWall("z", HALF_ROOM, 0, 0); // back addWall("z", -HALF_ROOM, Math.PI, 0); // front addWall("x", HALF_ROOM, -Math.PI / 2, 0); // right addWall("x", -HALF_ROOM, Math.PI / 2, 0); // left } // --- ADD A WALL (visual and physics) --- function addWall(axis, pos, rotY, rotZ) { // Visual let wallGeo = new THREE.PlaneGeometry(ROOM_SIZE, ROOM_SIZE); let wallMat = new THREE.MeshStandardMaterial({ color: 0x666666, side: THREE.DoubleSide, transparent: true, opacity: 0.25 }); let wallMesh = new THREE.Mesh(wallGeo, wallMat); if (axis === "z") { wallMesh.position.z = pos; wallMesh.position.y = HALF_ROOM; wallMesh.rotation.y = rotY; } else { wallMesh.position.x = pos; wallMesh.position.y = HALF_ROOM; wallMesh.rotation.y = rotY; } scene.add(wallMesh); // Physics let wallShape = new CANNON.Plane(); let wallBody = new CANNON.Body({ mass: 0, material: groundMaterial }); if (axis === "z") { wallBody.quaternion.setFromEuler(-Math.PI / 2, rotY, 0); wallBody.position.set(0, HALF_ROOM, pos); } else { wallBody.quaternion.setFromEuler(-Math.PI / 2, rotY, 0); wallBody.position.set(pos, HALF_ROOM, 0); } world.addBody(wallBody); } // --- SPAWN CUBE --- function spawnCube() { const size = 1; // THREE let geometry = new THREE.BoxGeometry(size, size, size); let material = new THREE.MeshStandardMaterial({ color: Math.random() * 0xffffff, metalness: 0.4, roughness: 0.7 }); let mesh = new THREE.Mesh(geometry, material); // Random position near top mesh.position.set( (Math.random() - 0.5) * (ROOM_SIZE - 2), ROOM_SIZE - 1.5, (Math.random() - 0.5) * (ROOM_SIZE - 2) ); scene.add(mesh); // CANNON let shape = new CANNON.Box(new CANNON.Vec3(size / 2, size / 2, size / 2)); let body = new CANNON.Body({ mass: 1, shape: shape, material: cubeMaterial, position: new CANNON.Vec3(mesh.position.x, mesh.position.y, mesh.position.z) }); // Give a small random velocity for fun body.velocity.set( (Math.random() - 0.5) * 3, Math.random() * 2, (Math.random() - 0.5) * 3 ); world.addBody(body); cubes.push({ mesh, body }); } // --- RESET SCENE: Remove all cubes --- function resetScene() { cubes.forEach(({ mesh, body }) => { scene.remove(mesh); world.remove(body); }); cubes = []; } // --- ANIMATION LOOP --- function animate() { requestAnimationFrame(animate); // Step physics world.step(1 / 60); // Sync cube meshes with their physics bodies cubes.forEach(({ mesh, body }) => { mesh.position.copy(body.position); mesh.quaternion.copy(body.quaternion); }); controls.update(); renderer.render(scene, camera); } // --- RESPONSIVE --- window.addEventListener("resize", () => { camera.aspect = window.innerWidth / (window.innerHeight * 0.8); camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight * 0.8); }); // --- INIT --- init();
Validating your code, please wait...
HTML
CSS
JS
3D Physics Cube Room
3D Physics Cube Room
Spawn Cube
Reset Scene
body { background: #181c20; color: #fff; font-family: sans-serif; text-align: center; margin: 0; padding: 0; } #viewer-container { width: 100vw; height: 80vh; display: flex; justify-content: center; align-items: center; background: #111; } #controls { margin: 20px 0; } button { margin: 0 10px; padding: 12px 24px; font-size: 1.1em; border: none; border-radius: 6px; background: #61dafb; color: #222; cursor: pointer; transition: background 0.2s; } button:hover { background: #21a1f3; color: #fff; }
// --- SCENE, CAMERA, RENDERER, CONTROLS --- let scene, camera, renderer, controls; // --- CANNON PHYSICS WORLD --- let world; // --- CUBES: Arrays of {mesh, body} --- let cubes = []; // --- ROOM SIZE --- const ROOM_SIZE = 10; const HALF_ROOM = ROOM_SIZE / 2; // --- PHYSICS MATERIALS --- let cubeMaterial, groundMaterial, contactMaterial; function init() { // Scene & Camera scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / (window.innerHeight * 0.8), 0.1, 1000 ); camera.position.set(8, 8, 8); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight * 0.8); document.getElementById("viewer-container").appendChild(renderer.domElement); controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.1; // Lighting scene.add(new THREE.AmbientLight(0xffffff, 0.8)); let dirLight = new THREE.DirectionalLight(0xffffff, 0.5); dirLight.position.set(10, 20, 10); scene.add(dirLight); // Physics world world = new CANNON.World(); world.gravity.set(0, -9.82, 0); world.broadphase = new CANNON.NaiveBroadphase(); world.solver.iterations = 12; // Materials for realistic collision cubeMaterial = new CANNON.Material("cubeMaterial"); groundMaterial = new CANNON.Material("groundMaterial"); contactMaterial = new CANNON.ContactMaterial( cubeMaterial, groundMaterial, { friction: 0.4, restitution: 0.5, } ); world.addContactMaterial(contactMaterial); // --- ROOM: Walls, Floor, Ceiling in Three.js and Cannon.js --- createRoom(); // --- BUTTONS --- document.getElementById("spawn-cube").onclick = spawnCube; document.getElementById("reset-scene").onclick = resetScene; // --- RENDER LOOP --- animate(); } // --- ROOM CREATION: Visual and Physics Walls --- function createRoom() { // Floor (THREE) let floorGeo = new THREE.PlaneGeometry(ROOM_SIZE, ROOM_SIZE); let floorMat = new THREE.MeshStandardMaterial({ color: 0x888888 }); let floorMesh = new THREE.Mesh(floorGeo, floorMat); floorMesh.rotation.x = -Math.PI / 2; floorMesh.position.y = 0; scene.add(floorMesh); // Floor (CANNON) let floorBody = new CANNON.Body({ mass: 0, material: groundMaterial, shape: new CANNON.Plane() }); floorBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0); floorBody.position.set(0, 0, 0); world.addBody(floorBody); // Ceiling (visual only) let ceilGeo = new THREE.PlaneGeometry(ROOM_SIZE, ROOM_SIZE); let ceilMat = new THREE.MeshStandardMaterial({ color: 0x444444, side: THREE.BackSide, transparent: true, opacity: 0.4 }); let ceilMesh = new THREE.Mesh(ceilGeo, ceilMat); ceilMesh.rotation.x = Math.PI / 2; ceilMesh.position.y = ROOM_SIZE; scene.add(ceilMesh); // Walls (THREE + CANNON) addWall("z", HALF_ROOM, 0, 0); // back addWall("z", -HALF_ROOM, Math.PI, 0); // front addWall("x", HALF_ROOM, -Math.PI / 2, 0); // right addWall("x", -HALF_ROOM, Math.PI / 2, 0); // left } // --- ADD A WALL (visual and physics) --- function addWall(axis, pos, rotY, rotZ) { // Visual let wallGeo = new THREE.PlaneGeometry(ROOM_SIZE, ROOM_SIZE); let wallMat = new THREE.MeshStandardMaterial({ color: 0x666666, side: THREE.DoubleSide, transparent: true, opacity: 0.25 }); let wallMesh = new THREE.Mesh(wallGeo, wallMat); if (axis === "z") { wallMesh.position.z = pos; wallMesh.position.y = HALF_ROOM; wallMesh.rotation.y = rotY; } else { wallMesh.position.x = pos; wallMesh.position.y = HALF_ROOM; wallMesh.rotation.y = rotY; } scene.add(wallMesh); // Physics let wallShape = new CANNON.Plane(); let wallBody = new CANNON.Body({ mass: 0, material: groundMaterial }); if (axis === "z") { wallBody.quaternion.setFromEuler(-Math.PI / 2, rotY, 0); wallBody.position.set(0, HALF_ROOM, pos); } else { wallBody.quaternion.setFromEuler(-Math.PI / 2, rotY, 0); wallBody.position.set(pos, HALF_ROOM, 0); } world.addBody(wallBody); } // --- SPAWN CUBE --- function spawnCube() { const size = 1; // THREE let geometry = new THREE.BoxGeometry(size, size, size); let material = new THREE.MeshStandardMaterial({ color: Math.random() * 0xffffff, metalness: 0.4, roughness: 0.7 }); let mesh = new THREE.Mesh(geometry, material); // Random position near top mesh.position.set( (Math.random() - 0.5) * (ROOM_SIZE - 2), ROOM_SIZE - 1.5, (Math.random() - 0.5) * (ROOM_SIZE - 2) ); scene.add(mesh); // CANNON let shape = new CANNON.Box(new CANNON.Vec3(size / 2, size / 2, size / 2)); let body = new CANNON.Body({ mass: 1, shape: shape, material: cubeMaterial, position: new CANNON.Vec3(mesh.position.x, mesh.position.y, mesh.position.z) }); // Give a small random velocity for fun body.velocity.set( (Math.random() - 0.5) * 3, Math.random() * 2, (Math.random() - 0.5) * 3 ); world.addBody(body); cubes.push({ mesh, body }); } // --- RESET SCENE: Remove all cubes --- function resetScene() { cubes.forEach(({ mesh, body }) => { scene.remove(mesh); world.remove(body); }); cubes = []; } // --- ANIMATION LOOP --- function animate() { requestAnimationFrame(animate); // Step physics world.step(1 / 60); // Sync cube meshes with their physics bodies cubes.forEach(({ mesh, body }) => { mesh.position.copy(body.position); mesh.quaternion.copy(body.quaternion); }); controls.update(); renderer.render(scene, camera); } // --- RESPONSIVE --- window.addEventListener("resize", () => { camera.aspect = window.innerWidth / (window.innerHeight * 0.8); camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight * 0.8); }); // --- INIT --- init();