C#Direct3D程式設計3D世界中的三角形(轉)

post0發表於2007-08-12
C#Direct3D程式設計3D世界中的三角形(轉)[@more@]

  那什麼是真正的3D世界呢?或者說Direct3D的3D模型是什麼樣的呢?

  

  Direct3D的模型由World 空間,View 空間和光源組成。World空間就像我們現實生活中的空間一樣,我們可以把物體放在這個空間的任何地方。但僅僅這樣是不夠的。因為現實中,我們是透過眼睛來看事物的,存在的東西不一定我們可以看得到,太遠的東西看不到,被擋住的東西看不到,太近的東西也看不到,在我們視角以外的東西一樣看不到。在Direct3D中用camera來模擬我們的眼睛。

  

  另外還有一個重要概念,transform,變換。在world空間中,我們可以把物體移動,旋轉,這需要透過變換來實現。透過camera來決定我們最終能看到的那些東西時也是經過變換。在Direct3D中,變換是透過4x4的矩陣來實現的。

  

  不是搞演算法的人沒有必要了解矩陣的具體內容,可以透過Maxtrix中的靜態函式來建立矩陣:

  

  Matrix.RotationX(), Matrix.RotationY(), Matrix,RotationZ(),建立分別圍繞X,Y,Z軸旋轉的矩陣。

  

  Matrix.Translation()用來建立移動物體的矩陣。

  

  而與camera相關的變換有兩個,View Transform,和Projection Transform.View Transform用來定義camera的資訊。而Projection Transform用來定義我們的可見範圍,

  

  也就是說那些物體會被繪製到螢幕上去。

  

  另外一個很重要的概念就是光源,在真實世界中,沒有光的情況下我們是看不到東西的,即使他存在。而且我們看到的物體的顏色/亮度,與光源的顏色/亮度,與他本身的材質/顏色都有關係。在Direct3D中也是如此,一旦一個物體在我們的可視範圍內,並且沒有被遮擋住,那麼他能否可見,以及什麼顏色/亮度,就由光源,物體的材質來決定了。

  

  下面就開始我們的例子。首先把我們的程式碼中的頂點格式,改成PositionColored格式。注意座標哦,這裡的座標可不是螢幕座標系了,而是World座標系,是左手笛卡爾3D座標系。第一步的程式碼如下:

  

  #region Using directives

  

  using System;

  

  using System.Collections.Generic;

  

  using System.ComponentModel;

  

  using System.Data;

  

  using System.Drawing;

  

  using System.Windows.Forms;

  

  using Microsoft.DirectX;

  

  using Microsoft.DirectX.Direct3D;

  

  #endregion

  

  namespace Exam2

  

  {

  

  partial class Form1 : Form

  

  {

  

  private Device device = null;

  

  public Form1()

  

  {

  

  InitializeComponent();

  

  this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true );

  

  }

  

  public void InitializeGraphics()

  

  {

  

  PresentParameters para = new PresentParameters();

  

  para.Windowed = true;

  

  para.SwapEffect = SwapEffect.Discard;

  

  device = new Device( 0, DeviceType.Hardware, this, CreateFlags.HardwareVertexProcessing, para );

  

  }

  

  private void Form1_Paint(object sender, PaintEventArgs e)

  

  {

  

  device.Clear( ClearFlags.Target, Color.Blue, 0.0f, 0 );

  

  CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];

  

  verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f);

  

  verts[0].Color = Color.Aqua.ToArgb();

  

  verts[1].Position = new Vector3(-1.0f, -1.0f, 1.0f);

  

  verts[1].Color = Color.Black.ToArgb();

  

  verts[2].Position = new Vector3(1.0f, -1.0f, 1.0f);

  

  verts[2].Color = Color.Purple.ToArgb();

  

  device.BeginScene();

  

  device.VertexFormat = CustomVertex.PositionColored.Format;

  

  device.DrawUserPrimitives( PrimitiveType.TriangleList, 1, verts );

  

  device.EndScene();

  

  device.Present();

  

  this.Invalidate();

  

  }

  

  }

  

  }

  

  執行以下看看,呵呵,什麼也看不到!就是藍色背景的視窗,誰動了我的漂亮的三角形阿?

  

  原因就在我們上面講到的內容裡。我們這裡使用的PositonColored頂點格式,是未經過變換的,沒有任何檢視變換的資訊,Direct3D就認為他們都不可見了。所以……

  

  我們接下來,就要把我們的漂亮的三角形找回來:加入camera的資訊。

  

  新的程式碼如下:

  

  #region Using directives

  

  using System;

  

  using System.Collections.Generic;

  

  using System.ComponentModel;

  

  using System.Data;

  

  using System.Drawing;

  

  using System.Windows.Forms;

  

  using Microsoft.DirectX;

  

  using Microsoft.DirectX.Direct3D;

  

  #endregion

  

  namespace Exam2

  

  {

  

  partial class Form1 : Form

  

  {

  

  private Device device = null;

  

  public Form1()

  

  {

  

  InitializeComponent();

  

  this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true );

  

  }

  

  public void InitializeGraphics()

  

  {

  

  PresentParameters para = new PresentParameters();

  

  para.Windowed = true;

  

  para.SwapEffect = SwapEffect.Discard;

  

  device = new Device( 0, DeviceType.Hardware, this, CreateFlags.HardwareVertexProcessing, para );

  

  }

  

  public void SetupCamera()

  

  {

  

  device.Transform.Projection = Matrix.PerspectiveFovLH( ( float ) Math.PI / 4, this.Width / this.Height, 1.0f, 100.0f );

  

  device.Transform.View = Matrix.LookAtLH( new Vector3( 0, 0, 5.0f ), new Vector3(), new Vector3( 0, 1, 0 ) );

  

  //      device.RenderState.Lighting = false;

  

  }

  

  private void Form1_Paint(object sender, PaintEventArgs e)

  

  {

  

  device.Clear( ClearFlags.Target, Color.Blue, 0.0f, 0 );

  

  SetupCamera();

  

  CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];

  

  verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f);

  

  verts[0].Color = Color.Aqua.ToArgb();

  

  verts[1].Position = new Vector3(-1.0f, -1.0f, 1.0f);

  

  verts[1].Color = Color.Black.ToArgb();

  

  verts[2].Position = new Vector3(1.0f, -1.0f, 1.0f);

  

  verts[2].Color = Color.Purple.ToArgb();

  

  device.BeginScene();

  

  device.VertexFormat = CustomVertex.PositionColored.Format;

  

  device.DrawUserPrimitives( PrimitiveType.TriangleList, 1, verts );

  

  device.EndScene();

  

  device.Present();

  

  this.Invalidate();

  

  }

  

  }

  

  }

  

  Matrix.LookAtLH()函式就是設定View Transform的資訊(Camera的資訊)。第一引數,是camera在world 空間的位置;第二個引數,camera在對著那一點(不懂?就好像我們的眼睛,只能盯著一點看,其他的是用餘光來看的),第三個參數列示那個是“上”(也就是我們腦袋指向的方向,我們倒立看東西時,上就是下,我們躺著看東西時,上就是左/右。場外音:你演雜技呢)。程式碼裡的函式,把camera放在了Z軸上,看著座標原點(? 你怎麼老看xx的地方……,沒辦法,不良少年啊),上方向是Y軸。

  

  Matrix.PerspectiveFovLH()函式設定投射變換。第一個引數,視角;第二個引數,可視區的長寬比(我們可視區的介面是矩型,就像camera的取景器),第三個引數是我們最近可以看到的地方,第四個引數,我們最遠可以看到的地方。這樣就描述出來一個四稜錐拄體。所有在這個空間的物體都是可見的

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-952143/,如需轉載,請註明出處,否則將追究法律責任。

相關文章