简体   繁体   中英

OBJ file in C++ with ubuntu problems

I'm having a problem reading an OBJ file... Problem 1 is that the vectors are declared as floats (and have been declared as doubles), but print out in the terminal gives me all integers. Terminal output has been:

    1-1-1
    1-11
    -1-11
    -1-1-1

when it ought to be:

     1.000000 -1.000000 -1.000000
     1.000000 -1.000000 1.000000
     -1.000000 -1.000000 1.000000
     -1.000000 -1.000000 -1.000000

Problem 2 is that I have been unable to read the faces in the file correctly. The output has been:

    1
    5
    1
    2

when it should be:

    1 2 3 4
    5 8 7 6
    1 5 6 2
    2 6 7 3

I'm trying to get the results to print out correctly now, since I will next be putting these results in nodes using dynamic memory allocation due to their varying in size. Here's the code:

/* This function opens the OBJ file */
void openFile(string nf){   
std::ifstream file;
file.open (nf, std::ifstream::out);

string line;
string o_name;
string faces;
char o;
char v;
char f;
int i = 0;
float x;
float y;
float z;

if(file.is_open()){
std::cout<< "file is open!\n";
//include actions for OBJ file...Just read. You work from memory
    while(std::getline(file, line))
    {
        if(line.empty())        //line is empty, then file is empty!
            std::cout << "file is empty! \n";
        /* finds the shape name*/
        if (line[i] == 'o')
        {
            std::istringstream iss (line);
            iss >> o >> o_name;
            std::cout << o_name << endl;
            line.clear();
            //createNodeO(string o_name);
        }
        /* finds the vertices*/             
        if (line[i] == 'v')
        {
            std::istringstream iss (line);
            iss >> v >> x >> y >> z;
            std::cout << x << y << z << endl;
            line.clear();
            //createNodeO(float x, float y, float z);
        }

        /* finds the faces*/                        
        if (line[i] == 'f')
        {
            std::istringstream iss (line);
            iss >> f >> faces;
            std::cout << faces << endl;
            //createNodeO(string faces);
        }
    }
}
else{
    std::cout<< "could not open the file!\n";
}
file.close();
std::cout<< "file is closed!\n";    

}

According to the g++ compiler, I'm crazy when it comes to the faces part. Please help!

This is sorta how I would do it. You could also use operator>> for each type if you felt fancy.

Differences from your example:

I ignore everything but verts and faces and assume there's no w in the verts and no vt, vn, vp, etc. in the file. There are possibly names, groups, materials, etc. that you might run into too. If you find yourself getting in over your head or your desire to write parsers wanes you might check out a library to do it. http://www.assimp.org/ is a good one, and there's a good viewer here http://www.open3mod.com/ which can definitely help if what you are parsing doesn't quite look right.

Your code is tokenizing and writing straight to your destination variables, I chose to tokenize first and then convert the tokens to the right type after some basic validation of the line. Either works. I'd usually do it the way you did, maybe with operator>> or a helper function.

I tested with a few of the files from here: https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html

Hope this helps.

#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

struct vertex
{
    double x, y, z;
};

struct face
{
    std::vector<int> v;
};

struct object
{
    std::vector<vertex> verts;
    std::vector<face> faces;
};

std::ostream& operator<<(std::ostream& out, const vertex& v)
{
    out << "v " 
        << std::fixed << std::setprecision(6) << v.x << " "
        << std::fixed << std::setprecision(6) << v.y << " "
        << std::fixed << std::setprecision(6) << v.z;
    return out;
}

std::ostream& operator<<(std::ostream& out, const face& f)
{
    out << "f";
    for (size_t i = 0; i < f.v.size(); ++i)
    {
        out << " " << f.v[i];
    }
    return out;
}

std::ostream& operator<<(std::ostream& out, const object& o)
{
    for (size_t i = 0; i < o.verts.size(); ++i)
    {
        out << o.verts[i] << "\n";
    }
    for (size_t i = 0; i < o.faces.size(); ++i)
    {
        out << o.faces[i] << "\n";
    }
    return out;
}

std::vector<std::string> split(const std::string& s)
{
    std::vector<std::string> ret;
    std::string token;
    std::stringstream ss(s);
    while (ss >> token)
    {
        ret.push_back(token);
    }
    return ret;
}

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " <obj filename>\n";
        return -1;
    }

    std::fstream in(argv[1]);
    if (!in)
    {
        std::cerr << "File: " << argv[1] << " could not be opened\n";
        return -1;
    }

    object o;
    std::string line;
    int lineNumber = 0;
    while (std::getline(in, line))
    {
        ++lineNumber;

        if (line.empty() || line[0] == '#')
        {
            continue;
        }

        std::vector<std::string> tokens = split(line);
        if (line[0] == 'v')
        {
            if (tokens.size() < 4)
            {
                std::cerr << "Invalid vert: '" << line << "' on line: " << lineNumber << "\n";
                continue;
            }

            vertex v;
            v.x = std::stod(tokens[1]);
            v.y = std::stod(tokens[2]);
            v.z = std::stod(tokens[3]);
            o.verts.push_back(v);
        }
        else if (line[0] == 'f')
        {
            if (tokens.size() < 4)
            {
                std::cerr << "Invalid face: '" << line << "' on line: " << lineNumber << "\n";
                continue;
            }

            face f;
            for (size_t i = 1; i < tokens.size(); ++i)
            {
                f.v.push_back(std::stoi(tokens[i]));
            }
            o.faces.push_back(f);
        }
    }

    std::cout << o;
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM