#include #include #include #include #include #include #include #include #include #include // #define PROFILE 1 #ifdef PROFILE #include #endif typedef struct { float x, y, z; float nx, ny, nz; float tu, tv; DWORD color; } D3DVERTEX; typedef D3DVERTEX *LPD3DVERTEX; typedef struct { int v1; int v2; int v3; } D3DTRIANGLE; typedef D3DTRIANGLE *LPD3DTRIANGLE; #define D3DVAL(f) ((float)(f)) #define RGB_MAKE(r, g, b) \ (((DWORD)((r) & 0xff) << 0) | \ ((DWORD)((g) & 0xff) << 8) | \ ((DWORD)((b) & 0xff) << 16) | \ ((DWORD)(0xff) << 24)) typedef float __GLfloat; typedef struct { __GLfloat matrix[4][4]; } __GLmatrix; __GLmatrix identity = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; void __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b) { __GLfloat b00, b01, b02, b03; __GLfloat b10, b11, b12, b13; __GLfloat b20, b21, b22, b23; __GLfloat b30, b31, b32, b33; GLint i; b00 = b->matrix[0][0]; b01 = b->matrix[0][1]; b02 = b->matrix[0][2]; b03 = b->matrix[0][3]; b10 = b->matrix[1][0]; b11 = b->matrix[1][1]; b12 = b->matrix[1][2]; b13 = b->matrix[1][3]; b20 = b->matrix[2][0]; b21 = b->matrix[2][1]; b22 = b->matrix[2][2]; b23 = b->matrix[2][3]; b30 = b->matrix[3][0]; b31 = b->matrix[3][1]; b32 = b->matrix[3][2]; b33 = b->matrix[3][3]; for (i = 0; i < 4; i++) { r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10 + a->matrix[i][2]*b20 + a->matrix[i][3]*b30; r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11 + a->matrix[i][2]*b21 + a->matrix[i][3]*b31; r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12 + a->matrix[i][2]*b22 + a->matrix[i][3]*b32; r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13 + a->matrix[i][2]*b23 + a->matrix[i][3]*b33; } } void MakePosMatrix(__GLmatrix *lpM, float x, float y, float z) { memcpy(lpM, &identity, sizeof(__GLmatrix)); lpM->matrix[3][0] = D3DVAL(x); lpM->matrix[3][1] = D3DVAL(y); lpM->matrix[3][2] = D3DVAL(z); } void MakeRotMatrix(__GLmatrix *lpM, float rx, float ry, float rz) { float ct, st; __GLmatrix My, Mx, Mz, T; memcpy(&My, &identity, sizeof(__GLmatrix)); ct = D3DVAL(cos(ry)); st = D3DVAL(sin(ry)); My.matrix[0][0] = ct; My.matrix[0][2] = -st; My.matrix[2][0] = st; My.matrix[2][2] = ct; memcpy(&Mx, &identity, sizeof(__GLmatrix)); ct = D3DVAL(cos(rx)); st = D3DVAL(sin(rx)); Mx.matrix[1][1] = ct; Mx.matrix[1][2] = st; Mx.matrix[2][1] = -st; Mx.matrix[2][2] = ct; memcpy(&Mz, &identity, sizeof(__GLmatrix)); ct = D3DVAL(cos(rz)); st = D3DVAL(sin(rz)); Mz.matrix[0][0] = ct; Mz.matrix[0][1] = st; Mz.matrix[1][0] = -st; Mz.matrix[1][1] = ct; __glMultMatrix(&T, &My, &Mx); __glMultMatrix(lpM, &T, &Mz); } void *Malloc(size_t bytes) { void *pv; pv = malloc(bytes); if (pv == NULL) { printf("Unable to alloc %d bytes\n", bytes); exit(1); } return pv; } #define PI ((float)3.14159265358979323846) #define WIDTH 400 #define HEIGHT 400 #define SPWIDTH 140 #define SPHEIGHT 140 #define MAWIDTH 90 #define MAHEIGHT 75 #define LAWIDTH 230 #define LAHEIGHT 190 int iSwapWidth, iSwapHeight; #define SRADIUS 0.4f #define DMINUSR 0.6 #define DV 0.05 #define DR 0.3 #define DEPTH 0.6f #define random(x) (((float)rand() / RAND_MAX) * (x)) #define FILL_TRIANGLES 50 #define MEDIUM_AREA 3000 #define LARGE_AREA 20000 #define FRONT_TO_BACK 0 #define BACK_TO_FRONT 1 #define ORDER_COUNT 2 int iOrder = FRONT_TO_BACK; char *pszOrders[] = { "front-to-back", "back-to-front" }; #define AREA_LARGE 0 #define AREA_MEDIUM 1 #define AREA_COUNT 2 int iFillSize = AREA_MEDIUM; int iTriangleArea; typedef struct _Sphere { GLfloat xrv, yrv, zrv; __GLmatrix pos, dpos; __GLmatrix rot, drot; } Sphere; #define NSPHERES 8 Sphere spheres[NSPHERES]; BOOL fSingle = FALSE; BOOL fRotate = TRUE; BOOL fBounce = TRUE; BOOL fSwap = TRUE; BOOL fPaused = FALSE; BOOL fUseScissor = TRUE; BOOL fSpread = FALSE; BOOL fExit = FALSE; BOOL fSingleColor = TRUE; BOOL fVerbose = FALSE; BOOL fDisplayList = TRUE; int iMultiLoop = 1; int nRings = 30; int nSections = 30; GLint iDlist; #define TEXOBJ #ifdef TEXOBJ GLuint uiTexObj; #endif PFNGLADDSWAPHINTRECTWINPROC glAddSwapHintRectWIN; #define TEST_FILL 0 #define TEST_POLYS 1 #define TEST_COUNT 2 int iTest = TEST_POLYS; AUX_RGBImageRec *pTexture; #define TEXMODE_REPLACE 0 #define TEXMODE_DECAL 1 #define TEXMODE_MODULATE 2 #define TEXMODE_COUNT 3 int iTexMode = TEXMODE_REPLACE; char *pszTexModes[] = { "replace", "decal", "modulate" }; GLenum eTexModes[] = { GL_REPLACE, GL_DECAL, GL_MODULATE }; BOOL fPerspective = TRUE; //--------------------------------------------------------------------------; // // FunctionName: GenerateSphere() // // Purpose: // Generate the geometry of a sphere. // // Returns BOOL // // History: // 11/17/95 RichGr // //--------------------------------------------------------------------------; /* * Generates a sphere around the y-axis centered at the origin including * normals and texture coordinates. Returns TRUE on success and FALSE on * failure. * sphere_r Radius of the sphere. * num_rings Number of full rings not including the top and bottom * caps. * num_sections Number of sections each ring is divided into. Each * section contains two triangles on full rings and one * on top and bottom caps. * sx, sy, sz Scaling along each axis. Set each to 1.0 for a * perfect sphere. * plpv On exit points to the vertices of the sphere. The * function allocates this space. Not allocated if * function fails. * plptri On exit points to the triangles of the sphere which * reference vertices in the vertex list. The function * allocates this space. Not allocated if function fails. * pnum_v On exit contains the number of vertices. * pnum_tri On exit contains the number of triangles. */ BOOL GenerateSphere(float sphere_r, int num_rings, int num_sections, float sx, float sy, float sz, LPD3DVERTEX* plpv, LPD3DTRIANGLE* plptri, int* pnum_v, int* pnum_tri) { float theta, phi; /* Angles used to sweep around sphere */ float dtheta, dphi; /* Angle between each section and ring */ float x, y, z, v, rsintheta; /* Temporary variables */ int i, j, n, m; /* counters */ int num_v, num_tri; /* Internal vertex and triangle count */ LPD3DVERTEX lpv; /* Internal pointer for vertices */ LPD3DTRIANGLE lptri; /* Internal pointer for trianlges */ /* * Check the parameters to make sure they are valid. */ if ((sphere_r <= 0) || (num_rings < 1) || (num_sections < 3) || (sx <= 0) || (sy <= 0) || (sz <= 0)) return FALSE; /* * Generate space for the required triangles and vertices. */ num_tri = (num_rings + 1) * num_sections * 2; num_v = (num_rings + 1) * num_sections + 2; *plpv = (LPD3DVERTEX)Malloc(sizeof(D3DVERTEX) * num_v); *plptri = (LPD3DTRIANGLE)Malloc(sizeof(D3DTRIANGLE) * num_tri); lpv = *plpv; lptri = *plptri; *pnum_v = num_v; *pnum_tri = num_tri; /* * Generate vertices at the top and bottom points. */ lpv[0].x = D3DVAL(0.0f); lpv[0].y = D3DVAL(sy * sphere_r); lpv[0].z = D3DVAL(0.0f); lpv[0].nx = D3DVAL(0.0f); lpv[0].ny = D3DVAL(1.0f); lpv[0].nz = D3DVAL(0.0f); lpv[0].color = RGB_MAKE(0, 0, 255); lpv[0].tu = D3DVAL(0.0f); lpv[0].tv = D3DVAL(0.0f); lpv[num_v - 1].x = D3DVAL(0.0f); lpv[num_v - 1].y = D3DVAL(sy * -sphere_r); lpv[num_v - 1].z = D3DVAL(0.0f); lpv[num_v - 1].nx = D3DVAL(0.0f); lpv[num_v - 1].ny = D3DVAL(-1.0f); lpv[num_v - 1].nz = D3DVAL(0.0f); lpv[num_v - 1].tu = D3DVAL(0.0f); lpv[num_v - 1].tv = D3DVAL(1.0f); lpv[num_v - 1].color = RGB_MAKE(0, 255, 0); /* * Generate vertex points for rings */ dtheta = PI / (float) (num_rings + 2); dphi = 2.0f * PI / (float) num_sections; n = 1; /* vertex being generated, begins at 1 to skip top point */ theta = dtheta; for (i = 0; i <= num_rings; i++) { y = (float)(sphere_r * cos(theta)); /* y is the same for each ring */ v = theta / PI; /* v is the same for each ring */ rsintheta = (float)(sphere_r * sin(theta)); phi = 0.0f; for (j = 0; j < num_sections; j++) { x = (float)(rsintheta * sin(phi)); z = (float)(rsintheta * cos(phi)); lpv[n].x = D3DVAL(sx * x); lpv[n].z = D3DVAL(sz * z); lpv[n].y = D3DVAL(sy * y); lpv[n].nx = D3DVAL(x / sphere_r); lpv[n].ny = D3DVAL(y / sphere_r); lpv[n].nz = D3DVAL(z / sphere_r); lpv[n].tv = D3DVAL(v); lpv[n].tu = D3DVAL(1.0f - phi / (2.0f * PI)); if (n & 1) { lpv[n].color = RGB_MAKE(0, 0, 255); } else { lpv[n].color = RGB_MAKE(0, 255, 0); } phi += dphi; ++n; } theta += dtheta; } /* * Generate triangles for top and bottom caps. */ for (i = 0; i < num_sections; i++) { lptri[i].v1 = 0; lptri[i].v2 = i + 1; lptri[i].v3 = 1 + ((i + 1) % num_sections); // lptri[i].flags = D3D_EDGE_ENABLE_TRIANGLE; lptri[num_tri - num_sections + i].v1 = num_v - 1; lptri[num_tri - num_sections + i].v2 = num_v - 2 - i; lptri[num_tri - num_sections + i].v3 = num_v - 2 - ((1 + i) % num_sections); // lptri[num_tri - num_sections + i].flags= D3D_EDGE_ENABLE_TRIANGLE; } /* * Generate triangles for the rings */ m = 1; /* first vertex in current ring,begins at 1 to skip top point*/ n = num_sections; /* triangle being generated, skip the top cap */ for (i = 0; i < num_rings; i++) { for (j = 0; j < num_sections; j++) { lptri[n].v1 = m + j; lptri[n].v2 = m + num_sections + j; lptri[n].v3 = m + num_sections + ((j + 1) % num_sections); // lptri[n].flags = D3D_EDGE_ENABLE_TRIANGLE; lptri[n + 1].v1 = lptri[n].v1; lptri[n + 1].v2 = lptri[n].v3; lptri[n + 1].v3 = m + ((j + 1) % num_sections); // lptri[n + 1].flags = D3D_EDGE_ENABLE_TRIANGLE; n += 2; } m += num_sections; } return TRUE; } // Creates triangle and quad strip index sets for vertex data generated // by GenerateSphere. The top and bottom triangle fans are omitted because // they're degenerate cases for strips int CreateStrip(int nSections, int **ppiStrip) { int nPts; int *piIdx, iIdxBase; int iRing, iSection; // Stick to a single strip for now nRings = 1; nPts = nRings*(nSections+1)*2; *ppiStrip = (int *)Malloc(sizeof(int)*nPts); piIdx = *ppiStrip; iIdxBase = 1; for (iRing = 0; iRing < nRings; iRing++) { for (iSection = 0; iSection <= nSections; iSection++) { *piIdx++ = iIdxBase+(iSection % nSections); *piIdx++ = iIdxBase+(iSection % nSections)+nSections; } iIdxBase += nSections; } return nPts; } float fltCenter[NSPHERES][2] = { -SRADIUS, 0.0f, 0.0f, SRADIUS, SRADIUS, 0.0f, 0.0f, -SRADIUS }; void InitSpheres(void) { int i; Sphere *sp; float x, y, z; #if 0 srand(time(NULL)); #else srand( (unsigned)8269362521); #endif for (i = 0; i < NSPHERES; i++) { sp = &spheres[i]; if (fBounce) { x = (float)DMINUSR - (float)random(2 * DMINUSR); y = (float)DMINUSR - (float)random(2 * DMINUSR); z = (float)-DEPTH + (float)random(2 * DEPTH); } else { x = fltCenter[i][0]; y = fltCenter[i][1]; z = 0.0f; } MakePosMatrix(&sp->pos, x, y, z); x = (float)DV - (float)random(2 * DV); y = (float)DV - (float)random(2 * DV); z = (float)DV - (float)random(2 * DV); MakePosMatrix(&sp->dpos, x, y, z); MakeRotMatrix(&sp->rot, 0.0f, 0.0f, 0.0f); sp->xrv = (float)DR - (float)random(2 * DR); sp->yrv = (float)DR - (float)random(2 * DR); sp->zrv = (float)DR - (float)random(2 * DR); MakeRotMatrix(&sp->drot, sp->xrv, sp->yrv, sp->zrv); } } void UpdateSphere(Sphere *sp) { GLboolean newRot; if (fBounce) { newRot = GL_FALSE; if (sp->pos.matrix[3][0] > DMINUSR || sp->pos.matrix[3][0] < -DMINUSR) { sp->dpos.matrix[3][0] = -sp->dpos.matrix[3][0]; sp->zrv = -sp->zrv; sp->yrv = -sp->yrv; newRot = GL_TRUE; } if (sp->pos.matrix[3][1] > DMINUSR || sp->pos.matrix[3][1] < -DMINUSR) { sp->dpos.matrix[3][1] = -sp->dpos.matrix[3][1]; sp->zrv = -sp->zrv; sp->xrv = -sp->xrv; newRot = GL_TRUE; } if (sp->pos.matrix[3][2] > DEPTH || sp->pos.matrix[3][2] < -DEPTH) { sp->dpos.matrix[3][2] = -sp->dpos.matrix[3][2]; sp->xrv = -sp->xrv; sp->yrv = -sp->yrv; newRot = GL_TRUE; } if (newRot) { MakeRotMatrix(&sp->drot, sp->xrv, sp->yrv, sp->zrv); } __glMultMatrix(&sp->pos, &sp->dpos, &sp->pos); } if (fRotate) { __glMultMatrix(&sp->rot, &sp->drot, &sp->rot); } } #define TAN_60 1.732 void SetTriangleVertices(LPD3DVERTEX v, float z, UINT ww, UINT wh, float a, int ox, int oy) { float dx, dy; float b = (float)sqrt((4 * a) / TAN_60); float h = (2 * a) / b; float x = (float)((b / 2) * (TAN_60 / 2)); float cx, cy; dx = (float)ww; dy = (float)wh; cx = dx / 2 + ox; cy = dy / 2 + oy; /* V 0 */ v[0].x = cx; v[0].y = cy + (h - x); v[0].z = z; v[0].color = RGB_MAKE(255, 0, 0); v[0].tu = D3DVAL(0.5); v[0].tv = D3DVAL(0.0); /* V 1 */ v[1].x = cx + (b / 2); v[1].y = cy - x; v[1].z = z; v[1].color = RGB_MAKE(255, 255, 255); v[1].tu = D3DVAL(1.0); v[1].tv = D3DVAL(1.0); /* V 2 */ v[2].x = cx - (b / 2); v[2].y = cy - x; v[2].z = z; v[2].color = RGB_MAKE(255, 255, 0); v[2].tu = D3DVAL(0.0); v[2].tv = D3DVAL(1.0); } void InitFill(LPD3DVERTEX *ppVertices, LPD3DTRIANGLE *ppTriangles) { *ppVertices = (LPD3DVERTEX)Malloc(3 * FILL_TRIANGLES * sizeof(D3DVERTEX)); *ppTriangles = (LPD3DTRIANGLE)Malloc(FILL_TRIANGLES * sizeof(D3DTRIANGLE)); } D3DVERTEX *pPolyVertices; D3DTRIANGLE *pPolyTriangles; int nNumVertices, nNumFaces; int *pPolyStrip; int nStripIndices; D3DVERTEX *pFillVertices; D3DTRIANGLE *pFillTriangles; int *pIndices; int nIndices; int nTriangles; #define POLYMODE_POINT 0 #define POLYMODE_LINE 1 #define POLYMODE_FILL 2 #define POLYMODE_COUNT 3 GLenum ePolygonModes[] = { GL_POINT, GL_LINE, GL_FILL }; int iPolygonMode = POLYMODE_FILL; #define SMODEL_SMOOTH 0 #define SMODEL_FLAT 1 #define SMODEL_COUNT 2 GLenum eShadeModels[] = { GL_SMOOTH, GL_FLAT }; char *pszShadeModels[] = { "smooth", "flat" }; int iShadeModel = SMODEL_SMOOTH; #define PRIM_TRIANGLES 0 #define PRIM_TSTRIP 1 #define PRIM_QSTRIP 2 #define PRIM_COUNT 3 GLenum ePrimTypes[] = { GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_QUAD_STRIP }; char *pszPrimTypes[] = { "Tris", "TStrip", "QStrip" }; int iPrimType = PRIM_TRIANGLES; int total_ms = 0; int total_tris = 0 ; double peak_tri = 0, peak_fill = 0, avg_tri = 0, avg_fill = 0; int avg_cnt = 0; void ModeChange(void) { total_ms = 0; total_tris = 0; avg_tri = 0; avg_fill = 0; avg_cnt = 0; } void SetPrim(int iNew) { ModeChange(); iPrimType = iNew; switch(iTest) { case TEST_POLYS: switch(iPrimType) { case PRIM_TRIANGLES: pIndices = (int *)pPolyTriangles; nIndices = nNumFaces*3; nTriangles = nNumFaces; break; case PRIM_TSTRIP: case PRIM_QSTRIP: pIndices = pPolyStrip; nIndices = nStripIndices; nTriangles = nSections*2; break; } nTriangles *= NSPHERES; break; case TEST_FILL: pIndices = (int *)pFillTriangles; nIndices = FILL_TRIANGLES*3; nTriangles = FILL_TRIANGLES; break; } } void SetVertexArrayVertices(LPD3DVERTEX pVertices) { glVertexPointer(3, GL_FLOAT, sizeof(D3DVERTEX), &pVertices[0].x); glNormalPointer(GL_FLOAT, sizeof(D3DVERTEX), &pVertices[0].nx); glTexCoordPointer(2, GL_FLOAT, sizeof(D3DVERTEX), &pVertices[0].tu); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(D3DVERTEX), &pVertices[0].color); } void SetFill(int iNewSize, int iNewOrder) { int i; float z; int NumTri; LPD3DVERTEX pVert; LPD3DTRIANGLE pTri; UINT w, h; float area; int ox, oy, dox, doy; RECT rct; ModeChange(); iFillSize = iNewSize; iOrder = iNewOrder; switch(iFillSize) { case AREA_LARGE: iTriangleArea = LARGE_AREA; iSwapWidth = LAWIDTH; iSwapHeight = LAHEIGHT; break; case AREA_MEDIUM: iTriangleArea = MEDIUM_AREA; iSwapWidth = MAWIDTH; iSwapHeight = MAHEIGHT; break; } glScissor((WIDTH-iSwapWidth)/2, (HEIGHT-iSwapHeight)/2, iSwapWidth, iSwapHeight); w = WIDTH; h = HEIGHT; NumTri = FILL_TRIANGLES; pVert = pFillVertices; if (fSpread) { ox = -NumTri*2; oy = -NumTri*2; dox = 4; doy = 4; } else { ox = 0; oy = 0; dox = 0; doy = 0; } if (iOrder == FRONT_TO_BACK) { for (i = 0, z = (float)0.0; i < NumTri; i++, z -= (float)0.9 / NumTri) { SetTriangleVertices(pVert, z, w, h, (float)iTriangleArea, ox, oy); pVert += 3; ox += dox; oy += doy; } } else { for (i = 0, z = (float)-0.9; i < NumTri; i++, z += (float)0.9 / NumTri) { SetTriangleVertices(pVert, z, w, h, (float)iTriangleArea, ox, oy); pVert += 3; ox += dox; oy += doy; } } pTri = pFillTriangles; for (i = 0; i < NumTri; i++) { pTri->v1 = i*3; pTri->v2 = i*3+1; pTri->v3 = i*3+2; pTri++; } GetClientRect(auxGetHWND(), &rct); FillRect(auxGetHDC(), &rct, GetStockObject(BLACK_BRUSH)); } static __GLmatrix proj = { D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(-1.0), D3DVAL(0.0) }; static __GLmatrix view = { D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(7.0), D3DVAL(1.0) }; void SetTest(int iNew) { RECT rct; ModeChange(); iTest = iNew; switch(iTest) { case TEST_POLYS: glDisableClientState(GL_COLOR_ARRAY); glEnable(GL_LIGHTING); glEnable(GL_CULL_FACE); iTexMode = TEXMODE_REPLACE; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, eTexModes[iTexMode]); glMatrixMode(GL_PROJECTION); glLoadIdentity(); #if 0 gluPerspective(45, 1, .01, 15); gluLookAt(0, 0, 8, 0, 0, 0, 0, 1, 0); #else glLoadMatrixf((float *)&proj); glMultMatrixf((float *)&view); glDepthRange(1, 0); #endif glMatrixMode(GL_MODELVIEW); SetVertexArrayVertices(pPolyVertices); iSwapWidth = SPWIDTH; iSwapHeight = SPHEIGHT; glScissor((WIDTH-iSwapWidth)/2, (HEIGHT-iSwapHeight)/2, iSwapWidth, iSwapHeight); break; case TEST_FILL: glEnableClientState(GL_COLOR_ARRAY); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); iTexMode = TEXMODE_MODULATE; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, eTexModes[iTexMode]); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, WIDTH, 0, HEIGHT, 0.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); SetVertexArrayVertices(pFillVertices); SetFill(iFillSize, iOrder); break; } SetPrim(iPrimType); GetClientRect(auxGetHWND(), &rct); FillRect(auxGetHDC(), &rct, GetStockObject(BLACK_BRUSH)); } void Init(void) { float fv4[4]; int iPrim, iOldPrim; if (!GenerateSphere(SRADIUS, nRings, nSections, 1.0f, 1.0f, 1.0f, &pPolyVertices, &pPolyTriangles, &nNumVertices, &nNumFaces)) { printf("Unable to generate sphere data\n"); exit(1); } nStripIndices = CreateStrip(nSections, &pPolyStrip); InitSpheres(); InitFill(&pFillVertices, &pFillTriangles); fv4[0] = 0.05f; fv4[1] = 0.05f; fv4[2] = 0.05f; fv4[3] = 1.0f; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fv4); fv4[0] = 0.0f; fv4[1] = 1.0f; fv4[2] = 1.0f; fv4[3] = 0.0f; glLightfv(GL_LIGHT0, GL_POSITION, fv4); fv4[0] = 0.9f; fv4[1] = 0.9f; fv4[2] = 0.9f; fv4[3] = 1.0f; glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (!fSingleColor) { glEnableClientState(GL_COLOR_ARRAY); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); #ifdef TEXOBJ glGenTextures(1, &uiTexObj); glBindTexture(GL_TEXTURE_2D, uiTexObj); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_2D, 0, 3, pTexture->sizeX, pTexture->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexture->data); glEnable(GL_TEXTURE_2D); glDisable(GL_DITHER); #ifdef GL_EXT_clip_volume glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); #endif SetTest(iTest); glClear(GL_COLOR_BUFFER_BIT); if (fDisplayList) { iDlist = glGenLists(3); iOldPrim = iPrimType; for (iPrim = 0; iPrim < PRIM_COUNT; iPrim++) { SetPrim(iPrim); glNewList(iDlist+iPrim, GL_COMPILE); glDrawElements(ePrimTypes[iPrim], nIndices, GL_UNSIGNED_INT, pIndices); glEndList(); } SetPrim(iOldPrim); } } void Redraw(void) { DWORD ms; int i; Sphere *sp; float fv4[4]; int iv1[1]; int loop; __GLmatrix xform; ms = GetTickCount(); for (loop = 0; loop < iMultiLoop; loop++) { #if PROFILE if (loop > 0) { StartCAP(); } #endif if (fUseScissor) { glEnable(GL_SCISSOR_TEST); if (glAddSwapHintRectWIN != NULL) { glAddSwapHintRectWIN((WIDTH-iSwapWidth)/2, (HEIGHT-iSwapHeight)/2, iSwapWidth, iSwapHeight); } } if (glIsEnabled(GL_DEPTH_TEST)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else { glClear(GL_COLOR_BUFFER_BIT); } if (fUseScissor) { glDisable(GL_SCISSOR_TEST); } if (fSingleColor && iTest == TEST_POLYS) { fv4[0] = 1.0f; fv4[1] = 1.0f; fv4[2] = 1.0f; fv4[3] = 1.0f; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, fv4); } fv4[0] = 0.6f; fv4[1] = 0.6f; fv4[2] = 0.6f; fv4[3] = 1.0f; glMaterialfv(GL_FRONT, GL_SPECULAR, fv4); iv1[0] = 40; glMaterialiv(GL_FRONT, GL_SHININESS, iv1); switch(iTest) { case TEST_POLYS: sp = &spheres[0]; for (i = 0; i < NSPHERES; i++) { UpdateSphere(sp); // Always done to even out timings #if 1 __glMultMatrix(&xform, &sp->rot, &sp->pos); #else __glMultMatrix(&xform, &sp->pos, &sp->rot); #endif if (fBounce && fRotate) { glLoadMatrixf(&xform.matrix[0][0]); } else if (fRotate) { glLoadMatrixf(&sp->rot.matrix[0][0]); } else { glLoadMatrixf(&sp->pos.matrix[0][0]); } #if 1 glVertexPointer(3, GL_FLOAT, sizeof(D3DVERTEX), &pPolyVertices[0].x); glNormalPointer(GL_FLOAT, sizeof(D3DVERTEX), &pPolyVertices[0].nx); glTexCoordPointer(2, GL_FLOAT, sizeof(D3DVERTEX), &pPolyVertices[0].tu); fv4[0] = 1.0f; fv4[1] = 1.0f; fv4[2] = 1.0f; fv4[3] = 1.0f; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, fv4); fv4[0] = 0.6f; fv4[1] = 0.6f; fv4[2] = 0.6f; fv4[3] = 1.0f; glMaterialfv(GL_FRONT, GL_SPECULAR, fv4); iv1[0] = 40; glMaterialiv(GL_FRONT, GL_SHININESS, iv1); glBindTexture(GL_TEXTURE_2D, uiTexObj); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); glDepthRange(1, 0); glEnableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glEnable(GL_LIGHTING); #endif if (fDisplayList) { glCallList(iDlist+iPrimType); } else { glDrawElements(ePrimTypes[iPrimType], nIndices, GL_UNSIGNED_INT, pIndices); } sp++; } break; case TEST_FILL: glDrawElements(GL_TRIANGLES, nIndices, GL_UNSIGNED_INT, pIndices); break; } if (fSwap && !fSingle) { auxSwapBuffers(); } else { glFinish(); } } #ifdef PROFILE if (iMultiLoop > 1) { StopCAP(); } #endif ms = GetTickCount()-ms; total_ms += ms; total_tris += nTriangles*iMultiLoop; if (total_ms > 2000) { double val; switch(iTest) { case TEST_POLYS: val = (double)total_tris*1000.0/total_ms; if (val > peak_tri) { peak_tri = val; } avg_tri += val; break; case TEST_FILL: val = (double)iTriangleArea*total_tris*1000.0/total_ms; if (val > peak_fill) { peak_fill = val; } avg_fill += val; break; } avg_cnt++; if (fVerbose) { printf("%s, %s", pszPrimTypes[iPrimType], pszShadeModels[iShadeModel]); if (glIsEnabled(GL_CULL_FACE)) { printf(", cull"); } if (glIsEnabled(GL_LIGHTING)) { printf(", lit"); } if (glIsEnabled(GL_TEXTURE_2D)) { printf(", %s", pszTexModes[iTexMode]); } if (glIsEnabled(GL_DITHER)) { printf(", dither"); } if (glIsEnabled(GL_DEPTH_TEST)) { printf(", z"); } #ifdef GL_EXT_clip_volume glGetIntegerv(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, &iv1[0]); if (iv1[0] != GL_FASTEST) #endif { printf(", clip"); } if (fSwap) { printf(", swap"); } if (fRotate) { printf(", rotate"); } if (fBounce) { printf(", bounce"); } if (fPerspective) { printf(", persp"); } printf(", %d tri/frame\n", nTriangles); switch(iTest) { case TEST_POLYS: printf("%d ms, %d tri, %.3lf tri/sec, %.3lf peak, %.3lf avg\n", total_ms, total_tris, val, peak_tri, avg_tri/avg_cnt); break; case TEST_FILL: printf("%d ms, %s, area %d, %.3lf pix/sec, " "%.3lf peak, %.3lf avg\n", total_ms, pszOrders[iOrder], iTriangleArea, val, peak_fill, avg_fill/avg_cnt); break; } } else { char msg[80]; switch(iTest) { case TEST_POLYS: sprintf(msg, "%.3lf tri/sec, %.3lf peak, %.3lf avg", val, peak_tri, avg_tri/avg_cnt); break; case TEST_FILL: sprintf(msg, "%.3lf pix/sec, %.3lf peak, %.3lf avg", val, peak_fill, avg_fill/avg_cnt); break; } SetWindowText(auxGetHWND(), msg); } total_ms = 0; total_tris = 0; } } void Reshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); } void Step(void) { Redraw(); } void KeyB(void) { ModeChange(); fBounce = !fBounce; } void Keyc(void) { ModeChange(); if (glIsEnabled(GL_CULL_FACE)) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); } } void KeyC(void) { ModeChange(); fUseScissor = !fUseScissor; } void Keyh(void) { ModeChange(); if (glIsEnabled(GL_DITHER)) { glDisable(GL_DITHER); } else { glEnable(GL_DITHER); } } void Keyi(void) { iFillSize = (iFillSize+1) % AREA_COUNT; SetFill(iFillSize, iOrder); } void Keyl(void) { ModeChange(); if (glIsEnabled(GL_LIGHTING)) { glDisable(GL_LIGHTING); } else { glEnable(GL_LIGHTING); } } void Keym(void) { ModeChange(); iPolygonMode = (iPolygonMode+1) % POLYMODE_COUNT; glPolygonMode(GL_FRONT_AND_BACK, ePolygonModes[iPolygonMode]); } void Keyo(void) { iOrder = (iOrder+1) % ORDER_COUNT; SetFill(iFillSize, iOrder); } void Keyp(void) { ModeChange(); fPerspective = !fPerspective; glHint(GL_PERSPECTIVE_CORRECTION_HINT, fPerspective ? GL_NICEST : GL_FASTEST); } void KeyP(void) { #ifdef GL_EXT_clip_volume int iv1[1]; ModeChange(); glGetIntegerv(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, &iv1[0]); if (iv1[0] == GL_FASTEST) { glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_DONT_CARE); } else { glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); } #endif } void KeyR(void) { ModeChange(); fRotate = !fRotate; } void Keys(void) { ModeChange(); iShadeModel = (iShadeModel+1) % SMODEL_COUNT; glShadeModel(eShadeModels[iShadeModel]); } void KeyS(void) { fSpread = !fSpread; SetFill(iFillSize, iOrder); } void Keyt(void) { SetPrim((iPrimType+1) % PRIM_COUNT); } void KeyT(void) { iTest = (iTest+1) % TEST_COUNT; SetTest(iTest); } void Keyw(void) { ModeChange(); fSwap = !fSwap; } void Keyx(void) { ModeChange(); if (glIsEnabled(GL_TEXTURE_2D)) { glDisable(GL_TEXTURE_2D); } else { glEnable(GL_TEXTURE_2D); } } void KeyX(void) { ModeChange(); iTexMode = (iTexMode+1) % TEXMODE_COUNT; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, eTexModes[iTexMode]); } void Keyz(void) { ModeChange(); if (glIsEnabled(GL_DEPTH_TEST)) { glDisable(GL_DEPTH_TEST); } else { glEnable(GL_DEPTH_TEST); } } void KeySPACE(void) { fPaused = !fPaused; if (fPaused) { auxIdleFunc(NULL); } else { auxIdleFunc(Step); } } void __cdecl main(int argc, char **argv) { int mode; int wd, ht; char szWinDir[256]; int l; wd = WIDTH; ht = HEIGHT; while (--argc > 0) { argv++; if (!strcmp(*argv, "-sb")) { fSingle = TRUE; } else if (!strcmp(*argv, "-paused")) { fPaused = TRUE; } else if (!strcmp(*argv, "-exit")) { fExit = TRUE; } else if (!strcmp(*argv, "-cols")) { fSingleColor = FALSE; } else if (!strcmp(*argv, "-v")) { fVerbose = TRUE; } else if (!strcmp(*argv, "-nodlist")) { fDisplayList = FALSE; } else if (!strcmp(*argv, "-norotate")) { fRotate = FALSE; } else if (!strcmp(*argv, "-nobounce")) { fBounce = FALSE; } else if (!strcmp(*argv, "-noscissor")) { fUseScissor = FALSE; } else if (!strncmp(*argv, "-multi", 6)) { sscanf(*argv+6, "%d", &iMultiLoop); } else if (!strncmp(*argv, "-wd", 3)) { sscanf(*argv+3, "%d", &wd); } else if (!strncmp(*argv, "-ht", 3)) { sscanf(*argv+3, "%d", &ht); } else if (!strncmp(*argv, "-rings", 6)) { sscanf(*argv+6, "%d", &nRings); } else if (!strncmp(*argv, "-sections", 9)) { sscanf(*argv+9, "%d", &nSections); } else if (!strncmp(*argv, "-tst", 4)) { sscanf(*argv+4, "%d", &iTest); } else if (!strncmp(*argv, "-fsz", 4)) { sscanf(*argv+4, "%d", &iFillSize); } } auxInitPosition(10, 10, wd, ht); mode = AUX_RGB | AUX_DEPTH16; if (!fSingle) { mode |= AUX_DOUBLE; } auxInitDisplayMode(mode); auxInitWindow("DrawElements Performance Test"); auxReshapeFunc(Reshape); if (!fPaused) { auxIdleFunc(Step); } l = GetWindowsDirectory(szWinDir, sizeof(szWinDir)); if (l == 0) { printf("Unable to get windows directory\n"); exit(1); } strcpy(szWinDir+l, "\\cover8.bmp"); pTexture = auxDIBImageLoad(szWinDir); if (pTexture == NULL) { printf("Unable to load texture\n"); exit(1); } auxKeyFunc(AUX_B, KeyB); auxKeyFunc(AUX_c, Keyc); auxKeyFunc(AUX_C, KeyC); auxKeyFunc(AUX_h, Keyh); auxKeyFunc(AUX_i, Keyi); auxKeyFunc(AUX_l, Keyl); auxKeyFunc(AUX_m, Keym); auxKeyFunc(AUX_o, Keyo); auxKeyFunc(AUX_p, Keyp); auxKeyFunc(AUX_P, KeyP); auxKeyFunc(AUX_R, KeyR); auxKeyFunc(AUX_s, Keys); auxKeyFunc(AUX_S, KeyS); auxKeyFunc(AUX_t, Keyt); auxKeyFunc(AUX_T, KeyT); auxKeyFunc(AUX_w, Keyw); auxKeyFunc(AUX_x, Keyx); auxKeyFunc(AUX_X, KeyX); auxKeyFunc(AUX_z, Keyz); auxKeyFunc(AUX_SPACE, KeySPACE); SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); glAddSwapHintRectWIN = (PFNGLADDSWAPHINTRECTWINPROC) wglGetProcAddress("glAddSwapHintRectWIN"); #if 0 _controlfp((unsigned int) (~(_EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW)), _MCW_EM); #endif Init(); if (fExit) { Redraw(); } else { auxMainLoop(Redraw); } }