Importando e exibindo arquivos .fbx

8

Estou com um pequeno problema com a importação / exibição de arquivos .fbx.

Eu verifiquei os exemplos, mas os que mais me interessam (animação e textura) estão mal documentados para serem entendidos por alguém que é novo nisso como eu.

Isto é o que eu tentei: consegui obter os vértices e os normais, mas estou preso em obter as cordas de textura para cada vértice.

Aqui esta o meu codigo ate agora:

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

Minhas perguntas são:

  1. Como obtenho as cordas de textura?
  2. Como faço para o liquidificador exportar a textura em um formato de foto? (como .jpg ou .tga)
  3. Há algum erro no meu modo de exibição até agora?
  4. Existe um projeto nas amostras .fbx que exibe apenas uma cena (incluindo animação e textura; eu não consegui encontrar uma)?
Taigi
fonte

Respostas:

3

Em relação ao item 1 : O método GetTextureUV do FbxMesh deve executar o truque.

EDIT: O código a seguir é não testado e copiado aleatoriamente daqui :

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];

  }
}

Edição 2: Passei por alguns outros exemplos que encontrei: Parece haver duas classes semelhantes: FbxVector2 e KFbxVector2, em que a última tem acesso direto aos valores duplos incluídos. Compare esse exemplo:

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

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

Você pode usar esses tipos K *?

EDIT3: Esses tipos K * são aparentemente de um SDK do FBX mais antigo, portanto não são relevantes para todos.

Philip Allgaier
fonte
Um pouco mais de detalhes seriam realmente apreciados, como uma explicação ou alguns exemplos. (Eu já vi esse método, mas realmente não entendi o que faz ou como faz).
Taigi
Alguns minutos atrás, editei um pequeno exemplo que achei que pode ajudar talvez. Eu nunca trabalhei com o FBX até agora, e muito menos escrevi um importador, por isso tenho medo de não poder ajudar mais, desculpe.
Philip Allgaier
Hmm, que parece muito bom (vou testá-lo um pouco mais tarde), mas, em seguida, muito deve funcionar! (Queria votar, mas eu não posso :( eu odeio ter menos de 15 representantes :())
Taigi
Eu conheço o sentimento. Eu também queria comentar alguns outros tópicos anteriormente, mas você precisa de 50 representantes para isso. Você já recebeu um voto positivo para este tópico, porque ele fornece um bom ponto de partida para outros. Boa sorte!
Philip Allgaier
Tentei isso ... ele não funciona desde GetPolygonCount é uma função bool e também requer 2 parâmetros
Taigi
2

Não sou especialista em FBX, mas tenho alguma experiência com isso, aqui estão minhas sugestões

Como obtenho as cordas de textura? Existe um projeto nas amostras .fbx que exibe apenas uma cena (incluindo animação e textura; eu não consegui encontrar uma)?

Eu sugeriria revisar o exemplo em $ (FBXSDK) \ samples \ ImportScene

Isso mostrará como obter as cordas UV e outros dados

Como faço para o liquidificador exportar a textura em um formato de foto? (como .jpg ou .tga)

Eu não trabalho com liquidificador exportando FBX, desculpe

Há algum erro no meu modo de exibição até agora?

Eu dei uma olhada rápida no seu código, então não posso dizer 100% se houver erros, mas darei algumas sugestões que aprendi a trabalhar com o FBX SDK.

Dependendo do software 3D, é necessário verificar se é necessário converter suas cordas UV. Por exemplo, pode ser o mesmo que o seu software espera ou você precisa fazer isso

mine.U = fbx.U

mine.V = 1 - fbx.V

Além disso, o FBX, dependendo do exportador (minha experiência com o 3ds max), mudará Y & Z apenas para traduções, a rotação será invertida. O que quero dizer é que se você exportar (no 3ds max) Y-UP, lclTranslation corresponderá a 1: 1, mas lclRotation será assim

myRot.x = fbxRot.x

myRot.y = fbxRot.z

myRot.z = fbxRot.y

Lembre-se também de verificar se o sistema de coordenadas é Esquerda ou Direita e se corresponde ao que o seu software espera, se não o corrigir.

Criar e importar importador para FBX é desafiador, não desista!

Carlos Ch
fonte
2

Obtendo coordenadas de textura para modelos com um conjunto UV Usando o FBX SDK 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_
fonte