我正在向我之前从互联网上下载的场景中添加一个包含动画的3D model
。在添加此node
之前,我在其上使用prepare
函数,因为我不想避免丢帧。但是我仍然得到一个非常短的帧下降到大约47帧/秒。这是由执行此prepare
函数引起的。我也尝试在其他调度队列上使用prepare(_:, shouldAbortBlock:)
,但这仍然没有帮助。有人可以帮我解决这个问题,或者告诉我为什么会发生这种情况?
arView.sceneView.prepare([mediaNode]) { [mediaNode, weak self] (success) in
guard let `self` = self else { return }
guard
let currentMediaNode = self.mediaNode as? SCNNode,
currentMediaNode === mediaNode,
!self.mainNode.childNodes.contains(mediaNode)
else { return }
self.mainNode.addChildNode(mediaNode)
}
顺便说一下,这是我用来加载此模型的文件列表:
https://www.dropbox.com/s/7968fe5wfdcxbyu/Serah-iOS.dae?dl=1
https://www.dropbox.com/s/zqb6b6rxynnvc5e/0001.png?dl=1
https://www.dropbox.com/s/hy9y8qyazkcnvef/0002.tga?dl=1
https://www.dropbox.com/s/fll9jbjud7zjlsq/0004.tga?dl=1
https://www.dropbox.com/s/4niq12mezlvi5oz/0005.png?dl=1
https://www.dropbox.com/s/wikqgd46643327i/0007.png?dl=1
https://www.dropbox.com/s/fioj9bqt90vq70c/0008.tga?dl=1
https://www.dropbox.com/s/4a5jtmccyx413j7/0010.png?dl=1
DAE文件已由Xcode工具编译,因此可以在从Internet下载后加载。这是我用来在下载后加载它的代码:
class func loadModel(fromURL url: URL) -> SCNNode? {
let options = [SCNSceneSource.LoadingOption.animationImportPolicy : SCNSceneSource.AnimationImportPolicy.playRepeatedly]
let sceneSource = SCNSceneSource(url: url, options: options)
let node = sceneSource?.entryWithIdentifier("MDL_Obj", withClass: SCNNode.self)
return node
}
答案 0 :(得分:0)
在ARKit
/ SceneKit
/ AVKit
中删除丢帧的最简单方法是使用Metal框架。试想一下:与基于CPU的等效过滤器相比,简单的图像过滤器在GPU上的执行速度要快一百倍。关于实时AV视频和3D动画,我可以说同样的事情 - 它们在GPU上表现得更好。
例如,您可以阅读useful post关于使用AVCaptureSession
的金属渲染的信息。如何使用Metal,这是一个非常棒的工作流程。
P.S。在编写代码之前,请在3D创作工具中检查您的动画对象/场景(如果没问题)。
答案 1 :(得分:0)
我遇到了同样的问题。我的节点都利用了基于物理的渲染(PBR),并且第一次将节点添加到场景时,帧速率显着下降,但之后很好。我可以在没有帧速率下降的情况下添加任意数量的其他节点。
我想出了解决这个问题的方法。我做的是在创建ARConfiguration之后,在调用session.run(配置)之前,我将带有PBR的测试节点添加到场景中。为了不显示该节点,我将节点的材质的colorBufferWriteMask设置为空数组(请参阅此答案:ARKit hide objects behind walls)然后,在添加内容之前,我删除该节点。添加和删除此测试节点对我来说非常有用。
以下是一个例子:
var pbrTestNode: SCNNode!
func addPBRTestNode() {
let testGeometrie = SCNBox(width: 0.5, height: 0.5, length: 0.5, chamferRadius: 0)
testGeometrie.materials.first?.diffuse.contents = UIColor.blue
testGeometrie.materials.first?.colorBufferWriteMask = []
testGeometrie.materials.first?.lightingModel = .physicallyBased
pbrTestNode = SCNNode(geometry: testGeometrie)
scene.rootNode.addChildNode(pbrTestNode)
}
func removePBRTestNode() {
pbrTestNode.removeFromParentNode()
}
func startSessionWithPlaneDetection() {
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
if #available(iOS 11.3, *) {
configuration.planeDetection = [.horizontal, .vertical]
} else {
configuration.planeDetection = .horizontal
}
configuration.isLightEstimationEnabled = true
// this prevents the delay when adding any nodes with PBR later
sceneController.addPBRTestNode()
// Run the view's session
sceneView.session.run(configuration)
}
将内容添加到场景时调用removePBRTestNode()。