RealityKit Rotation Origin

I am trying to rotate topEntity around the origin point of shapeEntity, but have not found a way to do so.

topEntity is an entity group that also contains shapeEntity, so I cannot set topEntity as a child of shapeEntity.

From Blender I set the correct origin of topEntity, but when I import the usd model into Reality Composer Pro it does not save the origin point and there is no way to set the origin in Reality Composer Pro.

            DragGesture()
                .targetedToEntity(where: .has(CustomComponent.self))
                .onChanged({ value in
                    let rotation = -Float(value.translation.height)
                    let clampedRotation = min(max(rotation, 0), 45)
                    
                    if value.entity.name == "grab"{
                        if let topEntity = selectedEntity.findEntity(named: "top"),
                           let shapeEntity = selectedEntity.findEntity(named: "Shape_1"){
                            topEntity.transform.rotation = simd_quatf(
                                angle: clampedRotation * .pi / 180,
                                axis: SIMD3(x: 0, y: 0, z: 1)
                            )
                        }
                    }
                })

Hi @lmigani

Could you describe more how you are trying to manipulate your asset in Reality Composer Pro? When you import your Blender model, are topEntity and shapeEntity separate entities in the Reality Composer Pro hierarchy, each with separate meshes? If not, then you need to separate them in Blender before importing to RCP.

Regarding saving the origin set in Blender when opening your asset in RCP, I am not seeing the issues you are describing. When I position objects in Blender, I see their new positions reflected in RCP after I reexport the blender asset as USD. Additionally, I am able to move around the imported entities independently from each other, although it is not possible to change their position in the hierarchy.

Assuming topEntity is the ascendent (container) entity of shapeEntity, then your current code should rotate topEntity in place, causing shapeEntity to "orbit" topEntity since it remains stationary in local space. However, I think you want the reverse, where topEntity orbits shapeEntity independently of their hierarchal relationship.

To do this, first create two variables for tracking state:

@State var offset: SIMD3<Float>
@State var orbitAngle: Float = 0

Track your offset (the distance from shapeEntity to topEntity) when you load your content for the first time:

var body: some View {
    RealityView { content in

        // ... load content here ...

        offset = topEntity.position(relativeTo: shapeEntity)

Then in your gesture closure, rotate your offset around an axis by orbitAngle, then position your topEntity relative to shapeEntity:

// I'm dividing by 1000 so it doesn't rotate too quickly.
orbitAngle -= Float(value.translation.height / 1000) 
orbitAngle = min(max(orbitAngle, 0), .pi / 2)
// Select an axis that makes sense for your context
let axis: SIMD3<Float> = [0, 0, 1]
let orbitRotation = simd_quatf(angle: orbitAngle, axis: axis)
let rotatedOffset = orbitRotation.act(offset)
topEntity.setPosition(rotatedOffset, relativeTo: shapeEntity)

There are many variations of .convert , .position, .setPosition, etc., that are useful for moving objects independent of their transform hierarchy. If you're using the code above, double check that the axis is right for your context. In my case I had to use Z because Blender uses Z for up while RCP uses Y, and I had to rotate the imported asset.

Let me know if you have any questions!

RealityKit Rotation Origin
 
 
Q