gpt4 book ai didi

ios - SCNCamera 移动相机的枢轴

转载 作者:行者123 更新时间:2023-11-28 08:31:14 25 4
gpt4 key购买 nike

我需要关注某个节点,例如金字塔。然后将距离应用于相机,然后根据用户点击移动相机。我的方法是这样的:

import SceneKit

class GameViewController: UIViewController {
let scene = SCNScene()
override func viewDidLoad() {
super.viewDidLoad()
let camera = SCNCamera()
camera.usesOrthographicProjection = true
camera.orthographicScale = 4
camera.zNear = 1
camera.zFar = 100
let cameraNode = SCNNode()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 6)
cameraNode.camera = camera
let cameraOrbit = SCNNode()
cameraOrbit.name = "orbit"
cameraOrbit.addChildNode(cameraNode)
scene.rootNode.addChildNode(cameraOrbit)

let Py = SCNPyramid(width: 2, height: 3, length: 2)
Py.firstMaterial?.diffuse.contents = UIColor.purple()
let P = SCNNode(geometry: Py)
P.position = SCNVector3(x:0,y:0,z:2) //see the note
scene.rootNode.addChildNode(P)

/* N O T E :
the position of the pyramid must not be changed
as my intention is to rotate the camera
not the pyramid node
I repeat, I don't want to rotate the pyramid
*/

let scnView = self.view as! SCNView
scnView.scene = scene
scnView.allowsCameraControl = false
scnView.backgroundColor = UIColor.black()

// user rotates the camera by tapping
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
scnView.addGestureRecognizer(tapGesture)
}


//the function which does camera rotation :
func handleTap(_ gestureRecognize: UIGestureRecognizer) {
//I guess the solution is around here
//like modify the cameraOrbit.position ?
//or cameraNode.position ?
//tried both but doesn't work
//or I used them wrong
let cameraOrbit = scene.rootNode.childNode(withName: "orbit", recursively: true)!
SCNTransaction.begin()
SCNTransaction.animationDuration = 2
cameraOrbit.eulerAngles.z += Float(M_PI_2) //see below
SCNTransaction.commit()
/*
I realise that by performing rotation on the camera
(the camera position is unchanged) works for z rotation,
but this is not what I want. What I want is a solution,
which also works for eulerAngles.x and eulerAngles.y.

I used eulerAngles.z as example since it's easier to observe.

I guess the true solution involves moving the camera
with specific trajectory, not only rotation of "anchored" camera.
*/
}

//...
}

结果是:

the triangle rotates around a point below the apex

我想要实现的是相对于它的中心进行旋转:

like this

我的问题是,如何调整枢轴以实现相对于金字塔中心的旋转?

注意:我不想旋转金字塔。

最佳答案

我找到了解决方案,但我无法解释原因。如果您可以解释,请发表评论。

相机轨道位置必须设置为与对象的位置(在本例中为金字塔)相匹配。所以

cameraOrbit.position = P.position

然后神秘的解决方案来了,将 cameraOrbit.position.y 添加到 pi 的一半:

cameraOrbit.position.y += Float(M_PI_2)
//therefore we have the final cameraOrbit.position as (0, pi/2, 2)

经过测试并完美适用于所有 cameraOrbit.eulerAngles。但我不知道它为什么有效。如果 pi/2 来自某种投影,那为什么它只隐藏在 y 上?我的意思是,当我执行任何 cameraOrbit.eulerAngles 时,我不需要将此 pi/2 分配给 x 或 z。

这是完整的代码

import SceneKit

class GameViewController: UIViewController {
let scene = SCNScene()
override func viewDidLoad() {
super.viewDidLoad()
let camera = SCNCamera()
camera.usesOrthographicProjection = true
camera.orthographicScale = 4
camera.zNear = 1
camera.zFar = 100
let cameraNode = SCNNode()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 6)
cameraNode.camera = camera
let cameraOrbit = SCNNode()
cameraOrbit.name = "orbit"
cameraOrbit.addChildNode(cameraNode)
scene.rootNode.addChildNode(cameraOrbit)

let Py = SCNPyramid(width: 2, height: 3, length: 2)
Py.firstMaterial?.diffuse.contents = UIColor.purple()
let P = SCNNode(geometry: Py)
P.position = SCNVector3(x:0,y:0,z:2)
scene.rootNode.addChildNode(P)

// S O L U T I O N :
cameraOrbit.position = P.position
cameraOrbit.position.y += Float(M_PI_2)
//therefore we have the final cameraOrbit.position as (0, pi/2, 2)

let scnView = self.view as! SCNView
scnView.scene = scene
scnView.allowsCameraControl = false
scnView.backgroundColor = UIColor.black()

// user rotates the camera by tapping
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
scnView.addGestureRecognizer(tapGesture)
}

//the function which does camera rotation :
func handleTap(_ gestureRecognize: UIGestureRecognizer) {
//I was wrong, the solution is not here
let cameraOrbit = scene.rootNode.childNode(withName: "orbit", recursively: true)!
SCNTransaction.begin()
SCNTransaction.animationDuration = 2
cameraOrbit.eulerAngles.z += Float(M_PI_2) //works also for x and y
SCNTransaction.commit()

}

...
}

关于ios - SCNCamera 移动相机的枢轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38839136/

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