0

I've constructed a quick python script that reads a wavefront .obj file and outputs the verticies and faces to files. I have another C++ function that reads these files and creates a mesh based of-of those.

The issue that I'm experiencing is that this works perfectly sometimes, and other time not so much - with the same mesh. E.g. I start my PhysX program, and the mesh displays like this;
perfect model

That is a perfect-case scenario. No errors within the mesh at all.

However if I close the program and come back to it, it can either look perfect again, or this time look something like this;
terrible model That is more of a worst-case scenario, sometimes only a few faces are messed up.

What confuses me the most is how random it is. Even if nothing has changed in the code, it can completely mess up. This leads me to believe that this is some sort of memory or file-access issue?

The following C++ is the code that loads the verticies and triangles:

//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();
}

EDIT: Just for anyone new, the code for this question has been updated and can be found here: Gist

Zyie
  • 134
  • 2
  • 12
davidpox
  • 135
  • 1
  • 5
  • 18

1 Answers1

0

Your file reading code is… weird. And broken! I have the strong suspicion that you have some out-of-bounds access somewhere in there. You're doing a new char[2] at two places there (and they are not balanced, that last delete[]will only free the allocation done in the very last iteration of the loop), then cin >> into that fixed size array, without bounds checks. I'm pretty sure, that's where your problem comes from.

Also why do you first create three individual vectors x,y,z, and then zip those into a vector of PxVec3. Just read into three variables and directly push into that large vector.

Also a BIG red flag: The .clear() calls at the start of the functions. Create fresh, temporary vectors there, into which you prepare the data. When you're done use move semantics to replace the contents of the class instance member vectors.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Specifically, since the `fileNumber` array is not nul terminated, the `atoi` on it can pick up additional digits past the end of the allocated space. – 1201ProgramAlarm Mar 14 '18 at 05:11
  • Thanks for your reply! I've implemented all the changes you've requested apart from removing `.clear()`, I wanted to see if the other solutions would work first. I've uploaded the updated code to a [gist](https://gist.github.com/davidpox/7899c228a021b44bc9839d1307687a3c) Doesn't seem to be the array issue as you have thought. Could it really be the fact that I'm useing `clear()`? – davidpox Mar 14 '18 at 14:27
  • @davidpox: `.clear()` is probably not the issue here. But its use is indicative of an unpolished programming style (namely the introduction of statefulness where it's not mandated for). I'll have a look at the Gist. – datenwolf Mar 14 '18 at 23:45
  • @datenwolf Okay thank you! Not sure if it'll help, but the following [gist](https://gist.github.com/davidpox/5a1eee9ab6bf144cb600051a66bfa3dd) is what is used by the Engine to load in vertex & triangle data to construct the mesh. Perhaps there's a discrepancy between my loading & their constructing? – davidpox Mar 15 '18 at 00:46
  • @davidpox: In the `TriangleMesh` class you absolutely must create a persistent deep copy of the vertex data. The `mesh_desc` struct takes *pointers* to the data; you pass only a const reference, which essentially means that whatever vector you pass in there may end it's life (and thereby make the pointers invalid) before CookMesh is run. That's definitely a bug right there. – datenwolf Mar 15 '18 at 10:04
  • @datenwolf Thanks! I reworked it a bit with the help of my friend & come to this - meshes work fine but it crashes often at cooking. I've uploaded the commented code to [gist](https://gist.github.com/SeanBurns221/4683d7d397b3f3dfe2402167f6d114ae) Error is described on line 29 of TriangleMesh.h . Hopefully you'll be able to diagnose! Thank you so much for your help so far. – davidpox Mar 15 '18 at 21:07
  • @davidpox: There's only so much I can help with, given the limited scope of your Gists. It would help a lot to see the whole picture. But my suspicion is, that you guys have trouble not doing "bad" things with pointers. What I've seen so far suggests, that you (still?) have problems wrapping your head around object lifetimes and what it means for the in-/validity of pointers. My suggestion is as following: Get the thing working without using references and pointers. Don't use the `new` and `delete` keywords, but use `std::vector` instead. Instead of passing reference or pointers, pass copies! – datenwolf Mar 19 '18 at 22:00
  • @davidpox: The "pass copies" advice might sound like this makes things inefficient. However modern implementations of the C++ standard library are pretty smart: To the outside it looks like it's all independent copies, but internally all the reference/pointer jugging is done for you, and deep copies are created only when it's really required. – datenwolf Mar 19 '18 at 22:02
  • After speaking with my guidance @ Uni, we've come to a conclusion that it's most likely an issue with PhysX and their cooking - it seems that it really dislikes concave & convex shapes, and throws a hissy fit. It's annoying but there's nothing I can do about it, seeing as PhysX is mainly closed source. But! Thanks so much for the help @datenwolf! even if it wasn't successful, you were still great help! – davidpox Mar 21 '18 at 13:35