Проект lights1

Main Menu в VS 2008: File → New Project... → Visual Studio installed templates: Windows Forms Application
Name: lights1 → Location: C:\temp → Create directory for solution:
отключить → OK
Сотрите Program.cs и Form1.Designer.cs и содержимое Form1.cs.

Add Reference - Microsoft.DirectX Version 1.0.2902.0 , Microsoft.DirectX.Direct3D Version 1.0.2902.0.

Form1, OnResize, OnTimer

Напишите в Form1.cs Следующий код:

using System; 
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
public class Form1 : Form { 
	[STAThread] static void Main() { 
		Application.Run( new Form1() ); 
	} 
	static Device device = null; 
static float fAngle;
VertexBuffer vertexBuffer;
const int N = 100; //N must be an even no. 6, 8, 10, etc
CustomVertex.PositionNormal[] vv = new CustomVertex.PositionNormal[N];
Timer myTimer = new Timer();
	public Form1() { 
		Text = "D3DLights"; 
//TriangleStrip forming a cylinder
//
radius = 1; axis = Z-axis; top = 1; bottom = -1; => height = 2;
//in order to see the vertices, replace the TriangleStrip by a LineStrip in OnTimer(...)
		float arcus_increment = (float)( 2 * Math.PI / (N-2) ); 
Vector3 v = new Vector3();
for (int i = 0; i < N; i++) //Fill up coordinates and normal vectors
{
float arcus = i * arcus_increment; v.X = (float)Math.Cos( arcus );
v.Y = (float)Math.Sin( arcus );
if ( i%2 == 0 ) v.Z = 1f;
else v.Z = -1f; //zigzag between top and bottom
vv[ i ].Position = v; //vertex = (cos,sin,+1) or (cos,sin,-1)
v.Z = 0; //cylinder normals are parallel to the xy-plane
vv[ i ].Normal = v; //normal = (cos,sin,0)
		} 
		//set up the timer 
myTimer.Tick += new EventHandler( OnTimer );
myTimer.Interval = 1;
ClientSize = new Size( 400, 300 ); //Calls OnResize( ... )
	} 
	protected override void OnResize( System.EventArgs e ) 
	//Whenever the window changes we have to initialize Direct3D from scratch 
	{ myTimer.Stop();// stop the timer during initialization 
		try { //get information from the operating system about 
//
its current graphics properties
PresentParameters presentParams = new PresentParameters();
//we have to set two flags
presentParams.Windowed = true; //no full screen display
presentParams.SwapEffect = SwapEffect.Discard; //no swap buffer
presentParams.EnableAutoDepthStencil = true; //with depth buffer
presentParams.AutoDepthStencilFormat = DepthFormat.D16; //16 bit depth
//Create a new D3D-device that serves as canvas.
if ( device != null ) device.Dispose();
//free the old canvas if any
device = new Device( 0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, presentParams );
//Create a white material.
Material mtrl = new Material();
mtrl.Diffuse = mtrl.Ambient = Color.White;
device.Material = mtrl;
//Create a single, white, directional, diffuse light source and a gray ambient light.
//Many lights may be active at a time. (Notice: Each one slows down the render process.)
device.Lights[0].Type = LightType.Directional;
device.Lights[0].Diffuse = System.Drawing.Color.DarkTurquoise;
device.Lights[0].Direction = new Vector3( 1, 1, 5 );
device.Lights[0].Enabled = true;//turn it on
//Finally, turn on some ambient light that scatters and lights the object evenly
device.RenderState.Ambient = System.Drawing.Color.FromArgb( 0x202020 );
//set up the transformation of world coordinates into camera or view space
device.Transform.View = Matrix.LookAtLH(
new Vector3( 0f, 0f,-4f ), //eye point 4.0 in front of the canvas
new Vector3( 0f, 0f, 0f ), //camera looks at point 0,0,0
new Vector3( 0f, 1f, 0f ) ); //world's up direction is the y-axis
//set up the projection transformation using 4 parameters:
//1.: field of view = 45 degrees; 2.: aspect ratio = width / height = 1 = square window;
//3.: near clipping distance = 1; 4.: far clipping distance = 10;
device.Transform.Projection =
Matrix.PerspectiveFovLH( (float)Math.PI/4, 1f, 1f, 10f );
//device.RenderState.FillMode = FillMode.WireFrame; //try this to see the cylinder mesh
//device.RenderState.FillMode = FillMode.Solid ; //this is the default FillMode
device.RenderState.CullMode = Cull.None;
device.RenderState.Lighting = true;
device.VertexFormat = CustomVertex.PositionNormal.Format;
//create a new vertex buffer and connect it to the device
if ( vertexBuffer != null ) vertexBuffer.Dispose();//free the old vertexBuffer if any
vertexBuffer = new VertexBuffer( typeof(CustomVertex.PositionNormal), N,
device, 0, CustomVertex.PositionNormal.Format,
Pool.Default );
//copy the coordinates and colors of "vv" into the vertex buffer
vertexBuffer.SetData( vv, 0, LockFlags.None );
device.SetStreamSource( 0, vertexBuffer, 0 );
myTimer.Start();//start the timer again
} catch (DirectXException) { MessageBox.Show("Could not initialize Direct3D.");
return;
}
}
	protected static void OnTimer( Object myObject, EventArgs myEventArgs ) 
	{ 
if (device == null) return;
//throw the old image away
device.Clear( ClearFlags.Target | ClearFlags.ZBuffer, Color.Blue, 1f, 0 );
//rotate with an angular velocity = 5.7o/timer event
fAngle += 0.1f; //try also += 0.01f to slow the rotation down
device.Transform.World = Matrix.RotationAxis( new Vector3(1, 1, 1), fAngle );
//draw on the canvas
device.BeginScene();
device.DrawPrimitives( PrimitiveType.TriangleStrip, 0, N-2 );
//Experiment: Replace the TriangleStrip by a LineStrip as follows:
//device.DrawPrimitives( PrimitiveType.LineStrip, 0, N-2 );
device.EndScene(); device.Present(); //show the canvas
}
}

Кликните DebugStart Without Debugging Ctrl F5.

Задания

1. замените строку в protected static void OnTimer( Object myObject, EventArgs myEventArgs )  TriangleStrip на LineStrip и опробуйте, как меняется плотность Вертексов, когда вы меняете константу N с 6 на 8,  12, 48 и т.д.
2. притормозите анимацию -  myTimer.Interval = 100;.
3. ускорьте анимацию fAngle += 0.5f; in OnTimer.
4. поверните трубу по осям (1,1,1) в OnTimer.
5. поменяйте цвет дифузного света.
6. поменяйте цвет амбиентного света.
7. поменяйте позицию источника света: только сверху, только снизу, только слева и т.д.
8. поменяйте точку наблюдения с ( 0f, 0f,-4f ) на ( 0f, 0f,-100f )и ( 0f, 0f,-2f ).