Home | Course Index | << Prev | Next >> | PDF Version of this Page |
Course 3D_MDX: 3D-Graphics with Managed DirectX 9.0
|
|
Let me know what you think |
Project mesh_viewer1 Complete Program Exercises |
Main Menu after starting VS 2008: File → New Project... → Visual Studio installed templates: Windows Forms Application
Name: mesh_viewer1 → Location: C:\temp → Create directory for solution: switch it off → OK
Delete the files Program.cs and Form1.Designer.cs and the content of Form1.cs, as described in the chapters 2DCisC1 to 2DCisC4.
If You can't find a Solution Explorer-window, open it via the main menu: View → Solution Explorer.
Inside the Solution Explorer-window click the plus-sign in front of mesh_viewer1. A tree opens. Look for the branch "References". Right-click References and left-click Add Reference.... An Add Reference dialog box opens. Scroll down to the component name: Microsoft.DirectX Version 1.0.2902.0.
Highlight this reference by a left-click and (holding the Strg-key pressed) two more references:
Microsoft.DirectX.Direct3D Version 1.0.2902.0 and
Microsoft.DirectX.Direct3DX Version 1.0.2902.0 or 1.0.2903.0 or 1.0.2904.0.
Quit the Add Reference dialog box with OK.
Check if three references:
Microsoft.DirectX and
Microsoft.DirectX.Direct3D and
Microsoft.DirectX.Direct3DX are now visible inside the Solution Explorer window underneath
If You want to use DirectX Libs = References older than Version 1.0.2902.0 You'll obtain 3 error messages. The solution is simple: You have to delete the first parameter of the function calls in these lines:
mesh0 = Mesh.Clean( CleanType.Optimization, mesh0, adjacency, adjacency );
myfont.DrawText( null, "This mesh has " ...
myfont.DrawText( null, "divided into " ...
i.e. You have to delete the parameters CleanType.Optimization, null, and null, and the program will run.
This chapter requires that C:\DXSDK\Samples\Media\Tiger\tiger.x and C:\DXSDK\Samples\Media\Tiger\tiger.bmp and other 13 mesh- and texture-files are located in specific paths.. In case these files are somewhere else, You have to change the string static String s = @"C:\DXSDK\Samples\"; in the head of Form1.
Write the following code into the empty 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; static float xAngle, yAngle, zAngle; static Mesh mesh0, mesh1; static ExtendedMaterial[] materials; static Microsoft.DirectX.Direct3D.Font myfont; struct m{ public String title; public String mesh; public String texture; public Int32 eyedistance; public m(String a, String b, String c, Int32 d) //Constructor { title = a; mesh = b; texture = c; eyedistance = d; } }; static String s = @"C:\DXSDK\Samples\"; static m[] meshes = { new m("tiger" ,s+@"Media\Tiger\tiger.x" ,s+@"Media\Tiger\tiger.bmp", 5), new m("bigship",s+@"Media\misc\bigship1.x" ,s+@"Media\Tiger\tiger.bmp", 50), new m("knot" ,s+@"Media\misc\knot.x" ,s+@"Media\Tiger\tiger.bmp", 5), new m("shapes" ,s+@"Media\misc\shapes1.x" ,s+@"Media\Earth\earth.bmp", 50), new m("scull" ,s+@"Media\misc\skullocc.x" ,s+@"Media\Tiger\tiger.bmp", 50), new m("shark" ,s+@"Media\Prt Demo\LandShark.x" ,s+@"Media\Tiger\tiger.bmp",1000), new m("car" ,s+@"C++\Direct3D\EffectParam\car2.x",s+@"C++\Direct3D\EffectParam\EffectParam.jpg",2000), new m("tiny" ,s+@"Media\Tiny\tiny.x" ,s+@"Media\Tiger\tiger.bmp",2000), new m("dwarf" ,s+@"Media\Dwarf\dwarf.x" ,s+@"Media\Tiger\tiger.bmp", 10), new m("airplan",s+@"Media\Airplane\airplane 2.x" ,s+@"Media\Airplane\bihull.bmp",50), new m("headsad",s+@"Media\Prt Demo\Head_Sad.x" ,s+@"Media\Tiger\tiger.bmp",1000), new m("virus" ,s+@"C++\Direct3D\EffectParam\cytovirus.x",s+@"Media\Tiger\tiger.bmp",2000) }; String myMeshFile = meshes[0].mesh; String myTextureFile = meshes[0].texture; Bitmap myBitmap = null; BaseTexture myTexture = null; GraphicsStream adjacency = null; GroupBox group = new GroupBox(); RadioButton[] radio = new RadioButton[meshes.Length]; TrackBar[] track = new TrackBar[2]; Label[] label = new Label[2]; TextBox[] text = new TextBox[2]; CheckBox check = new CheckBox(); Panel panel = new Panel(); Timer myTimer = new Timer(); public Form1() { Text = "Mesh Viewer"; for ( int i = 0; i < track.Length; i++ ) { label[i] = new Label(); Controls.Add( label[i] ); track[i] = new TrackBar(); Controls.Add( track[i] ); text [i] = new TextBox(); Controls.Add( text [i] ); label[i].BackColor = track[i].BackColor = Color.Gray; track[i].Minimum = 1; track[i].TickStyle = TickStyle.None; label[i].TextAlign = ContentAlignment.MiddleCenter; text [i].TextAlign = HorizontalAlignment.Center; } Controls.Add( group ); for ( int i = 0; i < meshes.Length; i++ ) { radio[i] = new RadioButton(); Controls.Add( radio[i] ); radio[i].Parent = group; radio[i].Text = meshes[i].title; radio[i].Location = new Point( 5, Convert.ToInt32((0.6 + i*1.2)*FontHeight) ); radio[i].Size = new Size( 60, Convert.ToInt32(1.2*Font.Height) ); radio[i].TextAlign = ContentAlignment.MiddleCenter; radio[i].CheckedChanged += new EventHandler( radio_changed ); } label[0].Text = "Reduce Vertices"; label[1].Text = "Eye Distance"; Controls.Add( check ); Controls.Add( panel ); track[0].MouseUp += new MouseEventHandler( track0_MouseUp ); track[1].MouseUp += new MouseEventHandler( track1_MouseUp ); check .CheckedChanged += new EventHandler( check_changed ); myTimer.Tick += new EventHandler( OnTimer ); myTimer.Interval = 1; myBitmap = (Bitmap)Image.FromFile( meshes[0].texture ); track[1].Value = track[1].Maximum = meshes[0].eyedistance; ClientSize = new Size( 1024, 800 ); //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 for ( int i = 0; i < track.Length; i++ ) label[i].Width = track[i].Width = text[i].Width = ClientSize.Width / 10; text[0].Text = "vertices = " + track[0].Value.ToString(); text[1].Text = "eye = - " + track[1].Value.ToString(); check .Text = "Wire Frame"; group.Size = new Size( ClientSize.Width / 10, meshes.Length*radio[0].Height + 6 ); check.Size = new Size( ClientSize.Width / 10, radio[0].Height ); panel.Size = new Size( ClientSize.Width - label[0].Width - 2, ClientSize.Height - 2 ); group .Location = new Point( 2, 1 ); label[0].Location = new Point( 2, group .Location.Y + group .Height + 20 ); track[0].Location = new Point( 2, label[0].Location.Y + label[0].Height + 1 ); text [0].Location = new Point( 2, track[0].Location.Y + track[0].Height + 2 ); label[1].Location = new Point( 2, text[ 0].Location.Y + text [0].Height + 20 ); track[1].Location = new Point( 2, label[1].Location.Y + label[1].Height + 1 ); text [1].Location = new Point( 2, track[1].Location.Y + track[1].Height + 2 ); check .Location = new Point( 2, text [1].Location.Y + text [1].Height + 20 ); panel .Location = new Point( 2 + group.Width + 2, group.Location.Y ); try { PresentParameters presentParams = new PresentParameters(); presentParams.Windowed = true; presentParams.SwapEffect = SwapEffect.Discard; presentParams.EnableAutoDepthStencil = true; presentParams.AutoDepthStencilFormat = DepthFormat.D16; if ( device != null ) device.Dispose(); device = new Device( 0, DeviceType.Hardware, panel, CreateFlags.MixedVertexProcessing, presentParams ); //turn on some white directional light from left to right device.Lights[0].Type = LightType.Directional; device.Lights[0].Diffuse = Color.White; device.Lights[0].Direction = new Vector3( 1, 0, 0 ); device.Lights[0].Enabled = true; Material myMaterial = new Material(); myMaterial.Diffuse = myMaterial.Ambient = Color.White; device.Material = myMaterial; device.RenderState.Ambient = Color.FromArgb( 0x00303030 ); device.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math.PI/4, 1f, 1f, 5000f ); device.Transform.View = Matrix.LookAtLH( new Vector3( 0f, 0f, -track[1].Value ), new Vector3( 0f,0f,0f ), new Vector3( 0f,1f,0f ) ); device.RenderState.Lighting = true; if ( check.Checked ) device.RenderState.FillMode = FillMode.WireFrame; else device.RenderState.FillMode = FillMode.Solid; myfont = new Microsoft.DirectX.Direct3D.Font( device, new System.Drawing.Font( "Arial", 12, FontStyle.Bold ) ); SetUpMesh(); SetUpTexture(); myTimer.Start(); } catch (DirectXException) { MessageBox.Show("Could not initialize Direct3D." ); return; } } private void SetUpMesh() { Cursor.Current = Cursors.WaitCursor; //change mouse pointer to hour glass if ( mesh0 != null ) mesh0 .Dispose(); //free the old mesh if any mesh0 = Mesh.FromFile( myMeshFile, MeshFlags.Managed, device, out adjacency, out materials ); mesh0 = Mesh.Clean( CleanType.Optimization, mesh0, adjacency, adjacency ); if ( mesh1 != null ) mesh1.Dispose(); //free the old mesh if any //make a copy mesh1 from mesh0 mesh1 = mesh0.Clone( mesh0.Options.Value, mesh0.VertexFormat | VertexFormats.Normal, device ); //if mesh0 has no normals, compute them within mesh1 and copy them back to mesh0 if ( (mesh0.VertexFormat & VertexFormats.Normal) == 0 ) { mesh1.ComputeNormals(); mesh0.Dispose(); mesh0 = mesh1.Clone( mesh1.Options.Value, mesh1.VertexFormat, device ); } track[0].Value = track[0].Maximum = mesh0.NumberVertices; text[0].Text = "vertices = " + track[0].Value.ToString(); Cursor.Current = Cursors.Arrow; //change mouse pointer back to normal arrow } private void SetUpTexture() { if ( myTexture != null ) myTexture.Dispose(); //free the old texture if any myTexture = new Texture( device, myBitmap, 0, Pool.Managed ); device.SetTexture( 0, myTexture ); } protected static void OnTimer( Object myObject, EventArgs myEventArgs ) { device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Gray, 1f, 0); device.Transform.World = Matrix.RotationYawPitchRoll( yAngle += 0.02f, xAngle += 0.02f, zAngle += 0.02f ); device.BeginScene(); for ( int i=0; i < materials.Length; i++ ) mesh1.DrawSubset( i ); myfont.DrawText( null, "This mesh has " + mesh1.NumberVertices.ToString() + " vertices", new Rectangle( 0, 0, 100, 20 ), DrawTextFormat.NoClip, Color.Red ); myfont.DrawText( null, "divided into " + materials.Length.ToString() + " subsets", new Rectangle( 0, 20, 100, 20 ), DrawTextFormat.NoClip, Color.Red ); device.EndScene(); device.Present(); //show the canvas } private void radio_changed( Object sender, EventArgs e ) { RadioButton radio = (RadioButton)sender; Int32 i; for ( i = 0; i < meshes.Length; i++ ) if ( meshes[i].title == radio.Text ) break; if ( myMeshFile != meshes[i].mesh ) { myMeshFile = meshes[i].mesh; SetUpMesh(); } if ( myTextureFile != meshes[i].texture ) { myBitmap = (Bitmap)Image.FromFile( myTextureFile = meshes[i].texture ); SetUpTexture(); } track[1].Value = track[1].Maximum = meshes[i].eyedistance; text [1].Text = "eye = - " + track[1].Value.ToString(); device.Transform.View = Matrix.LookAtLH( new Vector3( 0f, 0f, -meshes[i].eyedistance ), new Vector3( 0f,0f,0f ), new Vector3( 0f,1f,0f ) ); } private void track0_MouseUp(object sender, System.EventArgs e) //Reduce no. of vertices { if ( materials.Length > 1 ) { MessageBox.Show( "This mesh has more than one subset. It can't be simplified !" ); track[0].Value = track[0].Maximum; return; } Cursor.Current = Cursors.WaitCursor; if ( mesh1 != null ) mesh1.Dispose(); try { mesh1 = Mesh.Simplify( mesh0, adjacency, null, track[0].Value, MeshFlags.SimplifyVertex ); } catch { mesh1 = mesh0.Clone( mesh0.Options.Value, mesh0.VertexFormat, device ); MessageBox.Show( "This mesh cannot be simplified !" ); } track[0].Value = mesh1.NumberVertices; text[0].Text = "vertices = " + mesh1.NumberVertices.ToString(); Cursor.Current = Cursors.Default; } private void track1_MouseUp(object sender, System.EventArgs e)//Eye Distance { device.Transform.View = Matrix.LookAtLH( new Vector3( 0f, 0f, -track[1].Value ), //eye point 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 text[1].Text = "eye = - " + track[1].Value.ToString(); } private void check_changed( Object sender, EventArgs e ) //Wire Frame on/off { if ( check.Checked ) device.RenderState.FillMode = FillMode.WireFrame; else device.RenderState.FillMode = FillMode.Solid; } }
Click Debug → Start Without Debugging Ctrl F5.
If You used DirectX Libs = References older than Version 1.0.2902.0 You obtain 3 error messages. The solution is simple: You have to delete the first parameter of the function calls in these lines:
mesh0 = Mesh.Clean( CleanType.Optimization, mesh0, adjacency, adjacency );
myfont.DrawText( null, "This mesh has " ...
myfont.DrawText( null, "divided into " ...
i.e. You have to delete the parameters CleanType.Optimization, null, and null, and the program will run.
1. Add another trackbar which shifts the x-axis rotation increment between 0 and 0.02.
2. Add another two trackbars which shift the y-axis and z-axis rotation increment between 0 and 0.02.
3. Add fourth trackbar which shifts the eye point in z-direction from -2000 to +2000.
4. Reduce automatically the no. of vertices, when the eye point moves away and the level of details can be reduced
top of page: |