According to OpenGL's documentation, glBufferData()
needs a pointer to the data
(i.e. an array, i.e. the coordinates of the vertices).
Let's first have a look at glm::vec3
's implementation.
If you check out glm's Github repo, you'll see that, depending on your compilation flags, glm::vec3
is a typedef
of highp_vec3
which is a typedef
of tvec3<float, highp>
.
tvec3
is declared in type_vec3.hpp (included by vec3.hpp) and the class (template) methods are defined in type_vec3.inl.
In particular, operator[]
's definition is:
template <typename T, precision P>
GLM_FUNC_QUALIFIER T & tvec3<T, P>::operator[](typename tvec3<T, P>::length_type i)
{
assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this));
return (&x)[i];
}
Given that piece of code, one would assume that x
is the first element of the "array" containing the coordinates of glm::vec3
. However, when we go back to type_vec3.h, we find:
union { T x, r, s; };
union { T y, g, t; };
union { T z, b, p; };
So x
, y
and z
are separate attributes. But thanks to how class/struct members are laid out, they can be viewed as a single array starting from &x
.
We know now, that glm::vec3
(actually tvec3
) stores the coordinates in a contiguous manner. But does it also store other attributes ?
Well, we can continue to dive into the code, or use a simple program to give us the answer:
#include <iostream>
#include <ios>
#include <glm/vec3.hpp>
int main()
{
const glm::vec3 v;
const size_t sizeof_v = sizeof(v);
const size_t sizeof_xyz = sizeof(v.x) + sizeof(v.y) + sizeof(v.z);
std::cout << "sizeof(v) : " << sizeof_v << std::endl;
std::cout << "sizeof(xyz): " << sizeof_xyz << std::endl;
std::cout << "sizeof(v) == sizeof(xyz) : " << std::boolalpha << (sizeof_v == sizeof_xyz) << std::endl;
}
Which prints, on my machine:
sizeof(v) : 12
sizeof(xyz): 12
sizeof(v) == sizeof(xyz) : true
Therefore, glm::vec3
stores only the (x, y, z)
coordinates.
Now, if we create a std::vector<glm::vec3> vertices;
, it is safe to say that the layout of the data pointed by &vertices[0]
(which, in C++11 is vertices.data()
) is:
vertices == [vertice1 vertice2 ...]
== [vertice1.x vertice1.y vertice1.z vertice2.x vertice2.y vertice2.z ...]
Going back to the original issue -- glBufferData()
's requirements: when you pass &vertices[0]
you are actually passing the address (i.e. pointer) of the data
, just as expected by glBufferData()
. The same logic applies to glGetBufferSubData()
.