Проблемы с созданием мешей в Nvidia PhysX

Я создал быстрый скрипт на Python, который считывает файл .obj с волновым фронтом и выводит вершины и грани в файлы. У меня есть еще одна функция C++, которая читает эти файлы и создает сетку на их основе.

Проблема, с которой я сталкиваюсь, заключается в том, что иногда это работает отлично, а иногда не очень - с одной и той же сеткой. Например. Я запускаю программу PhysX, и сетка выглядит так:
perfect model

Это идеальный сценарий. Ошибок в сетке нет вообще.

Однако, если я закрою программу и вернусь к ней, она может либо снова выглядеть идеально, либо на этот раз выглядеть примерно так;
ужасная модель Это скорее наихудший сценарий, иногда перепутаны только несколько лиц.

Что меня больше всего смущает, так это то, насколько это случайно. Даже если в коде ничего не изменилось, он может полностью запутаться. Это наводит меня на мысль, что это какая-то проблема с памятью или доступом к файлам?

Следующий C++ представляет собой код, который загружает вершины и треугольники:

//uses 3 vectors to store x,y,z then combines them at the end to make the full PxVec3
void ModelLoader::LoadVertex(std::string fileLocation)
{
    //clears vector so it doesnt break when loading multiple models
    vertexArray.clear();

    std::ifstream file2;
    file2.open(fileLocation);


    if (!file2.is_open())
        std::cout << "Failed to load vertex data" << std::endl;

    //individual x,y,z values for the vertex arrays
    std::vector<float> x;
    std::vector<float> y;
    std::vector<float> z;

    int counter = 0;

    //grabs each line add places them into a vector to be used later
    while (!file2.eof())
    {
        if (counter == 3)
            counter = 0;

        std::string num;
        file2 >> num;

        switch (counter)
        {
        case 0:
            x.push_back(stof(num));  //converts string to float
            break;
        case 1:
            y.push_back(stof(num));
            break;
        case 2:
            z.push_back(stof(num));
            break;
        default:
            break;
        }
        counter++;
    }
    //adds x,y,z values to the vector to complete to full PxVec3
    for (int i = 0; i < x.size(); i++)
        vertexArray.push_back(PhysicsEngine::PxVec3(x[i], y[i], z[i]));

    file2.close();
}

//uses a char array to grab all values within the filelocation selected
void ModelLoader::LoadTriangles(std::string fileLocation)
{
    //clears vector so it doesnt break when loading multiple models
    triangleArray.clear();

    std::ifstream file;
    file.open(fileLocation);

    if (!file.is_open())
        std::cout << "Failed to load triangle data" << std::endl;


    //creates char array
    char* fileNumber = new char[2];
    int arrayCounter = 0;

    while (!file.eof())
    {
        //grabs next char
        char num;
        file >> num;

        //stops last char being repeated
        if (file.eof())
            break;

        if (num != ',')
        {
            fileNumber[arrayCounter] = num;
            arrayCounter++;
        }
        else 
        {
            //converts the char array to an int
            int fullNumber = atoi(fileNumber);
            //adds number to triangles vector
            //std::cout << fullNumber << std::endl;
            triangleArray.push_back((PhysicsEngine::PxU32)fullNumber);
            //resets array for next number
            fileNumber = new char[2];
            arrayCounter = 0;
        }

    }

    //adds the last number to the vector
    int fullNumber = atoi(fileNumber);
    triangleArray.push_back((PhysicsEngine::PxU32)fullNumber);

    delete[] fileNumber;
    file.close();
}

РЕДАКТИРОВАТЬ: только для всех, кто новичок, код для этого вопроса был обновлен, и его можно найти здесь: Gist


person davidpox    schedule 14.03.2018    source источник


Ответы (1)


Ваш код чтения файла… странный. И сломано! У меня есть сильное подозрение, что где-то там у вас есть какой-то запредельный доступ. Вы делаете new char[2] в двух местах (и они не сбалансированы, последний delete[] освободит только выделение, сделанное в самой последней итерации цикла), затем cin >> в этот массив фиксированного размера без проверок границ. Я почти уверен, что проблема именно в этом.

