448,570 Members | 1,310 Online
Need help? Post your question and get tips & solutions from a community of 448,570 IT Pros & Developers. It's quick & easy.

 P: n/a Hi everyone, This really is a tricky one ! (at least for me:). Actually I haven't found any solution to this problem anywhere... So I'll try to be as clear as possible in my explanations. First, I have the following structure: typedef struct _object3D { float coord[8][4]; float r, g, b; } object3D; float coord[8][4] is an array of 2 dimensions that hold the coordinates of the vertices of a 3D object read from a file.Those are homogenous coordinates, that's why the dimension of the columns is 4 instead of 3. Now as you can see my 3D object can be composed of 8 vertices. But the problem is that this number of vertices is static ! What if I want to have a 3D object made of 10 vertices. Even worse, the program will crash also in the case my 3D object is made of less than 8 vertices as you can see in the following: /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D){ for (i = 0; i < 8; i++) /*if not 8 vertices -> CRASH :( */ for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0; } So I thought about doing the following in order to solve my problem: #define NBPOINTS 8 typedef struct _object3D { float coord[NBPOINTS][4]; float r, g, b; } object3D; but then NBPOINTS can't be change... OK for those who are still with me here is another thing I thought about : typedef float (*rowPtr3D)[4]; typedef struct _object3D { int nbPoints; /*read from the file so we know the size of the first dimension*/ rowPtr3D coord; float r, g, b;} object3D; But then it crashes in the following : /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D) { for (i = 0; i < 8; i++) for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; <---- CRASH oups... myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0;} OK so if anybody as an idea that may help me, let me know. I'm kinda desperate !!!! Cheers, Sam. Nov 13 '05 #1
