overlay is temporarily restored

This commit is contained in:
iv_vuytsik
2025-12-11 14:00:16 +03:00
parent 60e8ef921d
commit 31030f2997

View File

@@ -21,13 +21,13 @@ import {
ImportMeshAsync, ImportMeshAsync,
PointerEventTypes, PointerEventTypes,
PointerInfo, PointerInfo,
Matrix,
} from '@babylonjs/core' } from '@babylonjs/core'
import '@babylonjs/loaders' import '@babylonjs/loaders'
import SceneToolbar from './SceneToolbar'; import SceneToolbar from './SceneToolbar';
import LoadingSpinner from '../ui/LoadingSpinner' import LoadingSpinner from '../ui/LoadingSpinner'
export interface ModelViewerProps { export interface ModelViewerProps {
modelPath: string modelPath: string
onSelectModel: (path: string) => void; onSelectModel: (path: string) => void;
@@ -202,7 +202,6 @@ const ModelViewer: React.FC<ModelViewerProps> = ({
} }
}; };
useEffect(() => { useEffect(() => {
isDisposedRef.current = false isDisposedRef.current = false
isInitializedRef.current = false isInitializedRef.current = false
@@ -548,6 +547,49 @@ const ModelViewer: React.FC<ModelViewerProps> = ({
} }
}, [focusSensorId, modelReady]) }, [focusSensorId, modelReady])
// Расчет позиции оверлея
const computeOverlayPosition = React.useCallback((mesh: AbstractMesh | null) => {
if (!sceneRef.current || !mesh) return null
const scene = sceneRef.current
try {
const bbox = (typeof mesh.getHierarchyBoundingVectors === 'function')
? mesh.getHierarchyBoundingVectors()
: { min: mesh.getBoundingInfo().boundingBox.minimumWorld, max: mesh.getBoundingInfo().boundingBox.maximumWorld }
const center = bbox.min.add(bbox.max).scale(0.5)
const viewport = scene.activeCamera?.viewport.toGlobal(engineRef.current!.getRenderWidth(), engineRef.current!.getRenderHeight())
if (!viewport) return null
const projected = Vector3.Project(center, Matrix.Identity(), scene.getTransformMatrix(), viewport)
if (!projected) return null
return { left: projected.x, top: projected.y }
} catch (error) {
console.error('[ModelViewer] Error computing overlay position:', error)
return null
}
}, [])
// Позиция оверлея изначально
useEffect(() => {
if (!chosenMeshRef.current || !overlayData) return
const pos = computeOverlayPosition(chosenMeshRef.current)
setOverlayPos(pos)
}, [overlayData, computeOverlayPosition])
// Позиция оверлея при движущейся камере
useEffect(() => {
if (!sceneRef.current || !chosenMeshRef.current || !overlayData) return
const scene = sceneRef.current
const updateOverlayPosition = () => {
const pos = computeOverlayPosition(chosenMeshRef.current)
setOverlayPos(pos)
}
scene.registerBeforeRender(updateOverlayPosition)
return () => scene.unregisterBeforeRender(updateOverlayPosition)
}, [overlayData, computeOverlayPosition])
return ( return (
<div className="w-full h-screen relative bg-gray-900 overflow-hidden"> <div className="w-full h-screen relative bg-gray-900 overflow-hidden">
{!modelPath ? ( {!modelPath ? (
@@ -603,16 +645,9 @@ const ModelViewer: React.FC<ModelViewerProps> = ({
/> />
</> </>
)} )}
{renderOverlay {renderOverlay && overlayPos && overlayData
? renderOverlay({ anchor: overlayPos, info: overlayData }) ? renderOverlay({ anchor: overlayPos, info: overlayData })
: (overlayData && overlayPos && ( : null
<div className="absolute z-40 pointer-events-none" style={{ left: overlayPos.left, top: overlayPos.top }}>
<div className="rounded bg-black/70 text-white text-xs px-3 py-2 shadow-lg">
<div className="font-semibold truncate max-w-[200px]">{overlayData.name || 'Sensor'}</div>
{overlayData.sensorId && <div className="opacity-80">ID: {overlayData.sensorId}</div>}
</div>
</div>
))
} }
</div> </div>
) )