Кроме того, почему вы сначала создаете три отдельных вектора x, y, z, а затем объединяете их в вектор PxVec3. Просто прочитайте три переменные и напрямую вставьте в этот большой вектор.

Также БОЛЬШОЙ красный флаг: .clear() вызывается в начале функций. Создайте там свежие временные векторы, в которые вы подготавливаете данные. Когда вы закончите, используйте переместить семантику, чтобы заменить содержимое векторов членов экземпляра класса.

person datenwolf    schedule 14.03.2018
comment
В частности, поскольку массив fileNumber не завершается нулем, atoi в нем может собирать дополнительные цифры после конца выделенного пространства. - person 1201ProgramAlarm; 14.03.2018
comment
Спасибо за ваш ответ! Я внес все запрошенные вами изменения, кроме удаления .clear(), я хотел сначала проверить, будут ли работать другие решения. Я загрузил обновленный код в gist Похоже, проблема не в массиве, поскольку вы подумали. Может быть, дело в том, что я использую clear()? - person davidpox; 14.03.2018
comment
@davidpox: .clear() здесь, вероятно, не проблема. Но его использование свидетельствует о неотшлифованном стиле программирования (а именно о введении сохранения состояния там, где это не требуется). Я посмотрю на Gist. - person datenwolf; 15.03.2018
comment
@datenwolf Хорошо, спасибо! Не уверен, что это поможет, но следующий gist используется движком для загрузить данные вершин и треугольников для построения сетки. Возможно, есть несоответствие между моей загрузкой и их построением? - person davidpox; 15.03.2018
comment
@davidpox: В классе TriangleMesh вы обязательно должны создать постоянную глубокую копию данных вершины. Структура mesh_desc принимает указатели на данные; вы передаете только константную ссылку, что, по сути, означает, что любой переданный вами вектор может закончить свою жизнь (и тем самым сделать указатели недействительными) до запуска CookMesh. Это определенно ошибка. - person datenwolf; 15.03.2018
comment
@datenwolf Спасибо! Я немного переработал его с помощью моего друга и пришел к этому - меши работают нормально, но он часто вылетает при приготовлении пищи. Я загрузил закомментированный код в gist. Ошибка описана в строке 29 файла TriangleMesh.h. Надеюсь, вы сможете поставить диагноз! Большое спасибо за вашу помощь до сих пор. - person davidpox; 16.03.2018
comment
@davidpox: Я мало чем могу помочь, учитывая ограниченный объем ваших Gists. Это очень помогло бы увидеть всю картину. Но я подозреваю, что у вас, ребята, есть проблемы с тем, чтобы не делать плохих вещей с указателями. То, что я видел до сих пор, предполагает, что у вас (все еще?) есть проблемы с пониманием времени жизни объекта и того, что это означает для недействительности/действительности указателей. Мое предложение таково: заставьте все работать без использования ссылок и указателей. Не используйте ключевые слова new и delete, вместо этого используйте std::vector. Вместо передачи ссылок или указателей передавайте копии! - person datenwolf; 20.03.2018
comment
@davidpox: Совет по копированию может звучать так, как будто это делает вещи неэффективными. Однако современные реализации стандартной библиотеки C++ довольно умны: внешне это выглядит так, как будто все это независимые копии, но внутри все манипуляции со ссылками и указателями выполняются за вас, а глубокие копии создаются только тогда, когда это действительно необходимо. - person datenwolf; 20.03.2018
comment
После разговора с моим руководством @ Uni мы пришли к выводу, что, скорее всего, это проблема с PhysX и их приготовлением - похоже, он действительно не любит вогнутые и выпуклые формы и вызывает шипение. Это раздражает, но я ничего не могу с этим поделать, поскольку PhysX в основном имеет закрытый исходный код. Но! Большое спасибо за помощь @datenwolf! даже если это не увенчалось успехом, вы все равно здорово помогли! - person davidpox; 21.03.2018