xna 摄像机的旋转!

来源:互联网 发布:数据分析模型作用 编辑:程序博客网 时间:2024/04/29 18:06


xna 摄像机的旋转!

分类: xna 341人阅读 评论(0)收藏 举报
vectormatrixfloat扩展存储
           -2.指定相机的目标

问题

         当你定义视图矩阵,你要指定一个目标向量。用这个向量设置相机的旋转。

方案

        当旋转相机时,位置是不变的。当位置和目标限定视图矩阵,并且这个视图矩阵基于相机的位置,目标,向上向量,旋转将通过改变相机的目标点,以及向上向量。(半段没翻)译者注:指向相机正前方的向量叫”向前向量”或”目标向量”

如何运作

如2-1所示,相机独特定义需要位置、目标、向上向量。如果你想在3D空间的某一点旋转相机,位置向量不变,但目标向量也可能向上的向量会改变。

旋转角围绕3个轴,一种方法是用手算出目标位置。不过是非常复杂的计算,而更为简洁快速的解决办法是可能的。

最简单的例子:相机在原点,沿向上向量旋转

让我们检查相机在坐标(0,0,0)原点的情况.指向(0,0,-1)方向,向上向量是(0,1,0)。这时你的代码如下:

Vector3 cameraPosition = new Vector3(0,0,0);

Vector3 cameraTarget = new Vector3(0,0,-1);

Vector3 cameraUpVector = new Vector3(0,1,0);

viewMatrix = Matrix.CreateLookAt(cameraPostition,cameraTarget,cameraUpVector);

你想要一个矩阵绕向上向量旋转45度。把你的眼做相机,就等于你的眼向右转45度方向看。当计算新视图矩阵,你的位置向量和向上向量不变,但你要找出新目标向量。你可以把原(0,0,-1)向量旋转45度得到。就是找出原向量的旋转版本。代码如下:

Matrix cameraRotation = Matrix.CreateRotationY(MathHelper.PiOver4);

Vector3 cameraPosition = new Vector3(0,0,0);

Vector3 cameraUpVector = new Vector3(0,1,0);

Vector3 cameraOriginalTarget = new Vector3(0,0,-1);

Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget,cameraRotation);

viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraRotatedTarget, cameraUpVector);

注意 矩阵是可以代表任何类型转变强大对象。矩阵可以完成平移,旋转,缩放等变换,详见4-2

第一行创建一个矩阵描述一个绕向上的轴旋转45度(PI/4)。后面几行把原(0,0,-1)目标向量旋转并存在新变量中,用来创建新视图矩阵。

注意 这个转变没什么神奇;他就是向量和矩阵的乘法,矩阵中不过是一些普通数字。

    第二个例子:相机在原点,任意旋转

现在,让我们来看一个比较复杂的例子。不是绕向上向量旋转,而是绕任意轴。而这个例子不那么一般,绕(1,0,0)右向量旋转了45度。假设你的眼就是相机,结果是向上看45度。

因为只是旋转了相机,位置不变。目标向量和上一节一样发生了变化,因为相机要指向不同的点。

这时,向上向量也发生了变化。上个例子没改变向上向量,但当前例子,因为你抬头了,向上向量也就变了。

和改变向前向量一样改变你的向上向量:把旋转存储在一个矩阵,并定义原来的向上向量。接下来,用旋转矩阵旋转向上向量来获得新的。代码如下:

Matrix cameraRotation = Matrix.CreateRotationX(MathHelper.PiOver4);

Vector3 cameraPosition = new Vector3(0,0,0);

Vector3 cameraOriginalUpVector = new Vector3(0,1,0);

Vector3 cameraOriginalTarget = new Vector3(0,0,-1);

Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget,cameraRotation);

Vector3 cameraRotatedUpVector = Vector3.Transform(cameraOriginalUpVector,cameraRotation);

viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraRotatedTarget, cameraRotatedUpVector);

这是简单的绕X轴“任意”旋转。尽管相同的代码,可以完成一些旋转,像下面的代码,结合了绕3个轴的旋转。绕Z轴45度,Y轴22.5度,X轴90度:

Matrix cameraRotation =

Matrix.CreateRotationX(MathHelper.PiOver2)*

Matrix.CreateRotationY(MathHelper.Pi/8.0f)*

Matrix.CreateRotationZ(MathHelper.PiOver4);

