<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Truncated Octahedron - Still</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 640px;
height: 640px;
background: linear-gradient(135deg, #0a0e27 0%, #1a1f3a 100%);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
#canvas-container {
position: relative;
width: 640px;
height: 640px;
background: radial-gradient(circle at 30% 30%, rgba(20, 100, 60, 0.1), transparent 50%),
radial-gradient(circle at center, #0a0e27, #050810);
display: flex;
justify-content: center;
align-items: center;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="canvas-container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
const container = document.getElementById('canvas-container');
const width = 640;
const height = 640;
const scene = new THREE.Scene();
scene.background = null;
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 10000);
camera.position.set(1.2, 1.5, 2.5);
camera.lookAt(0, -0.3, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(width, height);
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0x00ff99, 0.8);
directionalLight.position.set(3, 3, 3);
scene.add(directionalLight);
const backLight = new THREE.DirectionalLight(0x0088ff, 0.3);
backLight.position.set(-2, -2, -3);
scene.add(backLight);
function createTruncatedOctahedron() {
const geometry = new THREE.BufferGeometry();
const verts = [
[0, 1, 2], [0, 1, -2], [0, -1, 2], [0, -1, -2],
[0, 2, 1], [0, 2, -1], [0, -2, 1], [0, -2, -1],
[1, 0, 2], [1, 0, -2], [-1, 0, 2], [-1, 0, -2],
[2, 0, 1], [2, 0, -1], [-2, 0, 1], [-2, 0, -1],
[1, 2, 0], [1, -2, 0], [-1, 2, 0], [-1, -2, 0],
[2, 1, 0], [2, -1, 0], [-2, 1, 0], [-2, -1, 0]
];
const vertices = [];
const scale = 0.75;
for (let v of verts) {
const len = Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
vertices.push(v[0]/len * scale, v[1]/len * scale, v[2]/len * scale);
}
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3));
const edges = [];
const edgeSet = new Set();
for (let i = 0; i < verts.length; i++) {
for (let j = i + 1; j < verts.length; j++) {
const dx = verts[i][0] - verts[j][0];
const dy = verts[i][1] - verts[j][1];
const dz = verts[i][2] - verts[j][2];
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz);
if (Math.abs(dist - Math.sqrt(2)) < 0.01) {
const key = Math.min(i,j) + "," + Math.max(i,j);
if (!edgeSet.has(key)) {
edgeSet.add(key);
edges.push(i, j);
}
}
}
}
geometry.setIndex(new THREE.BufferAttribute(new Uint16Array(edges), 1));
const lineMaterial = new THREE.LineBasicMaterial({
color: 0x00ff99,
linewidth: 2
});
const lines = new THREE.LineSegments(geometry, lineMaterial);
return lines;
}
const octahedron = createTruncatedOctahedron();
scene.add(octahedron);
renderer.render(scene, camera);
</script>
</body>
</html>