XNA学习记录_绘制图形

 绘制几何类型

     当绘制3D几何对象时,你首先需要使用primitives(图元)定义它的形状。Primitives (图元)是可以被XNA绘制的最基本的对象,最常被使用的图元是三角形。任何形状,包括圆,如果圆的数量足够多的话,都能用来表示三角形。XNA Framework可以将点,线、三角形作为图元绘制。

      XNA允许你定义这些图元的所有3D坐标。当你调用DrawUserPrimitives方法时,只要你提供正确的观察矩阵和投影矩阵,XNA会自动将这些3D坐标转换为对应的屏幕坐标。

      XNA中有很多现成的结构来储存常见顶点类型,比如:VertexPositionColor, VertexPositionNormalTexture,VertexPositionTexture等结构。你也可以定义新的顶点类型。 目前,简单的VertexPositionColor类型就能满足需要,正如它的名字所示,这种顶点格式包含顶点的位置和颜色信息。位置是包含三个分量的矢量,定义顶点在3D空间中的坐标。XNA有自己的颜色系统,所以不需要使用System.Draw中的Color类。 

     要将3D坐标转换为屏幕上的像素位置,XNA需要知道相机的位置(存储在观察矩阵中)和关于相机镜头
的某些细节(存储在投影矩阵中)。相机系统
ExpandedBlockStart.gif 代码
using  System;
using  System.Collections.Generic;
using  Microsoft.Xna.Framework;
using  Microsoft.Xna.Framework.Audio;
using  Microsoft.Xna.Framework.Content;
using  Microsoft.Xna.Framework.Graphics;
using  Microsoft.Xna.Framework.Input;
using  Microsoft.Xna.Framework.Storage;

namespace  xnaDraw_test
{
    
class  QuakeCamera
    {
        Matrix viewMatrix;
        Matrix projectionMatrix;
        Viewport viewPort;

        
float  leftrightRot;
        
float  updownRot;
        
const   float  rotationSpeed  =   0.005f ;
        Vector3 cameraPosition;
        MouseState originalMouseState;

        
public  QuakeCamera(Viewport viewPort)
            :  this (viewPort,  new  Vector3( 0 1 15 ),  0 0 )
        {
            
// calls the constructor below with default startingPos and rotation values
        }

        
public  QuakeCamera(Viewport viewPort, Vector3 startingPos,  float  lrRot,  float  udRot)
        {
            
this .leftrightRot  =  lrRot;
            
this .updownRot  =  udRot;
            
this .cameraPosition  =  startingPos;
            
this .viewPort  =  viewPort;

            
float  viewAngle  =  MathHelper.PiOver4;
            
float  nearPlane  =   0.5f ;
            
float  farPlane  =   1000.0f ;
            projectionMatrix  =  Matrix.CreatePerspectiveFieldOfView(viewAngle, viewPort.AspectRatio, nearPlane, farPlane);

            UpdateViewMatrix();
#if  XBOX

#else
            Mouse.SetPosition(viewPort.Width  /   2 , viewPort.Height  /   2 );
            originalMouseState  =  Mouse.GetState();
#endif
        }

        
public   void  Update(MouseState currentMouseState, KeyboardState keyState, GamePadState gamePadState)
        {

            
if  (currentMouseState  !=  originalMouseState)
            {
                
float  xDifference  =  currentMouseState.X  -  originalMouseState.X;
                
float  yDifference  =  currentMouseState.Y  -  originalMouseState.Y;
                leftrightRot  -=  rotationSpeed  *  xDifference;
                updownRot  -=  rotationSpeed  *  yDifference;
                Mouse.SetPosition(viewPort.Width  /   2 , viewPort.Height  /   2 );
                UpdateViewMatrix();
            }

            
if  (keyState.IsKeyDown(Keys.Up)  ||  keyState.IsKeyDown(Keys.W))       // Forward
                AddToCameraPosition( new  Vector3( 0 0 - 1 ));
            
if  (keyState.IsKeyDown(Keys.Down)  ||  keyState.IsKeyDown(Keys.S))     // Backward
                AddToCameraPosition( new  Vector3( 0 0 1 ));
            
if  (keyState.IsKeyDown(Keys.Right)  ||  keyState.IsKeyDown(Keys.D))    // Right
                AddToCameraPosition( new  Vector3( 1 0 0 ));
            
if  (keyState.IsKeyDown(Keys.Left)  ||  keyState.IsKeyDown(Keys.A))     // Left
                AddToCameraPosition( new  Vector3( - 1 0 0 ));
            
if  (keyState.IsKeyDown(Keys.Q))                                      // Up
                AddToCameraPosition( new  Vector3( 0 1 0 ));
            
if  (keyState.IsKeyDown(Keys.Z))                                      // Down
                AddToCameraPosition( new  Vector3( 0 - 1 0 ));

        }

        
private   void  AddToCameraPosition(Vector3 vectorToAdd)
        {
            
float  moveSpeed  =   0.5f ;
            Matrix cameraRotation  =  Matrix.CreateRotationX(updownRot)  *  Matrix.CreateRotationY(leftrightRot);
            Vector3 rotatedVector  =  Vector3.Transform(vectorToAdd, cameraRotation);
            cameraPosition  +=  moveSpeed  *  rotatedVector;
            UpdateViewMatrix();
        }

        
private   void  UpdateViewMatrix()
        {
            Matrix cameraRotation  =  Matrix.CreateRotationX(updownRot)  *  Matrix.CreateRotationY(leftrightRot);

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

            Vector3 cameraRotatedTarget  =  Vector3.Transform(cameraOriginalTarget, cameraRotation);
            Vector3 cameraFinalTarget  =  cameraPosition  +  cameraRotatedTarget;

            Vector3 cameraRotatedUpVector  =  Vector3.Transform(cameraOriginalUpVector, cameraRotation);
            Vector3 cameraFinalUpVector  =  cameraPosition  +  cameraRotatedUpVector;

            viewMatrix  =  Matrix.CreateLookAt(cameraPosition, cameraFinalTarget, cameraRotatedUpVector);
        }

        
public   float  UpDownRot
        {
            
get  {  return  updownRot; }
            
set  { updownRot  =  value; }
        }

        
public   float  LeftRightRot
        {
            
get  {  return  leftrightRot; }
            
set  { leftrightRot  =  value; }
        }

        
public  Matrix ProjectionMatrix
        {
            
get  {  return  projectionMatrix; }
        }

        
public  Matrix ViewMatrix
        {
            
get  {  return  viewMatrix; }
        }
        
public  Vector3 Position
        {
            
get  {  return  cameraPosition; }
            
set
            {
                cameraPosition  =  value;
                UpdateViewMatrix();
            }
        }
        
public  Vector3 TargetPosition
        {
            
get
            {
                Matrix cameraRotation  =  Matrix.CreateRotationX(updownRot)  *  Matrix.CreateRotationY(leftrightRot);
                Vector3 cameraOriginalTarget  =   new  Vector3( 0 0 - 1 );
                Vector3 cameraRotatedTarget  =  Vector3.Transform(cameraOriginalTarget, cameraRotation);
                Vector3 cameraFinalTarget  =  cameraPosition  +  cameraRotatedTarget;
                
return  cameraFinalTarget;
            }
        }
        
public  Vector3 Forward
        {
            
get
            {
                Matrix cameraRotation  =  Matrix.CreateRotationX(updownRot)  *  Matrix.CreateRotationY(leftrightRot);
                Vector3 cameraForward  =   new  Vector3( 0 0 - 1 );
                Vector3 cameraRotatedForward  =  Vector3.Transform(cameraForward, cameraRotation);
                
return  cameraRotatedForward;
            }
        }
        
public  Vector3 SideVector
        {
            
get
            {
                Matrix cameraRotation  =  Matrix.CreateRotationX(updownRot)  *  Matrix.CreateRotationY(leftrightRot);
                Vector3 cameraOriginalSide  =   new  Vector3( 1 0 0 );
                Vector3 cameraRotatedSide  =  Vector3.Transform(cameraOriginalSide, cameraRotation);
                
return  cameraRotatedSide;
            }
        }
        
public  Vector3 UpVector
        {
            
get
            {
                Matrix cameraRotation  =  Matrix.CreateRotationX(updownRot)  *  Matrix.CreateRotationY(leftrightRot);
                Vector3 cameraOriginalUp  =   new  Vector3( 0 1 0 );
                Vector3 cameraRotatedUp  =  Vector3.Transform(cameraOriginalUp, cameraRotation);
                
return  cameraRotatedUp;
            }
        }
    }
}

