How to Animate a Model's Rotation in Realitykit

Change a rotation of AnchorEntity in RealityKit

Try move(...) instance method:

import UIKit
import RealityKit
import SceneKit

class ViewController: UIViewController {

@IBOutlet var arView: ARView!

override func viewDidLoad() {
super.viewDidLoad()

let box = try! Experience.loadBox()
let entity = box.steelBox!

DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {

let currentMatrix = entity.transform.matrix

// Nothing prevents you from using even SceneKit's matrix methods
let rotation = simd_float4x4(SCNMatrix4MakeRotation(.pi/2, 0,1,0))

let transform = simd_mul(currentMatrix, rotation)
entity.move(to: transform, relativeTo: nil, duration: 3.0)
}
arView.scene.anchors.append(box)
}
}

RealityKit – Rotating an Entity affects its Scale

You need a starting transform "point" and ending transform "point". If a value of referenceEntity (relativeTo) argument equal to nil it means relative to world space. Since the same 4x4 matrix slots are used for rotation values ​​as for scaling, when the model is rotated, its scale also changes at the same time, if there is a difference in scale.

For perpetual transform animation use some of RealityKit 2.0 tricks.

And, of course, there is a Trigonometry that was really conceived for perpetual orbiting.

Here's a correct version of your code:

import UIKit
import RealityKit
import Combine

class ViewController: UIViewController {

@IBOutlet var arView: ARView!
var cancellable: Cancellable? = nil
let anchor = AnchorEntity()

override func viewDidLoad() {
super.viewDidLoad()

cancellable = ModelEntity.loadAsync(named: "drummer.usdz").sink { _ in
self.cancellable?.cancel()
} receiveValue: { entity in
self.anchor.addChild(entity)
self.arView.scene.addAnchor(self.anchor)

let rotation = Transform(pitch: 0, yaw: .pi, roll: 0)
entity.move(to: rotation,
relativeTo: entity,
duration: 5.0,
timingFunction: .linear)
}
}
}

How do I rotate an object around only one axis in RealityKit?

In RealityKit there are, at least, three ways to rotate an object around single axis.

In each example we rotate an object counterclockwise (CCW).


First approach

let boxScene = try! Experience.loadBox()

boxScene.steelBox?.orientation = simd_quatf(angle: .pi/4, /* 45 Degrees */
axis: [0,0,1]) /* About Z axis */


Second approach

boxScene.steelBox?.transform = Transform(pitch: 0, 
yaw: 0,
roll: .pi/4) /* Around Z axis */

pitch, yaw and roll are rotations about X, Y and Z axis expressed in radians.


Third approach

let a: Float = cos(.pi/4)
let b: Float = sin(.pi/4)

let matrix = float4x4([ a, b, 0, 0 ], /* column 0 */
[-b, a, 0, 0 ], /* column 1 */
[ 0, 0, 1, 0 ], /* column 2 */
[ 0, 0, 0, 1 ]) /* column 3 */

boxAnchor.steelBox?.setTransformMatrix(matrix, relativeTo: nil)

Visual representation of rotation matrix looks like this:

let a: Float = cos(.pi/4)
let b: Float = sin(.pi/4)

// 0 1 2 3
┌ ┐
| a -b 0 0 |
| b a 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
└ ┘

If you wanna know more about Rotation Matrices, read this post.

RealityKit – How to add motion to a loaded ModelEntity from USDZ file?

Add to your code .generateCollisionShapes(recursive:) instance method for every participant (entity) that not only creates collision's shapes but also allows you to simulate physics.

Sample Image

import SwiftUI
import RealityKit

struct ARViewContainer: UIViewRepresentable {

let boxx = ModelEntity(mesh: .generateBox(size: 0.5))
let ball = ModelEntity(mesh: .generateSphere(radius: 0.25))
let anchor = AnchorEntity()

func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
// BALL
ball.physicsBody = .init()
ball.physicsMotion = .init()
ball.physicsMotion?.linearVelocity = [10,0,0]
ball.position.x = -3
ball.generateCollisionShapes(recursive: true)
anchor.addChild(ball)
// BOX
boxx.physicsBody = .init()
boxx.physicsMotion = .init()
boxx.physicsMotion?.linearVelocity = [0,2,0]
boxx.generateCollisionShapes(recursive: true)
anchor.addChild(boxx)
// Anchor
anchor.position.z = -3
arView.scene.addAnchor(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) { }
}

...

struct ContentView : View {
var body: some View {
return ARViewContainer().edgesIgnoringSafeArea(.all)
}
}

For more details, read THIS post.



Related Topics



Leave a reply



Submit