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

摘要:XNA-畫出空間中的點、線、面(二)

點畫完了就來試試看畫線吧!!
大家都知道兩點決定一條線,在這我們沿用前一篇的點,在這60點中選幾個來連連看吧!
原本的點是沿著X、Y、Z軸畫的,那這裡就將每個軸的頭尾連起來。

畫線的函式是

void DrawUserIndexedPrimitives(
         PrimitiveType primitiveType,
         T[] vertexData,
         int vertexOffset,
         int numVertices,
         short[] indexData,
         int indexOffset,
         int primitiveCount
)
參數:
primitiveType
畫圖型態
vertexData
點的陣列
vertexOffset
點開始位置
numVertices
畫幾個點
indexData
索引陣列
indexOffset
索引起點
primitiveCount
索引有幾組

其中有個新東西,就是索引陣列。
在DX畫線可以不用索引陣列,直接標示點座標,這樣會依據第一點和第二點畫一條線、第三點和第四點畫一條線,以此類推。
但是往往我們都是要畫連續的線,如此點座標就必須儲存成{第一點,第二點,第二點,第三點,第三點,第四點}
這樣才會一直接連著畫線,而頂點卻是一個struct,這樣重複儲存是非常浪費的(要節能省碳),
所以才會設計出索引陣列,此陣列只需要記錄點的索引值,點少可以用short,不然就用int,如此在複雜的3D圖中可以省下不少的記憶空間。
若我們的點座標為{第一點,第二點,第三點,第四點},而我們想讓每個點都相連,索引陣列就設為{1,2,2,3,3,4}。此時繪圖型態要設為PrimitiveType.LineList。

修改(新增)以下程式碼


int[] lineListIndices;

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);
    }
    // 索引陣列
    lineListIndices = new int[] { 0, 19, 20, 39, 40, 59 };

    // 設定點的大小
    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
            );
        graphics.GraphicsDevice.DrawUserIndexedPrimitives(
            PrimitiveType.LineList,
            pointList,
            0,
            pointList.Length,
            lineListIndices,
            0,
            lineListIndices.Length / 2
            );

        pass.End();
    }

    basicEffect.End();

    base.Draw(gameTime);
}

另外一種繪圖型態是LineStrip,他會將索引連結起來,第一條線是索引一和索引二兩點的連線、第二條線是索引二和索引三兩點的連線,以此類推。
所以若是要畫出下圖的連線

LineList的索引為 {1,2,2,3,3,4,4,5,5,6}
LineStrip的索引為{1,2,3,4,5,6}

接著就來試試看畫平面!
電腦3D圖學最基本的平面是三角形,也就是說電腦其實只會畫三角型平面,其他的奇形怪狀都是用三角形去組合起來的。
畫三角形的方式和畫線其實差不多,

修改(新增)以下程式碼


int[] TriangleIndeices = new int[9] { 0, 39, 19, 0, 39, 45, 0, 19, 45 };

protected override void Draw(GameTime gameTime){
    graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    // 將頂點型態告訴繪圖裝置
    graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;
    // 挑選形態
    graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;
    
    // 開始畫圖
    basicEffect.Begin();

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

        graphics.GraphicsDevice.DrawUserPrimitives(
            PrimitiveType.PointList,
            pointList,
            0,
            pointList.Length
            );
        graphics.GraphicsDevice.DrawUserIndexedPrimitives(
            PrimitiveType.TriangleList,
            pointList,
            0,
            pointList.Length,
            TriangleIndeices,
            0,
            3
            );


        pass.End();
    }

    basicEffect.End();

    base.Draw(gameTime);
}

這樣可以畫出三個白色的三角形,這裡有個沒見過的東西CullMode,要設定這個是因為預設畫三角形的三個點,
必須是順時針排列才會畫出來,但我們只是為了練習畫三角形,就不用計較這麼多了,所以把CullMode設定為None,
如此不管逆時針或順時針都會畫出來。

另外,畫三角形也和畫線一樣有不同的繪圖型態,先來說TriangleStrip,
他會把索引指向的1,2,3點畫成三角形、2,3,4點畫成三角形、3,4,5點化成三角形,這應該很好理解。
而另一種就比較特別了,TriangleFan是用來畫扇形的,他會以指定的第一點為基準,
1,2,3畫一個三角形、1,3,4畫一個三角形、1,4,5畫一個三角形以此類推,看你要畫幾組,這樣畫出扇形就很容易了。