6 Replies

 P: n/a berthelot samuel wrote: Hi everyone, This really is a tricky one ! (at least for me:). Actually I haven't found any solution to this problem anywhere... So I'll try to be as clear as possible in my explanations. First, I have the following structure: typedef struct _object3D { float coord[8][4]; float r, g, b; } object3D; float coord[8][4] is an array of 2 dimensions that hold the coordinates of the vertices of a 3D object read from a file.Those are homogenous coordinates, that's why the dimension of the columns is 4 instead of 3. Now as you can see my 3D object can be composed of 8 vertices. But the problem is that this number of vertices is static ! What if I want to have a 3D object made of 10 vertices. Even worse, the program will crash also in the case my 3D object is made of less than 8 vertices as you can see in the following: /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D){ for (i = 0; i < 8; i++) /*if not 8 vertices -> CRASH :( */ for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0; } So I thought about doing the following in order to solve my problem: #define NBPOINTS 8 typedef struct _object3D { float coord[NBPOINTS][4]; float r, g, b; } object3D; but then NBPOINTS can't be change... OK for those who are still with me here is another thing I thought about : typedef float (*rowPtr3D)[4]; typedef struct _object3D { int nbPoints; /*read from the file so we know the size of the first dimension*/ rowPtr3D coord; float r, g, b;} object3D; But then it crashes in the following : /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D) { for (i = 0; i < 8; i++) for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; <---- CRASH oups... myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0;} OK so if anybody as an idea that may help me, let me know. I'm kinda desperate !!!! Cheers, Sam. 1. Read the C Faq below on dynamic allocation of multidimensional arrays. This will be good fundation material. 2. Try making a vertex a separate class: struct Vertex { float x, y, z; }; Then an object is composed of {a container of} vertices: struct Object_3d { unsigned int num_vertices; struct Vertex * vertices; float r, g, b; // or perhaps c, m, y, k. } Your initialization function would dynamically allocate the vertices: void Initialize_Object_3d(struct Object_3d const * p_vertex, unsigned int num_vertices) { p_vertex->vertices = malloc(num_vertices * sizeof(struct Vertex)); p_vertex->num_vertices = num_vertices; /* ... */ p_vertex->vertics[0].x = 6.0; /* ... */ return; } 3. You could also youse a linked list for the container. -- Thomas Matthews C++ newsgroup welcome message: http://www.slack.net/~shiva/welcome.txt C++ Faq: http://www.parashift.com/c++-faq-lite C Faq: http://www.eskimo.com/~scs/c-faq/top.html alt.comp.lang.learn.c-c++ faq: http://www.raos.demon.uk/acllc-c++/faq.html Other sites: http://www.josuttis.com -- C++ STL Library book http://www.sgi.com/tech/stl -- Standard Template Library Nov 13 '05 #2

 P: n/a berthelot samuel wrote: Hi everyone, This really is a tricky one ! (at least for me:). Actually I haven't found any solution to this problem anywhere... So I'll try to be as clear as possible in my explanations. First, I have the following structure: typedef struct _object3D { float coord[8][4]; float r, g, b; } object3D; float coord[8][4] is an array of 2 dimensions that hold the coordinates of the vertices of a 3D object read from a file.Those are homogenous coordinates, that's why the dimension of the columns is 4 instead of 3. Now as you can see my 3D object can be composed of 8 vertices. But the problem is that this number of vertices is static ! What if I want to have a 3D object made of 10 vertices. Even worse, the program will crash also in the case my 3D object is made of less than 8 vertices as you can see in the following: You can make a typedef: typedef float (*vertices)[4]; and then dynamically allocate the needed vertices. The limit is only limited by your memory resources. Write a function to Add the vertices to the struct: Example: #include #include typedef float (*vertices)[4]; typedef struct _object3D { vertices coord; float r, g, b; size_t v_cnt; /* vertices count*/ } object3D; int AddVertice(object3D *p, float w, float x, float y, float z); void PrintObject3D(object3D *p); void FreeObject3D(object3D *p); int main(void) { object3D my = {{NULL},55.6f,23.6f,76.9f,0}; AddVertice(&my,1.22f,2.33f,3.44f,4.55f); AddVertice(&my,55.1f,44.1f,33.1f,22.1f); PrintObject3D(&my); FreeObject3D(&my); return 0; } int AddVertice(object3D *p, float w, float x, float y, float z) { vertices tmp; size_t count = p->v_cnt; if((tmp = realloc(p->coord,(p->v_cnt+1)*(sizeof *tmp))) == NULL) return 0; p->coord = tmp; p->coord[count][0] = w; p->coord[count][1] = x; p->coord[count][2] = y; p->coord[count][3] = z; p->v_cnt++; return 1; } void PrintObject3D(object3D *p) { size_t i,j; printf("r = %.2f\ng = %.2f\nb = %.2f\n\n",p->r,p->g,p->b); for(i = 0;i < p->v_cnt; i++) for(j = 0; j < 4; j++) printf("Coord[%u][%u] = %.2f\n%s",i,j,p->coord[i][j], (j==3)?"\n":""); return; } void FreeObject3D(object3D *p) { free(p->coord); p->coord = NULL; p->r = p->g = p->b = 0.0f; p->v_cnt = 0; return; } -- Al Bowers Tampa, Fl USA mailto: xa******@myrapidsys.com (remove the x to send email) http://www.geocities.com/abowers822/ Nov 13 '05 #3

 P: n/a On 2003-11-01, berthelot samuel wrote: typedef struct _object3D { float coord[8][4]; float r, g, b; } object3D; float coord[8][4] is an array of 2 dimensions that hold the coordinates of the vertices of a 3D object ... ... the problem is that this number of vertices is static ! You can declare coord as a pointer as you have tried below, or you can declare coord to be a flexible array. In the flexible array approach, the flexiby array has to be at the bottom of the struct. #ifdef HAVE_FLEXIBLE_ARRAYS # define FLEXIBLE_ARRAY_SIZE # define FLEXIBLE_ARRAY_FUDGE 0 #else # define FLEXIBLE_ARRAY_SIZE 1 # define FLEXIBLE_ARRAY_FUDGE 1 #endif typedef struct _object3D { int nbPoints; float r, g, b; float coord[FLEXIBLE_ARRAY_SIZE][4]; } object3D; When using a flexible array, the most straight forward way to use it is to use malloc() to create your object instance: object3D *makeObject3D(unsigned nbPoints) { object3D *obj; int extra_Points; extra_Points = nbPoints - FLEXIBLE_ARRAY_FUDGE; obj = malloc(sizeof(object3D) + extra_Points*sizeof(float[4])); if (obj != 0) obj->nbPoints= nbPoints; return obj; } /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D){ for (i = 0; i < 8; i++) /*if not 8 vertices -> CRASH :( */ for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0; } Nevermind that i and j are undeclared. I am not sure what you mean by CRASH, but one problem with this function is that you are passing an object3D value to the function and not a reference. This means when the function returns, the caller's object3D will still be uninitialized. In order to allow the function to manipulate the callers object3D, the function should be written to accept a reference to the object3D. In C this is done with a pointer. Combined with the flexible array approach above, the function changes to: void initObject3D(object3D *myObject3D) { int i, j; for (i = 0; i < myObject3D->nbPoints; i++) for (j = 0; j < 4; j++) myObject3D->coord[i][j] = 0.0; myObject3D->r = 1.0; myObject3D->g = 1.0; myObject3D->b = 1.0; } And the two functions could be used together like: { object3D *myObj; /* make an object with 9 vertices */ myObj = makeObject3D(9); initObject3D(myObj); /* ... */ } When you are done with an object, you will need a function to reap dynamically allocated memory: void freeObject3D(object3D *obj) { free(obj); } This works because makeObject3D did its work with a single call to malloc. typedef float (*rowPtr3D)[4]; typedef struct _object3D { int nbPoints; /*read from the file so we know the size of the first dimension*/ rowPtr3D coord; float r, g, b;} object3D; This is another approach. But if you go this route, when creating an instance of object3D, you will need another malloc for the array object3D *makeObject3D(unsigned nbPoints) { object3D *obj; obj = malloc(sizeof(object3D)); if (obj == 0) return 0; obj->coord = malloc(nbPoints*sizeof(float[4])); if (obj->coord == 0) { free(obj); return 0; } obj->nbPoints= nbPoints; return obj; } And to reap the memory, you will need two calls to free: void freeObject3D(object3D *obj) { if (obj == 0) return; free(obj->coord); free(obj); } This approach can be used without calling makeObject3D and freeObject3D though, if you declare both your object and the array off the stack: { int nbPoints = 9; float coords[nbPoints][4]; object3D myObj = { .nbPoints = nbPoints, .coord = coords }; initObject3D(&myObj); /* ... */ } Notice that we pass in the address of myObj to initObject3D so that initObject3D will be able to modify the object. /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D) { for (i = 0; i < 8; i++) for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; <---- CRASH oups... myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0;} Never mind that i and j are undeclared. Again, you have declared initObject3D to take an object3D by value. This causes the contents of the callers object3D to be copied into the function's object3D argument. The function will not copy back the values when the function exits. You did not show how it is that you created your object3D instance. Perhaps you did not allocated memory for the coord pointer, and the indicated assignment is in error because it is dereferencing an uninitialized pointer variable. Thirdly, your function assumes the size of the array coord is pointing to is always 8. This is an error. You declared your struct to contain the number of points, and the i variable should not exceed the number of points indicated by the object3D instance. -- James Nov 13 '05 #4

 P: n/a sa**************@voila.fr (berthelot samuel) wrote in message news:... Hi everyone, This really is a tricky one ! (at least for me:). Actually I haven't found any solution to this problem anywhere... So I'll try to be as clear as possible in my explanations. First, I have the following structure: typedef struct _object3D { float coord[8][4]; float r, g, b; } object3D; float coord[8][4] is an array of 2 dimensions that hold the coordinates of the vertices of a 3D object read from a file.Those are homogenous coordinates, that's why the dimension of the columns is 4 instead of 3. Now as you can see my 3D object can be composed of 8 vertices. But the problem is that this number of vertices is static ! What if I want to have a 3D object made of 10 vertices. Even worse, the program will crash also in the case my 3D object is made of less than 8 vertices as you can see in the following: /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D){ for (i = 0; i < 8; i++) /*if not 8 vertices -> CRASH :( */ for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0; } So I thought about doing the following in order to solve my problem: #define NBPOINTS 8 typedef struct _object3D { float coord[NBPOINTS][4]; float r, g, b; } object3D; but then NBPOINTS can't be change... OK for those who are still with me here is another thing I thought about : typedef float (*rowPtr3D)[4]; typedef struct _object3D { int nbPoints; /*read from the file so we know the size of the first dimension*/ rowPtr3D coord; float r, g, b;} object3D; But then it crashes in the following : /*Initialize elements of an Object3D*/ void initObject3D(object3D myObject3D) { for (i = 0; i < 8; i++) for (j = 0; j < 4; j++) myObject3D.coord[i][j] = 0.0; <---- CRASH oups... myObject3D.r = 1.0; myObject3D.g = 1.0; myObject3D.b = 1.0;} OK so if anybody as an idea that may help me, let me know. I'm kinda desperate !!!! Cheers, C's Arrays have fixed size, you can't modify their size dynamically. In cases which require variable sized arrays you use functions like 'malloc', 'realloc' and 'free' e.g. if you want to create a variable integer array you do so by int *intVarArray = malloc(some_size_in_bytes); You address the individual elements of the array now in the same way as you do for 'ordinary' arrays that is for the first element you would do intVarArray[0] = some_value; When you are done using this array, you free up the memory aquired when you called malloc by. free(intVarArray); In case you want to again change the size of the above array to 'larger' or 'smaller' then do so by calling realloc(intVarArray, new_size_in_bytes); Look in your C book for discussion on 'dynamic memory allocation' specifically look in your book's index for 'malloc', 'realloc' and 'free' functions. HTH -- Imanpreet Singh Arora imanomaniac AT acm DOT org Nov 13 '05 #5