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

Wczytanie Modelu *.fbx

Ostatnio zmodyfikowano 2025-07-03 14:04
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;
   
   
   
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 );
                       
}
                    }
                   
                   
FbxDouble3 localScale = node->LclScaling.Get();
                   
double toMeters = FbxSystemUnit::m.GetConversionFactorFrom( scene->GetGlobalSettings().GetSystemUnit() );
                   
                   
vertice vv;
                   
vv.x = float( v[ 0 ] * localScale[ 0 ] * toMeters );
                   
vv.y = float( v[ 2 ] * localScale[ 2 ] * toMeters );
                   
vv.z = - float( v[ 1 ] * localScale[ 1 ] * toMeters );
                   
                   
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
tBane
Temat założony przez niniejszego użytkownika
» 2025-07-01 13:42:03
A przepraszam wie ktoś jak pobrać przesunięte wierzchołki z animacji ?

wynik programu:

Znaleziono animacje:
[0] Take 001


przetwarzam [0] animacje ...

Kod ładowania animacji w formacie *.FBX:
C/C++
void loadFBXAnimation( std::wstring path ) {
   
FbxManager * manager = FbxManager::Create();
   
FbxIOSettings * ios = FbxIOSettings::Create( manager, IOSROOT );
   
manager->SetIOSettings( ios );
   
   
FbxImporter * importer = FbxImporter::Create( manager, "" );
   
if( !importer->Initialize( ConvertWideToUtf8( path ).c_str(), - 1, manager->GetIOSettings() ) ) {
       
std::wcout << L"Błąd: nie udało się wczytać animacji: " << path << L"\n";
       
return;
   
}
   
   
FbxScene * scene = FbxScene::Create( manager, "" );
   
importer->Import( scene );
   
importer->Destroy();
   
   
FbxAnimStack * animStack = scene->GetSrcObject < FbxAnimStack >( 0 );
   
if( !animStack ) {
       
std::cout << "Brak animacji\n";
       
return;
   
}
   
   
int animCount = scene->GetSrcObjectCount < FbxAnimStack >();
   
if( animCount == 0 ) {
       
std::cout << "Brak animacji\n";
       
return;
   
}
   
   
std::cout << "Znaleziono animacje:\n";
   
for( int i = 0; i < animCount; i++ ) {
       
FbxAnimStack * animStack = scene->GetSrcObject < FbxAnimStack >( i );
       
if( animStack ) {
           
std::cout << "[" << i << "] " << animStack->GetName() << "\n";
       
}
    }
   
   
std::cout << "\n\n";
   
   
for( int i = 0; i < animCount; i++ ) {
       
       
std::cout << "przetwarzam [" << i << "] animacje ... \n";
       
       
scene->SetCurrentAnimationStack( animStack );
       
       
// ...
       
   
}
}
P-182631
tBane
Temat założony przez niniejszego użytkownika
» 2025-07-01 17:55:01
No więc utknąłem. Mam animacje zapisane osobno tzn. w innych plikach *.fbx i teraz gdy wczytuje animacje to nadpisuje scenę modelu i program wypisuje mi, że mesh jest pusty. ChatGPT bezradny - ja zresztą  też :-/

https://github.com/tBane1995/Model3D-Loader


mdl/knight.FBX    // model
anm/WK_heavy_infantry_04_charge.FBX    // animacja
anm/WK_heavy_infantry_05_combat_idle.FBX    // animacja

C/C++
void loadFBX( std::wstring pathfile ) {
   
   
meshes.clear();
   
   
FbxImporter * importer = FbxImporter::Create( manager, "" );
   
if( !importer->Initialize( ConvertWideToUtf8( pathfile ).c_str(), - 1, manager->GetIOSettings() ) ) {
       
std::wcout << L"Błąd: nie udało się wczytać animacji: " << pathfile << L"\n";
       
return;
   
}
   
   
scene = FbxScene::Create( manager, "myScene" );
   
   
importer->Import( scene );
   
importer->Destroy();
   
   
FbxNode * root = scene->GetRootNode();
   
if( !root ) return;
   
   
// load the Meshes
   
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 );
                       
}
                    }
                   
                   
FbxDouble3 localScale = node->LclScaling.Get();
                   
double toMeters = FbxSystemUnit::m.GetConversionFactorFrom( scene->GetGlobalSettings().GetSystemUnit() );
                   
                   
vertice vv;
                   
vv.x = float( v[ 0 ] * localScale[ 0 ] * toMeters );
                   
vv.y = float( v[ 2 ] * localScale[ 2 ] * toMeters );
                   
vv.z = - float( v[ 1 ] * localScale[ 1 ] * toMeters );
                   
                   
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 );
       
}
       
       
for( int i = 0; i < node->GetChildCount(); ++i )
           
 traverse( node->GetChild( i ) );
       
   
};
   
   
traverse( root );
   
   
updateVerticesBuffer();
}

void ProcessNode( FbxNode * pNode, FbxAnimLayer * pAnimLayer, FbxTime time ) {
   
if( !pNode ) return;
   
   
FbxMesh * mesh = pNode->GetMesh();
   
   
if( mesh ) {
       
       
FbxAMatrix globalTransform = pNode->EvaluateGlobalTransform( time );
       
       
int vertexCount = mesh->GetControlPointsCount();
       
FbxVector4 * controlPoints = mesh->GetControlPoints();
       
       
for( int i = 0; i < vertexCount; i++ ) {
           
FbxVector4 localPos = controlPoints[ i ];
           
FbxVector4 worldPos = globalTransform.MultT( localPos );
           
           
std::cout << "vertex[" << i << "] = "
           
<< worldPos[ 0 ] << ", "
           
<< worldPos[ 1 ] << ", "
           
<< worldPos[ 2 ] << "\n";
       
}
    }
   
   
int childCount = pNode->GetChildCount();
   
for( int i = 0; i < childCount; i++ ) {
       
ProcessNode( pNode->GetChild( i ), pAnimLayer, time );
   
}
}

void loadFBXAnimation( std::wstring path ) {
   
   
FbxImporter * importer = FbxImporter::Create( manager, "" );
   
if( !importer->Initialize( ConvertWideToUtf8( path ).c_str(), - 1, manager->GetIOSettings() ) ) {
       
std::wcout << L"Błąd: nie udało się wczytać animacji: " << path << L"\n";
       
return;
   
}
   
   
importer->Import( scene );
   
importer->Destroy();
   
   
FbxAnimStack * animStack = scene->GetSrcObject < FbxAnimStack >( 0 );
   
if( !animStack ) {
       
std::cout << "Brak animacji\n";
       
return;
   
}
   
   
int animCount = scene->GetSrcObjectCount < FbxAnimStack >();
   
if( animCount == 0 ) {
       
std::cout << "Brak animacji\n";
       
return;
   
}
   
   
   
for( int i = 0; i < animCount; i++ ) {
       
FbxAnimStack * animStack = scene->GetSrcObject < FbxAnimStack >( i );
       
FbxAnimLayer * animLayer = animStack->GetMember < FbxAnimLayer >( 0 );
       
       
// ...
       
       
std::cout << "load animation no " << i << " : \"" << animStack->GetName() << "\"\n";
       
       
scene->SetCurrentAnimationStack( animStack );
       
       
// show time of animation
       
FbxTakeInfo * takeInfo = scene->GetTakeInfo( animStack->GetName() );
       
std::cout << "anim start: " << takeInfo->mLocalTimeSpan.GetStart().GetSecondDouble() << "s \n";
       
std::cout << "anim stop: " << takeInfo->mLocalTimeSpan.GetStop().GetSecondDouble() << "s \n";
       
       
// ...
       
       
FbxTime currentTime = takeInfo->mLocalTimeSpan.GetStart();
       
FbxTime frameTime;
       
frameTime.SetTime( 0, 0, 0, 1, 0, scene->GetGlobalSettings().GetTimeMode() ); // klatka co 1 frame
       
       
FbxNode * root = scene->GetRootNode();
       
if( !root )
           
 return;
       
       
while( currentTime <= takeInfo->mLocalTimeSpan.GetStop() ) {
           
static int i = 0;
           
std::cout << "frame: " << i++ << "\ttime: " << currentTime.GetSecondDouble() << "s\n";
           
           
ProcessNode( root, animLayer, currentTime );
           
currentTime += frameTime;
       
}
       
    }
}
P-182633
tBane
Temat założony przez niniejszego użytkownika
» 2025-07-02 15:00:33
W animacji szkieletowej mesh jest nullptr stąd próbuję pobrać macierze transformacji i jakoś je zastosować do node'sów. ChatGPT cały czas uparcie twierdzi, by ładować FbxMesh, którego wcale w animacji nie ma ... Więc jest trudno. Nie wiem co dalej. Jak te transformacje użyć. Jak na razie wczytuje animację do nowej sceny animScene i próbuję transformacje przekazać do sceny modelu modelScene.

