std :: vector <float>到std :: vector <glm :: vecx>而不复制

时间:2016-01-04 00:02:44

标签: c++ vector struct glm-math

我正在使用Tinyobjloader编写一个小玩具游戏引擎来加载.obj文件。我使用glm :: vecX存储顶点数据和所有内容,以简化操作。

当我需要std::vector<float>时,Tinyobjloader会给我一个std::vector<glm::vecX>。如果不复制,我该怎么做?

要明确的是,glm::vecX是一个简单的结构,例如包含float成员x, y, z

我在想,因为结构体的行为有点像数组,std::move会起作用,但没有运气。

谢谢!

编辑: 对不起,我知道我不清楚这一点。我想将std::vector<float>移到std::vector<glm::vecX>或将其作为std::vector<glm::vecX>&传递。

使用std::memcpy复制数据工作正常,但它会复制数据,我希望避免这种情况。

2 个答案:

答案 0 :(得分:1)

可以直接解释向量的内容作为结构的实例,而不必复制数据。如果你能保证表示是兼容的,那就是。 vector<float>的内容在内存中作为一系列浮点值直接相互跟随(一个数组),没有额外的填充,而vector<glm::vecX>的内容按顺序排列在内存中vecX。因此,您需要确保满足以下条件:

  • glm::vecX正好是X浮点数的大小,没有填充。根据结构的声明,这可能取决于平台。
  • vector<float>的内容是正确的顺序,即[x1,y1,z1,x2,y2,z2,...]为vec3而不是[x1,x2,.. ...,XN,Y1,Y2 ...]。

在这种情况下,您可以安全地重新解释float向量的数据指针作为指向vecX数组的指针,如下例所示:

std::vector<float> myObjData = ...;
auto nVecs = myObjData.size() / 3; // You should check that there are no remainders!
glm::vec3* vecs = reinterpret_cast<glm::vec3*>(myObjData.data());
std::cout << vecs[0]; // Use vecs[0..nVecs-1]

但是,您不能安全地将 vector 本身重新解释为glm :: vecX的向量,甚至不能作为const向量,因为存储的元素数量重新解释后,向量可能不一致。这取决于vector<T>代码是直接存储元素的数量,还是分配的字节数(然后size()除以sizeof(T)):

// Don't do this, the result of .size() and .end() may be wrong!
const std::vector<glm::vec3>& bad = *reinterpret_cast<std::vector<glm::vec3>*>(&myObjData);
bad[bad.size()-1].z = 0; // Potential BOOM!

但是,大多数情况下,您不需要传递实际的向量,因为标准库中的大多数函数都接受容器范围,这很容易为第一个例子中的数组提供数组。所以,如果你想根据z位置对你的vec3数组进行排序,然后将它打印出去你会这样做:

// nVecs and vecs from the first example
std::sort(vecs, vecs+nVecs, // Sort by Z position
    [](const glm::vec3& a, const glm::vec3& b) { return a.z < b.z; });
std::copy(vecs, vecs+nVecs, std::ostream_iterator<glm::vec3>(std::cout, "\n"));

答案 1 :(得分:0)

简而言之:据我所知,这是不可能没有复制的。

在我看来,std::memcpy没有与std::vector一起使用的商家。