上節內容中,我們已經有了一個三維的空間,本節中我們就來結識3D中最基本的圖元——三角形
在3D開發中,三角形佔有重要的地位。它是3D模型的最小基元,無論多複雜的3D模型,最終都可以表示成若干個三角形的組合。圖形處理晶片也對三角形渲染進行了硬體支援。可見三角形雖然簡單,但在3D開發中的重要性。下面我們就從這個最簡單的三角形開始。
沿用上節我們建好的XNA項目,在VS2010中開啟該項目。開啟Game1.cs檔案,我們來修改Game1類。
要想構建三角形,我們首先想到的是需要三個頂點的座標。在XNA中提供了VertexPositionColor類型,用於表示一個空間中的頂點的位置和顏色資訊,在此我們只用到位置資訊,顏色會在後文中使用。
為Game1類添加用於儲存三角形頂點資訊成員變數:VertexPositionColor[] triangle;
然後在LoadContent()方法中定義三個頂點:
triangle = newVertexPositionColor[]{
new VertexPositionColor(newVector3(0, 1, 0), Color.Red),
new VertexPositionColor(newVector3(1, -1, 0), Color.Green),
new VertexPositionColor(newVector3(-1,-1, 0), Color.Blue)
};
這三個頂點座標正好是一個三角形。然後在Draw()方法中將其繪製輸出:
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip,triangle, 0, 1);
DrawUserPrimitives()方法用於繪製圖元,方法的原型如下:
public voidDrawUserPrimitives<T>(
PrimitiveTypeprimitiveType, //圖元類型
T[]vertexData, //頂點資料
intvertexOffset, //讀頂點資料的起始位置
intprimitiveCount //圖元個數
)
其中PrimitiveType用於描述圖元類型,在Windows Phone中有四個取值,含義是:
- TriangleList:三角形列表
- TriangleStrip:三角形連環
- LineList:線段列表
- LineStrip:線段帶
例如同樣的6個頂點座標,當使用TriangleList時得到的圖形如下(註:圖片來源於網路):
當使用TriangleStrip時得到的圖形如下(註:圖片來源於網路):
運行程式,在模擬器中將看到如下結果:
雖然很簡陋,不過這確實是在3D空間中繪製的,如果有興趣,不妨修改一下攝像機的位置或者三角形的座標等參數,也可以繪製其他圖元,體會運行結果的變化。下節中我們將進行三維物體的運動處理。
附本節Game1類的完整源碼:
public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; Camera camera; Matrix world = Matrix.Identity; BasicEffect basicEffect; VertexPositionColor[] triangle; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; // Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); // Extend battery life under lock. InactiveSleepTime = TimeSpan.FromSeconds(1); graphics.IsFullScreen = true; } /// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } /// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { camera = new Camera(this, new Vector3(0, 0, 5), Vector3.Zero, Vector3.Up, MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 1.0f, 50.0f); Components.Add(camera); basicEffect = new BasicEffect(GraphicsDevice); triangle = new VertexPositionColor[]{ new VertexPositionColor(new Vector3(0, 1, 0), Color.Red), new VertexPositionColor(new Vector3(1, -1, 0), Color.Green), new VertexPositionColor(new Vector3(-1,-1, 0), Color.Blue) }; } /// <summary> /// UnloadContent will be called once per game and is the place to unload /// all content. /// </summary> protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } /// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here base.Update(gameTime); } /// <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); basicEffect.World = world; basicEffect.View = camera.view; basicEffect.Projection = camera.projection; foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, triangle, 0, 1); } base.Draw(gameTime); } }
——歡迎轉載,請註明出處 http://blog.csdn.net/caowenbin ——