如何实现sceneView.pointOfView绕根节点轴线旋转?
如何确保sceneView.pointOfView的旋转围绕根节点轴线进行?
问题背景
当前代码直接给sceneView.pointOfView设置固定transform,导致相机围绕自身轴线旋转,出现目标对象偏移视野的问题。需要实现相机围绕根节点下3D对象的轴线旋转的效果,且不直接旋转根节点或目标对象。
解决方案
核心是让相机围绕目标点(此处为iPad节点的世界位置)旋转,通过计算相机旋转后的位置并保持相机朝向目标点,而非直接修改相机的transform:
- 获取目标节点的世界空间位置作为旋转中心
- 计算相机到目标点的原始距离,确保旋转后距离不变
- 应用旋转矩阵计算相机相对于目标点的新偏移位置
- 让相机始终看向目标点,保证旋转围绕目标轴线进行
修改后的关键代码
替换原doubleTapped方法:
@objc func doubleTapped(sender: UITapGestureRecognizer) { SCNTransaction.begin() SCNTransaction.animationDuration = 1 guard let cameraNode = sceneView.pointOfView, let ipadNode = myScene.rootNode.childNodes.first(where: { $0.name?.contains("iPad") ?? false }) else { return } // 获取iPad的世界位置作为旋转中心 let targetPosition = ipadNode.worldPosition // 计算相机到目标点的原始距离,保证旋转后距离不变 let originalDistance = SCNVector3Distance(cameraNode.position, targetPosition) // 定义旋转角度(可根据需求调整,对应期望的旋转效果) let rotationAngleX: Float = -0.12 let rotationAngleY: Float = 0.0 let rotationAngleZ: Float = -0.04 // 创建围绕目标轴线的旋转矩阵 let rotationMatrix = SCNMatrix4Rotate(SCNMatrix4Identity, rotationAngleX, 1, 0, 0) .rotatedBy(angle: rotationAngleY, aroundAxis: SCNVector3(0, 1, 0)) .rotatedBy(angle: rotationAngleZ, aroundAxis: SCNVector3(0, 0, 1)) // 计算旋转后的相机偏移向量 let initialOffset = SCNVector3(0, 0, originalDistance) // 初始相机在Z轴正方向 let rotatedOffset = SCNVector3ApplyMatrix4(initialOffset, rotationMatrix) // 设置相机新位置:目标点 + 旋转后的偏移 cameraNode.position = SCNVector3Add(targetPosition, rotatedOffset) // 让相机始终看向目标点 cameraNode.look(at: targetPosition) cameraNode.camera?.fieldOfView = 60 SCNTransaction.commit() }
效果对比
- 错误效果:

- 期望效果:

- 3D对象参考:

内容的提问来源于stack exchange,提问作者Hassan Taleb
相关产品推荐
相关产品推荐

