2010-05-25 6 views
1

j'écrit petit programme en OpenGL, et j'ai problème (textures sont désalignement, et je ne sais pas pourquoi, ce modèle fonctionne dans un autre spectateur obj) Ce que j'ai: http://img696.imageshack.us/i/obrazo.png/ Qu'est-ce que Je veux http://img88.imageshack.us/i/obraz2d.jpg/ code de projet (j'utilise diable pour les images):problème Opengl texture dans le modèle de obj

#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(); 
} 

Répondre

1

Je pense que je venais de pousser un point factice sur le début de votre vecteur points, et laisse le point des références de base 1. Je voudrais également me débarrasser du while (!in.eof()), qui normalement lira la dernière ligne deux fois. Enfin, j'utiliser quelques operator>> de surcharge pour lire la plupart des données, ce qui donne un résultat qui ressemblait à ceci:

#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; 
} 

Un point mineur: tout en utilisant les paramètres régionaux pour traiter «/» comme séparateur entre le nombre de travaux pour la variante spécifique de OBJ que vous regardez, il ne travail pour les fichiers qui contiennent des lignes comme:

f a//b c//d e//f 

Néanmoins, l'idée générale (lecture avec plus operator>>) sera bien quand/si vous décidez de l'améliorer pour gérer cette variante du format.

Edit: Je pense que je viens de réaliser une partie du problème. Le code pour lire un visage doit être comme ceci:

temp >> triangle.a >> triangle.atc >> triangle.an; 
temp >> triangle.b >> triangle.btc >> triangle.bn; 
temp >> triangle.c >> triangle.ctc >> triangle.cn; 

Ie, dans le fichier, il est disposé comme sommet/TexCoord/normal, mais votre code et ma version précédente ci-dessus a essayé de le lire comme vertex/normal/texcoord). Une fois le code organisé de cette façon, la vérification par rapport à une référence rendait le problème assez évident.

+0

Thx :) Mais quand je compile ce code, j'obtiens une erreur dans free.c (certains fichiers incluent ce compilateur), je compile avec vs 2008, mayby ​​c'est un problème. Erreur: Windows a déclenché un point d'arrêt dans Project.exe. Cela peut être dû à une corruption du tas, ce qui indique un bogue dans Project.exe ou l'une des DLL qu'il a chargé. Cela peut également être dû au fait que l'utilisateur a appuyé sur F12 alors que Project.exe a le focus. La fenêtre de sortie peut avoir plus d'informations de diagnostic. – piotrek

+0

Mais, qu'en est-il de ce biais?:/Je ne sais pas pourquoi cela s'est propagé de cette façon. – piotrek

+0

Je suppose que le placement incorrect est dû à l'interprétation de la texcoord comme normale et vice versa. –

0

Ok je fixe tout: D: D Ce que je fais: changement

glTexCoord2f(tc.x,tc.y); 

à

glTexCoord2f(tc.x,1-tc.y); 

et la chose la plus importante que je changer la résolution d'image 1024x1024 (I useing mipmaping si Je pense que la résolution correcte de l'image est importante) Maintenant: Peut-on m'expliquer pourquoi lTexCoord2f (tc.x, 1-tc.y); travail ? et est-il important de faire chaque image 2^x résolution?