我需要帮助将自定义文件格式加载到我用c ++编写的程序中... 我知道有一种简单的方法可以做到这一点,但我想我正在使用它 错误的条款在线搜索...
我的3d对象自定义格式如下:
NumVerts 6
//verts (float)
-1
-1
0
1
-1
0
-1
1
0
1
-1
0
1
1
0
-1
1
0
//texture (float)
0
0
1
0
0
1
1
0
1
1
0
1
//index (int)
0
1
2
1
3
2
这是一个四核......(是的;我知道......可怕的格式......但它是我用于安卓游戏的东西)。
我想在c ++中为我的编辑器(SDL + OpenGL for windows)创建一个函数,将这些文件加载到数据中...不幸的是,虽然我知道如何用C ++导出这种格式,但我无法弄清楚如何导入它们...我希望使用fstream命令...
如果有人能够快速写出一个简单的版本,我会非常感激。
我只是做以下事情:
感谢您阅读,现在任何帮助都会非常好......或者是一个非常简单的重用链接,从文件中读取字符串并从中获取数字以放入内存...
我真的只想完成这个游戏,并且试图找到有用的教程时会非常紧张。
更新:更新了脚本......我意外地忘了分开1和0 ...
答案 0 :(得分:2)
希望这会有所帮助。顺便提一下,你的顶点组件数量是错误的 - 你需要18
个。
#include <algorithm>
#include <exception>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
int load_3d_object(const std::string& filename,
std::vector<float>& vertComponents,
std::vector<float>& texComponents,
std::vector<int>& indices)
{
std::ifstream fs(filename.c_str());
std::string line;
if(!std::getline(fs, line))
{
throw std::runtime_error("The input file is empty");
}
if(line.substr(0,8) != "NumVerts")
{
throw std::runtime_error("The first line must start with NumVerts");
}
// Extract the number of vertices.
int numVerts = lexical_cast<int>(line.substr(line.find(' ') + 1));
// Read in the vertex components, texture components and indices.
while(std::getline(fs, line))
{
boost::trim(line);
if(line.substr(0,2) == "//") continue;
if((int)vertComponents.size() < numVerts * 3) vertComponents.push_back(lexical_cast<float>(line));
else if((int)texComponents.size() < numVerts * 2) texComponents.push_back(lexical_cast<float>(line));
else indices.push_back(lexical_cast<int>(line));
}
return numVerts;
}
int main()
{
std::vector<float> vertComponents;
std::vector<float> texComponents;
std::vector<int> indices;
try
{
int numVerts = load_3d_object("input.txt", vertComponents, texComponents, indices);
}
catch(std::exception& e)
{
std::cout << e.what() << '\n';
}
return 0;
}
答案 1 :(得分:1)
希望这可能会有所帮助(最小的错误检查):
int _get_num_verts_value(std::ifstream& a_in)
{
char buf[128];
int result = -1;
a_in.getline(buf, sizeof(buf));
while (a_in.good())
{
if (a_in.gcount() > 9)
{
string s(buf);
if (0 == s.find("NumVerts "))
{
result = atoi(s.substr(8).c_str());
break;
}
}
a_in.getline(buf, sizeof(buf));
}
return result;
}
template <typename T>
void _get_values(std::ifstream& a_in, std::vector<T>& a_values)
{
char buf[128];
a_in.getline(buf, sizeof(buf));
int i = 0;
while (a_in.good())
{
string line(buf);
if (0 != line.find("//"))
{
a_values[i++] = boost::lexical_cast<T>(line);
// All read ?
if (i == a_values.capacity())
{
break;
}
}
a_in.getline(buf, sizeof(buf));
}
}
int main(int /*a_argc*/, char** /*a_argv*/)
{
ifstream in("test.txt");
const int num_verts_value = _get_num_verts_value(in);
std::vector<float> verts(num_verts_value * 3);
_get_values<float>(in, verts);
std::vector<float> textures(num_verts_value * 2);
_get_values<float>(in, textures);
std::vector<int> indexes(num_verts_value);
_get_values<int>(in, indexes);
in.close();
return 0;
}
答案 2 :(得分:0)
为此目的使用平面文件可能是一个坏主意。它非常脆弱。我更喜欢二进制文件或自描述文件(例如xml)。
std::ifstream in("in");
char buf[256];
std::string line;
int NumVerts;
in >> buf >> NumVerts;
std::vector<float> verts(NumVerts * 3);
std::getline(in, line);//read the rest of the line
std::getline(in, line);//skip the comment line
std::for_each(verts.begin(), verts.end(), [&in](float& par){
in >> par;
});
std::vector<float> texture(NumVerts * 2);
std::getline(in, line);//read the rest of the line
std::getline(in, line);//skip the comment line
std::for_each(texture.begin(), texture.end(), [&in](float& par){
in >> par;
});
std::vector<int> index(NumVerts);
std::getline(in, line);//read the rest of the line
std::getline(in, line);//skip the comment line
std::for_each(index.begin(), index.end(), [&in](int& par){
in >> par;
});
答案 3 :(得分:0)
关于如何DIY的链接:
示例代码:
#include <string>
#include <iostream> // needed for printing stuff out
#include <fstream> // Needed to read the file
#include <stdexcept>
#include <vector>
using namespace std;
struct Vertice {
double x,y,z; // 3 part stuff to read
double a,b; // 2 part stuff to read
int i; // 1 int thing to read
};
/// Reads a number ignoring comment lines (and any other line that isn't a number)
template <typename T>
T readNumber(istream& data) {
char lastChar;
while (data.good()) {
data >> lastChar; // Don't use peek as that won't skip whitespace
data.putback(lastChar);
if (( (lastChar >= '0') && (lastChar <= '9') ) || (lastChar == '-')) {
// If we're looking at a number read and return it
T result;
data >> result;
return result;
} else {
// If it's not part of a number .. assume it's a comment line and skip the whole line
string commentLine;
getline(data, commentLine);
// TODO: Maybe just skip '//' lines and throw an exception for everything else..
}
}
throw exception("Couldn't read file");
}
double readDouble(istream& data) { return readNumber<double>(data); }
int readInt(istream& data) { return readNumber<int>(data); }
int main(int argc, char** argv) {
if (argc != 2)
cout << "Usage: " << argv[0] << " [DATA_FILE_NAME]" << endl;
else {
fstream data(argv[1], ios_base::in);
data >> skipws; // Skip whitespace
string lastString;
long numVerts = -1;
// Read in words ignoring everything until we hit a 'NumVerts'
while (numVerts < 0) {
data >> lastString;
if (lastString == "NumVerts")
data >> numVerts;
}
// We know how many to get now
typedef vector<Vertice> Verts;
Verts verts(numVerts);
// Read in the triples
for (Verts::iterator i=verts.begin(); i != verts.end(); ++i) {
i->x = readDouble(data);
i->y = readDouble(data);
i->z = readDouble(data);
}
// Read in the pairs (some other data)
for (Verts::iterator i=verts.begin(); i != verts.end(); ++i) {
i->a = readDouble(data);
i->b = readDouble(data);
}
// Read in the single integer value
for (Verts::iterator i=verts.begin(); i != verts.end(); ++i) {
i->i = readInt(data);
}
// Print out all we found
for (Verts::iterator i=verts.begin(); i != verts.end(); ++i) {
cout << "Vertice" << endl
<< " x: " << i->x << endl
<< " y: " << i->y << endl
<< " z: " << i->z << endl
<< " a: " << i->a << endl
<< " b: " << i->b << endl
<< " i: " << i->i << endl
<< endl;
}
}
}
示例代码在提供的文件上引发错误,因为没有足够的数据来填写'NumVerts'。