SceneKit:如果目标是旋转相机和项目节点X单位在相机前,使用变换或直接操纵旋转/位置属性?
对于体素艺术应用程序,其目标是让用户在SceneKit场景中移动和旋转摄像头,然后点击以放置块。
下面的代码让用户通过平移来旋转摄像头。 手势结束后,我们移动一个现有的块,使其在相机的Z轴上为-X个单位(即相机前面的-X个单位)。
cameraNode
是场景的angular度,是userNode
一个子userNode
。 当用户移动操纵杆时,我们更新userNode.
的位置userNode.
问题:其他SOpost通过应用变换而不是改变旋转和位置属性来操作相机节点。 一种方法比另一种更好吗?
func sceneViewPannedOneFinger(sender: UIPanGestureRecognizer) { // Get pan distance & convert to radians let translation = sender.translationInView(sender.view!) var xRadians = GLKMathDegreesToRadians(Float(translation.x)) var yRadians = GLKMathDegreesToRadians(Float(translation.y)) // Get x & y radians xRadians = (xRadians / 6) + curXRadians yRadians = (yRadians / 6) + curYRadians // Limit yRadians to prevent rotating 360 degrees vertically yRadians = max(Float(-M_PI_2), min(Float(M_PI_2), yRadians)) // Set rotation values to avoid Gimbal Lock cameraNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: yRadians) userNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: xRadians) // Save value for next rotation if sender.state == UIGestureRecognizerState.Ended { curXRadians = xRadians curYRadians = yRadians } // Set preview block setPreviewBlock() } private func setPreviewBlock(var futurePosition: SCNVector3 = SCNVector3Zero, reach: Float = 8) -> SCNVector3 { // Get future position if SCNVector3EqualToVector3(futurePosition, SCNVector3Zero) { futurePosition = userNode.position } // Get current position after accounting for rotations let hAngle = Float(cameraNode.rotation.w * cameraNode.rotation.x) let vAngle = Float(userNode.rotation.w * userNode.rotation.y) var position = getSphericalCoords(hAngle, t: vAngle, r: reach) position += userNode.position // Snap position to grid position = position.rounded() // Ensure preview block never dips below floor position.y = max(0, position.y) // Return if snapped position hasn't changed if SCNVector3EqualToVector3(position, previewBlock.position) { return position } // If here, animate preview block to new position SCNTransaction.begin() SCNTransaction.setAnimationDuration(AnimationTime) previewBlock.position = position SCNTransaction.commit() // Return position return position } func getSphericalCoords(s: Float, t: Float, r: Float) -> SCNVector3 { return SCNVector3(-(cos(s) * sin(t) * r), sin(s) * r, -(cos(s) * cos(t) * r)) }