Importation et affichage de fichiers .fbx

8

J'ai un petit problème avec l'importation / l'affichage des fichiers .fbx.

J'ai vérifié les exemples mais ceux qui m'intéressent le plus (animation et texture) sont mal documentés pour être compris par quelqu'un qui est nouveau dans ce domaine comme moi.

C'est ce que j'ai essayé: j'ai réussi à obtenir les sommets et les normales mais je suis coincé à obtenir les coordonnées de texture pour chaque sommet.

Voici mon code jusqu'à présent:

3dModelBasicStructs.h

struct vertex
{
float x,y,z;
};

struct texturecoords
{
float a,b;
};

struct poligon
{
int a,b,c;
};

Model.h

#ifndef MODEL_H
#define MODEL_H
#define FBXSDK_NEW_API

#define MAX_VERTICES 80000

#include "3dModelBasicStructs.h"

#include <fbxsdk.h>
#include <iostream>
#include <GL/glut.h>
using namespace std;

class Model
{

     public:

         Model(char*);
         ~Model();

         void ShowDetails();

         char* GetModelName();
         void  SetModelName( char* );
         void  GetFbxInfo( FbxNode* );
         void  RenderModel();


      private:

          char Name[25];

          vertex vertices[MAX_VERTICES];
          texturecoords txt[MAX_VERTICES];

          float *normals;
          int numNormals;

          int *indices;
          int numIndices;

          int numVertices;


};
#endif

Model.cpp

#include "Model.h"

Model::Model(char *filename)
{
cout<<"\nA model has been built!";

numVertices=0;
numIndices=0;

FbxManager *manager = FbxManager::Create();

FbxIOSettings *ioSettings = FbxIOSettings::Create(manager, IOSROOT);
manager->SetIOSettings(ioSettings);

FbxImporter *importer=FbxImporter::Create(manager,"");
importer->Initialize(filename,-1,manager->GetIOSettings());

FbxScene *scene = FbxScene::Create(manager,"tempName");

importer->Import(scene);
importer->Destroy();

FbxNode* rootNode = scene->GetRootNode();
this->SetModelName(filename);
if(rootNode) { this->GetFbxInfo(rootNode); }

}

Model::~Model()
{
cout<<"\nA model has been destroyed!";
glDisableClientState(GL_VERTEX_ARRAY);
}


void Model::ShowDetails()
{
cout<<"\nName:"<<Name;
cout<<"\nVertices Number:"<<numVertices;
cout<<"\nIndices Number:"<<numIndices;

}

char* Model::GetModelName()
{
return Name;
}

void Model::SetModelName(char *x)
{
strcpy(Name,x);
}

void Model::GetFbxInfo( FbxNode* Node )
{

int numKids = Node->GetChildCount();
FbxNode *childNode = 0;

for ( int i=0 ; i<numKids ; i++)
{
    childNode = Node->GetChild(i);
    FbxMesh *mesh = childNode->GetMesh();

    if ( mesh != NULL)
    {
//================= Get Vertices ====================================
        int numVerts = mesh->GetControlPointsCount();

        for ( int j=0; j<numVerts; j++)
        {
            FbxVector4 vert = mesh->GetControlPointAt(j);
            vertices[numVertices].x=(float)vert.mData[0];
            vertices[numVertices].y=(float)vert.mData[1];
            vertices[numVertices++].z=(float)vert.mData[2];
    //      cout<<"\n"<<vertices[numVertices-1].x<<" "<<vertices[numVertices-1].y<<" "<<vertices[numVertices-1].z;
        }
//================= Get Indices ====================================
        numIndices=mesh->GetPolygonVertexCount();
        indices = new int[numIndices];
        indices = mesh->GetPolygonVertices();
        cout<<numIndices;
//================= Get Normals ====================================


        FbxGeometryElementNormal* normalEl = mesh->GetElementNormal();
        if( normalEl)
        {
            numNormals = mesh->GetPolygonCount()*3;
            normals = new float[numNormals*3];
            int vertexCounter=0;
            for(int polyCounter = 0 ; polyCounter<mesh->GetPolygonCount(); polyCounter++)
            {
                for(int i=0;i<3;i++)
                {
                    FbxVector4 normal = normalEl->GetDirectArray().GetAt(vertexCounter);
                    normals[vertexCounter*3+0] = normal[0];
                    normals[vertexCounter*3+1] = normal[1];
                    normals[vertexCounter*3+2] = normal[2];
                    cout<<"\n"<<normals[vertexCounter*3+0]<<" "<<normals[vertexCounter*3+1]<<" "<<normals[vertexCounter*3+2];
                    vertexCounter++;
                }
            }
        }


    }
    this->GetFbxInfo(childNode);
}
}

