本節(jié)學(xué)習(xí)目標(biāo)
如何設(shè)計換裝應(yīng)用
解決模型綁定骨骼動畫時出現(xiàn)的問題
由于今年是AR元年,在蘋果推出的ARKit框架之后,各行各業(yè)都在馬不停蹄的玩起了創(chuàng)意,希望在自己的應(yīng)用基礎(chǔ)上加入AR的元素
由于要和原生應(yīng)用進(jìn)行結(jié)合,聰明的移動設(shè)計是都會選擇SceneKit作為AR元素的渲染引擎,還有不少公司會選擇使用其他引擎,做到一半的時候,發(fā)現(xiàn)和原型的iOS 數(shù)據(jù)交互,調(diào)試實在是太繁瑣,工程包大的不可思議,最后有選擇了使用SceneKit來開發(fā)!所以選擇SceneKit的開發(fā)類似的需求是最明知的!
iOS 工程師組合拳 (UIKit + ARKit +SceneKit )
AR換裝通用需求
1.選擇體重,身高,性別,膚色,以及 臉型,體型,腿型,眼睛,嘴巴,鼻子,發(fā)型等生成對應(yīng)的模型
2.根據(jù)選擇的人物,進(jìn)入入住商家進(jìn)行服飾試穿(帽子,衣服,鞋,襪子,皮帶,紗巾,頭巾等)
3.兩種模式AR和瀏覽模式模型(AR模式可以真實的查看整體效果)
4.可以有多種人物動畫(下蹲,跳,跑等)
5.用戶可以將模型身上的服飾,打包生成訂單,在線下單購買
模型設(shè)計篇
1.生成模型
多模型分組,拼接
2.服飾顏色
替換貼圖
3.服飾模型
和人物模型進(jìn)行拼接
4.人物動畫
多模型骨骼動畫,服飾模型骨頭綁定,盡量一致,保證不穿幫
前兩天譚總找我解決一個模型綁定的問題,
在設(shè)計工具上調(diào)試骨骼動畫和人物綁定完全一致,沒有問題,但是加載到SceneKit引擎中出現(xiàn)的模型和動畫偏移的問題
頭發(fā)的動畫和身體的動畫分開了
先打開調(diào)試模型看一眼
猜測是那個部分的骨骼,在設(shè)計時進(jìn)行了旋轉(zhuǎn)導(dǎo)致,所以讓他重新查看一下,之后他改了一下骨骼動畫文件,我重新試了一下,一切正常
以后大家在開發(fā)過程中遇到這種問題就直接去找設(shè)計了
下面我將完整的加載骨骼正確姿勢的代碼寫在下面,各位開發(fā)類似需求的可以參考一下,demo由于包含了其他公司的模型,這里就不提供給大家了
import UIKit
import SceneKit
import ARKit
class ViewController: UIViewController {
var scnView:ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
self.scnView = ARSCNView(frame: self.view.bounds)
// 打開調(diào)試模式
self.scnView.debugOptions = .showSkeletons
self.scnView.allowsCameraControl = true
self.scnView.scene = SCNScene()
self.view.addSubview(self.scnView)
// 分別加載對應(yīng)模型和對應(yīng)的骨骼動畫
let body = self.generateSkeletonNode("NPC_girl_001.dae", animationFileName: "body_walk.dae")
let clothes = self.generateSkeletonNode("NPC_girl_clothes001.dae", animationFileName: "body_walk.dae")
let hair = self.generateSkeletonNode("NPC_girl_hair002.dae", animationFileName: "body_walk.dae")
let shoes = self.generateSkeletonNode("NPC_girl_shoes001.dae", animationFileName: "body_walk.dae")
// 創(chuàng)建一個人的節(jié)點
let person = SCNNode()
person.scale = SCNVector3Make(0.01, 0.01, 0.01)
person.addChildNode(body)
person.addChildNode(clothes)
person.addChildNode(hair)
person.addChildNode(shoes)
self.scnView.scene.rootNode.addChildNode(person)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.scnView.session.run(ARWorldTrackingConfiguration(), options: .resetTracking)
}
func generateSkeletonNode(_ modelFileName:String,animationFileName:String)->SCNNode{
let resourceName = animationFileName.components(separatedBy: ".")[0]
let extensionName = animationFileName.components(separatedBy: ".")[1]
print(resourceName)
print(extensionName)
let skeletonNode = SCNSceneSource(url: Bundle.main.url(forResource: resourceName , withExtension:extensionName)! , options: nil)
let node = SCNScene(named: modelFileName)?.rootNode.clone()
var animations:[CAAnimation] = []
let animationIds = skeletonNode?.identifiersOfEntries(withClass: CAAnimation.self)
var maxDuration:CFTimeInterval = 0
for id in animationIds! {
if let animation = skeletonNode?.entryWithIdentifier(id, withClass: CAAnimation.self) {
animations.append(animation)
maxDuration = max(maxDuration,animation.duration)
}
}
let animationGroup = CAAnimationGroup()
animationGroup.animations = animations
animationGroup.duration = maxDuration
animationGroup.repeatCount = 1000
node?.addAnimation(animationGroup, forKey: nil)
return node!
}
}
技術(shù)參考Appstore 上架應(yīng)用《SceneKit》