OBJ файл в C ++ с проблемами с Ubuntu - PullRequest
0 голосов
/ 20 сентября 2018

У меня проблема с чтением файла OBJ ... Проблема 1 в том, что векторы объявлены как числа с плавающей запятой (и были объявлены как числа с двойным числом), но распечатка в терминале дает мне все целые числа.Вывод на терминал был:

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

, когда он должен быть:

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

Проблема 2 в том, что я не смог правильно прочитать лица в файле.Вывод был:

    1
    5
    1
    2

, когда это должно быть:

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

Я пытаюсь получить результаты для правильной распечатки прямо сейчас, так как в следующий раз я буду помещать эти результатыв узлах используется динамическое выделение памяти из-за их разного размера.Вот код:

/* 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";    

}

Согласно компилятору g ++, я без ума от части лица.Пожалуйста, помогите!

1 Ответ

0 голосов
/ 26 сентября 2018

Это как бы я это сделал.Вы также можете использовать operator>> для каждого типа, если вам это нравится.

Отличия от вашего примера:

Я игнорирую все, кроме вершин и граней, и предполагаю, что в вертах нет w и нет vt, vn, vp и т. д. в файле.Возможно, есть имена, группы, материалы и т. Д., С которыми вы тоже можете столкнуться.Если у вас возникли проблемы с головой или ваше желание писать парсеры ослабло, вы можете проверить библиотеку, чтобы сделать это.http://www.assimp.org/ хороший, и здесь есть хороший зритель http://www.open3mod.com/, который определенно может помочь, если то, что вы анализируете, выглядит не совсем правильно.

Ваш код токенизирован изаписывая прямо в переменные назначения, я сначала выбрал токенизацию, а затем преобразовал токены в правильный тип после некоторой базовой проверки строки.Либо работает.Обычно я делаю это так, как вы, возможно, с помощью operator>> или вспомогательной функции.

Я протестировал несколько файлов здесь: https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html

Надеюсь, это поможет.

#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;
}
...