void Model::RenderModel()
{
int i,j;
for(i=0;i<numIndices-3;i++)
{
    glBegin(GL_TRIANGLES);
    glNormal3f(normals[i*3+0],normals[i*3+1],normals[i*3+2]); 
    for(j=i;j<=i+2;j++)
            glVertex3f(vertices[indices[j]].x,vertices[indices[j]].y,vertices[indices[j]].z);
    glEnd();
}
}

Mes questions sont:

  1. Comment obtenir les coordonnées de texture?
  2. Comment puis-je faire en sorte que le mélangeur exporte la texture au format photo? (comme .jpg ou .tga)
  3. Y a-t-il des erreurs dans ma façon d'afficher jusqu'à présent?
  4. Y a-t-il un projet dans les échantillons .fbx qui n'affiche qu'une scène (y compris l'animation et la texture; je n'ai pas pu en trouver une moi-même)?
Taigi
la source

Réponses:

3

Concernant # 1 : La méthode GetTextureUV de FbxMesh devrait faire l'affaire.

EDIT: Le code suivant n'est pas testé et est copié grossièrement à partir d' ici :

int polygonCount = mesh->GetPolygonCount();
for (int i = 0; i < polygonCount; ++i) {

  FbxLayerElementArrayTemplate<KFbxVector2>* uvVertices= 0;
  mesh->GetTextureUV(&uvVertices, KFbxLayerElement::eTextureDiffuse);

  for (int j = 0; j < mesh>GetPolygonSize(i); ++j) {

     FbxVector2 uv = uvVertices[mesh->GetTextureUVIndex(i, j)];

     texturecoords.a = uv[0];
     texturecoords.b = uv[1];

  }
}

EDIT 2: J'ai parcouru quelques autres exemples que j'ai trouvés: Il semble y avoir deux classes similaires: FbxVector2 et KFbxVector2 où ce dernier a un accès direct aux valeurs doubles incluses. Comparez cet exemple:

KFbxLayerElementArrayTemplate<KFbxVector2>* lUVArray = NULL;    
pMesh->GetTextureUV(&lUVArray, KFbxLayerElement::eDIFFUSE_TEXTURES); 

lUVArray->GetAt(mesh->GetTextureUVIndex(i, j)).mData[0];

Pouvez-vous utiliser ces types K *?

EDIT3: Ces types K * proviennent apparemment d'un SDK FBX plus ancien, donc pas pertinent pour tout le monde.

