[claude] Add glass-floor sections showing the void below the platform (#123) (#190)
Some checks failed
Deploy Nexus / deploy (push) Has been cancelled

This commit was merged in pull request #190.
This commit is contained in:
2026-03-24 04:12:32 +00:00
parent 36cc526df0
commit 60bc437cfb

107
app.js
View File

@@ -21,7 +21,16 @@ const scene = new THREE.Scene();
scene.background = new THREE.Color(NEXUS.colors.bg);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 5);
camera.position.set(0, 6, 11);
// === LIGHTING ===
// Required for MeshStandardMaterial / MeshPhysicalMaterial used on the platform.
const ambientLight = new THREE.AmbientLight(0x0a1428, 1.4);
scene.add(ambientLight);
const overheadLight = new THREE.PointLight(0x8899bb, 0.6, 60);
overheadLight.position.set(0, 25, 0);
scene.add(overheadLight);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
@@ -116,6 +125,92 @@ function buildConstellationLines() {
const constellationLines = buildConstellationLines();
scene.add(constellationLines);
// === GLASS PLATFORM ===
// Central floating platform with transparent glass-floor sections revealing the void (star field) below.
const glassPlatformGroup = new THREE.Group();
// Dark metallic frame material
const platformFrameMat = new THREE.MeshStandardMaterial({
color: 0x0a1828,
metalness: 0.9,
roughness: 0.1,
emissive: new THREE.Color(NEXUS.colors.accent).multiplyScalar(0.06),
});
// Outer solid rim (flat ring)
const platformRimGeo = new THREE.RingGeometry(4.7, 5.3, 64);
const platformRim = new THREE.Mesh(platformRimGeo, platformFrameMat);
platformRim.rotation.x = -Math.PI / 2;
glassPlatformGroup.add(platformRim);
// Raised border torus for visible 3-D thickness
const borderTorusGeo = new THREE.TorusGeometry(5.0, 0.1, 6, 64);
const borderTorus = new THREE.Mesh(borderTorusGeo, platformFrameMat);
borderTorus.rotation.x = Math.PI / 2;
glassPlatformGroup.add(borderTorus);
// Glass tile material — highly transmissive to reveal the void below
const glassTileMat = new THREE.MeshPhysicalMaterial({
color: new THREE.Color(NEXUS.colors.accent),
transparent: true,
opacity: 0.09,
roughness: 0.0,
metalness: 0.0,
transmission: 0.92,
thickness: 0.06,
side: THREE.DoubleSide,
depthWrite: false,
});
// Edge glow — bright accent outline on each tile
const glassEdgeBaseMat = new THREE.LineBasicMaterial({
color: NEXUS.colors.accent,
transparent: true,
opacity: 0.55,
});
const GLASS_TILE_SIZE = 0.85;
const GLASS_TILE_GAP = 0.14;
const GLASS_TILE_STEP = GLASS_TILE_SIZE + GLASS_TILE_GAP;
const GLASS_RADIUS = 4.55;
const tileGeo = new THREE.PlaneGeometry(GLASS_TILE_SIZE, GLASS_TILE_SIZE);
const tileEdgeGeo = new THREE.EdgesGeometry(tileGeo);
/** @type {Array<{mat: THREE.LineBasicMaterial, distFromCenter: number}>} */
const glassEdgeMaterials = [];
for (let row = -5; row <= 5; row++) {
for (let col = -5; col <= 5; col++) {
const x = col * GLASS_TILE_STEP;
const z = row * GLASS_TILE_STEP;
const distFromCenter = Math.sqrt(x * x + z * z);
if (distFromCenter > GLASS_RADIUS) continue;
// Transparent glass tile
const tile = new THREE.Mesh(tileGeo, glassTileMat.clone());
tile.rotation.x = -Math.PI / 2;
tile.position.set(x, 0, z);
glassPlatformGroup.add(tile);
// Glowing edge lines
const mat = glassEdgeBaseMat.clone();
const edges = new THREE.LineSegments(tileEdgeGeo, mat);
edges.rotation.x = -Math.PI / 2;
edges.position.set(x, 0.002, z);
glassPlatformGroup.add(edges);
glassEdgeMaterials.push({ mat, distFromCenter });
}
}
// Void shimmer — faint point light below the glass, emphasising the infinite depth
const voidLight = new THREE.PointLight(NEXUS.colors.accent, 0.5, 14);
voidLight.position.set(0, -3.5, 0);
glassPlatformGroup.add(voidLight);
scene.add(glassPlatformGroup);
// === MOUSE-DRIVEN ROTATION ===
let mouseX = 0;
let mouseY = 0;
@@ -131,7 +226,7 @@ document.addEventListener('mousemove', (/** @type {MouseEvent} */ e) => {
let overviewMode = false;
let overviewT = 0; // 0 = normal view, 1 = overview
const NORMAL_CAM = new THREE.Vector3(0, 0, 5);
const NORMAL_CAM = new THREE.Vector3(0, 6, 11);
const OVERVIEW_CAM = new THREE.Vector3(0, 200, 0.1); // overhead; tiny Z offset avoids gimbal lock
const overviewIndicator = document.getElementById('overview-indicator');
@@ -255,6 +350,14 @@ function animate() {
// Subtle pulse on constellation opacity
constellationLines.material.opacity = 0.12 + Math.sin(elapsed * 0.5) * 0.06;
// Glass platform — ripple edge glow outward from centre
for (const { mat, distFromCenter } of glassEdgeMaterials) {
const phase = elapsed * 1.1 - distFromCenter * 0.18;
mat.opacity = 0.25 + Math.sin(phase) * 0.22;
}
// Pulse the void light below
voidLight.intensity = 0.35 + Math.sin(elapsed * 1.4) * 0.2;
if (photoMode) {
orbitControls.update();
}