73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import { AbstractMesh, Matrix, Vector3, Scene, Engine } from '@babylonjs/core'
|
|
import * as statusColors from '../../lib/statusColors'
|
|
import { getSensorIdFromMesh } from './sensorHighlight'
|
|
|
|
export interface SensorOverlayCircle {
|
|
sensorId: string
|
|
left: number
|
|
top: number
|
|
colorHex: string
|
|
}
|
|
|
|
const parseHexColor = (hex: string) => {
|
|
let clean = hex.trim().replace('#', '')
|
|
if (clean.length === 3) {
|
|
clean = clean
|
|
.split('')
|
|
.map(c => c + c)
|
|
.join('')
|
|
}
|
|
const num = parseInt(clean, 16)
|
|
const r = (num >> 16) & 255
|
|
const g = (num >> 8) & 255
|
|
const b = num & 255
|
|
return { r, g, b }
|
|
}
|
|
|
|
export const hexWithAlpha = (hex: string, alpha: number) => {
|
|
const { r, g, b } = parseHexColor(hex)
|
|
return `rgba(${r}, ${g}, ${b}, ${alpha})`
|
|
}
|
|
|
|
export const computeSensorOverlayCircles = (params: {
|
|
scene: Scene
|
|
engine: Engine
|
|
meshes: AbstractMesh[]
|
|
sensorStatusMap?: Record<string, string>
|
|
}): SensorOverlayCircle[] => {
|
|
const { scene, engine, meshes, sensorStatusMap } = params
|
|
const camera = scene.activeCamera
|
|
if (!camera) return []
|
|
const viewport = camera.viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight())
|
|
const result: SensorOverlayCircle[] = []
|
|
|
|
for (const mesh of meshes) {
|
|
const sensorId = getSensorIdFromMesh(mesh)
|
|
if (!sensorId) continue
|
|
|
|
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 projected = Vector3.Project(center, Matrix.Identity(), scene.getTransformMatrix(), viewport)
|
|
if (!projected) continue
|
|
|
|
const statusColor = sensorStatusMap?.[sensorId] || statusColors.STATUS_COLOR_NORMAL
|
|
|
|
result.push({
|
|
sensorId,
|
|
left: projected.x,
|
|
top: projected.y,
|
|
colorHex: statusColor,
|
|
})
|
|
}
|
|
|
|
return result
|
|
}
|
|
|