Hi Marco,
I wanted to see if you were bale to make any headway in this area?
Were you able to successfully set a PPT server? What solution did you use?
Were you to allow users to listen to multiple channels at once?
Any help would be greatly appreciated.
Thanks,
Justin
Post
Replies
Boosts
Views
Activity
Same issue!!!
I will definitly file a bug report on this. Thank you very much.
I am aware of that feature of a volume, but unfortunately this is a simplified excert from a much larger mixed reality project that we are trying to control to selected entities. This code is only to illustrate and reproduce the issue we are seeing.
Can you think of a way I can work around this in the meantime? is there another way I can achieve a offset pivot point?Maybe without using the billboard component?
Feedback filed - FB16233297
Found a workaround by using the Billboard ECS from the VisionOS 1.0 version SwiftSplash. Came across the source on stack overflow. I made a few naming changes, but it fixes the issue.
Is there a better solution to this?
https://stackoverflow.com/questions/60577468/how-to-implement-a-billboard-effect-lookat-camera-in-realitykit
//
// BillboardAttachmentFixSystem.swift
//
// Created by Justin Leger on 1/3/25.
//
import Foundation
import ARKit
import RealityKit
import SwiftUI
import simd
import OSLog
/// An ECS system that points all entities containing a billboard component at the camera.
public struct BillboardAttachmentFixSystem: System {
static let query = EntityQuery(where: .has(BillboardAttachmentFixComponent.self))
private let arkitSession = ARKitSession()
private let worldTrackingProvider = WorldTrackingProvider()
public init(scene: RealityKit.Scene) {
setupARKitSession()
}
func setupARKitSession() {
Task {
do {
try await arkitSession.run([worldTrackingProvider])
} catch {
os_log(.info, "Error: \(error)")
}
}
}
public func update(context: SceneUpdateContext) {
let entities = context.scene.performQuery(Self.query).map({ $0 })
guard !entities.isEmpty,
let pose = worldTrackingProvider.queryDeviceAnchor(atTimestamp: CACurrentMediaTime()) else { return }
let cameraTransform = Transform(matrix: pose.originFromAnchorTransform)
for entity in entities {
entity.look(at: cameraTransform.translation,
from: entity.scenePosition,
relativeTo: nil,
forward: .positiveZ)
}
}
}
/// The component that marks an entity as a billboard object which will always face the camera.
public struct BillboardAttachmentFixComponent: Component, Codable {
public init() {}
}
/// Entity extension holding convenience accessors and mutators for the components
/// this system uses. Components are stored in the `components` dictionary using the
/// component class (`.self`) as the key. This adds calculated properties to allow setting
/// and getting these components.
extension Entity {
/// Property for getting or setting an entity's `MockThruBillboardComponent`.
var mockThruBillboardComponent: BillboardAttachmentFixComponent? {
get { components[BillboardAttachmentFixComponent.self] }
set { components[BillboardAttachmentFixComponent.self] = newValue }
}
}
Small renaming artifacts in the Entity extension that I missed when I refactor for this posting. Here is my corrected code. I can't seem to edit the previous post once it's been marked as the recommended solution.
//
// BillboardAttachmentFixSystem.swift
//
// Created by Justin Leger on 1/3/25.
//
import Foundation
import ARKit
import RealityKit
import SwiftUI
import simd
import OSLog
/// An ECS system that points all entities containing a billboard component at the camera.
public struct BillboardAttachmentFixSystem: System {
static let query = EntityQuery(where: .has(BillboardAttachmentFixComponent.self))
private let arkitSession = ARKitSession()
private let worldTrackingProvider = WorldTrackingProvider()
public init(scene: RealityKit.Scene) {
setupARKitSession()
}
func setupARKitSession() {
Task {
do {
try await arkitSession.run([worldTrackingProvider])
} catch {
os_log(.info, "Error: \(error)")
}
}
}
public func update(context: SceneUpdateContext) {
let entities = context.scene.performQuery(Self.query).map({ $0 })
guard !entities.isEmpty,
let pose = worldTrackingProvider.queryDeviceAnchor(atTimestamp: CACurrentMediaTime()) else { return }
let cameraTransform = Transform(matrix: pose.originFromAnchorTransform)
for entity in entities {
entity.look(at: cameraTransform.translation,
from: entity.scenePosition,
relativeTo: nil,
forward: .positiveZ)
}
}
}
/// The component that marks an entity as a billboard object which will always face the camera.
public struct BillboardAttachmentFixComponent: Component, Codable {
public init() {}
}
/// Entity extension holding convenience accessors and mutators for the components
/// this system uses. Components are stored in the `components` dictionary using the
/// component class (`.self`) as the key. This adds calculated properties to allow setting
/// and getting these components.
extension Entity {
/// Property for getting or setting an entity's `BillboardAttachmentFixComponent`.
var billboardAttachmentFixComponent: BillboardAttachmentFixComponent? {
get { components[BillboardAttachmentFixComponent.self] }
set { components[BillboardAttachmentFixComponent.self] = newValue }
}
}