windows-nt/Source/XPSP1/NT/multimedia/opengl/test/misc/membrane/wave.cxx
2020-09-26 16:20:57 +08:00

294 lines
8.2 KiB
C++

/*
* (c) copyright 1993, silicon graphics, inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "wave.hxx"
#define PI 3.14159265358979323846f
#define GETWCOORD(frame, x, y) (&(mesh.coords[frame*mesh.numCoords+(x)+(y)*(iWidthX+1)]))
#define GETFACET(frame, x, y) (&(mesh.facets[frame*mesh.numFacets+(x)+(y)*iWidthX]))
#ifndef cosf
#define cosf( x ) \
( (float) cos( (x) ) )
#define sinf( x ) \
( (float) sin( (x) ) )
#endif
#ifndef sqrtf
#define sqrtf( x ) \
( (float) sqrt( (x) ) )
#endif
/******************** WAVE *************************************************
*
* Creates a moving wave in the x-y plane, with varying height along the z-axis.
*
* The x,y ranges are confined to (-.5, .5). Height can be any positive number.
* A number of frames are generated, which are drawn sequentially on Draw calls.
* It can run in either smooth or flat shaded modes. In smooth mode, the
* materials are generated with glMaterialColor.
* Two of the opposite corners of the wave are pinned down, while the wave moves
* diagonally between the other corners.
*
* It looks like there is only one period of the wave visible at any one time,
* and no way to adjust this. (mf: we need more periods)
*
* In the standard GL reference axis scheme, the normals for wave all have
* normals pointing in the -z direction. Looking at wave from that direction,
* the quad orientation is CW. So need to rotate by 180 around y if viewing
* down the -z axis. Alternatively, could construct the wave differently
***************************************************************************/
WAVE::WAVE()
{
nFrames = 10;
iWidthX = 10;
iWidthY = 10;
iCheckerSize = 2;
fHeight = 0.2f;
iCurFrame = 0;
InitMaterials();
InitMesh();
}
WAVE::~WAVE()
{
if( mesh.coords )
free( mesh.coords );
if( mesh.facets )
free( mesh.facets );
}
void
WAVE::Draw()
{
//mf: could be a candidate for vertex array ??
WCOORD *coord;
FACET *facet;
float *lastColor;
float *thisColor;
GLint i, j;
// Set any state required (caller will have to 'push' this state), or ?
// should do it here ?
//mf: need to set front face, etc. Caller can probably do this, since it's
// going to need to know how the wave is constructed anyways.
if (bSmooth) {
glShadeModel(GL_SMOOTH);
} else {
glShadeModel(GL_FLAT);
}
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
iCurFrame++;
// Draw the wave frame
if (iCurFrame >= nFrames) {
iCurFrame = 0;
}
for (i = 0; i < iWidthX; i++) {
glBegin(GL_QUAD_STRIP);
lastColor = NULL;
for (j = 0; j < iWidthY; j++) {
facet = GETFACET(iCurFrame, i, j);
if (!bSmooth && bLighting) {
glNormal3fv(facet->normal);
}
if (bLighting) {
thisColor = facet->color;
glColor3fv(facet->color);
} else {
thisColor = facet->color;
glColor3fv(facet->color);
}
if (!lastColor || (thisColor[0] != lastColor[0] && bSmooth)) {
if (lastColor) {
glEnd();
glBegin(GL_QUAD_STRIP);
}
coord = GETWCOORD(iCurFrame, i, j);
if (bSmooth && bLighting) {
glNormal3fv(coord->normal);
}
glVertex3fv(coord->vertex);
coord = GETWCOORD(iCurFrame, i+1, j);
if (bSmooth && bLighting) {
glNormal3fv(coord->normal);
}
glVertex3fv(coord->vertex);
}
coord = GETWCOORD(iCurFrame, i, j+1);
if (bSmooth && bLighting) {
glNormal3fv(coord->normal);
}
glVertex3fv(coord->vertex);
coord = GETWCOORD(iCurFrame, i+1, j+1);
if (bSmooth && bLighting) {
glNormal3fv(coord->normal);
}
glVertex3fv(coord->vertex);
lastColor = thisColor;
}
glEnd();
}
}
void
WAVE::InitMesh()
{
WCOORD *coord;
FACET *facet;
float dp1[3], dp2[3];
float *pt1, *pt2, *pt3;
float angle, d, x, y;
GLint numFacets, numCoords, frameNum, i, j;
numFacets = iWidthX * iWidthY;
numCoords = (iWidthX + 1) * (iWidthY + 1);
mesh.numCoords = numCoords;
mesh.numFacets = numFacets;
mesh.coords = (WCOORD *)malloc(nFrames*numCoords*
sizeof(WCOORD));
mesh.facets = (FACET *)malloc(nFrames*numFacets*
sizeof(FACET));
assert( mesh.coords != NULL || mesh.facets != NULL);
for (frameNum = 0; frameNum < nFrames; frameNum++) {
for (i = 0; i <= iWidthX; i++) {
x = i / (float)iWidthX;
for (j = 0; j <= iWidthY; j++) {
y = j / (float)iWidthY;
d = (float) sqrtf(x*x+y*y);
if (d == 0.0f) {
d = 0.0001f;
}
angle = 2 * PI * d + (2 * PI / nFrames * frameNum);
coord = GETWCOORD(frameNum, i, j);
coord->vertex[0] = x - 0.5f;
coord->vertex[1] = y - 0.5f;
coord->vertex[2] = (fHeight - fHeight * d) * cosf(angle);
coord->normal[0] = -(fHeight / d) * x * ((1 - d) * 2 * PI *
sinf(angle) + cosf(angle));
coord->normal[1] = -(fHeight / d) * y * ((1 - d) * 2 * PI *
sinf(angle) + cosf(angle));
coord->normal[2] = -1.0f;
d = 1.0f / sqrtf(coord->normal[0]*coord->normal[0]+
coord->normal[1]*coord->normal[1]+1);
coord->normal[0] *= d;
coord->normal[1] *= d;
coord->normal[2] *= d;
}
}
for (i = 0; i < iWidthX; i++) {
for (j = 0; j < iWidthY; j++) {
facet = GETFACET(frameNum, i, j);
if (((i/iCheckerSize)%2)^(j/iCheckerSize)%2) {
facet->color[0] = 1.0f;
facet->color[1] = 0.2f;
facet->color[2] = 0.2f;
} else {
facet->color[0] = 0.2f;
facet->color[1] = 1.0f;
facet->color[2] = 0.2f;
}
pt1 = GETWCOORD(frameNum, i, j)->vertex;
pt2 = GETWCOORD(frameNum, i, j+1)->vertex;
pt3 = GETWCOORD(frameNum, i+1, j+1)->vertex;
dp1[0] = pt2[0] - pt1[0];
dp1[1] = pt2[1] - pt1[1];
dp1[2] = pt2[2] - pt1[2];
dp2[0] = pt3[0] - pt2[0];
dp2[1] = pt3[1] - pt2[1];
dp2[2] = pt3[2] - pt2[2];
facet->normal[0] = dp1[1] * dp2[2] - dp1[2] * dp2[1];
facet->normal[1] = dp1[2] * dp2[0] - dp1[0] * dp2[2];
facet->normal[2] = dp1[0] * dp2[1] - dp1[1] * dp2[0];
d = 1.0f / sqrtf(facet->normal[0]*facet->normal[0]+
facet->normal[1]*facet->normal[1]+
facet->normal[2]*facet->normal[2]);
facet->normal[0] *= d;
facet->normal[1] *= d;
facet->normal[2] *= d;
}
}
}
}
#if 0
if (bLighting) {
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
} else {
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_COLOR_MATERIAL);
}
#endif