应用程序开发总结(11)--三维中Camera的控制的总结

第十三章  三维中Camera的控制的总结

   13.1 环绕平滑浏览

     这里说的环绕浏览,是指绕一个轴旋转浏览。这种方式就等于从一个球上的一点移动到球面的另外一点。而平滑浏览是指这两点之间的轨迹在球面上,从而构成一个圆弧。

假如存在起点P,终点为Q,中间插值点M,那么M的计算可以通过一个函数来获得,M=F(P,Q,t)。如果PMQ三点是直线的话,F就是直线的公式,也就是M=P*t+Q(1-t)。但是现在不是直线,而是曲线,所以这个公式自然跟直线的不同。

     这时候我们引入四元数。四元数可以实现下面功能:

  • 球面上的一点可以通过转换转换为四元数,也可以从四元数反转化为球面一点。
  • 两个四元数可以进行插值运算,而且插值的结果是等差的。(也就是说|MP|/|PQ|=t/1,其中|MP|表示MP的模)
   好了,至此环绕平滑浏览的基本思路应该明了了。下面的就是一些细节了。
   
   第一个问题,球面一点如何转换为四元数。
       转换的方法有两种:
  •  球面上的一点可以笛卡尔坐标(X,Y,Z)来表示位置,位置转换为四元数是Quaternion4d(0,X,Y,Z);
  • 球面的一点使用欧拉角(φ,θ,ψ)来表示,然后再转换为四元数。
         其中球面一点转换为欧拉角的计算公式是 θ= Math.Atan2(Y, X); φ=Math.Asin(Z), ψ可以定义为自旋转角。【注:这里半径为1】
        欧拉角转四元数的公式是
     
  第二个问题,如何进行插值
     起点P和终点Q直接的角度差 θ,而等差的角度对应圆弧上相同的长度。所以使用的插值方式是 q(t)=q1 * sinθ(1-t)/sinθ + q2 * sinθt/sineθ

  到此,基本操作方式以及列举出来了。至于为啥是这样的,需要对四元数的计算进行额外的学习。下面简单的列出插值的函数:
public static Quaternion4d Slerp(Quaternion4d q0, Quaternion4d q1, double t)
        {
            double cosom = q0.X * q1.X + q0.Y * q1.Y + q0.Z * q1.Z + q0.W * q1.W;
            double tmp0, tmp1, tmp2, tmp3;
            if (cosom < 0.0)
            {
                cosom = -cosom;
                tmp0 = -q1.X;
                tmp1 = -q1.Y;
                tmp2 = -q1.Z;
                tmp3 = -q1.W;
            }
            else
            {
                tmp0 = q1.X;
                tmp1 = q1.Y;
                tmp2 = q1.Z;
                tmp3 = q1.W;
            }

            /* calc coeffs */
            double scale0, scale1;

            if ((1.0 - cosom) > double.Epsilon)
            {
                // standard case (slerp)
                double omega = Math.Acos(cosom);
                double t1 = omega * 180 / Math.PI;//可以从这看出起始点和终点直接的角度。

                double sinom = Math.Sin(omega);
                scale0 = Math.Sin((1.0 - t) * omega) / sinom;
                scale1 = Math.Sin(t * omega) / sinom;
            }
            else
            {
                /* just lerp */
                scale0 = 1.0 - t;
                scale1 = t;
            }

            Quaternion4d q = new Quaternion4d();

            q.X = scale0 * q0.X + scale1 * tmp0;
            q.Y = scale0 * q0.Y + scale1 * tmp1;
            q.Z = scale0 * q0.Z + scale1 * tmp2;
            q.W = scale0 * q0.W + scale1 * tmp3;

            return q;
        }
    另外,采用不同的球面一点如何转换为四元数方式会产生不同的效果。欧拉角转四元数的方式,如果把 ψ设为0,那么跟笛卡尔转欧拉角的效果差不多,生成的圆弧半径是球的半径。但是如果 ψ!=0,那么会导致斜的圆弧。下面配两幅图简单的展示下。

 


参考文档
[0]   kUANGtOBY的日记      http://www.douban.com/note/206638855/

[2]  四元数与欧拉角之间的转换  http://www.cnblogs.com/wqj1212/archive/2010/11/21/1883033.html

猜你喜欢

转载自blog.csdn.net/htsitr2/article/details/39695027