DirectX projekt i Visual Studio 2005

Anvendelse af World koordinater og rotation af figuren

Start med at gennemføre de tre første punkter i Eksempel 1, eller anvend Copy & paste.

  1. World koordinater i 3D
  2. To trekanter
  3. Rotation af objekterne
  4. Forskellig transformation af de enkelte objekter

1. World koordinater i 3D

Det er ofte nemmere at angive koordinater i et regulært cartesisk koordinatsystem. I det følgende vil vi placere en trekant med koordinaterne (100, 100, 10), (400, 600, 400) og (700, 100, 10). Koordinaterne skal desuden angives i 3D - det kræver, at man vælger en anden type til definition af trekantens hjørner. Vi kan f.eks. bruge typen PositionColored. Bemærk at koordinaterne defineres med urets retning.

 	// Global variables for this project
   	private Device device = null; // Rendering device
   	CustomVertex.PositionColored[] vertices = new CustomVertex.PositionColored[3];

Indholdet i metoden CreateVertices erstattes med følgende:

 	public void CreateVertices()
   	{
   		int i = 0;
   		vertices[i++] = new CustomVertex.PositionColored(100f, 100f, 10f, 
			System.Drawing.Color.Red.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(400f, 600f, 400f, 
			System.Drawing.Color.Green.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(700f, 100f, 10f, 
			System.Drawing.Color.Yellow.ToArgb());
   	}

Når en figur defineret i world koordinater skal tegnes, skal man have omdannet world koordinaterne til skærmkoordinater. Dette sker igennem en række transformationer, som device objektet kan udføre. Definitionen af Projection i det følgende definerer vinklen i det perspektiv, som det virtuelle kamera har. Den valgte værdi (pi divideret med 4) anvendes ofte i grafik systemer og svarer til en vinkel på ca. 90 grader.

Med egenskaben View kan man bestemme, hvor kameraet skal være placeret (400, 100, -1500), hvor det skal pege hen (400, 100, 0) og hvad der skal være opad.

Egenskaben Lightning i RenderState sættes til false, fordi trekantens hjørner selv indeholder lyskilder.

 		//Placering af kameraet
   		device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 
   			this.Width / this.Height, 0f, 50f);
   		device.Transform.View = Matrix.LookAtLH(new Vector3(400, 100, -1500), 
   			new Vector3(400, 100, 0), new Vector3(0, 1, 0));
		device.RenderState.Lighting = false;

Endelig skal der foretages en mindre rettelse i Render metoden:

		device.BeginScene();
   		device.VertexFormat = CustomVertex.PositionColored.Format; // Rettet linie
   		device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertices);
   		//End the scene
   		device.EndScene();

Billedet viser resultatet af en testkørsel.

2. To trekanter

Lad os prøve at udvide tegningen med yderligere en trekant. Det kræver en udvidelse af vertices tabellen:

	CustomVertex.PositionColored[] vertices = new CustomVertex.PositionColored[6];

