Created
February 4, 2025 04:53
-
-
Save sperand-io/650064e3c6d7c8cbcc40d95aa052d27c to your computer and use it in GitHub Desktop.
coplanar points on a rotating cube
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
import * as THREE from 'three'; | |
const camera = new THREE.PerspectiveCamera( | |
45, | |
window.innerWidth / window.innerHeight, | |
0.1, | |
100 | |
); | |
camera.position.set(3, 3, 5); | |
camera.lookAt(0, 0, 0); | |
const scene = new THREE.Scene(); | |
scene.background = new THREE.Color(0xffffff); | |
// A simple ambient & directional light so we can see the highlights: | |
scene.add(new THREE.AmbientLight(0x888888)); | |
const dirLight = new THREE.DirectionalLight(0xffffff, 0.6); | |
dirLight.position.set(10, 10, 10); | |
scene.add(dirLight); | |
const cubeGroup = new THREE.Group(); | |
scene.add(cubeGroup); | |
// Create the edges of the cube | |
const boxGeometry = new THREE.BoxGeometry(2, 2, 2); | |
const edges = new THREE.EdgesGeometry(boxGeometry); | |
const edgesMaterial = new THREE.LineBasicMaterial({ color: 0x000000 }); | |
const boxEdges = new THREE.LineSegments(edges, edgesMaterial); | |
cubeGroup.add(boxEdges); | |
// Corner positions (box is centered at origin, ±1 in each axis) | |
const cornerPositions = [ | |
new THREE.Vector3(-1, -1, 1), // 0 | |
new THREE.Vector3(1, -1, 1), // 1 | |
new THREE.Vector3(1, 1, 1), // 2 | |
new THREE.Vector3(-1, 1, 1), // 3 | |
new THREE.Vector3(-1, -1, -1), // 4 | |
new THREE.Vector3(1, -1, -1), // 5 | |
new THREE.Vector3(1, 1, -1), // 6 | |
new THREE.Vector3(-1, 1, -1), // 7 | |
]; | |
// Create a small sphere at each corner | |
const cornerSpheres = []; | |
const sphereRadius = 0.07; | |
const sphereGeometry = new THREE.SphereGeometry(sphereRadius, 16, 16); | |
cornerPositions.forEach(pos => { | |
const material = new THREE.MeshPhongMaterial({ color: 0x888888 }); | |
const sphere = new THREE.Mesh(sphereGeometry, material); | |
sphere.position.copy(pos); | |
cubeGroup.add(sphere); // Add sphere into the same group | |
cornerSpheres.push(sphere); | |
}); | |
// List of coplanar sets (corner indices) | |
const coplanarSets = [ | |
[0, 1, 2, 3], // front face | |
[4, 5, 6, 7], // back face | |
[0, 1, 5, 4], // bottom face | |
[2, 3, 7, 6], // top face | |
[0, 3, 7, 4], // left face | |
[1, 2, 6, 5], // right face | |
[0, 2, 6, 4], // one diagonal plane | |
[1, 3, 7, 5], // other diagonal plane | |
]; | |
let currentSetIndex = 0; | |
const highlightColor = 0xff00ff; | |
const neutralColor = 0x888888; | |
function highlightCoplanarSet() { | |
// reset all spheres | |
cornerSpheres.forEach(s => s.material.color.setHex(neutralColor)); | |
// highlight the next 4 | |
coplanarSets[currentSetIndex].forEach(i => { | |
cornerSpheres[i].material.color.setHex(highlightColor); | |
}); | |
} | |
// cycle to next subset every second | |
setInterval(() => { | |
currentSetIndex = (currentSetIndex + 1) % coplanarSets.length; | |
highlightCoplanarSet(); | |
}, 1000); | |
// start with the first subset highlighted | |
highlightCoplanarSet(); | |
// --- Animate / render loop --- | |
function animation() { | |
window.requestAnimationFrame(animate); | |
cubeGroup.rotation.x += 0.005; | |
cubeGroup.rotation.y += 0.01; | |
renderer.render(scene, camera); | |
} | |
const renderer = new THREE.WebGLRenderer({ antialias: true }); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
renderer.setAnimationLoop(animation); | |
document.body.appendChild(renderer.domElement); | |
window.addEventListener('resize', onWindowResize); | |
function onWindowResize() { | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment