From d8ae939a8d19ef9a8683687fd1a25232717b32f7 Mon Sep 17 00:00:00 2001 From: norly Date: Fri, 21 Oct 2011 16:48:59 +0100 Subject: [PATCH] Initial commit. grGL currently generates and shows a random graph of 1000 nodes with 6000 edges as well as a red box as an example of OpenGL drawing operations. --- .gitignore | 1 + Makefile | 19 ++++ src/glancillary.c | 155 +++++++++++++++++++++++++++++++ src/glancillary.h | 9 ++ src/graph.c | 117 +++++++++++++++++++++++ src/graph.h | 32 +++++++ src/main.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 564 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 src/glancillary.c create mode 100644 src/glancillary.h create mode 100644 src/graph.c create mode 100644 src/graph.h create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a007fea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e946635 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +CINCLUDE= +#CWARNS=-Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations -Wnested-externs +CWARNS=-Wall -Wpointer-arith -Wnested-externs +CFLAGS=$(CINCLUDE) $(CWARNS) -O2 +LIBS=-lglut -lGL -lGLU + +SRCDIR=src +SRCFILES=*.c +BINFILE=build/grGL + +$(BINFILE): src/*.c src/*.h Makefile + mkdir -p build + gcc $(CFLAGS) $(LIBS) -o $(BINFILE) src/*.c + +clean: + rm -rf build + +run: $(BINFILE) + build/grGL diff --git a/src/glancillary.c b/src/glancillary.c new file mode 100644 index 0000000..959cdac --- /dev/null +++ b/src/glancillary.c @@ -0,0 +1,155 @@ +#include +#include + +#include "glancillary.h" + + + +/**************************** + * GL init + ***************************/ + +void glaInit(void) +{ + glClearColor(0.0, 0.0, 0.0, 0.0); + glShadeModel(GL_FLAT); + //glShadeModel(GL_SMOOTH); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Init Model/view transformation + glMatrixMode(GL_MODELVIEW); + + // Reset MV matrix + glLoadIdentity(); +} + + + + +/**************************** + * GL camera simulation helpers + ***************************/ + +void glaCameraRotatef(GLfloat *cmat, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + glPushMatrix(); + glLoadIdentity(); + glRotatef(angle, x, y, z); + glMultMatrixf(cmat); + glGetFloatv(GL_MODELVIEW_MATRIX, cmat); + glPopMatrix(); +} + +void glaCameraTranslatef(GLfloat *cmat, GLfloat x, GLfloat y, GLfloat z) +{ + glPushMatrix(); + glLoadIdentity(); + glTranslatef(x, y, z); + glMultMatrixf(cmat); + glGetFloatv(GL_MODELVIEW_MATRIX, cmat); + glPopMatrix(); +} + + + + +/**************************** + * GL box drawing example + ***************************/ + +void glaDrawExample(void) +{ + // Draw the corner dots + glPointSize(5.0); + glColor3f(1.0, 1.0, 0.0); + glBegin(GL_POINTS); + glVertex3f(-1.0, -1.0, -1.0); + glVertex3f(1.0, -1.0, -1.0); + glVertex3f(1.0, 1.0, -1.0); + glVertex3f(-1.0, 1.0, -1.0); + glVertex3f(-1.0, -1.0, -1.0); + glVertex3f(-1.0, -1.0, 1.0); + glVertex3f(-1.0, 1.0, 1.0); + glEnd(); + + // Draw a line with fixed vertices + glColor3f(0.5, 1.0, 0.5); + glBegin(GL_LINE_STRIP); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(0.0, 0.5, 0.0); + glVertex3f(0.5, 0.5, 0.5); + glEnd(); + + // Draw the box boundaries + glColor3f(1.0, 0.0, 0.0); + glBegin(GL_LINE_STRIP); + glVertex3f(-1.0, -1.0, -1.0); + glVertex3f(1.0, -1.0, -1.0); + glVertex3f(1.0, 1.0, -1.0); + glVertex3f(-1.0, 1.0, -1.0); + glVertex3f(-1.0, -1.0, -1.0); + glVertex3f(-1.0, -1.0, 1.0); + glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(-1.0, 1.0, -1.0); + glEnd(); +} + + + + + + + + + + +/**************************** + * GL selection (currently defunct) + ***************************/ + +// Selection helper, currently defunct. +void glaSelect(int x, int y) +{ + int i; + GLuint namebuf[64] = {0}; + GLint hits, view[4]; + GLfloat projmat[16]; + + // Account for inverse Y coordinate + glGetIntegerv(GL_VIEWPORT, view); + y = view[3] - y; + + glSelectBuffer(64, namebuf); + glRenderMode(GL_SELECT); + + // Reset name stack + glInitNames(); + glPushName(0); + + // Restrict projection matrix to selection area + glGetFloatv(GL_PROJECTION_MATRIX, projmat); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluPickMatrix(x, y, 1.0, 1.0, view); + glMultMatrixf(projmat); + + // Redraw points to fill selection buffer + glMatrixMode(GL_MODELVIEW); + //glutSwapBuffers(); + //drawPoints(); + + // Reset projection + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + hits = glRenderMode(GL_RENDER); + + for (i = 0; i < hits; i++) + // Do something with the namebuf element here + break; + + glMatrixMode(GL_MODELVIEW); +} diff --git a/src/glancillary.h b/src/glancillary.h new file mode 100644 index 0000000..4fa63a2 --- /dev/null +++ b/src/glancillary.h @@ -0,0 +1,9 @@ +#ifndef _GLANCILLARY_H_ +#define _GLANCILLARY_H_ + +void glaInit(void); +void glaCameraRotatef(GLfloat *cmat, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +void glaCameraTranslatef(GLfloat *cmat, GLfloat x, GLfloat y, GLfloat z); +void glaDrawExample(void); + +#endif diff --git a/src/graph.c b/src/graph.c new file mode 100644 index 0000000..9a69ba5 --- /dev/null +++ b/src/graph.c @@ -0,0 +1,117 @@ +#include +#include + +#include "graph.h" + +/**************************** + * Graph memory + ***************************/ + +// Free the memory for a graph and substructures +void grFree(grGraph *g) +{ + if (g) + { + if (g->nodes) + free(g->nodes); + if (g->edges) + free(g->edges); + free(g); + } +} + + +// Allocate memory for a new graph, return NULL on any error +grGraph* grAlloc(int numnodes, int numedges) +{ + grGraph *g; + + g = malloc(sizeof(grGraph)); + if (!g) + return NULL; + + g->nodes = malloc(sizeof(grNode[numnodes])); + g->edges = malloc(sizeof(grEdge[numedges])); + if (!g->nodes || !g->edges) + goto ERR; + + g->numnodes = numnodes; + g->numedges = numedges; + + return g; + + ERR: + grFree(g); + return NULL; +} + + + +/**************************** + * Graph generation + ***************************/ + +// Randomize a graph +void grGenRandom(grGraph *g) +{ + int i; + int ns = g->numnodes; + int es = g->numedges; + + for (i = 0; i < ns; i++) + { + grNode *n = &g->nodes[i]; + + n->x = (float)rand() / (RAND_MAX/4); + n->y = (float)rand() / (RAND_MAX/4); + n->z = (float)rand() / (RAND_MAX/4); + n->colour = 0.0; + } + + for (i = 0; i < es; i++) + { + grEdge *e = &g->edges[i]; + + e->n1 = rand() / (RAND_MAX/ns); + e->n2 = rand() / (RAND_MAX/ns); + } +} + + + +/**************************** + * Graph drawing functions + ***************************/ + +// Draw the graph on the current OpenGL context +void graphDrawGL(grGraph *g) +{ + int i; + int ns = g->numnodes; + int es = g->numedges; + + // Draw edges + glColor4f(0.0, 0.0, 1.0, 0.5); + for (i = 0; i < es; i++) + { + grNode *n1 = &g->nodes[g->edges[i].n1]; + grNode *n2 = &g->nodes[g->edges[i].n2]; + + glBegin(GL_LINE_STRIP); + glVertex3f(n1->x, n1->y, n1->z); + glVertex3f(n2->x, n2->y, n2->z); + glEnd(); + } + + // Draw nodes + glPointSize(5.0); + glBegin(GL_POINTS); + for (i = 0; i < ns; i++) + { + grNode *n = &g->nodes[i]; + //glLoadName(i); // Load point number into depth buffer for selection + glColor4f(n->colour, 1.0, 0.3, 0.7); + glVertex3f(n->x, n->y, n->z); + } + glEnd(); +} diff --git a/src/graph.h b/src/graph.h new file mode 100644 index 0000000..0b70fab --- /dev/null +++ b/src/graph.h @@ -0,0 +1,32 @@ +#ifndef _GRAPH_H_ +#define _GRAPH_H_ + +typedef struct { + int n1; + int n2; +} grEdge; + + +typedef struct { + float x; + float y; + float z; + float colour; +} grNode; + + +typedef struct { + grNode *nodes; + grEdge *edges; + int numnodes; + int numedges; +} grGraph; + + +void grFree(grGraph *g); +grGraph* grAlloc(int numnodes, int numedges); +void grGenRandom(grGraph *g); +void graphDrawGL(grGraph *g); + + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..7825a2d --- /dev/null +++ b/src/main.c @@ -0,0 +1,231 @@ +// A simple OpenGL graph renderer. +// -- norly. + +#include +#include + +#include "graph.h" +#include "glancillary.h" + + +enum MOUSE_MODES { + MOUSE_IDLE, + MOUSE_ROTATING, + MOUSE_TRANSLATING, + MOUSE_TRANSLATING2, + MOUSE_DRAGGING +}; + +enum MOUSE_MODES mouse_mode = MOUSE_IDLE; +int mouse_x, mouse_y; +GLfloat cameramat[16]; + +// The graph itself. +grGraph *g = NULL; + + + + +/**************************** + * GLUT window event handlers + ***************************/ + +void on_display(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Set up the camera + glLoadMatrixf(cameramat); + + // Draw the old example objects + glaDrawExample(); + + // Draw the graph + graphDrawGL(g); + + glFlush(); + glutSwapBuffers(); +} + +void on_reshape(int w, int h) +{ + // Set up the Viewport transformation + glViewport(0, 0, (GLsizei) w, (GLsizei) h); + + // Set up the Projection transformation + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(90, (GLfloat)w/(GLfloat)h, 0.0, 5.0); + + // Switch to Model/view transformation for drawing objects + glMatrixMode(GL_MODELVIEW); +} + + + + +/**************************** + * GLUT input event handlers + ***************************/ + +void on_keyboard(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: + case 'Q': + case 'q': + exit(0); + break; + case 'a': + glaCameraTranslatef(cameramat, 1.0, 0.0, 0.0); + break; + case 'd': + glaCameraTranslatef(cameramat, -1.0, 0.0, 0.0); + break; + case 'w': + glaCameraTranslatef(cameramat, 0.0, 0.0, 1.0); + break; + case 's': + glaCameraTranslatef(cameramat, 0.0, 0.0, -1.0); + break; + case '=': + //glScalef(1.5, 1.5, 1.5); + break; + case '-': + //glScalef(1/1.5, 1/1.5, 1/1.5); + break; + } + glutPostRedisplay(); +} + +void on_specialKeyboard(int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_LEFT: + glaCameraRotatef(cameramat, -15.0, 0.0, 1.0, 0.0); + break; + case GLUT_KEY_UP: + glaCameraTranslatef(cameramat, 0.0, -1.0, 0.0); + break; + case GLUT_KEY_RIGHT: + glaCameraRotatef(cameramat, 15.0, 0.0, 1.0, 0.0); + break; + case GLUT_KEY_DOWN: + glaCameraTranslatef(cameramat, 0.0, 1.0, 0.0); + break; + } + glutPostRedisplay(); +} + + + +void on_mousebutton(int button, int state, int x, int y) +{ + if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) + { + if (mouse_mode != MOUSE_IDLE) + return; + + switch(glutGetModifiers()) + { + case 0: // When no modifiers are pressed + //mouse_mode = MOUSE_DRAGGING; + //glaSelect(x, y); + //break; + case GLUT_ACTIVE_SHIFT: + mouse_mode = MOUSE_ROTATING; + break; + case GLUT_ACTIVE_SHIFT | GLUT_ACTIVE_CTRL: + mouse_mode = MOUSE_TRANSLATING; + break; + case GLUT_ACTIVE_CTRL: + mouse_mode = MOUSE_TRANSLATING2; + break; + } + + mouse_x = x; + mouse_y = y; + } + else if (state == GLUT_UP) + mouse_mode = MOUSE_IDLE; +} + +void on_mousemove(int x, int y) +{ + int dx, dy; + + if (mouse_mode != MOUSE_IDLE) + { + dx = x - mouse_x; + dy = y - mouse_y; + mouse_x = x; + mouse_y = y; + + glPushMatrix(); + glLoadIdentity(); + switch(mouse_mode) + { + case MOUSE_TRANSLATING: + glTranslatef((0.1) * dx, (-0.1) * dy, 0.0); + break; + case MOUSE_TRANSLATING2: + glRotatef(dx, 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, (-0.1) * dy); + break; + case MOUSE_ROTATING: + glRotatef(dx, 0.0, 1.0, 0.0); + glRotatef(dy, 1.0, 0.0, 0.0); + break; + case MOUSE_DRAGGING: + case MOUSE_IDLE: + break; + } + glMultMatrixf(cameramat); + glGetFloatv(GL_MODELVIEW_MATRIX, cameramat); + glPopMatrix(); + } + glutPostRedisplay(); +} + + + + +/**************************** + * Main function + ***************************/ + +int main(int argc, char** argv) +{ + glutInit(&argc, argv); + glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA); + glutInitWindowSize (500, 500); + glutInitWindowPosition (100, 100); + glutCreateWindow (argv[0]); + + // Init graph and GL + g = grAlloc(1000, 6000); + srand(0); + grGenRandom(g); + glaInit (); + + // Init camera matrix + glMatrixMode(GL_MODELVIEW); + gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + glGetFloatv(GL_MODELVIEW_MATRIX, cameramat); + glLoadIdentity(); + + // Register callbacks + glutDisplayFunc(on_display); + glutReshapeFunc(on_reshape); + glutKeyboardFunc(on_keyboard); + glutSpecialFunc(on_specialKeyboard); + glutMouseFunc(on_mousebutton); + glutMotionFunc(on_mousemove); + + glutMainLoop(); + + grFree(g); + return 0; +} -- 2.30.2