COMP: cleanup of surfaceCoarsen/bunnylod

- remove MSWindows components (code and makefiles)

- use cxx, hxx extensions to reduce possible confusion with other
  "list" and "vector" classes

- use C++ versions for C headers
This commit is contained in:
Mark Olesen
2020-04-16 11:39:33 +02:00
parent a5b2cf9069
commit b2bf82360c
13 changed files with 39 additions and 911 deletions

View File

@ -1,5 +1,5 @@
bunnylod/progmesh.C
bunnylod/vector.C
bunnylod/progmesh.cxx
bunnylod/vector.cxx
surfaceCoarsen.C
EXE = $(FOAM_APPBIN)/surfaceCoarsen

View File

@ -7,3 +7,14 @@ The PC executable bunnylod.exe should run
on a standard PC.
Just run it and enjoy.
Mouse dragging spins the rabbit.
-------------------------------------------------------------------
Changes
2020-04-16 OpenCFD Ltd
- remove MSWindows components (code and makefiles)
- use cxx, hxx extensions to reduce possible confusion with other
"list" and "vector" classes
- use C++ versions for C headers
-------------------------------------------------------------------

View File

@ -1,282 +0,0 @@
/*
* Polygon Reduction Demo by Stan Melax (c) 1998
* Permission to use any of this code wherever you want is granted..
* Although, please do acknowledge authorship if appropriate.
*
* This module initializes the bunny model data and calls
* the polygon reduction routine. At each frame the RenderModel()
* routine is called to draw the model. This module also
* animates the parameters (such as number of vertices to
* use) to show the model at various levels of detail.
*/
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <GL/gl.h>
#pragma warning(disable : 4244)
#include "vector.h"
#include "font.h"
#include "progmesh.h"
#include "rabdata.h"
extern float DeltaT; // change in time since last frame
int render_num; // number of vertices to draw with
float lodbase=0.5f; // the fraction of vertices used to morph toward
float morph=1.0f; // where to render between 2 levels of detail
List<Vector> vert; // global list of vertices
List<tridata> tri; // global list of triangles
List<int> collapse_map; // to which neighbor each vertex collapses
int renderpolycount=0; // polygons rendered in the current frame
Vector model_position; // position of bunny
Quaternion model_orientation; // orientation of bunny
// Note that the use of the Map() function and the collapse_map
// list isn't part of the polygon reduction algorithm.
// We just set up this system here in this module
// so that we could retrieve the model at any desired vertex count.
// Therefore if this part of the program confuses you, then
// dont worry about it. It might help to look over the progmesh.cpp
// module first.
// Map()
//
// When the model is rendered using a maximum of mx vertices
// then it is vertices 0 through mx-1 that are used.
// We are able to do this because the vertex list
// gets sorted according to the collapse order.
// The Map() routine takes a vertex number 'a' and the
// maximum number of vertices 'mx' and returns the
// appropriate vertex in the range 0 to mx-1.
// When 'a' is greater than 'mx' the Map() routine
// follows the chain of edge collapses until a vertex
// within the limit is reached.
// An example to make this clear: assume there is
// a triangle with vertices 1, 3 and 12. But when
// rendering the model we limit ourselves to 10 vertices.
// In that case we find out how vertex 12 was removed
// by the polygon reduction algorithm. i.e. which
// edge was collapsed. Lets say that vertex 12 was collapsed
// to vertex number 7. This number would have been stored
// in the collapse_map array (i.e. collapse_map[12]==7).
// Since vertex 7 is in range (less than max of 10) we
// will want to render the triangle 1,3,7.
// Pretend now that we want to limit ourselves to 5 vertices.
// and vertex 7 was collapsed to vertex 3
// (i.e. collapse_map[7]==3). Then triangle 1,3,12 would now be
// triangle 1,3,3. i.e. this polygon was removed by the
// progressive mesh polygon reduction algorithm by the time
// it had gotten down to 5 vertices.
// No need to draw a one dimensional polygon. :-)
int Map(int a,int mx) {
if(mx<=0) return 0;
while(a>=mx) {
a=collapse_map[a];
}
return a;
}
void DrawModelTriangles() {
assert(collapse_map.num);
renderpolycount=0;
int i=0;
for(i=0;i<tri.num;i++) {
int p0= Map(tri[i].v[0],render_num);
int p1= Map(tri[i].v[1],render_num);
int p2= Map(tri[i].v[2],render_num);
// note: serious optimization opportunity here,
// by sorting the triangles the following "continue"
// could have been made into a "break" statement.
if(p0==p1 || p1==p2 || p2==p0) continue;
renderpolycount++;
// if we are not currenly morphing between 2 levels of detail
// (i.e. if morph=1.0) then q0,q1, and q2 are not necessary.
int q0= Map(p0,(int)(render_num*lodbase));
int q1= Map(p1,(int)(render_num*lodbase));
int q2= Map(p2,(int)(render_num*lodbase));
Vector v0,v1,v2;
v0 = vert[p0]*morph + vert[q0]*(1-morph);
v1 = vert[p1]*morph + vert[q1]*(1-morph);
v2 = vert[p2]*morph + vert[q2]*(1-morph);
glBegin(GL_POLYGON);
// the purpose of the demo is to show polygons
// therefore just use 1 face normal (flat shading)
Vector nrml = (v1-v0) * (v2-v1); // cross product
if(0<magnitude(nrml)) {
glNormal3fv(normalize(nrml));
}
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v2);
glEnd();
}
}
void PermuteVertices(List<int> &permutation) {
// rearrange the vertex list
List<Vector> temp_list;
int i;
assert(permutation.num==vert.num);
for(i=0;i<vert.num;i++) {
temp_list.Add(vert[i]);
}
for(i=0;i<vert.num;i++) {
vert[permutation[i]]=temp_list[i];
}
// update the changes in the entries in the triangle list
for(i=0;i<tri.num;i++) {
for(int j=0;j<3;j++) {
tri[i].v[j] = permutation[tri[i].v[j]];
}
}
}
void GetRabbitData(){
// Copy the geometry from the arrays of data in rabdata.cpp into
// the vert and tri lists which we send to the reduction routine
int i;
for(i=0;i<RABBIT_VERTEX_NUM;i++) {
float *vp=rabbit_vertices[i];
vert.Add(Vector(vp[0],vp[1],vp[2]));
}
for(i=0;i<RABBIT_TRIANGLE_NUM;i++) {
tridata td;
td.v[0]=rabbit_triangles[i][0];
td.v[1]=rabbit_triangles[i][1];
td.v[2]=rabbit_triangles[i][2];
tri.Add(td);
}
render_num=vert.num; // by default lets use all the model to render
}
void InitModel() {
List<int> permutation;
GetRabbitData();
ProgressiveMesh(vert,tri,collapse_map,permutation);
PermuteVertices(permutation);
model_position = Vector(0,0,-3);
Quaternion yaw(Vector(0,1,0),-3.14f/4); // 45 degrees
Quaternion pitch(Vector(1,0,0),3.14f/12); // 15 degrees
model_orientation = pitch*yaw;
}
void StatusDraw() {
// Draw a slider type widget looking thing
// to show portion of vertices being used
float b = (float)render_num/(float)vert.num;
float a = b*(lodbase );
glDisable(GL_LIGHTING);
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
glOrtho(-0.15,15,-0.1,1.1,-0.1,100);
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glBegin(GL_POLYGON);
glColor3f(1,0,0);
glVertex2f(0,0);
glVertex2f(1,0);
glVertex2f(1,a);
glVertex2f(0,a);
glEnd();
glBegin(GL_POLYGON);
glColor3f(1,0,0);
glVertex2f(0,a);
glVertex2f(morph,a);
glVertex2f(morph,b);
glVertex2f(0,b);
glEnd();
glBegin(GL_POLYGON);
glColor3f(0,0,1);
glVertex2f(morph,a);
glVertex2f(1,a);
glVertex2f(1,b);
glVertex2f(morph,b);
glEnd();
glBegin(GL_POLYGON);
glColor3f(0,0,1);
glVertex2f(0,b);
glVertex2f(1,b);
glVertex2f(1,1);
glVertex2f(0,1);
glEnd();
glPopMatrix();
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
}
/*
* The following is just a quick hack to animate
* the object through various polygon reduced versions.
*/
struct keyframethings {
float t; // timestamp
float n; // portion of vertices used to start
float dn; // rate of change in "n"
float m; // morph value
float dm; // rate of change in "m"
} keys[]={
{0 ,1 ,0 ,1, 0},
{2 ,1 ,-1,1, 0},
{10,0 ,1 ,1, 0},
{18,1 ,0 ,1, 0},
{20,1 ,0 ,1,-1},
{24,0.5 ,0 ,1, 0},
{26,0.5 ,0 ,1,-1},
{30,0.25,0 ,1, 0},
{32,0.25,0 ,1,-1},
{36,0.125,0,1, 0},
{38,0.25,0 ,0, 1},
{42,0.5 ,0 ,0, 1},
{46,1 ,0 ,0, 1},
{50,1 ,0 ,1, 0},
};
void AnimateParameters() {
static float time=0; // global time - used for animation
time+=DeltaT;
if(time>=50) time=0; // repeat cycle every so many seconds
int k=0;
while(time>keys[k+1].t) {
k++;
}
float interp = (time-keys[k].t)/(keys[k+1].t-keys[k].t);
render_num = vert.num*(keys[k].n + interp*keys[k].dn);
morph = keys[k].m + interp*keys[k].dm;
morph = (morph>1.0f) ? 1.0f : morph; // clamp value
if(render_num>vert.num) render_num=vert.num;
if(render_num<0 ) render_num=0;
}
void RenderModel() {
AnimateParameters();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(model_position.x,model_position.y,model_position.z);
// Rotate by quaternion: model_orientation
Vector axis=model_orientation.axis();
float angle=model_orientation.angle()*180.0f/3.14f;
glRotatef(angle,axis.x,axis.y,axis.z);
DrawModelTriangles();
StatusDraw();
glPopMatrix();
char buf[256];
sprintf(buf,"Polys: %d Vertices: %d ",renderpolycount,render_num);
if(morph<1.0) {
sprintf(buf+strlen(buf),"<-> %d morph: %4.2f ",
(int)(lodbase *render_num),morph);
}
PostString(buf,0,-2,5);
}

