C ++ Vector Math and OpenGL Compatibility

I made a lot of vector math materials and wrote my own template for myself.

My requirements are a lot of vector mathematical calculations (addition, subtraction, scale, cross prod and dot prod), I also need to pass my vector as float [] so that openGL can use it.

I used it quite happily for a while, today the lecturer saw it and groaned. In particular, he hated (one of which I understand), I used inheritance because he did not seem to adhere to is a style. And my casting (T*)this , of course, he didn’t have much of a solution.

First: Inheritance, I should be able to use vec2 for vec4, so I designed my vectors as follows.

 template<typename T> Vector2D { public: getX(), getY(), setX(), setY() .... }; template<typename T> Vector3D : public Vector2D<T> { public: getZ(), setZ() ... } template<typename T> Vector4D : public Vector3D<T> { public: getW(), setW() ... } 

Why is that bad? and tbh I don’t see how to improve it. I need (want) to be able to determine the type and have some getters and setters. If I rebuilt it as

 template<typename T, int _size> VectorT 

I would lose my stuff .getX() , .setX() and had to replace it with something like .at() or [] . tbh I prefer the readability of .getX() , although this will make it easier to define operators.

Second: I see why this is bad, but to do this, I can pass these vectors to the openGL method, expecting a floating-point array, which I overloaded the splat operator

 // Defined in Vector2D<T> operator*() { return (T*)this; } 

As I understand it, there is no guarantee that the compiler will put the x, y, z, w member variables at the beginning of the class, and if not careful, I can end up passing the v-table. However, I must admit that so far I have not had any problems.

The only way I can see is to maintain an array that is returned. Most likely, it would be easier if I changed them the way I primarily relate to vectors.

+7
source share
6 answers

Instead, you can use GLM . It does everything you described (although I found the documentation is missing), including integration with OpenGL.

+6
source

You can listen to your teacher and use a partial specialization (warning: not verified):

 template<typename T, int size> class Vector; template< typename T > class Vector< T, 2 > { public : Vector() : data() {} T GetX() const { return data[0]; }; T GetY() const { return data[1]; }; void SetX( const T v ) const { data[0]=v; }; void SetY( const T v ) const { data[1]=v; }; private : T data[2]; }; template< typename T > class Vector< T, 3 > { public : Vector() : data() {} T GetX() const { return data[0]; }; T GetY() const { return data[1]; }; T GetZ() const { return data[2]; }; void SetX( const T v ) const { data[0]=v; }; void SetY( const T v ) const { data[1]=v; }; void SetZ( const T v ) const { data[2]=v; }; private : T data[3]; }; 
+2
source

How about this:

 template<class T, int _dim> class Vector { T v[_dim]; operator*(){return v;} friend T inner_product(Vector<T, _dim> const &v1, Vector<T, _dim> const &v2); }; template<class T, int _dim> T inner_product(Vector<T, _dim> const &v1, Vector<T, _dim> const &v2) { T p = 0.; for(int i; i < _dim; i++) p += v1.v[i] * v2.v[i]; return p; } template<class T> class Vector2 : Vector<T, 2> { float getX() const {return v[0];} float getS() const {return v[0];} float getY() const {return v[1];} float getT() const {return v[1];} } template<class T> class Vector3 : Vector<T, 3>, Vector2<T> { float getZ() const {return v[2];} float getR() const {return v[2];} } template<class T> class Vector4 : Vector<T, 4>, Vector3<T> { float getW() const {return v[3];} float getQ() const {return v[3];} } 

Note that creating an inner_product friend that is not part of the class allows you to use it for all derived types!

+1
source

As you said, you are abusing the nature of the is-a inheritance. A problem may arise if you wrote a function such as

float dotProduct (vector2D a, vector2D b);

You can transfer a 3D vector and get a scalar result when the really point product of the 2d vector and the 3d vector is undefined, and in fact this is a mistake that can lead to strange behavior. Of course, this is not a huge deal, but you are discarding some type checking, and if you are going to deal with the pain of static typing, you can also take advantage of it when such errors occur.

Maintaining an array is certainly an excellent solution; you do not want to rely on undefined behavior because you never know when it will completely plunge you.

0
source

I would probably do something like this:

 template<typename T> class VectorT{ protected: T* m_data; int m_size; public: VectorT(unsigned int size) : m_size(size) { m_data=new T[size]; } virtual ~VectorT() { delete[] m_data; } T* operator*() { return m_data; } T& operator[](int ii) { return m_data[ii]; } } template<typename T> class Vector3 : public VectorT<T> { public: Vector3() : VectorT(3) {} T getX() { return m_data[0]; } T getY() { return m_data[1]; } T getZ() { return m_data[2]; } Vector3 crossP(const Vector3& vv) { ... } } 
0
source

Here is the complete OpenGL math library (open source) for C ++

http://glm.g-truc.net/

-one
source

All Articles