-
-
Save Aakash67/062d5e96618918dfa0e74cf350599818 to your computer and use it in GitHub Desktop.
Interactive Bouncing Balls in a 3D Cube by Grok 3 Think mode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>3D Scene with Bouncing Balls</title> | |
| <style> | |
| body { margin: 0; } | |
| canvas { display: block; } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Include Three.js and OrbitControls from CDN --> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script> | |
| <script> | |
| // Initialize Scene, Camera, and Renderer | |
| const scene = new THREE.Scene(); | |
| const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
| camera.position.set(0, 0, 5); | |
| const renderer = new THREE.WebGLRenderer(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| document.body.appendChild(renderer.domElement); | |
| // Define Cube Size | |
| const cubeSize = 3; | |
| const cubeHalfSize = cubeSize / 2; // 1.5 | |
| // Create the Transparent Cube | |
| const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize); | |
| const cubeMaterial = new THREE.MeshPhongMaterial({ | |
| color: 0xffffff, | |
| transparent: true, | |
| opacity: 0.5, | |
| side: THREE.DoubleSide | |
| }); | |
| const cube = new THREE.Mesh(cubeGeometry, cubeMaterial); | |
| scene.add(cube); | |
| // Create 10 Colored Balls | |
| const sphereGeometry = new THREE.SphereGeometry(0.2, 32, 32); | |
| const colors = [ | |
| 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, | |
| 0x00ffff, 0x990000, 0x009900, 0x000099, 0x999900 | |
| ]; | |
| const balls = []; | |
| for (let i = 0; i < 10; i++) { | |
| const material = new THREE.MeshPhongMaterial({ color: colors[i] }); | |
| const ball = new THREE.Mesh(sphereGeometry, material); | |
| const ballRadius = 0.2; | |
| const positionRange = 2 * (cubeHalfSize - ballRadius); // 2 * (1.5 - 0.2) = 2.6 | |
| ball.position.set( | |
| (Math.random() - 0.5) * positionRange, | |
| (Math.random() - 0.5) * positionRange, | |
| (Math.random() - 0.5) * positionRange | |
| ); | |
| ball.velocity = new THREE.Vector3( | |
| (Math.random() - 0.5) * 0.06, | |
| (Math.random() - 0.5) * 0.06, | |
| (Math.random() - 0.5) * 0.06 | |
| ); | |
| scene.add(ball); | |
| balls.push(ball); | |
| } | |
| // Add Lighting | |
| const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); | |
| scene.add(ambientLight); | |
| const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); | |
| directionalLight.position.set(1, 1, 1); | |
| scene.add(directionalLight); | |
| // Set Up OrbitControls | |
| const controls = new THREE.OrbitControls(camera, renderer.domElement); | |
| controls.enableDamping = true; | |
| controls.dampingFactor = 0.05; | |
| // Mouse Tracking | |
| const mouse = new THREE.Vector2(); | |
| window.addEventListener('mousemove', (event) => { | |
| mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | |
| mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; | |
| }, false); | |
| // Raycaster for Mouse Interaction | |
| const raycaster = new THREE.Raycaster(); | |
| // Animation Loop | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| controls.update(); | |
| // Update ball positions based on mouse and camera | |
| raycaster.setFromCamera(mouse, camera); | |
| const intersects = raycaster.intersectObject(cube); | |
| if (intersects.length > 0) { | |
| const targetPosition = intersects[0].point; | |
| const k = 0.001; // Attraction strength | |
| const damping = 0.99; // Velocity damping | |
| const ballRadius = 0.2; | |
| balls.forEach(ball => { | |
| ball.velocity.multiplyScalar(damping); | |
| const direction = new THREE.Vector3().subVectors(targetPosition, ball.position); | |
| const force = direction.multiplyScalar(k); | |
| ball.velocity.add(force); | |
| ball.position.add(ball.velocity); | |
| // Bounce off cube walls | |
| if (ball.position.x - ballRadius < -cubeHalfSize) { | |
| ball.position.x = -cubeHalfSize + ballRadius; | |
| ball.velocity.x *= -1; | |
| } else if (ball.position.x + ballRadius > cubeHalfSize) { | |
| ball.position.x = cubeHalfSize - ballRadius; | |
| ball.velocity.x *= -1; | |
| } | |
| if (ball.position.y - ballRadius < -cubeHalfSize) { | |
| ball.position.y = -cubeHalfSize + ballRadius; | |
| ball.velocity.y *= -1; | |
| } else if (ball.position.y + ballRadius > cubeHalfSize) { | |
| ball.position.y = cubeHalfSize - ballRadius; | |
| ball.velocity.y *= -1; | |
| } | |
| if (ball.position.z - ballRadius < -cubeHalfSize) { | |
| ball.position.z = -cubeHalfSize + ballRadius; | |
| ball.velocity.z *= -1; | |
| } else if (ball.position.z + ballRadius > cubeHalfSize) { | |
| ball.position.z = cubeHalfSize - ballRadius; | |
| ball.velocity.z *= -1; | |
| } | |
| }); | |
| } | |
| renderer.render(scene, camera); | |
| } | |
| // Start the animation | |
| animate(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment