Reputation: 673
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 *'
Upvotes: 1
Views: 1123
Reputation: 18247
"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:
Vertex *
of size num_faces
, andnum_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).
Upvotes: 0
Reputation: 168876
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
.
Upvotes: 0
Reputation: 14129
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
Upvotes: 0
Reputation: 263360
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];
Upvotes: 3