基礎(chǔ)概念就不講了,講講SceneKit
和RealityKit
構(gòu)建AR場景的差異模闲。
一.支持的系統(tǒng)和手機(jī)型號
1.SceneKit
支持iOS11.0以上系統(tǒng)建瘫,iphone 6s以上手機(jī)(即iphone8,1以上)。
2.RealityKit
支持iOS13.0以上系統(tǒng)尸折,iphone xs以上手機(jī)(即iphone11,2以上)啰脚。
二.追蹤模式
1.平面追蹤
沒有區(qū)別,iOS11.3以上支持垂直平面檢測(如墻面)实夹,iOS13支持人體遮擋拣播,AR場景不再浮在人物表面,而是根據(jù)空間位置有人體遮擋效果收擦。讓AR體驗更加真實。
let config = ARWorldTrackingConfiguration()
if #available(iOS 13.0,*){
if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentationWithDepth){
config.frameSemantics = .personSegmentationWithDepth
}
}
2.人體追蹤
RealityKit
支持人體追蹤谍倦,具體代碼官方已給出塞赂。可以獲得人體各個節(jié)點(diǎn)的三維坐標(biāo)昼蛀,但是比較耗性能宴猾,可以在session
的didUpdate
代理方法里降低檢測頻率。
三.添加3D模型
1.SceneKit
除了可以創(chuàng)建比較規(guī)則的3D模型叼旋,如SCNBox
仇哆,SCNTube
等,還支持加載dae格式和obj格式的3D模型夫植。
let scene = SCNScene(name:"~.scnassets/model.dae")
let node = SCNNode()
for child in scene.rootNode.childNodes{
node.addChildNode(child)
}
2.RealityKit
可以創(chuàng)建比較規(guī)則的3D模型和3D文字(ModelEntity
)讹剔,也可以支持加載usdz格式的3d模型(導(dǎo)出usdz格式的方法)。
var cancellable : AnyCancellable ?= nil
cancellable = Entity.loadModelAsync(name:"model.usdz").sink(receiveCompletion:{ completion in
if case let .failure(error) = comletion{
print("加載失斚昝瘛:\(error.locaizedDescription)")
}
cancellable?.cancel()
},receiveValue:{(character:Entity) in
if let entity = character as? ModelEntity{
entity.scale = [0.001,0.001,0.001] //調(diào)整模型比例
cancellabe?.cancel()
}else{
//沒有找到ModelEntity類型的
}
})
四.模型動畫
1.系統(tǒng)動畫
SceneKit
支持關(guān)鍵幀動畫延欠,即CAKeyframeAnimation
,常見的有移動,旋轉(zhuǎn)沈跨,放大等由捎。還支持SCNAction,SCNTransaction動畫饿凛。
let node = SCNNode()
node.addAnimation(keyFrameAnimation(),forKey:nil)
//位置移動(從初始位置往0狞玛,0,0處移動)
let position = node.position
let moveAnimation = CAKeyframeAnimation.init(keyPath:"transform.translation")
moveAnimation.value = [NSValue.init(scnVector3:position),NSValue.init(scnVector3:SCNVector3Make(0,0,0))]
//scale動畫(從0到1)
let scaleAnimation = CAKeyframeAnimation.init(keyPath:"scale")
scaleAnimation.value = [NSValue.init(scnVector3:SCNVector3Make(0,0,0)),NSValue.init(scnVector3:SCNVector3Make(1,1,1))]
//rotate動畫(繞y軸旋轉(zhuǎn))
let rotateAnimation = CAKeyframeAnimation.init(keyPath:"rotation")
scaleAnimation.value = [NSValue.init(scnVector3:SCNVector4Make(0,0,0,0)),NSValue.init(scnVector3:SCNVector4Make(0,1,0,Float(-2*Double.pi)))]
RealityKit
支持的系統(tǒng)動畫就比較少了涧窒。
let entity = ModelEntity(
//省略
)
var transform = entity.transform
//scale動畫
transform.scale = SIMD3<Float>(repeating:1.0)
entity.move(to:transform,relationTo:entity.parent,duration:1,timingFunction.easeOut)
//rotate動畫(繞y軸旋轉(zhuǎn))
transform.rotation = simd_quatf(angle:-pi,axis:[0,1,0])
entity.move(to:transform,relationTo:entity.parent,duration:1,timingFunction.easeOut)
2.模型自帶動畫
SceneKit
加載和播放dae模型動畫
//加載動畫
let sceneURL = Bundle.main.url(forResource: sceneName, withExtension: "dae")
let sceneSource = SCNSceneSource(url: sceneURL!, options: nil)
let ids = sceneSource?.identifiersOfEntries(withClass:CAAnimation.self)
if let animationObject = sceneSource?.entryWithIdentifier((ids?.first)!, withClass: CAAnimation.self)
{
animationObject.repeatCount = 1
animationObject.fadeInDuration = CGFloat(1)
animationObject.fadeOutDuration = CGFloat(0.5)
//保存到字典
animations[withKey] = animationObject
}
//播放心肪、移除動畫
sceneView.scene.rootNode.addAnimation(animations[key]!, forKey: key)
sceneView.scene.rootNode.removeAnimation(forKey: key, blendOutDuration: CGFloat(0.5))
RealityKit
加載和播放usdz模型動畫(這個還未驗證,待填坑纠吴,可以參考開發(fā)文檔:Animation Playback)
五.采集攝像頭數(shù)據(jù)
1.SceneKit
和RealityKit
都可以在session
的代理方法里拿到CVPixelBuffer
數(shù)據(jù)蒙畴,然后進(jìn)行Metal,OpenGL ES圖像處理和音視頻編碼。
func session(_ session: ARSession, didUpdate frame: ARFrame) {
let pixelBuffer = frame.capturedImage
}
2.但此處拿到CVPixelBuffer
數(shù)據(jù)是不包含AR效果的膳凝。有個方案是:開個定時器每0.1s使用snapshot
方法獲取AR view的截屏碑隆,然后和攝像頭取得的數(shù)據(jù)合成。
3.可以參考GitHub上的ARVideoKit蹬音,支持ar截圖上煤,gifs,視頻劫狠。但目前不支持RealityKit
,希望后續(xù)能補(bǔ)上永部。
六.其他問題
1.Archive時出現(xiàn)了no such module RealityKit
報錯。
版本兼容性問題苔埋。低版本中不包含RealityKit
這個庫,需要加上編譯開關(guān)组橄。
# if canImport(RealityKit)
import RealityKit
//相關(guān)代碼
#endif
2.RealityKit
中的Entity
沒有隱藏的方法,可以設(shè)置materials
的顏色為透明色玉工。
self.entity.model.materials[0] = SimpleMaterial(color:roughness:,isMetallic:)
3.SceneKit
的render
代理方法里內(nèi)存經(jīng)常暴漲羽资,有優(yōu)化的空間(此坑待填)遵班。
七.總結(jié)
RealityKit
的人體追蹤還是很驚艷的,能夠較為準(zhǔn)確的識別人體動作狭郑,但是功耗高,攝像頭發(fā)熱非常明顯愿阐。另外可使用的api較SceneKit
少微服,有待完善缨历。AR
是非常值得期待的技術(shù)以蕴,就目前表現(xiàn)而言,娛樂性較強(qiáng)辛孵。而將娛樂性轉(zhuǎn)化為實用性丛肮,還有很長的一段路要走。