Utknąłem z kodem w ProcessNode

https://github.com/tBane1995/Model3D-Loader


load animation no 0 : "Take 001"
anim start: 0s
anim stop: 1.2s
frame: 0        time: 0s
Node: RootNode
  Local T: 0, 0, 0
  Local R: 0, -0, 0
  Local S: 1, 1, 1
Node: Bip001
  Local T: -0.114992, 26.9211, -0.732213
  Local R: -82.686, -80.6823, -7.14676
  Local S: 1, 1, 1
Node: Bip001 Pelvis
  Local T: 0, 0, 0
  Local R: -176.341, -88.4104, 90.1054
  Local S: 1, 1, 1
Node: Bip001 Spine
  Local T: 4.43681, -0.0177662, -0.117892
  Local R: -25.7714, 5.23571, 11.7771
  Local S: 1, 1, 1
Node: Bip001 Neck
  Local T: 15.4001, -0.24454, -6.24657e-05
  Local R: 1.59725, 3.04569, 31.7437
  Local S: 1, 1, 1
Node: Bip001 Head
  Local T: 2.78382, 0.587482, 7.15256e-07
  Local R: 14.1978, -3.33051, -35.9205
  Local S: 1, 1, 1
// etc ...

C/C++
#ifndef AnimatedModel3D_hpp
#define AnimatedModel3D_hpp

struct AnimationVertice {
   
Mesh * mesh = nullptr;
   
int vertice_index;
   
float x, y, z;
};

struct Frame {
   
float time;
   
std::vector < AnimationVertice > move_vertices;
};

