I writing small program in OpenGL, and I have problem ( textures are skew, and I dont know why, this model work in another obj viewer) What I have: http://img696.imageshack.
I think I'd just push a dummy point on the beginning of your points
vector, and leave the point references 1-based. I'd also get rid of the while (!in.eof())
, which will normally read the last line twice. Finally, I'd use a few overloads of operator>>
to read most of the data, giving a result that looked something like this:
#include <locale>
#include <vector>
#include <sstream>
#include <string>
#include <fstream>
/* change to "#if 0" for normal compilation: */
#if 1
struct Triangle { float a, an, atc, b, bn, btc, c, cn, ctc; };
struct Vector2d { float x, y; };
struct Vector3d { float x, y, z; };
std::vector<Triangle> triangles;
std::vector<Vector3d> points, normals;
std::vector<Vector2d> texcords;
#endif
namespace {
struct slashsep: std::ctype<char> {
slashsep(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::mask());
rc['/'] = std::ctype_base::space; // Treat '/' as a separator between numbers.
rc[' '] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
rc['\t'] = std::ctype_base::space;
return &rc[0];
}
};
std::istream &operator>>(std::istream &in, Triangle &triangle) {
std::string str;
std::getline(in, str);
std::istringstream temp(str);
slashsep loc;
temp.imbue(std::locale(std::locale(), &loc));
temp >> triangle.a >> triangle.an >> triangle.atc;
temp >> triangle.b >> triangle.bn >> triangle.btc;
temp >> triangle.c >> triangle.cn >> triangle.ctc;
return in;
}
std::istream &operator>>(std::istream &in, Vector3d &v) {
return in >> v.x >> v.y >> v.z;
}
std::istream &operator>>(std::istream &in, Vector2d &v) {
return in >> v.x >> v.y;
}
}
bool read_obj(std::string const &fileName) {
points.clear();
points.push_back(Vector3d());
triangles.clear();
std::ifstream in(fileName.c_str());
std::string cmd;
if (!in.is_open())
return false;
while(in>>cmd) {
if(cmd=="v") {
Vector3d vector;
in >> vector;
points.push_back(vector);
}
if(cmd=="vt") {
Vector2d texcord;
in >> texcord;
texcords.push_back(texcord);
}
if(cmd=="vn"){
Vector3d normal;
in >> normal;
normals.push_back(normal);
}
if(cmd=="f") {
Triangle triangle;
in >> triangle;
triangles.push_back(triangle);
}
}
return true;
}
One minor point: while using the locale to treat '/' as a separator between numbers works for the specific variant of OBJ that you're looking at, it will not work for files that contain lines like:
f a//b c//d e//f
Nonetheless, the general idea (most reading with operator>>
) will be fine when/if you decide to enhance it to handle this variant of the format.
Edit: I think I just realized part of the problem. The code to read a face should be like this:
temp >> triangle.a >> triangle.atc >> triangle.an;
temp >> triangle.b >> triangle.btc >> triangle.bn;
temp >> triangle.c >> triangle.ctc >> triangle.cn;
I.e., in the file, it's arranged as vertex/texcoord/normal, but your code and my previous version above tried to read it as vertex/normal/texcoord). Once the code was arranged this way, checking against a reference made the problem fairly obvious.
Ok i fix all :D:D What I do: change
glTexCoord2f(tc.x,tc.y);
to
glTexCoord2f(tc.x,1-tc.y);
and the most important thing I change image resolution to 1024x1024 ( I useing mipmaping so I think correct image resolution is important) Now: Can sameone explain me why lTexCoord2f(tc.x,1-tc.y); work ? and is it important to make every image 2^x resolution ?