О проекте:
Я работаю над трассировщиком лучей Opengl, который может загружать файлы obj и отслеживать их. Мое приложение загружает файл obj с помощью assimp, а затем отправляет все грани треугольника (вершины и индексы) во фрагментный шейдер, используя объекты хранилища шейдеров. Структура basi c собирается визуализировать результаты в четырехугольник из фрагментного шейдера.
Когда я загружаю более крупные объекты (более 100 треугольников), компьютеру потребовалось много времени, чтобы сделать пересечениях, поэтому я начал создавать BVH-дерево, чтобы ускорить процесс. Мой BVH рекурсивно разделяет пространство на два выровненных по оси ограничивающих прямоугольников на основе средней медианы граней треугольников, содержащихся в AABB.
Мне удалось построить древовидную структуру BVH (на CPU), и теперь Я хочу преобразовать его в простой массив, а затем отправить его во фрагментный шейдер (в буфер хранения шейдера).
Вот метод, отвечающий за преобразование узла BVH root в массив:
BvhNode bvhNode; //global variable
BvhNode* putNodeIntoArray() {
int size=bvhNode.getNumberOfNodes();
BvhNode nodesArray[size];
int current_index = 0;
vector<BvhNode> tempNodes;
tempNodes.push_back(bvhNode);
BvhNode current_node;
while (!tempNodes.empty()) {
current_node = tempNodes.at(0);
tempNodes.erase(tempNodes.begin());
nodesArray[current_index] = current_node;
if(!current_node.isLeaf)
{
tempNodes.push_back(current_node.children.at(0)); // Segmentation error occurs here!
tempNodes.push_back(current_node.children.at(1));
}
current_index++;
}
return nodesArray;
}
О проблеме:
Не знаю почему, но это дает мне ошибку сегментации, когда я хочу push_back первого потомка в tempNodes
вектор (точное место можно увидеть из комментария выше). Мне кажется, что current_node.children.at(0)
не существует, но на самом деле он существует согласно отладчику. Я попытался написать оператор ссылки (&): tempNodes.push_back(¤t_node.children.at(0));
, но в этом случае он дает мне странные координаты объектов. Я попытался определить переменные в функции как глобальные, пытаясь избежать проблем с областью видимости, а также определить переменную current_node
как указатель. К сожалению, ни один из них не дал мне лучших результатов.
Вот мой класс BvhNode, если он помогает:
class BvhNode {
public:
BBox bBox;
int depthOfNode;
vector<BvhNode> children;
int order;
bool isLeaf;
bool createdEmpty = false;
vector<glm::vec3> primitiveCoordinates;
BvhNode() {}
BvhNode(BvhNode *pNode) {}
BvhNode(vector<glm::vec3> &primitiveCoordinates) {
this->primitiveCoordinates = primitiveCoordinates; }
void buildTree(vector<glm::vec3>& indicesPerFaces, int depth) {... }
Обновление 1:
Я обновил метод согласно комментариям. Поэтому я изменил тип возвращаемого значения на вектор, вставленный в BvhNode *. Алгоритм работает нормально, пока не дойдет до процесса помещения листовых узлов в std :: vector. Поэтому, когда он начинает помещать последний уровень графика в вектор, он дает мне эту ошибку:
Program received signal SIGSEGV, Segmentation fault.
0x00007fbda4d69c01 in __GI___libc_free (mem=0x555be3a9dba0) at malloc.c:3123
3123 malloc.c: No such file or directory.
Мне удалось разместить семь узлов (что означает все уровни глубины дерева, кроме уровня листьев ) в вектор. Я также пытался запустить valgring, но на самом деле valgrind не выдает никаких ошибок, в отличие от CLion.
Это мой модифицированный метод. Я прокомментировал место ошибки сегментации и исправления.
BvhNode bvhNode;
vector<BvhNode> putNodeIntoArray() {
int size=bvhNode.getNumberOfNodes();
// FIX: I modified the array into an std::vector
vector<BvhNode> nodesArray(size);
int current_index = 0;
vector<BvhNode> tempNodes;
tempNodes.push_back(bvhNode);
BvhNode current_node;
while (!tempNodes.empty()) {
current_node = tempNodes.front();// Segmentation error!!
tempNodes.erase(tempNodes.begin());
nodesArray.at(current_index)=current_node;
nodesArray.at(current_index).children.clear();
// FIX: I also modified this not to iterate through leaves' children, because they don't exist.
if(!current_node.children.empty())
{
tempNodes.push_back(current_node.children.at(0));
tempNodes.push_back(current_node.children.at(1));
}
current_index++;
}
return nodesArray;
}