Scene
包含Shape
的列表。
每个Shape
都包含:
std::vector
Vertex
(表面法线,texcoord,3空间位置)std::vector
Triangle
(绑定顶点,用于网格交叉)我想将Scene
对象可迭代两者作为Vertex
的集合,以及Triangle
的集合,在中不那么凌乱的方式。
目前需要的是走三角形:(这里是C#语法):
foreach( Shape shape in Scene )
{
foreach( Mesh mesh in shape.meshGroup.meshes )
{
foreach( Triangle tri in mesh.tris )
{
// work with tri
}
}
}
三重嵌套for
不好看,当然C ++语法更糟糕,使用计数器i,j和k或使用::iterator
s ..
要访问每个Vertex
:
foreach( Shape shape in Scene )
{
foreach( Mesh mesh in shape.meshGroup.meshes )
{
foreach( Vertex v in mesh.verts )
{
// work with v
}
}
}
由于从开始走所有三角形/顶点是昂贵的,最好的方法是什么? (假设有必要点击每个 Triangle
/ Vertex
,因此不需要空间细分算法等)
您可以使用任何C ++ 0x功能(启用VS-2010),包括lambda。
答案 0 :(得分:2)
您可以创建迭代所有元素并调用函数对象的函数:
template <typename F>
inline void for_each_vertex(Scene& scene,F f)
{
for (Shape& shape : scene) {
for (Mesh& mesh : shape.meshGroup.meshes) {
for (Vertex& vertex : mesh.verts) {
f(vertex);
}
}
}
}
template <typename F>
inline void for_each_triangle(Scene& scene,F f)
{
for (Shape& shape : scene) {
for (Mesh& mesh : shape.meshGroup.meshes) {
for (Triangle& triangle : mesh.tris) {
f(triangle);
}
}
}
}
现在你可以做到
for_each_vertex(scene,[](Vertex& vertex)(/* work with vertex */});
for_each_triangle(scene,[](Triangle& triangle)(/* work with triangle */});
这应该与原始代码具有相同的性能,但您不必在整个程序中多次编写相同的循环结构。
答案 1 :(得分:0)
如果所有处理都在内部循环中完成,则可以创建一个自定义迭代器,它迭代所有三个级别,并生成(Shape*,Mesh*,Vertex*)
三元组,处理移动的逻辑,例如在为当前Mesh
迭代所有Vertex
es后,转到下一个Mesh
。
如果你想在中间或外部循环中进行某些处理,你可以添加一些钩子,或者例如第一次通过新的{{(Shape*,NULL,NULL)
三元组返回Shape
三元组。 1}}。
答案 2 :(得分:0)
我通常做的是将单独的“逻辑容器”暴露给一个大(多)容器类:
我定义了一个方法'getMeshRange(),
getShapeRange()`等。
如果您使用提升范围库,则可以返回boost::iterator_range<const Shape*>
,boost::sub_range<std::vector<Vertex> >
等。
在实践中,IIRC,为了满足范围概念,您只需返回std::pair<const_iterator, const_iterator>
。
范围可以如下使用:
for (It it = std::begin(X.getMeshRange()); it!= std::end(X.getMeshRange()); ++it)
{
// use *it
}
或在C ++ 0x中
for (auto& mesh : X.getMeshRange())
{
// use mesh
}
使用Boost Range算法,您可以使用“常规”容器执行任何操作:
const Shape& shape = *std::min_element(X.getShapeRange());