Sunday June 16, 2024
 Home | Contact | Support | XBOX Programming.. More than just a toy... | XBOX Programming.. More than just a toy...
 XBOX Programming.. More than just a toy...

# Prt6b - More than just a shape - a rotating shape...Cool

Author: bkenwright@xbdev.net

To take the sphere to a higher level, I've added some complex stuff which I'm wondering if I should have .... I've added a light, so that our sphere is illuminated - put those normals to good use.  Also I've added a matrix to rotate our world.... its a lot of code.... and its messy... but still ... this piece of code will be a cool in the future when we make it explode....

Now before you go running away screaming...take a deep breadth....that's it...now stay calm...its not that bad ...

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

void DrawSphereTriangleList()

{

UINT D3DFVF_CUSTOMVERTEX =  (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE);

struct CUSTOMVERTEX

{

FLOAT x, y, z;

FLOAT nx, ny, nz;

DWORD colour;

};

int nRings = 4;

int nSegments = 4;

DWORD dwNumOfVertices = (nRings + 1) * (nSegments + 1);

DWORD dwNumOfPolygons = dwNumOfVertices * 3;

LPDIRECT3DVERTEXBUFFER8 pVertexBuffer = NULL;

//CUSTOMVERTEX pVertex[dwNumOfVertices*3];

CUSTOMVERTEX pVertex[25*3] = {0};

D3DXVECTOR3 vNormal;

int nCurrentRing = 0;

//Setup some angles

float rDeltaRingAngle   = (D3DX_PI / nRings);

float rDeltaSegAngle    = (2.0f * D3DX_PI / nSegments);

//PART-1- Read in all the vertices that make up the shape

//Generate the group of rings for the sphere

for(nCurrentRing = 0; nCurrentRing < nRings +1; nCurrentRing++)

{

float r0 = sinf(nCurrentRing * rDeltaRingAngle);

float y0 = cosf(nCurrentRing * rDeltaRingAngle);

//OOooo Generate the group of segments for the current ring

for(int nCurrentSegment=0; nCurrentSegment < nSegments + 1; nCurrentSegment++)

{

float x0 = r0 * sinf(nCurrentSegment * rDeltaSegAngle);

float z0 = r0 * cosf(nCurrentSegment * rDeltaSegAngle);

vNormal.x = x0;

vNormal.y = y0;

vNormal.z = z0;

D3DXVec3Normalize(&vNormal, &vNormal);

//Add one vector to the strip which makes up the sphere

int i = nCurrentRing * nSegments + nCurrentSegment;

pVertex[i].x = x0;

pVertex[i].y = y0;

pVertex[i].z = z0;

pVertex[i].nx = vNormal.x;

pVertex[i].ny = vNormal.y;

pVertex[i].nz = vNormal.z;

pVertex[i].colour = 0xff00ff00;

}

}

//PART-2- Arrange them in list order

//This part puts all of our lovely vertices into a nice tidy order of triangles.

//CUSTOMVERTEX pVertexList[dwNumOfVertices*3];

CUSTOMVERTEX pVertexList[50*3] = {0};

int index = 0;

for(nCurrentRing = 0; nCurrentRing < nRings +1; nCurrentRing++)

{

for(int nCurrentSegment=0; nCurrentSegment < nSegments + 1; nCurrentSegment++)

{

if(nCurrentRing != nRings)

{

//These few lines specify the triangles into the pVertexList, as

//above we have just generated the vertices for the sphere, but they

//arnt aranged in an order of triangles, e.g. the first three points

//make up a triangle, the next three points make up a second triangle

//etc.  These lines within the loop take the points and generate

//a list of triangles which we can draw using D3DPT_TRIANGLELIST

int i =  nCurrentRing * nSegments;

pVertexList[index].x = pVertex[i+nCurrentSegment].x;

pVertexList[index].y = pVertex[i+nCurrentSegment].y;

pVertexList[index].z = pVertex[i+nCurrentSegment].z;

pVertexList[index].nx = pVertex[i+nCurrentSegment].nx;

pVertexList[index].ny = pVertex[i+nCurrentSegment].ny;

pVertexList[ index].nz = pVertex[i+nCurrentSegment].nz;

pVertexList[index].colour = pVertex[i+nCurrentSegment].colour;

index++;

///////////////////////////////////////////////////////////////

pVertexList[index].x = pVertex[i+nCurrentSegment + nSegments].x;

pVertexList[index].y = pVertex[i+nCurrentSegment + nSegments].y;

pVertexList[index].z = pVertex[i+nCurrentSegment + nSegments].z;

pVertexList[index].nx = pVertex[i+nCurrentSegment + nSegments].nx;

pVertexList[index].ny = pVertex[i+nCurrentSegment + nSegments].ny;

pVertexList[index].nz = pVertex[i+nCurrentSegment + nSegments].nz;

pVertexList[index].colour = pVertex[i+nCurrentSegment + nSegments].colour;

index++;

//////////////////////////////////////////////////////////////

pVertexList[index].x = pVertex[i+nCurrentSegment +1].x;

pVertexList[index].y = pVertex[i+nCurrentSegment  +1].y;

pVertexList[index].z = pVertex[i+nCurrentSegment  +1].z;

pVertexList[index].nx = pVertex[i+nCurrentSegment  +1].nx;

pVertexList[index].ny = pVertex[i+nCurrentSegment  +1].ny;

pVertexList[index].nz = pVertex[i+nCurrentSegment  +1].nz;

pVertexList[index].colour = pVertex[i+nCurrentSegment+1].colour;

index++;

/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////

pVertexList[index].x = pVertex[i+nCurrentSegment+ nSegments].x;

pVertexList[index].y = pVertex[i+nCurrentSegment+ nSegments].y;

pVertexList[index].z = pVertex[i+nCurrentSegment+ nSegments].z;

pVertexList[index].nx = pVertex[i+nCurrentSegment+ nSegments].nx;

pVertexList[index].ny = pVertex[i+nCurrentSegment+ nSegments].ny;

pVertexList[ index].nz = pVertex[i+nCurrentSegment+ nSegments].nz;

pVertexList[index].colour = pVertex[i+nCurrentSegment+ nSegments].colour;

index++;

///////////////////////////////////////////////////////////////

pVertexList[index].x = pVertex[i+nCurrentSegment + nSegments+ 1].x;

pVertexList[index].y = pVertex[i+nCurrentSegment + nSegments+ 1].y;

pVertexList[index].z = pVertex[i+nCurrentSegment + nSegments+ 1].z;

pVertexList[index].nx = pVertex[i+nCurrentSegment + nSegments+ 1].nx;

pVertexList[index].ny = pVertex[i+nCurrentSegment + nSegments+ 1].ny;

pVertexList[index].nz = pVertex[i+nCurrentSegment + nSegments+ 1].nz;

pVertexList[index].colour = pVertex[i+nCurrentSegment + nSegments].colour;

index++;

//////////////////////////////////////////////////////////////

pVertexList[index].x = pVertex[i+nCurrentSegment +1].x;

pVertexList[index].y = pVertex[i+nCurrentSegment  +1].y;

pVertexList[index].z = pVertex[i+nCurrentSegment  +1].z;

pVertexList[index].nx = pVertex[i+nCurrentSegment  +1].nx;

pVertexList[index].ny = pVertex[i+nCurrentSegment  +1].ny;

pVertexList[index].nz = pVertex[i+nCurrentSegment  +1].nz;

pVertexList[index].colour = pVertex[i+nCurrentSegment+1].colour;

index++;

}

}

}

g_pD3DDevice->CreateVertexBuffer(index * sizeof(CUSTOMVERTEX),

0, D3DFVF_CUSTOMVERTEX,

D3DPOOL_DEFAULT, &pVertexBuffer);

VOID* pV;

pVertexBuffer->Lock(0,0, (BYTE**)&pV, 0);

memcpy(pV, pVertexList, sizeof(CUSTOMVERTEX)*index);

pVertexBuffer->Unlock();

g_pD3DDevice->SetStreamSource(0, pVertexBuffer, sizeof(CUSTOMVERTEX));

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, index/3);//dwNumOfPolygons

pVertexBuffer->Release();

}

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

Now to make the sphere cooler....and not to make the whole tutorial to complex, I added a couple of functions to add light to the sphere.

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

void setlight()

{

//Set a light up?

D3DLIGHT8 d3dLight;

//Initialize the light structure.

ZeroMemory(&d3dLight, sizeof(D3DLIGHT8));

//Set up a white point light at (0, 0, -10).

d3dLight.Type = D3DLIGHT_POINT;

d3dLight.Diffuse.r = 1.0f;

d3dLight.Diffuse.g = 1.0f;

d3dLight.Diffuse.b = 1.0f;

d3dLight.Ambient.r = 0.0f;

d3dLight.Ambient.g = 0.0f;

d3dLight.Ambient.b = 0.0f;

d3dLight.Specular.r = 0.0f;

d3dLight.Specular.g     = 0.0f;

d3dLight.Specular.b     = 0.0f;

d3dLight.Position.x     = 0.0f;

d3dLight.Position.y     = 10.0f;//2

d3dLight.Position.z     = -10.0f;

d3dLight.Attenuation0 = 1.0f;

d3dLight.Attenuation1 = 0.0f;

d3dLight.Attenuation2 = 0.0f;

d3dLight.Range = 100.0f;

g_pD3DDevice->SetLight(0, &d3dLight);

g_pD3DDevice->LightEnable(0,TRUE);

//Turn on lighting

g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(5,100,32));

}

