Импорт и просмотр файлов .fbx

8

У меня небольшая проблема с импортом / отображением файлов .fbx.

Я проверил примеры, но те, которые меня интересуют больше всего (анимация и текстура), плохо документированы для понимания кем-то, кто плохо знаком с этим, как я.

Это то, что я пробовал: мне удалось получить вершины и нормали, но я застрял на получении координат текстуры для каждой вершины.

Вот мой код до сих пор:

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

Мои вопросы:

  1. Как получить координаты текстуры?
  2. Как мне заставить блендер экспортировать текстуру в формат фото? (например .jpg или .tga)
  3. Есть ли какие-либо ошибки в моем отображении?
  4. Есть ли в образцах .fbx проект, который отображает только сцену (включая анимацию и текстуру; я сам не смог ее найти)?
Taigi
источник

Ответы:

3

Относительно # 1 : метод GetTextureUV из FbxMesh должен добиться цели.

РЕДАКТИРОВАТЬ: Следующий код не проверен и грубо скопирован отсюда :

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

  }
}

РЕДАКТИРОВАТЬ 2: я рассмотрел некоторые другие примеры, которые я нашел: Кажется, есть два похожих класса: FbxVector2 и KFbxVector2, где последний имеет прямой доступ к включенным двойным значениям. Сравните этот пример:

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

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

Можете ли вы использовать эти типы K *?

РЕДАКТИРОВАТЬ 3: Эти типы K *, очевидно, из старого FBX SDK, поэтому не для всех.

Филипп Альгайер
источник
Хотелось бы получить немного больше подробностей, например, объяснение или несколько примеров. (Я уже видел этот метод, но не совсем понял, что он делает или как он это делает).
Тайги
Несколько минут назад я отредактировал небольшой пример, который нашел, что может помочь. До сих пор я никогда не работал с FBX, не говоря уже о том, что написал импортер, так что, боюсь, я не могу больше помочь, извините.
Филипп Альгайер
Хм, это выглядит довольно хорошо (я проверю это немного позже), но во многом это должно сработать! (Хотел проголосовать, но не могу :( Ненавижу иметь до 15 представителей :()
Тайги
Я знаю это чувство. Я также хотел прокомментировать некоторые другие темы ранее, но вам нужно 50 повторений для этого. Вы уже проголосовали за меня в этой теме, потому что она является хорошей отправной точкой для других. Удачи!
Филипп Алгайер
Попробовал ... Это не работает, так как GetPolygonCount является функцией bool, и для нее также требуется 2 параметра
Taigi
2

Я не эксперт в FBX, но у меня есть некоторый опыт с этим, вот мои предложения

Как получить координаты текстуры? Есть ли в образцах .fbx проект, который отображает только сцену (включая анимацию и текстуру; я сам не смог ее найти)?

Я бы предложил перейти к примеру в $ (FBXSDK) \ samples \ ImportScene

Это покажет вам, как получить УФ-координаты и другие данные

Как мне заставить блендер экспортировать текстуру в формат фото? (например .jpg или .tga)

У меня не работает блендер с экспортом FBX, извините

Есть ли какие-либо ошибки в моем отображении?

Я быстро просмотрел ваш код, поэтому не могу сказать 100%, если у вас есть ошибки, но я дам вам несколько советов, которые я изучу, работая с FBX SDK.

В зависимости от программного обеспечения 3D вы должны проверить, нужно ли конвертировать ваши UV координаты. Например, это может быть тем же, что ожидает ваше программное обеспечение, или вам нужно это сделать.

mine.U = fbx.U

мой.V = 1 - fbx.V

Также FBX в зависимости от экспортера (мой опыт работы с 3ds max) будет изменять Y & Z только для переводов, вращение будет инвертировано. Я хочу сказать, что если вы экспортируете (в 3ds max) Y-UP, lclTranslation будет соответствовать 1: 1, но lclRotation будет таким

myRot.x = fbxRot.x

myRot.y = fbxRot.z

myRot.z = fbxRot.y

Также не забудьте проверить, является ли система координат левой или правой и соответствует ли она тому, что ожидает ваше программное обеспечение, если не исправляет ее.

Создавать и настраивать импортер для FBX сложно, не сдавайтесь!

Карлос Ч
источник
2

Получение координат текстуры для моделей с одним набором UV с помощью 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_
источник