static CustomVertex.PositionColored[] v = new CustomVertex.PositionColored[3]; //Memory space for 3 vertices each containing x,y,z plus a RGB-color. The keyword static is just needed in version 1 where v is directly used by the renderer inside the static OnTimer-function. All higher versions of the program use vertexBuffer instead of v and do not need this keyword anymore.

Timer myTimer = new Timer(); //This Timer sends messages at fixed time intervals to Form1, that trigger Form1 to execute its OnTimer(..) method.

static Random r = new Random(); //Class to generate random numbers. Its method Random.NextDouble() furnishes an arbitrary value between 0.0 and 1.0. We use it in the Constructor and in the Timer event handler to give each triangle its individual random position and individual rotation.

Constructor public Form1() inside public class Form1

Text = "D3DTriangleAnimation"; //Title in the blue title bar of Form1.

myTimer.Tick += new EventHandler( OnTimer ); //Obligatory definition of an event handler for the Timer event.myTimer.Interval = 1; //1 millisecond intervals means: as fast as possible. The operating system will raise as many events as possible.

//Whenever the window changes we have to initialize Direct3D from scratch.

myTimer.Stop(); //Stop the timer during initialization. It may disturb DirectX-initialization.

try //All the following things crash when DirectX is not properly installed. In this case the try-catch clause allows a decent suicide.

//Get information from the operating system about its current graphics properties.PresentParameters presentParams = new PresentParameters(); //This structure is an obligatory parameter for creating a new Device. It carries several flags such as Windowed = true; and SwapEffect.Discard; = status flags controlling the behavior of the Device.//we have to set two flagspresentParams.Windowed = true; //We want a program in a window not a full screen program.presentParams.SwapEffect = SwapEffect.Discard; //This flag tells the graphic board how to handle the backbuffer(s) after front-back flipping. Many graphic boards need this flag, but I do not really know why.
See: http://msdn.microsoft.com/library/.../D3DSWAPEFFECT.asp

//create a new D3D-device that serves as canvasif ( device != null ) device.Dispose(); //Free the old canvas if any.device = new Device( 0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams );
//1. parameter = 0 = default device. (The computer can have differnt devices f.i. two graphic boards.)
//2. parameter = DeviceType.Hardware allows rasterization by the graphic board (HAL=first choice), software (HEL) or mixed.
//3. parameter = this means a pointer to a System.Windows.Forms.Control being the target of any graphical output.
//4. parameter = CreateFlags.SoftwareVertexProcessing is a flag that switches off the vector graphics part of the graphic board to avoid any risk from old graphic boards and/or old DirectX-drivers = all vector graphics via HEL. Disadvantage: Waste of the powerful HAL vector pipelines of a modern graphic board.
//5. parameter = presentParams is a structure of status flags describing the bevahior of a graphic board.
//see: ../../Lectures/L05_OpenGL_DirectX

//set up the transformation of world coordinates into camera or view space //Commentdevice.Transform.View = Matrix.LookAtLH( // new Vector3( 0.0f, 0.0f,-4.0f ), // eye point 4.0 in front of the canvas new Vector3( 0.0f, 0.0f, 0.0f ), // camera looks at point 0,0,0 new Vector3( 0.0f, 1.0f, 0.0f ) ); // worlds up direction is the y-axis. See: http://msdn.microsoft.com/archive

//set up the projection transformation using 4 parameters:
//1.: field of view = 45 degrees; 2.: aspect ratio = width/height = 1.0 = square window;
//3.: near clipping distance = 0; 4.: far clipping distance = 10;device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI/4, 1f, 0f, 10f );.
//Describe the truncated viewing pyramid = frustum. 1. is the viewing angle in radians (PI/4=45o), 2. is the ratio width/height, 3. is the z-value of the front plane of the viewing volume and 4. the z-value of its back plane.
//See: http://msdn.microsoft.com/archive
//See: www.lighthouse3d.com/opengl/viewfrustum/ Please mail me if this link is dead.
Recommended experiment 1: Enlarge Math.PI/4 to Math.PI/2 = 90o. The scene will appear shifted away.
Recommended experiment 2: Distort the ratio to a) 0.5 and b) to 2.0.
Recommended experiment 3: Shift the front plane away from you in steps of 0.5.
Recommended experiment 4: Shift the back plane nearer to you in steps of 1.0 until it cuts through the convention of triangles.

//Turn off culling, so the user sees the front and back of the triangle //device.RenderState.CullMode = Cull.None; //Culling means excluding (mostly back) surfaces from being rendered.

//Turn off lighting, since the triangle provides its own colorsdevice.RenderState.Lighting = false; //Switch off any external light. The triangles carry their own color.

//set up the property that fills the triangle with colorsdevice.VertexFormat = CustomVertex.PositionColored.Format; //We have to tell the device that any vertex carries a color.

if ( vertexBuffer != null ) vertexBuffer.Dispose(); //Free the old vertexBuffer if any.//Create a new vertex buffer on the graphics card and connect it to the device.vertexBuffer = new VertexBuffer( typeof(CustomVertex.PositionColored), 3, device, Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default ); //
// See: ../../Lectures/L06_3DVector/3D_Vertex/3DVertex_d.htm#a3vertexBuffer.SetData( v, 0, LockFlags.None ); //Copy the vertices from main memory to graphics card memory.device.SetStreamSource( 0, vertexBuffer, 0 ); //Tell the device to use the vertexBuffer on the graphics card.

myTimer.Start(); //Start the timer again that has been stopped by the first statment of this function.

catch (DirectXException) { MessageBox.Show( "Could not initialize Direct3D." ); return; } //Emergency exit when DirectX 9.0 was not found and/or new Device crashed. End of the try-clause = second statement of this function.

//throw the old image awaydevice.Clear( ClearFlags.Target, Color.Blue, 1f, 0 ); //Erase any former content from the canvas.
Recommended experiment: Kick out the Clear-statement and observe how the new cylinders cover the old ones.

//rotate with an angular velocity = 0.1 //The angular increment is 0.1 radians ≈ 5.7o.fAngle += 0.1f; //Recommended experiment: Change this value in order to accelerate or slow down the animation.device.Transform.World = Matrix.RotationY( fAngle ); //Presets two initial values sinus(fAngle) and cosinus(fAngel) into the world transform matrix = common basic orientation of all traingles.