windows-nt/Source/XPSP1/NT/shell/osshell/control/scrnsave/flyingobjects/genexpld.cpp

381 lines
11 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************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 <windows.h>
#include <math.h>
#include <d3dx8.h>
#include "D3DSaver.h"
#include "FlyingObjects.h"
#include "mesh.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;
// Data type accepted by glInterleavedArrays
typedef struct _POINT_N3F_V3F {
POINT3D normal;
POINT3D vertex;
} POINT_N3F_V3F;
static POINT_N3F_V3F *pN3V3;
static FLOAT matl1Diffuse[] = {1.0f, 0.8f, 0.0f, 1.0f};
static FLOAT matl2Diffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
static FLOAT matlSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f};
static FLOAT 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;
}
}
BOOL 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)));
if( faceMat == NULL )
return FALSE;
xstep = (float*)SaverAlloc(iPrec * iPrec * sizeof(float));
if( xstep == NULL )
return FALSE;
ystep = (float*)SaverAlloc(iPrec * iPrec * sizeof(float));
if( ystep == NULL )
return FALSE;
zstep = (float*)SaverAlloc(iPrec * iPrec * sizeof(float));
if( zstep == NULL )
return FALSE;
xrot = (float*)SaverAlloc(iPrec * iPrec * sizeof(float));
if( xrot == NULL )
return FALSE;
yrot = (float*)SaverAlloc(iPrec * iPrec * sizeof(float));
if( yrot == NULL )
return FALSE;
zrot = (float*)SaverAlloc(iPrec * iPrec * sizeof(float));
if( zrot == NULL )
return FALSE;
genExplode();
/*
// Find out the OpenGL version that we are running on.
bOpenGL11 = ss_fOnGL11();
*/
// Setup the data arrays.
pN3V3 = (POINT_N3F_V3F*)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);
}
*/
myglMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matl1Diffuse);
myglMaterialfv(GL_FRONT, GL_SPECULAR, matlSpecular);
myglMaterialf(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);
*/
/*
D3DXMATRIX matProj;
D3DXMatrixPerspectiveLH( &matProj, 0.66f, 0.66f, 0.3f, 3.0f );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
*/
SetProjectionMatrixInfo( FALSE, 0.66f, 0.66f, 0.3f, 3.0f );
D3DXMATRIX matView;
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
D3DXVECTOR3 vEyePt(0, 0, 1.5f);
D3DXVECTOR3 vLookatPt(0, 0, 0);
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
return TRUE;
}
void delExplodeScene()
{
delMesh(&explodeMesh);
SaverFree(faceMat);
SaverFree(xstep);
SaverFree(ystep);
SaverFree(zstep);
SaverFree(xrot);
SaverFree(yrot);
SaverFree(zrot);
SaverFree(pN3V3);
}
void updateExplodeScene(int flags, FLOAT fElapsedTime)
{
static float maxR;
static float r = 0.0f;
static float rChange = 0.0f;
static float rChangePrev = 1.0f;
static float rotZ = 0.0f;
static int count = 0;
static float fCount = 0.0f;
static int direction = 1;
static FLOAT fRestCount = 0.0f;
static float lightSpin = 0.0f;
static float spinDelta = 5.0f;
static FLOAT fH = 0.0f;
static RGBA color;
if( fElapsedTime > 0.25f )
fElapsedTime = 0.25f;
FLOAT fTimeFactor = fElapsedTime * 20.0f;
int i;
MFACE *faces;
POINT_N3F_V3F *pn3v3;
D3DXMATRIX mat1, mat2, mat3, mat4, mat5, matFinal;
static FLOAT fTimer = 0.0f;
/*
// Only update 50x per second
fTimer += fElapsedTime;
if( fTimer < 1.0f/50.0f )
return;
fTimer = 0.0f;
*/
if (bColorCycle || fH == 0.0f)
{
ss_HsvToRgb(fH, 1.0f, 1.0f, &color);
myglMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, (FLOAT *) &color);
fH += fTimeFactor;
if( fH >= 360.0f )
fH -= 360.0f;
}
/*
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glRotatef(-lightSpin, 0.0f, 1.0f, 0.0f);
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
lightSpin += spinDelta * fTimeFactor;
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 (fRestCount > 0.0f)
;
else {
xrot[i] += (xstep[i]) * fTimeFactor;
yrot[i] += (ystep[i]) * fTimeFactor;
zrot[i] += (zstep[i]) * fTimeFactor;
}
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));
}
}
{
m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX );
static WORD s_indexArray[5000];
static MYVERTEX s_vertexArray[5000];
INT numPrims = 0;
INT numIndices = 0;
INT numVertices = 0;
WORD iVertexA, iVertexB, iVertexC, iVertexD;
INT a,b,c,d;
HRESULT hr;
for( int iFace = 0; iFace < explodeMesh.numFaces; iFace++ )
{
a = iFace * 4 + 0;
b = iFace * 4 + 1;
c = iFace * 4 + 2;
d = iFace * 4 + 3;
s_vertexArray[numVertices].p = pN3V3[a].vertex;
s_vertexArray[numVertices].n = pN3V3[a].normal;
iVertexA = numVertices++;
s_vertexArray[numVertices].p = pN3V3[b].vertex;
s_vertexArray[numVertices].n = pN3V3[b].normal;
iVertexB = numVertices++;
s_vertexArray[numVertices].p = pN3V3[c].vertex;
s_vertexArray[numVertices].n = pN3V3[c].normal;
iVertexC = numVertices++;
s_vertexArray[numVertices].p = pN3V3[d].vertex;
s_vertexArray[numVertices].n = pN3V3[d].normal;
iVertexD = numVertices++;
s_indexArray[numIndices++] = iVertexA;
s_indexArray[numIndices++] = iVertexB;
s_indexArray[numIndices++] = iVertexC;
numPrims++;
s_indexArray[numIndices++] = iVertexA;
s_indexArray[numIndices++] = iVertexC;
s_indexArray[numIndices++] = iVertexD;
numPrims++;
}
hr = m_pd3dDevice->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, 0, numVertices,
numPrims, s_indexArray, D3DFMT_INDEX16, s_vertexArray, sizeof(MYVERTEX) );
}
/*
if (bOpenGL11) {
glDrawArrays(GL_QUADS, 0, explodeMesh.numFaces * 4);
} else {
glEnd();
}
*/
if (fRestCount > 0.0f) {
fRestCount -= fTimeFactor;
goto resting;
}
rChange += fTimeFactor;
while( (INT)rChangePrev < (INT)rChange )
{
rChangePrev += 1.0;
if (direction) {
maxR = r;
r += (float) (0.3 * pow((double)(STEPS - count) / (double)STEPS, 4.0));
} else {
r -= (float) (maxR / (double)(STEPS));
}
}
fCount += fTimeFactor;
count = (INT)fCount;
if (count > STEPS) {
direction ^= 1;
count = 0;
fCount = 0.0f;
if (direction == 1) {
fRestCount = 10.0f;
r = 0.0f;
rChange = 0.0f;
rChangePrev = 1.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:
;
}