2016-07-28 23 views
0

我自己写了数学实用程序,它可以完成我编程的简单图形所需的一切。但是,我不知道如何让他们有资格直接传递给OpenGL。这可以用GLM,如来完成:glm数据类型如何通过OpenGL缓冲区直接传递给GPU?

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); 

我希望能够用我自己的VEC 3类,数学:: 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个'operator []'(一个非const和一个const)参见std :: vector签名。他们应该为非const和const版本返回'_type&'和'_type const&'。 –

+0

添加这样的功能对结果没有任何影响。 (当我用math :: vec3f替换glm :: vec3的所有出现时) – Anickyan

回答

1

glBufferData需要void指针。这正是你使用glm :: vec3的代码片所做的。但是,您可以采用不同的方式。

由于GLM存储在union它的数据,你可以访问一个向量的元素以多种方式:通过operator[]或坐标xyz。由于元素是值,而不是指针,因此需要&运算符来取消引用它们。因此&myvec[0]&myvec.x具有相同的效果。

你的代码片段需要std :: vector中第一个glm :: vec3的指针。每个glm :: vec3的内存地址是其第一个元素的内存地址。这样,你传递一个指针float数组(向量的元素,如果他们紧凑 - 在GLM他们):

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); 

我建议你熟悉的概念C++中的指针,引用和联合,因为我的答案的以下部分依赖于它们。


math::vec3实现了多个问题。

1)正如其他人在评论中已经说过,你既需要

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

支持const -ness。

2)返回,而不是一个值(_type)的参考(_type&)。目前,您返回的值为_type operator[](int i);,因此您的元素是只读的。使用引用你可以读写它们。

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

3)既然你不能有负的索引,你不应该使用的索引签署int。使用无符号类型:unsigned int完成这项工作,但size_t更好。

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

4)测试针对if (i < 0 || i >= 3)是没有必要的。它只是让您的元素在关键循环中访问得更慢(当您多次访问元素时)。使用size_t你不能有一个小于0的值,并且在一个正确的代码中,你永远不应该传递一个高于矢量实际大小的索引。

5)您存储的数据进行两次:在xyz一次_gl_a[3]一次。这是一个巨大的内存浪费。相反,您应该使用union以多种方式访问​​相同的数据。

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

一旦你有一个正确的实现您的math::vec3,你将能够使用它以同样的方式作为GLM类型。

+0

谢谢!我没有想过如何使用工会。它非常有意义。 – Anickyan

2

glBufferData()需要void*,所以它不关心你传递给它的类型。该功能只是看到原始记忆。但是,您需要通过其他方式告诉OpenGL如何解释该数据(例如,glVertexAttribPointer())。如果你告诉它需要一个float x3的数组,那么你需要将它传递给一个float x3的数组,否则你会得到错误的输出。

虽然glm::vec3包含3个浮点数,您的包含6个(假设_type是浮点数)。你似乎没有理由复制组件。要么删除重复项,要么告诉opengl期望你的格式,最好是前者。

+0

另外:用足够的'static_asserts'来测试你的代码,以确保这里没有成员之间的隐藏填充,也不在结构的末端,也没有对齐要求这可能会在您构建数组时引入填充! – peppe

相关问题