/* * A viewer for patterns generated by the Reaction-Diffusion simulator for PLY objects. * (rdviewer) * * for usage info, run program without any parameters * */ #include #include #include #include "rply.h" /* cell activator (colour) level array */ GLfloat *activator; /* 3d object data arrays */ GLfloat **vertices; GLfloat **normals; long **faces; /* just some vars for extracting data from PLY (could be done better) */ long vertex=0, axis=0, face=0, fvertex=0, home=0, neighb=0; GLfloat maxv = -100; GLfloat minv = 100; /* angles and stuff for rotating and zooming the object */ GLfloat xangle = 0.0; GLfloat yangle = 0.0; GLfloat zangle = 0.0; GLfloat zoom = 1.5; GLfloat atX = 0.0; GLfloat atY = 0.0; /* global for number of vertices and faces */ long nvertices,nfaces; e_ply_type vertex_t, face_length_t, face_value_t; /* GLUT window identifier and viewport size (so we see whole object)*/ static int win; GLfloat view; /* input PLY filename */ char *filename; char plyfilename[15]; /* * * Display usage info * */ void printUsage() { printf("Results Viewer for Reaction-Diffusion Simulator\n\nusage:\trdviewer \n\n"); printf("\t\t- File exported from R-D simulators\n\n"); printf("\tControls:\n\t\tRotate on X axis: 'a' and 'd'\n\t\tRotate on Y axis: 's' and 'w'\n\t\tRotate on Z axis: 'z' and 'c'\n\t\tZoom in and out: '+', '-'\n\t\tMove object: Left, Right, Up and Down arrows\n\t\tReset view: 'r'\n\t\tQuit: 'q'\n\n"); } /* * * GLUT routines, callbacks and whatnot * */ void update(void) /* * update(): GLUT callback function. called every refresh. Need to call for a redisplay. */ { glutPostRedisplay(); } void face3(long face) /* * face3(face): Render the triangular polygon indexed to in the faces array by * input parameter face. Colour is set according to activator[] value for the face. * The glMaterial and glNormal calls are required for lighting. */ { GLfloat colour[] = {activator[face], activator[face], activator[face]}; // for cheetah colours: {activator[face]/1.4, activator[face]/2.0, 0}; GLfloat material[] = {activator[face], activator[face], activator[face], 1.0}; // {activator[face]/1.4, activator[face]/2.0, 0, 1.0}; glColor3fv(colour); glMaterialfv(GL_FRONT, GL_SPECULAR, material); glMaterialfv(GL_FRONT, GL_AMBIENT, material); glMaterialfv(GL_FRONT, GL_DIFFUSE, material); glBegin(GL_POLYGON); glNormal3fv(normals[faces[face][0]]); glVertex3fv(vertices[faces[face][0]]); glNormal3fv(normals[faces[face][1]]); glVertex3fv(vertices[faces[face][1]]); glNormal3fv(normals[faces[face][2]]); glVertex3fv(vertices[faces[face][2]]); glEnd(); } void display(void) /* * display(): GLUT display callback, it sets up the view, and rotation of the scene, * then it renders all the polygons, and swaps buffers (we're using double-buffering). */ { long i; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Set up the modelview transformation. */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //gluLookAt(6.0, 4.0, 14.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); gluLookAt(0, 0, zoom * view, atX, atY, 0.0, 0.0, 1.0, 0.0); glRotatef(xangle, 1.0, 0.0, 0.0); glRotatef(yangle, 0.0, 1.0, 0.0); glRotatef(zangle, 0.0, 0.0, 1.0); for (i=0;i maxv) maxv = vertices[vertex][axis]; if (vertices[vertex][axis] < minv) minv = vertices[vertex][axis]; axis++; if (eol) { vertex++; axis=0; } return 1; } static int normal_cb(p_ply_argument argument) /* * normal_cb(argument): RPly normal callback. Store the normal for each vertex. */ { long eol; ply_get_argument_user_data(argument, NULL, &eol); normals[vertex-1][axis] = (GLfloat)ply_get_argument_value(argument); axis++; if (eol) { //vertex++; axis=0; } return 1; } static int face_cb(p_ply_argument argument) /* * face_cb(argument): RPly face callback. Store vertex indices for each face. */ { long length, value_index; p_ply_property property; ply_get_argument_property(argument, &property, &length, &value_index); ply_get_property_info(property, NULL, NULL, &face_length_t, &face_value_t); switch (value_index) { case 0: case 1: faces[face][fvertex++] = (long)ply_get_argument_value(argument); break; case 2: faces[face][fvertex++] = (long)ply_get_argument_value(argument); face++; fvertex=0; break; default: break; } return 1; } /* * * Lots of initialisation stuff. Loading the object, etc. * */ void init(void) { long i,j; FILE *fp; p_ply ply; GLfloat mat_specular[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat mat_shininess[] = { 10.0 }; GLfloat light_ambient[] = {0.1, 0.1, 0.1, 0.5}; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; float concA, concI; /* some GL initialisation */ glClearColor(0.0, 0.0, 0.5, 1.0); glEnable(GL_DEPTH_TEST); /* load PLY file */ ply = ply_open(plyfilename, NULL); if ((!ply) || (!ply_read_header(ply))) { printf("Error opening PLY file or reading header.\n"); exit; } /* set callbacks for PLY reading and get number of vertices and faces */ nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 1); ply_set_read_cb(ply, "vertex", "xnorm", normal_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "ynorm", normal_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "znorm", normal_cb, NULL, 1); nfaces = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); if (nfaces == 0) nfaces = ply_set_read_cb(ply, "face", "vertex_index", face_cb, NULL, 0); printf("Vertices: %ld\nFaces: %ld\n", nvertices, nfaces); /* mallocate memory for arrays */ /* 3d structure data */ vertices = malloc(nvertices * sizeof(GLfloat *)); normals = malloc(nvertices * sizeof(GLfloat *)); for(i=0;i