Sure!
Here is the code how the board and a vehicle are added to the scene. I removed everything that is to my mind not essential. I hope this makes sense to you.
struct ImmersiveView: View {
@Environment(\.realityKitScene) var scene: RealityKit.Scene?
@Environment(AppModel.self) private var appModel: AppModel
@State private var realityContent = RealityContent()
var body: some View {
RealityView { content, attachments in
appModel.scene = scene
let initialEntities = realityContent.setUpContent(boardDimensions: boardDimensions,
boardPosition_m: boardPosition_m,
appModel: appModel)
initialEntities.forEach { content.add($0) }
}
update: { content, attachments in
guard let boardEntity = content.entities.filter({ $0.name == boardEntityName }).first as? ModelEntity else { return }
realityContent.updateVehicles(boardEntity: boardEntity,
vehicles: appModel.vehicles,
boardTopFaceSize_m: appModel.boardTopFaceSize_m)
}
}
@MainActor
struct RealityContent {
func setUpContent(boardDimensions: BoxSize, boardPosition_m: SIMD3<Float>, appModel: AppModel) -> Set<Entity> {
var entities: Set<Entity> = []
entities.insert(makeBoardEntity(boardDimensions: boardDimensions, boardPosition_m: boardPosition_m, fields: appModel.fields))
return entities
}
func makeBoardEntity(boardDimensions: BoxSize, boardPosition_m: SIMD3<Float>, fields: Set<Field>) -> Entity {
// Define geometry
let boardWidth = Float(boardDimensions.x_width.m)
let boardHeight = Float(boardDimensions.y_height.m)
let boardDepth = Float(boardDimensions.z_depth.m)
let mesh = MeshResource.generateBox(width: boardWidth,
height: boardHeight,
depth: boardDepth,
splitFaces: true)
// Define materials
let (materials, textureImage) = makeBoardMaterials(boardDimensions: boardDimensions, fields: fields)
// Make entity
let boardEntity = ModelEntity(mesh: mesh, materials: materials)
boardEntity.name = boardEntityName
// Add a custom texture image component. This is required to get the pixel color after a ray cast hit the board.
boardEntity.components[TextureImageComponent.self] = TextureImageComponent(textureImage: textureImage)
// Position the board
boardEntity.transform.translation = boardPosition_m
// Allow to tap the board
boardEntity.components.set(InputTargetComponent())
boardEntity.generateCollisionShapes(recursive: false)
// Add the board entity to the reality content and return it
return boardEntity
}
func updateVehicles(boardEntity: ModelEntity, vehicles: Set<Vehicle>, boardTopFaceSize_m: CGSize) {
let vehicleEntity = makeVehicleEntity(vehicle: vehicle, boardTopFaceSize_m: boardTopFaceSize_m)
transformVehicle(boardEntity: boardEntity,
vehicleEntity: vehicleEntity,
boardTopFacePosition_m: vehicle.onBoardPosition_m,
orientation: vehicle.orientation,
animated: false)
// Add the new entity to the board
boardEntity.addChild(vehicleEntity)
}
func transformVehicle(boardEntity: ModelEntity,
vehicleEntity: ModelEntity,
boardTopFacePosition_m: CGPoint,
orientation: Angle,
animated: Bool) {
// Position the vehicle on the board.
// The y offset relative to the board is board thickness / 2 + half of the vehicle height.
let halfVehicleHeight_ = vehicleEntity.model!.mesh.bounds.extents.y / 2.0
let halfVehicleHeight_m = halfVehicleHeight_ * vehicleEntity.scale.y
let halfBoardThickness_m = Float(boardDimensions.y_height.m) / 2.0
let yOffset_m = halfVehicleHeight_m + halfBoardThickness_m
// Move the vehicle to the right position and turn it to the right direction
let scale = vehicleEntity.scale
let translation = SIMD3<Float>(Float(boardTopFacePosition_m.x), yOffset_m, Float(boardTopFacePosition_m.y))
let rotationY = simd_quatf(angle: Float(orientation.radians), axis: SIMD3(x: 0, y: 1, z: 0))
let transform = Transform(scale: scale, rotation: rotationY, translation: translation)
// Move the vehicle with the right orientation to the right position.
if animated {
animatedMove(boardEntity: boardEntity,
vehicleEntity: vehicleEntity,
transform: transform,
duration: slowEvolutionTimeStep)
} else {
vehicleEntity.transform = transform
}
}