我自己编写了数学实用程序,它为我编程的简单图形做了我需要的一切。但是,我不知道如何使它们有资格直接传递给OpenGL。这可以用glm来完成,例如:
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);
我希望能够使用我自己的vec3类型math :: vec3f,因为我不想“浪费”我自己编写这些实用程序的时间。它的实现可以在这里看到:
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;
};
我必须添加另一个运算符重载函数,还是完全不同的东西?
答案 0 :(得分:2)
glBufferData()
需要void*
,所以它不关心你传递给它的类型。该功能只能看到原始内存。
但是,您需要以其他方式告诉OpenGL如何解释该数据(例如glVertexAttribPointer()
)。如果你告诉它期望一个float x3数组,那么你需要传递一个float x3数组,否则你会得到破坏的输出。
虽然glm::vec3
包含3个浮点数,但是你的包含6个浮点数(假设_type是浮点数)。你似乎没有理由复制组件。删除重复项,或告诉opengl期望您的格式,最好是前者。
答案 1 :(得分:1)
glBufferData获取void
指针。这正是你使用glm :: vec3的代码片段所做的。但是你可以这样做。
由于GLM将其数据存储在union
中,您可以通过多种方式访问向量的元素:operator[]
或坐标x
,y
,{ {1}}。由于元素是值而不是指针,因此需要z
运算符来取消引用它们。因此&
与&myvec[0]
具有相同的效果。
你的代码片段在std :: vector中获取了第一个glm :: vec3的指针。每个glm :: vec3的内存地址是其第一个元素的内存地址。这样你就可以将指针传递给一个浮点数组(向量的元素,如果它们被紧密打包 - 在GLM中它们是):
&myvec.x
我建议你熟悉C ++中指针,引用和联合的概念,因为我的答案的以下部分依赖于它们。
您的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);
实施有多个问题。
1)正如其他人已经在评论中说明的那样,你需要两者
math::vec3
支持_type operator[](int i);
_type operator[](int i) const;
- ness。
2)返回引用const
)而不是值(_type&
)。目前,您返回_type
的值,因此您的元素是只读的。使用引用,您可以读取和写入它们。
_type operator[](int i);
3)由于您不能拥有否定索引,因此您不应使用签名_type& operator[](int i);
_type& operator[](int i) const;
进行索引编制。使用无符号类型:int
完成工作,但unsigned int
更好。
size_t
4)无需针对&_type operator[](size_t i);
&_type operator[](size_t i) const;
进行测试。它只会使你的元素在关键循环中访问速度变慢(当你多次访问元素时)。使用if (i < 0 || i >= 3)
,您的值不能小于0,并且在正确的代码中,您不应该传递高于矢量实际大小的索引。
5)您将数据存储两次:一次在size_t
,一次在_gl_a[3]
,x
,y
。这是对内存的巨大浪费。相反,您应该使用z
以多种方式访问相同的数据。
union
一旦正确实施了union // anonymous union
{
_gl_a[3];
struct { x, y, z, }; // anonymous struct
};
,您就可以像使用glm类型一样使用它。