摘要: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畫一個三角形以此類推,看你要畫幾組,這樣畫出扇形就很容易了。