在 OpenGl 中导入和显示 .fbx 文件

4

我一直在尝试使用 FBX SDK 导入和显示一个 fbx 文件,但是我卡在了显示部分。虽然已经成功加载了文件,但是无法正确显示。

  1. 那些索引具体指的是什么?
  2. 如何显示这些顶点?

这是我编写的类:

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
#define MAX_POLIGONS 80000


#include <fbxsdk.h>
#include "3dModelBasicStructs.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();
                     void  InitializeVertexBuffer( vertex* );

      private:

          char Name[25];

          vertex vertices[MAX_VERTICES];
          poligon poligons[MAX_POLIGONS];

          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 destroied!";
}


void Model::ShowDetails()
{
cout<<"\nName:"<<Name;
cout<<"\nVertices Number:"<<numVertices;
cout<<"\nIndices which i never get:"<<indices;

}

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;
this->InitializeVertexBuffer(vertices);
        }
//================= Get Indices ====================================
        int *indices = mesh->GetPolygonVertices();
        numIndices+=mesh->GetPolygonVertexCount();
    }
    this->GetFbxInfo(childNode);
}
}

void Model::RenderModel()
{
glDrawElements(GL_TRIANGLES,36,GL_INT,indices);
}
void Model::InitializeVertexBuffer(vertex *vertices)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,0,vertices);
//glDrawArrays(GL_TRIANGLES,0,36);
}

很遗憾,当我尝试使用drawelements时,出现了以下错误: 在A new begging.exe中的0x77e215de处未处理的异常: 0xC0000005: 访问冲突,读取位置为0xcdcdcdcd。


那个访问冲突只是一个指针“指向”它的边界,可能像操作系统的边界等。我不知道如何修复它,最好尝试定位该指针并可能不使用指针来处理该访问冲突。或者你可以尝试导入KERNAL32到你的程序中,以可能解决它。检查是否有任何可能导致问题的char[MAX+1]。 - Nfagie Yansaneh
1个回答

13

2)如何显示顶点?

这类问题表明您需要学习一些OpenGL教程,这是基础知识,您需要掌握它们。

以下链接是解决您问题的好起点,但您需要完成整个教程:http://opengl.datenwolf.net/gltut/html/Basics/Tut01%20Following%20the%20Data.html

1)这些索引到底是什么?

您有一个顶点列表。顶点的索引是其在该列表中的位置。您可以使用索引绘制顶点数组,方法是使用glDrawElements

由于评论更新

假设您有一个具有共享顶点的立方体(在OpenGL中不常见,但我懒得编写24个顶点)。

Cube Vertices

我将它们放在程序中的一个数组中,形成它们位置的列表。您可以从文件中加载它们,我将它们写成C数组:

GLfloat vertices[3][] = {
    {-1,-1, 1},
    { 1,-1, 1},
    { 1, 1, 1},
    {-1, 1, 1},
    {-1,-1,-1},
    { 1,-1,-1},
    { 1, 1,-1},
    {-1, 1,-1},
};

这给出了顶点索引(在数组中的位置),在图片中看起来像:

Cube Vertices with Indices

为了绘制一个立方体,我们需要告诉OpenGL在哪些顶点,以及以哪个顺序组成面。让我们来看看这些面:

Cube with face edges

我们将用三角形构建该立方体。三个连续的索引组成一个三角形。对于立方体来说是这样的:

GLuint face_indices[3][] = {
    {0,1,2},{2,3,0},
    {1,5,6},{6,2,1},
    {5,4,7},{7,6,5},
    {4,0,3},{3,7,4},
    {3,2,6},{6,7,2},
    {4,5,0},{1,0,5}
};
你可以通过将OpenGL指向顶点数组来绘制它。
glVertexPointer(3, GL_FLOAT, 0, &vertices[0][0]);

使用顶点数组并发出批量调用。有6 * 2 = 12个三角形,每个三角形由3个顶点组成,这样就得到了一个包含36个索引的列表。

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, &face_indices[0][0]);

谢谢教程,我会去看看(我知道如何显示顶点等,但我并没有真正使用过顶点数组或缓冲区之类的东西)。至于那些索引,我知道它们是一个列表,但我不明白它们代表什么?(我的意思是,假设我们有一个顶点数组和一个三角形,每个三角形点都是顶点数组的索引/当我看到“索引”这个词时,大多数情况下我理解的是这个) - Taigi
顺便说一下,它打印了cdcdcdcd的索引,所以我猜那就是它无法读取的位置... - Taigi
@Taigi:嗯,0xcdcdcdcd对我来说不像是一个有效的指针。我不熟悉FBX SDK,需要花费一些时间(大约半天左右)来了解它。但是得到这个值意味着有些地方出了问题。你现在面临两个问题:作为OpenGL新手,没有牢固的理解其概念,并且面对一个SDK的API(已经很难了),甚至不知道所需的概念。我建议先扎实你的OpenGL知识。按照我提供的教程(所有章节)进行学习,然后再处理FBX文件。 - datenwolf
face_indices 的答案中有一个小错误 - 面 {6,7,2} 应该是 {6,7,3},这样它就与 {3,2,6} 互补了。 - Armen Ablak
我认为他的意思是OP想要导入一个.fbx文件并像ASSIMP文件一样读取其中的所有顶点,他知道如何使用VBO VAO INDICIES,他正在尝试制作一个类来获取.fbx文件中的数据并读取其内容和网格,并显示它。就像Unity或Unreal引擎一样。 - Nfagie Yansaneh
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接