Hi, I've written a program that reads object information from an ASCII file (exported from 3dsmax) so that an object/objects can be reproduced in OpenGL. It works fine at the minute and can read multiple objects from a single file but what I want to be able to do is specify more than one file and store the data in seperate arrays.
I am currently using two variables 'int ***facets' and 'float ***vertices' to store the vertices and facet windings of all shapes in a single file ("scene.ASE"). I now want to extend that so that I could say use 'int ***tableFacets' and 'float ***tableVertices' to store the vertices and facet windings of the file "table.ASE" aswell.

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 *nFacets;
int *nVertices;

int ***tableFacets;
float ***tableVertices;
int ***boxFacets;
float ***boxVertices;
int numObjects;

int number = 0;

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;
GLfloat rShapeZ = 0.0;


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, int i);
void shape();
void DrawGround();

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 objects

    // 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 up and enable light 0
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glEnable(GL_LIGHT0);

	//Enable colour 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 );
    
	//Rescale normals to unit length
    glEnable(GL_NORMALIZE);
    }


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

	loadShape("scene.ASE");
	//loadShape("test_box.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);

	//Draw the ground
	//DrawGround();

	glPushMatrix();
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
		shape();
	glPopMatrix();

	glFlush();
	glutSwapBuffers();
}

void adjustSize(GLsizei w, GLsizei h)
{
	float size = 200.0;

	//Prevent a divide by zero
	if(h == 0)
		h = 1;

	//Set viewport to window dimensions
	glViewport(0,0,w,h);

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


	if (w <= h)
		glOrtho(-size, size, -size * (GLfloat) h / (GLfloat) w, size * (GLfloat) h / (GLfloat) w, -size, size);
	else if (h <= w)
		glOrtho(-size * (GLfloat) w / (GLfloat) h, size * (GLfloat) w / (GLfloat) h, -size, size, -size, size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

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

void polygon(int a, int b, int c, int i)
{
		//glBegin(GL_POLYGON);
		glBegin(GL_LINE_LOOP);
			glColor3ub(0,0,0);
			glVertex3fv(vertices[i][a]);
			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],i);
		}
	}
}

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));
			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));
			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));
			}
		}

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			for(i = 0; i < numCols; ++i)
			{
				strtok(NULL, delim);
				facets[nObj][f][i] = atof(strtok (NULL, delim));
			}
		}
		pch = strtok (NULL, delim);
	}
	free (fullFile);
	if(number = 0){
	tableVertices = vertices;
	tableFacets = facets;}
	else{
		boxVertices = vertices;
		boxFacets = facets;
	}
	number++;
}

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;
	case 'r':
		rShapeZ += 1.0f;
		break;
	case 'f':
		rShapeZ -= 1.0f;
		break;
	}
}

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

/*void DrawGround(void)
{
	GLfloat fExtent = 200.0f;
	GLfloat fStep = 10.0f;
	GLfloat y = -0.4f;
	GLint iLine;

	glBegin(GL_LINES);
		for(iLine = -fExtent; iLine <= fExtent; iLine += fStep)
		{
			glVertex3f(iLine, y, fExtent);	//Draw Z lines
			glVertex3f(iLine, y, -fExtent);

			glVertex3f(fExtent, y, iLine);
			glVertex3f(-fExtent, y, iLine);
		}
	glEnd();
}*/

I have tried passing variables into the loadshape method to store the data that would be loaded but I haven't had any success and I can't really see much of a way to make my code as generic as I want (hence the post).
Any help would be greatly appreciated, thanks :)

Recommended Answers

All 57 Replies

Make a structure for your objects:

struct Object3D {
  int ***facets; 
  float ***vertices;
  int *nFacets;
  int *nVertices;
  int numObjects;

  ... /* add all variables specific to your object here */
}

Then, modify countObjects, loadShape and whatever other functions you need to take a struct Object3D* as one of their parameters, and instead of modifying your globals, they should be modifying data within the structure.

I'm not quite sure what you mean by saying:
"/* add all variables specific to your object here */"

I currently load the data from my file into the 5 variables that you have stated in the structure so wouldn't my object specific variables just be another 5 variables of the same types but with different names?

i.e.

struct Object3D {
  int ***facets; 
  float ***vertices;
  int *nFacets;
  int *nVertices;
  int numObjects;

  int ***facets1; 
  float ***vertices1;
  int *nFacets1;
  int *nVertices1;
  int numObjects1;
}

I don't think I am quite understanding how you would implement what you have suggested :s

No. The purpose of a struct is so that you can keep numerous sets of data organized. You can now do the following:

struct Object3D* box;
struct Object3D* table;

Change functions that modify objects to take a struct Object3D* as a parameter. For example, the prototype of loadShape would now look like:

void loadShape(char fileName[20], struct Object3D* object);

Any place where it modifies something like 'tableVertices' you change to object->vertices . Now you can use loadShape to load your scene:

loadShape(table_filename, scene);

Or you can use it to load your box:

loadShape(box_filename, box);

The idea behind all of this is that you generalize your functions to modify parameters that they take, not hardcoded globals. This way the functions are flexible and can be used to handle different data depending on the situation.

