Hi, I am basically writing a program that reads in ASCII files exported from 3ds max in order to reproduce an object in OpenGL. My code works fine for one object and I've even got it working for two as long as the second object contains less vertices/facet windings than the previous. Problem is, if I try and load any more than two or if the first object is 'smaller' than any that follow, my program crashes. I don't have much experiene using C but I'm pretty sure it's something to do with the way in which I am trying to allocate and then reallocate the memory for my 3d array.

I've attached the ASCII files (as text files because I can't upload .ASE files) that I'm trying to read and a text file with the actual code(for, perhaps, easier viewing). Any help would be greatly appreciated

code below:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "glut.h"
#include <GL\gl.h>
#include <GL\glu.h>

GLint ***facets; 
GLfloat ***vertices;

int nRows, nCols, row, col, i, j, k, numVertices, numFacets, shapeNum;
int numShapes = 2;
int numCols = 3;
GLfloat rquad;

//int totalVertices = 0;
//int totalFacets = 0;

int nFacets[10];
int nVertices[10];


GLfloat colors[][3] = {{0.0,0.0,0.0},{1.0,0.0,0.0},{1.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,0.0,1.0},{1.0,1.0,1.0},
{0.0,1.0,1.0}};

//All methods used
void display();
void adjustSize(GLsizei, GLsizei);
void animate();
//void mouse(int btn, int state, int x, int y);
void polygon(int a, int b, int c, int shapeNum);
void shape(int shapeNum);

void loadShape(char filename[20], int shapeNum);
char *readFile(FILE *sceneFile);


GLint ***allocate_memoryi(int nShapes, int nRows, int nCols)
{
	int ***shapeArray;
	shapeArray = (int***) malloc(nShapes * sizeof(int**));
	for(i=0; i<nShapes; ++i)
	{
		shapeArray[i] = (int**) malloc(nRows * sizeof(int));
		for(j=0; j<nRows; ++j)
		{
			shapeArray[i][j] = (int*) malloc(nCols * sizeof(int));
		}
	}
	return shapeArray;
}


GLfloat ***allocate_memoryf(int nShapes, int nRows, int nCols)
{
	float ***shapeArray;
	shapeArray = (float***) malloc(nShapes * sizeof(float**));
	for(i=0; i<nShapes; ++i)
	{
		shapeArray[i] = (float**) malloc(nRows * sizeof(float));
		for(j=0; j<nRows; ++j)
		{
			shapeArray[i][j] = (float*) malloc(nCols * sizeof(float));
		}
	}
	return shapeArray;
}


GLfloat ***reallocate_memoryf(int nShapes, int nRows, int nCols)
{
	float ***shapeArray;
	shapeArray = (float***) realloc(vertices, nShapes * sizeof(float**));
	for(i=0; i<nShapes; ++i)
	{
		shapeArray[i] = (float**) realloc(vertices[i], nVertices[i] * sizeof(float));
		for(j=0; j<nVertices[i]; ++j)
		{
			shapeArray[i][j] = (float*) realloc(vertices[i][j], nCols * sizeof(float));
		}
	}
	return shapeArray;
}

GLint ***reallocate_memoryi(int nShapes, int nRows, int nCols)
{
	int ***shapeArray;
	shapeArray = (int***) realloc(facets, nShapes * sizeof(int**));
	for(i=0; i<nShapes; ++i)
	{
		shapeArray[i] = (int**) realloc(facets[i], nFacets[i] * sizeof(int));
		for(j=0; j<nFacets[i]; ++j)
		{
			shapeArray[i][j] = (int*) realloc(facets[i][j], nCols * sizeof(int));
		}
	}
	return shapeArray;
}


int main(int argc, char **argv)
{
	loadShape("test_pyramid.ASE", 0);//won't work this way round as pyramid requires less vertices/facet windings
	loadShape("test_sphere.ASE", 1);

	//loadShape("test_sphere.ASE", 0);
	//loadShape("test_pyramid.ASE", 1);//does work this way round

	//loadShape("test_box.ASE", 2); as soon as a third shape is added it also crashes


	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutCreateWindow("TEST READING ASCII FILE");
	glutDisplayFunc(display);
	glutReshapeFunc(adjustSize);
	//glutMouseFunc(mouse);
	glutIdleFunc(animate);
	glEnable(GL_DEPTH_TEST); //enable hidden surface removal
	glutMainLoop();
	return 0;
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glRotatef(rquad, 1.0f, 1.0f, 1.0f);
	glColor3f(0.0f, 0.0f, 1.0f);
	shape(0);
	shape(1);
	//shape(2);
	glFlush();
	glutSwapBuffers();
}

void adjustSize(GLsizei w, GLsizei h)
{
	glViewport(0,0,w,h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-30.0, 30.0, -30.0 * (GLfloat) h / (GLfloat) w,30.0 * (GLfloat) h / (GLfloat) w, -100.0, 100.0);
	else if (h <= w)
		glOrtho(-30.0 * (GLfloat) w / (GLfloat) h, 30.0 * (GLfloat) w / (GLfloat) h, -30.0, 30.0, -100.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void animate()
{
	rquad -= 0.15f;
	display();
}

void polygon(int a, int b, int c, int shapeNum)
{
	//for(i = 0; i < numShapes; ++i)
	//{
	//glBegin(GL_POLYGON);
	glBegin(GL_LINE_LOOP);
		glColor3f(0.0,0.0,1.0);
		//glColor3fv(colors[a]);
		glVertex3fv(vertices[shapeNum][a]);
		//glColor3fv(colors[b]);
		glVertex3fv(vertices[shapeNum][b]);
		//glColor3fv(colors[c]);
		glVertex3fv(vertices[shapeNum][c]);
	glEnd();
	//}
}

void shape(int shapeNum)
{
		for(row = 0; row < nFacets[shapeNum]; ++row)
		{
			polygon(facets[shapeNum][row][0], facets[shapeNum][row][1], facets[shapeNum][row][2], shapeNum);
		}
}

void loadShape(char filename[20], int shapeNum)
{
	char *fullFile = readFile(fopen (filename, "rb"));
	char *pch;
	int v, f;
	char *delim = " *\x9\xA\xD\\:";

	pch = strtok(fullFile, delim);
	while(pch != NULL)
	{
		if(strcmp(pch, "MESH_NUMVERTEX") == NULL)
		{
			numVertices = atoi(strtok (NULL, delim));
			printf("numVertices%d\n", numVertices);
			//totalVertices += numVertices;
			nVertices[shapeNum] = numVertices;
			if(shapeNum == 0)
				vertices = allocate_memoryf(numShapes, nVertices[shapeNum], numCols);
			else
				vertices = reallocate_memoryf(numShapes, numVertices, numCols);
		}

		if(strcmp(pch, "MESH_NUMFACES") == NULL)
		{
			numFacets = atoi(strtok (NULL, delim));
			printf("numFacets%d\n", numFacets);
			//totalFacets += numFacets;
			nFacets[shapeNum] = numFacets;
			if(shapeNum == 0)
				facets = allocate_memoryi(numShapes, nFacets[shapeNum], numCols);
			else
				facets = reallocate_memoryi(numShapes, numFacets, numCols);
		}

		if(strcmp(pch, "MESH_VERTEX") == NULL)
		{
			v = atoi(strtok (NULL, delim));
			printf("v=%d\n", v);
			for(i = 0; i < numCols; ++i)
			{
				vertices[shapeNum][v][i] = atof(strtok (NULL, delim));
				printf("%f ", vertices[shapeNum][v][i]);
			}
			printf("\n");
		}

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			strtok (NULL, delim);
			for(i = 0; i < numCols; ++i)
			{
				facets[shapeNum][f][i] = atoi(strtok (NULL, delim));
				printf("%d: ", facets[shapeNum][f][i]);
				strtok(NULL, delim);
			}
		}
		pch = strtok (NULL, delim);
	}
	free (fullFile);
}

char *readFile(FILE *sceneFile)
{
	long fileSize;
	char *fullFile;
	size_t result;

	if(sceneFile==NULL)
	{
		fputs ("Error 1", stderr);
		exit(1);
	}

	fseek(sceneFile, 0, SEEK_END);
	fileSize = ftell(sceneFile);
	rewind(sceneFile);

	fullFile = (char*)malloc(sizeof(char)*fileSize);
	if(fullFile == NULL)
	{
		fputs("Error 2", stderr);
		exit(2);
	}

	result = fread(fullFile,1,fileSize,sceneFile);
	if(result != fileSize)
	{
		fputs("Error 3", stderr);
		exit(3);
	}

	fclose(sceneFile);

	return fullFile;
}

I only looked at allocate_memoryi and reallocate_memoryi. Any problems with them probably also exist in the "f" models. Compare the code below with the original carefully to see the differences.

GLint ***allocate_memoryi(int nShapes, int nRows, int nCols)
{
	GLint ***shapeArray;
	shapeArray = (GLint***) malloc(nShapes * sizeof(GLint**));
	for(i=0; i<nShapes; ++i)
	{
		shapeArray[i] = (GLint**) malloc(nRows * sizeof(GLint*));
		for(j=0; j<nRows; ++j)
		{
			shapeArray[i][j] = (GLint*) malloc(nCols * sizeof(GLint));
		}
	}
	return shapeArray;
}

GLint ***reallocate_memoryi(int nShapes, int nRows, int nCols)
{
	GLint ***shapeArray;
	shapeArray = (GLint***) realloc(facets, nShapes * sizeof(GLint**));
	for(i=0; i<nShapes; ++i)
	{
		shapeArray[i] = (GLint**) realloc(shapeArray[i], nRows * sizeof(GLint*));
		for(j=0; j<nRows[i]; ++j)
		{
			shapeArray[i][j] = (GLint*) realloc(shapeArray[i][j], nCols * sizeof(GLint));
		}
	}
	return shapeArray;
}

Also, you really shouldn't be using all those globals. It's just lazy, and as your program gets bigger it will come back to haunt you.

I've tried adjusting my code as you suggested Nucleon but it still isn't running.

I get this error message when ever I run it with more than two shapes being loaded:

Unhandled exception at 0x60d912b4 (msvcr90d.dll) in Final_3d_read.exe: 0xC0000005: Access violation reading location 0xcdcdcdc8.

Also there is a bit of code that is highlighted in the dbgheap.c code that is produced:

/*---------------------------------------------------------------------------
 *
 * Memory management
 *
 --------------------------------------------------------------------------*/

/***
*static int CheckBytes() - verify byte range set to proper value
*
*Purpose:
*       verify byte range set to proper value
*
*Entry:
*       unsigned char *pb       - pointer to start of byte range
*       unsigned char bCheck    - value byte range should be set to
*       size_t nSize            - size of byte range to be checked
*
*Return:
*       TRUE - if all bytes in range equal bcheck
*       FALSE otherwise
*
*******************************************************************************/
extern "C" static int __cdecl CheckBytes(
        unsigned char * pb,
        unsigned char bCheck,
        size_t nSize
        )
{
        int bOkay = TRUE;
        while (nSize--)
        {
            if (*pb++ != bCheck)   //this line is highlighted with an arrow
            {
/* Internal error report is just noise; calling functions all report results - JWM */
/*                _RPT3(_CRT_WARN, "memory check error at 0x%p = 0x%02X, should be 0x%02X.\n", */
/*                    (BYTE *)(pb-1),*(pb-1), bCheck); */
                bOkay = FALSE;
            }
        }
        return bOkay;
}

You're right. I wasn't thinking clearly with that last piece of sh..., I mean code.

Since you do not seem to need the previous data, you may as well just free the memory and allocate it again with your allocate_memory function. So just free it like this before allocating it again.

void release_memoryi(GLint*** facets, int nShapes, int nRows) {
    int i, j;
    for(i = 0; i < nShapes; ++i) {
        for(j = 0; j < nRows; ++j) free(facets[i][j]);
        free(facets[i]);
    }
    free(facets);
}

Hmmm...it seems to be reading in the object vertices and facet windings now (or so I think) but I get an error further down the line when I try to draw the objects. I get the error:

Unhandled exception at 0x00eb22c1 in Final_3d_read.exe: 0xC0000005: Access violation reading location 0x373f5454.

I assume that this means I am accessing the data in the array incorrectly. The error occurs as soon as the line 'glVertex3fv(vertices[shapeNum][a]);' is executed in the method below:

void polygon(int a, int b, int c, int shapeNum)
{
    //glBegin(GL_POLYGON);
    glBegin(GL_LINE_LOOP);
        glColor3f(0.0,0.0,1.0);
        //glColor3fv(colors[a]);
        glVertex3fv(vertices[shapeNum][a]);  //when it reaches this line
        //glColor3fv(colors[b]);
        glVertex3fv(vertices[shapeNum][b]);
        //glColor3fv(colors[c]);
        glVertex3fv(vertices[shapeNum][c]);
    glEnd();
}

This is the method that calls the above:

void shape(int shapeNum)
{
        for(row = 0; row < nFacets[shapeNum]; ++row)
        {
            polygon(facets[shapeNum][row][0], facets[shapeNum][row][1], facets[shapeNum][row][2], shapeNum);
        }
}

I've looked further into it and I think that it could perhaps be my allocation method that still isn't qute right because after making the changes that you have suggested Nucleon, it allows me to draw one object still but as soon as I try drawing more than one I get the error mentioned in the previous post.

Post your entire program again and I'll take a look at it.

Ok I realised that I will need to read multiple objects from a single file so I've changed it quite a bit but it still works the same and I'm still getting the exact same error as before.

Code below:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "glut.h"
#include <GL\gl.h>
#include <GL\glu.h>

int ***facets; 
float ***vertices;
int numObjects;

int numShapes = 1;
int numCols = 3;
GLfloat rquad;

GLfloat ud = 0.0;
GLfloat lr = 0.0;
GLfloat zz = 5.0;

GLfloat rShapeY = 0.0;
GLfloat rShapeX = 0.0;

int *nFacets;
int *nVertices;


GLfloat colors[][3] = {{0.0,0.0,0.0},{1.0,0.0,0.0},{1.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,0.0,1.0},{1.0,1.0,1.0},
{0.0,1.0,1.0}};

//All methods used
void display();
void adjustSize(GLsizei, GLsizei);
void animate();
//void mouse(int btn, int state, int x, int y);
void Keyboard(unsigned char key, int x, int y);
void SpecialKeys(int key, int x, int y);
void polygon(int a, int b, int c);
void shape();

void loadShape(char filename[20]);
char *readFile(FILE *sceneFile);


void countObjects(char fileName[20])
{
	char * fullFile = readFile(fopen (fileName, "rb"));
	char * pch;
	char * delim = " *\x9\xA\xD\\:";
	int i;

	numObjects = 0;

	pch = strtok(fullFile, delim);
	while(pch != NULL)//while NEOF
	{
		if(strcmp(pch, "GEOMOBJECT")==NULL)
			numObjects++;
		pch = strtok(NULL, delim);
	}
	vertices = (float ***) calloc(numObjects, sizeof(float **));
	facets = (int ***) calloc(numObjects, sizeof(int **));
	nVertices = (int *) calloc(numObjects, sizeof(int));
	nFacets = (int *) calloc(numObjects, sizeof(int));
}


void SetupRC()
    {
    // Light values and coordinates
    GLfloat  ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
    GLfloat  diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };

    glEnable(GL_DEPTH_TEST);	// Hidden surface removal
    glFrontFace(GL_CCW);		// Counter clock-wise polygons face out
    glEnable(GL_CULL_FACE);		// Do not calculate inside of jet

    // Enable lighting
    glEnable(GL_LIGHTING);

    // Setup and enable light 0
    glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
    glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
    glEnable(GL_LIGHT0);

    // Enable color tracking
    glEnable(GL_COLOR_MATERIAL);
	
    // Set Material properties to follow glColor values
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    // Light blue background
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
    
    glEnable(GL_NORMALIZE);
    }


int main(int argc, char **argv)
{

	//loadShape("test_sphere.ASE", 0);
	loadShape("club.ASE");


	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutCreateWindow("TEST READING ASCII FILE");
	glutDisplayFunc(display);
	glutReshapeFunc(adjustSize);
	//glutMouseFunc(mouse);
	glutKeyboardFunc(Keyboard);
	glutSpecialFunc(SpecialKeys);
	glutIdleFunc(animate);
	glEnable(GL_DEPTH_TEST); //enable hidden surface removal
	SetupRC();
	glutMainLoop();
	return 0;
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	gluLookAt(lr,ud,zz,0.0,0.0,0.0,0.0,1.0,0.0);
	glPushMatrix();
		glTranslatef(10.0f,0.0f,0.0f);
		shape();
	glPopMatrix();
	glPushMatrix();
		//glRotatef(rquad, 1.0f, 1.0f, 1.0f);
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		shape();
	glPopMatrix();
	glColor3f(0.0f, 0.0f, 1.0f);
	glFlush();
	glutSwapBuffers();
}

void adjustSize(GLsizei w, GLsizei h)
{
	/*GLfloat fAspect;
	//Prevent a divide by zero
	if(h == 0)
		h = 1;*/
	//Set viewport to window dimensions
	glViewport(0,0,w,h);
	//fAspect = (GLfloat)w / (GLfloat)h;

	//Reset coordinate system
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/*//Produce the perspective projection
	gluPerspective(60.0f, fAspect, 1.0f, 400.0f);*/

	if (w <= h)
		glOrtho(-30.0, 30.0, -30.0 * (GLfloat) h / (GLfloat) w,30.0 * (GLfloat) h / (GLfloat) w, -200.0, 100.0);
	else if (h <= w)
		glOrtho(-30.0 * (GLfloat) w / (GLfloat) h, 30.0 * (GLfloat) w / (GLfloat) h, -30.0, 30.0, -200.0, 100.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void animate()
{
	//rquad -= 0.15f;
	display();
}

void polygon(int a, int b, int c)
{
	int i;
	for(i = 0; i < numObjects; ++i)
	{
		//glBegin(GL_POLYGON);
		glBegin(GL_LINE_LOOP);
			glColor3ub(255,150,10);
			glVertex3fv(vertices[i][a]);             //This is where the program crashes
			glVertex3fv(vertices[i][b]);
			glVertex3fv(vertices[i][c]);
		glEnd();
	}
}

void shape()
{
	int i, j;
	for(i = 0; i < numObjects; ++i)
	{
		for(j = 0; j < nFacets[i]; ++j)
		{
			polygon(facets[i][j][0], facets[i][j][1], facets[i][j][2]);
		}
	}
}

void loadShape(char fileName[20])
{
	char *fullFile = readFile(fopen (fileName, "rb"));
	char *pch;
	int v, f;
	char *delim = " *\x9\xA\xD\\:";
	int i, nObj;

	countObjects(fileName);
	nObj = -1;

	pch = strtok(fullFile, delim);
	while(pch != NULL)
	{
		if(strcmp(pch, "GEOMOBJECT") == NULL)
			nObj++;

		if(strcmp(pch, "MESH_NUMVERTEX") == NULL)
		{
			nVertices[nObj] = atoi(strtok (NULL, delim));
			//printf("numVertices%d\n", numVertices);
			vertices[nObj] = (float **) calloc(nVertices[nObj], sizeof(float *));
			for(i = 0; i < nVertices[nObj]; ++i)
				vertices[nObj][i] = (float *) calloc(numCols, sizeof(float));
		}

		if(strcmp(pch, "MESH_NUMFACES") == NULL)
		{
			nFacets[nObj] = atoi(strtok (NULL, delim));
			//printf("numFacets%d\n", numFacets);
			facets[nObj] = (int **) calloc(nFacets[nObj], sizeof(int *));
			for(i = 0; i < nFacets[nObj]; ++i)
				facets[nObj][i] = (int *) calloc(numCols, sizeof(int));
		}

		if(strcmp(pch, "MESH_VERTEX") == NULL)
		{
			v = atoi(strtok (NULL, delim));
			printf("v=%d\n", v);
			for(i = 0; i < numCols; ++i)
			{
				vertices[nObj][v][i] = atof(strtok (NULL, delim));
				//printf("%f ", vertices[shapeNum][v][i]);
			}
			//printf("\n");
		}

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			//strtok (NULL, delim);
			for(i = 0; i < numCols; ++i)
			{
				strtok(NULL, delim);
				facets[nObj][f][i] = atof(strtok (NULL, delim));
				//printf("%d: ", facets[shapeNum][f][i]);
			}
		}
		pch = strtok (NULL, delim);
	}
	free (fullFile);
}

char *readFile(FILE *sceneFile)
{
	long fileSize;
	char *fullFile;
	size_t result;

	if(sceneFile==NULL)
	{
		fputs ("Error 1", stderr);
		exit(1);
	}

	fseek(sceneFile, 0, SEEK_END);
	fileSize = ftell(sceneFile);
	rewind(sceneFile);

	fullFile = (char*)malloc(sizeof(char)*fileSize);
	if(fullFile == NULL)
	{
		fputs("Error 2", stderr);
		exit(2);
	}

	result = fread(fullFile,1,fileSize,sceneFile);
	if(result != fileSize)
	{
		fputs("Error 3", stderr);
		exit(3);
	}

	fclose(sceneFile);

	return fullFile;
}

void Keyboard(unsigned char key, int x, int y)
{
	switch(key)
	{
	case 'd':
		//ud += 0.1f;
		rShapeY += 1.0f;
		break;
	case 'a':
		//ud -= 0.1f;
		rShapeY -= 1.0f;
		break;
	case 's':
		//lr += 0.1f;
		rShapeX += 1.0f;
		break;
	case 'w':
		//lr += 0.1f;
		rShapeX -= 1.0f;
		break;
	}
}

void SpecialKeys(int key, int x, int y)
{
	switch(key)
	{
	case GLUT_KEY_UP:
		//rShapeY += 0.1f;
		zz += 1.0f;
		break;
	case GLUT_KEY_DOWN:
		//rShapeY -= 0.1f;
		zz -= 1.0f;
		break;
	case GLUT_KEY_LEFT:
		rShapeX += 0.1f;
		break;
	case GLUT_KEY_RIGHT:
		rShapeX -= 0.1f;
		break;
	}
}

It seems to be when I try and draw the objects (shape and polygon functions) that the problem occurs, probably because I'm accessing the data in my arrays incorrectly.

Unfortunately I cannot run your code right now, but in looking it over I noted the following.

The strangest thing (if I'm not mistaken) is the loop in polygon. Shouldn't you be passing in "i" from shape? I may just not understand what's going on here, but it seems weird to be looping through numObjects (in polygon) within a loop that is doing the same thing (in shape).

In readFile, since you're treating the whole file as a string, you should null-terminate it. So malloc an extra char's worth and be sure to set it to zero. (Or use calloc.)

The following are points that probably won't change anything but are still good practice.

You should really move the fopen() call into readFile and pass in the fileName. There's no advantage to doing it the way you're doing it. Also, you should probably read the file in text mode instead of binary mode. (Change "rb" to "r".)

In loadShape, since you've already read the entire file into fullFile before calling countObjects, you may as well pass fullFile to countObjects so it doesn't have to read the file again.

Your delimiters are better expressed like this: char * delim = " *:\t\n\r\\"; You should compare the result of strcmp to 0 (not NULL).

You got it without having to run it :)
As soon as I passed "i" from shape into the polygon method (and got rid of the additional unnecessary loop) it worked. I realised that I was passing the correct facet windings from 'shape' to 'polygon' but then using them in a loop for each object when I only wanted to use them once for that particular object.

Thanks so much for your help, I really appreciate it. Oh and just out of interest do you have a career in programming?

Anyway, thanks again

> do you have a career in programming?

No, I'm just a hobby programmer, but I've been programming since the age of 8 or 9 and am 25 now and have read quite a few university texts (algorithms, operating systems, AI) as well as Knuth. My job is VERY different but I love it! You probably make more money as a programmer, though.