#include #include #include #include #include #include #include #include #include #include #include "mtk.hxx" #include "objects.hxx" #define RGB_COLOR(red, green, blue) \ (((DWORD)(BYTE)(red) << 0) | \ ((DWORD)(BYTE)(green) << 8) | \ ((DWORD)(BYTE)(blue) << 16)) #define RGBA_COLOR(red, green, blue, alpha) \ (((DWORD)(BYTE)(red) << 0) | \ ((DWORD)(BYTE)(green) << 8) | \ ((DWORD)(BYTE)(blue) << 16) | \ ((DWORD)(BYTE)(alpha) << 24)) #define FRANDOM(x) (((float)rand() / RAND_MAX) * (x)) /****** OBJECT *******************************************************/ OBJECT::OBJECT( int rings, int sections ) : nRings( rings ), nSections( sections ) { pTriData = NULL; pVertData = NULL; alphaVal = 255; } OBJECT::~OBJECT() { // These ptrs alloc'd in inheriting classes... if( pVertData ) free( pVertData ); if( pTriData ) free( pTriData ); } /****** SPHERE *******************************************************/ SPHERE::SPHERE( int rings, int sections, float fOpacity ) : OBJECT( rings, sections ) { iType = OBJECT_TYPE_SPHERE; alphaVal = (int) (fOpacity * 255.0f); SS_CLAMP_TO_RANGE2( alphaVal, 0, 255 ); nVerts = CalcNVertices(); nTris = CalcNTriangles(); // Allocate memory for the sphere data (freed by the base OBJECT class) // Vertex data pVertData = (VERTEX *) malloc( nVerts * sizeof(VERTEX) ); assert( pVertData != NULL ); // Triangle indices pTriData = (TRIANGLE *) malloc( nTris * sizeof(TRIANGLE) ); assert( pTriData != NULL ); GenerateData(1.0f); } int SPHERE::CalcNVertices() { return (((nRings)+1)*(nSections)+2); } int SPHERE::CalcNTriangles() { return (((nRings)+1)*(nSections)*2); } void SPHERE::GenerateData( float fRadius ) { float fTheta, fPhi; /* Angles used to sweep around sphere */ float fDTheta, fDPhi; /* Angle between each section and ring */ float fX, fY, fZ, fV, fRSinTheta; /* Temporary variables */ int i, j, n, m; /* counters */ VERTEX *pvtx = pVertData; TRIANGLE *ptri = pTriData; //mf: ! give these different alpha values ! DWORD color0 = RGBA_COLOR( 255, 0, 0, alphaVal ); DWORD color1 = RGBA_COLOR( 255, 255, 0, alphaVal ); // yellow /* * Generate vertices at the top and bottom points. */ pvtx[0].fX = 0.0f; pvtx[0].fY = fRadius; pvtx[0].fZ = 0.0f; pvtx[0].fNx = 0.0f; pvtx[0].fNy = 1.0f; pvtx[0].fNz = 0.0f; pvtx[0].dwColor = color0; pvtx[nVerts - 1].fX = 0.0f; pvtx[nVerts - 1].fY = -fRadius; pvtx[nVerts - 1].fZ = 0.0f; pvtx[nVerts - 1].fNx = 0.0f; pvtx[nVerts - 1].fNy = -1.0f; pvtx[nVerts - 1].fNz = 0.0f; pvtx[nVerts - 1].dwColor = color1; /* * Generate vertex points for rings */ fDTheta = PI / (float) (nRings + 2); fDPhi = 2.0f * PI / (float) nSections; n = 1; /* vertex being generated, begins at 1 to skip top point */ fTheta = fDTheta; for (i = 0; i <= nRings; i++) { fY = (float)(fRadius * cos(fTheta)); /* y is the same for each ring */ fV = fTheta / PI; /* v is the same for each ring */ fRSinTheta = (float)(fRadius * sin(fTheta)); fPhi = 0.0f; for (j = 0; j < nSections; j++) { fX = (float)(fRSinTheta * sin(fPhi)); fZ = (float)(fRSinTheta * cos(fPhi)); pvtx[n].fX = fX; pvtx[n].fZ = fZ; pvtx[n].fY = fY; pvtx[n].fNx = fX / fRadius; pvtx[n].fNy = fY / fRadius; pvtx[n].fNz = fZ / fRadius; if (n & 1) { pvtx[n].dwColor = color0; } else { pvtx[n].dwColor = color1; } fPhi += fDPhi; n++; } fTheta += fDTheta; } /* * Generate triangles for top and bottom caps. */ for (i = 0; i < nSections; i++) { ptri[i].iV1 = 0; ptri[i].iV2 = i + 1; ptri[i].iV3 = 1 + ((i + 1) % nSections); ptri[nTris - nSections + i].iV1 = nVerts - 1; ptri[nTris - nSections + i].iV2 = nVerts - 2 - i; ptri[nTris - nSections + i].iV3 = nVerts - 2 - ((1 + i) % nSections); } /* * Generate triangles for the rings */ m = 1; /* first vertex in current ring, begins at 1 to skip top point*/ n = nSections; /* triangle being generated, skip the top cap */ for (i = 0; i < nRings; i++) { for (j = 0; j < nSections; j++) { ptri[n].iV1 = m + j; ptri[n].iV2 = m + nSections + j; ptri[n].iV3 = m + nSections + ((j + 1) % nSections); ptri[n + 1].iV1 = ptri[n].iV1; ptri[n + 1].iV2 = ptri[n].iV3; ptri[n + 1].iV3 = m + ((j + 1) % nSections); n += 2; } m += nSections; } }