import React, { useMemo, useRef } from 'react'; import { useFrame, useThree } from '@react-three/fiber'; import * as THREE from 'three'; export const LOD_LEVELS = { HIGH: 0, MEDIUM: 1, LOW: 2, }; export const LOD_DISTANCES = { HIGH: 5, MEDIUM: 10, }; const createSimplifiedDeviceMesh = (device, uHeight, rackDepth, deviceColor, statusColor) => { const depth = rackDepth || 1.0; const dHeight = device.height || device.u_height || 1; const height = dHeight * uHeight; const chassisWidth = 0.44; const chassisDepth = 0.8; const panelWidth = 0.4826; const panelDepth = 0.02; const frontZ = depth / 2 - 0.02; const halfHeight = height / 2; return ( ); }; const createMediumDeviceMesh = (device, uHeight, rackDepth, deviceColor, statusColor) => { const depth = rackDepth || 1.0; const dHeight = device.height || device.u_height || 1; const height = dHeight * uHeight; const chassisWidth = 0.44; const chassisDepth = 0.8; const panelWidth = 0.4826; const panelDepth = 0.02; const frontZ = depth / 2 - 0.02; const is2U = height > 0.08; const halfHeight = height / 2; return ( {Array.from({ length: is2U ? 4 : 2 }).map((_, i) => ( ))} ); }; const LODManager = ({ device, uHeight, rackDepth, position, deviceColor, statusColor, children, level = LOD_LEVELS.HIGH, }) => { const groupRef = useRef(); const highDetailRef = useRef(); const mediumDetailRef = useRef(); const lowDetailRef = useRef(); const { camera } = useThree(); const lodLevelRef = useRef(LOD_LEVELS.HIGH); const distanceRef = useRef(0); const prevDistanceRef = useRef(null); const [, forceUpdate] = React.useReducer(x => x + 1, 0); useFrame(() => { if (!groupRef.current) return; const distance = camera.position.distanceTo(groupRef.current.position); // 仅当距离变化超过阈值(10%)时才检查 if (prevDistanceRef.current !== null) { const changeRatio = Math.abs(distance - prevDistanceRef.current) / (prevDistanceRef.current || 1); if (changeRatio < 0.1) return; } prevDistanceRef.current = distance; distanceRef.current = distance; const highThreshold = LOD_DISTANCES.HIGH; const mediumThreshold = LOD_DISTANCES.MEDIUM; let newLevel = LOD_LEVELS.HIGH; if (distance > mediumThreshold) { newLevel = LOD_LEVELS.LOW; } else if (distance > highThreshold) { newLevel = LOD_LEVELS.MEDIUM; } if (newLevel !== lodLevelRef.current) { lodLevelRef.current = newLevel; if (highDetailRef.current) { highDetailRef.current.visible = newLevel === LOD_LEVELS.HIGH; } if (mediumDetailRef.current) { mediumDetailRef.current.visible = newLevel === LOD_LEVELS.MEDIUM; } if (lowDetailRef.current) { lowDetailRef.current.visible = newLevel === LOD_LEVELS.LOW; } forceUpdate(); } }); if (level !== LOD_LEVELS.HIGH) { return children; } return ( {/* 高细节模型 - 默认显示 */} {children} {/* 中等细节模型 */} {createMediumDeviceMesh(device, uHeight, rackDepth, deviceColor, statusColor)} {/* 低细节模型 */} {createSimplifiedDeviceMesh(device, uHeight, rackDepth, deviceColor, statusColor)} ); }; export default LODManager;