Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exporter des fichier *.obj dans VC++ express 2005

aidez moiiiiiiiiiii

    22 novembre 2007 à 19:50:32

    salut les zeros!

    Ben je cois ke le titre du topique résume bien la situation :(
    je veut exporter un objet blender ds mon programme qui utilise openGL mais je ne sais pas comment faire??? j'ai bien éssayé avant de poster ici de chercher par moi même,je suis tombé sur plein d'idées comme l'utilisation de GLM,oubien d'un logiciel (3D EXPLORATION) qui fait ce genre de convertion (waveform to c++) o_O mais voilà, non seulement une fois mon fichier c++ crée je ne sais pas comment l'introduire dans mon code mais en plus je suis un archi débutant en programmation :euh:
    quand a GLM j'ai rien compris a son utilisation,pourtant il me parait le plus approprié a mon cas...enfin je crois...
    alors si quelqu'un peut m'expliquer comment on fait,il est le bienvenu!
    • Partager sur Facebook
    • Partager sur Twitter
      23 novembre 2007 à 16:30:01

      Le mieux, c'est de créer sois même son propre convertisseur. Plusieurs raisons à celà:

      Utiliser un programme qui crée un fichier .cpp n'est pas pratique. En effet, des qu'il faudra ajouter un modèle, ou autre, il faudra tout recompiler. Et il faudra auttant de fichier .cpp que de modèles.

      Deuxièmement, les outils que l'on trouve sur le net utilise une structure qui leur est propre, et qui n'est pas forcément adaptée à la structure que tu utilises.


      Qu'est ce que j'entends par structure ?

      Il s'agit de la façon dont sont organisée les données. Elle est évidement dépendante de la façon dont on affiche notre modèle 3D.

      Globalement, un modèle 3D (ici fixe avec un fichier OBJ), est composées de faces, elles mêmes composées de vertex, normales, coordonnées de textures.

      On va donc commencer par créer les structures nécéssaire à la représentation d'un fichier OBJ.
      Ce format comporte:
      - la liste des vertex
      - la liste des coordonnées de texture
      - la liste des coordonnées des normales
      - la liste des indices (les polygones)

      Ce qui se traduit par

      1. // cette structure peut être utilisée par les vertex, les coordonnées de textures, et les normales
      2. struct OBJvector
      3. {
      4.     float x, y, z;
      5. };
      6. // la structure d'indices
      7. struct OBJface
      8. {
      9.      int vertex[3];
      10.      int normal[3];
      11.      int texture[3];
      12. };


      La lecture du fichier se fera ligne par ligne.
      Il faut donc savoir quel type de données contient la ligne, puis lire la ligne et interpréter son contenu.
      Déclarons alors les prototypes des fonctions suivantes:

      1. // les fonctions prennent en paramètres une ligne du fichier, et retourne son contenu correctement formaté
      2. OBJvector readVertex(std::string line);
      3. OBJvector readNormal(std::string line);
      4. OBJvector readTexture(std::string line);
      5. OBJface readFace(std::string line);


      Maintenant, passons à la fonction principale qui va lire le fichier, et appeler la fonction nécéssaire à la bonne lecture de la ligne.



      1. #include <string>
      2. #include <sstream>
      3. #include <fstream>
      4. #include <vector>
      5. void loadOBJ(std::string nom_du_fichier)
      6. {
      7.      std::ifstream file(fileName.c_str()); // on ouvre le fichier
      8.      if( !file ) {  // si le fichier ne peut pas être ouvert
      9.           return ;  // on s'arrète
      10.      }
      11.      // on utilise des vecteurs pour stocker nos données
      12.      std::vector<OBJvector> vvertex;
      13.      std::vector<OBJvector> vnormal;
      14.      std::vector<OBJvector> vtexture;
      15.      std::vector<OBJface> vface;
      16.      // tous les fichier wavefront n'ont pas forcément de texture, ou de normales
      17.      // on crée donc deux variable qui vont nous permettre de savoir si le fichier en contient
      18.      bool usetexture = false;
      19.      bool usenormal = false;
      20.      // on déclarer une ligne
      21.      std::string line;
      22.      // on lit les lignes du fichier les une après les autres
      23.      // getline() prend en paramètre le fichier, et va mettre le contenu de la ligne dans
      24.      // notre variable line
      25.      while( std::getline(file, line) )
      26.      {
      27.          // on fait un switch sur le premier caractère de la ligne
      28.          switch(line[0])
      29.          {
      30.              // si c'est un "v", on doit regarder le caractère suivant
      31.              case 'v':
      32.                   line = line.substr(1); // on supprime le premier caractère de notre ligne
      33.                   switch(line[0])        // on lis le premier caractère de notre ligne (qui ne contient plus le "v"
      34.                   {
      35.                       // si c'est un vertex
      36.                       case ' ':
      37.                           OBJvector v = readVertex(line); // on lis le vertex
      38.                           vvertex.push_back(v); // on l'ajoute aux autres
      39.                           break;
      40.                       // si c'est une normale
      41.                       case 'n':
      42.                           usenormal = true; // on indique que le fichier contient des normales
      43.                           OBJvector n = readNormal(line);
      44.                           vnormal.push_back(n);
      45.                           break;
      46.                       // si c'est une texture
      47.                       case 't':
      48.                           usetexture = true; // on indique que le fichier contient des textures
      49.                           OBJvector t = readTexture(line);
      50.                           vtexture.push_back(t);
      51.                           break;
      52.                   }
      53.                   break;
      54.               // si c'est un polygone
      55.               case 'f':
      56.                   OBJface f = readFace(line);
      57.                   vface.push_back(f);
      58.                   break;
      59.               default:
      60.                   // il s'agit d'une ligne de commentaire, on ne fait rien...
      61.                   break;
      62.           }
      63.       }
      64.       file.close(); // et on ferme le fichier
      65. }


      Voilà, avec ce code, on est capable de lire correctement un fichier OBJ, et de classer les données (quoiqu'il faut encore écrire nos fonctions "read...()" )
      Ici, comme les std::vector sont définit dans la fonction, elle seront perdues. Ce code n'est qu'à titre d'exemple. En réalité, il faudrait mettre nos std::vector dans une classe en attribut.

      Voyons maintenant nos fonction de lectures des lignes:

      1. // avant tout, une petite fonction "trim", elle s'occupe d'effacer les espaces en début de ligne
      2. std::string trim(const std::string &s)
      3. {
      4.     return s.substr(s.find_first_not_of(' ') );
      5. }
      6. OBJvector readVertex(std::string line)
      7.     {
      8.         OBJvector vector;  // on crée notre vertex
      9.         line = trim(line); // on efface les éventuels espaces
      10.         // on va convertir un morceau de string en nombre
      11.         std::istringstream is( line.substr(line.find_last_of(' ')) );
      12.         is >> vector.z;  // on obtient le z
      13.         line = line.substr(0, line.find_last_of(' '));
      14.         line = trim(line);
      15.         std::istringstream iss( line.substr(line.find_last_of(' ')) );
      16.         iss >> vector.y; // on obtient le y
      17.         line = line.substr(0, line.find_last_of(' '));
      18.         line = trim(line);
      19.         std::istringstream isss( line );
      20.         isss >> vector.x; // on obtient le x
      21.         return vector; // on retourne notre vecteur :)
      22.     }
      23. // on fait pareil pour les normales
      24. OBJvector OBJLoader::readNormal(std::string line)
      25.     {
      26.         OBJvector vector;
      27.         line = line.substr(1); // on enlève le n
      28.         line = trim(line);
      29.         std::istringstream is( line.substr(line.find_last_of(' ')) );
      30.         is >> vector.z;
      31.         line = line.substr(0, line.find_last_of(' '));
      32.         line = trim(line);
      33.         std::istringstream iss( line.substr(line.find_last_of(' ')) );
      34.         iss >> vector.y;
      35.         line = line.substr(0, line.find_last_of(' '));
      36.         line = trim(line);
      37.         std::istringstream isss( line );
      38.         isss >> vector.x;
      39.         return vector;
      40.     }
      41. // puis pour les textures.
      42. // Ici, il faut vérifier deux cas différents:
      43. // - une texture à 2 dimensions
      44. // - une texture à 3 dimensions
      45. OBJvector readTexture(std::string line)
      46.     {
      47.         float f;
      48.         OBJvector vector;
      49.         std::string stemp;
      50.         line = line.substr(1); // on enlève le "t"
      51.         line = trim(line);     // on supprime les éventuels espaces en début de ligne
      52.         // on récupère la dernière valeure
      53.         stemp = line.substr(line.find_last_of(' '));
      54.         stemp = trim(stemp);
      55.         std::istringstream iss( line.substr(line.find_last_of(' ')) );
      56.         iss >> f;
      57.         line = line.substr(0, line.find_last_of(' '));  // on récupère le reste de la chaine
      58.         line = trim(line);                              // on supprime les éventuels espaces en début de ligne
      59.         // si on est à  la dernière valeure
      60.         if( line.find_last_of(' ') > 10 || line.find_last_of(' ') < 0 )
      61.         {
      62.              std::istringstream iss( line );
      63.              iss >> vector.x;
      64.              vector.y = f;
      65.              vector.z = 0.0f;
      66.         }
      67.         else
      68.         {
      69.             std::istringstream iss( line.substr(line.find_last_of(' ')) );
      70.             iss >> vector.y;
      71.             line = line.substr(0, line.find_last_of(' '));
      72.             line = trim(line);
      73.             std::istringstream isss( line );
      74.             isss >> vector.x;
      75.             vector.z = f;
      76.         }
      77.         return vector;
      78.     }
      79. // puis notre fonction pour lire un polygone
      80. OBJface readFace(std::string line)
      81.     {
      82.         OBJface temp;
      83.         std::string s;
      84.         temp.vertex[0] = 0; temp.vertex[1] = 0; temp.vertex[2] = 0;
      85.         temp.texture[0] = 0; temp.texture[1] = 0; temp.texture[2] = 0;
      86.         temp.normal[0] = 0; temp.normal[1] = 0; temp.normal[2] = 0;
      87.         line = line.substr(1); // on retire le 'f'
      88.         line = trim(line);     // on supprime les éventuels espaces
      89.         std::istringstream is( line.substr(line.find_last_of(' ')) );
      90.         int nb=0;
      91.         while( std::getline(is, s, '/') )
      92.         {
      93.             int index;
      94.             if( s != "" )
      95.             {
      96.                 s = trim(s);
      97.                 std::istringstream convert( s );
      98.                 if(!(convert >> index) )
      99.                     index = 0;
      100.                 switch(nb)
      101.                 {
      102.                     case 0:
      103.                         temp.vertex[2] = index;
      104.                         break;
      105.                     case 1:
      106.                         temp.texture[2] = index;
      107.                         break;
      108.                     case 2:
      109.                         temp.normal[2] = index;
      110.                         break;
      111.                 }
      112.             }
      113.             nb++;
      114.         }
      115.         line = line.substr(0, line.find_last_of(' '));
      116.         line = trim(line);
      117.         std::istringstream iss( line.substr(line.find_last_of(' ')) );
      118.         nb=0;
      119.         while( std::getline(iss, s, '/') )
      120.         {
      121.             int index;
      122.             if( s != "" )
      123.             {
      124.                 s = trim(s);
      125.                 std::istringstream convert( s );
      126.                 if(!(convert >> index) )
      127.                     index = 0;
      128.                 switch(nb)
      129.                 {
      130.                     case 0:
      131.                         temp.vertex[1] = index;
      132.                         break;
      133.                     case 1:
      134.                         temp.texture[1] = index;
      135.                         break;
      136.                     case 2:
      137.                         temp.normal[1] = index;
      138.                         break;
      139.                 }
      140.             }
      141.             nb++;
      142.         }
      143.         line = line.substr(0, line.find_last_of(' '));
      144.         line = trim(line);
      145.         std::istringstream isss( line );
      146.         nb=0;
      147.         while( std::getline(isss, s, '/') )
      148.         {
      149.             int index;
      150.             if( s != "" )
      151.             {
      152.                 s = trim(s);
      153.                 std::istringstream convert( s );
      154.                 if(!(convert >> index) )
      155.                     index = 0;
      156.                 switch(nb)
      157.                 {
      158.                     case 0:
      159.                         temp.vertex[0] = index;
      160.                         break;
      161.                     case 1:
      162.                         temp.texture[0] = index;
      163.                         break;
      164.                     case 2:
      165.                         temp.normal[0] = index;
      166.                         break;
      167.                 }
      168.             }
      169.             nb++;
      170.         }
      171.         return temp;
      172.     }


      Et voilà... je t'invite à ouvrir le fichier .obj avec le bloc note pour bien comprendre comment sont organisées les données, et comment le programme les interpretes.

      Pour pouvoir afficher l'objet, celà dépend de ce que tu utilises.
      Si il s'agit de glVertex, de simple boucles suffiront:

      1. for(int i=0; i<vface.size(); ++i)
      2. {
      3.      glVertex(vvertex[vface.vertex[0]].x, vvertex[vface.vertex[0]].y, vvertex[vface.vertex[0]].z);
      4.      glVertex(vvertex[vface.vertex[1]].x, vvertex[vface.vertex[1]].y, vvertex[vface.vertex[1]].z);
      5.      glVertex(vvertex[vface.vertex[2]].x, vvertex[vface.vertex[2]].y, vvertex[vface.vertex[2]].z);
      6. }

      Il s'agit du code minimal (sans textures, ni normale), mais le principe y est.
      Pour chaque face, on récupère le vertex à utiliser ( le 1, puis le 2, puis le 3).

      Si tu utilises des tableaux, ce sera un algo dans le même genre. Mais au lieu d'afficher, il faudra mettre le tout dans un tableau.

      Voilà, en esperant t'avoir donné au moins une piste...
      • Partager sur Facebook
      • Partager sur Twitter

      Exporter des fichier *.obj dans VC++ express 2005

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown