Importación y visualización de archivos .fbx

8

Tengo un pequeño problema con la importación / visualización de archivos .fbx.

Revisé los ejemplos, pero los que más me interesan (animación y textura) están mal documentados para que alguien que es nuevo en esto los entienda como yo.

Esto es lo que he intentado: logré obtener los vértices y las normales, pero estoy atascado en obtener las coordenadas de textura para cada vértice.

Aquí está mi código hasta ahora:

3dModelBasicStructs.h

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

struct texturecoords
{
float a,b;
};

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

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

Mis preguntas son:

  1. ¿Cómo obtengo los cordones de textura?
  2. ¿Cómo hago para que Blender exporte la textura en formato de foto? (como .jpg o .tga)
  3. ¿Hay algún error en mi forma de mostrar hasta ahora?
  4. ¿Hay un proyecto en las muestras .fbx que solo muestre una escena (incluyendo animación y textura; no pude encontrar una yo mismo)?
Taigi
fuente

Respuestas:

3

Con respecto al n. ° 1 : El método GetTextureUV de FbxMesh debería ser el truco.

EDITAR: el siguiente código no se ha probado y se ha copiado desde aquí :

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: Revisé algunos otros ejemplos que encontré: Parece que hay dos clases similares: FbxVector2 y KFbxVector2 donde este último tiene acceso directo a los valores dobles incluidos. Compara ese ejemplo:

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

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

¿Puedes usar esos tipos K *?

EDIT3: esos tipos K * aparentemente son de un SDK FBX anterior, por lo que no son relevantes para todos.

Philip Allgaier
fuente
Se agradecería un poco más de detalle, como una explicación o algunos ejemplos. (Ya he visto este método pero realmente no entendí lo que hace o cómo lo hace).
Taigi el
Hace unos minutos, edité en un pequeño ejemplo que encontré que puede ayudar tal vez. Nunca trabajé con FBX hasta ahora, y mucho menos escribí un importador, así que me temo que realmente no puedo ser de más ayuda, lo siento.
Philip Allgaier
Hmm eso se ve bastante bien (lo probaré un poco más tarde) pero muchas gracias, ¡esto debería funcionar! (Quería votar pero no puedo :( odio tener menos de 15 rep :()
Taigi
Conozco el sentimiento También quería comentar algunos otros hilos anteriormente, pero necesitas 50 repeticiones para eso. Ya obtuviste un voto positivo de mi parte para este hilo, porque proporciona un buen punto de partida para otros. ¡La mejor de las suertes!
Philip Allgaier
Lo probé ... No funciona ya que GetPolygonCount es una función bool y también requiere 2 parámetros
Taigi
2

No soy un experto en FBX pero tengo algo de experiencia, aquí están mis sugerencias

¿Cómo obtengo los cordones de textura? ¿Hay un proyecto en las muestras .fbx que solo muestre una escena (incluyendo animación y textura; no pude encontrar una yo mismo)?

Sugeriría revisar el ejemplo en $ (FBXSDK) \ samples \ ImportScene

Esto le mostrará cómo obtener los códigos UV y otros datos.

¿Cómo hago para que Blender exporte la textura en formato de foto? (como .jpg o .tga)

No he trabajado con Blender exportando FBX, lo siento

¿Hay algún error en mi forma de mostrar hasta ahora?

Eché un vistazo rápido a su código, así que no puedo decir 100% si tiene errores, pero le daré algunas sugerencias que aprendo trabajando con FBX SDK.

Dependiendo del software 3D, debe verificar si necesita convertir sus UV Coords. Por ejemplo, podría ser lo mismo que su software espera o necesita hacer esto

mine.U = fbx.U

mine.V = 1 - fbx.V

También FBX dependiendo del exportador (mi experiencia con 3ds max) cambiará Y y Z solo para traducciones, la rotación se invertirá. Lo que quiero decir es que si exportas (en 3ds max) Y-UP, lclTranslation coincidirá con 1: 1 pero lclRotation será así

myRot.x = fbxRot.x

myRot.y = fbxRot.z

myRot.z = fbxRot.y

También recuerde verificar para verificar si el sistema de coordenadas es Izquierdo o Derecho y si coincide con lo que su software espera, si no lo corrige.

La creación y el importador personalizado para FBX es un desafío, ¡no te rindas!

Carlos Ch
fuente
2

Obtención de coordenadas de textura para modelos con un conjunto UV con 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_
fuente