8
\$\begingroup\$

I have a little problem with importing/displaying .fbx files.

I checked the examples but the ones which I am intrested the most (animation and texture) are badly documented for understanding by someone who is new to this like I am.

This is what I have tried: I managed to get the vertices and the normals but I'm stuck on getting the texture coords for each vertex.

Here is my code so far:

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

My questions are:

  1. How do I get the texture coords?
  2. How do I make blender export the texture in a photo format? (like .jpg or .tga)
  3. Are there any mistakes in my displaying way so far?
  4. Is there a project in the .fbx samples which only display a scene (including animation and texture; I couldn't find one myself)?
\$\endgroup\$
1
  • \$\begingroup\$ a small correction in getIndices, you allocate an array then reassign the variable: indices = new int[numIndices]; <---- do you need that? indices = mesh->GetPolygonVertices(); <--- gets lost here \$\endgroup\$
    – Spider
    Commented Dec 5, 2023 at 0:46

3 Answers 3

3
\$\begingroup\$

Regarding #1: The method GetTextureUV of FbxMesh should get the trick done.

EDIT: The following code is untested and rougly copied from here:

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: I went through some other examples I found: There seems to be two similar classes: FbxVector2 and KFbxVector2 where the latter one has the direct access to the included double values. Compare that example:

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

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

Can you use those K* types?

EDIT3: Those K* types are apparently from an older FBX SDK, so not relevant for everyone.

\$\endgroup\$
19
  • \$\begingroup\$ A little bit more detail would be really appreciated , like an explanation or some examples. ( I have already saw this method but did not really understood what it does or how it does it). \$\endgroup\$
    – Taigi
    Commented Jan 5, 2013 at 0:13
  • \$\begingroup\$ Some minutes ago, I edited in a little example I found that can help perhaps. I never worked with FBX so far, let alone wrote an importer, so I'm afraid I cannot really be of more help, sorry. \$\endgroup\$ Commented Jan 5, 2013 at 0:15
  • \$\begingroup\$ Hmm that looks pretty good ( I will test it out a lil bit latter ) but thnx a lot this should work! ( Wanted to vote up but i can't :( i hate having under 15 rep:() \$\endgroup\$
    – Taigi
    Commented Jan 5, 2013 at 0:22
  • \$\begingroup\$ I know the feeling. I also wanted to comment on some other threads earlier, but you need 50 rep for that. You already got an up-vote from me for this thread, because it provides a good starting point for others. Best of luck! \$\endgroup\$ Commented Jan 5, 2013 at 0:26
  • \$\begingroup\$ Tryed it ... It does not work since GetPolygonCount is a bool function and it also requires 2 parameters \$\endgroup\$
    – Taigi
    Commented Jan 5, 2013 at 1:40
2
\$\begingroup\$

I am no expert in FBX but I have some experience with it, here are my suggestions

How do I get the texture coords? Is there a project in the .fbx samples which only display a scene (including animation and texture; I couldn't find one myself)?

I would suggest going over the example in $(FBXSDK)\samples\ImportScene

This will show you how to get the UV Coords and other data

How do I make blender export the texture in a photo format? (like .jpg or .tga)

I have not work with blender exporting FBX, sorry

Are there any mistakes in my displaying way so far?

I had a quick look at your code, so can't say 100% if you have mistakes, but I will give you some suggestions that I learn working with FBX SDK.

Depending on the 3D Software you have to check if you need to convert your UV Coords. For example it could be the same as what your software expects or you need to do this

mine.U = fbx.U

mine.V = 1 - fbx.V

Also FBX depending on the exporter (my experience with 3ds max) it will change Y & Z for translations only, rotation will be inverted. What I want to say is if you export (in 3ds max) Y-UP, lclTranslation will match 1:1 but lclRotation will be like this

myRot.x = fbxRot.x

myRot.y = fbxRot.z

myRot.z = fbxRot.y

Also remember to check to check if the coordinate system is Left or Right and if it matches what your software expect, if not correct it.

Creating and custom importer for FBX is challenging do not give up!

\$\endgroup\$
2
\$\begingroup\$

Getting texture coordinates for models with one UV set Using 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 );
     }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .