windows-nt/Source/XPSP1/NT/shell/osshell/control/scrnsave/flyingobjects/genlem.cpp
2020-09-26 16:20:57 +08:00

391 lines
10 KiB
C++

/******************************Module*Header*******************************\
* Module Name: genlem.c
*
* The Twist style of the 3D Flying Objects screen saver.
*
* Solid model of a 3D lemniscate.
*
* Copyright (c) 1994 Microsoft Corporation
*
\**************************************************************************/
#include <stdlib.h>
#include <windows.h>
//#include <GL\gl.h>
#include <string.h>
#include <math.h>
//#include "ss3dfo.h"
#include <d3dx8.h>
#include "D3DSaver.h"
#include "FlyingObjects.h"
#include "mesh.h"
#define ROT_PREC 10
#define NORMS(x, y) lemMesh.norms[((x) * iPrec) + y]
#define GRID(x, y) lemMesh.pts[((x) * iPrec) + y]
static MESH lemMesh;
static POINT3D basis[ROT_PREC];
static double zrot = 0.2;
static int iPrec = 32;
static double *lemX;
static double *lemY;
static double *lemXT;
static double *lemYT;
static void getLem(double index, double max, double *angle, double *r)
{
double a, sina;
a = (index * PI) / (max - 1.0);
if (a >= PI)
a -= PI;
if (a > PI / 2.0) {
*angle = (2.0 * PI) - a;
sina = sin( 2.0 * *angle );
if( sina < 0.0 )
sina = 0.0; // protect against sqrt fpe
*r = 0.5 * sqrt(sina);
} else {
*angle = a;
sina = sin( 2.0 * *angle );
if( sina < 0.0 )
sina = 0.0;
*r = 0.5 * sqrt(sina);
}
}
static void initLemCoords(int iMax)
{
int i;
double max = (double)iMax;
double angle;
double r;
for (i = 0; i < iMax; i++) {
getLem((double)i, (double)iPrec, &angle, &r);
lemX[i] = r * cos(angle);
lemY[i] = r * sin(angle);
getLem((double)i + 0.00001, (double)iPrec, &angle, &r);
lemXT[i] = r * cos(angle);
lemYT[i] = r * sin(angle);
}
}
void genLemniscate(void)
{
int i;
int j;
double posInc = 2.0 / (float)iPrec;
int facecount = 0;
int ptcount = 0;
POINT3D norm;
static float twistFact = 0.0f;
static float twistFactAdd = 0.05f;
POINT3D a[ROT_PREC];
POINT3D b[ROT_PREC];
MATRIX matrix;
MESH *mesh = &lemMesh;
mesh->numPoints = 0;
mesh->numFaces = 0;
for (i = 0; i < (iPrec - 1) * (ROT_PREC - 1); i++)
mesh->norms[i] = ss_ptZero;
for (i = 0; i < (iPrec - 1); i++) {
double x1, y1, x2, y2;
double len;
double sinAngle;
double rotZ;
int id[4];
x1 = lemX[i];
y1 = lemY[i];
x2 = lemXT[i];
y2 = lemYT[i];
x2 -= x1;
y2 -= y1;
len = sqrt(x2 * x2 + y2 * y2);
if (len > 0.0)
sinAngle = y2 / len;
else
sinAngle = 0.0;
if (y2 < 0.0)
sinAngle = -sinAngle;
rotZ = asin(sinAngle);
if (x2 < 0.0)
rotZ = PI - rotZ;
if (y2 < 0.0)
rotZ = -rotZ;
if (rotZ < 0.0)
rotZ = 2.0 * PI + rotZ;
ss_matrixIdent(&matrix);
ss_matrixRotate(&matrix, 0.0, 0.0, -rotZ);
ss_matrixTranslate(&matrix, x1, y1,
twistFact * cos((2.0 * PI * (float)i) / ((float)iPrec - 1)));
for (j = 0; j < ROT_PREC; j++)
ss_xformPoint(&a[j], &basis[j], &matrix);
x1 = lemX[i+1];
y1 = lemY[i+1];
x2 = lemXT[i+1];
y2 = lemYT[i+1];
x2 -= x1;
y2 -= y1;
len = sqrt(x2 * x2 + y2 * y2);
if (len > 0.0)
sinAngle = y2 / len;
else
sinAngle = 0.0;
if (y2 < 0.0)
sinAngle = -sinAngle;
rotZ = asin(sinAngle);
if (x2 < 0.0)
rotZ = PI - rotZ;
if (y2 < 0.0)
rotZ = -rotZ;
if (rotZ < 0.0)
rotZ = 2.0 * PI + rotZ;
ss_matrixIdent(&matrix);
ss_matrixRotate(&matrix, 0.0, 0.0, -rotZ);
ss_matrixTranslate(&matrix, x1, y1,
twistFact * cos((2.0 * PI * ((float)i + 1.0)) / ((float)iPrec - 1)));
for (j = 0; j < ROT_PREC; j++)
ss_xformPoint(&b[j], &basis[j], &matrix);
memcpy(&mesh->pts[ptcount], &a, sizeof(POINT3D) * (ROT_PREC - 1));
ptcount += (ROT_PREC - 1);
mesh->numPoints += (ROT_PREC - 1);
for (j = 0; j < (ROT_PREC - 1); j++) {
int k;
int jj;
if (j == (ROT_PREC - 2))
jj = 0;
else
jj = j + 1;
ss_calcNorm(&norm, &b[j + 1], &b[j], &a[j]);
mesh->faces[facecount].material = 3;
mesh->faces[facecount].norm = norm;
if (i == iPrec - 2) {
id[0] = mesh->faces[facecount].p[0] = j;
id[1] = mesh->faces[facecount].p[1] = jj;
} else {
id[0] = mesh->faces[facecount].p[0] = ptcount + j;
id[1] = mesh->faces[facecount].p[1] = ptcount + jj;
}
id[2] = mesh->faces[facecount].p[2] = ptcount - (ROT_PREC - 1) + j;
id[3] = mesh->faces[facecount].p[3] = ptcount - (ROT_PREC - 1) + jj;
for (k = 0; k < 4; k++) {
POINT3D *pn = &mesh->norms[id[k]];
pn->x += norm.x;
pn->y += norm.y;
pn->z += norm.z;
}
mesh->numFaces++;
facecount++;
}
}
ss_normalizeNorms(lemMesh.norms, lemMesh.numPoints);
if (twistFact >= 1.0f)
twistFactAdd = -0.01f;
else if (twistFact <= -1.0f)
twistFactAdd = 0.01f;
twistFact += twistFactAdd;
}
BOOL initLemScene()
{
int i;
RGBA lightAmbient = {0.0f, 0.0f, 0.0f, 1.0f};
iPrec = (int)(fTesselFact * 32.5);
if (iPrec < 5)
iPrec = 5;
lemX = (double*)SaverAlloc(sizeof(double) * iPrec);
if( lemX == NULL )
return FALSE;
lemY = (double*)SaverAlloc(sizeof(double) * iPrec);
if( lemY == NULL )
return FALSE;
lemXT = (double*)SaverAlloc(sizeof(double) * iPrec);
if( lemXT == NULL )
return FALSE;
lemYT = (double*)SaverAlloc(sizeof(double) * iPrec);
if( lemYT == NULL )
return FALSE;
/*
D3DXMATRIX matProj;
D3DXMatrixOrthoLH( &matProj, 3.0, 3.0, 0.0f, 3.0f );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
*/
SetProjectionMatrixInfo( TRUE, 3.0f, 3.0f, 0.0f, 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 );
if (!newMesh(&lemMesh, (ROT_PREC - 1) * (iPrec - 1) ,
(ROT_PREC - 1) * (iPrec - 1)) )
{
return FALSE;
}
for (i = 0; i < ROT_PREC; i++) {
basis[i].x = 0.0f;
basis[i].y = (float) (0.15 * cos((i * 2.0 * PI) / (ROT_PREC - 1.0)));
basis[i].z = (float) (0.15 * sin((i * 2.0 * PI) / (ROT_PREC - 1.0)));
}
initLemCoords(iPrec);
/*
glFrontFace(GL_CW);
glEnable(GL_CULL_FACE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (FLOAT *) &lightAmbient);
*/
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
(FLOAT *) &Material[3].Diffuse);
return TRUE;
}
void delLemScene()
{
delMesh(&lemMesh);
SaverFree(lemX);
SaverFree(lemY);
SaverFree(lemXT);
SaverFree(lemYT);
}
void updateLemScene(int flags, FLOAT fElapsedTime)
{
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 zrotInc = 0.1;
static double mzrotInc = 0.0;
RGBA color;
MATRIX model;
D3DXMATRIX mat1, mat2, mat3, mat4, mat5, matFinal;
static FLOAT fH = 0.0f;
FLOAT fTimeFactor = fElapsedTime * 20.0f;
if( fTimeFactor > 0.25f )
fTimeFactor = 0.25f;
mxrot += mxrotInc * fTimeFactor;
myrot += myrotInc * fTimeFactor;
mzrot += mzrotInc * fTimeFactor;
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;
}
zrot += zrotInc * fTimeFactor;
if (zrot >= PI / 4.0) {
zrot = PI / 4.0;
zrotInc = -0.03;
} else if (zrot <= -PI / 4.0) {
zrot = -PI / 4.0;
zrotInc = 0.03;
}
genLemniscate();
if (bColorCycle) {
ss_HsvToRgb(fH, 1.0f, 1.0f, &color );
myglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (FLOAT *) &color);
fH += fTimeFactor;
if( fH >= 360.0f )
fH -= 360.0f;
}
/*
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.5, 1.5, -1.5, 1.5, 0.0, 3.0);
glTranslatef(0.0f, 0.0f, -1.5f);
*/
/*
glRotatef((FLOAT) (zrot * (180.0 / PI)), 0.0f, 1.0f, 0.0f);
glRotatef(50.0f, 1.0f, 0.0f, 0.0f);
glRotatef(50.0f, 0.0f, 0.0f, 1.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 );
/*
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, -0.5f, 0.0f);
glRotatef((FLOAT) (mxrot * (180.0 / PI)), 1.0f, 0.0f, 0.0f);
glRotatef((FLOAT) (myrot * (180.0 / PI)), 0.0f, 1.0f, 0.0f);
glRotatef((FLOAT) (mzrot * (180.0 / PI)), 0.0f, 0.0f, 1.0f);
*/
D3DXMatrixTranslation(&mat1, 0.0f, -0.5f, 0.0f);
D3DXMatrixRotationX(&mat2, D3DXToRadian((FLOAT)(mxrot * (180.0 / PI))));
D3DXMatrixRotationY(&mat3, D3DXToRadian((FLOAT)(myrot * (180.0 / PI))));
D3DXMatrixRotationZ(&mat4, D3DXToRadian((FLOAT)(mzrot * (180.0 / PI))));
matFinal = mat4 * mat3 * mat2 * mat1 ;
m_pd3dDevice->SetTransform( D3DTS_WORLD , &matFinal );
ss_matrixIdent(&model);
ss_matrixRotate(&model, mxrot, myrot, mzrot);
ss_matrixTranslate(&model, 0.0, -0.5, 0.0);
// updateObject(&lemMesh, bSmoothShading);
RenderMesh3(&lemMesh, bSmoothShading);
}