【发布时间】:2023-03-03 13:03:01
【问题描述】:
也许这更像是一道数学题,但我希望有人能帮助我了解如何补偿相机方向的变化。
我想做的是能够使用类似游戏的控件在场景中移动我的相机。我设置了 W S A D 键来分别向前、向后、向左和向右移动相机。我通过更改相机节点的位置向量的值来做到这一点。我还有右左上和下箭头键映射到转动和倾斜相机。我通过调整相机节点的欧拉规则(俯仰和偏航)来做到这一点。
在我用左右箭头转动相机之前,一切正常。在此之后按 W 将相机移动到它在我对其应用偏航之前所面对的方向。这种行为对我来说很有意义,但我无法弄清楚我需要对位置矢量调整做什么来补偿我应用的偏航。
我是否需要以某种方式将我的位置向量乘以新的变换?或者更好的是还有其他一些属性,比如我可以更改的枢轴,以便我可以保持我的位置代码相同?
感谢您的任何指点。
这里更新的是我目前正在使用的代码:
public func displayTimerDidFire(timer: MyCustomDisplayTimer!) {
if timer === cameraMoveTimer {
var cameraTransform = cameraNode.transform
var x = CGFloat(0.0)
var y = CGFloat(0.0)
var z = CGFloat(0.0)
var step : CGFloat = 10.0
if moveUpKeyDown {
y += step
}
if moveDownKeyDown {
y -= step
}
if moveLeftKeyDown {
x -= step
}
if moveRightKeyDown {
x += step
}
if moveForwardKeyDown {
z -= step
}
if moveBackwardKeyDown {
z += step
}
cameraTransform = SCNMatrix4Translate(cameraTransform, x, y, z)
cameraNode.transform = cameraTransform
}
else if timer === cameraTiltTimer {
var angles = cameraNode.eulerAngles
var stepAngle : CGFloat = CGFloat(M_PI_2 / 90.0)
if turnLeftKeyDown {
angles.y += stepAngle
}
if turnRightKeyDown {
angles.y -= stepAngle
}
if tiltForwardKeyDown {
angles.x -= stepAngle
}
if tiltBackwardKeyDown {
angles.x += stepAngle
}
cameraNode.eulerAngles = angles
}
}
我有两个计时器,一个更新相机位置,另一个更新其方向。
我坚持的部分是我知道我的新变换(旧位置加上从 A S D W 的移动增量),我知道相机的旋转,但我不知道如何将这两者结合到我真正的新转换。 Transform 是 SCNMatrix4,rotation 是 SCNVector4。
更新 2
这是代码的修改版本。我改为使用转换。但是,我仍然找不到正确的操作来解释旋转。
public func displayTimerDidFire(timer: MyDisplayTimer!) {
var cameraTransform = cameraNode.transform
var x = CGFloat(0.0)
var y = CGFloat(0.0)
var z = CGFloat(0.0)
var step : CGFloat = 10.0
if moveUpKeyDown {
y += step
}
if moveDownKeyDown {
y -= step
}
if moveLeftKeyDown {
x -= step
}
if moveRightKeyDown {
x += step
}
if moveForwardKeyDown {
z -= step
}
if moveBackwardKeyDown {
z += step
}
cameraTransform = SCNMatrix4Translate(cameraTransform, x, y, z)
// Do something with the transform to compensate for rotation..
// ???
cameraNode.transform = cameraTransform
var angles = cameraNode.eulerAngles
var stepAngle : CGFloat = CGFloat(M_PI_2 / 90.0)
if turnLeftKeyDown {
angles.y += stepAngle
}
if turnRightKeyDown {
angles.y -= stepAngle
}
if tiltForwardKeyDown {
angles.x -= stepAngle
}
if tiltBackwardKeyDown {
angles.x += stepAngle
}
cameraNode.eulerAngles = angles
// printNode(cameraNode)
}
上次更新
感谢您的建议。这是对我有用的实现
我需要这个 objc 助手,因为其中一些函数在 Swift 中似乎不可用:
@implementation MySceneKitUtils
+ (SCNVector3)position:(SCNVector3)position multipliedByRotation:(SCNVector4)rotation
{
if (rotation.w == 0) {
return position;
}
GLKVector3 gPosition = SCNVector3ToGLKVector3(position);
GLKMatrix4 gRotation = GLKMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z);
GLKVector3 r = GLKMatrix4MultiplyVector3(gRotation, gPosition);
return SCNVector3FromGLKVector3(r);
}
@end
以及实现
public func displayTimerDidFire(timer: MyDisplayTimer!) {
var x = CGFloat(0.0)
var y = CGFloat(0.0)
var z = CGFloat(0.0)
var step : CGFloat = 10.0
if moveUpKeyDown {
y += step
}
if moveDownKeyDown {
y -= step
}
if moveLeftKeyDown {
x -= step
}
if moveRightKeyDown {
x += step
}
if moveForwardKeyDown {
z -= step
}
if moveBackwardKeyDown {
z += step
}
var cameraTransform = cameraNode.transform
var rotation = cameraNode.rotation
var rotatedPosition = MySceneKitUtils.position(SCNVector3Make(x, y, z), multipliedByRotation: cameraNode.rotation)
cameraTransform = SCNMatrix4Translate(cameraTransform, rotatedPosition.x, rotatedPosition.y, rotatedPosition.z)
cameraNode.transform = cameraTransform
// The rotation
cameraTransform = cameraNode.transform
var stepAngle = CGFloat(0.05)
if turnLeftKeyDown {
cameraTransform = SCNMatrix4Rotate(cameraTransform, stepAngle, 0.0, 1.0, 0.0);
}
if turnRightKeyDown {
cameraTransform = SCNMatrix4Rotate(cameraTransform, -stepAngle, 0.0, 1.0, 0.0);
}
if tiltForwardKeyDown {
cameraTransform = SCNMatrix4Rotate(cameraTransform, stepAngle, 1.0, 0.0, 0.0);
}
if tiltBackwardKeyDown {
cameraTransform = SCNMatrix4Rotate(cameraTransform, -stepAngle, 1.0, 0.0, 0.0);
}
cameraNode.transform = cameraTransform
}
【问题讨论】:
-
发布您的代码,听起来像是一个简单的错误,因为您将转换从输入应用到相机
-
更新了代码示例。谢谢。