Herefter kan metoden CreateVertices udvides med definition af yderligere en trekant:

 	public void CreateVertices()
   	{
   		int i = 0;
   		vertices[i++] = new CustomVertex.PositionColored(100f, 100f, 10f, 
			System.Drawing.Color.Red.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(400f, 600f, 400f, 
			System.Drawing.Color.Green.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(700f, 100f, 10f, 
			System.Drawing.Color.Yellow.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(0f, -200f, 0f, 
			System.Drawing.Color.Cyan.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(100f, 500f, 100f, 
			System.Drawing.Color.Magenta.ToArgb());
   		vertices[i++] = new CustomVertex.PositionColored(200f, -300f, 100f, 
			System.Drawing.Color.Yellow.ToArgb());
   	}

Afprøv programmet - der skulle meget gerne dukke noget op, der ligner dette billede:

3. Rotation af objekterne

I første omgang defineres en rotation omkring Z-aksen. Først defineres en variabel, som kan bruges til at angive en rotationsvinkel:

 	private float angle = 0F; // Ny linie

I Render metoden indsættes kald af metoder, som forsyner device objektet med en passende transformations matrix:

 		device.BeginScene();
   		device.VertexFormat = CustomVertex.PositionColored.Format;
   		// Rotation om Z-aksen
   		device.Transform.World = Matrix.RotationZ(angle);
   		device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices);
   		//End the scene
   		device.EndScene();
   		device.Present();
   		angle += 0.01f; // Ny linie

Transform.World egenskaben i device objektet sættes lig med en matrix, som bevirker en rotation til den vinkel, der er angivet som parameter (angle). Herunder ses et øjebliksbillede fra en kørsel af programmet. Den hvide prik markerer punktet (0, 0, 0) og dermed Z-aksen, som figuren roterer omkring.

Herefter følger et andet eksempel, hvor vi vil rotere om en anden akse - denne gang om en akse, som er parallel med Y-aksen; men som skærer X-aksen i 400 (midt i den store trekant. Herunder er vist de ændringer, der skal gennemføres i Render metoden. Transformationen bliver nu sammensat af tre transformationer, der multipliceres til en fælles transformationsmatrix. Først flyttes figuren til (0, 0, 0) med en translation (-400, 0, 0), derefter roteres om Y-aksen, og endelig flyttes figuren tilbage hvor den kom fra med endnu en translation (400, 0, 0).

 		device.BeginScene();
   		device.VertexFormat = CustomVertex.PositionColored.Format;
   		// Rotation om en Y-akse, der går igennem (400, 0, 0)
   		device.Transform.World = Matrix.Translation(-400, 0, 0) * 
   			Matrix.RotationY(angle) * Matrix.Translation(400, 0, 0); 
		device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices);
   		//End the scene

Herunder ses et øjebliksbillede fra en kørsel af programmet. Der er tilføjet en hvid prik i punktet (400, 0, 0) for referencens skyld.

4. Forskellig transformation af de enkelte objekter

I denne sidste ændring af dette eksempel, vil vi se, hvordan man kan få de to trekanter til at bevæge sig uafhængigt af hinanden. Det kræver i første omgang opsplitning af vertex tabellen i to separate tabeller - her er nogle nye variabler erklæret:

 	// Global variables for this project
   	private Device device = null; // Rendering device
   	CustomVertex.PositionColored[] vertices1 = new CustomVertex.PositionColored[3]; // Den ene trekant
   	CustomVertex.PositionColored[] vertices2 = new CustomVertex.PositionColored[3]; // Den anden trekant
   	CustomVertex.PositionColored[] vb = new CustomVertex.PositionColored[3]; // Prikken
   	private float angle1 = 0F; // Rotation for den ene trekant
   	private float angle2 = 0F; // Rotation for den anden trekant
Metoden CreateVertices ser herefter således ud:
 	public void CreateVertices()
   	{
		// Første trekant
   		int i = 0;
   		vertices1[i++] = new CustomVertex.PositionColored(100f, 100f, 10f, System.Drawing.Color.Red.ToArgb());
   		vertices1[i++] = new CustomVertex.PositionColored(400f, 600f, 400f, System.Drawing.Color.Green.ToArgb());
   		vertices1[i++] = new CustomVertex.PositionColored(700f, 100f, 10f, System.Drawing.Color.Yellow.ToArgb());
		// Anden trekant
   		i = 0;
   		vertices2[i++] = new CustomVertex.PositionColored(0f, -200f, 0f, System.Drawing.Color.Cyan.ToArgb());
   		vertices2[i++] = new CustomVertex.PositionColored(100f, 500f, 100f, System.Drawing.Color.Magenta.ToArgb());
   		vertices2[i++] = new CustomVertex.PositionColored(200f, -300f, 100f, System.Drawing.Color.Yellow.ToArgb());
		// Prikken
   		i = 0;
   		vb[i++] = new CustomVertex.PositionColored(395f, 0f, 0f, System.Drawing.Color.White.ToArgb());
   		vb[i++] = new CustomVertex.PositionColored(400f, 5f, 0f, System.Drawing.Color.White.ToArgb());
   		vb[i++] = new CustomVertex.PositionColored(405f, 0f, 0f, System.Drawing.Color.White.ToArgb());
   	}

I Render metoden indsættes følgende ændringer:

 		device.BeginScene();
   		device.VertexFormat = CustomVertex.PositionColored.Format;
   		// Rotation om en Y-akse, der går gennem X=400 - første trekant
   		device.Transform.World = Matrix.Translation(-400, 0, 0) *
   			Matrix.RotationY(angle1) * Matrix.Translation(400, 0, 0);
   		device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertices1);
   		// Rotation om Z-aksen - anden trekant
   		device.Transform.World = Matrix.RotationZ(angle2);
   		device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertices2);
		// Prikken
   		device.Transform.World = Matrix.Identity;
   		device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vb);
   		//End the scene
   		device.EndScene();
   		device.Present();
   		angle1 += 0.01f; // Ny linie
   		angle2 -= 0.02f; // Ny linie

Vedhæftede arkiv-fil indeholder koden for dette eksempel.


Sidst opdateret: 12. februar 2007

Index