View File

@ -1,114 +0,0 @@
# Microsoft Developer Studio Project File - Name="bunnylod" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=bunnylod - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "bunnylod.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "bunnylod.mak" CFG="bunnylod - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "bunnylod - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "bunnylod - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "bunnylod - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib winmm.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "bunnylod - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "bunnylod - Win32 Release"
# Name "bunnylod - Win32 Debug"
# Begin Source File
SOURCE=.\bunnygut.cpp
# End Source File
# Begin Source File
SOURCE=.\font.cpp
# End Source File
# Begin Source File
SOURCE=.\progmesh.cpp
# End Source File
# Begin Source File
SOURCE=.\rabdata.cpp
# End Source File
# Begin Source File
SOURCE=.\vector.cpp
# End Source File
# Begin Source File
SOURCE=.\winmain.cpp
# End Source File
# End Target
# End Project

View File

@ -1,29 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 5.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "bunnylod"=.\bunnylod.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -1,8 +0,0 @@
#ifndef FONT_H
#define FONT_H
void PrintString(char *s,int x=0,int y=-1);
void PostString(char *_s,int _x,int _y,float _life=5.0);
void RenderStrings();
#endif

View File

@ -1,13 +1,16 @@
/*
* -*- C++ -*-
*
* A generic template list class.
* Fairly typical of the list example you would
* find in any c++ book.
*/
#ifndef GENERIC_LIST_H
#define GENERIC_LIST_H
#include <assert.h>
#include <stdio.h>
#include <cassert>
#include <cstdio>
template<class Type> class List {
public:
@ -123,8 +126,4 @@ void List<Type>::Remove(Type t){
}
}
#endif