void setmaterial()

{

D3DMATERIAL8 matMaterial;

D3DCOLORVALUE rgbaDiffuse= {1.0, 1.0, 1.0, 0.0};

D3DCOLORVALUE rgbaAmbient = {1.0, 1.0, 1.0, 0.0};

D3DCOLORVALUE rgbaSpecular = {0.0, 0.0, 0.0, 0.0};

D3DCOLORVALUE rgbaEmissive = {0.0, 0.0, 0.0, 0.0};

matMaterial.Ambient = rgbaAmbient;

matMaterial.Specular = rgbaSpecular;

matMaterial.Emissive = rgbaEmissive;

matMaterial.Power = 100.0f;

g_pD3DDevice->SetMaterial(&matMaterial);

}

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

The DirectX Initilisation and De-Initilisation functions.

//Main header file for the XDK

#include <xtl.h>

LPDIRECT3D8 g_pD3D = NULL;                      // DirectX Object

LPDIRECT3DDEVICE8 g_pD3DDevice = NULL;          // Screen Object

void InitialiseD3D()

{

g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory(&d3dpp, sizeof(d3dpp));

d3dpp.BackBufferWidth = 640;

d3dpp.BackBufferHeight = 480;

d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;

d3dpp.BackBufferCount = 1;

d3dpp.EnableAutoDepthStencil = TRUE;

d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;

g_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL,

D3DCREATE_HARDWARE_VERTEXPROCESSING,

&d3dpp, &g_pD3DDevice);

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

//Turn on z-buffering

g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

//Turn off culling - so we can see the back of the sphere :)

g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

}

void CleanUp()

{

g_pD3DDevice->Release();

g_pD3D->Release();

}

And finally the entry point...the point where it all starts.

//Application entry point

void __cdecl main()

{

InitialiseD3D();

setlight();

setmaterial();

while(true)

{

//Clear the backbuffer to black

g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

//Begin the scene

g_pD3DDevice->BeginScene();

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

//camera

D3DXMATRIX view_matrix, matProj;

D3DXMatrixLookAtLH(&view_matrix,&D3DXVECTOR3( 0.0f, 0.0f,-5.0f ),

&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),

&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ));

g_pD3DDevice->SetTransform(D3DTS_VIEW,&view_matrix);

D3DXMatrixPerspectiveFovLH(&matProj, //Result Matrix

D3DX_PI/4,//Field of View, in radians. (PI/4) is typical

((float)600 / (float)400),     //Aspect ratio

1.0f,     //Near view plane

1000.0f ); // Far view plane

g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );

//end camera

//Okay this all may seem scary for someone new to matrix's but these few lines

//of code rotate our sphere so that we can make sure its round :)

D3DXMATRIX matWorld;

D3DXMATRIX trans_matrix;   //Our translation matrix

D3DXMATRIX y_rot_matrix;

static float y_rot=0;

y_rot-=0.001f;

//Set up the rotation matrix for the triangle

D3DXMatrixRotationY(&y_rot_matrix,y_rot);

//Set up the translation matrix (move it over to the left a bit)

D3DXMatrixTranslation(&trans_matrix,-1.0,0.0f,0.0f);

//Combine out matrices

D3DXMatrixMultiply(&matWorld,&y_rot_matrix,&trans_matrix);

//Set our World Matrix

g_pD3DDevice->SetTransform(D3DTS_WORLD,&matWorld );

//NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW NEW

DrawSphereTriangleList();

//End the scene

g_pD3DDevice->EndScene();

//Filp the back and front buffers so that whatever has been rendered on the back buffer

//will now be visible on screen (front buffer).

g_pD3DDevice->Present(NULL, NULL, NULL, NULL);

}

CleanUp();

}

Now if you go through the code slowly, you'll find the only code you need to know is the DrawSphereTriangleList() function...which of corse is a beauty to try and understand in one go.  But most of the other code is for effect - e.g. I've added a few lines in the main() function which rotates our world...so our lovely sphere is rotated slowly.