You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS SceneKit导入外部动画致模型变形问题排查

GLB模型导入SceneKit后应用DAE动画出现严重变形

我有一个glb格式的人物模型,通过GLTFKit2导入至SceneKit中。
未应用动画的模型

我还有一个对应模型的单独fbx格式动画文件,已通过Blender转换为dae格式,二者层级结构一致。我编写代码遍历动画文件中的动画,将其添加到模型对应的节点上:

func applyAnimation(on scene: SCNScene) {
    guard
      let animationSource = getAnimationSource()
    else {
      return
    }

    let identifiers = animationSource.identifiersOfEntries(
      withClass: SCNAnimation.self
    )

    identifiers.forEach {
      guard
        let animation = animationSource.entryWithIdentifier($0, withClass: SCNAnimation.self)
      else {
        return
      }

      guard
        let fullKeyPath = animation.keyPath,
        let keyPath = fullKeyPath.dropFirst().components(separatedBy: ".").first
      else {
        return
      }

      animation.repeatCount = .greatestFiniteMagnitude

      guard
        let node = find(keypath: keyPath, in: scene.rootNode)
      else {
        return
      }
      normalize(node: node)
      node.addAnimation(animation, forKey: "animationKey-\(fullKeyPath)")
    }
  }

func find(keypath: String, in node: SCNNode) -> SCNNode? {
    if node.name == keypath {
      return node
    }
    if let node = node.childNodes.first(
      where: {
        $0.name == keypath
      }
    ) {
      return node
    }

    for childNode in node.childNodes {
      if let node = find(keypath: keypath, in: childNode) {
        return node
      }
    }

    return nil
  }

但应用动画后,模型严重变形,仿佛动画的尺度远大于模型,每个骨骼都散开,层级结构保持完整但模型形态完全异常:
应用动画后的模型

我认为问题出在动画的尺度/坐标上,尝试归一化模型及动画的节点属性,但修改后效果并无变化:

func normalizeAllNodes(for node: SCNNode) {
    for node in node.childNodes {
      normalize(node: node)
      normalizeAllNodes(for: node)
    }
  }

  // Normalize coordinates
  func normalize(node: SCNNode) {
    node.transform = SCNMatrix4Identity
    node.position = SCNVector3(1.0, 1.0, 1.0)
    node.rotation = SCNVector4(1.0, 1.0, 1.0, 1.0)
    node.scale = SCNVector3(1.0, 1.0, 1.0)
  }

我的最终实现方法如下:

public func makeUIView(context: Context) -> UIView {
    let view = SCNView()

    guard
      let modelUrl = Bundle.main.url(
        forResource: "model",
        withExtension: "glb"
      )
    else {
      return view
    }

    extractSceneSource(from: modelUrl) { source in
      guard
        let scene = source?.defaultScene
      else {
        return
      }
      normalizeAllNodes(for: scene.rootNode)
      printNodeHierarchy(node: scene.rootNode)
      applyAnimation(on: scene)

      view.scene = scene
    }

    view.autoenablesDefaultLighting = true
    view.allowsCameraControl = true
    view.showsStatistics = true
    view.backgroundColor = .black

    return view
  }

在Blender中,动画文件与模型文件的尺寸/尺度是一致的。请问如何调整动画变换使其与模型匹配?或者我的流程中还存在哪些问题?


内容的提问来源于stack exchange,提问作者Artem Misesin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 08:08:13