mytudousi

.Net,GIS,3D

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  41 随笔 :: 0 文章 :: 32 评论 :: 0 引用

公告

例如我们要想保持我们正在看东西的一个状态,例如看一个茶杯,需要量化到哪些参数,才能保持该状态?最容易想到的就是位置,就是你的头的位置不能变,例如本来你坐在椅子上看这个杯子,又站起来看,肯定呈现在你眼睛里面的效果是不一样的。如果你向左或向右歪一下头呢,头的位置即使保持不变,但头歪了,看到的杯子也是歪的。你可能会说,我看着还是正的,但这是我们在日常生活中养成的一种习惯,杯子正正的放在桌子上。但在你的眼睛里呈现的杯子已经是歪的了。头如果上下左右都旋转的话,可能连杯子都看不到了。如果保持这些参数不动的话,是不是你除了把眼睛闭上,看到的都是一幅景象了?

从上面的生活小例子,我们可以看出,影响人看一个东西呈现的状态有四个因素,第一,是人的头的位置;第二,人的头左右旋转;第三,人的头上下旋转;第四,左右歪头。

如果我们更专业一些说的话,以XNA的右手坐标系为例子,相机在Z轴的正方向的某一点看远点。影响相机呈现的景象的参数分别是相机的位置,绕Z轴方向的夹角,绕X轴方向的夹角和绕Y轴方向的夹角。由此我们可以说一个相机可以由这四个参数定义。

 

XNA中是怎么确定相机的呢?用的是上个方法的改进方法,位置信息没有变,把沿Z轴旋转的角度变成UP向量,把沿X轴和Y轴方向变为Target,称为观察目标,是一个点。设置观察目标后,相当于在X轴和Y轴方向上的旋转角度就已经确定。我们还是还原到眼睛的例子。我们看那个杯子,一直盯杯子的某一点,这个你的头就不能上下左右转了。而新增加的UP向量,就是确定头歪的角度,就是头顶朝的方向。这些信息一旦确定,是不是你的头再也不能动了?

所以在XNA中,由一下三个参数确定相机的状态,位置(Position)、观察目标(Target)、UP向量(UP)。

理解完这些之后,我们还会发现有一些问题,例如你眼睛离那个杯子只有一厘米的时候,你还看时什么感觉,头昏脑胀,估计可以吐掉。还有很远很远的地方你能看到吗?在XNA中,相机也一样,如果离相机很近的东西都要能看见的话,很小的一个点,都会把整个相机遮住,让你不知道自己在什么地方。同样无穷远得到东西也能看见,首先是不真实,第二,系统的性能也会有问题的。事实上,人眼睛看东西时,上下左右都要有界限的,不可能360°都能看到。这就出来一个新的东西叫视椎体。就是设置你可见的范围。同样XNA中定义相机也要有这样的一个东西。

在现实世界中,人的眼睛看世界,看到的范围应该是一个圆锥体,但我们平常用的计算机都是四方屏幕的,为了正常显示,在XNA中,视锥体是一个方形椎体。示意图如下。

 

到此为止,相机怎么定义已经说完了,四个参数,相机的位置、观察对象、向上向量、视锥体。

下面我们就用代码来说明怎么创建一个相机。

在写正式代码之前,我们先来了解一下在XNA中定义的向量和矩阵类。向量类Vector3,矩阵类Matrix。向量可以表示位置、方向、带方向的值等。而矩阵就是本质是对运动的描述。一个模型从一个状态变成另一个状态就可以用矩阵表示。

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// TODO: Add your drawing code here

//---开始相机的定义
//声明投影矩阵
float viewAngle = MathHelper.PiOver4;
float aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
float nearPlane = 0.5f;
float farPlane = 100.0f;
Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearPlane, farPlane);

//声明视角矩阵
Vector3 camPosition = new Vector3(10, 10, -10);
Vector3 camTarget = new Vector3(0, 0, 0);
Vector3 camUpVector = new Vector3(0, 1, 0);
Matrix viewMatrix = Matrix.CreateLookAt(camPosition, camTarget, camUpVector);
//---结束相机的定义

//使用两个矩阵渲染示例代码
Model _model=this.Content.Load<Model>("Cube");
foreach (ModelMesh myModelMesh in _model.Meshes)
{
Matrix myWorld = myModelMesh.ParentBone.Transform * Matrix.Identity;
foreach (ModelMeshPart myModelMeshPart in myModelMesh.MeshParts)
{
IEffectMatrices myEffect = myModelMeshPart.Effect as IEffectMatrices;
myEffect.World = myWorld;
myEffect.View = viewMatrix;
myEffect.Projection =projectionMatrix;
myModelMeshPart.Effect.CurrentTechnique.Passes[0].Apply();
this.GraphicsDevice.Indices = myModelMeshPart.IndexBuffer;
this.GraphicsDevice.SetVertexBuffer(myModelMeshPart.VertexBuffer);
this.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList
, myModelMeshPart.VertexOffset, 0, myModelMeshPart.NumVertices
, myModelMeshPart.StartIndex, myModelMeshPart.PrimitiveCount);
}
}

base.Draw(gameTime);
}


 

posted on 2011-12-14 22:23 mytudousi 阅读(99) 评论(0) 编辑 收藏