XNA-畫出空間中的點、線、面(一)

摘要:畫出空間中的點、線、面(一)

空間中畫圖最基本的就是點,這裡的點就是所謂的頂點,頂點可以包含很多資訊,
如基本的座標、顏色、法線、切線等,甚至你可以自定需求。
但對於初學的我來說,直接用xna內建的就可以了。

宣告頂點的形態:
 

VertexDeclaration (
         GraphicsDevice graphicsDevice,
         VertexElement[] elements
)

參數:
graphicsDevice
繪圖裝置
VertexElement
頂點資料元素

而xna內建的頂點資料元素有VertexPositionColor、VertexPositionColorTexture、VertexPositionNormalTexture、
VertexPositionTexture這幾種,都是Structure。在這裡我們先用VertexPositionNormalTexture就好。
要取出頂點資料直接用VertexPositionNormalTexture.VertexElements即可。

決定了頂點型態,我們就可以將要畫的點設定好,每個點都是一個VertexPositionNormalTexture結構。

VertexPositionNormalTexture:

VertexPositionNormalTexture (
         Vector3 position,
         Vector3 normal,
         Vector2 textureCoordinate
)

參數:
position
點座標
normal
法向量
textureCoordinate
紋理座標

接著還有一個很重要的類別-BasicEffect,他提供我們基本的3D繪圖效果,包括燈光、材質、顏色等,將由他來計算出成像結果。

BasicEffect:
 

BasicEffect (
         GraphicsDevice device,
         EffectPool effectPool
)

參數:
device
繪圖裝置
effectPool
Specifies a pool of resources to share between effects

他有很多成員可以設定,在這裡只要設定DiffuseColor就好,這表示基本的顏色。
若我們要設定光線,則我們的頂點要有法向量屬性、
若我們要設定顏色,則我們的頂點要有顏色屬性、
若我們要設定紋理,則我們的頂點要有紋理屬性。
同時我們也需要將世界、觀察、投影矩陣分別設定給BasicEffect的成員World、View 和Projection。

設定了這麼多東西,我們終於可以開始畫點了!!(真麻煩)


畫點的函式:
 

void DrawUserPrimitives (
         PrimitiveType primitiveType,
         T[] vertexData,
         int vertexOffset,
         int primitiveCount
)

參數:
primitiveType
繪圖類型
vertexData
頂點陣列
vertexOffset
開始位置
primitiveCount
畫幾個點

繪圖類型有五種:LineList、LineStrip、PointList、TriangleFan、TriangleList、TriangleStrip。
畫點只能用PointList,另外四種會在畫線的地方介紹。

開一個新的xna專案,修改(加入)以下程式碼:

 

Matrix WorldMatrix;
Matrix ViewMatrix;
Matrix ProjectionMatrix;
VertexDeclaration vertexDeclaration;
BasicEffect basicEffect;
VertexPositionNormalTexture[] pointList;
       
protected override void Initialize(){
    // 設定三種矩陣
    WorldMatrix = Matrix.CreateTranslation(Vector3.Zero);
    ViewMatrix = Matrix.CreateLookAt(new Vector3(7, 7, 10), new Vector3(7, 7, 0), Vector3.Up);
    ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
        MathHelper.ToRadians(120),
        (float)graphics.GraphicsDevice.Viewport.Width /
        (float)graphics.GraphicsDevice.Viewport.Height,
        1.0f, 100.0f
        );

    base.Initialize();
}

protected override void LoadContent(){
    // 設定頂點型態
    vertexDeclaration = new VertexDeclaration(
        graphics.GraphicsDevice,
        VertexPositionNormalTexture.VertexElements
        );
    // 設定BasicEffect
    basicEffect = new BasicEffect(graphics.GraphicsDevice, null);
    basicEffect.DiffuseColor = new Vector3(1.0f, 1.0f, 1.0f);
   
    basicEffect.World = WorldMatrix;
    basicEffect.View = ViewMatrix;
    basicEffect.Projection = ProjectionMatrix;

    // 設定頂點資訊
    pointList = new VertexPositionNormalTexture[60];
    for (int i = 0; i < 20; i++) {
        pointList[i] = new VertexPositionNormalTexture(new Vector3(i, 0, 0), Vector3.Forward, Vector2.One);
        pointList[i + 20] = new VertexPositionNormalTexture(new Vector3(0, i, 0), Vector3.Forward, Vector2.One);
        pointList[i + 40] = new VertexPositionNormalTexture(new Vector3(0, 0, i), Vector3.Forward, Vector2.One);
    }

    // 設定點的大小
    graphics.GraphicsDevice.RenderState.PointSize = 3;
}

protected override void Draw(GameTime gameTime){
    graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    // 將頂點型態告訴繪圖裝置
    graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;

    // 開始畫圖
    basicEffect.Begin();

    foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) {
        pass.Begin();

        graphics.GraphicsDevice.DrawUserPrimitives(
            PrimitiveType.PointList,
            pointList,
            0,
            pointList.Length
            );

        pass.End();
    }

    basicEffect.End();

    base.Draw(gameTime);
}

此例是在X、Y、Z軸上畫點。