summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornorly <ny-git@enpas.org>2011-10-21 16:48:59 +0100
committernorly <ny-git@enpas.org>2011-10-21 16:48:59 +0100
commitd8ae939a8d19ef9a8683687fd1a25232717b32f7 (patch)
treec48addac0a98f9297a425228ac833999373f9f81
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.
-rw-r--r--.gitignore1
-rw-r--r--Makefile19
-rw-r--r--src/glancillary.c155
-rw-r--r--src/glancillary.h9
-rw-r--r--src/graph.c117
-rw-r--r--src/graph.h32
-rw-r--r--src/main.c231
7 files changed, 564 insertions, 0 deletions
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 <GL/gl.h>
+#include <GL/glu.h>
+
+#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 <stdlib.h>
+#include <GL/gl.h>
+
+#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 <stdlib.h>
+#include <GL/glut.h>
+
+#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;
+}