Math 限制摄像机俯仰

Math 限制摄像机俯仰,math,3d,camera,quaternions,Math,3d,Camera,Quaternions,当我只有相机四元数时,如何有效地限制相机间距?我必须转换为euler角度,然后再转换回四元数吗?还是有其他方法?相机旋转四元数可以定义为: vector A = [x, y, z] Q.x = A.x * sin(theta/2) Q.y = A.y * sin(theta/2) Q.z = A.z * sin(theta/2) Q.w = cos(theta/2) 其中A是位置,θ是要旋转相机的角度(调整俯仰) 因此,如果您有可用的四元数,您可以通过每次验证旋转角度加/减实际角度是否正确来

当我只有相机四元数时,如何有效地限制相机间距?我必须转换为euler角度,然后再转换回四元数吗?还是有其他方法?

相机旋转四元数可以定义为:

vector A = [x, y, z] 
Q.x = A.x * sin(theta/2)
Q.y = A.y * sin(theta/2)
Q.z = A.z * sin(theta/2)
Q.w = cos(theta/2)
其中A是位置,θ是要旋转相机的角度(调整俯仰)

因此,如果您有可用的四元数,您可以通过每次验证旋转角度加/减实际角度是否正确来限制俯仰角度

我认为你可以避免转换,如果你把你的限制设置为

+cos(supLim/2) < (Q.w + P.w) < -cos(infLim/2)
+cos(supLim/2)<(Q.w+P.w)<-cos(infLim/2)
因为余弦是一个连续函数,所以这应该是可行的


如果您可以发布您实际使用的代码,也许我们可以提供更多帮助。

俯仰只是整个旋转的一个组成部分,因此如果您想这样考虑旋转,最好单独存储俯仰,可能使用Euler角度

当你需要限制运动时,仅仅转换为Euler角并返回可能不太好,因为你需要记住最后一帧(如果你有),看看你是否通过了限制,以及在什么方向


在我看来,四元数的要点是,你不必为这样的极限而烦恼。任何事物都没有任何奇点。你到底为什么要限制投球?

如果相机从来没有任何滚动(这在很多游戏中很常见,比如第一人称射击),那么解决方案很简单。如果有滚动,则需要另外一个步骤。我将从没有滚动时该做什么开始,并将解决方案推广到有滚动时该做什么

让qc是摄像机的旋转。让qy以与qc相同的偏航旋转,但以零俯仰旋转。如果没有滚动,相机旋转是偏航旋转,然后是俯仰旋转:

qc = qp * qy
我们可以将俯仰旋转qp恢复为从qy到qc的旋转:

qp = qc * qy^-1
那么,诀窍就是构造qy,这样我们就可以把它插入上面的方程来求解qp。设vc为指向相机镜头外的单位矢量,或“前向矢量”。设vy为同一向量,但投影到水平面并归一化。最后,当摄像机旋转qc为恒等旋转时,设v0为正向矢量。将v0旋转为vy的旋转是偏航旋转。该角度可表示为:

yaw = asin(Norm(cross(v0, vy)))
相应的偏航旋转为:

qy = { cos(yaw/2), up * sin(yaw/2) }
其中“向上”是向上方向的单位矢量,也称为偏航旋转轴。将其插入上面的qp=qy^-1*qc以获得俯仰四元数qp。最后,从qp获得俯仰角,如下所示:

pitch = 2*asin(Dot(right, [qp[1], qp[2], qp[3]]))
其中“right”是右方向的单位矢量,也称为俯仰旋转轴

就像我说的,如果相机也有滚动,事情会变得更复杂,但总体策略是一样的。将摄影机旋转公式化为旋转组件的乘积,然后隔离所需的组件(在本例中为俯仰)。例如,如果用于定义“俯仰”的欧拉序列是常见的偏航-俯仰-滚转序列,则将qc定义为:

qc = qr * qp * qy
我们可以将变量qx定义为纵摇和横摇的组合旋转:

qx = qr * qp
我们现在可以将qc写为:

qc = qx * qy
我们已经知道如何以这种形式求解qx,通过回顾我们在上面用于求解qp的步骤。重新定义qx,我们得到:

qp = qr^-1 * qx
我们刚刚解决了qx,所以要解决俯仰旋转qp,我们只需要滚动qr。我们可以像以前一样使用向量来构造它。让vc再次成为前向向量。滚动将围绕该向量旋转。让vu为摄影机的上方向向量(在世界坐标系中),让vu0为摄影机的上方向向量,滚动为零。我们可以通过将全局上方向向量投影到垂直于vc的平面,然后进行规格化来构造vu0。滚动旋转qr是从vu0到vu的旋转。此旋转的轴为正向矢量vc。滚动角度是

roll = asin(Dot(vc, cross(vu0, vu)))
相应的四元数为:

qr = { cos(roll/2), forward * sin(roll/2) }

其中“前进”是滚动旋转轴。

我可能会晚一点参加聚会,但我就是这样解决的:

        // "Up" = local vector -> rotation * Vector3.UnitY
        // "Forward" = local vector -> rotation * Vector3.UnitZ
        // "Right" = local vector -> rotation * Vector3.UnitX

    public void Rotate(Vector3 axis, float angle)
    {
        if (LerpRotation)
        {
            RotationTarget *= Quaternion.FromAxisAngle(axis, angle);
        }
        else
        {
            Rotation *= Quaternion.FromAxisAngle(axis, angle);
        }
        //Locking the Pitch in 180°
        float a = Vector3.CalculateAngle(Vector3.UnitY, Up);
        float sign = Math.Sign(Forward.Y);
        float delta = (float)Math.PI / 2 - a;
        if(delta < 0)
            Rotation *= Quaternion.FromAxisAngle(Right, delta * sign);
    }
/“向上”=局部向量->旋转*向量3.1
//“前进”=局部向量->旋转*向量3.UnitZ
//“右”=局部向量->旋转*向量3.UnitX
公共空心旋转(矢量3轴,浮动角度)
{
如果(保护)
{
旋转目标*=四元数。从轴角度(轴,角度);
}
其他的
{
旋转*=四元数。从轴角度(轴,角度);
}
//将俯仰锁定在180°
浮点a=Vector3.CalculateAngle(Vector3.UnitY,向上);
浮点符号=数学符号(正向Y);
float delta=(float)Math.PI/2-a;
if(δ<0)
旋转*=四元数。从轴角度(右,三角形*符号);
}

Wert,过去几个小时我一直在想一个好答案。。。伙计,我已经好几年没有处理过四元数了。。。我现在有烟从我的耳朵里冒出来。。。我放弃…;-)隐马尔可夫模型。。A不是旋转轴吗?如果四元数超过了间距限制,我怎么能将其设置为间距限制?A绝对是轴作为单位向量。即使“位置”是一个输入错误,只有当Q已经是俯仰旋转,而不是相机的总旋转C时,答案才会起作用。我们试图从C中提取Q。