gpt4 book ai didi

ios - iPhone 5 上的 SceneKit 和 CoreMotion "lagging"但在 iPhone 6 上正常

转载 作者:搜寻专家 更新时间:2023-10-30 22:28:42 25 4
gpt4 key购买 nike

我正在使用 SceneKit 进行测试,所以我决定制作一个虚拟现实测试应用程序。我将从设备运动中获取数据,然后根据数据更改摄像机角度。我在 iPhone 6 上进行测试,所以没问题。当我在 iPhone 5 和 friend 的 iPhone 5S 上运行它时,事情变得很奇怪,相机将需要一些延迟才能旋转,这与 iPhone 6 非常不同,后者是即时的。 Xcode 上的 FPS 在两台设备上都保持在 60 FPS 左右,我添加了一些时间测试,两台设备上的运动数据也在 60Hz 左右。我迷路了。

代码的基础是这个项目:https://github.com/stevenjs/VR-iOS-Experiment

如果可能的话,我想要一些关于如何修复它的提示,而不仅仅是准备好复制和粘贴的代码。我想学习。

我无法用语言很好地解释它,所以我录制了一些视频向您展示这是怎么回事:

iPhone 6:https://www.youtube.com/watch?v=pdyTEwvsR1I

iPhone 5:https://www.youtube.com/watch?v=MlDdKtHkrYo

代码如下:

    // Create Scene
var scene = SCNScene()
scnView.scene = scene
//scnView.autoenablesDefaultLighting = true

//Add camera to scene.
let camera = SCNCamera()
camera.xFov = 45
camera.yFov = 45

let camerasNode = SCNNode()
camerasNode.camera = camera
camerasNode.position = SCNVector3(x: 0, y: 0, z: 0)
// The user will be holding their device up (i.e. 90 degrees roll from a flat orientation)
// so roll the camera by -90 degrees to orient the view correctly
// otherwise the object will be created "below" the user
camerasNode.eulerAngles = SCNVector3Make(degreesToRadians(-90.0), 0, 0)

let cameraRollNode = SCNNode()
cameraRollNode.addChildNode(camerasNode)

let cameraPitchNode = SCNNode()
cameraPitchNode.addChildNode(cameraRollNode)

let cameraYawNode = SCNNode()
cameraYawNode.addChildNode(cameraPitchNode)

scene.rootNode.addChildNode(cameraYawNode)

scnView.pointOfView = camerasNode

// Ambient Light
let ambientLight = SCNLight()
ambientLight.type = SCNLightTypeAmbient
ambientLight.color = UIColor(white: 0.1, alpha: 1.0)
let ambientLightNode = SCNNode()
ambientLightNode.light = ambientLight
scene.rootNode.addChildNode(ambientLightNode)

// Omni Light
let diffuseLight = SCNLight()
diffuseLight.type = SCNLightTypeOmni
diffuseLight.color = UIColor(white: 1.0, alpha: 1.0)
let diffuseLightNode = SCNNode()
diffuseLightNode.light = diffuseLight
diffuseLightNode.position = SCNVector3(x: -30, y: 30, z: 50)
scene.rootNode.addChildNode(diffuseLightNode)

let material = SCNMaterial()
material.diffuse.contents = UIColor.redColor()
material.locksAmbientWithDiffuse = true
let material2 = SCNMaterial()
material2.diffuse.contents = UIColor.whiteColor()
material2.locksAmbientWithDiffuse = true
let material3 = SCNMaterial()
material3.diffuse.contents = UIColor.blueColor()
material3.locksAmbientWithDiffuse = true
let material4 = SCNMaterial()
material4.diffuse.contents = UIColor.purpleColor()
material4.locksAmbientWithDiffuse = true
let material5 = SCNMaterial()
material5.diffuse.contents = UIColor.yellowColor()
material5.locksAmbientWithDiffuse = true
let material6 = SCNMaterial()
material6.diffuse.contents = UIColor.orangeColor()
material6.locksAmbientWithDiffuse = true


//Create the box
let baseBox = SCNBox(width: 5, height: 5, length: 5, chamferRadius: 0)