自定义顶点类型

     当XNA中的预定义顶点类型不能满足要求时,可以手动创建结构来保存顶点数据。假设我们希望顶点中包含位置,纹理坐标,法线和切线信息,把这个结构称为VertexPosTexNorTan,它只是一个简单的数据集合:

  struct  VertexPosTexNorTan

    {               
        
public  Vector3 Position;
        
public  Vector3 Normal;
        
public  Vector2 UV;     
        
public  Vector3 Tangent;
    }
    对于创建VertexDeclaration来说就稍微麻烦一点,它的构造函数需要一个VertexElement类型的数组,需要先构造出这个数组:
ExpandedBlockStart.gif 代码
VertexElement[] element  =   new  VertexElement[]

    {
        
new  VertexElement( 0 , 0 ,VertexElementFormat.Vector3,VertexElementMethod.Default,VertexElementUsage.Position, 0 ),

        
new  VertexElement( 0 , 12 ,VertexElementFormat.Vector3,VertexElementMethod.Default,VertexElementUsage.Normal, 0 ),

        
new  VertexElement( 0 , 24 ,VertexElementFormat.Vector2,VertexElementMethod.Default,VertexElementUsage.TextureCoordinate, 0 ),

        
new  VertexElement( 0 , 32 ,VertexElementFormat.Vector3,VertexElementMethod.Default,VertexElementUsage.Tangent, 0 ),         

 };
VertexElement里每个元素对应VertexPosTexNorTan中的一个成员。第一个参数表示关联到顶点分量的数据流索引。大多数情况下一条数据流就可以了,索引0表示第一条流。第二个参数是成员在顶点结构中的偏移值。Positon是结构中的第一个元素,因此偏移为0。Position是Vector3类型的变量,所以对第二个成员Normal来说,它在结构中的偏移值为12。这里的偏移值都以Byte为单位。下一个参数是VertexElementFormat类型的枚举,用来表示每个成员的数据类型。接下来的VertexElementMethod枚举表示在图形流水线中的图元镶嵌光栅化阶段如何对当前变量进行插值,一般使用默认值就可以。VertexElementUsage是一个比较重要的参数,指定当前成员的用途。比如,定义Position变量在程序中表示顶点的位置。最后一个变量也和VertexElementUsage枚举有关。有时,一个顶点可能会有一个以上的同用途元素,比如,有两组纹理坐标,为了区分两组不同的纹理坐标,必须指定一个索引值。这里,并没有重复用途的元素,所用使用0表示它是该用途的第一组数据就可以。

        有了VertexElement数据,创建VertexPosTexNorTan顶点相应的VertexDeclaration就很简单了:

decl  =   new  VertexDeclaration(graphicsDevice, element);



转载于:https://www.cnblogs.com/alex_85/archive/2010/03/01/1675695.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值