I have written math utilities myself, which do everything I need for the simple graphics I am programming. However, I don't know how to make them eligible for passing directly to OpenGL. This can be done with glm, e.g.:

```
std::vector<glm::vec3> locations;
[...]
glGenBuffers(NUM_BUFFERS, _vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[POSITION_VBO]);
// throw data in vbo[0]
glBufferData(GL_ARRAY_BUFFER, _num_vertices * sizeof(locations[0]), &locations[0], GL_STATIC_DRAW);
```

I would like to be able to do this with my own vec3 type, math::vec3f, as I wouldn't like to have "wasted" my own time writing these utilities. Its implementation can be seen here:

```
namespace math
{
template<typename _type> class vec2;
template<typename _type>
class vec3
{
private:
_type _gl_a[3];
public:
_type x, y, z;
vec3() {};
vec3(_type _x, _type _y, _type _z)
{
_gl_a[0] = x = _x;
_gl_a[1] = y = _y;
_gl_a[2] = z = _z;
}
vec3(vec2<_type> v, _type w)
{
_gl_a[0] = x = v.x;
_gl_a[1] = y = v.y;
_gl_a[2] = z = w;
}
inline vec3<_type> operator=(vec2<_type> &v)
{
_gl_a[0] = x = v.x;
_gl_a[1] = y = v.y;
_gl_a[2] = z = 0;
}
inline vec3<_type> operator+(_type other) { return vec3<_type>(x + other, y + other, z + other); }
inline vec3<_type> operator-(_type other) { return vec3<_type>(x - other, y - other, z - other); }
inline vec3<_type> operator*(_type other) { return vec3<_type>(x * other, y * other, z * other); }
inline vec3<_type> operator/(_type other) { return vec3<_type>(x / other, y / other, z / other); }
inline vec3<_type> operator+(vec3<_type> &other) { return vec3<_type>(x + other.x, y + other.y, z + other.z); }
inline vec3<_type> operator-(vec3<_type> &other) { return vec3<_type>(x - other.x, y - other.y, z - other.z); }
inline vec3<_type> operator*(vec3<_type> &other) { return vec3<_type>(x * other.x, y * other.y, z * other.z); }
inline vec3<_type> operator/(vec3<_type> &other) { return vec3<_type>(x / other.x, y / other.y, z / other.z); }
inline _type operator[](int i)
{
if(i < 0 || i >= 3)
return 0;
_gl_a[0] = x;
_gl_a[1] = y;
_gl_a[2] = z;
return _gl_a[i];
}
inline double magnitude()
{
return sqrt(x * x + y * y + z * z);
}
inline vec3<_type> normal()
{
double m = this->magnitude();
return vec3<_type>(x / m, y / m, z / m);
}
inline _type dot(vec3<_type> other)
{
return x * other.x + y * other.y + z * other.z;
}
inline vec3<_type> cross(vec3<_type> other)
{
return vec3<_type>(y * other.z - other.y * z,
z * other.x - other.z * x,
x * other.y - other.x * y);
}
};
typedef vec3<float> vec3f;
typedef vec3<double> vec3d;
typedef vec3<int> vec3i;
typedef vec3<unsigned int> vec3ui;
typedef vec3<short> vec3s;
typedef vec3<unsigned short> vec3us;
};
```

Is it another operator overload function I have to add, or something entirely different?

glBufferData takes a `void`

pointer. That's exactly what you do using the code piece with glm::vec3. However you can do this different ways.

Since GLM stores its data in a `union`

, you can access the elements of a vector in multiple ways: by `operator[]`

or by coordinates `x`

, `y`

, `z`

. Since the elements are values, not pointers, you need the `&`

operator to dereference them. So `&myvec[0]`

has the same effect as `&myvec.x`

.

Your code snippet takes the pointer of the 1st glm::vec3 in the std::vector. The memory address of each glm::vec3 is the memory address of its 1st element. This way you pass a pointer to an array of floats (the elements of the vector, if they are tightly packed - in GLM they are):

```
std::vector<glm::vec3> locations;
glBufferData(GL_ARRAY_BUFFER, _num_vertices * sizeof(locations[0]), &locations[0], GL_STATIC_DRAW);
// same as above
//glBufferData(GL_ARRAY_BUFFER, _num_vertices * sizeof(locations[0]), &locations[0][0], GL_STATIC_DRAW);
// same as above
//glBufferData(GL_ARRAY_BUFFER, _num_vertices * sizeof(locations[0]), &locations[0].x, GL_STATIC_DRAW);
```

**I recommend you to become familiar with the concept of pointers, references and unions in C++, since the following part of my answer rely on them.**

Your `math::vec3`

implementation has multiple issues.

**1)** As others already stated in the comments, you need both

```
_type operator[](int i);
_type operator[](int i) const;
```

to support `const`

-ness.

**2)** Return a reference `(_type&`

) instead of a value (`_type`

). Currently, you return a value by `_type operator[](int i);`

, thus your elements are read-only. Using references you can both read and write them.

```
_type& operator[](int i);
_type& operator[](int i) const;
```

**3)** Since you cannot have negative indices, you shouldn't use signed `int`

for the indexing. Use an unsigned type: `unsigned int`

does the job, but `size_t`

is even better.

```
&_type operator[](size_t i);
&_type operator[](size_t i) const;
```

**4)** Testing against `if (i < 0 || i >= 3)`

is not necessary. It just makes your element access a LOT slower in critical loops (when you access the elements many times). Using `size_t`

you cannot have a value less than 0, and in a correct code you should never pass an index higher than the actual size of the vector.

**5)** You store your data twice: once in `_gl_a[3]`

and once in `x`

, `y`

, `z`

. This is a huge waste of memory. Instead, you should use a `union`

to access the same data in multiple ways.

```
union // anonymous union
{
_gl_a[3];
struct { x, y, z, }; // anonymous struct
};
```

Once you have a correct implementation of your `math::vec3`

, you will be able to use it in the same way as glm types.