OpenGL的问题与纹理的OBJ模型 [英] Opengl problem with texture in model from obj
问题描述
我写小程序在OpenGL中,我有问题(纹理斜,我不知道为什么,在另一个OBJ观众这一模式的工作) 我有: http://img696.imageshack.us/i/obrazo.png/ 我想要的是 http://img88.imageshack.us/i/obraz2d.jpg/ $ C $项目C(我用魔鬼的图像):
的#pragma一次
#包括< WINDOWS.H>
#定义GLUT_DISABLE_ATEXIT_HACK
#包括< glut.h>
#包括< GL / glu.h>
#包括< GL / gl.h>
#包括< GL / GLEXT.h>
#包括<的iostream>
#包括< CMATH>
#包括< IL / il.h>
#包括<载体>
#包括< fstream的>
#包括<字符串>
#包括< cstdlib>
#包括< sstream>
#包括< clocale>
类TextureManager
{
结构TextureInfo {
性病::字符串名称;
GLuint形象;
};
私人:
的std ::矢量< TextureInfo>纹理;
上市:
TextureManager(无效);
〜TextureManager(无效);
布尔AddTexture(标准::字符串名称,性病::字符串文件名);
INT GetTexture(标准::字符串名);
};
TextureManager :: TextureManager(无效)
{
ilInit();
}
TextureManager ::〜TextureManager(无效)
{
}
布尔TextureManager :: AddTexture(标准::字符串名称,性病::字符串文件名)
{
布尔成功;
ILuint texId;
GLuint形象;
ilGenImages(1,&安培; texId);
ilBindImage(texId);
成功= ilLoadImage((WCHAR *)fileName.c_str());
如果(成功)
{
成功= ilConvertImage(IL_RGB,IL_UNSIGNED_BYTE);
如果(!成功)
{
返回false;
}
}
其他
{
返回false;
}
glGenTextures(1,&安培;图像);
glBindTexture(GL_TEXTURE_2D,图像);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST_MIPMAP_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,ilGetInteger(IL_IMAGE_WIDTH),ilGetInteger(IL_IMAGE_HEIGHT),GL_RGB,GL_UNSIGNED_BYTE,ilGetData());
ilDeleteImages(1,&安培; texId);
TextureInfo TI;
ti.name =名称;
ti.image =图像;
textures.push_back(TI);
返回true;
}
INT TextureManager :: GetTexture(标准::字符串名称)
{
INT大小= textures.size();
的for(int i = 0; I<大小;我++)
{
如果(textures.at(我).name.compare(名称)== 0)
{
返回textures.at(我)在图像配;
}
}
返回-1;
}
使用名字空间std;
TextureManager TM;
结构点
{
双X,Y,Z;
};
结构正常
{
双X,Y,Z;
};
结构三角
{
诠释A,B,C;
INT时,BT,CT;
诠释一个,BN,CN;
};
结构TexCord
{
浮动的x,y;
};
矢量<点和GT;分;
矢量<正常>法线;
矢量<三角>三角形;
矢量< TexCord> texcords;
INT W,H;
双J = 0.0;
双K = 0.0;
INT模式= 1;
布尔showNormals = FALSE;
无效setCamera(双eyex,双eyey,双EYEZ,双重的centerX,双centery,双centerz)
{
gluLookAt(eyex,eyey,EYEZ,的centerX,centery,centerz,0,1,0);
}
无效DrawPoint(TexCord TC,点P,法线N)
{
glTexCoord2f(tc.x,tc.y);
glNormal3f(n.x的,N.Y,n.z);
glVertex3f(p.x,p.y,p.z);
}
无效DrawNormal(点P,法线N)
{
glPushMatrix();
glTranslated(p.x,p.y,p.z);
在glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(n.x的* 2,N.Y * 2,* n.z 2);
glEnd();
glPopMatrix();
}
无效processNormalKeys(无符号字符键,诠释的x,int y)对{
如果(关键== 27)
出口(0);
如果(关键=='Q')
{
模式= 0;
}
如果(关键=='W')
{
模式= 1;
}
如果(关键=='A')
{
的k - = 0.1;
}
如果(关键=='S')
{
K + = 0.1;
}
如果(关键=='Z')
{
的J - = 0.1;
}
如果(关键==X)
{
J + = 0.1;
}
如果(关键=='N')
{
如果(showNormals ==真)
{
showNormals = FALSE;
}
其他
{
showNormals = TRUE;
}
}
glutPostRedisplay();
}
无效renderScene(无效){
//j+=0.0005;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)瓦特/(GLfloat)H,1.0,100.0);
setCamera(15 * SIN(j)中,15 * COS(k)时,15 * COS(j)条* SIN(k)时,0,0,0);
glMatrixMode(GL_MODELVIEW);
过glEnable(GL_DEPTH_TEST);
过glEnable(GL_LIGHTING);
//过glEnable(GL_LIGHT0);
浮环境[] = {1.0,1.0,1.0,0.0};
浮动扩散[] = {1.0,1.0,1.0,1.0};
浮动位置[] = {25.0,25.0,25.0,1.0};
glLightfv(GL_LIGHT0,GL_AMBIENT,弥漫性);
glLightfv(GL_LIGHT0,GL_DIFFUSE,弥漫性);
glLightfv(GL_LIGHT0,GL_POSITION,位置);
过glEnable(GL_DEPTH_TEST);
过glEnable(GL_LIGHTING);
过glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glClearColor(0.0,0.0,0.0,1.0F);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
过glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,tm.GetTexture(特));
如果(模式== 0)
{
在glBegin(GL_TRIANGLES);
}
其他
{
在glBegin(GL_LINES);
}
的for(int i = 0; I< triangles.size();我++)
{
//双R =兰特()/(双)RAND_MAX;
// glColor3f(R,R,R);
DrawPoint(texcords [三角形[I]。CT-1],点[三角形[I]的.c-1],法线[三角形[I]的.cn-1]);
DrawPoint(texcords [三角形[I]。BT-1],点[三角形[i]于.B-1],法线[三角形[i]于.bn-1]);
DrawPoint(texcords [三角形[i]于.AT-1],点[三角形[i]于.A-1],法线[三角形[I]。一种-1]);
}
glEnd();
glDisable(GL_TEXTURE_2D);
如果(showNormals ==真)
{
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glColor3f(1,0.5f,0.25f);
的for(int i = 0; I< points.size();我++)
{
DrawNormal(点[I],法线[I]);
}
}
glFlush();
glutSwapBuffers();
}
无效重塑(INT宽度,高度INT){
W =宽度; H =高度;
glViewport(0,0,(GLsizei)宽度,(GLsizei)高度);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)宽度/(GLfloat)高度,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
}
无效更新(int值){
J + = 0.1F;
glutPostRedisplay(); //告诉GLUT的一幕发生了变化
//告诉GLUT调用更新又在25毫秒
// glutTimerFunc(100,更新,0);
}
INT主(INT ARGC,字符** argv的){
矢量<正常> * NN =安培;法线;
矢量<点和GT; * PP =放大器;点;
矢量<三角> * TT =安培;三角形;
矢量< TexCord> * TTCC =安培; texcords;
glutInit(安培; ARGC,ARGV);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320320);
glutCreateWindow(模型视图);
glutKeyboardFunc(processNormalKeys);
glutDisplayFunc(renderScene);
// glutIdleFunc(renderScene);
glutReshapeFunc(重塑);
ifstream的F;
串CMD;
f.open(model.obj);
如果(f.is_open())
{
而(!f.eof())
{
F>>在cmd;
如果(CMD ==V)
{
点p;
F>> p.x;
F>> p.y;
F>> p.z;
points.push_back(对);
}
如果(CMD ==VN)
{
普通N;
F>> n.x的;
F>> N.Y;
F>> n.z;
normals.push_back(N);
}
如果(CMD ==VT)
{
TexCord TC;
F>> tc.x;
F>> tc.y;
texcords.push_back(TC);
}
如果(CMD ==F)
{
三角吨;
字符串str;
串pointStr,normalStr,cordStr;
字符串分隔符(/);
INT POS,POS2;
stringstream的SS(字符串流::在| stringstream的::出来);
F>> STR;
POS = str.find(分隔符);
pointStr = str.substr(0,POS);
cordStr = str.substr(POS + delimeter.length());
POS2 = cordStr.find(分隔符);
normalStr = cordStr.substr(POS2 + delimeter.length());
cordStr = cordStr.substr(0,POS2);
SS<< pointStr;
SS>> T.A;
ss.clear();
SS<< normalStr;
SS>> t.an;
ss.clear();
SS<< cordStr;
SS>> t.at;
ss.clear();
F>> STR;
POS = str.find(分隔符);
pointStr = str.substr(0,POS);
cordStr = str.substr(POS + delimeter.length());
POS2 = cordStr.find(分隔符);
normalStr = cordStr.substr(POS2 + delimeter.length());
cordStr = cordStr.substr(0,POS2);
SS<< pointStr;
SS>> t.b;
ss.clear();
SS<< normalStr;
SS>> t.bn;
ss.clear();
SS<< cordStr;
SS>> t.bt;
ss.clear();
F>> STR;
POS = str.find(分隔符);
pointStr = str.substr(0,POS);
cordStr = str.substr(POS + delimeter.length());
POS2 = cordStr.find(分隔符);
normalStr = cordStr.substr(POS2 + delimeter.length());
cordStr = cordStr.substr(0,POS2);
SS<< pointStr;
SS>> T.C;
ss.clear();
SS<< normalStr;
SS>> t.cn;
ss.clear();
SS<< cordStr;
SS>> t.ct;
ss.clear();
triangles.push_back(T);
}
CMD =;
}
f.close(); }
tm.AddTexture(特克斯,texture.png);
// glutTimerFunc(100,更新,0);
glutMainLoop();
}
我觉得我只是推了你的点开始
载体的虚拟点,并留下点参考文献1为主。我还摆脱了,而(!in.eof())
,这将正常读取的最后一行的两倍。最后,我想用几个重载运营商GT;>
读取大部分数据,给人一种结果看起来是这样的:
的#include<区域>
#包括<载体>
#包括< sstream>
#包括<字符串>
#包括< fstream的>
/ *变更为#如果0正常编译:* /
#如果1
结构三角{浮起,一,空管,B,BN,BTC,C,CN,CTC; };
结构的Vector2D {浮动的x,y; };
结构的Vector3D {浮法X,Y,Z; };
的std ::矢量<三角>三角形;
的std ::矢量<&的Vector3D GT;点,法线;
的std ::矢量<&的Vector2D GT; texcords;
#ENDIF
命名空间{
结构slashsep:性病:: CTYPE<焦炭> {
slashsep():的std :: CTYPE<烧焦>(get_table()){}
静态的std :: ctype_base ::面具常量* get_table(){
静态的std ::矢量<的std :: ctype_base ::面膜>
RC(STD :: CTYPE<烧焦> :: table_size,性病:: ctype_base ::面膜());
RC ['/'] =的std :: ctype_base ::空间; //款待/作为数字之间的隔板。
RC [''] =的std :: ctype_base ::空间;
RC ['\ N'] =的std :: ctype_base ::空间;
RC ['\ t'] =的std :: ctype_base ::空间;
返回和放大器; RC [0];
}
};
的std :: istream的&放大器;运营商GT;>(的std :: istream的&放大器;而在三角和放大器;三角形){
的std ::字符串str;
的std ::函数getline(中,STR);
的std :: istringstream温度(STR);
slashsep禄;
temp.imbue(性病::区域设置(标准::区域设置(),放大器; LOC));
温度>> triangle.a>> triangle.an>> triangle.atc;
温度>> triangle.b>> triangle.bn>> triangle.btc;
温度>> triangle.c>> triangle.cn>> triangle.ctc;
返回;
}
的std :: istream的&放大器;运营商GT;>(的std :: istream的&放大器;而在,的Vector3D和放大器; 5){
返回>> V.X>> V.Y>> V.Z;
}
的std :: istream的&放大器;运营商GT;>(的std :: istream的&放大器;而在,的Vector2D和放大器; 5){
返回>> V.X>> V.Y;
}
}
布尔read_obj(标准::字符串常量和放大器;文件名){
points.clear();
points.push_back(的Vector3D());
triangles.clear();
的std :: ifstream的在(fileName.c_str());
标准::字符串CMD;
如果(!in.is_open())
返回false;
而(在>> CMD){
如果(CMD ==V){
的Vector3D载体;
在>>向量;
points.push_back(向量);
}
如果(CMD ==VT){
的Vector2D texcord;
在>> texcord;
texcords.push_back(texcord);
}
如果(CMD ==VN){
的Vector3D正常;
在>>正常;
normals.push_back(正常);
}
如果(CMD ==F){
三角三角;
在>>三角形;
triangles.push_back(三角形);
}
}
返回true;
}
一个小问题:在使用的语言环境来治疗'/'作为数字之间的分隔符工程OBJ的具体变量,你看,它会的没有的工作文件包含行这样的:
F A // B C // D E //˚F
不过,总的想法(大多数的阅读与运营商GT;>
)。当/如果你决定提升其处理这种变体的格式将被罚款
编辑:我想我只是意识到了问题的一部分。在code阅读面应该是这样的:
温度>> triangle.a>> triangle.atc>> triangle.an;
温度>> triangle.b>> triangle.btc>> triangle.bn;
温度>> triangle.c>> triangle.ctc>> triangle.cn;
也就是说,在该文件中,它设置为顶点/ TEXCOORD /正常的,但你的code和我的previous以上版本试图读取它的顶点/正常/ TEXCOORD)。一旦code被安排这样一来,核对参考使问题相当明显。
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.us/i/obrazo.png/ What I want http://img88.imageshack.us/i/obraz2d.jpg/ Code of project (I use devil for images):
#pragma once
#include <windows.h>
#define GLUT_DISABLE_ATEXIT_HACK
#include <glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <GL/GLEXT.h>
#include <iostream>
#include <cmath>
#include <IL/il.h>
#include <vector>
#include <fstream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <clocale>
class TextureManager
{
struct TextureInfo{
std::string name;
GLuint image;
};
private:
std::vector<TextureInfo> textures;
public:
TextureManager(void);
~TextureManager(void);
bool AddTexture(std::string name, std::string fileName);
int GetTexture(std::string name);
};
TextureManager::TextureManager(void)
{
ilInit();
}
TextureManager::~TextureManager(void)
{
}
bool TextureManager::AddTexture(std::string name, std::string fileName)
{
bool success;
ILuint texId;
GLuint image;
ilGenImages(1, &texId);
ilBindImage(texId);
success = ilLoadImage((WCHAR*)fileName.c_str());
if(success)
{
success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
if(!success)
{
return false;
}
}
else
{
return false;
}
glGenTextures(1, &image);
glBindTexture(GL_TEXTURE_2D, image);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST_MIPMAP_LINEAR);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT),GL_RGB, GL_UNSIGNED_BYTE, ilGetData());
ilDeleteImages(1, &texId);
TextureInfo ti;
ti.name = name;
ti.image = image;
textures.push_back(ti);
return true;
}
int TextureManager::GetTexture(std::string name)
{
int size = textures.size();
for(int i=0;i<size;i++)
{
if(textures.at(i).name.compare(name) == 0)
{
return textures.at(i).image;
}
}
return -1;
}
using namespace std;
TextureManager tm;
struct Point
{
double x,y,z;
};
struct Normal
{
double x,y,z;
};
struct Triangle
{
int a,b,c;
int at,bt,ct;
int an,bn,cn;
};
struct TexCord
{
float x,y;
};
vector<Point> points;
vector<Normal> normals;
vector<Triangle> triangles;
vector<TexCord> texcords;
int w,h;
double j = 0.0;
double k = 0.0;
int mode = 1;
bool showNormals = false;
void setCamera(double eyex,double eyey, double eyez, double centerx, double centery, double centerz)
{
gluLookAt(eyex,eyey,eyez,centerx,centery,centerz,0,1,0);
}
void DrawPoint(TexCord tc,Point p,Normal n)
{
glTexCoord2f(tc.x,tc.y);
glNormal3f(n.x,n.y,n.z);
glVertex3f(p.x,p.y,p.z);
}
void DrawNormal(Point p,Normal n)
{
glPushMatrix();
glTranslated(p.x,p.y,p.z);
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(n.x*2,n.y*2,n.z*2);
glEnd();
glPopMatrix();
}
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
if (key == 'q')
{
mode = 0;
}
if (key == 'w')
{
mode = 1;
}
if (key == 'a')
{
k -= 0.1;
}
if (key == 's')
{
k += 0.1;
}
if (key == 'z')
{
j -= 0.1;
}
if (key == 'x')
{
j += 0.1;
}
if (key == 'n')
{
if(showNormals == true)
{
showNormals = false;
}
else
{
showNormals = true;
}
}
glutPostRedisplay();
}
void renderScene(void) {
//j+=0.0005;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
setCamera(15*sin(j),15*cos(k),15*cos(j)*sin(k),0,0,0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);
float ambient[]={ 1.0, 1.0, 1.0, 0.0};
float diffuse[]={1.0, 1.0, 1.0, 1.0};
float position[]={25.0,25.0, 25.0, 1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, diffuse);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tm.GetTexture("tex"));
if(mode == 0 )
{
glBegin(GL_TRIANGLES);
}
else
{
glBegin(GL_LINES);
}
for(int i=0;i<triangles.size();i++)
{
//double r = rand()/(double)RAND_MAX;
//glColor3f(r,r,r);
DrawPoint(texcords[triangles[i].ct-1],points[triangles[i].c-1],normals[triangles[i].cn-1]);
DrawPoint(texcords[triangles[i].bt-1],points[triangles[i].b-1],normals[triangles[i].bn-1]);
DrawPoint(texcords[triangles[i].at-1],points[triangles[i].a-1],normals[triangles[i].an-1]);
}
glEnd();
glDisable(GL_TEXTURE_2D);
if(showNormals == true)
{
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glColor3f(1,0.5f,0.25f);
for(int i = 0;i<points.size();i++)
{
DrawNormal(points[i],normals[i]);
}
}
glFlush();
glutSwapBuffers();
}
void reshape (int width, int height) {
w = width; h = height;
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void update(int value) {
j += 0.1f;
glutPostRedisplay(); //Tell GLUT that the scene has changed
//Tell GLUT to call update again in 25 milliseconds
// glutTimerFunc(100, update, 0);
}
int main(int argc, char **argv) {
vector<Normal> *nn = &normals;
vector<Point> *pp = &points;
vector<Triangle> *tt = &triangles;
vector<TexCord> *ttcc = &texcords;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("Model view");
glutKeyboardFunc(processNormalKeys);
glutDisplayFunc(renderScene);
//glutIdleFunc(renderScene);
glutReshapeFunc(reshape);
ifstream f;
string cmd;
f.open ("model.obj");
if (f.is_open())
{
while(!f.eof())
{
f>>cmd;
if(cmd=="v")
{
Point p;
f>>p.x;
f>>p.y;
f>>p.z;
points.push_back(p);
}
if(cmd=="vn")
{
Normal n;
f>>n.x;
f>>n.y;
f>>n.z;
normals.push_back(n);
}
if(cmd=="vt")
{
TexCord tc;
f>>tc.x;
f>>tc.y;
texcords.push_back(tc);
}
if(cmd=="f")
{
Triangle t;
string str;
string pointStr,normalStr,cordStr;
string delimeter("/");
int pos,pos2;
stringstream ss (stringstream::in | stringstream::out);
f>>str;
pos = str.find(delimeter);
pointStr = str.substr(0,pos);
cordStr = str.substr(pos+delimeter.length());
pos2 = cordStr.find(delimeter);
normalStr = cordStr.substr(pos2+delimeter.length());
cordStr = cordStr.substr(0,pos2);
ss<<pointStr;
ss>>t.a;
ss.clear();
ss<<normalStr;
ss>>t.an;
ss.clear();
ss<<cordStr;
ss>>t.at;
ss.clear();
f>>str;
pos = str.find(delimeter);
pointStr = str.substr(0,pos);
cordStr = str.substr(pos+delimeter.length());
pos2 = cordStr.find(delimeter);
normalStr = cordStr.substr(pos2+delimeter.length());
cordStr = cordStr.substr(0,pos2);
ss<<pointStr;
ss>>t.b;
ss.clear();
ss<<normalStr;
ss>>t.bn;
ss.clear();
ss<<cordStr;
ss>>t.bt;
ss.clear();
f>>str;
pos = str.find(delimeter);
pointStr = str.substr(0,pos);
cordStr = str.substr(pos+delimeter.length());
pos2 = cordStr.find(delimeter);
normalStr = cordStr.substr(pos2+delimeter.length());
cordStr = cordStr.substr(0,pos2);
ss<<pointStr;
ss>>t.c;
ss.clear();
ss<<normalStr;
ss>>t.cn;
ss.clear();
ss<<cordStr;
ss>>t.ct;
ss.clear();
triangles.push_back(t);
}
cmd = "";
}
f.close(); }
tm.AddTexture("tex","texture.png");
//glutTimerFunc(100, update, 0);
glutMainLoop();
}
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.
这篇关于OpenGL的问题与纹理的OBJ模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!