Initial commit.
authornorly <ny-git@enpas.org>
Fri, 21 Oct 2011 15:48:59 +0000 (16:48 +0100)
committernorly <ny-git@enpas.org>
Fri, 21 Oct 2011 15:48:59 +0000 (16:48 +0100)
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 [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/glancillary.c [new file with mode: 0644]
src/glancillary.h [new file with mode: 0644]
src/graph.c [new file with mode: 0644]
src/graph.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a007fea
--- /dev/null
@@ -0,0 +1 @@
+build/*
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..959cdac
--- /dev/null
@@ -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 (file)
index 0000000..4fa63a2
--- /dev/null
@@ -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 (file)
index 0000000..9a69ba5
--- /dev/null
@@ -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 (file)
index 0000000..0b70fab
--- /dev/null
@@ -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 (file)
index 0000000..7825a2d
--- /dev/null
@@ -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;
+}