class AnimatedModel3D {
public:
   
Transform transform;
   
   
std::vector < Mesh > meshes;
   
   
unsigned int VAO = 0;
   
unsigned int VBO = 0;
   
   
std::vector < Frame > frames;
   
unsigned int current_frame;
   
   
FbxManager * manager = nullptr;
   
FbxIOSettings * ios = nullptr;
   
FbxScene * modelScene = nullptr;
   
   
AnimatedModel3D() {
       
meshes.clear();
       
current_frame = 0;
       
       
manager = FbxManager::Create();
       
       
ios = FbxIOSettings::Create( manager, IOSROOT );
       
manager->SetIOSettings( ios );
   
}
   
~AnimatedModel3D() { }
   
   
void setPosition( float x, float y, float z ) {
       
transform.setPosition( glm::vec3( x, y, z ) );
   
}
   
   
void setScale( float x, float y, float z ) {
       
transform.setScale( glm::vec3( x, y, z ) );
   
}
   
   
void updateVerticesBuffer() {
       
// Łączenie wszystkich meshów w jeden bufor
       
std::vector < vertice > buffer_vertices;
       
       
for( const auto & mesh: meshes )
           
 buffer_vertices.insert( buffer_vertices.end(), mesh.vertices.begin(), mesh.vertices.end() );
       
       
       
// 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 );
   
}
   
   
void loadFBX( std::wstring pathfile ) {
       
       
meshes.clear();
       
       
FbxImporter * importer = FbxImporter::Create( manager, "" );
       
if( !importer->Initialize( ConvertWideToUtf8( pathfile ).c_str(), - 1, manager->GetIOSettings() ) ) {
           
std::wcout << L"Błąd: nie udało się wczytać animacji: " << pathfile << L"\n";
           
return;
       
}
       
       
modelScene = FbxScene::Create( manager, "myScene" );
       
       
importer->Import( modelScene );
       
importer->Destroy();
       
       
FbxNode * root = modelScene->GetRootNode();
       
if( !root ) return;
       
       
// load the Meshes
       
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 );
                           
}
                        }
                       
                       
FbxDouble3 localScale = node->LclScaling.Get();
                       
double toMeters = FbxSystemUnit::m.GetConversionFactorFrom( modelScene->GetGlobalSettings().GetSystemUnit() );
                       
                       
vertice vv;
                       
vv.x = float( v[ 0 ] * localScale[ 0 ] * toMeters );
                       
vv.y = float( v[ 2 ] * localScale[ 2 ] * toMeters );
                       
vv.z = - float( v[ 1 ] * localScale[ 1 ] * toMeters );
                       
                       
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 );
           
}
           
           
for( int i = 0; i < node->GetChildCount(); ++i )
               
 traverse( node->GetChild( i ) );
           
       
};
       
       
traverse( root );
       
       
updateVerticesBuffer();
   
}
   
   
void ProcessNode( FbxNode * pNode, FbxAnimLayer * pAnimLayer, FbxTime time ) {
       
if( !pNode ) {
           
return;
       
}
       
       
// mesh is nullptr so make a metrices
       
FbxAnimEvaluator * anim_eval = pNode->GetAnimationEvaluator();
       
       
FbxAMatrix localTransform = anim_eval->GetNodeLocalTransform( pNode, time );
       
       
FbxVector4 t = localTransform.GetT(); // translacja
       
FbxVector4 r = localTransform.GetR(); // rotacja
       
FbxVector4 s = localTransform.GetS(); // skala
       
       
std::cout << "Node: " << pNode->GetName() << "\n";
       
std::cout << "  Local T: " << t[ 0 ] << ", " << t[ 1 ] << ", " << t[ 2 ] << "\n";
       
std::cout << "  Local R: " << r[ 0 ] << ", " << r[ 1 ] << ", " << r[ 2 ] << "\n";
       
std::cout << "  Local S: " << s[ 0 ] << ", " << s[ 1 ] << ", " << s[ 2 ] << "\n";
       
       
//
        // teraz przypisac wierzcholki do modelScene
        // modelScene
        //
       
        /*
        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);
        */
       
        /////////////
       
        ////////////
       
       
int childCount = pNode->GetChildCount();
       
for( int i = 0; i < childCount; i++ ) {
           
ProcessNode( pNode->GetChild( i ), pAnimLayer, time );
       
}
    }
   
   
void loadFBXAnimation( std::wstring pathfile ) {
       
       
FbxImporter * importer = FbxImporter::Create( manager, "" );
       
if( !importer->Initialize( ConvertWideToUtf8( pathfile ).c_str(), - 1, manager->GetIOSettings() ) ) {
           
std::wcout << L"Błąd: nie udało się wczytać animacji: " << pathfile << L"\n";
           
return;
       
}
       
       
FbxScene * animScene = FbxScene::Create( manager, "animation" );
       
       
importer->Import( animScene );
       
importer->Destroy();
       
       
FbxAnimStack * animStack = animScene->GetSrcObject < FbxAnimStack >( 0 );
       
if( !animStack ) {
           
std::cout << "Brak animacji\n";
           
return;
       
}
       
       
int animCount = animScene->GetSrcObjectCount < FbxAnimStack >();
       
if( animCount == 0 ) {
           
std::cout << "Brak animacji\n";
           
return;
       
}
       
       
       
for( int i = 0; i < animCount; i++ ) {
           
FbxAnimStack * animStack = animScene->GetSrcObject < FbxAnimStack >( i );
           
FbxAnimLayer * animLayer = animStack->GetMember < FbxAnimLayer >( 0 );
           
           
// ...
           
           
std::cout << "load animation no " << i << " : \"" << animStack->GetName() << "\"\n";
           
           
animScene->SetCurrentAnimationStack( animStack );
           
           
// show time of animation
           
FbxTakeInfo * takeInfo = animScene->GetTakeInfo( animStack->GetName() );
           
std::cout << "anim start: " << takeInfo->mLocalTimeSpan.GetStart().GetSecondDouble() << "s \n";
           
std::cout << "anim stop: " << takeInfo->mLocalTimeSpan.GetStop().GetSecondDouble() << "s \n";
           
           
// ...
           
           
FbxTime currentTime = takeInfo->mLocalTimeSpan.GetStart();
           
FbxTime frameTime;
           
frameTime.SetTime( 0, 0, 0, 1, 0, animScene->GetGlobalSettings().GetTimeMode() ); // klatka co 1 frame
           
           
FbxNode * root = animScene->GetRootNode();
           
if( !root ) {
               
std::cout << "rootNode is nullptr\n";
               
return;
           
}
           
           
           
while( currentTime <= takeInfo->mLocalTimeSpan.GetStop() ) {
               
static int i = 0;
               
std::cout << "frame: " << i++ << "\ttime: " << currentTime.GetSecondDouble() << "s\n";
               
               
ProcessNode( root, animLayer, currentTime );
               
currentTime += frameTime;
           
}
           
        }
    }
   
   
void animate() {
       
       
//std::cout << "frame: " << current_frame << "\n";
        /*
        if (frames.size() < 3000) {
            Frame f;
            f.time = current_time;
            for (auto& m : meshes) {
                for (int i = 0; i < m.vertices.size(); i++) {
                    AnimationVertice av;
                    av.mesh = &m;
                    av.vertice_index = i;
                    av.x = m.vertices[i].x;
                    av.y = m.vertices[i].y;
                    av.z = m.vertices[i].z + 0.001f;
                    f.move_vertices.push_back(av);
                }
            }
            frames.push_back(f);
        }

        */
       
       
if( frames.empty() || meshes.empty() )
           
 return;
       
       
const Frame & frame = frames[ current_frame ];
       
       
for( auto & mv: frame.move_vertices ) {
           
mv.mesh->vertices[ mv.vertice_index ].x = mv.x;
           
mv.mesh->vertices[ mv.vertice_index ].y = mv.y;
           
mv.mesh->vertices[ mv.vertice_index ].z = mv.z;
       
}
       
       
updateVerticesBuffer();
       
       
current_frame++;
       
if( current_frame >= frames.size() ) {
           
current_frame = 0;
       
}
    }
   
   
   
void update() {
       
animate();
   
}
   
   
void draw() {
       
       
Program * program = getProgram( L"advanced program" );
       
       
glBindVertexArray( VAO );
       
       
unsigned int offset = 0;
       
       
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]);
           
           
glDrawArrays( GL_TRIANGLES, offset, meshes[ i ].vertices.size() );
           
offset += meshes[ i ].vertices.size();
       
}
       
       
glBindVertexArray( 0 );
   
}
}
;


#endif
P-182636
« 1 » 2
  Strona 1 z 2 Następna strona