70 lines
2.6 KiB
Swift
70 lines
2.6 KiB
Swift
//
|
||
// TankHighlightFactory.swift
|
||
// GasTankAR
|
||
//
|
||
// Created by Dennis Nemec on 28.08.26.
|
||
//
|
||
|
||
import RealityKit
|
||
import UIKit
|
||
|
||
/// Baut die Auswahl-Markierung um den Tank: ein (ansonsten unsichtbarer) Quader, dessen
|
||
/// acht Ecken mit kräftig gefärbten Winkeln hervorgehoben werden – deutlich sichtbar,
|
||
/// ohne den Tank selbst zu verdecken.
|
||
@MainActor
|
||
enum TankHighlightFactory {
|
||
/// Name der Markierungs-Entity (zum Ein-/Ausblenden bei Auswahl).
|
||
static let name = "TankSelectionHighlight"
|
||
|
||
private static let color = UIColor.systemTeal
|
||
|
||
/// Erzeugt die Eck-Winkel passend zur Bounding-Box (im Koordinatensystem des Containers).
|
||
static func makeHighlight(for bounds: BoundingBox) -> Entity {
|
||
let root = Entity()
|
||
root.name = name
|
||
|
||
let extents = bounds.extents
|
||
let smallestEdge = min(extents.x, min(extents.y, extents.z))
|
||
let armLength = max(0.05, smallestEdge * 0.3)
|
||
let thickness = max(0.008, smallestEdge * 0.05)
|
||
|
||
var material = UnlitMaterial(color: color)
|
||
material.faceCulling = .none
|
||
|
||
for x in [bounds.min.x, bounds.max.x] {
|
||
for y in [bounds.min.y, bounds.max.y] {
|
||
for z in [bounds.min.z, bounds.max.z] {
|
||
let corner = SIMD3(x, y, z)
|
||
// Vorzeichen: Winkel zeigt von der Ecke nach innen (zur Boxmitte).
|
||
let signX: Float = (x == bounds.min.x) ? 1 : -1
|
||
let signY: Float = (y == bounds.min.y) ? 1 : -1
|
||
let signZ: Float = (z == bounds.min.z) ? 1 : -1
|
||
|
||
root.addChild(beam(
|
||
size: SIMD3(armLength, thickness, thickness),
|
||
center: corner + SIMD3(signX * armLength / 2, 0, 0),
|
||
material: material
|
||
))
|
||
root.addChild(beam(
|
||
size: SIMD3(thickness, armLength, thickness),
|
||
center: corner + SIMD3(0, signY * armLength / 2, 0),
|
||
material: material
|
||
))
|
||
root.addChild(beam(
|
||
size: SIMD3(thickness, thickness, armLength),
|
||
center: corner + SIMD3(0, 0, signZ * armLength / 2),
|
||
material: material
|
||
))
|
||
}
|
||
}
|
||
}
|
||
return root
|
||
}
|
||
|
||
private static func beam(size: SIMD3<Float>, center: SIMD3<Float>, material: UnlitMaterial) -> ModelEntity {
|
||
let beam = ModelEntity(mesh: .generateBox(size: size), materials: [material])
|
||
beam.position = center
|
||
return beam
|
||
}
|
||
}
|