1 cube & sphere chapter 5. 2 draw cube cube has 8 vertices as the picture shows. each vertex has...

Post on 24-Dec-2015

219 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

Cube & Sphere

Chapter 5

2

Draw CubeCube 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 orderTop 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 Vertexvoid 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

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 devicevoid 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.Fontusing 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

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

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

Out put

14

IndexBuffer methodIndexBuffer is a D3D object that could set index for a given VertexBufferTo 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

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

Set IndexBuffer ValueThe 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

DrawIndexedPrimitivesIn 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 memoryDevice 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

Exampleprivate void SetVertex(){

// those are two class member variablesVertices = 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 ListVertices[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 ListVertices[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 stripVertices2[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

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

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 Listindeces = 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 positionHere 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 downint lastX, lastY; // remember the last mouse positionMatrix mat = Matrix.Identity; // remember rotationsprivate void SetPosition() // replace rotation in Render() { device.Transform.World = mat;}

First we define class member variables and function

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

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 positionlastX =x;lastY =y ;

}

And

29

Draw Spherical BallWe must decompose the spherical surface into triangles.

The sphere equation is

sin (0 π)

cos cos (0 2π)

cos sin

z r

x r

y r

So we equally partition value from 0 to and partition value from 0 to 2to get many rectangles on the spherical surface, and each rectangle has 2 triangles.

Note: Near poles, we actually get triangles directly.

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 .

2

m intervals

n in

terv

als

Map sphere surface to Rectangle2π

m

π

n

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

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

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

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

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

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

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

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

Output

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

top related