问题
I can’t figure out the common objects of 3D models for multipeer sessions (with their synchronization).
Design: Users of the application can enter a multipeer session, place objects on the stage, while other peers can see these models, their transformations, interact with these objects themselves and place their own - while also maintaining the ability to interact with their objects to other peers of the session.
Questions I have encountered:
- How to publish one instance of a model for one object (now when you publish two copies of each model are obtained - one instance of a model for peer A, which peer B cannot interact with, and one instance of a model for peer B, with which peer A cannot interact).
UPDATE:
This issue was resolved by adding in the session (_ session :, didAdd anchors:)
code block (modeled on WWDC 2019 - 610):
// Use session identifier to determine creator of the ARAnchor
// Self-placed ARanchor
if anchor.sessionIdentifier == session.identifier {
// ...
// ARAnchor from another participant
} else {
// ...
}
Now func correctly separates addition of its anchors from those added by other participants.
In addition, when loading, for example, modelA, with peer A, in order to use this model in a multipeer session, you need to not only load it in ModelEntity.loadAsync (contentsOf :)
method, but give a unique multipeer session name via ModelEntity.loadAsync (contentsOf :, withName :)
- then at peer B in session (_ session: ARSession, didAdd anchors: [ARAnchor])
you get model name (for example, modelA) from name of such ARAnchor (when created on peer A, it should be named - for example, anchor_modelA), you also load as an asset through ModelEntity.loadAsync (contentsOf :, withName: "modelA")
- in contentsOf:
specify the URL of the locally stored model file, after which modelA correctly displayed at the peer B, and in the placement of the duplicate does not occur.
- When changing some settings, I get only a wireframe for peer В (AnchorEntity + Collision + Gestures for Entity, where Entity itself with the loaded model is missing) - this option in some sense works, since only one instance gets onto the scene , and peer A (author) can interact with him (peer B cannot), but still this is an unsatisfactory result.
UPDATE: Answer in paragraph 1
- How to dynamically transfer and obtain Entity rights (when peer B can work with peer A model and vice versa)?
Scenario:
I tap on the screen to save simd_float4x4 for the future ARAnchor, select the model file from the local file directory, and return.
By simd_float4x4 I form ARAnchor:
/// Creates and adds in ARSession new ARAnchor.
/// - Parameter modelName: Name of placed model to form name of ARAnchor.
func placeAnchor(with modelName: String) {
defer {
tempSimd_float4x4 = nil
}
guard let worldPosition = tempSimd_float4x4 else { fatalError()}
let anchor = ARAnchor(name: "\(SettingsApp.anchorARSessionPrefix)\(modelName)", transform: worldPosition)
arView.session.add(anchor: anchor)
}
- In method
session (_ session: ARSession, didAdd anchors: [ARAnchor])
, after adding ARAnchor, it is validated by name and function is called
/// Adds model to scene of ARView.
/// - Parameters:
/// - anchor: Anchor for AnchorEntity binding.
/// - modelName: Name of added model.
/// - modelLocalUrl: URL of added model.
/// - Throws: Function can throw exceptions.
func placeEntity(for anchor: ARAnchor, modelName: String, modelLocalUrl: URL?) throws {
defer {
keychainSwift.delete(KeychainSwiftKeys.placingModelURL.rawValue)
}
var modelURL: URL?
if modelLocalUrl == nil {
if let modelUrlKeychainString = keychainSwift.get(KeychainSwiftKeys.placingModelURL.rawValue),
let modelUrlKeychainURL = URL(string: modelUrlKeychainString) {
modelURL = modelUrlKeychainURL
} else {
fatalError()
}
} else {
modelURL = modelLocalUrl
}
do {
let modelEntity = try Entity.loadModel(contentsOf: modelURL!, withName: "\(SettingsApp.modelEntityARSessionPrefix)\(String(modelName))")
modelEntity.name = "\(SettingsApp.modelEntityARSessionPrefix)\(modelName)"
modelEntity.generateCollisionShapes(recursive: true)
let anchorEntity = AnchorEntity(anchor: anchor)
anchorEntity.name = "\(SettingsApp.anchorEntityARSessionPrefix)\(modelName)"
anchorEntity.addChild(modelEntity)
arView.scene.addAnchor(anchorEntity)
arView.installGestures(for: modelEntity)
playAnimation(for: modelEntity)
} catch {
fatalError(error.localizedDescription)
}
}
Accordingly, when transferring Collaboration Data, peer B calls session (_ session: ARSession, didAdd anchors: [ARAnchor])
, ARAnchor validates by name and also calls placeEntity (for anchor :, modelName :, modelLocalUrl :?) throws
.
The multipeer session is configured as shown here: https://github.com/AddedLayer/multipeer-session
I will accept any help with thanks, thank you in advance for the answers! Have a nice code!
来源:https://stackoverflow.com/questions/61839870/realitykit-multipeer-session-object-sync-issue