Reading An OBJ File (Help Please!)

Discussion in 'Programming' started by MrQuetch, Feb 23, 2017.

  1. MrQuetch

    MrQuetch Member

    Joined:
    Feb 23, 2017
    Posts:
    29
    Hello, GMC!

    This is my first thread and post on the forums! I wasn't sure where to post this, but I figured that this part of the forum felt like the right place, especially in the 'Program' section. If this thread was not meant for this section - just let me know! Perhaps a moderator can move it if that's the case.

    Anyways, I've been making a model creator that can write files to different model formats. One that I'm trying to read in is an OBJ format (such as the title says). This is a problem that I've been trying to solve for a few days now, and have spent countless hours trying to figure out a good way to get it working. I honestly felt like now would be a good time to get some help.

    So, I can read text files fine, the same goes for binary. It's going to sound simple perhaps to some, and though it looks simple, I've had trouble trying to read the file in a specific way.

    For those who don't know, the OBJ file format is literally human readable (anyone could understand what it means). Here's an example if anyone wants to know:

    Where each 'v' character represents a vertex in 3D space consisting of an X, Y, and Z specifically in that order.
    And where each 'f' character represents a face consisting of the triangle indices, those being vertex 1, 2, and 3.

    The vertices in this file are placed in such a manner to create a box.
    I didn't bother placing the faces to the correct numbers, but you get the idea.
    There are twice as many triangles to account for the 'quad's on the many faces of the box primitive.
    So, there are 8 vertices, and 12 triangles (6 sides).

    OBJ Example:
    --------------------------------------------------------------------
    v -1 1 0
    v 1 1 0
    v 1 -1 0
    v -1 -1 0
    v -1 1 1
    v 1 1 1
    v 1 -1 1
    v -1 -1 1

    f 1 2 3
    f 4 5 6
    f 7 8 9
    f 10 11 12
    f 1 2 3
    f 4 5 6
    f 7 8 9
    f 10 11 12
    f 1 2 3
    f 4 5 6
    f 7 8 9
    f 10 11 12
    --------------------------------------------------------------------

    My OBJ's look just like the normal OBJ's with a couple exceptions. Mine take the original, and I add on the vertices and triangles so that GMS knows how to read the file manually. Where 8 is the number of vertices, and 12 is the number of faces after. The file looks like this - this is what I want GMS to read:

    My OBJ Example:
    --------------------------------------------------------------------
    8
    v -1 1 0
    v 1 1 0
    v 1 -1 0
    v -1 -1 0
    v -1 1 1
    v 1 1 1
    v 1 -1 1
    v -1 -1 1
    12
    f 1 2 3
    f 4 5 6
    f 7 8 9
    f 10 11 12
    f 1 2 3
    f 4 5 6
    f 7 8 9
    f 10 11 12
    f 1 2 3
    f 4 5 6
    f 7 8 9
    f 10 11 12
    --------------------------------------------------------------------

    So the program reads the vertices fine and places it's value for me. I can partially read the data (which is a good thing), but not all of it (I can only read the very last value correctly - if I try for the other ones, they are just assigned to Z as well). It's starting to bother me now. I'm very sure it's just a simple problem that could be fixed in a matter of minutes, but I guess I just simply don't know enough yet to get it to work properly - I'm willing to learn. I actually found a forum and post on Reddit, and it helped a little bit. If it helps a bit, I took a little bit of this code and altered it a bit into mine:

    https://www.reddit.com/r/gamemaker/comments/3zxota/splitting_strings/

    If it's really needed, and aids in getting the help I need / desire, here is the code that I have:

    --------------------------------------------------------------------
    Code:
    var loadFile;
    
    loadFile = get_open_filename_ext("myModel|*.c", "", working_directory, "Model Code");
    
    if (loadFile != "")
        {
        loadFile = file_text_open_read(loadFile);
      
        //for loading OBJ models from third party software
        //reads through each line like normal, but deletes strings to get var (real) offsets
      
        var pos1; //num of vertices
        var pos2; //vert x, y, and z
      
        var pos_X; //vert X
        var pos_Y; //vert Y
        var pos_Z; //vert Z
      
        var pos3; //num of triangles
        var pos4; //tri vert 1, 2, and 3
      
        //line 1
        pos1 = file_text_read_real(loadFile);
        obj_controller.vertices = pos1;
        pos1 = string_delete(string(pos1), 1, 4); //here is where the number of vertices is
        file_text_readln(loadFile);
      
        //keep testing - getting close
        for (i = 1; i <= obj_controller.vertices; i++)
            {
            var space = 0; //used to count the characters
            var aSpace = " "; //for counting the spaces in the string
            var allSpaces = 0; //array for holding all of the spaces (to exclude them)
            var aBlank = ""; //for holding the current space that's being built
          
            //var pos_X = 0; //vert x
            //var pos_Y = 0; //vert y
            //var pos_Z = 0; //vert z
          
            pos2 = file_text_read_string(loadFile);
            pos2 = string_delete(pos2, 1, 2); //this gets rid of the v on the line
          
            //read the string, and repeat for all others
            for (var j = 1; j < (string_length(pos2) + 1); j++)
                {
                //counts by 1 to get every character in the string
                var theString = string_copy(pos2, j, 1);
              
                //if a space is found, exclude it
                if (theString = aSpace)
                    {
                    allSpaces[space] = aBlank;
                    space++; //add this space to the array of allSpaces
                    aBlank = "";
                    };
                else
                    { 
                    aBlank = aBlank + theString; //extract value and insert it for a variable
                    pos_Z = aBlank + theString; //z works
                    };
                };
          
            for (var k = 1; k < (string_length(pos2) + 1); k++)
                {
                //counts by 1 to get every character in the string
                var theString = string_copy(pos2, k, 1);
              
                //if a space is found, exclude it
                if (theString = aSpace)
                    {
                    allSpaces[space] = aBlank;
                    space++; //add this space to the array of allSpaces
                    aBlank = "";
                    };
                else
                    { 
                    aBlank = aBlank + theString; //extract value and insert it for a variable
                    pos_Y = aBlank + theString; //
                    };
                };
          
            for (var l = 1; l < (string_length(pos2) + 1); l++)
                {
                //counts by 1 to get every character in the string
                var theString = string_copy(pos2, l, 1);
              
                //if a space is found, exclude it
                if (theString = aSpace)
                    {
                    allSpaces[space] = aBlank;
                    space++; //add this space to the array of allSpaces
                    aBlank = "";
                    };
                else
                    { 
                    aBlank = aBlank + theString; //extract value and insert it for a variable
                    pos_X = aBlank + theString; //
                    };
                };
          
            global.vertex_ID[i] = instance_create(real(pos_X), real(pos_Y), obj_vertex); //converts the strings to real values
            global.vertex_ID[i].z = real(pos_Z); //z axis
            //OBJ includes no color values, so set colors to 0 except alpha
            global.vertex_ID[i].color_R = 0;
            global.vertex_ID[i].color_G = 0;
            global.vertex_ID[i].color_B = 0;
            global.vertex_ID[i].color_A = 255;
          
            file_text_readln(loadFile);
            };
    --------------------------------------------------------------------

    I still have yet to implement the triangles being created, but I need to understand the vertices first before I move on. Of course, you can tell from the code that all of the strings known as 'pos2' are getting read the same way, but what I'm wondering is how I can get the values in the middle as well, the X and Y specifically (the Z's are the only ones being read).

    Again, thank you all for your support. I look forward to comments and suggestions and hope that I can achieve my goal. Hopefully this problem can be resolved and come to a close.

    - MrQuetch of the GMC.
     
    Last edited: Feb 23, 2017

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice