1

So I made my own class in order to hold a 3D vertex. That basically looks like:

class Vertex                                    // Vertex Class
{
public:
    float x;                                // X Component
    float y;                                // Y Component
    float z;                                // Z Component

    float getX() {
        return x;
    }
    float getY() {
        return y;
    }
    float getZ() {
        return z;
    }
};

Now I need to make a 2D array of these but when I initialize it it won't work. Basically each row will be a face of a polygon. And each column will contain a vertex of that row. So if one row is

(0,0,0) (1, 1, 1) (3, 3, 3) (4,4,4);

Then that row will represent a face with vertices (0,0,0) (1, 1, 1) (3, 3, 3) (4,4,4);

Now when I try to initialize it using

Vertex faces = new Vertex[num_faces][4];

It work work. This seems pretty simple so what am I doing wrong?

EDIT: I changed it to

Vertex *faces = new Vertex[num_faces][4];

and I get this error:

cannot convert from 'Vertex (*)[4]' to 'Vertex *'

Aeonstrife
  • 553
  • 1
  • 6
  • 20
  • Just a sidenote. Did you check the [GLM library](http://glm.g-truc.net/)? And I would recommend the [vector](http://glm.g-truc.net/) class for this as well, instead of arrays. – Marnix Mar 23 '11 at 18:14
  • [related FAQ](http://stackoverflow.com/questions/4810664/) – fredoverflow Mar 23 '11 at 18:16

4 Answers4

3
cannot convert from 'Vertex (*)[4]' to 'Vertex *'

The compiler is already telling you what you need to know, just change the type of faces:

Vertex (*faces)[4] = new Vertex[num_faces][4];
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Does this really do what you're hoping it would do ? I've tried: `int main(int argc, char **argv) { int (*some)[4] = new int[argc][4]; }` and it gives a compiler error: t.C: In function ‘int main(int, char**)’: t.C:5: error: invalid conversion from ‘int*’ to ‘int’ – FrankH. Mar 24 '11 at 17:20
  • @Frank: Are you absolutely sure about that? I copied your code snippet verbatim and compiled it without any problems. The error must be in code you did not post. – fredoverflow Mar 24 '11 at 20:13
  • Weird; sorry - must have had a typo yesterday. Tried again, it compiles ok. – FrankH. Mar 25 '11 at 10:16
0

You need to declare a two dimensional array for what you want to archive.

Vertex **faces = new Vertex*[num_faces];
for(int i=0; i < num_faces; ++i)
    faces[i] = new Vertex[4];

Or of course when you num_faces is compile time constant you can just declare the array like this.

Vertex faces[num_faces][4];

A good resource of dynamic arrays with multiple dimensions can be found in c++-faq lite

mkaes
  • 13,781
  • 10
  • 52
  • 72
0

Never use arrays when vectors will do the same thing. The data structure you need is std::vector<std::vector<Vertex> >.

class Vertex {
    ...
    Vertex(float x, float y, float z) : x(x), y(y), z(z) {}
};

int main() {
    // a 1D array of vertices is a polygon
    std::vector<Vertex> square;
    square.push_back(Vertex(0, 0, 0));
    square.push_back(Vertex(0, 1, 0));
    square.push_back(Vertex(1, 1, 0));
    square.push_back(Vertex(1, 0, 0));

    // Another square, in a different plane
    std::vector<Vertex> square1;
    square1.push_back(Vertex(0, 0, 1));
    square1.push_back(Vertex(0, 1, 1));
    square1.push_back(Vertex(1, 1, 1));
    square1.push_back(Vertex(1, 0, 1));

    // A 2D array of vertices is a polyhedron.
    std::vector<std::vector<Vertex> > cube;
    cube.push_back(square);
    cube.push_back(square1);
    // need four more sides
}

Notice the complete lack of pointers, malloc or new.

For increased readability, I'd recommend typedef std::vector<Vertex> polygon, typedef std::vector<polygon> polyhedron, and liberal use of the functions from boost::assign.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
0

"Twodimensional arrays" are of evil ... they often don't quite do what you're hoping to achieve.

Thing is, to compile your code, it either needs to turn the indices around, in which case you get:

Vertex *faces[4] = {
    new Vertex[num_faces],
    new Vertex[num_faces],
    new Vertex[num_faces],
    new Vertex[num_faces]
};

Or you'd have to use the code that mkaes posted.

The problem with this is that it requires at least four (if not five) calls to new(), any of which theoretically could fail. You can also not delete this "thing" in a single operation.

For fully "struct-like" objects as this one, one can do the following trick:

char *memblk =
    malloc(num_faces * 4 * sizeof(Vertex) + num_faces * sizeof(Vertex *));

Vertex **faces = static_cast<Vertex **>memblk;
Vertex *first = static_cast<Vertex *>(memblk + num_faces * sizeof(Vertex *));

for(i = 0; i < num_faces; first += 4, i++)
    faces[i] = first;

where you allocate a single block of memory large enough to hold:

  1. an array of Vertex * of size num_faces, and
  2. num_faces arrays of Vertex of size 4.

and then initialize the former to contain the respective starting addresses.

To "delete" this, you'd need to use again the C function free(faces) - but it's ok with a single call.

The above is actually quite efficient and corresponds closely to the sort of low-level representation that e.g. OpenGL Vertex buffer objects use for the data (in fact, it can be made to match those).

FrankH.
  • 17,675
  • 3
  • 44
  • 63