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 ? #include <fbxsdk.h> #include <iostream>
void LoadFBX( const char * filename ) { FbxManager * manager = FbxManager::Create(); FbxIOSettings * ios = FbxIOSettings::Create( manager, IOSROOT ); manager->SetIOSettings( ios ); 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; } FbxScene * scene = FbxScene::Create( manager, "scene" ); importer->Import( scene ); importer->Destroy(); 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; } } } } manager->Destroy(); }
|
|
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. |
|
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 FBXvoid 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 ); FbxVector4 v = controlPoints[ ctrlIndex ]; FbxVector2 uv( 0, 0 ); bool unmapped = false; if( uvElement ) mesh->GetPolygonVertexUV( polyIndex, vert, uvElement->GetName(), uv, unmapped ); 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 ); 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(); } 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 GLFWvoid 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 ); 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; static float lightRange = 10.0f; 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 ] ); auto[ offset, count ] = mesh_draw_ranges[ i ]; glDrawArrays( GL_TRIANGLES, offset, count ); offset += meshes[ i ].vertices.size(); } glBindVertexArray( 0 ); }
|
|
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'. |
|
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ę :-) |
|
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: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 ); } }
|
|
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
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; 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 ); FbxVector4 v = controlPoints[ ctrlIndex ]; FbxVector2 uv( 0, 0 ); bool unmapped = false; if( uvElement ) mesh->GetPolygonVertexUV( polyIndex, vert, uvElement->GetName(), uv, unmapped ); 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 ); 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() ); 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; } } }
|
|
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 ProcessNodehttps://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 ...
#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() { std::vector < vertice > buffer_vertices; for( const auto & mesh: meshes ) buffer_vertices.insert( buffer_vertices.end(), mesh.vertices.begin(), mesh.vertices.end() ); 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; 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 ); FbxVector4 v = controlPoints[ ctrlIndex ]; FbxVector2 uv( 0, 0 ); bool unmapped = false; if( uvElement ) mesh->GetPolygonVertexUV( polyIndex, vert, uvElement->GetName(), uv, unmapped ); 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; } FbxAnimEvaluator * anim_eval = pNode->GetAnimationEvaluator(); FbxAMatrix localTransform = anim_eval->GetNodeLocalTransform( pNode, time ); FbxVector4 t = localTransform.GetT(); FbxVector4 r = localTransform.GetR(); FbxVector4 s = localTransform.GetS(); 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"; 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 ); 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() ); 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() { 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 ); 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; static float lightRange = 10.0f; 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 ] ); glDrawArrays( GL_TRIANGLES, offset, meshes[ i ].vertices.size() ); offset += meshes[ i ].vertices.size(); } glBindVertexArray( 0 ); } };
#endif
|
|
« 1 » 2 |