View File

@ -1,4 +1,6 @@
/*
* -*- C++ -*-
*
* Progressive Mesh type Polygon Reduction Algorithm
* by Stan Melax (c) 1998
* Permission to use any of this code wherever you want is granted..
@ -7,15 +9,14 @@
* See the header file progmesh.h for a description of this module
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
//#include <windows.h>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cassert>
#include "vector.h"
#include "list.h"
#include "progmesh.h"
#include "vector.hxx"
#include "list.hxx"
#include "progmesh.hxx"
#define min(x,y) (((x) <= (y)) ? (x) : (y))
#define max(x,y) (((x) >= (y)) ? (x) : (y))

View File

@ -1,4 +1,6 @@
/*
* -*- C++ -*-
*
* Progressive Mesh type Polygon Reduction Algorithm
* by Stan Melax (c) 1998
*
@ -18,8 +20,8 @@
#ifndef PROGRESSIVE_MESH_H
#define PROGRESSIVE_MESH_H
#include "vector.h"
#include "list.h"
#include "vector.hxx"
#include "list.hxx"
class tridata {
public:

View File

@ -1,8 +1,8 @@
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <cstdio>
#include <cmath>
#include <cassert>
#include "vector.h"
#include "vector.hxx"
float sqr(float a) {return a*a;}

View File

@ -1,3 +1,4 @@
// -*- C++ -*-
//
// This module contains a bunch of well understood functions
// I apologise if the conventions used here are slightly
@ -7,8 +8,8 @@
#ifndef GENERIC_VECTOR_H
#define GENERIC_VECTOR_H
#include <stdio.h>
#include <math.h>
#include <cstdio>
#include <cmath>
class Vector {

View File

@ -1,453 +0,0 @@
/*
* Polygon Reduction Demo by Stan Melax (c) 1998
* Permission to use any of this code wherever you want is granted..
* Although, please do acknowledge authorship if appropriate.
*
* This module contains the window setup code, mouse input, timing
* routines, and that sort of stuff. The interesting modules
* to see are bunnygut.cpp and progmesh.cpp.
*
* The windows 95 specific code for this application was taken from
* an example of processing mouse events in an OpenGL program using
* the Win32 API from the www.opengl.org web site.
*
* Under Project->Settings, Link Options, General Category
* Add:
* Opengl32.lib glu32.lib winmm.lib
* to the Object/Library Modules
*
* You will need have OpenGL libs and include files to compile this
* Go to the www.opengl.org web site if you need help with this.
*/
#include <windows.h> /* must include this before GL/gl.h */
#include <GL/gl.h> /* OpenGL header file */
#include <GL/glu.h> /* OpenGL utilities header file */
#include <stdio.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <time.h>
#include "vector.h"
#include "font.h"
// Functions and Variables from bunny module
extern void InitModel();
extern void RenderModel();
extern Vector model_position; // position of bunny
extern Quaternion model_orientation; // orientation of bunny
// Global Variables
float DeltaT = 0.1f;
float FPS;
int Width = 512;
int Height = 512;
int MouseX = 0;
int MouseY = 0;
Vector MouseVector; // 3D direction mouse points
Vector OldMouseVector;
int MouseState=0; // true iff left button down
float ViewAngle=45.0f;
HDC hDC; /* device context */
HPALETTE hPalette = 0; /* custom palette (if needed) */
void CalcFPSDeltaT(){
static int timeinit=0;
static int start,start2,current,last;
static int frame=0, frame2=0;
if(!timeinit){
frame=0;
start=timeGetTime();
timeinit=1;
}
frame++;
frame2++;
current=timeGetTime(); // found in winmm.lib
double dif=(double)(current-start)/CLOCKS_PER_SEC;
double rv = (dif)? (double)frame/(double)dif:-1.0;
if(dif>2.0 && frame >10) {
start = start2;
frame = frame2;
start2 = timeGetTime();
frame2 = 0;
}
DeltaT = (float)(current-last)/CLOCKS_PER_SEC;
if(current==last) {
DeltaT = 0.1f/CLOCKS_PER_SEC; // it just cant be 0
}
// if(DeltaT>1.0) DeltaT=1.0;
FPS = (float)rv;
last = current;
}
void ComputeMouseVector(){
OldMouseVector=MouseVector;
float spread = (float)tan(ViewAngle/2*3.14/180);
float y = spread * ((Height-MouseY)-Height/2.0f) /(Height/2.0f);
float x = spread * (MouseX-Width/2.0f) /(Height/2.0f);
Vector v(x ,y,-1);
// v=UserOrientation *v;
v=normalize(v);
MouseVector = v;
}
Quaternion VirtualTrackBall(Vector cop,Vector cor,Vector dir1,Vector dir2) {
// Implement track ball functionality to spin stuf on the screen
// cop center of projection
// cor center of rotation
// dir1 old mouse direction
// dir2 new mouse direction
// pretend there is a sphere around cor. Then find the points
// where dir1 and dir2 intersect that sphere. Find the
// rotation that takes the first point to the second.
float m;
// compute plane
Vector nrml = cor - cop;
// since trackball proportional to distance from cop
float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f);
nrml = normalize(nrml);
float dist = -(nrml^cor);
Vector u= planelineintersection(nrml,dist,cop,cop+dir1);
u=u-cor;
u=u*fudgefactor;
m= magnitude(u);
if(m>1) {u=u*1.0f/m;}
else {
u=u - (nrml * (float)sqrt(1-m*m));
}
Vector v= planelineintersection(nrml,dist,cop,cop+dir2);
v=v-cor;
v=v*fudgefactor;
m= magnitude(v);
if(m>1) {v=v*1.0f/m;}
else {
v=v - (nrml * (float)sqrt(1-m*m));
}
Vector axis = u*v;
float angle;
m=magnitude(axis);
if(m>1)m=1; // avoid potential floating point error
Quaternion q(Vector(1.0f,0.0f,0.0f),0.0f);
if(m>0 && (angle=(float)asin(m))>3.14/180) {
axis = normalize(axis);
q=Quaternion(axis,angle);
}
return q;
}
void SpinIt(){
// Change the orientation of the bunny according to mouse drag
Quaternion q=VirtualTrackBall(Vector(0,0,0),model_position,
OldMouseVector,MouseVector);
model_orientation=q*model_orientation;
}
void Reshape(int width, int height){
// called initially and when the window changes size
Width=width;
Height=height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(ViewAngle, (float)width/height, 0.1, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void PrintStats(){
char buf[1024];buf[0]='\0';
sprintf(buf,"FPS: %5.2f ",FPS);
PostString(buf,0,-1,0);
}
void Display(){
// main drawing routine - called every frame
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
// camera at default (zero) position and orientation
RenderModel();
PrintStats();
glLoadIdentity();
RenderStrings();
glPopMatrix();
glFlush();
SwapBuffers(hDC); /* nop if singlebuffered */
}
LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static PAINTSTRUCT ps;
static GLboolean left = GL_FALSE; /* left button currently down? */
static GLboolean right = GL_FALSE; /* right button currently down? */
static int omx, omy, mx, my;
switch(uMsg) {
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
case WM_SIZE:
Reshape(LOWORD(lParam), HIWORD(lParam));
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_CHAR:
switch (wParam) {
case 27: /* ESC key */
PostQuitMessage(0);
break;
}
return 0;
case WM_LBUTTONDOWN:
/* if we don't set the capture we won't get mouse move
messages when the mouse moves outside the window. */
SetCapture(hWnd);
MouseX = LOWORD(lParam);
MouseY = HIWORD(lParam);
ComputeMouseVector();
MouseState = 1;
return 0;
case WM_LBUTTONUP:
MouseX = LOWORD(lParam);
MouseY = HIWORD(lParam);
if(MouseX & 1 << 15) MouseX -= (1 << 16);
if(MouseY & 1 << 15) MouseY -= (1 << 16);
ComputeMouseVector();
if(MouseState) SpinIt();
MouseState=0;
/* remember to release the capture when we are finished. */
ReleaseCapture();
return 0;
case WM_MOUSEMOVE:
MouseX = LOWORD(lParam);
MouseY = HIWORD(lParam);
/* Win32 is pretty braindead about the x, y position that
it returns when the mouse is off the left or top edge
of the window (due to them being unsigned). therefore,
roll the Win32's 0..2^16 pointer co-ord range to the
more amenable (and useful) 0..+/-2^15. */
if(MouseX & 1 << 15) MouseX -= (1 << 16);
if(MouseY & 1 << 15) MouseY -= (1 << 16);
ComputeMouseVector();
if(MouseState) SpinIt();
return 0;
case WM_PALETTECHANGED:
if (hWnd == (HWND)wParam) break;
/* fall through to WM_QUERYNEWPALETTE */
case WM_QUERYNEWPALETTE:
if (hPalette) {
UnrealizeObject(hPalette);
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
return TRUE;
}
return FALSE;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
HWND CreateOpenGLWindow(char* title)
{
// make a double-buffered, rgba, opengl window
int n, pf;
HWND hWnd;
WNDCLASS wc;
LOGPALETTE* lpPal;
PIXELFORMATDESCRIPTOR pfd;
static HINSTANCE hInstance = 0;
/* only register the window class once - use hInstance as a flag. */
if (!hInstance) {
hInstance = GetModuleHandle(nullptr);
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
wc.lpszClassName = "OpenGL";
if (!RegisterClass(&wc)) {
MessageBox(nullptr, "RegisterClass() failed: "
"Cannot register window class.",
"Error", MB_OK);
return nullptr;
}
}
hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0,0,Width,Height, nullptr, nullptr, hInstance, nullptr);
if (hWnd == nullptr) {
MessageBox(nullptr,
"CreateWindow() failed: Cannot create a window.",
"Error", MB_OK);
return nullptr;
}
hDC = GetDC(hWnd);
/* there is no guarantee that the contents of the stack that become
the pfd are zeroed, therefore _make sure_ to clear these bits. */
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cDepthBits = 32;
pfd.cColorBits = 32;
pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0) {
MessageBox(nullptr, "ChoosePixelFormat() failed: "
"Cannot find a suitable pixel format.",
"Error", MB_OK);
return 0;
}
if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
MessageBox(nullptr, "SetPixelFormat() failed: "
"Cannot set format specified.", "Error", MB_OK);
return 0;
}
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if (pfd.dwFlags & PFD_NEED_PALETTE ||
pfd.iPixelType == PFD_TYPE_COLORINDEX) {
n = 1 << pfd.cColorBits;
if (n > 256) n = 256;
lpPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
sizeof(PALETTEENTRY) * n);
memset(lpPal, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * n);
lpPal->palVersion = 0x300;
lpPal->palNumEntries = n;
GetSystemPaletteEntries(hDC, 0, n, &lpPal->palPalEntry[0]);
/* if the pixel type is RGBA, then we want to make an RGB ramp,
otherwise (color index) set individual colors. */
if (pfd.iPixelType == PFD_TYPE_RGBA) {
int redMask = (1 << pfd.cRedBits) - 1;
int greenMask = (1 << pfd.cGreenBits) - 1;
int blueMask = (1 << pfd.cBlueBits) - 1;
int i;
/* fill in the entries with an RGB color ramp. */
for (i = 0; i < n; ++i) {
lpPal->palPalEntry[i].peRed =
(((i >> pfd.cRedShift) & redMask) * 255)
/redMask;
lpPal->palPalEntry[i].peGreen =
(((i >> pfd.cGreenShift) & greenMask) * 255)
/greenMask;
lpPal->palPalEntry[i].peBlue =
(((i >> pfd.cBlueShift) & blueMask) * 255)
/blueMask;
lpPal->palPalEntry[i].peFlags = 0;
}
} else {
lpPal->palPalEntry[0].peRed = 0;
lpPal->palPalEntry[0].peGreen = 0;
lpPal->palPalEntry[0].peBlue = 0;
lpPal->palPalEntry[0].peFlags = PC_NOCOLLAPSE;
lpPal->palPalEntry[1].peRed = 255;
lpPal->palPalEntry[1].peGreen = 0;
lpPal->palPalEntry[1].peBlue = 0;
lpPal->palPalEntry[1].peFlags = PC_NOCOLLAPSE;
lpPal->palPalEntry[2].peRed = 0;
lpPal->palPalEntry[2].peGreen = 255;
lpPal->palPalEntry[2].peBlue = 0;
lpPal->palPalEntry[2].peFlags = PC_NOCOLLAPSE;
lpPal->palPalEntry[3].peRed = 0;
lpPal->palPalEntry[3].peGreen = 0;
lpPal->palPalEntry[3].peBlue = 255;
lpPal->palPalEntry[3].peFlags = PC_NOCOLLAPSE;
}
hPalette = CreatePalette(lpPal);
if (hPalette) {
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
}
free(lpPal);
}
ReleaseDC(hDC, hWnd);
return hWnd;
}
int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
LPSTR lpszCmdLine, int nCmdShow)
{
HGLRC hRC; /* opengl context */
HWND hWnd; /* window */
MSG msg; /* message */
// InitModel() initializes some data structures and
// does the progressive mesh polygon reduction algorithm
// on the model.
CalcFPSDeltaT(); // to time the algorithm
InitModel();
CalcFPSDeltaT();
hWnd = CreateOpenGLWindow("bunnylod by Stan Melax");
if (hWnd == nullptr) exit(1);
hDC = GetDC(hWnd);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
ShowWindow(hWnd, nCmdShow);
glEnable(GL_DEPTH_TEST);
PostString("Demo by Stan Melax (c)1998",5,-5,20);
PostString("Model by Viewpoint Datalabs (c)1996",5,-4,20);
char buf[128];
PostString("Mesh Reduction Algorithm (non-optimized)",1,0,5);
sprintf(buf,"was executed in %5.3f seconds",DeltaT);
PostString(buf,2,1,6);
while (1) {
while(PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) {
if(GetMessage(&msg, hWnd, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
// This 'goto' was in the sample code
goto quit;
}
}
CalcFPSDeltaT();
Display();
}
quit:
wglMakeCurrent(nullptr, nullptr);
ReleaseDC(hDC, hWnd);
wglDeleteContext(hRC);
DestroyWindow(hWnd);
if (hPalette) DeleteObject(hPalette);
return msg.wParam;
}

View File

@ -50,7 +50,7 @@ Description
#include "triFaceList.H"
// From bunnylod
#include "progmesh.h"
#include "progmesh.hxx"
using namespace Foam;