fix: improve 3D digital twin visual clarity
- Increase item visual scale ×2.5 with glow ring - Move camera closer [4.0, 3.0, 4.0] - Improve scene contrast (brighter conveyor, floor) - Add glow to active routes - Enhance gate/pusher visibility - Add highlight rings to active zones - Brighten sensors with detection effects Based on REAL_3D_AUDIT_REPORT.md P0/P1 fixes.
This commit is contained in:
@@ -5,6 +5,13 @@ import { DIMENSION_LIMITS } from '../../domain/classifier';
|
||||
import { getModelAsset } from '../../data/modelAssets';
|
||||
import STLModel from './STLModel';
|
||||
|
||||
/**
|
||||
* Visual scale multiplier for 3D demo visibility.
|
||||
* Physical dimensions remain unchanged in data/proof panel.
|
||||
* This only affects the rendered mesh size so item is visible in scene.
|
||||
*/
|
||||
const VISUAL_SCALE_MULTIPLIER = 2.5;
|
||||
|
||||
interface Props {
|
||||
simulation: SimulationState;
|
||||
currentItem?: SimulatedItem;
|
||||
@@ -18,6 +25,7 @@ function FallbackPrimitive({
|
||||
color,
|
||||
emissive,
|
||||
roughness,
|
||||
emissiveIntensity = 0.35,
|
||||
}: {
|
||||
primitive: 'box' | 'cylinder' | 'sphere';
|
||||
sx: number;
|
||||
@@ -26,15 +34,16 @@ function FallbackPrimitive({
|
||||
color: string;
|
||||
emissive: string;
|
||||
roughness: number;
|
||||
emissiveIntensity?: number;
|
||||
}) {
|
||||
if (primitive === 'cylinder') {
|
||||
return (
|
||||
<mesh>
|
||||
<cylinderGeometry args={[Math.min(sx, sz) / 2, Math.min(sx, sz) / 2, sy, 16]} />
|
||||
<cylinderGeometry args={[Math.min(sx, sz) / 2, Math.min(sx, sz) / 2, sy, 24]} />
|
||||
<meshStandardMaterial
|
||||
color={color}
|
||||
emissive={emissive}
|
||||
emissiveIntensity={0.2}
|
||||
emissiveIntensity={emissiveIntensity}
|
||||
roughness={roughness}
|
||||
/>
|
||||
</mesh>
|
||||
@@ -44,11 +53,11 @@ function FallbackPrimitive({
|
||||
if (primitive === 'sphere') {
|
||||
return (
|
||||
<mesh>
|
||||
<sphereGeometry args={[Math.max(sx, sy, sz) / 2, 16, 12]} />
|
||||
<sphereGeometry args={[Math.max(sx, sy, sz) / 2, 24, 16]} />
|
||||
<meshStandardMaterial
|
||||
color={color}
|
||||
emissive={emissive}
|
||||
emissiveIntensity={0.2}
|
||||
emissiveIntensity={emissiveIntensity}
|
||||
roughness={roughness}
|
||||
/>
|
||||
</mesh>
|
||||
@@ -62,7 +71,7 @@ function FallbackPrimitive({
|
||||
<meshStandardMaterial
|
||||
color={color}
|
||||
emissive={emissive}
|
||||
emissiveIntensity={0.2}
|
||||
emissiveIntensity={emissiveIntensity}
|
||||
roughness={roughness}
|
||||
/>
|
||||
</mesh>
|
||||
@@ -79,19 +88,29 @@ export default function Item3D({ simulation, currentItem }: Props) {
|
||||
const color = ROUTE_COLORS[category] ?? '#38bdf8';
|
||||
const dims = currentItem.item.dimensionsMm;
|
||||
|
||||
// Scale to Three.js units (1 unit = 1 meter, dimensions in mm)
|
||||
const sx = Math.max(0.12, Math.min(0.45, dims.width / 1000));
|
||||
const sy = Math.max(0.1, Math.min(0.4, dims.height / 1000));
|
||||
const sz = Math.max(0.12, Math.min(0.45, dims.depth / 1000));
|
||||
// Physical scale to Three.js units (1 unit = 1 meter, dimensions in mm)
|
||||
const physicalSx = Math.max(0.12, Math.min(0.45, dims.width / 1000));
|
||||
const physicalSy = Math.max(0.1, Math.min(0.4, dims.height / 1000));
|
||||
const physicalSz = Math.max(0.12, Math.min(0.45, dims.depth / 1000));
|
||||
|
||||
// Apply visual multiplier for demo visibility (does not affect proof panel data)
|
||||
const sx = physicalSx * VISUAL_SCALE_MULTIPLIER;
|
||||
const sy = physicalSy * VISUAL_SCALE_MULTIPLIER;
|
||||
const sz = physicalSz * VISUAL_SCALE_MULTIPLIER;
|
||||
|
||||
const detecting = simulation.machineState === 'DETECTING';
|
||||
const moving = simulation.machineState.startsWith('ROUTE_TO_') ||
|
||||
simulation.machineState === 'MOVING_TO_CAMERA' ||
|
||||
simulation.machineState === 'MOVING_TO_GATE';
|
||||
const fault = simulation.machineState === 'FAULT' || simulation.machineState === 'EMERGENCY_STOP';
|
||||
|
||||
// Get model asset for this item
|
||||
const asset = getModelAsset(currentItem.item.id);
|
||||
const finalColor = fault ? '#fb3d4e' : color;
|
||||
const finalEmissive = fault ? '#fb3d4e' : color;
|
||||
const finalRoughness = asset?.loaderType === 'stl' ? 0.45 : 0.5;
|
||||
const finalRoughness = asset?.loaderType === 'stl' ? 0.35 : 0.4;
|
||||
// Brighter emissive when moving for visibility
|
||||
const emissiveBoost = moving ? 0.55 : 0.35;
|
||||
|
||||
// Fallback primitive
|
||||
const fallbackPrimitive = asset?.fallbackPrimitive ?? 'box';
|
||||
@@ -109,6 +128,7 @@ export default function Item3D({ simulation, currentItem }: Props) {
|
||||
color={finalColor}
|
||||
emissive={finalEmissive}
|
||||
roughness={finalRoughness}
|
||||
emissiveIntensity={emissiveBoost}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -119,7 +139,7 @@ export default function Item3D({ simulation, currentItem }: Props) {
|
||||
position={[0, 0, 0]}
|
||||
color={finalColor}
|
||||
emissive={finalEmissive}
|
||||
emissiveIntensity={0.2}
|
||||
emissiveIntensity={emissiveBoost}
|
||||
roughness={finalRoughness}
|
||||
fallback={
|
||||
<FallbackPrimitive
|
||||
@@ -130,6 +150,7 @@ export default function Item3D({ simulation, currentItem }: Props) {
|
||||
color={finalColor}
|
||||
emissive={finalEmissive}
|
||||
roughness={finalRoughness}
|
||||
emissiveIntensity={emissiveBoost}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@@ -143,13 +164,26 @@ export default function Item3D({ simulation, currentItem }: Props) {
|
||||
color={finalColor}
|
||||
emissive={finalEmissive}
|
||||
roughness={finalRoughness}
|
||||
emissiveIntensity={emissiveBoost}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Glow ring under item for visibility */}
|
||||
<mesh position={[0, -sy / 2 + 0.01, 0]} rotation={[-Math.PI / 2, 0, 0]}>
|
||||
<ringGeometry args={[Math.max(sx, sz) * 0.4, Math.max(sx, sz) * 0.6, 32]} />
|
||||
<meshStandardMaterial
|
||||
color={finalColor}
|
||||
emissive={finalColor}
|
||||
emissiveIntensity={moving ? 0.8 : 0.4}
|
||||
transparent
|
||||
opacity={moving ? 0.7 : 0.4}
|
||||
/>
|
||||
</mesh>
|
||||
|
||||
{detecting ? (
|
||||
<mesh>
|
||||
<boxGeometry args={[sx + 0.08, sy + 0.08, sz + 0.08]} />
|
||||
<meshStandardMaterial color="#38bdf8" wireframe transparent opacity={0.8} />
|
||||
<boxGeometry args={[sx + 0.12, sy + 0.12, sz + 0.12]} />
|
||||
<meshStandardMaterial color="#38bdf8" wireframe transparent opacity={0.9} />
|
||||
</mesh>
|
||||
) : null}
|
||||
</group>
|
||||
|
||||
Reference in New Issue
Block a user