XNA 3.0 Game Programming Recipes翻译2-2

2-2.指定相机的目标

问题

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

方案

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

 

如何运作

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

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

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

让我们检查相机在坐标(000)原点的情况.指向(00-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度方向看。当计算新视图矩阵,你的位置向量和向上向量不变,但你要找出新目标向量。你可以把原(00-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个轴的旋转。绕Z45度,Y22.5度,X90度:

 

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.ForwardVector3.Up来快捷表示。这只是个惯例,但你可以自定义比如(0,0,1)作为向前,(0-1,0)作为向上,随你高兴,这只取决于你想要为你的项目采用什么坐标系统。

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

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

转载于:https://www.cnblogs.com/XNAconglele/archive/2009/08/24/1553245.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值