iOS ARKit 动画

          动画是增强虛拟元素真实感和生动性的重要方面,RealityKit 支持变換动面(Transform Animation)和骨骼动画(Skeletal Animation)两种动面模式。变换动画一般程序化地执行,支持基本的平移、旋转、缩放,更复杂的动画通常由第三方模型制作软件采用骨骼绑定的方式生成,独立或者内置于模型文件中。USDZ和 Reality 文件格式都支持动画,在使用时,可以直接由该类文件将动画导人场景中。

  • 变换动画 TransForm

     变换动画可以实现对虚拟元素常见的基本操作,如平移、旋转、缩放,在执行时,通常使用实体类的move(to: relativeTo:duration:)方法,该方法参数 duration 用于指定动画时间。

import SwiftUI
import RealityKit
import ARKit

struct TransformView : View {
    var body: some View {
        return ARViewContainer14().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer14: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        let arView = ARView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        arView.session.run(config, options:[ ])
        arView.session.delegate = arView
        arView.createPlane14()
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
    }
}
var cubeEntity : ModelEntity?
var gestureStartLocation: SIMD3<Float>?

extension ARView{
    
    func createPlane14(){
        let planeAnchor = AnchorEntity(plane:.horizontal)
        do {
            let cubeMesh = MeshResource.generateBox(size: 0.1)
            var cubeMaterial = SimpleMaterial(color:.white,isMetallic: false)
            cubeMaterial.color = try SimpleMaterial.BaseColor(tint:UIColor.yellow.withAlphaComponent(0.9999), texture: MaterialParameters.Texture(TextureResource.load(named: "Box_Texture.jpg")))
            cubeEntity = ModelEntity(mesh:cubeMesh,materials:[cubeMaterial])
            cubeEntity!.generateCollisionShapes(recursive: false)
            cubeEntity?.name = "this is a cube"
            planeAnchor.addChild(cubeEntity!)
            self.scene.addAnchor(planeAnchor)
            self.installGestures(.all,for:cubeEntity!).forEach{
                $0.addTarget(self, action: #selector(handleModelGesture))
            }
        } catch {
            print("找不到文件")
        }
    }
    
    @objc func handleModelGesture(_ sender: Any) {
        switch sender {
        case let rotation as EntityRotationGestureRecognizer:
            rotation.isEnabled = false
            var transform = rotation.entity!.transform
            transform.rotation =  simd_quatf(angle: .pi*1.5, axis: [0, 1, 0])
            rotation.entity!.move(to: transform, relativeTo: nil, duration: 5.0)
            rotation.isEnabled = true
        case let translation as EntityTranslationGestureRecognizer:
            translation.isEnabled = false
            var transform = translation.entity!.transform
            transform.translation = SIMD3<Float>(x: 0.8, y: 0, z: 0)
            translation.entity!.move(to:transform,relativeTo:nil,duration:5.0)
            translation.isEnabled = true
        case let Scale as EntityScaleGestureRecognizer:
            Scale.isEnabled = false
            var scaleTransform = Scale.entity!.transform
            scaleTransform.scale = SIMD3<Float>(x: 2, y: 2, z: 2)
            Scale.entity!.move(to:scaleTransform,relativeTo:nil,duration:5.0)
            Scale.isEnabled = true
        default:
            break
        }
    }
    
    @objc func handleScaleGesture(_ sender : EntityScaleGestureRecognizer){
        print("in scale")
    }
}


#if DEBUG
struct TransformView_Previews : PreviewProvider {
    static var previews: some View {
        ARViewContainer14()
    }
}
#endif

     在使用 move()方法进行变换动画之前,应当先设置需要达到的目标,利用duration 参数控制动画时长。move()方法另一个重载 move(to:relativeTo:duration:timingFunction:)版本,其参数 timingFunction为 Animation TimingFunction 类型,通过它可以指定动画效果,如线性(linear)、缓入(easeln)、缓出(easeOut)、缓入缓出(easelnOut)、三次贝赛尔曲线(cubicBezier),通过使用该方法可以改善动画体验。

  • 骨骼动画

     变换动画只适合于执行相对简单的动画操作,如控制灯光沿圆形轨道移动、用户单击模型时出现弹跳效果等,对于复杂的动画,一般使用第三方软件(Maya、3ds MAX 等)预先制作好骨骼动画,然后导出为USDZ 或Reality 格式文件供 ARKit 使用。在RealityKit 中,使用骨骼动画的典型代码如代码下所示。

import SwiftUI
import RealityKit
import ARKit

struct BoneAnimationView : View {
    var body: some View {
        return ARViewContainer9().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer9: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        arView.session.run(config, options:[ ])
        arView.session.delegate = arView
        arView.CreateRobot()
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
    }
}

extension ARView{
    func CreateRobot(){
        let planeAnchor = AnchorEntity(plane:.horizontal)
        do {
            let robot =  try ModelEntity.load(named: "toy_drummer")
            planeAnchor.addChild(robot)
            robot.scale = [0.01,0.01,0.01]
            self.scene.addAnchor(planeAnchor)
            print("Total animation count : \(robot.availableAnimations.count)")
            robot.playAnimation(robot.availableAnimations[0].repeat())
        } catch {
            print("找不到USDZ文件")
        }
    }
}


#if DEBUG
struct BoneAnimationView_Previews : PreviewProvider {
    static var previews: some View {
        BoneAnimationView()
    }
}
#endif

 具体代码地址:https://github.com/duzhaoquan/ARkitDemo.git

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值