I've tried implementing what you have suggested but my code now produces some access vialation error when it reaches the point at which count objects is initialised to 0 in the countObjects method.
This is what is displayed in the debug display:
0x00000000 {facets=??? vertices=??? nFacets=??? ...}

To me this looks as though it is saying that I haven't initialised my variables or something but I'm not too sure. I'll post my adjusted code below:

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

//Structure for imported 3d objects
typedef struct Object3D
{
	int ***facets;
	float ***vertices;
	int *nFacets;
	int *nVertices;
	int numObjects;
};

struct Object3D* table;
struct Object3D* box;

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


GLfloat rShapeY = 0.0;
GLfloat rShapeX = 0.0;
GLfloat rShapeZ = 0.0;

GLfloat cubeVert[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0},{1.0,1.0,-1.0},{-1.0,1.0,-1.0},{-1.0,-1.0,1.0},{1.0,-1.0,1.0},
						{1.0,1.0,1.0},{-1.0,1.0,1.0}};

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, int i, struct Object3D* object);
void shape(struct Object3D* object);
void DrawGround();
void windCube();
void cube(int a, int b, int c, int d);

void loadShape(char filename[20], struct Object3D* object);
char *readFile(FILE *sceneFile);
void countObjects(char fileName[20], struct Object3D* object);


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

	object->numObjects = 0;

	pch = strtok(fullFile, delim);
	while(pch != NULL)//while NEOF
	{
		if(strcmp(pch, "GEOMOBJECT")==NULL)
			object->numObjects++;
		pch = strtok(NULL, delim);
	}
	object->vertices = (float ***) calloc(object->numObjects, sizeof(float **));
	object->facets = (int ***) calloc(object->numObjects, sizeof(int **));
	object->nVertices = (int *) calloc(object->numObjects, sizeof(int));
	object->nFacets = (int *) calloc(object->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 objects

    // 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 up and enable light 0
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glEnable(GL_LIGHT0);

	//Enable colour 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 );
    
	//Rescale normals to unit length
    glEnable(GL_NORMALIZE);
    }


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

	//loadShape("test_sphere.ASE", 0);
	loadShape("scene.ASE", table);


	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	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);

	//Draw the ground
	//DrawGround();

	glPushMatrix();
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
		shape();
	glPopMatrix();

	glFlush();
	glutSwapBuffers();

}

void adjustSize(GLsizei w, GLsizei h)
{
	float size = 200.0;

	//Prevent a divide by zero
	if(h == 0)
		h = 1;

	//Set viewport to window dimensions
	glViewport(0,0,w,h);

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


	if (w <= h)
		glOrtho(-size, size, -size * (GLfloat) h / (GLfloat) w, size * (GLfloat) h / (GLfloat) w, -size, size);
	else if (h <= w)
		glOrtho(-size * (GLfloat) w / (GLfloat) h, size * (GLfloat) w / (GLfloat) h, -size, size, -size, size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

}

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

void polygon(int a, int b, int c, int i, struct Object3D* object)
{
		glBegin(GL_POLYGON);
		//glBegin(GL_LINE_LOOP);
			glColor3ub(128,64,0);

			glVertex3fv(object->vertices[i][a]);
			glVertex3fv(object->vertices[i][b]);
			glVertex3fv(object->vertices[i][c]);
		glEnd();
}

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

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

	countObjects(fileName, object);
	nObj = -1;

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

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

		if(strcmp(pch, "MESH_NUMFACES") == NULL)
		{
			object -> nFacets[nObj] = atoi(strtok (NULL, delim));
			//printf("numFacets%d\n", numFacets);
			object -> facets[nObj] = (int **) calloc(object->nFacets[nObj], sizeof(int *));
			for(i = 0; i < object->nFacets[nObj]; ++i)
				object->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)
			{
				object->vertices[nObj][v][i] = atof(strtok (NULL, delim));
			}
		}

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			for(i = 0; i < numCols; ++i)
			{
				strtok(NULL, delim);
				object->facets[nObj][f][i] = atof(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;
}

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;
	case 'r':
		rShapeZ += 1.0f;
		break;
	case 'f':
		rShapeZ -= 1.0f;
		break;
	}
}

void SpecialKeys(int key, int x, int y)
{
	
}

void DrawGround(void)
{
	GLfloat fExtent = 200.0f;
	GLfloat fStep = 10.0f;
	GLfloat y = -3.0f;
	GLint iLine;

	glBegin(GL_LINES);
		for(iLine = -fExtent; iLine <= fExtent; iLine += fStep)
		{
			glVertex3f(iLine, y, fExtent);	//Draw Z lines
			glVertex3f(iLine, y, -fExtent);

			glVertex3f(fExtent, y, iLine);
			glVertex3f(-fExtent, y, iLine);
		}
	glEnd();
}

You forgot to allocate memory for your structures. Yes, you're allocating memory for the pointers inside the objects, but before you can do that you need to allocate memory for the entire object. Either that or don't make 'table' and 'box' pointers, and then just pass them to your functions with the '&' operator.

You need to declare your object array like this:

typedef struct Object3D {
	int**   facets;
	float** vertices;
	int     nFacets;
	int     nVertices;
} Object3D;

Object3D *object; // Object array
int numObjects;   // Number of objects in object array

And the object array is accessed like this: object[nObj].nFacets At this stage I wouldn't bother de-globalizing your variables; your code-structure (such as it is) depends on them being global.

At this stage I wouldn't bother de-globalizing your variables

when would you suggest he start "de-globalizing" his design process?

the inappropriate use of globals (ie 98% of the time) is one of the major systemic contributors to buggy, unmaintainable code.

remove those globals now and get the pain over with before it devlops into a chronic disability.

Calm down, jephthah.

I am well aware of the problems with globals. I simply assumed that his project was due soon, and looking at the crazy structure of the whole thing it would not be worth his time in this particular instance to "de-globalize" his variables.

Have you even read the code? For instance, how would he pass the requisite data to display()? I assume there's a solution, but I don't feel like working it out. Are you trying to help anybody but yourself here?

What exactly is your problem?

hmm. i thought my post was calm and to the point. the inappropriate use of and reliance on globals is a habit that is reinforced by laziness and/or a 'get-r-dun' attitude.

i understand your position: you think that at this point it's not worth the time to undo what he's already done. presumably, he'll learn to not learn globals some future point.

but what i'm saying is that I think it IS worth the time, right now -- otherwise, the time never gets taken. and the habit steadily becomes more firmly entrenched.

i'm just expressing my opinion based on my experience. i wasnt attacking you; don't take everything so personal.


.

commented: "Who has time? But then if we never *take* time, how can we have time?" - Merovingian +29

Just checking nucleon, but have you intentionally declared vertices and facets as "float **vertices" and "int **facets" etc. and not "float ***vertices" and "int ***facets"....?
I assume that if you have this would be because Object3D itself points to the components of the structure?

It is my understanding that the third pointer level was there to make an array of objects. But since an Object3D object represents a single object, you would make a pointer to an array of them like this: Object3D *object; The asterisk above now represents the level of indirection previously represented by an (extra) asterisk in front of each of the variables facets, vertices, nFacets, and nVertices in Object3D.

Ah ok, but what if I were to load a file that consisted of more than one object that I wanted to be reproduced as a single object in OpenGL? The table example mentioned earlier for instance is made up of several objects to produce the final result (a table), so in order to be able to load more than one object into one object structure should I still remove the additional asterisk or would I need to keep it?

Remove the additional asterisk.
Declare table like this: Object3D* table;

Sorry I haven't responded in some time, I've been busy with a java assignment. I still seem to be having trouble with understanding exactly how the structure works in my code, I thought I had it figured but I get a compile error when my program tries to allocate memory for the elements of the structure.
When the program gets to the point at which the memory for vertices, facets, nFacets and nVertices is allocated (see code below) my program crashes.

void countObjects(char fileName[20], struct Object3D* object)
{
	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);
	}
	object->vertices = (float **) calloc(numObjects, sizeof(float *));
	object->facets = (int **) calloc(numObjects, sizeof(int *));
	//object->nVertices = (int *) calloc(numObjects, sizeof(int));
	//object->nFacets = (int *) calloc(numObjects, sizeof(int));
}

I'll add in my updated code because I'm not 100% sure that I've implemented that in the way that you were suggesting nucleon.

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

typedef struct Object3D{
	int **facets;
	float **vertices;
	int nFacets;
	int nVertices;
}Object3D;

Object3D *cube; //Cube array
int numObjects;

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


GLfloat rShapeY = 0.0;
GLfloat rShapeX = 0.0;
GLfloat rShapeZ = 0.0;

GLfloat cubeVert[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0},{1.0,1.0,-1.0},{-1.0,1.0,-1.0},{-1.0,-1.0,1.0},{1.0,-1.0,1.0},
						{1.0,1.0,1.0},{-1.0,1.0,1.0}};

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, int i, struct Object3D* object);
void shape(struct Object3D* object);
void DrawGround();
//void windCube();
//void cube(int a, int b, int c, int d);

void loadShape(char filename[20], struct Object3D* object);
char *readFile(FILE *sceneFile);
void countObjects(char fileName[20], struct Object3D* object);


void countObjects(char fileName[20], struct Object3D* object)
{
	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);
	}
	object->vertices = (float **) calloc(numObjects, sizeof(float *));
	object->facets = (int **) calloc(numObjects, sizeof(int *));
	//object->nVertices = (int *) calloc(numObjects, sizeof(int));
	//object->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 objects

    // 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 up and enable light 0
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glEnable(GL_LIGHT0);

	//Enable colour 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 );
    
	//Rescale normals to unit length
    glEnable(GL_NORMALIZE);
    }


int main(int argc, char **argv)
{
	//loadShape("scene.ASE");
	loadShape("test_box.ASE", cube);


	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	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();
	glEnable(GL_DEPTH_TEST);

	//Draw the ground
	glColor3ub(0,0,0);
	DrawGround();
	
	//windCube();
	

	glPushMatrix();
		glTranslatef(0.0f,0.0f,-20.0f);
		glTranslatef(0.0f,-3.0f,0.0f);
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
		glPushMatrix();
			glRotatef(90.0f,0.0f,0.0f,1.0f);
			glRotatef(90.0f,0.0f,1.0f,0.0f);
			glScalef(0.08f,0.08f,0.08f);
			shape(cube);
		glPopMatrix();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0.0f,0.0f,-20.0f);
	glTranslatef(0.0f,1.0f,0.0f);
	glScalef(0.5f,0.5f,0.5f);
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
		glBegin(GL_QUADS);						// Start Drawing The Cube
		glColor3f(0.0f,1.0f,0.0f);				// Set The Color To Green
		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Bottom Left Of The Quad (Top)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Bottom Right Of The Quad (Top)
		glColor3f(0.0f,1.0f,0.0f);				// Set The Color To Green
		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Bottom Left Of The Quad (Top)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Bottom Right Of The Quad (Top)
		glColor3f(1.0f,0.0f,0.0f);				// Set The Color To Red
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Front)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Front)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Front)
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Front)
		glColor3f(1.0f,1.0f,0.0f);				// Set The Color To Yellow
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Back)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Back)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Back)
		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Back)
		glColor3f(0.0f,0.0f,1.0f);				// Set The Color To Blue
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Left)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Left)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Left)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Left)
		glColor3f(1.0f,0.0f,1.0f);				// Set The Color To Violet
		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Right)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Right)
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Right)
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Right)
	glEnd();									// Done Drawing The Quad*/
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0.0f,0.0f,-20.0f);
	glTranslatef(0.0f,1.5f,0.0f);
	glTranslatef(2.0f,0.0f,0.0f);
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
		glBegin(GL_TRIANGLES);									//Start drawing the pyramid
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//top of the triangle(front)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(-1.0f,-1.0f,1.0f);							//left of the triangle(front)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(1.0f,-1.0f,1.0f);							//right of the triangle(front)
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//Top of triangle (right)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(1.0f,-1.0f,1.0f);							//Left of triangle (right)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(1.0f,-1.0f,-1.0f);							//Right of triangle (right)
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//Top of triangle(back)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(1.0f,-1.0f,-1.0f);							//Left of triangle (back)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(-1.0f,-1.0f,-1.0f);							//Right of triangle (back)
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//Top of triangle (left)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(-1.0f,-1.0f,-1.0f);							//Left of triangle (left)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(-1.0f,-1.0f,1.0f);							//Right of triangle (left)
		glEnd();												//Done drawing the pyramid
	glPopMatrix();

	glFlush();
	glutSwapBuffers();
}

void adjustSize(GLsizei w, GLsizei h)
{
	GLfloat fAspect;

    // Prevent a divide by zero, when window is too short
    // (you cant make a window of zero width).
    if(h == 0)
        h = 1;

    glViewport(0, 0, w, h);
        
    fAspect = (GLfloat)w / (GLfloat)h;

    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	
    // Set the clipping volume
    gluPerspective(35.0f, fAspect, 1.0f, 100.0f);
        
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

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

void polygon(int a, int b, int c, int i, struct Object3D* object)
{
		/*glBegin(GL_POLYGON);
		//glBegin(GL_LINE_LOOP);
			glColor3ub(128,64,0);

			glVertex3fv(vertices[i][a]);
			glVertex3fv(vertices[i][b]);
			glVertex3fv(vertices[i][c]);
		glEnd();*/

	glBegin(GL_POLYGON);
		glColor3ub(128,64,0);
		glVertex3fv(object[i].vertices[a]);
		glVertex3fv(object[i].vertices[b]);
		glVertex3fv(object[i].vertices[c]);
	glEnd();
}

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

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

	countObjects(fileName, object);
	nObj = -1;

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

		if(strcmp(pch, "MESH_NUMVERTEX") == NULL)
		{
			object[nObj].nVertices = atoi(strtok (NULL, delim));
			object[nObj].vertices = (float **) calloc(object[nObj].nVertices, sizeof(float *));
			for(i = 0; i < object[nObj].nVertices; ++i)
				object[nObj].vertices[i] = (float *) calloc(numCols, sizeof(float));
		}

		if(strcmp(pch, "MESH_NUMFACES") == NULL)
		{
			object[nObj].nFacets = atoi(strtok (NULL, delim));
			object[nObj].facets = (int **) calloc(object[nObj].nFacets, sizeof(int *));
			for(i = 0; i < object[nObj].nFacets; ++i)
				object[nObj].facets[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)
			{
				object[nObj].vertices[v][i] = atof(strtok (NULL, delim));
			}
		}

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			for(i = 0; i < numCols; ++i)
			{
				strtok(NULL, delim);
				object[nObj].facets[f][i] = atof(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;
}

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;
	case 'r':
		rShapeZ += 1.0f;
		break;
	case 'f':
		rShapeZ -= 1.0f;
		break;
	}
}

void SpecialKeys(int key, int x, int y)
{
	
}

void DrawGround(void)
{
	GLfloat fExtent = 200.0f;
	GLfloat fStep = 10.0f;
	GLfloat y = -3.0f;
	GLint iLine;

	glBegin(GL_LINES);
		for(iLine = -fExtent; iLine <= fExtent; iLine += fStep)
		{
			glVertex3f(iLine, y, fExtent);	//Draw Z lines
			glVertex3f(iLine, y, -fExtent);

			glVertex3f(fExtent, y, iLine);
			glVertex3f(-fExtent, y, iLine);
		}
	glEnd();
}

If you could get back to me asap I would really appreciate it; I don't have very long at all left to finish this.
Thanks

Just to check, are each of the following statements correct?
1. Each object is made up of an arbitrary number of facets.
2. Each facet is made up of three integers (used as indices into vertices)
3. vertices is a list of all the float-3D points used by all the facets.

If the above is true, then numCols never changes from 3 and in fact simply represents the fact that your points are 3D and your facets are triangles. This allows us to remove another level of indirection from both facets and vertices and replace it with a 3-element struct.

typedef struct Point3Df {
	float x, y, z;
} Point3Df;

typedef struct ThreeInts {
	int a, b, c;
} ThreeInts;

typedef struct Object3D {
	ThreeInts *facets;       // List of facets
	int        nFacets;
	Point3Df  *vertices;     // List of vertices
	int        nVertices;
} Object3D;

This structure is used like this:

Object3D  aCube;    // A single object
Object3D *objects;  // A list of objects
// As I understand it, you need a list of objects.

// Get first index of a facet
a = objects[objectNum].facets[facetNum].a;

// Retrieve the x coord of the point represented by that index.
x = objects[objectNum].vertices[a].x;

I have not yet looked through your code carefully (this time), but you MUST change the way you deal with the file. So at least make this change (as your posted code has no line-numbers (use code=c for line-numbers) you'll have to match up the text below because I've only given the changed bits).

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

	countObjects(fullFile, object);

// .................

void countObjects(char *fullFile, Object3D *object)
{
	char * pch;
	char * delim = " *\x9\xA\xD\\:";
	int i;

So make those file-handling changes and implement the new structure. Also, your reliance on globals is still disconcerting, but as I've said before, I'm unsure how you could get rid of ALL of them. But you could certainly get rid of MOST of them. If you're unsure how to do that then leave them for now, implement the above, and we'll look at the globals later.

How does memory get allocated in the countObjects method for the vertices and facets if I don't have an object number to access the array? (i.e. object[nObj].vertices)

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));
}

Is the following right?

void countObjects(char fileName[20], struct Object3D *object)
{
	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);
	}
	object->vertices = (float *) calloc(numObjects, sizeof(float));
	object->facets = (int *) calloc(numObjects, sizeof(int));
}

Please change your data structure and file-handling as I asked above and repost your code. I had asked you some questions, too.

Here's a go at the new data structure and file-handling. Note that the new data structure is easier to use and initialize. I just hope it works. I've made object global (for now) since that is most consonant with the bulk of your design.

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

// A type to hold there ints
typedef struct ThreeInts {
    int a, b, c;
} ThreeInts;

// A type to hold a 3 floats
typedef struct Point3Df {
    float x, y, z;
} Point3Df;

// A type to hold the information for a single 3D object.
typedef struct Object3D {

    // Dynamically-allocated array of facets.
	ThreeInts *facets;
	int        nFacets; // Size of facets array.

    // Dynamically-allocated array of vertices.
	Point3Df  *vertices;
	int        nVertices; // Size of vertices array.

} Object3D;


// A global pointer to hold a dynamically-allocated array of objects.
Object3D *object
int numObjects;  // Size of object array.


GLfloat rquad;
GLfloat rShapeY = 0.0;
GLfloat rShapeX = 0.0;
GLfloat rShapeZ = 0.0;


GLfloat cubeVert[][3] = {
    {-1.0,-1.0,-1.0},{1.0,-1.0,-1.0},{1.0,1.0,-1.0},{-1.0,1.0,-1.0},
    {-1.0,-1.0,1.0},{1.0,-1.0,1.0},{1.0,1.0,1.0},{-1.0,1.0,1.0}};

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}};


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, int i);
void shape();
void DrawGround();
//void windCube();
//void cube(int a, int b, int c, int d);
void loadShapes(char filename[20]);
char *readFile(FILE *sceneFile);
void countObjects(char *fullFile);


int main(int argc, char **argv)
{
	//loadShapes("scene.ASE");
	loadShapes("test_box.ASE", object);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	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 loadShapes(char fileName[])
{
	char *fullFile = readFile(fileName);
	char *pch;
	int v, f;
	char *delim = " *\x9\xA\xD\\:";
	int i, nObj;

	countObjects(fullFile, object);
	nObj = -1;

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

		if(strcmp(pch, "MESH_NUMVERTEX") == NULL)
		{
			object[nObj].nVertices = atoi(strtok (NULL, delim));
			object[nObj].vertices =
                (Point3Df*) calloc(object[nObj].nVertices, sizeof(Point3Df));
		}

		if(strcmp(pch, "MESH_NUMFACES") == NULL)
		{
			object[nObj].nFacets = atoi(strtok (NULL, delim));
			object[nObj].facets =
                (ThreeInts*) calloc(object[nObj].nFacets, sizeof(ThreeInts));
		}

		if(strcmp(pch, "MESH_VERTEX") == NULL)
		{
			v = atoi(strtok (NULL, delim));
			printf("v=%d\n", v);
			object[nObj].vertices[v].x = atof(strtok (NULL, delim));
			object[nObj].vertices[v].y = atof(strtok (NULL, delim));
			object[nObj].vertices[v].z = atof(strtok (NULL, delim));
		}

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			strtok(NULL, delim);
			object[nObj].facets[f].a = atof(strtok (NULL, delim));
			strtok(NULL, delim);
			object[nObj].facets[f].b = atof(strtok (NULL, delim));
			strtok(NULL, delim);
			object[nObj].facets[f].c = atof(strtok (NULL, delim));
		}
		pch = strtok (NULL, delim);
	}
	free (fullFile);
}

char *readFile(char *fileName)
{
    FILE *sceneFile = fopen (fileName, "rb");
	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 countObjects(char *fullFile)
{
	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);
	}

	object = (Object3D*) malloc(numObjects, sizeof(Object3D));
}

void polygon(int a, int b, int c, int i)
{
	glBegin(GL_POLYGON);
		glColor3ub(128,64,0);
		glVertex3fv(object[i].vertices[a]);
		glVertex3fv(object[i].vertices[b]);
		glVertex3fv(object[i].vertices[c]);
	glEnd();
}

void shape()
{
	int i, j;
	for(i = 0; i < numObjects; ++i)
		for(j = 0; j < object[i].nFacets; ++j)
			polygon(object[i].facets[j].a, object[i].facets[j].b,
                    object[i].facets[j].c, i);
}


void display()  // Note signature has changed
{
    // ....
}

// No other functions have changed.

Ah ok, it was the loadshape and countObjects methods that I wasn't understanding because I was unsure as to how I would allocate the memory for the structs but you've cleared that up now, thanks.

I get a compile error with the code now though:

Error 4 error C2664: 'glVertex3fv' : cannot convert parameter 1 from 'Point3Df' to 'const GLfloat *'

it's given in the polygon method when tring to access the three values using glVertex3fv, should I be using a different command?

Try this. Note the ampersands.

void polygon(int a, int b, int c, int i)
{
	glBegin(GL_POLYGON);
		glColor3ub(128,64,0);
		glVertex3fv(&object[i].vertices[a]);
		glVertex3fv(&object[i].vertices[b]);
		glVertex3fv(&object[i].vertices[c]);
	glEnd();
}

It's still giving the same error, it's as if it's saying that I'm trying to use a type that isn't compatible with glVertex3fv...

I see. Then REMOVE those ampersands I added to glVertex3fv's argument, and try changing this:

// A type to hold 3 floats
typedef struct Point3Df {
    float x, y, z;
} Point3Df;

to this:

// Point3Df is an array of 3 floats.
typedef float Point3Df[3];

And this:

if(strcmp(pch, "MESH_VERTEX") == NULL)
		{
			v = atoi(strtok (NULL, delim));
			printf("v=%d\n", v);
			object[nObj].vertices[v].x = atof(strtok (NULL, delim));
			object[nObj].vertices[v].y = atof(strtok (NULL, delim));
			object[nObj].vertices[v].z = atof(strtok (NULL, delim));
		}

to this:

typedef float Float3[3];

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

Damn these spaces and tabs! ;)

Is this line intentional?
"typedef float Float3[3];"

If so then I'm not sure what its doing :s With or without it I'm getting a different error now. The program compiles but then crashes with an access violation error and "Access violation writing location 0x0000000c.".

I'll post my code to date so that you can see if I'm missing something that you may have mentioned.

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "glut.h"
#include <GL\gl.h>
#include <GL\glu.h>
#include <math.h>
#include "myMath.h"
#include "glCamera.h"
#include <memory.h>
#include "myMath.cpp"

//Array to hold 3 floats
typedef float Point3Df[3];

//Structure to hold 3 ints (facet windings)
typedef struct ThreeInts {
	int a, b, c;
} ThreeInts;

//Structure used to hold all data of an object
typedef struct Object3D {
	ThreeInts *facets;       // List of facets
	int        nFacets;
	Point3Df  *vertices;     // List of vertices
	int        nVertices;
} Object3D;

int numObjects;

Object3D *object;//array of objects

GLCamera frameCamera;

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


GLfloat rShapeY = 0.0;
GLfloat rShapeX = 0.0;
GLfloat rShapeZ = 0.0;

int curShape = 1; //Used to select an object in the scene

GLfloat cubeVert[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0},{1.0,1.0,-1.0},{-1.0,1.0,-1.0},{-1.0,-1.0,1.0},{1.0,-1.0,1.0},
						{1.0,1.0,1.0},{-1.0,1.0,1.0}};

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, int i);
void shape();
void DrawGround();
void windCube();
void cube(int a, int b, int c, int d);

void loadShape(char filename[20], struct Object3D *object);
char *readFile(FILE *sceneFile);
void countObjects(char fileName[20], struct Object3D *object);


