PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/applications/utilities/surface/surfaceCoarsen/bunnylod/bunnygut.C

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