overlay is temporarily restored
This commit is contained in:
@@ -21,13 +21,13 @@ import {
|
||||
ImportMeshAsync,
|
||||
PointerEventTypes,
|
||||
PointerInfo,
|
||||
Matrix,
|
||||
} from '@babylonjs/core'
|
||||
import '@babylonjs/loaders'
|
||||
|
||||
import SceneToolbar from './SceneToolbar';
|
||||
import LoadingSpinner from '../ui/LoadingSpinner'
|
||||
|
||||
|
||||
export interface ModelViewerProps {
|
||||
modelPath: string
|
||||
onSelectModel: (path: string) => void;
|
||||
@@ -202,7 +202,6 @@ const ModelViewer: React.FC<ModelViewerProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
isDisposedRef.current = false
|
||||
isInitializedRef.current = false
|
||||
@@ -548,6 +547,49 @@ const ModelViewer: React.FC<ModelViewerProps> = ({
|
||||
}
|
||||
}, [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 (
|
||||
<div className="w-full h-screen relative bg-gray-900 overflow-hidden">
|
||||
{!modelPath ? (
|
||||
@@ -603,16 +645,9 @@ const ModelViewer: React.FC<ModelViewerProps> = ({
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{renderOverlay
|
||||
{renderOverlay && overlayPos && overlayData
|
||||
? renderOverlay({ anchor: overlayPos, info: overlayData })
|
||||
: (overlayData && overlayPos && (
|
||||
<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>
|
||||
))
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user