1 / 42

# Cube &amp; Sphere

Cube &amp; Sphere. Chapter 5. 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

Télécharger la présentation

## Cube &amp; Sphere

E N D

### Presentation Transcript

1. Cube & Sphere Chapter 5

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. 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. Set Cube Vertex • void SetVertex() • { • CustomVertex.PositionColored [] verts= • newCustomVertex.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. 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. 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. private void Render(){ …………… • device.RenderState.CullMode = Cull.CounterClockwise ; device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); //top facedevice.DrawPrimitives(PrimitiveType.TriangleStrip, 4, 2); //bottom facedevice.DrawPrimitives(PrimitiveType.TriangleStrip, 8, 2); //front facedevice.DrawPrimitives(PrimitiveType.TriangleStrip, 12, 2); //right facedevice.DrawPrimitives(PrimitiveType.TriangleStrip, 16, 2); //back facedevice.DrawPrimitives(PrimitiveType.TriangleStrip, 20, 2);//left face ……….. • }

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. 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. Microsoft.DirectX.Direct3D.Font using D3D=Microsoft.DirectX.Direct3D; Constructer D3D.Font(Devicedevice, intheight, intwidth, FontWeight weight, int miplevel, bool italic, CharacterSet set, Precision precision, FontQuality qty, PitchAndFamily paf, stringfontfamily); Example D3D.Font m_font = new D3D.Font (device, 20, 0, FontWeight.Bold,0, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.DefaultPitch, "Arial");

11. Font::DrawText(…) int DrawText(D3D.SpritepSprite, string pString, Rectangle pRect, DrawTextFormat Format, int Color ); Example privatevoidDrawText(string str) { font.DrawText(null, str, new Rectangle(5,5,400, 40), DrawTextFormat.Left, Color.Yellow.ToArgb()); }

12. Calculate frame rate Define member variables; int t=0; int count =0; float fps=30.0f; 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. Out put

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 aVertexBuffer of 8 vertices. (ii) Then create anIndexBufferof with 24 elements, each element is only one int size. (iii) Use IndexBufferto set index for the VertexBuffer (iv) Draw cube by method. DrawIndexedPrimative(…)

15. Constructor public IndexBuffer(TypetypeOfIndex  int sizeOfBufferInBytes, Devicedevice,Usageusage,Poolpool,); Example IndexBuffer IB = new IndexBuffer(typeof(int), 24, m_device, Usage.WriteOnly, Pool.Managed);

16. Set IndexBuffer Value The IndexBuffer Value can be set by function SetData(…) • privateboolInitIB() • { • 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); • returntrue; • }

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. 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 TriangleListfor PrimitiveType. Object will be the vertex array defined by user.

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. 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. // 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. DrawIndexedUserPrimitives(. . .) • public void DrawUserIndexdPrimitives( • PrimitiveType primitiveType, • int MinimalIndex • int TotalVertexUsed • int primitiveCount, • object IndexArray • bool 16BitIndex • object vertexArray • ) Note: Set false for 16BitIndex if using Int32 array index

23. Define class member variables: CustomVertex.PositionColored [] v_cube;int []indeces; 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();

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. 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 Vertexarray

26. Use mouse to control position 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. ); Here we will use static function of class Matrix First we define class member variables and function bool down = false; // check mouse downint lastX, lastY; // remember the last mouse positionMatrix mat = Matrix.Identity; // remember rotations private void SetPosition() // replace rotation in Render(){ device.Transform.World = mat;}

27. Then implement three event handling functions • 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;}

28. And • 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 ; • }

29. Draw Spherical Ball We must decompose the spherical surface into triangles. The sphere equation is So we equally partition q value from 0 to p and partition a value from 0 to 2p to get many rectangles on the spherical surface, and each rectangle has 2 triangles. Note: Near poles, we actually get triangles directly.

30. Map sphere surface to Rectangle 2p a m intervals n intervals p q 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 .

31. Set (m+1)(n+1)Vertex 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 the VertexBuffer is same as before.

32. Set IndexBuffer 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; }

33. Draw Sphere 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); . . . . . . . } Total points Total triangles

34. Output

35. Draw solar system If we want draw 3 spheres, one is the sun, one is the earth and the 3rd one is the moon. It is better to design a class to wrap all operations including VertexBuffer and IndexBuffer setting. • publicclassSphere • { • int m, n;float r;Color color;Device device;VertexBuffer VB = null;IndexBuffer IB = null;CustomVertex.PositionColored [] v_sphere = null;bool active=false;

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. 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. 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. publicSphere(int mm, int nn, float rr, Color col, Device dev) { m=mm; n=nn; color =col; r = rr; device = dev; SetVertex(); active = SetVB(); SetIB(); } publicvoidDraw() { 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. publicvoidStartGame() { 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. Note:we must record the World Translation Matrix of the earth and use this matrix to combine the rotation of the moon. 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}

42. Output Note: We must use the world transform matrix of the earth to design the rotation function of the moon

More Related