Download presentation
Presentation is loading. Please wait.
Published byCassandra Taylor Modified over 9 years ago
1
1 Cube & Sphere Chapter 5
2
2 Draw Cube Cube has 8 vertices as the picture shows. Each vertex has color of Red, Blue, Green or Yellow. We need to draw 6 faces. However, we want to draw the front faces only and remove all the back faces. How to control that? There are two methods to do so (i)Use the triangle direction control; (ii) Use the z-buffer.
3
3 Decide the draw order Top face, 0123 is clock wise. Bottom face, 4657 is counter-clock wise. Front face, 4062 is clock wise Right face, 6273 is clock wise Back face 7351 is counter-clock wise Left face 5140 is counter-clock wise. This is one possible order to draw all those faces. When the back face turns to the front, the order will change to the clock wise.
4
4 Set Cube Vertex void SetVertex() { CustomVertex.PositionColored [] verts = new CustomVertex.PositionColored[8]; // make eight vertices first verts[0].X=-4.0f; verts[0].Z=-4.0f; verts[0].Y= 4.0f; verts[0].Color = Color.Yellow.ToArgb(); verts[1].X=-4.0f; verts[1].Z= 4.0f; verts[1].Y= 4.0f; verts[1].Color = Color.Red.ToArgb(); verts[2].X= 4.0f; verts[2].Z=-4.0f; verts[2].Y= 4.0f; verts[2].Color = Color.Green.ToArgb();
5
5 verts[3].X= 4.0f; verts[3].Z= 4.0f; verts[3].Y= 4.0f; verts[3].Color = Color.Blue.ToArgb(); verts[4].X=-4.0f; verts[4].Z=-4.0f; verts[4].Y=-4.0f; verts[4].Color = Color.Blue.ToArgb(); verts[5].X=-4.0f; verts[5].Z= 4.0f; verts[5].Y=-4.0f; verts[5].Color = Color.Green.ToArgb(); verts[6].X=4.0f; verts[6].Z=-4.0f; verts[6].Y=-4.0f; verts[6].Color = Color.Red.ToArgb(); verts[7].X= 4.0f; verts[7].Z= 4.0f; verts[7].Y=-4.0f; verts[7].Color = Color.Yellow.ToArgb(); // next to make 24 vertices
6
6 v_cube = new CustomVertex.PositionColored[24]; v_cube[0] =verts[0] ; v_cube[1] =verts[1] ; v_cube[2] =verts[2] ; v_cube[3] =verts[3] ; // top face v_cube[4] =verts[4] ; v_cube[5] =verts[6] ; v_cube[6] =verts[5] ;v_cube[7] =verts[7] ; // bottom face v_cube[8] =verts[4] ; v_cube[9] =verts[0] ; v_cube[10] =verts[6] ;v_cube[11] =verts[2] ; // front face v_cube[12] =verts[6] ; v_cube[13] =verts[2] ; v_cube[14] =verts[7] ;v_cube[15] =verts[3] ; // right face v_cube[16] =verts[7] ; v_cube[17] =verts[3] ; v_cube[18] =verts[5] ;v_cube[19] =verts[1] ; // back face v_cube[20] =verts[5] ; v_cube[21] =verts[1] ; v_cube[22] =verts[4] ; v_cube[23] =verts[0] ; // left face }
7
7 private void Render() { …………… device.RenderState.CullMode = Cull.CounterClockwise ; device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); //top face device.DrawPrimitives(PrimitiveType.TriangleStrip, 4, 2); //bottom face device.DrawPrimitives(PrimitiveType.TriangleStrip, 8, 2); //front face device.DrawPrimitives(PrimitiveType.TriangleStrip, 12, 2); //right face device.DrawPrimitives(PrimitiveType.TriangleStrip, 16, 2); //back face device.DrawPrimitives(PrimitiveType.TriangleStrip, 20, 2); //left face ……….. }
8
8 Initialize Z-buffer for device void Init3D() { PresentParameters pp = new PresentParameters(); pp.Windowed = true; pp.SwapEffect = SwapEffect.Discard; // now add code to initialize z-buffer pp.EnableAutoDepthStencil=true; pp.AutoDepthStencilFormat=DepthFormat.D16 ; device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pp);} }
9
9 Initialize Z-buffer for drawing device.RenderState.CullMode = Cull.None; device.RenderState.ZBufferEnable=true; Clear Z-buffer to 1.0f before drawing device.Clear(ClearFlags.Target|ClearFlags.ZBuffer, Color.Black.ToArgb(),1.0f,0); Z-buffer value is from 0.0f to 1.0f. 1.0f means at infinity. 0.0f means the most closer.
10
10 Microsoft.DirectX.Direct3D.Font using D3D=Microsoft.DirectX.Direct3D; Constructer D3D.Font m_font = new D3D.Font (device, 20, 0, FontWeight.Bold,0, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.DefaultPitch, "Arial"); D3D.Font(Device device, int height, int width, FontWeight weight, int miplevel, bool italic, CharacterSet set, Precision precision, FontQuality qty, PitchAndFamily paf, string fontfamily); Example
11
11 Font::DrawText(…) private void DrawText(string str) { font.DrawText(null, str, new Rectangle(5,5,400, 40), DrawTextFormat.Left, Color.Yellow.ToArgb()); } int DrawText(D3D.Sprite pSprite, string pString, Rectangle pRect, DrawTextFormat Format, int Color ); Example
12
12 Calculate frame rate int t=0; int count =0;float fps=30.0f; Define member variables; t= Environment.TickCount; void Render() {............. int gap = Environment.TickCount - t; count++; if(gap>1000){ fps = (float)count*1000/(float)gap; fps= (float)Math.Round(fps,2); count=0; t=Environment.TickCount; } DrawText("Frame Rate: "+fps +" fps"); // must after Clear code.............. }
13
13 Out put
14
14 IndexBuffer method IndexBuffer is a D3D object that could set index for a given VertexBuffer To draw 6 cube faces, we have created a VertexBuffer of 24 vertices. However, we only need 8 different vertices. In order to save memory space, we can use IndexBuffer. The basic procedure is that: (i) First create a VertexBuffer of 8 vertices. (ii) Then create an IndexBuffer of with 24 elements, each element is only one int size. (iii) Use IndexBuffer to set index for the VertexBuffer (iv) Draw cube by method. DrawIndexedPrimative(…)
15
15 Constructor public IndexBuffer( Type typeOfIndex int sizeOfBufferInBytes, Device device, Usage usage, Pool pool, ); Example IndexBuffer IB = new IndexBuffer(typeof(int), 24, m_device, Usage.WriteOnly, Pool.Managed);
16
16 Set IndexBuffer Value The IndexBuffer Value can be set by function SetData(…) private bool InitIB() { IB=new IndexBuffer(typeof(int), 24, device,Usage.WriteOnly,Pool.Managed); if(IB==null) return false; int[] indices = new int[24]; indices[0]=0; indices[1]=1; indices[2]=2; indices[3]=3;......... IB.SetData(indices, 0, LockFlags.None); return true; }
17
17 DrawIndexedPrimitives In order to draw from index, we need to device.SetStreamSource( 0, VB, 0); device.Indices=IB; // set index device.DrawIndexedPrimitives( PrimitiveType.TriangleStrip, 0, 0, 8, 0, 2); Note: What is the meaning of 0, 0, 8, 0, 2? (1) The offset in VertexBuffer is 0. (2) The minimum index used in this call is 0. (3) The total source vertices is 8. (4) Begin drawing from index 0 of VertexBuffer. (5) Draw 2 triangles.
18
18 Draw from user memory Device can draw geometries directly from user defined memory array instead from VertexBuffer, which is in video card. public void DrawUserPrimitives( PrimitiveType primitiveType, int primitiveCount, object vertexArray ) We can use TriangleStrip or TriangleList for PrimitiveType. Object will be the vertex array defined by user.
19
19 Example private void SetVertex() { // those are two class member variables Vertices = new CustomVertex.PositionColored[12]; Vertices2 = new CustomVertex.PositionColored[10]; CustomVertex.PositionColored [] cube = new CustomVertex.PositionColored[8]; cube[0].Position = new Vector3( -4.0f,4.0f, -4.0f); cube[0].Color =Color.Yellow.ToArgb(); cube[1].Position = new Vector3( 4.0f,4.0f, -4.0f); cube[1].Color =Color.Red.ToArgb(); cube[2].Position = new Vector3( -4.0f,4.0f, 4.0f); cube[2].Color =Color.Green.ToArgb(); cube[3].Position = new Vector3( 4.0f,4.0f, 4.0f); cube[3].Color =Color.Blue.ToArgb();
20
20 cube[4].Position = new Vector3( -4.0f,-4.0f, -4.0f); cube[4].Color =Color.Blue.ToArgb(); cube[5].Position = new Vector3( 4.0f,-4.0f, -4.0f); cube[5].Color =Color.Green.ToArgb(); cube[6].Position = new Vector3( -4.0f,-4.0f, 4.0f); cube[6].Color =Color.Red.ToArgb(); cube[7].Position = new Vector3( 4.0f,-4.0f, 4.0f); cube[7].Color =Color.Yellow.ToArgb(); // top face use List Vertices[0]=cube[0]; Vertices[1]=cube[1]; Vertices[2]=cube[2]; Vertices[3]=cube[1]; Vertices[4]=cube[2];Vertices[5]=cube[3]; // bottom face List Vertices[6]=cube[4]; Vertices[7]=cube[5]; Vertices[8]=cube[6]; Vertices[9]=cube[5]; Vertices[10]=cube[6]; Vertices[11]=cube[7];
21
21 // all other 4 faces use strip Vertices2[0] = cube[4]; Vertices2[1] = cube[0]; Vertices2[2] = cube[5];Vertices2[3] = cube[1]; Vertices2[4] = cube[7];Vertices2[5] = cube[3]; Vertices2[6] = cube[6];Vertices2[7] = cube[2]; Vertices2[8] = cube[4];Vertices2[9] = cube[0]; } Draw Triangles m_device.DrawUserPrimitives(PrimitiveType.TriangleList,4, Vertices); m_device.DrawUserPrimitives(PrimitiveType.TriangleStrip,8, Vertices2);
22
22 DrawIndexedUserPrimitives(...) public void DrawUserIndexdPrimitives( PrimitiveType primitiveType, intMinimalIndex intTotalVertexUsed int primitiveCount, objectIndexArray bool16BitIndex object vertexArray ) Note: Set false for 16BitIndex if using Int32 array index
23
23 private void SetVertex() { v_cube = new CustomVertex.PositionColored[8]; indeces = new int[36]; v_cube [0].Position = new Vector3( -4.0f,4.0f, -4.0f); v_ cube[0].Color =Color.Yellow.ToArgb(); v_ cube[1].Position = new Vector3( 4.0f,4.0f, -4.0f); v_ cube[1].Color =Color.Red.ToArgb(); v_ cube[2].Position = new Vector3( -4.0f,4.0f, 4.0f); v_ cube[2].Color =Color.Green.ToArgb(); v_ cube[3].Position = new Vector3( 4.0f,4.0f, 4.0f); v_ cube[3].Color =Color.Blue.ToArgb(); v_ cube[4].Position = new Vector3( -4.0f,-4.0f, -4.0f); v_ cube[4].Color =Color.Blue.ToArgb(); Define class member variables: CustomVertex.PositionColored [] v_cube; int []indeces;
24
24 cube[5].Position = new Vector3( 4.0f,-4.0f, -4.0f); cube[5].Color =Color.Green.ToArgb(); cube[6].Position = new Vector3( -4.0f,-4.0f, 4.0f); cube[6].Color =Color.Red.ToArgb(); cube[7].Position = new Vector3( 4.0f,-4.0f, 4.0f); cube[7].Color =Color.Yellow.ToArgb(); // now set index for each triangle, use Triangle List indeces = new int[36]; indeces[0] = 0; indeces[1] = 1;indeces[2] = 2; indeces[3] = 1; indeces[4] = 2; indeces[5] = 3; indeces[6] = 4; indeces[7] = 5;indeces[8] = 6; indeces[9] = 5; indeces[10] = 6; indeces[11] = 7; indeces[12] = 4; indeces[13] = 0; indeces[14] = 5; indeces[15] = 0; indeces[16] = 5; indeces[17] = 1;
25
25 indeces[18] = 5; indeces[19] = 1; indeces[20] = 7; indeces[21] = 1; indeces[22] = 7; indeces[23] = 3; indeces[24] = 7; indeces[25] = 3; indeces[26] = 6; indeces[27] = 3; indeces[28] = 6; indeces[29] = 2; indeces[30] = 6; indeces[31] = 2; indeces[32] = 4; indeces[33] = 2; indeces[34] = 4; indeces[35] = 0; } Draw code device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, 8,12,indeces, false, v_cube); Minimum index Total vertex Total triangles Index array Vertex array
26
26 Use mouse to control position Here we will use static function of class Matrix public static Matrix RotationYawPitchRoll( float yaw, //around the y-axis, in radians float pitch, //around the x-axis, in radians. float roll,//around the z-axis, in radians. ); bool down = false; // check mouse down int lastX, lastY; // remember the last mouse position Matrix mat = Matrix.Identity; // remember rotations private void SetPosition() // replace rotation in Render() { device.Transform.World = mat; } First we define class member variables and function
27
27 protected override void OnMouseDown( MouseEventArgs e) { if(e.Button==MouseButtons.Left) { down = true; lastX = e.X; lastY = e.Y ; } } protected override void OnMouseUp( MouseEventArgs e) { down = false; } Then implement three event handling functions
28
28 protected override void OnMouseMove( MouseEventArgs e) { if(!down)return; int x = e.X ; int y = e.Y ; float dx= (float)(lastX-x)/50.0f ; float dy= (float)(lastY-y)/50.0f ; Matrix rot = Matrix.RotationYawPitchRoll(dx, dy, 0.0f); mat = mat*rot; // combine the previous position lastX =x; lastY =y ; } And
29
29 Draw Spherical Ball We must decompose the spherical surface into triangles. The sphere equation is So we equally partition value from 0 to and partition value from 0 to 2 to get many rectangles on the spherical surface, and each rectangle has 2 triangles. Note: Near poles, we actually get triangles directly.
30
30 So we totally have (m+1)(n+1) points, mn rectangles, 2mn triangles, 6mn vertices. Note: Near poles, some triangles are reduced to line segments. However, that does not affect drawing. 22 m intervals n intervals Map sphere surface to Rectangle
31
31 private void SetVertex() { v_sphere = new CustomVertex.PositionColored [(m+1)*(n+1)]; float alpha = 2.0f*(float)Math.PI /(float)m; float theta = (float)Math.PI /(float)n; for(int i=0; i<m+1; i++) for(int k=0; k<n+1; k++) { v_sphere[k*(m+1)+i].Z =r*(float) Math.Cos(k*theta ); v_sphere[k*(m+1)+i].X = r*(float)Math.Sin(k*theta)*(float) Math.Cos(i*alpha); v_sphere[k*(m+1)+i].Y = r*(float)Math.Sin(k*theta)*(float) Math.Sin(i*alpha); v_sphere[k*(m+1)+i].Color = Color.Yellow.ToArgb(); } Set (m+1)(n+1)Vertex Set the VertexBuffer is same as before.
32
32 private bool InitIB() { IB=new IndexBuffer(typeof(int), n*3*(2*m), device,Usage.WriteOnly,Pool.Managed); if(IB==null) return false; int[] indices = new int[n*3*(2*m)]; for(int k=0; k<n; k++) for(int i=0; i<m;i++) { indices[0+i*6+k*(6*m)] = i+0+k*(m+1); indices[1+i*6+k*(6*m)] = i+(m+1)+k*(m+1); indices[2+i*6+k*(6*m)] = i+(m+2)+k*(m+1); indices[3+i*6+k*(6*m)] = i+0+k*(m+1);; indices[4+i*6+k*(6*m)] = i+1+k*(m+1);; indices[5+i*6+k*(6*m)] = i+(m+2)+k*(m+1);; } IB.SetData(indices, 0, LockFlags.None); return true; } Set IndexBuffer
33
33 private void Render() {.... device.RenderState.FillMode=FillMode.WireFrame ; device.SetStreamSource( 0, VB2, 0); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, (m+1)*(n+1), 0, 2*m*n);....... } Draw Sphere Total pointsTotal triangles
34
34 Output
35
35 Draw solar system If we want draw 3 spheres, one is the sun, one is the earth and the 3 rd one is the moon. It is better to design a class to wrap all operations including VertexBuffer and IndexBuffer setting. public class Sphere { int m, n; float r; Color color; Device device; VertexBuffer VB = null; IndexBuffer IB = null; CustomVertex.PositionColored [] v_sphere = null; bool active=false;
36
36 private void SetVertex() { v_sphere = new CustomVertex.PositionColored [(m+1)*(n+1)]; float alpha = 2.0f*(float)Math.PI /(float)m; float theta = (float)Math.PI /(float)n; for(int i=0; i<m+1; i++) for(int k=0; k<n+1; k++) { v_sphere[k*(m+1)+i].Z =r*(float) Math.Cos(k*theta ); v_sphere[k*(m+1)+i].X = r*(float)Math.Sin(k*theta)*(float) Math.Cos(i*alpha); v_sphere[k*(m+1)+i].Y = r*(float)Math.Sin(k*theta)*(float) Math.Sin(i*alpha); v_sphere[k*(m+1)+i].Color = Color.Yellow.ToArgb(); }
37
37 private bool SetVB() { VB = new VertexBuffer( typeof(CustomVertex.PositionColored), v_sphere.Length, device, 0, CustomVertex.PositionColored.Format, Pool.Default); if(VB==null) return false; VB.Created += new System.EventHandler(this.WriteVBData); WriteVBData(null, null); return true; } public void WriteVBData(object sender, EventArgs e) { GraphicsStream stream = VB.Lock(0, 0, 0); stream.Write(v_sphere); VB.Unlock(); }
38
38 private void InitIB() { IB=new IndexBuffer(typeof(int), n*3*(2*m), device,Usage.WriteOnly,Pool.Managed); int[] indices = new int[n*3*(2*m)]; for(int k=0; k<n; k++) for(int i=0; i<m;i++) { indices[0+i*6+k*(6*m)] = i+0+k*(m+1); indices[1+i*6+k*(6*m)] = i+(m+1)+k*(m+1); indices[2+i*6+k*(6*m)] = i+(m+2)+k*(m+1); indices[3+i*6+k*(6*m)] = i+0+k*(m+1);; indices[4+i*6+k*(6*m)] = i+1+k*(m+1);; indices[5+i*6+k*(6*m)] = i+(m+2)+k*(m+1);; } IB.SetData(indices, 0, LockFlags.None); }
39
39 public Sphere(int mm, int nn, float rr, Color col, Device dev) { m=mm; n=nn; color =col; r = rr; device = dev; SetVertex(); active = SetVB(); SetIB(); } public void Draw() { if(!active)MessageBox.Show("Cannot draw sphere"); device.SetStreamSource( 0, VB, 0); device.Indices =IB; device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0,0, (m+1)*(n+1), 0,2*m*n); }
40
40 public void StartGame() { GameActive =Init3D(); ball1 = new Sphere(40,20,1.2f, Color.Yellow, device); ball2 = new Sphere(12,10,0.5f, Color.Blue, device); ball3 = new Sphere(10,8, 0.2f, Color.White, device); while(GameActive) { Render(); Application.DoEvents(); } private void Render() {....... device.RenderState.FillMode=FillMode.WireFrame ; SetRotation1(); ball1.Draw(); SetRotation2(); ball2.Draw(); SetRotation3(); ball3.Draw();....... }
41
41 Matrix mat; private void SetRotation2() // rotation of the earth {....... Matrix RY = Matrix.RotationY (theta) ; Matrix T = Matrix.Translation (2.7f,0,0) ; device.Transform.World=T*RY; mat =T*RY; // record the earth position } private void SetRotation3() // rotation of the moon {....... Matrix RY = Matrix.RotationY (theta) ; Matrix T = Matrix.Translation (0.7f,0,0) ; device.Transform.World=T*RY*mat; // combine mat } Note: we must record the World Translation Matrix of the earth and use this matrix to combine the rotation of the moon.
42
42 Output Note: We must use the world transform matrix of the earth to design the rotation function of the moon
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.