c++矢量数学和OpenGL兼容
C++ Vector Math and OpenGL compatible
我一直在做很多矢量数学的东西,并为它写了自己的模板。
我的需求是大量的矢量数学(加法,减法,比例,交叉prod和点prod),我还需要能够将我的矢量作为浮点数传递[],以便openGL可以使用它。
我一直很高兴地使用它一段时间,今天一个讲师看到它并抱怨。有两件事他特别讨厌(其中一件我理解),我对继承的使用,因为它似乎不遵循is a
的风格。而我选的(T*)this
,当然他没有太多的解决办法。
: 继承,我需要能够利用vec2到vec4的,所以我这样设计我的向量
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() ...
}
为什么这不好?而且我不知道如何改进它。我需要(想要)能够定义类型,并有某种类型的getter和setter。如果我把它重新排列成
template<typename T, int _size>
VectorT
我会失去我的.getX()
, .setX()
的东西,不得不取代它与.at()
或[]
的东西。我更喜欢.getX()
的可读性,尽管它会使操作符定义更容易。
我可以看到为什么这是不好的,但为了使它,我可以将这些向量传递到openGL的方法,期望一个浮点数组,我已经重载了splat操作符
// Defined in Vector2D<T>
operator*() { return (T*)this; }
在我的理解中,不能保证编译器会将成员变量x、y、z、w放在类的开头,如果不小心的话,我可能最终会传递v表。但是我必须承认,到目前为止我还没有遇到任何问题。
我能看到的唯一方法是维护一个返回的数组。我想如果我一开始就改变处理向量的方式的话会容易一些
您可能需要考虑使用GLM。它完成了您所描述的所有功能(尽管我发现缺少文档),包括与OpenGL的集成。
你可以听你的老师,并使用部分专业化(警告:未测试):
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];
};
这个怎么样:
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];}
}
注意,使inner_product
成为朋友,而不是类的一部分,允许您将其用于所有派生类型!
就像你说的,你在滥用继承的"is-a"性质。如果您编写这样的函数,可能会出现问题
float dotProduct(vector2D a, vector2D b);
你可以传入一个3D向量并得到一个标量结果,而实际上2d向量和3D向量的点积是未定义的,这实际上是一个可能导致奇怪行为的bug。虽然这不是什么大问题,但是你放弃了一些类型检查,如果你要处理静态类型的痛苦,你也可以在类似的错误出现时得到它的好处。
维护数组绝对是一个更好的解决方案,你不想依赖于未定义的行为,因为你永远不知道什么时候它会把你彻底搞砸。
我可能会这样做:
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) { ... }
}
这是一个完整的OpenGL风格的c++数学库(开源)
http://glm.g-truc.net/- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 了解 GLM- openGL 中的相机转换
- 如何在全屏模式下(在OpenGL中)使背景透明
- 为什么我不能使用 EGL 创建无头 OpenGl 上下文?
- OpenGL大的3D纹理(>2GB)非常慢
- OpenGl glm rotate
- C++atioglxx.pdb未加载错误glBufferData OpenGL
- OpenGL在启用深度测试时不会丢弃我的碎片
- OpenGL相机和相机空间转型的困惑
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 布局兼容类型的并集
- OpenGL将纹理四边形渲染为(0,0)
- OpenGL 和 GLM 矩阵无法正确扩展,总是按比例缩小
- 发布旋转矩阵(openGL/glm)
- 如何在Visual Basic中使用矩形函数OpenGL绘制矩形
- 无法使用VAO和EBO(openGL)绘制多个对象
- 为什么我没有获得与GLFW向前兼容的OpenGL上下文
- void类型的OpenGL C++参数与void(*)()类型的参数不兼容
- c++矢量数学和OpenGL兼容