Philip Allgaier
la source
Un peu plus de détails seraient vraiment appréciés, comme une explication ou quelques exemples. (J'ai déjà vu cette méthode mais je n'ai pas vraiment compris ce qu'elle fait ni comment elle le fait).
Taigi
Il y a quelques minutes, j'ai édité un petit exemple que j'ai trouvé qui peut peut-être aider. Je n'ai jamais travaillé avec FBX jusqu'à présent, et encore moins écrit un importateur, donc je crains de ne pas vraiment pouvoir être plus utile, désolé.
Philip Allgaier
Hmm ça a l'air plutôt bien (je vais le tester un peu plus tard) mais merci beaucoup ça devrait marcher! (Je voulais voter mais je ne peux pas :( je déteste avoir moins de 15 représentants :()
Taigi
Je connais ce sentiment. Je voulais également commenter certains autres fils plus tôt, mais vous avez besoin de 50 répétitions pour cela. Vous avez déjà obtenu un vote positif de ma part pour ce fil, car il fournit un bon point de départ pour les autres. Bonne chance!
Philip Allgaier
J'ai essayé ... Cela ne fonctionne pas car GetPolygonCount est une fonction booléenne et elle nécessite également 2 paramètres
Taigi
2

Je ne suis pas un expert en FBX mais j'ai une certaine expérience avec lui, voici mes suggestions

Comment obtenir les coordonnées de texture? Y a-t-il un projet dans les échantillons .fbx qui n'affiche qu'une scène (y compris l'animation et la texture; je n'ai pas pu en trouver une moi-même)?

Je suggère de passer en revue l'exemple dans $ (FBXSDK) \ samples \ ImportScene

Cela vous montrera comment obtenir les coordonnées UV et d'autres données

Comment puis-je faire en sorte que le mélangeur exporte la texture au format photo? (comme .jpg ou .tga)

Je n'ai pas travaillé avec le mélangeur exportant FBX, désolé

Y a-t-il des erreurs dans ma façon d'afficher jusqu'à présent?

J'ai jeté un coup d'œil à votre code, donc je ne peux pas dire à 100% si vous avez des erreurs, mais je vais vous donner quelques suggestions que j'apprends à travailler avec FBX SDK.

Selon le logiciel 3D, vous devez vérifier si vous devez convertir vos cordons UV. Par exemple, cela peut être identique à ce que votre logiciel attend ou vous devez le faire

mine.U = fbx.U

mine.V = 1 - fbx.V

Aussi FBX selon l'exportateur (mon expérience avec 3ds max) cela changera Y & Z pour les traductions uniquement, la rotation sera inversée. Ce que je veux dire, c'est que si vous exportez (dans 3ds max) Y-UP, lclTranslation correspondra à 1: 1 mais lclRotation sera comme ceci

myRot.x = fbxRot.x

myRot.y = fbxRot.z

myRot.z = fbxRot.y

N'oubliez pas de vérifier pour vérifier si le système de coordonnées est à gauche ou à droite et s'il correspond à ce que votre logiciel attend, sinon le corriger.

La création et l'importateur personnalisé pour FBX est difficile, n'abandonnez pas!

Carlos Ch
la source
2

Obtention des coordonnées de texture pour les modèles avec un ensemble UV à l'aide du SDK FBX 2013:

// UV Container
std::vector<float[2]> UVList;

// Loop for each poly
for ( int Poly(0); Poly < fbxMesh->GetPolygonCount(); Poly++ )
{
    // Get number of verts in this poly
    const int NumVertices = fbxMesh->GetPolygonSize( Poly );

    // Loop for each vert in poly
    for( int Vertex(0); Vertex < NumVertices; Vertex++ )
    {
         FbxVector2 fbxTexCoord;
         FbxStringList UVSetNameList;

         // Get the name of each set of UV coords
         fbxMesh->GetUVSetNames( UVSetNameList );

         // Get the UV coords for this vertex in this poly which belong to the first UV set
         // Note: Using 0 as index into UV set list as this example supports only one UV set
         fbxMesh->GetPolygonVertexUV( Poly, Vertex, UVSetNameList.GetStringAt(0), fbxTexCoord );

         // Convert to floats
         float UVCoord[2];
         UVCoord[0] = static_cast<float>( fbxTexCoord[0] );
         UVCoord[1] = static_cast<float>( fbxTexCoord[1] );

         // Store UV
         UVList.push_back( UVCoord );
     }
}
Syntac_
la source