位置不变,但你要找出相机旋转版的向前和向上向量。

第三个例子:相机在指定点,任意旋转

在最一般的情况下,你需要指定在3D空间的某一点设置一个相机并任意旋转。想象你的相机在3D空间的(10,20,30)这个点,没有旋转。很简单,位置向量是(10,20,30)。

你要你的相机朝(0,0,-1)方向看。

注意 记住,你必须指定目标点,而不是目标方向。用目标向量表示将是错误的,因为这会使你的相机永远看着(0,0-1)方向。想象等下你把相机移到(-10,20,30)。如果仍指定(0,0-1),相机将仍然看着(0,0-1)方向,目标就变了。

        所以你要指定(10,20,29)做目标向量。把相机位置和目标位置相加就能得到,像这样:

        Vector3 cameraPosition = new Vector3(10,20,30);

        Vector3 cameraOriginalTarget = new Vector3(0,0,-1);

        cameraTargetPoint = cameraPosition + cameraOriginalTarget;

现在是把一切组合的时候了。你将定义一个在(10,20,30)位置任意旋转的相机。位置向量仍是(10,20,30)。找到已经应用旋转后的向前方向,你用旋转矩阵改变了它。最后,找到目标向量,使定位在(10,20,30)将看着这个旋转了的方向,相机将重新审视这个旋转方向,你需要添加到这个旋转方向,向上向量同样的方法得到,代码如下:

Matrix cameraRotation =

Matrix.CreateRotationX(MathHelper.PiOver2)*

Matrix.CreateRotationY(MathHelper.Pi/8.0f)*

Matrix.CreateRotationZ(-MathHelper.PiOver4);

Vector3 cameraPosition = new Vector3(10,20,30);

Vector3 cameraOriginalTarget = new Vector3(0,0,-1);

Vector3 cameraOriginalUpVector = new Vector3(0,1,0);

Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget,cameraRotation);

Vecotr3 cameraFinalTarget = cameraPosition + cameraRotatedTarget;

Vector3 cameraRotatedUpVector = Vector3.Transform(cameraOriginalUpVector,cameraRotation);

Vecotr3 cameraFinalUpVector = cameraPosition + cameraRotatedUpVector;

viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraFinalUpVector, cameraFinalTarget);

    移动旋转了的相机

现在你的相机朝着正确的方向,但移动相机是新挑战。如果想向前移动,简单的加(0,0,-1)到位置向量是不行的,因为你要找出旋转后的相对位置。你在第一个例子已经通过旋转(0,0,-1)向量做到了。简单的添加如下代码:

Float moveSpeed = 0.5f;

Vector3 cameraOriginalForward = new Vector3(0,0,-1);

Vector3 cameraRotatedForward = Vector3.Transform(cameraOriginalForward,cameraRotation);

cameraPosition += moveSpeed * cameraRotatedForward;

改变moveSpeed的值将改变相机移动的速度,因为这个值乘以旋转过的向量。左右移动也是一样的,(1,0,0)就是向右的向量,当然也要被旋转。

float moveSpeed = 0.5f;

Vector3 cameraOriginalRight = new Vector3(1,0,0);

Vector3 cameraRotatedRight = Vector3.Transform(cameraOriginalRight,cameraRotation);

cameraPosition += moveSpeed * cameraRotatedRight;

完整代码自己下载看吧

扩展阅读

    矩阵乘法规则(见4-2)

    选择坐标系统

把(0,0,-1)作为向前(0,1,0)作为向上是XNA的官方向量方向,你也可以用Vector3.Forward和Vector3.Up来快捷表示。这只是个惯例,但你可以自定义比如(0,0,1)作为向前,(0-1,0)作为向上,随你高兴,这只取决于你想要为你的项目采用什么坐标系统。

然而,3个向量必须服从XNA的规则,他们的X,Y和Z轴形成一个右手坐标系统。这意味着一旦你知道其中2个轴,你就能得到第3个。拿出你的右手,平摊你的手掌,伸出拇指(和手掌同平面)让它和食指互成90度,折回另外3指,使他们垂直于你的手掌。这就是你在XNA的坐标系统,其中拇指是X轴,食指是Y轴,其余3指是Z轴。所指的均为各轴正方向。

拇指向右,食指向上,你就知道为什么向前的向量是(0,0,-1)了。

0 0