节点(相机)的连续平滑增量旋转
continuos smooth incremental rotation of a node (camera)
我正在尝试将相机绕 x 轴增量旋转 5 度。它工作正常,除了突然跳 355 次的动画。它是由于动画链接而发生的。如果在 SCNSceneRendererDelegate
中调用了我的以下方法,则它不是基于时间的轮换。 SCNSceneRendererDelegate
在每一帧中被触发。这意味着我的持续时间场景动画动作还没有准备好。通过降低动画持续时间,动画不再流畅。做一个基于与动画持续时间相同的间隔的计时器看起来也很糟糕。有没有办法让这个动画流畅?
-(void) updateCameraRotation
{
SCNQuaternion oldRotScnQuat = _cameraNode.presentationNode.rotation;
GLKQuaternion glQuatOldRot = GLKQuaternionMakeWithAngleAndAxis(oldRotScnQuat.w, oldRotScnQuat.x, oldRotScnQuat.y, oldRotScnQuat.z);
float xan = GLKMathDegreesToRadians(5);
GLKQuaternion newx = GLKQuaternionIdentity;
GLKVector3 vec = GLKVector3Normalize(GLKVector3Make(1, 0, 0));
double result = sinf(xan/2);
newx = GLKQuaternionMakeWithAngleAndAxis(cosf(xan/2), vec.x *result, vec.y * result, vec.z * result);
newx = GLKQuaternionNormalize(newx);
glQuatOldRot = GLKQuaternionMultiply(glQuatOldRot, newx);
axis = GLKQuaternionAxis(glQuatOldRot);
angle = GLKQuaternionAngle(glQuatOldRot);
[_cameraNode runAction:[SCNAction rotateToAxisAngle:SCNVector4Make(axis.x, axis.y, axis.z, angle) duration:1]];
}
SLERP 用于在两个已知姿态之间进行平滑旋转。尝试避免在轴角和四元数之间进行不必要的转换(如果可能,将它们保留在四元数中)。
http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
您还需要计算四元数轴之间的角度:https://math.stackexchange.com/questions/90081/quaternion-distance
这两个功能我都用过,效果不错。
您可以指定 [0, 1].
范围内的标量 t,而不是每帧添加 5 度
例如,当从四元数 P 旋转到 Q 时,R = SLERP(P,Q,t) 将为您提供从 P 到 Q 的四元数 R。如果 t = 0,则 R = P,如果 t = 1那么 R = Q.
尝试提供一个 CABasicAnimation,将 byValue 设置为您的 5 度并将重复次数设置为无限。那行不通吗?
我正在尝试将相机绕 x 轴增量旋转 5 度。它工作正常,除了突然跳 355 次的动画。它是由于动画链接而发生的。如果在 SCNSceneRendererDelegate
中调用了我的以下方法,则它不是基于时间的轮换。 SCNSceneRendererDelegate
在每一帧中被触发。这意味着我的持续时间场景动画动作还没有准备好。通过降低动画持续时间,动画不再流畅。做一个基于与动画持续时间相同的间隔的计时器看起来也很糟糕。有没有办法让这个动画流畅?
-(void) updateCameraRotation
{
SCNQuaternion oldRotScnQuat = _cameraNode.presentationNode.rotation;
GLKQuaternion glQuatOldRot = GLKQuaternionMakeWithAngleAndAxis(oldRotScnQuat.w, oldRotScnQuat.x, oldRotScnQuat.y, oldRotScnQuat.z);
float xan = GLKMathDegreesToRadians(5);
GLKQuaternion newx = GLKQuaternionIdentity;
GLKVector3 vec = GLKVector3Normalize(GLKVector3Make(1, 0, 0));
double result = sinf(xan/2);
newx = GLKQuaternionMakeWithAngleAndAxis(cosf(xan/2), vec.x *result, vec.y * result, vec.z * result);
newx = GLKQuaternionNormalize(newx);
glQuatOldRot = GLKQuaternionMultiply(glQuatOldRot, newx);
axis = GLKQuaternionAxis(glQuatOldRot);
angle = GLKQuaternionAngle(glQuatOldRot);
[_cameraNode runAction:[SCNAction rotateToAxisAngle:SCNVector4Make(axis.x, axis.y, axis.z, angle) duration:1]];
}
SLERP 用于在两个已知姿态之间进行平滑旋转。尝试避免在轴角和四元数之间进行不必要的转换(如果可能,将它们保留在四元数中)。 http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
您还需要计算四元数轴之间的角度:https://math.stackexchange.com/questions/90081/quaternion-distance
这两个功能我都用过,效果不错。 您可以指定 [0, 1].
范围内的标量 t,而不是每帧添加 5 度例如,当从四元数 P 旋转到 Q 时,R = SLERP(P,Q,t) 将为您提供从 P 到 Q 的四元数 R。如果 t = 0,则 R = P,如果 t = 1那么 R = Q.
尝试提供一个 CABasicAnimation,将 byValue 设置为您的 5 度并将重复次数设置为无限。那行不通吗?