/******************************Module*Header*******************************\ * Module Name: genexpld.c * * The Explode style of the 3D Flying Objects screen saver. * * Simulation of a sphere that occasionally explodes. * * Copyright (c) 1994 Microsoft Corporation * \**************************************************************************/ #include #include #include #include #include #include "ss3dfo.h" #define RADIUS 0.3 #define STEPS 30 #define MAXPREC 20 static MATRIX *faceMat; static float *xstep; static float *ystep; static float *zstep; static float *xrot; static float *yrot; static float *zrot; static MESH explodeMesh; static int iPrec = 10; static BOOL bOpenGL11; // Data type accepted by glInterleavedArrays typedef struct _POINT_N3F_V3F { POINT3D normal; POINT3D vertex; } POINT_N3F_V3F; static POINT_N3F_V3F *pN3V3; static GLfloat matl1Diffuse[] = {1.0f, 0.8f, 0.0f, 1.0f}; static GLfloat matl2Diffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; static GLfloat matlSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f}; static GLfloat light0Pos[] = {100.0f, 100.0f, 100.0f, 0.0f}; void genExplode() { int i; POINT3D circle[MAXPREC+1]; double angle; double step = -PI / (float)(iPrec - 1); double start = PI / 2.0; for (i = 0, angle = start; i < iPrec; i++, angle += step) { circle[i].x = (float) (RADIUS * cos(angle)); circle[i].y = (float) (RADIUS * sin(angle)); circle[i].z = 0.0f; } revolveSurface(&explodeMesh, circle, iPrec); for (i = 0; i < explodeMesh.numFaces; i++) { ss_matrixIdent(&faceMat[i]); xstep[i] = (float)(((float)(rand() & 0x3) * PI) / ((float)STEPS + 1.0)); ystep[i] = (float)(((float)(rand() & 0x3) * PI) / ((float)STEPS + 1.0)); zstep[i] = (float)(((float)(rand() & 0x3) * PI) / ((float)STEPS + 1.0)); xrot[i] = 0.0f; yrot[i] = 0.0f; zrot[i] = 0.0f; } } void initExplodeScene() { iPrec = (int)(fTesselFact * 10.5); if (iPrec < 5) iPrec = 5; if (iPrec > MAXPREC) iPrec = MAXPREC; faceMat = (MATRIX *)SaverAlloc((iPrec * iPrec) * (4 * 4 * sizeof(float))); xstep = SaverAlloc(iPrec * iPrec * sizeof(float)); ystep = SaverAlloc(iPrec * iPrec * sizeof(float)); zstep = SaverAlloc(iPrec * iPrec * sizeof(float)); xrot = SaverAlloc(iPrec * iPrec * sizeof(float)); yrot = SaverAlloc(iPrec * iPrec * sizeof(float)); zrot = SaverAlloc(iPrec * iPrec * sizeof(float)); genExplode(); // Find out the OpenGL version that we are running on. bOpenGL11 = ss_fOnGL11(); // Setup the data arrays. pN3V3 = SaverAlloc(explodeMesh.numFaces * 4 * sizeof(POINT_N3F_V3F)); // If we are running on OpenGL 1.1, use the new vertex array functions. if (bOpenGL11) { glInterleavedArrays(GL_N3F_V3F, 0, pN3V3); } glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matl1Diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, matlSpecular); glMaterialf(GL_FRONT, GL_SHININESS, 100.0f); glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, matl2Diffuse); glMaterialfv(GL_BACK, GL_SPECULAR, matlSpecular); glMaterialf(GL_BACK, GL_SHININESS, 60.0f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-0.33, 0.33, -0.33, 0.33, 0.3, 3.0); glTranslatef(0.0f, 0.0f, -1.5f); } void delExplodeScene() { delMesh(&explodeMesh); SaverFree(faceMat); SaverFree(xstep); SaverFree(ystep); SaverFree(zstep); SaverFree(xrot); SaverFree(yrot); SaverFree(zrot); SaverFree(pN3V3); } void updateExplodeScene(int flags) { static double mxrot = 0.0; static double myrot = 0.0; static double mzrot = 0.0; static double mxrotInc = 0.0; static double myrotInc = 0.1; static double mzrotInc = 0.0; static float maxR; static float r = 0.0f; static float rotZ = 0.0f; static int count = 0; static int direction = 1; static int restCount = 0; static float lightSpin = 0.0f; static float spinDelta = 5.0f; static int h = 0; static RGBA color; int i; MFACE *faces; POINT_N3F_V3F *pn3v3; if( gbBounce ) { // floating window bounced off an edge if (mxrotInc) { mxrotInc = 0.0; myrotInc = 0.1; } else if (myrotInc) { myrotInc = 0.0; mzrotInc = 0.1; } else if (mzrotInc) { mzrotInc = 0.0; mxrotInc = 0.1; } gbBounce = FALSE; } mxrot += mxrotInc; myrot += myrotInc; mzrot += mzrotInc; if (bColorCycle || h == 0) { ss_HsvToRgb((float)h, 1.0f, 1.0f, &color); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, (GLfloat *) &color); h++; h %= 360; } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glRotatef(-lightSpin, 0.0f, 1.0f, 0.0f); glLightfv(GL_LIGHT0, GL_POSITION, light0Pos); lightSpin += spinDelta; if ((lightSpin > 90.0) || (lightSpin < 0.0)) spinDelta = -spinDelta; glPopMatrix(); if (!bOpenGL11) { glBegin(GL_QUADS); } for( i = 0, faces = explodeMesh.faces, pn3v3 = pN3V3; i < explodeMesh.numFaces; i++, faces++, pn3v3 += 4 ) { int a, b, c, d; int j; POINT3D vector; ss_matrixIdent(&faceMat[i]); ss_matrixRotate(&faceMat[i], xrot[i], yrot[i], zrot[i]); if (restCount) ; else { xrot[i] += (xstep[i]); yrot[i] += (ystep[i]); zrot[i] += (zstep[i]); } a = faces->p[0]; b = faces->p[1]; c = faces->p[3]; d = faces->p[2]; memcpy(&pn3v3[0].vertex, (explodeMesh.pts + a), sizeof(POINT3D)); memcpy(&pn3v3[1].vertex, (explodeMesh.pts + b), sizeof(POINT3D)); memcpy(&pn3v3[2].vertex, (explodeMesh.pts + c), sizeof(POINT3D)); memcpy(&pn3v3[3].vertex, (explodeMesh.pts + d), sizeof(POINT3D)); vector.x = pn3v3[0].vertex.x; vector.y = pn3v3[0].vertex.y; vector.z = pn3v3[0].vertex.z; for (j = 0; j < 4; j++) { pn3v3[j].vertex.x -= vector.x; pn3v3[j].vertex.y -= vector.y; pn3v3[j].vertex.z -= vector.z; ss_xformPoint((POINT3D *)&pn3v3[j].vertex, (POINT3D *)&pn3v3[j].vertex, &faceMat[i]); pn3v3[j].vertex.x += vector.x + (vector.x * r); pn3v3[j].vertex.y += vector.y + (vector.y * r); pn3v3[j].vertex.z += vector.z + (vector.z * r); } if (bSmoothShading) { memcpy(&pn3v3[0].normal, (explodeMesh.norms + a), sizeof(POINT3D)); memcpy(&pn3v3[1].normal, (explodeMesh.norms + b), sizeof(POINT3D)); memcpy(&pn3v3[2].normal, (explodeMesh.norms + c), sizeof(POINT3D)); memcpy(&pn3v3[3].normal, (explodeMesh.norms + d), sizeof(POINT3D)); for (j = 0; j < 4; j++) ss_xformNorm((POINT3D *)&pn3v3[j].normal, (POINT3D *)&pn3v3[j].normal, &faceMat[i]); } else { memcpy(&pn3v3[0].normal, &faces->norm, sizeof(POINT3D)); ss_xformNorm((POINT3D *)&pn3v3[0].normal, (POINT3D *)&pn3v3[0].normal, &faceMat[i]); memcpy(&pn3v3[1].normal, &pn3v3[0].normal, sizeof(POINT3D)); memcpy(&pn3v3[2].normal, &pn3v3[0].normal, sizeof(POINT3D)); memcpy(&pn3v3[3].normal, &pn3v3[0].normal, sizeof(POINT3D)); } if (!bOpenGL11) { if (bSmoothShading) { glNormal3fv((GLfloat *)&pn3v3[0].normal); glVertex3fv((GLfloat *)&pn3v3[0].vertex); glNormal3fv((GLfloat *)&pn3v3[1].normal); glVertex3fv((GLfloat *)&pn3v3[1].vertex); glNormal3fv((GLfloat *)&pn3v3[2].normal); glVertex3fv((GLfloat *)&pn3v3[2].vertex); glNormal3fv((GLfloat *)&pn3v3[3].normal); glVertex3fv((GLfloat *)&pn3v3[3].vertex); } else { glNormal3fv((GLfloat *)&pn3v3[0].normal); glVertex3fv((GLfloat *)&pn3v3[0].vertex); glVertex3fv((GLfloat *)&pn3v3[1].vertex); glVertex3fv((GLfloat *)&pn3v3[2].vertex); glVertex3fv((GLfloat *)&pn3v3[3].vertex); } } } if (bOpenGL11) { glDrawArrays(GL_QUADS, 0, explodeMesh.numFaces * 4); } else { glEnd(); } if (restCount) { restCount--; goto resting; } if (direction) { maxR = r; r += (float) (0.3 * pow((double)(STEPS - count) / (double)STEPS, 4.0)); } else { r -= (float) (maxR / (double)(STEPS)); } count++; if (count > STEPS) { direction ^= 1; count = 0; if (direction == 1) { restCount = 10; r = 0.0f; for (i = 0; i < explodeMesh.numFaces; i++) { ss_matrixIdent(&faceMat[i]); xstep[i] = (float) (((float)(rand() & 0x3) * PI) / ((float)STEPS + 1.0)); ystep[i] = (float) (((float)(rand() & 0x3) * PI) / ((float)STEPS + 1.0)); zstep[i] = (float) (((float)(rand() & 0x3) * PI) / ((float)STEPS + 1.0)); xrot[i] = 0.0f; yrot[i] = 0.0f; zrot[i] = 0.0f; } } } resting: ; }