FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

bunnygut.C

Go to the documentation of this file.
00001 /*
00002  *   Polygon Reduction Demo by Stan Melax (c) 1998
00003  *  Permission to use any of this code wherever you want is granted..
00004  *  Although, please do acknowledge authorship if appropriate.
00005  *
00006  *  This module initializes the bunny model data and calls
00007  *  the polygon reduction routine.  At each frame the RenderModel()
00008  *  routine is called to draw the model.  This module also
00009  *  animates the parameters (such as number of vertices to
00010  *  use) to show the model at various levels of detail.
00011  */
00012 
00013 #include <windows.h>
00014 #include <stdio.h>  
00015 #include <math.h>
00016 #include <stdlib.h>
00017 #include <assert.h>
00018 #include <string.h>
00019 #include <GL/gl.h>
00020 #pragma warning(disable : 4244)
00021 
00022 #include "vector.h"
00023 #include "font.h"
00024 #include "progmesh.h"
00025 #include "rabdata.h"
00026 
00027 extern float DeltaT;  // change in time since last frame
00028 int   render_num;   // number of vertices to draw with
00029 float lodbase=0.5f; // the fraction of vertices used to morph toward
00030 float morph=1.0f;   // where to render between 2 levels of detail
00031 List<Vector> vert;       // global list of vertices
00032 List<tridata> tri;       // global list of triangles
00033 List<int> collapse_map;  // to which neighbor each vertex collapses
00034 int renderpolycount=0;   // polygons rendered in the current frame
00035 Vector model_position;         // position of bunny
00036 Quaternion model_orientation;  // orientation of bunny
00037 
00038 // Note that the use of the Map() function and the collapse_map
00039 // list isn't part of the polygon reduction algorithm.
00040 // We just set up this system here in this module
00041 // so that we could retrieve the model at any desired vertex count.
00042 // Therefore if this part of the program confuses you, then
00043 // dont worry about it.  It might help to look over the progmesh.cpp
00044 // module first.
00045 
00046 //       Map()
00047 //
00048 // When the model is rendered using a maximum of mx vertices
00049 // then it is vertices 0 through mx-1 that are used.  
00050 // We are able to do this because the vertex list 
00051 // gets sorted according to the collapse order.
00052 // The Map() routine takes a vertex number 'a' and the
00053 // maximum number of vertices 'mx' and returns the 
00054 // appropriate vertex in the range 0 to mx-1.
00055 // When 'a' is greater than 'mx' the Map() routine
00056 // follows the chain of edge collapses until a vertex
00057 // within the limit is reached.
00058 //   An example to make this clear: assume there is
00059 //   a triangle with vertices 1, 3 and 12.  But when
00060 //   rendering the model we limit ourselves to 10 vertices.
00061 //   In that case we find out how vertex 12 was removed
00062 //   by the polygon reduction algorithm.  i.e. which
00063 //   edge was collapsed.  Lets say that vertex 12 was collapsed
00064 //   to vertex number 7.  This number would have been stored
00065 //   in the collapse_map array (i.e. collapse_map[12]==7).
00066 //   Since vertex 7 is in range (less than max of 10) we
00067 //   will want to render the triangle 1,3,7.  
00068 //   Pretend now that we want to limit ourselves to 5 vertices.
00069 //   and vertex 7 was collapsed to vertex 3 
00070 //   (i.e. collapse_map[7]==3).  Then triangle 1,3,12 would now be
00071 //   triangle 1,3,3.  i.e. this polygon was removed by the
00072 //   progressive mesh polygon reduction algorithm by the time
00073 //   it had gotten down to 5 vertices.
00074 //   No need to draw a one dimensional polygon. :-)
00075 int Map(int a,int mx) {
00076     if(mx<=0) return 0;
00077     while(a>=mx) {  
00078         a=collapse_map[a];
00079     }
00080     return a;
00081 }
00082 
00083 void DrawModelTriangles() {
00084     assert(collapse_map.num);
00085     renderpolycount=0;
00086     int i=0;
00087     for(i=0;i<tri.num;i++) {
00088         int p0= Map(tri[i].v[0],render_num);
00089         int p1= Map(tri[i].v[1],render_num);
00090         int p2= Map(tri[i].v[2],render_num);
00091         // note:  serious optimization opportunity here,
00092         //  by sorting the triangles the following "continue" 
00093         //  could have been made into a "break" statement.
00094         if(p0==p1 || p1==p2 || p2==p0) continue;
00095         renderpolycount++;
00096         // if we are not currenly morphing between 2 levels of detail
00097         // (i.e. if morph=1.0) then q0,q1, and q2 are not necessary.
00098         int q0= Map(p0,(int)(render_num*lodbase));
00099         int q1= Map(p1,(int)(render_num*lodbase));
00100         int q2= Map(p2,(int)(render_num*lodbase));
00101         Vector v0,v1,v2; 
00102         v0 = vert[p0]*morph + vert[q0]*(1-morph);
00103         v1 = vert[p1]*morph + vert[q1]*(1-morph);
00104         v2 = vert[p2]*morph + vert[q2]*(1-morph);
00105         glBegin(GL_POLYGON);
00106             // the purpose of the demo is to show polygons
00107             // therefore just use 1 face normal (flat shading)
00108             Vector nrml = (v1-v0) * (v2-v1);  // cross product
00109             if(0<magnitude(nrml)) {
00110                 glNormal3fv(normalize(nrml));
00111             }
00112             glVertex3fv(v0);
00113             glVertex3fv(v1);
00114             glVertex3fv(v2);
00115         glEnd();
00116     }
00117 }
00118 
00119 
00120 void PermuteVertices(List<int> &permutation) {
00121     // rearrange the vertex list 
00122     List<Vector> temp_list;
00123     int i;
00124     assert(permutation.num==vert.num);
00125     for(i=0;i<vert.num;i++) {
00126         temp_list.Add(vert[i]);
00127     }
00128     for(i=0;i<vert.num;i++) {
00129         vert[permutation[i]]=temp_list[i];
00130     }
00131     // update the changes in the entries in the triangle list
00132     for(i=0;i<tri.num;i++) {
00133         for(int j=0;j<3;j++) {
00134             tri[i].v[j] = permutation[tri[i].v[j]];
00135         }
00136     }
00137 }
00138 
00139 void GetRabbitData(){
00140     // Copy the geometry from the arrays of data in rabdata.cpp into
00141     // the vert and tri lists which we send to the reduction routine
00142     int i;
00143     for(i=0;i<RABBIT_VERTEX_NUM;i++) {
00144         float *vp=rabbit_vertices[i];
00145         vert.Add(Vector(vp[0],vp[1],vp[2]));
00146     }
00147     for(i=0;i<RABBIT_TRIANGLE_NUM;i++) {
00148         tridata td;
00149         td.v[0]=rabbit_triangles[i][0];
00150         td.v[1]=rabbit_triangles[i][1];
00151         td.v[2]=rabbit_triangles[i][2];
00152         tri.Add(td);
00153     }
00154     render_num=vert.num;  // by default lets use all the model to render
00155 }
00156 
00157 
00158 void InitModel() {
00159     List<int> permutation;
00160     GetRabbitData();  
00161     ProgressiveMesh(vert,tri,collapse_map,permutation);
00162     PermuteVertices(permutation);
00163     model_position    = Vector(0,0,-3);
00164     Quaternion yaw(Vector(0,1,0),-3.14f/4);    // 45 degrees
00165     Quaternion pitch(Vector(1,0,0),3.14f/12);  // 15 degrees 
00166     model_orientation = pitch*yaw;
00167 }
00168 
00169 void StatusDraw() {
00170     //  Draw a slider type widget looking thing
00171     // to show portion of vertices being used
00172     float b = (float)render_num/(float)vert.num;
00173     float a = b*(lodbase );
00174     glDisable(GL_LIGHTING);
00175     glMatrixMode( GL_PROJECTION );
00176     glPushMatrix();
00177     glLoadIdentity();
00178     glOrtho(-0.15,15,-0.1,1.1,-0.1,100);
00179     glMatrixMode( GL_MODELVIEW );
00180 
00181     glPushMatrix();
00182     glLoadIdentity();
00183     glBegin(GL_POLYGON);
00184     glColor3f(1,0,0);
00185     glVertex2f(0,0);
00186     glVertex2f(1,0);
00187     glVertex2f(1,a);
00188     glVertex2f(0,a);
00189     glEnd();
00190     glBegin(GL_POLYGON);
00191     glColor3f(1,0,0);
00192     glVertex2f(0,a);
00193     glVertex2f(morph,a);
00194     glVertex2f(morph,b);
00195     glVertex2f(0,b);
00196     glEnd();
00197     glBegin(GL_POLYGON);
00198     glColor3f(0,0,1);
00199     glVertex2f(morph,a);
00200     glVertex2f(1,a);
00201     glVertex2f(1,b);
00202     glVertex2f(morph,b);
00203     glEnd();
00204     glBegin(GL_POLYGON);
00205     glColor3f(0,0,1);
00206     glVertex2f(0,b);
00207     glVertex2f(1,b);
00208     glVertex2f(1,1);
00209     glVertex2f(0,1);
00210     glEnd();
00211     glPopMatrix();
00212     glMatrixMode( GL_PROJECTION );
00213     glPopMatrix();
00214     glMatrixMode( GL_MODELVIEW );
00215 }
00216 
00217 /*
00218  *  The following is just a quick hack to animate
00219  *  the object through various polygon reduced versions.
00220  */
00221 struct keyframethings {
00222     float t;   // timestamp
00223     float n;   // portion of vertices used to start
00224     float dn;  // rate of change in "n"
00225     float m;   // morph value
00226     float dm;  // rate of change in "m"
00227 } keys[]={
00228     {0 ,1   ,0 ,1, 0},
00229     {2 ,1   ,-1,1, 0},
00230     {10,0   ,1 ,1, 0},
00231     {18,1   ,0 ,1, 0},
00232     {20,1   ,0 ,1,-1},
00233     {24,0.5 ,0 ,1, 0},
00234     {26,0.5 ,0 ,1,-1},
00235     {30,0.25,0 ,1, 0},
00236     {32,0.25,0 ,1,-1},
00237     {36,0.125,0,1, 0},
00238     {38,0.25,0 ,0, 1},
00239     {42,0.5 ,0 ,0, 1},
00240     {46,1   ,0 ,0, 1},
00241     {50,1   ,0 ,1, 0},
00242 };
00243 void AnimateParameters() {
00244     static float time=0;  // global time - used for animation
00245     time+=DeltaT;
00246     if(time>=50) time=0;  // repeat cycle every so many seconds
00247     int k=0;
00248     while(time>keys[k+1].t) {
00249         k++;
00250     }
00251     float interp = (time-keys[k].t)/(keys[k+1].t-keys[k].t);
00252     render_num = vert.num*(keys[k].n + interp*keys[k].dn);
00253     morph    = keys[k].m + interp*keys[k].dm;
00254     morph = (morph>1.0f) ? 1.0f : morph;  // clamp value
00255     if(render_num>vert.num) render_num=vert.num;
00256     if(render_num<0       ) render_num=0;
00257 }
00258 
00259 void RenderModel() {
00260     AnimateParameters();
00261     
00262     glEnable(GL_LIGHTING);
00263     glEnable(GL_LIGHT0);
00264     glColor3f(1,1,1);
00265     glPushMatrix();
00266     glTranslatef(model_position.x,model_position.y,model_position.z);
00267     // Rotate by quaternion: model_orientation
00268     Vector axis=model_orientation.axis();
00269     float angle=model_orientation.angle()*180.0f/3.14f;
00270     glRotatef(angle,axis.x,axis.y,axis.z);
00271     DrawModelTriangles();
00272     StatusDraw();
00273     glPopMatrix();
00274 
00275     char buf[256];
00276     sprintf(buf,"Polys: %d  Vertices: %d ",renderpolycount,render_num);
00277     if(morph<1.0) {
00278         sprintf(buf+strlen(buf),"<-> %d  morph: %4.2f ",
00279                 (int)(lodbase *render_num),morph); 
00280     }
00281     PostString(buf,0,-2,5);
00282 }
00283 
00284 
00285 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines