Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Wczytanie Modelu *.fbx

Ostatnio zmodyfikowano dzisiaj: 13 min
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
Wczytanie Modelu *.fbx
» 2025-06-30 13:39:19
Witam. Chciałbym wczytać animowany model zapisany w formacie *.fbx.
Mam kod na pobranie wierzchołków, ale nie jestem pewien czy zapisywanie wszystkich wierzchołków dla danej klatki będzie dobrym rozwiązaniem. Co o tym sądzicie ?

C/C++
#include <fbxsdk.h>
#include <iostream>

void LoadFBX( const char * filename ) {
   
// 1. Inicjalizacja menadżera FBX
   
FbxManager * manager = FbxManager::Create();
   
FbxIOSettings * ios = FbxIOSettings::Create( manager, IOSROOT );
   
manager->SetIOSettings( ios );
   
   
// 2. Importer
   
FbxImporter * importer = FbxImporter::Create( manager, "" );
   
if( !importer->Initialize( filename, - 1, manager->GetIOSettings() ) ) {
       
std::cerr << "Nie udało się wczytać pliku FBX: " << importer->GetStatus().GetErrorString() << std::endl;
       
return;
   
}
   
   
// 3. Załaduj scenę
   
FbxScene * scene = FbxScene::Create( manager, "scene" );
   
importer->Import( scene );
   
importer->Destroy();
   
   
// 4. Odwiedź węzły sceny
   
FbxNode * root = scene->GetRootNode();
   
if( root ) {
       
for( int i = 0; i < root->GetChildCount(); i++ ) {
           
FbxNode * child = root->GetChild( i );
           
if( child->GetNodeAttribute() &&
           
child->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh ) {
               
FbxMesh * mesh =( FbxMesh * ) child->GetNodeAttribute();
               
               
std::cout << "Mesh: " << child->GetName() << std::endl;
               
               
int vertexCount = mesh->GetControlPointsCount();
               
FbxVector4 * vertices = mesh->GetControlPoints();
               
for( int v = 0; v < vertexCount; v++ ) {
                   
std::cout << "Vertex[" << v << "] = ("
                   
<< vertices[ v ][ 0 ] << ", "
                   
<< vertices[ v ][ 1 ] << ", "
                   
<< vertices[ v ][ 2 ] << ")" << std::endl;
               
}
            }
        }
    }
   
   
// 5. Zwolnij pamięć
   
manager->Destroy();
}
P-182621
DejaVu
» 2025-06-30 21:56:09
Poczytaj jak to się robi poprawnie, jeżeli nie wiesz jak zrobić animacje. W końcu i tak większość modeli z animacjami prawdopodobnie będziesz miał z Internetu.
P-182626
tBane
Temat założony przez niniejszego użytkownika
» 2025-07-01 10:06:59
Tak, z assetstory od Unity bo tam jest wiele modeli. Tylko większość jest w formacie FBX. Udało mi się załadować wierzchołki, uv i normalne. Ale jak wczytać animację to nie mam pojęcia. Wiem, że można pobierać współrzędne wierzchołków z polygonów po transformacji kości. Ale czy to optymalne rozwiązanie ? Wszystko renderuje przez GLFW więc innej opcji nie widzę ..

load FBX
C/C++
void loadFBX() {
   
   
meshes.clear();
   
   
FbxManager * manager = FbxManager::Create();
   
FbxIOSettings * ios = FbxIOSettings::Create( manager, IOSROOT );
   
manager->SetIOSettings( ios );
   
   
FbxImporter * importer = FbxImporter::Create( manager, "" );
   
if( !importer->Initialize( "mdl\\knight.FBX", - 1, manager->GetIOSettings() ) ) {
       
std::cerr << "Błąd: nie udało się wczytać modelu." << std::endl;
       
return;
   
}
   
   
FbxScene * scene = FbxScene::Create( manager, "myScene" );
   
importer->Import( scene );
   
importer->Destroy();
   
   
FbxNode * root = scene->GetRootNode();
   
if( !root ) return;
   
   
FbxSystemUnit sys = scene->GetGlobalSettings().GetSystemUnit();
   
std::cout << "Scene unit scale: " << sys.GetScaleFactor() << std::endl;
   
double scaleFactor = sys.GetScaleFactor(); // np. 1.0 = metry, 100.0 = centymetry
   
   
std::function < void( FbxNode * ) > traverse =[ & ]( FbxNode * node ) {
       
FbxMesh * mesh = node->GetMesh();
       
if( mesh ) {
           
Mesh m;
           
           
const int polygonCount = mesh->GetPolygonCount();
           
FbxVector4 * controlPoints = mesh->GetControlPoints();
           
FbxGeometryElementUV * uvElement = mesh->GetElementUV();
           
FbxGeometryElementNormal * normalElement = mesh->GetElementNormal();
           
           
for( int polyIndex = 0; polyIndex < polygonCount; ++polyIndex ) {
               
for( int vert = 0; vert < 3; ++vert ) {
                   
int ctrlIndex = mesh->GetPolygonVertex( polyIndex, vert );
                   
                   
// --- V ---
                   
FbxVector4 v = controlPoints[ ctrlIndex ];
                   
                   
// --- UV ---
                   
FbxVector2 uv( 0, 0 );
                   
bool unmapped = false;
                   
if( uvElement )
                       
 mesh->GetPolygonVertexUV( polyIndex, vert, uvElement->GetName(), uv, unmapped );
                   
                   
// --- Normal ---
                   
FbxVector4 n( 0, 1, 0 );
                   
if( normalElement ) {
                       
int idx = polyIndex * 3 + vert;
                       
if( normalElement->GetReferenceMode() == FbxGeometryElement::eDirect )
                           
 n = normalElement->GetDirectArray().GetAt( idx );
                       
else if( normalElement->GetReferenceMode() == FbxGeometryElement::eIndexToDirect ) {
                           
int nidx = normalElement->GetIndexArray().GetAt( idx );
                           
n = normalElement->GetDirectArray().GetAt( nidx );
                       
}
                    }
                   
                   
                   
                   
vertice vv;
                   
const float globalFix = 0.1f; // zmniejsz 100×
                   
double sceneScale = scene->GetGlobalSettings().GetSystemUnit().GetScaleFactor(); // np. 2.54
                   
float scaleFactor = 1.0f / static_cast < float >( sceneScale );
                   
                   
vv.x = float( v[ 0 ] ) * scaleFactor * globalFix;
                   
vv.y = float( v[ 2 ] ) * scaleFactor * globalFix;
                   
vv.z = - float( v[ 1 ] ) * scaleFactor * globalFix;
                   
                   
vv.u = float( uv[ 0 ] );
                   
vv.v = float( uv[ 1 ] );
                   
                   
vv.nx = float( n[ 0 ] );
                   
vv.ny = float( n[ 2 ] );
                   
vv.nz = - float( n[ 1 ] );
                   
                   
m.vertices.push_back( vv );
               
}
            }
           
           
m.material = getMaterial( L"DemoKnightMaterial" );
           
meshes.push_back( m );
       
}
       
       
// Rekurencja dla dzieci
       
for( int i = 0; i < node->GetChildCount(); ++i )
           
 traverse( node->GetChild( i ) );
       
   
};
   
   
traverse( root );
   
   
// Łączenie wszystkich meshów w jeden bufor
   
std::vector < vertice > buffer_vertices;
   
mesh_draw_ranges.clear();
   
   
int offset = 0;
   
for( const auto & mesh: meshes ) {
       
mesh_draw_ranges.emplace_back( offset, mesh.vertices.size() );
       
buffer_vertices.insert( buffer_vertices.end(), mesh.vertices.begin(), mesh.vertices.end() );
       
offset += mesh.vertices.size();
   
}
   
   
// VAO i VBO
   
glGenVertexArrays( 1, & VAO );
   
glGenBuffers( 1, & VBO );
   
   
glBindVertexArray( VAO );
   
glBindBuffer( GL_ARRAY_BUFFER, VBO );
   
glBufferData( GL_ARRAY_BUFFER, buffer_vertices.size() * sizeof( vertice ), buffer_vertices.data(), GL_STATIC_DRAW );
   
   
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( vertice ),( void * ) offsetof( vertice, x ) );
   
glEnableVertexAttribArray( 0 );
   
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, sizeof( vertice ),( void * ) offsetof( vertice, u ) );
   
glEnableVertexAttribArray( 1 );
   
glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof( vertice ),( void * ) offsetof( vertice, nx ) );
   
glEnableVertexAttribArray( 2 );
   
   
glBindVertexArray( 0 );
}