void countObjects(char *fullFile, struct Object3D *object)
{
	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);
	}

	object = (Object3D*) calloc(numObjects, sizeof(Object3D));
}



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 objects

    // 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 up and enable light 0
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glEnable(GL_LIGHT0);

	//Enable colour 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 );
    
	//Rescale normals to unit length
    glEnable(GL_NORMALIZE);
    }


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

	//loadShape("test_sphere.ASE", 0);
	loadShape("scene.ASE", object);


	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);//RGB colour, double buffering and
	glutCreateWindow("OpenGL Assignment");					 //depth testing(hidden surface removal)
	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();
	glEnable(GL_DEPTH_TEST);
	
	glPushMatrix();
	frameCamera.ApplyCameraTransform();
	//Draw the ground
	DrawGround();	

	glPushMatrix();
		glTranslatef(0.0f,0.0f,-20.0f);
		glTranslatef(0.0f,-3.0f,0.0f);
		if(curShape == 1)//allow rotation only if selected
		{
			glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
			glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
			glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
		}
		glPushMatrix();
			glRotatef(90.0f,0.0f,0.0f,1.0f);
			glRotatef(90.0f,0.0f,1.0f,0.0f);
			glScalef(0.08f,0.08f,0.08f);
			//Draw the table
			shape();
		glPopMatrix();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0.0f,0.0f,-20.0f);
	glTranslatef(0.0f,1.0f,0.0f);
	glScalef(0.5f,0.5f,0.5f);
	if(curShape == 2)
	{
		glTranslatef(0.0f, 3.0f, 0.0f);
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
	}
	windCube();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0.0f,0.0f,-20.0f);
	glTranslatef(0.0f,1.5f,0.0f);
	glTranslatef(2.0f,0.0f,0.0f);
	if(curShape == 3)
	{
		glTranslatef(0.0f, 3.0f, 0.0f);
		glRotatef(rShapeY, 0.0f, 1.0f, 0.0f);
		glRotatef(rShapeX, 1.0f, 0.0f, 0.0f);
		glRotatef(rShapeZ, 0.0f, 0.0f, 1.0f);
	}
		glBegin(GL_TRIANGLES);									//Start drawing the pyramid
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//top of the triangle(front)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(-1.0f,-1.0f,1.0f);							//left of the triangle(front)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(1.0f,-1.0f,1.0f);							//right of the triangle(front)
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//Top of triangle (right)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(1.0f,-1.0f,1.0f);							//Left of triangle (right)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(1.0f,-1.0f,-1.0f);							//Right of triangle (right)
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//Top of triangle(back)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(1.0f,-1.0f,-1.0f);							//Left of triangle (back)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(-1.0f,-1.0f,-1.0f);							//Right of triangle (back)
		glColor3f(1.0f,0.0f,0.0f);								//red
		glVertex3f(0.0f,1.0f,0.0f);								//Top of triangle (left)
		glColor3f(0.0f,0.0f,1.0f);								//blue
		glVertex3f(-1.0f,-1.0f,-1.0f);							//Left of triangle (left)
		glColor3f(0.0f,1.0f,0.0f);								//green
		glVertex3f(-1.0f,-1.0f,1.0f);							//Right of triangle (left)
		glEnd();												//Done drawing the pyramid
	glPopMatrix();
	glPopMatrix();

	glFlush();
	glutSwapBuffers();
}

void adjustSize(GLsizei w, GLsizei h)
{
	GLfloat fAspect;

    // Prevent a divide by zero, when window is too short
    // (you cant make a window of zero width).
    if(h == 0)
        h = 1;

    glViewport(0, 0, w, h);
        
    fAspect = (GLfloat)w / (GLfloat)h;

    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	
    // Set the clipping volume
    gluPerspective(35.0f, fAspect, 1.0f, 100.0f);
        
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

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

void polygon(int a, int b, int c, int i)
{
		glBegin(GL_POLYGON);
		//glBegin(GL_LINE_LOOP);
			glColor3ub(128,64,0);
			glVertex3fv(object[i].vertices[a]);
			glVertex3fv(object[i].vertices[b]);
			glVertex3fv(object[i].vertices[c]);
		glEnd();
}

void shape()
{
	int i, j;
	int a,b,c;
	for(i = 0; i < numObjects; ++i)
	{
		for(j = 0; j < object[i].nFacets; ++j)
		{
			polygon(object[i].facets[j].a, object[i].facets[j].b, object[i].facets[j].c, i); 
		}
	}
}

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

	countObjects(fileName, object);
	nObj = -1;

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

		if(strcmp(pch, "MESH_NUMVERTEX") == NULL)
		{
			object[nObj].nVertices = atoi(strtok (NULL, delim));
			object[nObj].vertices = (Point3Df*) calloc(object[nObj].nVertices, sizeof(Point3Df));
		}

		if(strcmp(pch, "MESH_NUMFACES") == NULL)
		{
			object[nObj].nFacets = atoi(strtok (NULL, delim));
			object[nObj].facets = (ThreeInts*) calloc(object[nObj].nFacets, sizeof(ThreeInts));
		}

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

		if(strcmp(pch, "MESH_FACE") == NULL)
		{
			f = atoi(strtok (NULL, delim));
			strtok(NULL, delim);
			object[nObj].facets[f].a = atof(strtok (NULL, delim));
			strtok(NULL, delim);
			object[nObj].facets[f].b = atof(strtok (NULL, delim));
			strtok(NULL, delim);
			object[nObj].facets[f].c = atof(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;
}

void Keyboard(unsigned char key, int x, int y)
{
	switch(key)
	{
	case '1':
		curShape = 1;
		rShapeY = 0;//reset all rotation variables each time a new object is selected
		rShapeX = 0;
		rShapeZ = 0;
		break;
	case '2':
		curShape = 2;
		rShapeY = 0;
		rShapeX = 0;
		rShapeZ = 0;
		break;
	case '3':
		curShape = 3;
		rShapeY = 0;
		rShapeX = 0;
		rShapeZ = 0;
		break;
	case '4':
		curShape = 4;
		rShapeY = 0;
		rShapeX = 0;
		rShapeZ = 0;
		break;
	case '5':
		curShape = 5;
		rShapeY = 0;
		rShapeX = 0;
		rShapeZ = 0;
		break;
	case 'd':
		rShapeY += 3.0f;
		break;
	case 'a':
		rShapeY -= 3.0f;
		break;
	case 's':
		rShapeX += 3.0f;
		break;
	case 'w':
		rShapeX -= 3.0f;
		break;
	case 'r':
		rShapeZ += 3.0f;
		break;
	case 'f':
		rShapeZ -= 3.0f;
		break;
	}
}

void SpecialKeys(int key, int x, int y)
{
	if(key == GLUT_KEY_UP)
        frameCamera.MoveForward(0.4f);
		//frameCamera.MoveUp(0.1f);
        
    if(key == GLUT_KEY_DOWN)
        frameCamera.MoveForward(-0.4f);
		//frameCamera.MoveUp(-0.1f);

    if(key == GLUT_KEY_LEFT)
        frameCamera.RotateLocalY(0.4f);
        
    if(key == GLUT_KEY_RIGHT)
        frameCamera.RotateLocalY(-0.4f);
                        
    // Refresh the Window
    glutPostRedisplay();
}

void DrawGround(void)
{
	GLfloat fExtent = 200.0f;
    GLfloat fStep = 8.0f;
    GLfloat y = -3.0f;
    GLfloat fColor;
    GLfloat iStrip, iRun;
    GLint iBounce = 0;
    
    glShadeModel(GL_FLAT);
    for(iStrip = -fExtent; iStrip <= fExtent; iStrip += fStep)
        {
        glBegin(GL_TRIANGLE_STRIP);
            for(iRun = fExtent; iRun >= -fExtent; iRun -= fStep)
                {
                if((iBounce %2) == 0)
                    fColor = 1.0f;
                else
                    fColor = 0.0f;
                    
                glColor4f(fColor, fColor, fColor, 0.5f);
                glVertex3f(iStrip, y, iRun);
                glVertex3f(iStrip + fStep, y, iRun);
                
                iBounce++;
                }
        glEnd();
        }
    glShadeModel(GL_SMOOTH);
}

void cube(int a, int b, int c, int d)
{
	//draw the cube via a list of vertices

	glBegin(GL_POLYGON);
		glColor3fv(colors[a]);
		glVertex3fv(cubeVert[a]);
		glColor3fv(colors[b]);
		glVertex3fv(cubeVert[b]);
		glColor3fv(colors[c]);
		glVertex3fv(cubeVert[c]);
		glColor3fv(colors[d]);
		glVertex3fv(cubeVert[d]);
	glEnd();
}

void windCube()
{
	//map the cubes vertices to its faces
		cube(0,3,2,1);
		cube(2,3,7,6);
		cube(0,4,7,3);
		cube(1,2,6,5);
		cube(4,5,6,7);
		cube(0,1,5,4);
}

Change these two function signatures from this:

void loadShape(char filename[20], struct Object3D *object);
void countObjects(char fileName[20], struct Object3D *object);

to this:

void loadShape(char filename[20]);
void countObjects(char *fullFile);

Change the call to countObjects (in loadShape) from this: countObjects(fileName, object); to this: countObjects(fullFile); Change the call to loadShape (in main) frm this: loadShape("scene.ASE", object); to this: loadShape("scene.ASE");

And, yes, the Float3 thing is a mistake. :)

If I make these changes won't I then be restricted to only loading a single shape again though? I won't be able to load seperate objects unless I create the same methods again for each object I want to import.

Ok it runs now but the shape that I'm loading isn't there :s I'm not sure whether it's actually reading in the data or whether it's somehow jumping out of the 'while' loop in loadShape...

Ok I've got it working now. The countObjects method doesn't work if I use fullFile as a parameter, only if I pass 'char fileName[20]' as it was before.
Is there no way to pass the object I want to load into the methods so that I don't have to create almost identical methods everytime I want a new shape though?

Is there no way to pass the object I want to load into the methods so that I don't have to create almost identical methods everytime I want a new shape though?

It is my understanding that object is a dynamically allocated array of objects. Do you mean you want to be able to load sets of objects from multiple files?

The countObjects method doesn't work if I use fullFile as a parameter, only if I pass 'char fileName[20]' as it was before.

That makes no sense to me.

Try zipping and attaching your code this time. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.