mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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:
@ -1,5 +1,5 @@
|
||||
bunnylod/progmesh.C
|
||||
bunnylod/vector.C
|
||||
bunnylod/progmesh.cxx
|
||||
bunnylod/vector.cxx
|
||||
surfaceCoarsen.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/surfaceCoarsen
|
||||
|
||||
@ -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
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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))
|
||||
@ -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:
|
||||
@ -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;}
|
||||
|
||||
@ -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 {
|
||||
@ -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;
|
||||
}
|
||||
@ -50,7 +50,7 @@ Description
|
||||
#include "triFaceList.H"
|
||||
|
||||
// From bunnylod
|
||||
#include "progmesh.h"
|
||||
#include "progmesh.hxx"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user