My .OBJ Model Loader doesn't seem to output the right scanned data of cube.obj?

Started by
22 comments, last by Dominic Hughes 8 years, 10 months ago

I can't access why and how this code is not outputing the right results and if this is the best way to .obj file parsing with c++ since ".c_str()"?

So far it gets the filename and opens it up with ifstream then checks if the ifstream opened up good
then it gets the lines and checks with strstr if the char array contains a v and space "v "
if it does then sscanf the char array "c-string" at that position "I suppose" for the format number.number number number.

However even that format specifier is wrong I think... but it's all so confusing to me.

The documentation writes "..." for this parameter of sscanf(const char * char, const char *format , ...);


Here is the code :

void OpenGL::LoadObj(const char * objfile)
{
std::ifstream objstream(objfile);
std::string objfiletext;
int value[3];
while(objstream.good())
{
std::getline(objstream, objfiletext);
if(strstr(objfiletext.c_str(), "v "))
{
sscanf(objfiletext.c_str(), "%d.%d %d %d", value[0], value[1], value[2], value[3]);
std::cout << value[0] << value[1] << value[2] << std::endl;
}
}

}

public member function usage :

GLrenderer.LoadObj("cube.obj");



CONSOLE OUTPUT :

3414949232
3414949232
3414949232
3414949232
3414949232
3414949232
3414949232
3414949232


CUBE.OBJ :

# Blender v2.74 (sub 0) OBJ File: ''
# www.blender.org
o Cube
v 1.500000 -1.000000 -1.000000
v 1.500000 -1.000000 1.000000
v -1.500000 -1.000000 1.000000
v -1.500000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
s off
f 2 3 4
f 8 7 6
f 5 6 2
f 6 7 3
f 3 7 8
f 1 4 8
f 1 2 4
f 5 8 6
f 1 5 2
f 2 6 3
f 4 3 8
f 5 1 8
Please don't tell me to use a library like assimp , I wanna do this all by myself thank you.
Advertisement

%d is integers, %f is floats. You probably just need "%f %f %f". Your values are also ints, which is obviously wrong.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Wondering if the only data you can get is from objfiletext.c_str() not from the stored values...??

Just tried that same thing different garbage output :

4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039
4.2039e-0452.8026e-0454.83284e-039


CUBE.OBJ :

# Blender v2.74 (sub 0) OBJ File: ''
# www.blender.org
o Cube
v 1.500000 -1.000000 -1.000000
v 1.500000 -1.000000 1.000000
v -1.500000 -1.000000 1.000000
v -1.500000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
s off
f 2 3 4
f 8 7 6
f 5 6 2
f 6 7 3
f 3 7 8
f 1 4 8
f 1 2 4
f 5 8 6
f 1 5 2
f 2 6 3
f 4 3 8
f 5 1 8
UPDATED CODE :

void OpenGL::LoadObj(const char * objfile)
{


     std::ifstream objstream(objfile);
    std::string objfiletext;


    float value[2];


    while(objstream.good())
    {
        std::getline(objstream, objfiletext);


        if(strstr(objfiletext.c_str(), "v "))
        {


            sscanf(objfiletext.c_str(), "%f %f %f", value[0], value[1], value[2]);


            std::cout << value[0] << value[1] << value[2] << std::endl;
        }
    }


}


Oh - you still need the v part in the string. Try: "v %f %f %f".

Also, your array declaration is incorrect, it should be value[3] as you have three values.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

You’ve done this 2 times now. You keep declaring your array 1 shorter than it has to be.
float value[3];
In both sets of code you posted you overflowed the buffer when you used it in ::sscanf().


L. Spiro

Ninja’ed.

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

You’ve done this 2 times now. You keep declaring your array 1 shorter than it has to be.
float value[3];
In both sets of code you posted you overflowed the buffer when you used it in ::sscanf().


L. Spiro

Ninja’ed.

For the record, clang by default emits a warning, among others, that highlights the out of bounds access (gcc, obviously, does not):


test.cpp:24:73: warning: array index 2 is past the end of the array (which contains 2 elements) [-Warray-bounds]
  ...sscanf(objfiletext.c_str(), "%f %f %f", value[0], value[1], value[2]);
                                                                 ^     ~

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

URGH.... I'm aware of this ..

However I'm still getting this crappy output :

v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 0.000000

changed it to c instead for ease "I think"


void OpenGL::LoadObj(const char * objfile)
{
    FILE *objfile_pointer;
    long objfile_size;
    objfile_pointer = fopen(objfile, "r+w");

    float tmpx, tmpy, tmpz;
    char i;

    char objfile_buffer[256];
    if(objfile_pointer!= NULL)
    {
        while(fgets(objfile_buffer, sizeof(objfile_buffer), objfile_pointer))
        {
            if(fgetc(objfile_pointer) == 'v')
            {
      
               sscanf(objfile_buffer, "v %f %f %f", &tmpx, &tmpy, &tmpz);
               printf("v %f %f %f");
         
            }

        }
    }
}

You could use tinyobjloader. It does the job well enough.

https://github.com/syoyo/tinyobjloader

LOL Dave ... that is just no thanks.

printf("v %f %f %f");

should be

printf("v %f %f %f", tmpx, tmpy, tmpz);
Engine, graphics, low-level, security and cross-platform programming. xsngine

This topic is closed to new replies.

Advertisement