#ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_GL_GL_H # include #elif HAVE_OPENGL_GL_H # include #endif #include #include #include "error.h" #include "globals.h" #include "height_quantity.h" #include "netcdf_util.h" #include "vector.h" #include "xfunctions.h" static int compileDisplayLists(struct height_quantity_simple *height){ int frame; unsigned int vol; unsigned int vertex; int vertIndex; vector vs[3]; vector v1; vector v2; vector normal; vector flippedNormal; vector up = {0.0, 0.0, 1.0}; float *heights = xmalloc(sizeof(float) * anugavis.number_of_points * height->frames, "compileDisplayLists()"); if(heights == NULL) return -1; if(nc_get_var_float_by_name(anugavis.netcdfId, height->name, heights) != NC_NOERR){ free(heights); return -1; } for(frame = 0 ; frame < height->frames ; frame++){ glNewList(height->displayLists + frame, GL_COMPILE); for(vol = 0 ; vol < anugavis.number_of_volumes ; vol++){ glBegin(GL_POLYGON); for(vertex = 0 ; vertex < 3 ; vertex++){ /* Calculate normal */ vertIndex = anugavis.volumes[vol*anugavis.number_of_vertices + vertex]; vs[vertex][0] = anugavis.x[vertIndex]; vs[vertex][1] = anugavis.y[vertIndex]; vs[vertex][2] = heights[frame*anugavis.number_of_points + vertIndex]; } vsub(vs[1], vs[0], v1); vsub(vs[2], vs[0], v2); vcross(v1, v2, normal); if(vdot(normal, up) / vlen(normal) < 0){ vscale(normal, -1.0, flippedNormal); glNormal3fv(flippedNormal); }else glNormal3fv(normal); for(vertex = 0 ; vertex < anugavis.number_of_vertices ; vertex++){ vertIndex = anugavis.volumes[vol*anugavis.number_of_vertices + vertex]; glVertex3f(anugavis.x[vertIndex], anugavis.y[vertIndex], heights[frame * anugavis.number_of_points + vertIndex]); } glEnd(); } glEndList(); } free(heights); return 0; } static void freeHeightQuantity(struct height_quantity_simple *height){ if(height->name != NULL) free(height->name); if(glIsList(height->displayLists) == GL_TRUE) glDeleteLists(height->displayLists, height->frames); free(height); } int AnugaVis_DefineHeightQuantity(const char *name, double offset, double scale, GLfloat red, GLfloat green, GLfloat blue){ struct height_quantity_simple *height; int ncstatus; int ncvarid; int numdims; GLenum glerror; /* Check that it's actually in the NetCDF file */ if((ncstatus = nc_inq_varid(anugavis.netcdfId, name, &ncvarid)) != NC_NOERR){ AnugaVis_NetCDFError(ncstatus); return -1; } /* Redefining a quantity? */ for(height = anugavis.heights ; height != NULL ; height = height->next) if(!strcmp(name, height->name)) break; if(height == NULL){ /* Make a new entry. */ if((height = xmalloc(sizeof(struct height_quantity_simple), "AnugaVis_DefineHeightQuantity()")) == NULL) return -1; height->name = NULL; height->displayLists = -1; if((height->name = xstrdup(name, "AnugaVis_DefineHeightQuantity()")) == NULL){ freeHeightQuantity(height); return -1; } /* If the NetCDF variable is 2-dimensional, then it's dynamic. */ if((ncstatus = nc_inq_varndims(anugavis.netcdfId, ncvarid, &numdims)) != NC_NOERR){ AnugaVis_NetCDFError(ncstatus); freeHeightQuantity(height); return -1; } height->frames = (numdims == 2) ? anugavis.number_of_timesteps : 1; height->displayLists = glGenLists(height->frames); if((glerror = glGetError()) != GL_NO_ERROR){ AnugaVis_OpenGLError(glerror); freeHeightQuantity(height); return -1; } if(compileDisplayLists(height) == -1){ freeHeightQuantity(height); return -1; } height->next = anugavis.heights; anugavis.heights = height; } height->offset = offset; height->scale = scale; height->red = red; height->green = green; height->blue = blue; return 0; } void AnugaVis_DrawHeightQuantity(struct height_quantity_simple *height){ glPushMatrix(); glScalef(1, 1, height->scale); glTranslatef(0, 0, height->offset); glColor3f(height->red, height->green, height->blue); glCallList(height->displayLists + (height->frames == 1 ? 0 : anugavis.current_frame)); glPopMatrix(); } void AnugaVis_UndefineHeightQuantity(const char *name){ struct height_quantity_simple *height = anugavis.heights; struct height_quantity_simple *nextHeight; if(height == NULL) return; if(!strcmp(name, height->name)){ anugavis.heights = height->next; freeHeightQuantity(height); return; } for(; height != NULL ; height = height->next) if(height->next == NULL) return; if(!strcmp(name, height->next->name)){ nextHeight = height->next; height->next = height->next->next; freeHeightQuantity(nextHeight); return; } }