2
D3D virtual viewpoint Definition: virtual viewpoint is like a camera that was positioned in some where and oriented in some direction. Then from this location and direction we can see that part of our world in the monitor. This viewable solid is called viewing frustum.
Eventually, we will get a 2D image in the projection window for all objects.
3
3 parameters to set viewpoint(i) Location of the Camera (ii) Looking direction (iii) Up direction.
Up direction
In real world, the default up direction is (0, 0, 1). However, in 3D program, the default up direction is (0, 1, 0), which is y-axis.
4
Viewpoint Matrix Viewpoint matrix is
Call the following code to set up Viewpoint in 3D program
Static Matrix LookAtLH (
Vector3 CameraPosition,
Vector3 LookingTarget, // (0,0.0)
Vector3 UpDirection // (0,1,0)
)
device.Transform.View = Viewpoint_Matrix;
5
Actual functionprivate void SetViewpoint(){
Matrix viewMatrix = Matrix.LookAtLH (
new Vector3(2.0f, 3.0f, 3.0f), // location of cameranew Vector3(0.0f, 0.0f,0.0f), // looking targetnew Vector3(0.0f, 1.0f,0.0f) // up direction
); device.Transform.View =viewMatrix ;
}
6
D3D Projective windowAfter setting up viewpoint, we must setup Projective window,
which decided by 4 parameters: i) Float Angle, which means how wide that we can see
vertically.ii) Float Ratio of width over height, which can be simply set
to be 1.0 if we choose a square viewing window.iii) Near distance, which we usually choose 1.0iv) Far distance , which we usually choose 100.0
Projective window
7
Projective Matrix Projective matrix is
Call the following code to set up Projection in 3D program
Static Matrix PerspectiveFovLH (
float angle, //vertical Viewing
float Ratio, // width/height
float near, // near distance
float far // far distance
)
device.Transform. Projection = Projective_Matrix;
8
Actual functionprivate void SetProjective(){
Matrix ProjMatrix = Matrix.PerspectiveFovLH(
(float)Math.PI / 4, // vertical viewing angle (float)this.Width/(float)this.Height, // ratio
1.0f, // near distance100.0f // far distance
);m_device.Transform.Projection = ProjMatrix;
}
9
Set Rotation In order to make rotation in a constant speed, we need to
measure the time elapse by value Environment.TickCount
which is the number of milliseconds elapse since the system started. private void SetRotation(){
float a = ((float)Environment.TickCount)/1000.0f;float angle = a*2.0f * (float)Math.PI;
// one second, 360 degreedevice.Transform.World = Matrix.RotationY(angle ); // for all objects in 3D world in future drawing
}
After this function call, all objects in 3D world are rotated around y-axis by same angle
10
RenderState.CullMode
device.RenderState.CullMode = Cull.Clockwise ;
There are 3 CullMode values for RenderState , which are the
mode for the triangle direction.
1) Cull.None draw either directional triangle
2) Cull.Clockwise not draw clockwise triangle
3) Cull.CounterClockwise not draw anticlockwise triangle
The following is the code to set CullMode
11
RenderState.Lighting
device.RenderState.Lighting = false;
The colors of vertices will not be shown in 3D world unless the state of Lighting is set to be false. The following is the code to set Lighting.
Later, when we use texture to map picture to triangles, we must set lighting false too. Otherwise all triangle will be black and no picture at all.
12
Set vertexprivate void SetVertex(){
verts = new CustomVertex.PositionColored[3];
verts[0].X=-1.0f;verts[0].Y=0.0f;verts[0].Z=0.0f; verts[0].Color = Color.Yellow.ToArgb();
verts[1].X=1.0f;verts[1].Y=0.0f;verts[1].Z=0.0f; verts[1].Color = Color.Blue.ToArgb() ;
verts[2].X=0.0f; verts[2].Y=1.0f;verts[2].Z=0.0f; verts[2].Color = Color.Red.ToArgb();
// the three vertexes of a triangle}
13
private void SetV_Axis(){
v_axis = new CustomVertex.PositionColored[5];v_axis[1].X=0.0f; v_axis[1].Y=0.0f; v_axis[1].Z=0.0f; v_axis[1].Color = Color.White.ToArgb();
// origin (0,0,0, Color.White)v_axis[0]= v_axis[1]; v_axis[2]= v_axis[1];v_axis[3]= v_axis[1]; v_axis[4]= v_axis[1];
// copy all v_axis[0].X=4.0f;
// v[0] & v[1] for drawing x-axis v_axis[2].Y=4.0f;
// v[1]& v[2] for drawing y-axisv_axis[3].Z=4.0f;
// v[3] & v[4] for drawing z-axis}
This function is used to draw 3 axis
14
private bool InitVB(){
SetVertex(); VB = new VertexBuffer(typeof(CustomVertex.PositionColored), verts.Length, m_device, 0, CustomVertex.PositionColored.Format, Pool.Default);if(VB==null) return false;VB.Created += new System.EventHandler(this.WriteVertexData); WriteVertexData(null, null);SetV_Axis();VB2 = new VertexBuffer(typeof(CustomVertex.PositionColored), 5, m_device, 0, CustomVertex.PositionColored.Format, Pool.Default);if(VB2==null) return false;VB2.Created += new System.EventHandler(this.WriteVertexData2); WriteVertexData2(null, null);return true;
} // we must separate EventHandler for both vertex buffer
Init Vertex Buffers
15
private void WriteVertexData(object sender, EventArgs e){
GraphicsStream stream = VB.Lock(0, 0, 0);stream.Write(verts);VB.Unlock();
}
private void WriteVertexData2(object sender, EventArgs e){
GraphicsStream stream = VB2.Lock(0, 0, 0);stream.Write(v_axis);VB2.Unlock();
}
VB2 is for drawing axis.
Write Data into Vertex Buffer
16
Render functionprivate void Render(){
device.RenderState.CullMode = Cull.None;// both directions of triangle are drawn
device.RenderState.Lighting = false; // set lighting off
SetViewpoint(); // set view pointSetProjective();; // set projective windowdevice.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
// clear surface to black colordevice.BeginScene();
// begin drawingdevice.VertexFormat = CustomVertex.PositionColored.Format;
// set vertex format
17
device.SetStreamSource( 0, VB2, 0); // set stream source
device.Transform.World=Matrix.Identity ;// set identity matrix to 3D world
device.DrawPrimitives(PrimitiveType.LineList, 0, 1);device.DrawPrimitives(PrimitiveType.LineList, 1, 1);device.DrawPrimitives(PrimitiveType.LineList, 3, 1);
// draw 3 axis in fixed positiondevice.SetStreamSource( 0, VB, 0); SetRotation(); // reset rotation matrixdevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
// draw triangle in rotated positiondevice.EndScene(); // end drawingdevice.Present(); // flip surface
}
Note: Without setting identity matrix, all axis will be rotating
19
Two side color triangle
private void SetVertex(){
verts = new CustomVertex.PositionColored[6];verts[0].X=-1.0f;verts[0].Y=0.0f;verts[0].Z=0.0f; verts[1].X=1.0f;verts[1].Y=0.0f;verts[1].Z=0.0f; verts[2].X=0.0f; verts[2].Y=1.0f;verts[2].Z=0.0f;verts[0].Color = verts[1].Color = verts[2].Color = Color.Yellow.ToArgb();verts[3] = verts[0];verts[4] = verts[1];verts[5] = verts[2];verts[3].Color = verts[4].Color=verts[5].Color = Color.Red.ToArgb(); }
If we want to make the triangle to have red color in one side and yellow color in the other side, the code is:
20
Then we use Cull.Mode to make a control
private void Render(){
. . . . . . device.SetStreamSource( 0, VB, 0); // set resourcedevice.RenderState.CullMode=Cull.Clockwise ;device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);device.RenderState.CullMode=Cull.CounterClockwise ;device.DrawPrimitives(PrimitiveType.TriangleList, 3, 1);
. . . . . .}
// each time we only can draw one triangle
21
private void SetVertex(){
verts = new CustomVertex.PositionColored[6];verts[0].X=-1.0f;verts[0].Y=0.0f;verts[0].Z=0.0f; verts[1].X=1.0f;verts[1].Y=0.0f;verts[1].Z=0.0f; verts[2].X=0.0f; verts[2].Y=1.0f;verts[2].Z=0.0f;verts[0].Color = verts[1].Color = verts[2].Color = Color.Yellow.ToArgb();verts[3] = verts[0];verts[4] = verts[2]; verts[5] = verts[1];
// now the direction are different verts[3].Color = verts[4].Color=verts[5].Color = Color.Red.ToArgb();
}
Or define the the second triangle with a different direction
22
Then we change Cull.Mode code to
private void Render(){
. . . . . . device.SetStreamSource( 0, VB, 0); // set resourcedevice.RenderState.CullMode=Cull.Clockwise ;device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);device.DrawPrimitives(PrimitiveType.TriangleList, 3, 1);
. . . . . . // similarly we only can draw one triangle}