Importieren und Anzeigen von .fbx-Dateien

8

Ich habe ein kleines Problem beim Importieren / Anzeigen von .fbx-Dateien.

Ich habe die Beispiele überprüft, aber diejenigen, die mich am meisten interessieren (Animation und Textur), sind für jemanden, der so neu ist wie ich, schlecht dokumentiert, um sie zu verstehen.

Folgendes habe ich versucht: Ich habe es geschafft, die Scheitelpunkte und Normalen zu ermitteln, aber ich bin fest entschlossen, die Texturkoordinaten für jeden Scheitelpunkt zu ermitteln.

Hier ist mein Code bisher:

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

Meine Fragen sind:

  1. Wie bekomme ich die Texturkoordinaten?
  2. Wie lasse ich Blender die Textur in ein Fotoformat exportieren? (wie .jpg oder .tga)
  3. Gibt es bisher Fehler bei der Anzeige?
  4. Gibt es in den .fbx-Beispielen ein Projekt, das nur eine Szene anzeigt (einschließlich Animation und Textur; ich konnte selbst keine finden)?
Taigi
quelle

Antworten:

3

Zu # 1 : Die Methode GetTextureUV von FbxMesh sollte den Trick erledigen.

BEARBEITEN: Der folgende Code ist ungetestet und wird von hier grob kopiert :

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: Ich habe einige andere Beispiele durchgesehen, die ich gefunden habe: Es scheint zwei ähnliche Klassen zu geben: FbxVector2 und KFbxVector2, wobei letztere direkten Zugriff auf die enthaltenen Doppelwerte haben. Vergleichen Sie dieses Beispiel:

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

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

Können Sie diese K * -Typen verwenden?

EDIT3: Diese K * -Typen stammen anscheinend aus einem älteren FBX-SDK und sind daher nicht für alle relevant.

Philip Allgaier
quelle
Ein bisschen mehr Details wären sehr willkommen, wie eine Erklärung oder einige Beispiele. (Ich habe diese Methode bereits gesehen, aber nicht wirklich verstanden, was sie tut oder wie sie es tut).
Taigi
Vor einigen Minuten habe ich ein kleines Beispiel bearbeitet, das mir vielleicht helfen kann. Ich habe bisher noch nie mit FBX gearbeitet, geschweige denn einen Importeur geschrieben. Ich fürchte, ich kann nicht wirklich weiterhelfen, sorry.
Philip Allgaier
Hmm das sieht ziemlich gut aus (ich werde es ein bisschen später testen), aber vielen Dank sollte das funktionieren! (Wollte abstimmen, aber ich kann nicht :( Ich hasse es, unter 15 Wiederholungen zu haben :()
Taigi
Ich kenne das Gefühl. Ich wollte auch einige andere Themen früher kommentieren, aber dafür brauchst du 50 Wiederholungen. Sie haben bereits eine Gegenstimme von mir für diesen Thread erhalten, da er einen guten Ausgangspunkt für andere bietet. Viel Glück!
Philip Allgaier
Versucht es ... Es funktioniert nicht, da GetPolygonCount eine Bool-Funktion ist und es auch 2 Parameter erfordert
Taigi
2

Ich bin kein Experte für FBX, aber ich habe einige Erfahrungen damit. Hier sind meine Vorschläge

Wie bekomme ich die Texturkoordinaten? Gibt es in den .fbx-Beispielen ein Projekt, das nur eine Szene anzeigt (einschließlich Animation und Textur; ich konnte selbst keine finden)?

Ich würde vorschlagen, das Beispiel in $ (FBXSDK) \ samples \ ImportScene durchzugehen

Dies zeigt Ihnen, wie Sie die UV-Koordinaten und andere Daten erhalten

Wie lasse ich Blender die Textur in ein Fotoformat exportieren? (wie .jpg oder .tga)

Ich habe nicht mit Blender gearbeitet, der FBX exportiert, sorry

Gibt es bisher Fehler bei der Anzeige?

Ich habe mir Ihren Code kurz angesehen, kann also nicht 100% sagen, wenn Sie Fehler haben, aber ich werde Ihnen einige Vorschläge geben, die ich beim Arbeiten mit FBX SDK gelernt habe.

Abhängig von der 3D-Software müssen Sie prüfen, ob Sie Ihre UV-Koordinaten konvertieren müssen. Zum Beispiel könnte es das sein, was Ihre Software erwartet, oder Sie müssen dies tun

mine.U = fbx.U

mine.V = 1 - fbx.V

Auch FBX ändert je nach Exporteur (meine Erfahrung mit 3ds Max) Y & Z nur für Übersetzungen, Rotation wird invertiert. Was ich sagen möchte ist, wenn Sie (in maximal 3ds) Y-UP exportieren, wird lclTranslation 1: 1 entsprechen, aber lclRotation wird so sein

myRot.x = fbxRot.x

myRot.y = fbxRot.z

myRot.z = fbxRot.y

Denken Sie auch daran, zu überprüfen, ob das Koordinatensystem links oder rechts ist und ob es den Erwartungen Ihrer Software entspricht, wenn es nicht korrigiert wird.

Erstellen und benutzerdefinierten Importer für FBX ist eine Herausforderung, nicht aufgeben!

Carlos Ch
quelle
2

Abrufen von Texturkoordinaten für Modelle mit einem UV-Satz Verwenden von 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_
quelle