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(); // 使用 ref 存储 LOD 级别,避免 React 状态更新 const lodLevelRef = useRef(LOD_LEVELS.HIGH); const distanceRef = useRef(0); // 帧计数器,用于节流 const frameCount = useRef(0); // 用于强制重新渲染的 state(仅在必要时更新) const [, forceUpdate] = React.useReducer(x => x + 1, 0); useFrame(() => { if (!groupRef.current) return; // 节流:每5帧检查一次 frameCount.current++; if (frameCount.current % 5 !== 0) return; const distance = camera.position.distanceTo(groupRef.current.position); distanceRef.current = distance; // 添加缓冲避免频繁切换(10% 缓冲) const buffer = 0.1; const highThreshold = LOD_DISTANCES.HIGH * (1 + buffer); const mediumThreshold = LOD_DISTANCES.MEDIUM * (1 + buffer); 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; // 直接操作 ref 切换可见性,避免频繁的 React 重渲染 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; } // 偶尔强制更新以确保同步(每30帧) if (frameCount.current % 30 === 0) { 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;