我正在开发 C++/OpenGL 3D 网格建模软件。基本上是一个极其原始的搅拌机。
A
Mesh
包含顶点缓存(下面的 EditCache<Vertex>
类),其顶点数据存储在单个块中以发送到 glBufferData。这就是下面的 vertices
向量。然后与每个顶点关联的是边索引和面索引的动态数组,它们引用包含该顶点的边和面的 ID。
template<typename T>
class EditCache {
private:
std::vector<T> vertices;
std::vector<std::vector<int>> edge_indices;
std::vector<std::vector<int>> face_indices;
public:
int addVertex(T vertex) {
vertices.push_back(vertex);
edge_indices.push_back(std::vector<int>());
face_indices.push_back(std::vector<int>());
return vertices.size() - 1;
}
void pairEdgeIndex(int vertex_index, int edge_index) {
edge_indices[point_index].push_back(edge_index);
}
void pairFaceIndex(int vertex_index, int face_index) {
face_indices[point_index].push_back(face_index);
}
...
};
当在现有顶点的
Mesh
类中创建新边或面时,新边/面的 ID 会被推回到与该类中每个顶点关联的 edge_indices
/face_indices
中的数组。边缘/面。创建新顶点时,它会被推回 vertices
数组,并在新顶点位置推回两个新的空向量,以保存新顶点所在的边和面列表。
数据结构大致如下(不是如何存储在内存中)。
- vertex_0 | { edge_0, ..., edge_n } | { face_0, ..., face_m }
- vertex_1 | { edge_0, ..., edge_n } | { face_0, ..., face_m }
- vertex_2 | { edge_0, ..., edge_n } | { face_0, ..., face_m }
- ...
其中每条边或面列表的长度都是可变的。在内存中,每列(顶点、边索引和面索引)都是三个独立的数组。
创建新的四边形、面或具有许多新顶点的更大结构时,我必须多次执行多个
std::vector.push_back()
来创建新顶点并将每个顶点与其每个新边和面配对。而且一一分配内存确实很慢。我认为还有优化空间的地方是:
1.) 边和面 ID 的数组不必是连续的,它们可以是链表。
2.) 我会知道在任务开始时我将添加多少分。
因此,在完美的世界中,我会分配所需大小的单个块,然后将每个数据点一一附加到该新空间中的每个链表。我怎样才能完成这个任务?当然,我不喜欢暴露
new
和 delete
操作以及暴露指向可用空间的原始指针。有没有办法用 std::unique_ptr
或 std::shared_ptr
做到这一点?如何以安全的方式分配内存?
因此,在完美的世界中,我会分配所需大小的单个块,然后将每个数据点一一附加到该新空间中的每个链表。我怎样才能完成这个任务?
当您知道需要多少空间时,您可以预先为向量预留空间:
std::vector<int> x;
x.reserve(100000);
// then later
x.push_back(42); // no allocation happens here
坦率地说,我认为你的其他问题只是因为预期事情比实际情况更复杂而引发。为此,您不需要手动
new
也不需要 delete
,也不需要智能指针,向量可以做到这一点(而且它并不不安全)。