Introduce TankDefinition/TankCatalog loaded from Tanks.json, bundle the Drachengas USDZ tank models, add tank selection and preview views, and update the AR experience, editor and project views to use the catalog. Includes tests for catalog loading and model selection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
2.3 KiB
Swift
64 lines
2.3 KiB
Swift
//
|
||
// PipeRouteEntityFactory.swift
|
||
// GasTankAR
|
||
//
|
||
// Created by Dennis Nemec on 28.08.26.
|
||
//
|
||
|
||
import RealityKit
|
||
import UIKit
|
||
|
||
/// Baut die AR-Visualisierung einer Rohrführung: Wegpunkt-Kugeln und die verbindenden
|
||
/// Segmente. Bewusst in einer markanten, naturfremden Farbe (Pink/Magenta) gehalten.
|
||
@MainActor
|
||
enum PipeRouteEntityFactory {
|
||
/// Markante, in der Natur kaum vorkommende Linien-/Punktfarbe.
|
||
private static let color = UIColor.systemPink
|
||
private static let waypointRadius: Float = 0.02
|
||
private static let segmentThickness: Float = 0.012
|
||
|
||
/// Kugel für einen Wegpunkt.
|
||
static func makeWaypoint(at position: SIMD3<Float>) -> ModelEntity {
|
||
let sphere = ModelEntity(
|
||
mesh: .generateSphere(radius: waypointRadius),
|
||
materials: [UnlitMaterial(color: color)]
|
||
)
|
||
sphere.position = position
|
||
return sphere
|
||
}
|
||
|
||
/// Verbindungssegment zwischen zwei Wegpunkten.
|
||
static func makeSegment(from start: SIMD3<Float>, to end: SIMD3<Float>) -> ModelEntity {
|
||
let segment = makeSegmentBase()
|
||
configureSegment(segment, from: start, to: end)
|
||
segment.collision = CollisionComponent(shapes: [
|
||
ShapeResource.generateBox(size: SIMD3(0.08, 0.08, 1))
|
||
])
|
||
segment.components.set(InputTargetComponent())
|
||
return segment
|
||
}
|
||
|
||
static func setSegmentColor(_ segment: Entity, color: UIColor) {
|
||
guard let model = segment as? ModelEntity else { return }
|
||
model.model?.materials = [UnlitMaterial(color: color)]
|
||
}
|
||
|
||
/// Basis-Segment der Länge 1 m (entlang +Z) – für die Live-Vorschau wiederverwendbar.
|
||
static func makeSegmentBase() -> ModelEntity {
|
||
ModelEntity(
|
||
mesh: .generateBox(size: SIMD3(segmentThickness, segmentThickness, 1)),
|
||
materials: [UnlitMaterial(color: color)]
|
||
)
|
||
}
|
||
|
||
/// Richtet ein Segment zwischen zwei Punkten aus (Länge über Z-Skalierung).
|
||
static func configureSegment(_ segment: Entity, from start: SIMD3<Float>, to end: SIMD3<Float>) {
|
||
let length = max(simd_distance(start, end), 0.0001)
|
||
segment.transform = Transform(
|
||
scale: SIMD3(1, 1, length),
|
||
rotation: simd_quatf(from: SIMD3(0, 0, 1), to: normalize(end - start)),
|
||
translation: (start + end) / 2
|
||
)
|
||
}
|
||
}
|