funckja renderująca w GLFW
C/C++
void draw() {
   
   
Program * program = getProgram( L"advanced program" );
   
   
glBindVertexArray( VAO );
   
   
for( int i = 0; i < meshes.size(); ++i ) {
       
       
       
glUseProgram( program->shader_program );
       
       
glActiveTexture( GL_TEXTURE0 );
       
       
( meshes[ i ].material != nullptr ) ? glBindTexture( GL_TEXTURE_2D, meshes[ i ].material->texture->id )
            :
glBindTexture( GL_TEXTURE_2D, 0 );
       
       
glUniform1i( glGetUniformLocation( program->shader_program, "texture1" ), 0 );
       
glUniform3f( glGetUniformLocation( program->shader_program, "fogColor" ), 0.25f, 0.25f, 0.25f );
       
glUniform1f( glGetUniformLocation( program->shader_program, "fogStart" ), 1.0f );
       
glUniform1f( glGetUniformLocation( program->shader_program, "fogEnd" ), 200.0f );
       
       
// send metrices
       
glm::mat4 view = cam->GetViewMatrix();
       
glm::mat4 projection = glm::perspective( glm::radians( 45.0f ), 800.0f / 600.0f, 0.1f, 400.0f );
       
glm::mat4 model = glm::mat4( 1.0f );
       
       
model = glm::translate( model, transform.position );
       
model = glm::rotate( model, glm::radians( transform.rotation.x ), glm::vec3( 1.0f, 0.0f, 0.0f ) );
       
model = glm::rotate( model, glm::radians( transform.rotation.y ), glm::vec3( 0.0f, 1.0f, 0.0f ) );
       
model = glm::rotate( model, glm::radians( transform.rotation.z ), glm::vec3( 0.0f, 0.0f, 1.0f ) );
       
model = glm::scale( model, transform.scale );
       
       
glUniformMatrix4fv( glGetUniformLocation( program->shader_program, "projection" ), 1, GL_FALSE, & projection[ 0 ][ 0 ] );
       
glUniformMatrix4fv( glGetUniformLocation( program->shader_program, "view" ), 1, GL_FALSE, & view[ 0 ][ 0 ] );
       
glUniformMatrix4fv( glGetUniformLocation( program->shader_program, "model" ), 1, GL_FALSE, & model[ 0 ][ 0 ] );
       
       
glm::vec3 lightPos = glm::vec3( - 10, 10, 0 );
       
glm::vec3 lightColor = glm::vec3( 1.0f, 1.0f, 1.0f );
       
static float lightPower = 0.1f;
       
//lightPower += 0.00005f;  
       
static float lightRange = 10.0f;
       
//lightRange += 0.0001f;
       
       
       
        // Pozycje światła i kamery
       
glUniform3f( glGetUniformLocation( program->shader_program, "LightPosition" ), lightPos.x, lightPos.y, lightPos.z );
       
glUniform3fv( glGetUniformLocation( program->shader_program, "LightColor" ), 1, & lightColor[ 0 ] );
       
glUniform1f( glGetUniformLocation( program->shader_program, "LightPower" ), lightPower );
       
glUniform1f( glGetUniformLocation( program->shader_program, "LightRange" ), lightRange );
       
       
glUniform3fv( glGetUniformLocation( program->shader_program, "Ka" ), 1, & meshes[ i ].material->Ka[ 0 ] );
       
glUniform3fv( glGetUniformLocation( program->shader_program, "Ks" ), 1, & meshes[ i ].material->Ks[ 0 ] );
       
//glUniform3fv(glGetUniformLocation(program->shader_program, "Ke"), 1, &meshes[i].material->Ks[0]);
       
       
auto[ offset, count ] = mesh_draw_ranges[ i ];
       
glDrawArrays( GL_TRIANGLES, offset, count );
       
offset += meshes[ i ].vertices.size();
   
}
   
   
glBindVertexArray( 0 );
}
P-182627
DejaVu
» 2025-07-01 10:17:07
Nie szukaj optymalnego rozwiązania tylko rozwiązania które działa. Najpierw musisz nauczyć się obsługiwać to co już jest powszechnie znane/ustandaryzowane zanim zaczniesz robić jakiekolwiek 'optymalizacje'.
P-182628
tBane
Temat założony przez niniejszego użytkownika
» 2025-07-01 10:21:52
No dobra, w końcu mam ponad 3500 FPS, więc zbyt wiele nie stracę :P odezwę się jak już coś napiszę :-)
P-182629
« 1 »
  Strona 1 z 1