Skip to content

Commit 773e501

Browse files
mbreiserclaude
andcommitted
Fix 3D viewer: LEDs now face inward, add panel borders and fly view
- Fixed LED orientation to face toward center (inside of cylinder walls) - Added thin grey panel border lines for visual clarity - Added "Fly View" button to view arena from center looking outward - Reduced minimum camera distance to allow center positioning Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 03a9b4e commit 773e501

1 file changed

Lines changed: 50 additions & 13 deletions

File tree

arena_3d_viewer.html

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ <h1>Arena 3D Viewer</h1>
316316
</div>
317317

318318
<button class="btn" id="reset-view">Reset Camera View</button>
319+
<button class="btn" id="fly-view">Fly View (From Center)</button>
319320
<button class="btn secondary" id="toggle-rotation">Toggle Auto-Rotate</button>
320321
</div>
321322

@@ -417,7 +418,7 @@ <h3>Resolution</h3>
417418
controls = new THREE.OrbitControls(camera, renderer.domElement);
418419
controls.enableDamping = true;
419420
controls.dampingFactor = 0.05;
420-
controls.minDistance = 3;
421+
controls.minDistance = 0.1; // Allow getting close to center for fly view
421422
controls.maxDistance = 50;
422423

423424
// Lighting
@@ -517,6 +518,15 @@ <h3>Resolution</h3>
517518
controls.update();
518519
});
519520

521+
// Fly view - camera at center looking outward
522+
document.getElementById('fly-view').addEventListener('click', () => {
523+
// Position camera at center of arena, slightly elevated
524+
camera.position.set(0, 0, 0);
525+
// Look outward toward a panel (along positive Z)
526+
controls.target.set(0, 0, 5);
527+
controls.update();
528+
});
529+
520530
// Auto-rotate toggle
521531
document.getElementById('toggle-rotation').addEventListener('click', () => {
522532
autoRotate = !autoRotate;
@@ -583,14 +593,43 @@ <h3>Resolution</h3>
583593
function createPanelWithLEDs(specs, width, height, depth, angle) {
584594
const group = new THREE.Group();
585595

586-
// Panel background (black)
596+
// Panel is positioned at radius, facing inward (toward center)
597+
// The panel's local +Z axis should point toward center (inward)
598+
599+
// Panel background (black) - thin box representing the panel PCB
587600
const panelGeom = new THREE.BoxGeometry(width, height, depth * 0.1);
588601
const panelMat = new THREE.MeshLambertMaterial({ color: 0x111111 });
589602
const panel = new THREE.Mesh(panelGeom, panelMat);
590-
panel.rotation.y = -angle + Math.PI / 2;
603+
// Rotate panel so its front face points toward center
604+
// Panel is at angle, needs to face inward (toward origin)
605+
panel.rotation.y = angle + Math.PI;
591606
group.add(panel);
592607

593-
// LED dots
608+
// Panel border lines (thin grey)
609+
const borderMat = new THREE.LineBasicMaterial({ color: 0x4a5568 });
610+
const halfW = width / 2;
611+
const halfH = height / 2;
612+
const borderOffset = depth * 0.06; // slightly in front of panel
613+
614+
// Create border as line segments on the inner face
615+
const borderGeom = new THREE.BufferGeometry();
616+
const borderVertices = new Float32Array([
617+
// Rectangle on the panel face (in local coords before rotation)
618+
-halfW, -halfH, borderOffset,
619+
halfW, -halfH, borderOffset,
620+
halfW, -halfH, borderOffset,
621+
halfW, halfH, borderOffset,
622+
halfW, halfH, borderOffset,
623+
-halfW, halfH, borderOffset,
624+
-halfW, halfH, borderOffset,
625+
-halfW, -halfH, borderOffset
626+
]);
627+
borderGeom.setAttribute('position', new THREE.BufferAttribute(borderVertices, 3));
628+
const border = new THREE.LineSegments(borderGeom, borderMat);
629+
border.rotation.y = angle + Math.PI;
630+
group.add(border);
631+
632+
// LED dots - positioned on the inner face of the panel
594633
const ledRadius = Math.min(width, height) / (specs.pixels_horizontal * 3);
595634
const ledSpacingX = width / specs.pixels_horizontal;
596635
const ledSpacingY = height / specs.pixels_vertical;
@@ -603,18 +642,16 @@ <h3>Resolution</h3>
603642
const ledGeom = new THREE.CircleGeometry(ledRadius, 8);
604643
const led = new THREE.Mesh(ledGeom, ledMat);
605644

606-
// Position LED on panel face
645+
// LED position in panel's local coordinate space
646+
// Center the grid of LEDs, offset slightly toward center (inner face)
607647
const localX = (px - (specs.pixels_horizontal - 1) / 2) * ledSpacingX;
608648
const localY = (py - (specs.pixels_vertical - 1) / 2) * ledSpacingY;
649+
const localZ = depth * 0.06; // small offset toward center
650+
651+
led.position.set(localX, localY, localZ);
609652

610-
// Rotate and offset to face inward
611-
const offsetDist = depth * 0.06;
612-
led.position.set(
613-
-Math.sin(angle) * offsetDist + localX * Math.cos(angle),
614-
localY,
615-
Math.cos(angle) * offsetDist + localX * Math.sin(angle)
616-
);
617-
led.rotation.y = -angle + Math.PI / 2;
653+
// LED circle faces inward (toward center) - same as panel rotation
654+
led.rotation.y = angle + Math.PI;
618655

619656
group.add(led);
620657
}

0 commit comments

Comments
 (0)