mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
470 lines
10 KiB
470 lines
10 KiB
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <windows.h>
|
|
#include <gl\gl.h>
|
|
#include <gl\glu.h>
|
|
#include <gl\glaux.h>
|
|
|
|
#define PI ((float)3.14159265358979323846)
|
|
|
|
#define WIDTH 512
|
|
#define HEIGHT 512
|
|
|
|
#define COMPUTE_SPHERE_VERTICES(rings, sections) \
|
|
(((rings)+1)*(sections)+2)
|
|
#define COMPUTE_SPHERE_TRIANGLES(rings, sections) \
|
|
(((rings)+1)*(sections)*2)
|
|
#define RINGS 50
|
|
#define SECTIONS 50
|
|
#define SVERTICES COMPUTE_SPHERE_VERTICES(RINGS, SECTIONS)
|
|
#define STRIANGLES COMPUTE_SPHERE_TRIANGLES(RINGS, SECTIONS)
|
|
|
|
#define RGB_COLOR(red, green, blue) \
|
|
(((DWORD)(BYTE)(red) << 0) | \
|
|
((DWORD)(BYTE)(green) << 8) | \
|
|
((DWORD)(BYTE)(blue) << 16))
|
|
|
|
#define FRANDOM(x) (((float)rand() / RAND_MAX) * (x))
|
|
|
|
#define DROT 10.0f
|
|
|
|
#define NLISTS 3
|
|
|
|
typedef struct
|
|
{
|
|
float fX, fY, fZ;
|
|
float fNx, fNy, fNz;
|
|
DWORD dwColor;
|
|
} VERTEX;
|
|
|
|
typedef struct
|
|
{
|
|
int iV1;
|
|
int iV2;
|
|
int iV3;
|
|
} TRIANGLE;
|
|
|
|
typedef struct _SPHERE
|
|
{
|
|
GLfloat fXr, fYr, fZr;
|
|
GLfloat fDXr, fDYr, fDZr;
|
|
} SPHERE;
|
|
|
|
SPHERE sphere;
|
|
|
|
BOOL fSingle = FALSE;
|
|
BOOL fDisplayList = TRUE;
|
|
|
|
int iCurrentType = 0;
|
|
GLint dlLists[NLISTS];
|
|
char *pszListType[NLISTS] =
|
|
{
|
|
"Vertex Array", "Direct Triangles", "Direct Strips"
|
|
};
|
|
|
|
void DrawVertexArray(void);
|
|
void DrawTriangles(void);
|
|
void DrawStrips(void);
|
|
void (*pfnDraw[NLISTS])(void) =
|
|
{
|
|
DrawVertexArray, DrawTriangles, DrawStrips
|
|
};
|
|
|
|
VERTEX vtxSphere[SVERTICES];
|
|
TRIANGLE triSphere[STRIANGLES];
|
|
|
|
void *Malloc(size_t cb)
|
|
{
|
|
void *pv;
|
|
|
|
pv = malloc(cb);
|
|
if (pv == NULL)
|
|
{
|
|
printf("Unable to alloc %d bytes\n", cb);
|
|
exit(1);
|
|
}
|
|
return pv;
|
|
}
|
|
|
|
void GenerateSphere(float fRadius, int iRings, int iSections,
|
|
VERTEX *pvtx, TRIANGLE *ptri)
|
|
{
|
|
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 */
|
|
int iVert, iTri; /* Internal vertex and triangle count */
|
|
|
|
iTri = COMPUTE_SPHERE_TRIANGLES(iRings, iSections);
|
|
iVert = COMPUTE_SPHERE_VERTICES(iRings, iSections);
|
|
|
|
/*
|
|
* 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 = RGB_COLOR(0, 0, 255);
|
|
pvtx[iVert - 1].fX = 0.0f;
|
|
pvtx[iVert - 1].fY = -fRadius;
|
|
pvtx[iVert - 1].fZ = 0.0f;
|
|
pvtx[iVert - 1].fNx = 0.0f;
|
|
pvtx[iVert - 1].fNy = -1.0f;
|
|
pvtx[iVert - 1].fNz = 0.0f;
|
|
pvtx[iVert - 1].dwColor = RGB_COLOR(0, 255, 0);
|
|
|
|
/*
|
|
* Generate vertex points for rings
|
|
*/
|
|
fDTheta = PI / (float) (iRings + 2);
|
|
fDPhi = 2.0f * PI / (float) iSections;
|
|
n = 1; /* vertex being generated, begins at 1 to skip top point */
|
|
fTheta = fDTheta;
|
|
|
|
for (i = 0; i <= iRings; 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 < iSections; 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 = RGB_COLOR(0, 0, 255);
|
|
}
|
|
else
|
|
{
|
|
pvtx[n].dwColor = RGB_COLOR(0, 255, 0);
|
|
}
|
|
fPhi += fDPhi;
|
|
n++;
|
|
}
|
|
|
|
fTheta += fDTheta;
|
|
}
|
|
|
|
/*
|
|
* Generate triangles for top and bottom caps.
|
|
*/
|
|
for (i = 0; i < iSections; i++)
|
|
{
|
|
ptri[i].iV1 = 0;
|
|
ptri[i].iV2 = i + 1;
|
|
ptri[i].iV3 = 1 + ((i + 1) % iSections);
|
|
ptri[iTri - iSections + i].iV1 = iVert - 1;
|
|
ptri[iTri - iSections + i].iV2 = iVert - 2 - i;
|
|
ptri[iTri - iSections + i].iV3 = iVert - 2 - ((1 + i) % iSections);
|
|
}
|
|
|
|
/*
|
|
* Generate triangles for the rings
|
|
*/
|
|
m = 1; /* first vertex in current ring,begins at 1 to skip top point*/
|
|
n = iSections; /* triangle being generated, skip the top cap */
|
|
|
|
for (i = 0; i < iRings; i++)
|
|
{
|
|
for (j = 0; j < iSections; j++)
|
|
{
|
|
ptri[n].iV1 = m + j;
|
|
ptri[n].iV2 = m + iSections + j;
|
|
ptri[n].iV3 = m + iSections + ((j + 1) % iSections);
|
|
ptri[n + 1].iV1 = ptri[n].iV1;
|
|
ptri[n + 1].iV2 = ptri[n].iV3;
|
|
ptri[n + 1].iV3 = m + ((j + 1) % iSections);
|
|
n += 2;
|
|
}
|
|
|
|
m += iSections;
|
|
}
|
|
}
|
|
|
|
void InitSphere(void)
|
|
{
|
|
GenerateSphere(1.0f, RINGS, SECTIONS, vtxSphere, triSphere);
|
|
|
|
glVertexPointer(3, GL_FLOAT, sizeof(VERTEX), &vtxSphere[0].fX);
|
|
glNormalPointer(GL_FLOAT, sizeof(VERTEX), &vtxSphere[0].fNx);
|
|
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VERTEX), &vtxSphere[0].dwColor);
|
|
|
|
srand(time(NULL));
|
|
sphere.fXr = 0.0f;
|
|
sphere.fYr = 0.0f;
|
|
sphere.fZr = 0.0f;
|
|
sphere.fDXr = DROT - FRANDOM(2 * DROT);
|
|
sphere.fDYr = DROT - FRANDOM(2 * DROT);
|
|
sphere.fDZr = DROT - FRANDOM(2 * DROT);
|
|
}
|
|
|
|
void UpdateSphere(void)
|
|
{
|
|
sphere.fXr += sphere.fDXr;
|
|
sphere.fYr += sphere.fDYr;
|
|
sphere.fZr += sphere.fDZr;
|
|
}
|
|
|
|
void DrawVertexArray(void)
|
|
{
|
|
glDrawElements(GL_TRIANGLES, STRIANGLES*3, GL_UNSIGNED_INT, triSphere);
|
|
}
|
|
|
|
void Vertex(int iVert)
|
|
{
|
|
VERTEX *pvtx;
|
|
|
|
pvtx = &vtxSphere[iVert];
|
|
glColor3ubv((GLubyte *)&pvtx->dwColor);
|
|
glNormal3fv(&pvtx->fNx);
|
|
glVertex3fv(&pvtx->fX);
|
|
}
|
|
|
|
void DrawTriangles(void)
|
|
{
|
|
int iVert, *pidx;
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
pidx = (int *)&triSphere[0];
|
|
for (iVert = 0; iVert < STRIANGLES*3; iVert++)
|
|
{
|
|
Vertex(*pidx++);
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
void DrawStrips(void)
|
|
{
|
|
int iIdxBase;
|
|
int iRing, iSection;
|
|
|
|
// Triangle fans for top and bottom caps
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
|
|
Vertex(0);
|
|
iIdxBase = 1;
|
|
for (iSection = 0; iSection <= SECTIONS; iSection++)
|
|
{
|
|
Vertex(iIdxBase+(iSection % SECTIONS));
|
|
}
|
|
|
|
glEnd();
|
|
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
|
|
Vertex(SVERTICES-1);
|
|
iIdxBase = SVERTICES-SECTIONS-1;
|
|
for (iSection = SECTIONS; iSection >= 0 ; iSection--)
|
|
{
|
|
Vertex(iIdxBase+(iSection % SECTIONS));
|
|
}
|
|
|
|
glEnd();
|
|
|
|
// Triangle strips for each ring
|
|
iIdxBase = 1;
|
|
for (iRing = 0; iRing < RINGS; iRing++)
|
|
{
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
|
|
for (iSection = 0; iSection <= SECTIONS; iSection++)
|
|
{
|
|
Vertex(iIdxBase+(iSection % SECTIONS));
|
|
Vertex(iIdxBase+(iSection % SECTIONS)+SECTIONS);
|
|
}
|
|
|
|
glEnd();
|
|
|
|
iIdxBase += SECTIONS;
|
|
}
|
|
}
|
|
|
|
void Init(void)
|
|
{
|
|
float fv4[4];
|
|
int iv1[1];
|
|
int i;
|
|
GLint dlBase;
|
|
|
|
InitSphere();
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(45, 1, .01, 15);
|
|
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
dlBase = glGenLists(NLISTS);
|
|
for (i = 0; i < NLISTS; i++)
|
|
{
|
|
dlLists[i] = dlBase+i;
|
|
glNewList(dlLists[i], GL_COMPILE);
|
|
pfnDraw[i]();
|
|
glEndList();
|
|
}
|
|
}
|
|
|
|
DWORD dwTotalMillis = 0;
|
|
int iTotalTriangles = 0;
|
|
|
|
void ResetTotals(void)
|
|
{
|
|
dwTotalMillis = 0;
|
|
iTotalTriangles = 0;
|
|
}
|
|
|
|
void Redraw(void)
|
|
{
|
|
DWORD dwMillis;
|
|
char szMsg[80];
|
|
|
|
dwMillis = GetTickCount();
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glLoadIdentity();
|
|
glRotatef(sphere.fXr, 1.0f, 0.0f, 0.0f);
|
|
glRotatef(sphere.fYr, 0.0f, 1.0f, 0.0f);
|
|
glRotatef(sphere.fZr, 0.0f, 0.0f, 1.0f);
|
|
|
|
if (fDisplayList)
|
|
{
|
|
glCallList(dlLists[iCurrentType]);
|
|
}
|
|
else
|
|
{
|
|
pfnDraw[iCurrentType]();
|
|
}
|
|
|
|
UpdateSphere();
|
|
|
|
if (fSingle)
|
|
{
|
|
glFlush();
|
|
}
|
|
else
|
|
{
|
|
auxSwapBuffers();
|
|
}
|
|
|
|
dwMillis = GetTickCount()-dwMillis;
|
|
|
|
dwTotalMillis += dwMillis;
|
|
iTotalTriangles += STRIANGLES;
|
|
|
|
if (dwTotalMillis > 1000)
|
|
{
|
|
sprintf(szMsg, "%s%s: %.3lf tri/sec",
|
|
fDisplayList ? "Display List " : "",
|
|
pszListType[iCurrentType],
|
|
(double)iTotalTriangles*1000.0/dwTotalMillis);
|
|
SetWindowText(auxGetHWND(), szMsg);
|
|
|
|
ResetTotals();
|
|
}
|
|
}
|
|
|
|
void Reshape(GLsizei w, GLsizei h)
|
|
{
|
|
glViewport(0, 0, w, h);
|
|
}
|
|
|
|
void Keyd(void)
|
|
{
|
|
fDisplayList = !fDisplayList;
|
|
ResetTotals();
|
|
}
|
|
|
|
void KeySPACE(void)
|
|
{
|
|
iCurrentType = (iCurrentType+1) % NLISTS;
|
|
ResetTotals();
|
|
}
|
|
|
|
void _CRTAPI1 main(int argc, char **argv)
|
|
{
|
|
GLenum eMode;
|
|
|
|
while (--argc > 0)
|
|
{
|
|
argv++;
|
|
|
|
if (!strcmp(*argv, "-sb"))
|
|
{
|
|
fSingle = TRUE;
|
|
}
|
|
else if (!strcmp(*argv, "-nodlist"))
|
|
{
|
|
fDisplayList = FALSE;
|
|
}
|
|
}
|
|
|
|
auxInitPosition(10, 10, WIDTH, HEIGHT);
|
|
eMode = AUX_RGB;
|
|
if (!fSingle)
|
|
{
|
|
eMode |= AUX_DOUBLE;
|
|
}
|
|
auxInitDisplayMode(eMode);
|
|
auxInitWindow("Vertex Array/Direct Comparison");
|
|
|
|
auxReshapeFunc(Reshape);
|
|
auxIdleFunc(Redraw);
|
|
|
|
auxKeyFunc(AUX_d, Keyd);
|
|
auxKeyFunc(AUX_SPACE, KeySPACE);
|
|
|
|
Init();
|
|
auxMainLoop(Redraw);
|
|
}
|