Vector of pointer question
-
I recently start a project using c++ 11 Qt, and opengl. During the design of the classes i fall in some doubt: Pointers or not...!
Basically the problem is: I have a vertex class that take a glm::vec3 coords in constructor and assign it to it's private member. A second (mesh) class take a vector of vertex, since this vertex are shared between other classes i make the vector taking pointer in order to avoid copies of the same data around. Since mesh class own the vertex(when the mesh is destroyed also vertex are destroyed) i'm using unique_ptr for memory management.
The mesh class has a method for retrieving the coords of the vertex and put in a vector of pointer and return it. The question is since coords are non pointer and the returned vector uses pointer is this a good way to do it like this?
@
std::vector<glm::vec3 *coords> vertexCoords()
{
std::vector<glm::vec3 *coords> coords;
for(auto &v : privateMemberVectorofvertex)
coords.push_back(&v.coords());
return coords;
}
@or it's better to make Vertex::coords a pointer too?
-
It all sounds like a lot of copying and pointer chasing. Not a good sign for performance.
To be honest I would go for something a lot simpler and faster, e.g.
class Mesh { using Vertices = std::vector<glm::vec3>; public: inline Vertices& vertices() { return vertices_; } inline float* data() { return vertices.empty() ? nullptr : &vertices[0].x; }; private: Vertices vertices_; }
I would even go further. Keep the vertices in an OpenGL buffer object and map it to the CPU memory only when you need to copy them somewhere and even then check if you can do it on the GPU side. Only keep the buffer id in the Mesh class and use it to move data in and out of the GPU memory and delete the buffer in the destructor.
Pointers mean indirection. Indirection means cache misses. Cache misses mean wasting CPU cycles and bad performance. Avoid pointer indirections in high performance code.
-
Sure. If you have a couple of vertex attributes and you use them often I would consider packing them into a single structure like so:
struct VertexData { glm::vec3 position; glm::vec3 color; ... }; struct Mesh { std::vector<VertexData> data; std::vector<int> indices; };
Just remember about alignment e.g don't put a char between two floats in that struct etc.
Again, I would really go for a GPU side memory like this:
struct Mesh { QOpenGLBuffer vertexData; QOpenGLBuffer Indices; };
and make a bunch of convenience member functions for that class (bind(), setData(const std::vector<VertexData>&) etc.)
and then use allocate andmap to fill these buffers.Keeping the data as close to each other as possible and in a linear fashion is key to performance. A GPU will blast through a contiguous buffer like a knife through a warm butter, but if it has to jump around you will pay for the lookup.