obj 模型中纹理的 Opengl 问题
我在 OpenGL 中编写小程序,但遇到问题(纹理倾斜,我不知道为什么,该模型在另一个 obj 查看器中工作) 我有什么: http://img696.imageshack.us/i/obrazo.png/ 我想要什么 http://img88.imageshack.us/i/obraz2d.jpg/ 项目代码(我使用 Devil 来表示图像):
#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 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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想我只需在
points
向量的开头推入一个虚拟点,并将点引用保留为基于 1 的。我还要去掉 while (!in.eof()) ,它通常会读取最后一行两次。最后,我将使用operator>>
的一些重载来读取大部分数据,给出如下所示的结果:一个小要点: while using the locale to treat '/'由于数字之间的分隔符适用于您正在查看的 OBJ 的特定变体,因此它不适用于包含以下行的文件:
尽管如此,总体思路(大多数使用
operator> 阅读;>
) 当/如果您决定增强它以处理这种格式变体时会很好。编辑:我想我刚刚意识到部分问题。读取脸部的代码应该是这样的:
即,在文件中,它被排列为顶点/法线/法线,但是您的代码和我上面的先前版本尝试将其读取为顶点/法线/法线)。一旦代码按照这种方式排列,对照参考进行检查就会使问题变得相当明显。
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 thewhile (!in.eof())
, which will normally read the last line twice. Finally, I'd use a few overloads ofoperator>>
to read most of the data, giving a result that looked something like this: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:
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:
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.
好的,我修复了所有 :D:D
我做什么:
更改
为
,最重要的是我将图像分辨率更改为 1024x1024(我使用 mipmaping,所以我认为正确的图像分辨率很重要)
现在:
Sameone 可以解释一下为什么 lTexCoord2f(tc.x,1-tc.y);工作 ?
让每张图像的分辨率都为 2^x 重要吗?
Ok i fix all :D:D
What I do:
change
to
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 ?