Hello @Vision Pro Engineer, fantastic code!
I am using your code in order to grab a key and insert it in a door lock. When I put the key inside the hole, I would like to fix the key in that position and rotate it only on z axis.
I tried two different approaches.
For the first one, I added in the ImmersiveView this piece of code:
_ = content.subscribe(to: CollisionEvents.Began.self, on: nil) { event in
let entityA = event.entityA
let entityB = event.entityB
let modelEntity = entityB.findEntity(named: "Chiave_TriplaShape") as? ModelEntity
if event.entityB.name == "Chiave_TriplaShape", var physicsBody = entityB.components[PhysicsBodyComponent.self], isInserted, !hasRotated {
physicsBody.mode = .dynamic
// Lock rotation by setting angular damping to a high value
physicsBody.isTranslationLocked = (true, true, true)
physicsBody.isRotationLocked = (true, true, false)
entityB.components[PhysicsBodyComponent.self] = physicsBody
}
// insert the key in the unit and disabling dynamic mode
if event.entityA.name == "ErlenmeyerFlask" && event.entityB.name == "Chiave_TriplaShape", !isInserted {
entityB.transform.scale = SIMD3<Float>(x: 0.03, y: 0.03, z: 0.03)
entityB.transform.rotation = simd_quatf(real: 0.5963677, imag: SIMD3<Float>(0.59636784, 0.37992808, -0.3799282))
entityB.transform.translation = SIMD3<Float>(x: 0.52, y: 1, z: -0.7)
if var physicsBody = entityB.components[PhysicsBodyComponent.self] {
physicsBody.mode = .kinematic
entityB.components.set(physicsBody)
}
isInserted = true
}
if modelEntity == nil { return }
entityA.components[ThrowByHandComponent.self]?.entityCollidedWith = modelEntity
}
For the second approach, I tried instead to add this piece of code in update function of ThrowByHandSystem:
let lastHandPose = component.lastHandPose
print(component.entityCollidedWithIsInserted)
if lastHandPose != handPose, let entityCollidedWith = component.entityCollidedWith {
if handPose == .closed {
entityCollidedWith.components[PhysicsBodyComponent.self]?.mode = .kinematic
component.entityCollidedWithPreviousParent = entity.parent
entity.addChild(entityCollidedWith, preservingWorldTransform: true)
}
else if handPose == .closed, component.entityCollidedWithIsInserted, !component.entityCollidedWithIsRotated, let lastOrientation = component.lastOrientation {
let rotation = currentOrientation * simd_inverse(lastOrientation)
let angularSpeed = rotation.angle / Float(context.deltaTime)
let angularForceMultiplier: Float = 2.0
let isRotating = rotation.angle > Float.pi / 2
let angularImpulse = isRotating ? normalize(rotation.axis) * angularSpeed * angularForceMultiplier : [0, 0, 0]
entityCollidedWith.components[PhysicsBodyComponent.self]?.mode = .dynamic
component.entityCollidedWithPreviousParent?.addChild(entityCollidedWith, preservingWorldTransform: true)
component.entityCollidedWithPreviousParent = nil
entityCollidedWith.applyAngularImpulse(angularImpulse, relativeTo: nil)
} else if handPose == .open, let lastPosition = component.lastPosition {
let distance = distance(lastPosition, currentPosition)
let speed = distance / Float(context.deltaTime)
let forceMultiplier: Float = 2.0
let isStationary = distance < 0.01
let throwDirection = isStationary ? [0, 0, 0] : normalize(currentPosition - lastPosition)
let linearImpulse = throwDirection * speed * forceMultiplier
entityCollidedWith.components[PhysicsBodyComponent.self]?.mode = .dynamic
component.entityCollidedWithPreviousParent?.addChild(entityCollidedWith, preservingWorldTransform: true)
component.entityCollidedWithPreviousParent = nil
entityCollidedWith.applyLinearImpulse(linearImpulse, relativeTo: nil)
}
}
component.lastHandPose = handPose
}
Neither of the two approaches seems to work. Do you have any suggestions?
Thank you very much!