ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / applications / utilities / surface / surfaceCoarsen / bunnylod / bunnygut.C
blob3e78b37861a66b3d3781fda85bdab2f3bd765ab4
1 /*
2  *   Polygon Reduction Demo by Stan Melax (c) 1998
3  *  Permission to use any of this code wherever you want is granted..
4  *  Although, please do acknowledge authorship if appropriate.
5  *
6  *  This module initializes the bunny model data and calls
7  *  the polygon reduction routine.  At each frame the RenderModel()
8  *  routine is called to draw the model.  This module also
9  *  animates the parameters (such as number of vertices to
10  *  use) to show the model at various levels of detail.
11  */
13 #include <windows.h>
14 #include <stdio.h>
15 #include <math.h>
16 #include <stdlib.h>
17 #include <assert.h>
18 #include <string.h>
19 #include <GL/gl.h>
20 #pragma warning(disable : 4244)
22 #include "vector.h"
23 #include "font.h"
24 #include "progmesh.h"
25 #include "rabdata.h"
27 extern float DeltaT;  // change in time since last frame
28 int   render_num;   // number of vertices to draw with
29 float lodbase=0.5f; // the fraction of vertices used to morph toward
30 float morph=1.0f;   // where to render between 2 levels of detail
31 List<Vector> vert;       // global list of vertices
32 List<tridata> tri;       // global list of triangles
33 List<int> collapse_map;  // to which neighbor each vertex collapses
34 int renderpolycount=0;   // polygons rendered in the current frame
35 Vector model_position;         // position of bunny
36 Quaternion model_orientation;  // orientation of bunny
38 // Note that the use of the Map() function and the collapse_map
39 // list isn't part of the polygon reduction algorithm.
40 // We just set up this system here in this module
41 // so that we could retrieve the model at any desired vertex count.
42 // Therefore if this part of the program confuses you, then
43 // dont worry about it.  It might help to look over the progmesh.cpp
44 // module first.
46 //       Map()
48 // When the model is rendered using a maximum of mx vertices
49 // then it is vertices 0 through mx-1 that are used.
50 // We are able to do this because the vertex list
51 // gets sorted according to the collapse order.
52 // The Map() routine takes a vertex number 'a' and the
53 // maximum number of vertices 'mx' and returns the
54 // appropriate vertex in the range 0 to mx-1.
55 // When 'a' is greater than 'mx' the Map() routine
56 // follows the chain of edge collapses until a vertex
57 // within the limit is reached.
58 //   An example to make this clear: assume there is
59 //   a triangle with vertices 1, 3 and 12.  But when
60 //   rendering the model we limit ourselves to 10 vertices.
61 //   In that case we find out how vertex 12 was removed
62 //   by the polygon reduction algorithm.  i.e. which
63 //   edge was collapsed.  Lets say that vertex 12 was collapsed
64 //   to vertex number 7.  This number would have been stored
65 //   in the collapse_map array (i.e. collapse_map[12]==7).
66 //   Since vertex 7 is in range (less than max of 10) we
67 //   will want to render the triangle 1,3,7.
68 //   Pretend now that we want to limit ourselves to 5 vertices.
69 //   and vertex 7 was collapsed to vertex 3
70 //   (i.e. collapse_map[7]==3).  Then triangle 1,3,12 would now be
71 //   triangle 1,3,3.  i.e. this polygon was removed by the
72 //   progressive mesh polygon reduction algorithm by the time
73 //   it had gotten down to 5 vertices.
74 //   No need to draw a one dimensional polygon. :-)
75 int Map(int a,int mx) {
76         if(mx<=0) return 0;
77         while(a>=mx) {
78                 a=collapse_map[a];
79         }
80         return a;
83 void DrawModelTriangles() {
84         assert(collapse_map.num);
85         renderpolycount=0;
86         int i=0;
87         for(i=0;i<tri.num;i++) {
88                 int p0= Map(tri[i].v[0],render_num);
89                 int p1= Map(tri[i].v[1],render_num);
90                 int p2= Map(tri[i].v[2],render_num);
91                 // note:  serious optimization opportunity here,
92                 //  by sorting the triangles the following "continue"
93                 //  could have been made into a "break" statement.
94                 if(p0==p1 || p1==p2 || p2==p0) continue;
95                 renderpolycount++;
96                 // if we are not currenly morphing between 2 levels of detail
97                 // (i.e. if morph=1.0) then q0,q1, and q2 are not necessary.
98                 int q0= Map(p0,(int)(render_num*lodbase));
99                 int q1= Map(p1,(int)(render_num*lodbase));
100                 int q2= Map(p2,(int)(render_num*lodbase));
101                 Vector v0,v1,v2;
102                 v0 = vert[p0]*morph + vert[q0]*(1-morph);
103                 v1 = vert[p1]*morph + vert[q1]*(1-morph);
104                 v2 = vert[p2]*morph + vert[q2]*(1-morph);
105                 glBegin(GL_POLYGON);
106                         // the purpose of the demo is to show polygons
107                         // therefore just use 1 face normal (flat shading)
108                         Vector nrml = (v1-v0) * (v2-v1);  // cross product
109                         if(0<magnitude(nrml)) {
110                                 glNormal3fv(normalize(nrml));
111                         }
112                         glVertex3fv(v0);
113                         glVertex3fv(v1);
114                         glVertex3fv(v2);
115                 glEnd();
116         }
120 void PermuteVertices(List<int> &permutation) {
121         // rearrange the vertex list
122         List<Vector> temp_list;
123         int i;
124         assert(permutation.num==vert.num);
125         for(i=0;i<vert.num;i++) {
126                 temp_list.Add(vert[i]);
127         }
128         for(i=0;i<vert.num;i++) {
129                 vert[permutation[i]]=temp_list[i];
130         }
131         // update the changes in the entries in the triangle list
132         for(i=0;i<tri.num;i++) {
133                 for(int j=0;j<3;j++) {
134                         tri[i].v[j] = permutation[tri[i].v[j]];
135                 }
136         }
139 void GetRabbitData(){
140         // Copy the geometry from the arrays of data in rabdata.cpp into
141         // the vert and tri lists which we send to the reduction routine
142         int i;
143         for(i=0;i<RABBIT_VERTEX_NUM;i++) {
144                 float *vp=rabbit_vertices[i];
145                 vert.Add(Vector(vp[0],vp[1],vp[2]));
146         }
147         for(i=0;i<RABBIT_TRIANGLE_NUM;i++) {
148                 tridata td;
149                 td.v[0]=rabbit_triangles[i][0];
150                 td.v[1]=rabbit_triangles[i][1];
151                 td.v[2]=rabbit_triangles[i][2];
152                 tri.Add(td);
153         }
154         render_num=vert.num;  // by default lets use all the model to render
158 void InitModel() {
159         List<int> permutation;
160         GetRabbitData();
161         ProgressiveMesh(vert,tri,collapse_map,permutation);
162         PermuteVertices(permutation);
163         model_position    = Vector(0,0,-3);
164         Quaternion yaw(Vector(0,1,0),-3.14f/4);    // 45 degrees
165         Quaternion pitch(Vector(1,0,0),3.14f/12);  // 15 degrees
166         model_orientation = pitch*yaw;
169 void StatusDraw() {
170         //  Draw a slider type widget looking thing
171         // to show portion of vertices being used
172         float b = (float)render_num/(float)vert.num;
173         float a = b*(lodbase );
174         glDisable(GL_LIGHTING);
175         glMatrixMode( GL_PROJECTION );
176         glPushMatrix();
177         glLoadIdentity();
178         glOrtho(-0.15,15,-0.1,1.1,-0.1,100);
179         glMatrixMode( GL_MODELVIEW );
181         glPushMatrix();
182         glLoadIdentity();
183         glBegin(GL_POLYGON);
184         glColor3f(1,0,0);
185         glVertex2f(0,0);
186         glVertex2f(1,0);
187         glVertex2f(1,a);
188         glVertex2f(0,a);
189         glEnd();
190         glBegin(GL_POLYGON);
191         glColor3f(1,0,0);
192         glVertex2f(0,a);
193         glVertex2f(morph,a);
194         glVertex2f(morph,b);
195         glVertex2f(0,b);
196         glEnd();
197         glBegin(GL_POLYGON);
198         glColor3f(0,0,1);
199         glVertex2f(morph,a);
200         glVertex2f(1,a);
201         glVertex2f(1,b);
202         glVertex2f(morph,b);
203         glEnd();
204         glBegin(GL_POLYGON);
205         glColor3f(0,0,1);
206         glVertex2f(0,b);
207         glVertex2f(1,b);
208         glVertex2f(1,1);
209         glVertex2f(0,1);
210         glEnd();
211         glPopMatrix();
212         glMatrixMode( GL_PROJECTION );
213         glPopMatrix();
214         glMatrixMode( GL_MODELVIEW );
218  *  The following is just a quick hack to animate
219  *  the object through various polygon reduced versions.
220  */
221 struct keyframethings {
222         float t;   // timestamp
223         float n;   // portion of vertices used to start
224         float dn;  // rate of change in "n"
225         float m;   // morph value
226         float dm;  // rate of change in "m"
227 } keys[]={
228         {0 ,1   ,0 ,1, 0},
229         {2 ,1   ,-1,1, 0},
230         {10,0   ,1 ,1, 0},
231         {18,1   ,0 ,1, 0},
232         {20,1   ,0 ,1,-1},
233         {24,0.5 ,0 ,1, 0},
234         {26,0.5 ,0 ,1,-1},
235         {30,0.25,0 ,1, 0},
236         {32,0.25,0 ,1,-1},
237         {36,0.125,0,1, 0},
238         {38,0.25,0 ,0, 1},
239         {42,0.5 ,0 ,0, 1},
240         {46,1   ,0 ,0, 1},
241         {50,1   ,0 ,1, 0},
243 void AnimateParameters() {
244         static float time=0;  // global time - used for animation
245         time+=DeltaT;
246         if(time>=50) time=0;  // repeat cycle every so many seconds
247         int k=0;
248         while(time>keys[k+1].t) {
249                 k++;
250         }
251         float interp = (time-keys[k].t)/(keys[k+1].t-keys[k].t);
252         render_num = vert.num*(keys[k].n + interp*keys[k].dn);
253         morph    = keys[k].m + interp*keys[k].dm;
254         morph = (morph>1.0f) ? 1.0f : morph;  // clamp value
255         if(render_num>vert.num) render_num=vert.num;
256         if(render_num<0       ) render_num=0;
259 void RenderModel() {
260         AnimateParameters();
262         glEnable(GL_LIGHTING);
263         glEnable(GL_LIGHT0);
264         glColor3f(1,1,1);
265         glPushMatrix();
266         glTranslatef(model_position.x,model_position.y,model_position.z);
267         // Rotate by quaternion: model_orientation
268         Vector axis=model_orientation.axis();
269         float angle=model_orientation.angle()*180.0f/3.14f;
270         glRotatef(angle,axis.x,axis.y,axis.z);
271         DrawModelTriangles();
272         StatusDraw();
273         glPopMatrix();
275         char buf[256];
276         sprintf(buf,"Polys: %d  Vertices: %d ",renderpolycount,render_num);
277         if(morph<1.0) {
278                 sprintf(buf+strlen(buf),"<-> %d  morph: %4.2f ",
279                         (int)(lodbase *render_num),morph);
280         }
281         PostString(buf,0,-2,5);