source: anuga_work/development/anugavis/src/height_quantity.c @ 5488

Last change on this file since 5488 was 5292, checked in by jack, 16 years ago

anugavis: Some basic camera control and frame stepping.

File size: 5.1 KB
Line 
1#ifdef HAVE_CONFIG_H
2#  include "config.h"
3#endif
4
5#ifdef HAVE_STDLIB_H
6#  include <stdlib.h>
7#endif
8#ifdef HAVE_STRING_H
9#  include <string.h>
10#endif
11#ifdef HAVE_GL_GL_H
12#  include <GL/gl.h>
13#elif HAVE_OPENGL_GL_H
14#  include <OpenGL/gl.h>
15#endif
16#include <netcdf.h>
17#include <SDL.h>
18#include "error.h"
19#include "globals.h"
20#include "height_quantity.h"
21#include "netcdf_util.h"
22#include "vector.h"
23#include "xfunctions.h"
24
25static int compileDisplayLists(struct height_quantity_simple *height){
26  int frame;
27  unsigned int vol;
28  unsigned int vertex;
29  int vertIndex;
30  vector vs[3];
31  vector v1;
32  vector v2;
33  vector normal;
34  vector flippedNormal;
35  vector up = {0.0, 0.0, 1.0};
36  float *heights = xmalloc(sizeof(float)
37                           * anugavis.number_of_points
38                           * height->frames, "compileDisplayLists()");
39  if(heights == NULL)
40    return -1;
41  if(nc_get_var_float_by_name(anugavis.netcdfId,
42                              height->name, heights) != NC_NOERR){
43    free(heights);
44    return -1;
45  }
46
47  for(frame = 0 ; frame < height->frames ; frame++){
48    glNewList(height->displayLists + frame, GL_COMPILE);
49    for(vol = 0 ; vol < anugavis.number_of_volumes ; vol++){
50      glBegin(GL_POLYGON);
51      for(vertex = 0 ; vertex < 3 ; vertex++){ /* Calculate normal */
52        vertIndex = anugavis.volumes[vol*anugavis.number_of_vertices + vertex];
53        vs[vertex][0] = anugavis.x[vertIndex];
54        vs[vertex][1] = anugavis.y[vertIndex];
55        vs[vertex][2] = heights[frame*anugavis.number_of_points + vertIndex];
56      }
57      vsub(vs[1], vs[0], v1);
58      vsub(vs[2], vs[0], v2);
59      vcross(v1, v2, normal);
60      if(vdot(normal, up) / vlen(normal) < 0){
61        vscale(normal, -1.0, flippedNormal);
62        glNormal3fv(flippedNormal);
63      }else glNormal3fv(normal);
64      for(vertex = 0 ; vertex < anugavis.number_of_vertices ; vertex++){
65        vertIndex = anugavis.volumes[vol*anugavis.number_of_vertices + vertex];
66        glVertex3f(anugavis.x[vertIndex], anugavis.y[vertIndex],
67                   heights[frame * anugavis.number_of_points + vertIndex]);
68      }
69      glEnd();
70    }
71    glEndList();
72  }
73
74  free(heights);
75  return 0;
76}
77
78static void freeHeightQuantity(struct height_quantity_simple *height){
79  if(height->name != NULL) free(height->name);
80  if(glIsList(height->displayLists) == GL_TRUE)
81    glDeleteLists(height->displayLists, height->frames);
82  free(height);
83}
84
85int AnugaVis_DefineHeightQuantity(const char *name,
86                                  double offset, double scale,
87                                  GLfloat red, GLfloat green, GLfloat blue){
88  struct height_quantity_simple *height;
89  int ncstatus;
90  int ncvarid;
91  int numdims;
92  GLenum glerror;
93  /* Check that it's actually in the NetCDF file */
94  if((ncstatus = nc_inq_varid(anugavis.netcdfId, name, &ncvarid)) != NC_NOERR){
95    AnugaVis_NetCDFError(ncstatus);
96    return -1;
97  }     
98
99  /* Redefining a quantity? */
100  for(height = anugavis.heights ; height != NULL ; height = height->next)
101    if(!strcmp(name, height->name)) break;
102
103  if(height == NULL){ /* Make a new entry. */
104    if((height = xmalloc(sizeof(struct height_quantity_simple),
105                         "AnugaVis_DefineHeightQuantity()")) == NULL)
106      return -1;
107
108    height->name = NULL;
109    height->displayLists = -1;
110
111    if((height->name = xstrdup(name,
112                               "AnugaVis_DefineHeightQuantity()")) == NULL){
113      freeHeightQuantity(height);
114      return -1;
115    }
116
117    /* If the NetCDF variable is 2-dimensional, then it's dynamic. */
118    if((ncstatus = nc_inq_varndims(anugavis.netcdfId,
119                                   ncvarid, &numdims)) != NC_NOERR){
120      AnugaVis_NetCDFError(ncstatus);
121      freeHeightQuantity(height);
122      return -1;
123    }
124
125    height->frames = (numdims == 2) ? anugavis.number_of_timesteps : 1;
126    height->displayLists = glGenLists(height->frames);
127    if((glerror = glGetError()) != GL_NO_ERROR){
128      AnugaVis_OpenGLError(glerror);
129      freeHeightQuantity(height);
130      return -1;
131    }
132
133    if(compileDisplayLists(height) == -1){
134      freeHeightQuantity(height);
135      return -1;
136    }
137
138    height->next = anugavis.heights;
139    anugavis.heights = height;
140  }
141
142  height->offset = offset;
143  height->scale = scale;
144  height->red = red;
145  height->green = green;
146  height->blue = blue;
147  return 0;
148}
149
150void AnugaVis_DrawHeightQuantity(struct height_quantity_simple *height){
151  glPushMatrix();
152  glScalef(1, 1, height->scale);
153  glTranslatef(0, 0, height->offset);
154  glColor3f(height->red, height->green, height->blue);
155  glCallList(height->displayLists + (height->frames == 1 ? 0 :
156                                     anugavis.current_frame));
157  glPopMatrix();
158}
159
160void AnugaVis_UndefineHeightQuantity(const char *name){
161  struct height_quantity_simple *height = anugavis.heights;
162  struct height_quantity_simple *nextHeight;
163  if(height == NULL) return;
164  if(!strcmp(name, height->name)){
165    anugavis.heights = height->next;
166    freeHeightQuantity(height);
167    return;
168  }
169  for(; height != NULL ; height = height->next)
170    if(height->next == NULL) return;
171    if(!strcmp(name, height->next->name)){
172      nextHeight = height->next;
173      height->next = height->next->next;
174      freeHeightQuantity(nextHeight);
175      return;
176    }
177}
Note: See TracBrowser for help on using the repository browser.