baseBox.materials = [material, material2, material3, material4, material5, material6]
let boxNode = SCNNode(geometry: baseBox)
boxNode.position = SCNVector3(x: 0, y: 3, z: -10)
scene.rootNode.addChildNode(boxNode)


// Respond to user head movement
motionManager = CMMotionManager()
motionManager?.deviceMotionUpdateInterval = 1.0 / 60.0

motionManager?.startDeviceMotionUpdatesUsingReferenceFrame(CMAttitudeReferenceFrameXArbitraryZVertical,
toQueue: NSOperationQueue.mainQueue(),
withHandler: { (motion: CMDeviceMotion!, error: NSError!) -> Void in
self.counter++
let currentAttitude = motion.attitude
let roll = Float(currentAttitude.roll)
let pitch = Float(currentAttitude.pitch)
let yaw = Float(currentAttitude.yaw)

//only working at 60FPS on iPhone 6... WHY

//according to documentation, SCNVector3 from a node is, (pitch, yaw, node)
cameraRollNode.eulerAngles = SCNVector3Make(0.0, 0.0, -roll)
cameraPitchNode.eulerAngles = SCNVector3Make(pitch, 0.0, 0.0)
cameraYawNode.eulerAngles = SCNVector3Make(0.0, yaw, 0.0)
})

最佳答案

好吧,这只是一种预感,但我想它是正确的,所以让我们把它正式化吧!

您的问题似乎是有两个 60Hz 计时器/循环在主线程上争用时间 — CoreMotion 更新队列和 SceneKit 渲染循环。您正在有效地从一个到另一个进行通信,因为您在 CoreMotion 更新处理程序中设置 SceneKit 状态,并希望 SceneKit 渲染循环在同一帧上拾取它。

(我怀疑硬件差异在于 iPhone 6 有足够的性能开销,以至于时序恰好可以正常工作,而较旧的硬件则不然——所以 SceneKit 正在拾取比你的模型落后一两帧的模型位置运动数据。)

相反,在同一个 60Hz 循环中执行所有操作。 (实际上,这是一个很好的一般性建议,无论您的其他 60Hz 事件源是 CoreMotion 还是其他东西 — 在游戏引擎或类似的实时渲染器中,您应该让渲染的目标帧率决定您所做的一切。)

这意味着您应该轮询运动数据,而不是将其推送给您——您只关心您正在渲染的帧的时间戳的运动状态,而不是来自的样本之前 1/60 秒,或者如果丢帧,最后几个样本。使用 scene renderer delegate 连接到 SceneKit 渲染循环, 阅读 CoreMotion 的 deviceMotion在您的 renderer:updateAtTime: 方法中并在那里设置您的模型旋转。请注意,您仍然需要调用 startDeviceMotionUpdatesUsingReferenceFrame:在开始轮询运动数据之前。

此外,SceneKit 通常仅在知道场景内容需要动画时才运行其渲染循环——例如如果您已将动画附加到场景中的某物,或在事务中设置动画属性,或使用 Action 或物理。 (这样,如果渲染的下一帧与上一帧相同,它就不会耗尽设备的电池一次又一次地绘制相同的东西。)但是当您希望在动画循环期间进行更改时,你需要确保它一直在运行。

设置playing将 View 上的属性设置为 true 实际上是正确的方法——它告诉 SceneKit 你希望它继续渲染,而不是在动画停止时停止。 (是的,文档在这一点上可能会更清楚......如果你 let Apple know 他们可能会修复它。)


最后,Swift 提示:您可以直接将结构类型的属性分配给成员,而无需构造一个全新的值,所以不要这样做:

cameraRollNode.eulerAngles = SCNVector3Make(0.0, 0.0, -roll)
cameraPitchNode.eulerAngles = SCNVector3Make(pitch, 0.0, 0.0)
cameraYawNode.eulerAngles = SCNVector3Make(0.0, yaw, 0.0)

你可以这样做:

cameraRollNode.eulerAngles.z = -roll
cameraPitchNode.eulerAngles.x = pitch
cameraYawNode.eulerAngles.y = yaw

关于ios - iPhone 5 上的 SceneKit 和 CoreMotion "lagging"但在 iPhone 6 上正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29283877/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com