I have begin to convert a simple NeHe tutorial for to make the base of the chromadepth program
// YLP 12/12/12 : transformation of a basic NeHe OpenGL code source sample (http://nehe.gamedev.net/tutorial/3d_shapes/10035/)
// for to handle chromadepth PGM pictures
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h> // Header File For The GLUT Library
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#include <unistd.h> // needed to sleep
/* ASCII code for the escape key. */
#define ESCAPE 27
/* The number of our GLUT window */
int window;
/* specifics variables used for the PGM chromadepth */
int width = 0, height = 0, maxVal = 0;
int **gridData = NULL;
int *indicesArray = NULL;
float *verticesArray = NULL;
float *normalsArray = NULL;
int totalVertices = 0;
int totalIndices = 0;
int totalNormals = 0;
int vertexPositionAttr = 0;
GLuint indexBuffer = 0;
GLuint vertexBuffer = 0;
GLuint normalsBuffer = 0;
float rarray = 0;
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height==0) // Prevent A Divide By Zero If The Window Is Too Small
Height=1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
/* Init into the drawing function. */
void InitGLScene()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
}
/* The function called whenever a key is pressed. */
void keyPressed(unsigned char key, int x, int y)
{
/* avoid thrashing this call */
usleep(100);
/* If escape is pressed, kill everything. */
if (key == ESCAPE)
{
/* shut down our window */
glutDestroyWindow(window);
/* exit the program...normal termination. */
exit(0);
}
}
// Here are located specifics Chromadepth funcs
double getNormalizedX(unsigned long x)
{
return ((double)x/((width-1)) * 2.0 - 1.0);
}
double getNormalizedY(unsigned long y)
{
return ((double)(height - 1 - y) /( (height - 1))* 2.0 - 1.0);
}
double getNormalizedZ(unsigned long x,unsigned long y)
{
unsigned long yPrime = (height - 1) - y;
// return (0.25 * gridData[yPrime][x]) / (double)maxVal;
return -fabs(gridData[yPrime][x]) / 20.0f;
}
void loadPGMFile(char *filename)
{
FILE *pgmFile;
int x, y;
char pgm_name[10000];
unsigned char temp[4];
// pgmFile = fopen("sample.pgm","r");
pgmFile = fopen(filename,"r");
if( pgmFile == NULL )
{
printf("Canot open the %s file :(
", filename);
return;
}
fgets(pgm_name,10000,pgmFile);
fscanf(pgmFile,"%d", &width);
fscanf(pgmFile,"%d", &height);
fscanf(pgmFile,"%d", &maxVal);
printf("%s : width=%d height=%d maxVal=%d
", filename, width, height, maxVal);
gridData = (int **)malloc(height * sizeof(int *));
for( y = 0; y < height; y++)
{
gridData[y] = malloc(width * sizeof(int));
for(x = 0; x < width; x++)
{
// fscanf(pgmFile, "%d", &gridData[y][x]);
fscanf(pgmFile, "%c", temp);
gridData[y][x] = temp[0];
// printf("gridData[%d][%d] = %d
", y, x, gridData[y][x] );
}
}
}
void InitTerrain()
{
size_t x,y;
unsigned long vertexIndex = 0;
// XXX Change this allocation once everything is finished.
indicesArray = malloc(width * height * 6 * sizeof(GLuint));
verticesArray = malloc(width * height * 3 * sizeof(GLfloat));
normalsArray = malloc(width * height * 3 * sizeof(GLfloat));
int vertsI = 0, indicesI=0, normalsI = 0;
unsigned long i=0,j=0;
for(i = 0; i < width; i++)
{
if(i > 1)
{
indicesArray[indicesI++] = vertexIndex;
indicesArray[indicesI++] = vertexIndex;
}
for(j = 0; j < height; j++)
{
verticesArray[vertsI++] = getNormalizedX(i);
verticesArray[vertsI++] = getNormalizedY(j);
verticesArray[vertsI++] = getNormalizedZ(i,j);
if(i > 0)
{
indicesArray[indicesI++] = vertexIndex;
indicesArray[indicesI++] = vertexIndex - height;
}
vertexIndex++;
}
if(i > 0)
{
indicesArray[indicesI++] = vertexIndex - height -1;
indicesArray[indicesI++] = vertexIndex - height -1;
}
/**
** Trying to create Normals*
**/
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, verticesArray);
// glEnableClientState(GL_NORMAL_ARRAY);
// glVertexPointer(3, GL_FLOAT, 0, normalsArray);
totalVertices = vertsI / 3;
totalIndices = indicesI;
totalNormals = normalsI;
printf("%d vertices, %d indices, %d normals
", totalVertices, totalIndices, totalNormals);
/*
for( i = 0 ; i < totalVertices ; i++)
{
printf("chromadepth(%f,%f) = %f
", verticesArray[i*3], verticesArray[i*3+1], verticesArray[i*3+2]);
}
*/
}
void DrawTerrain()
{
glLoadIdentity();
// glRotatef(rarray, 0.0f,1.0f,0.0f); // Rotate The Terrain On The Y axis
glScalef(0.02f, 0.02f, 0.02f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3f(1.0f,1.0f,1.0f);
glDrawElements(GL_TRIANGLE_STRIP, totalIndices, GL_UNSIGNED_INT, indicesArray);
rarray += 1.0f;
}
void DrawGLScene()
{
InitGLScene();
DrawTerrain();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
/* Initialize GLUT state - glut will take any command line arguments that pertain to it or
X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */
glutInit(&argc, argv);
/* Select type of Display mode:
Double buffer
RGBA color
Alpha components supported
Depth buffered for automatic clipping */
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
/* get a 640 x 480 window */
glutInitWindowSize(640, 480);
/* the window starts at the upper left corner of the screen */
glutInitWindowPosition(0, 0);
/* Open a window */
window = glutCreateWindow("Chromadepth PGM by YLP v0.0 (12/12/12) ");
/* Register the function to do all our OpenGL drawing. */
glutDisplayFunc(&DrawGLScene);
/* Go fullscreen. This is as soon as possible. */
// glutFullScreen();
/* Even if there are no events, redraw our gl scene. */
glutIdleFunc(&DrawGLScene);
/* Register the function called when our window is resized. */
glutReshapeFunc(&ReSizeGLScene);
/* Register the function called when the keyboard is pressed. */
glutKeyboardFunc(&keyPressed);
/* Initialize our window. */
InitGL(640, 480);
/* Chromadepth loading */
loadPGMFile("sample.pgm");
InitTerrain();
/* Start Event Processing Engine */
glutMainLoop();
return 1;
}
I compile this using gcc on my Linux box
gcc chromadepth.c -o chromadepth -lX11 -lglut -lGL -lGLU -lm
The important functions are loadPGMFile(), getNormalized*(), InitTerrain() and DrawTerrain()
(I have a little modify your source for to can use a variable filename of the .pgm picture and read unsigned bytes instead ints [this is perhaps for this that I have a problem with the format …])
I have found a depth picture at http://dev.bukkit.org/profiles/thedeadlytao/, converted it to a grayscale picture, resample to 30x30 (for to have an array that I can speedly analyze) and save it to sample.pgm DL.FREE.FR
I have discover a problem with the reading of the pgm file because GIMP/ImageMagick store a label on the header
=> I have suppress this line and it can read the file
But I think that the data isn’t really loaded at the good format
(I read pixels data from disk as unsigned chars and have modified the getNormalizedZ() function for to have something displayed)
PS : I add the computation of normals as soon as I can properly read/decode .pgm files 
(and/or can properly handle the scaling of the depth)