This is a cross-post from game-dev because it seems more general to graphical programming than game development.
I have written a simple .obj parser for my OpenGL game engine that reads vertices, uv’s and normals; but when I get to drawing the model in the texture isn’t mapped correctly.
I have tried
uv.y = 1.0f-uv.y
to get inverted Y axis coordinates as suggested by a few people but my textures are still skewed.
I know the texture and my rendering are correct because when I render a plane, with hand written texture coordinates and vertices using the same texture, it renders fine. I can render a textured cube by hand fine too.
I am using an index buffer to store vertex elements and I use the face elements provided by the obj to fill texture coordinate and normal buffers with the correct vectors.
What is wrong with my parser?
PARSER CODE:
Model::Model(const string &givenName, const string &filePath){
name = givenName;
std::ifstream in(MODEL_PATH+filePath, std::ios::in);
if(!in){
error("Model \"" + filePath + "\" does not exist");
return;
}
ModelMeshIndex tempindex;
vector<vec3> normals;
vector<vec2> uvs;
string line;
while(getline(in, line)){
if(line.substr(0,2) == "v "){
std::istringstream s(line.substr(2));
vec3 v(0.0f);
s >> v.x >> v.y >> v.z;
data.vertices.push_back(v);
}
else if(line.substr(0,2) == "vt"){
std::istringstream s(line.substr(2));
vec2 v(0.0f);
s >> v.x >> v.y;
//v.y = 1.0f-v.y;
uvs.push_back(v);
}
else if(line.substr(0,2) == "vn"){
std::istringstream s(line.substr(2));
vec3 v(0.0f);
s >> v.x >> v.y >> v.z;
normals.push_back(v);
}
else if(line.substr(0,2) == "f "){
std::istringstream s(line.substr(1));
char tmp; // For the slashes between elements
unsigned short a,b,c, d,e,f, g,h,i;
s >> a >> tmp >> d >> tmp >>g;
s >> b >> tmp >> e >> tmp >>h;
s >> c >> tmp >> f >> tmp >>i;
a--; b--; c--; d--; e--; f--; g--; h--; i--;
data.index.vertexElements.push_back(a); data.index.vertexElements.push_back(b); data.index.vertexElements.push_back(c);
data.index.uvElements.push_back(d); data.index.uvElements.push_back(e); data.index.uvElements.push_back(f);
data.index.normalElements.push_back(g); data.index.normalElements.push_back(h); data.index.normalElements.push_back(i);
}
else if(line[0] == '#') continue;
else continue;
}
for(unsigned int i = 0; i < data.index.normalElements.size(); ++i)
data.normals.push_back(normals[data.index.normalElements[i]]);
for(unsigned int i = 0; i < data.index.uvElements.size(); ++i)
data.uvs.push_back(uvs[data.index.uvElements[i]]);
//data.uvs.push_back(vec2( 0.0f, 0.0f)); // bottom left
//data.uvs.push_back(vec2( 0.0f, 1.0f)); // top left
//data.uvs.push_back(vec2( 1.0f, 0.0f)); // bottom right
//data.uvs.push_back(vec2( 1.0f, 1.0f)); // top right
good = true;
}
:doh: