3d游戏引擎的ContentTools的实现

发布于:2025-06-18 ⋅ 阅读:(19) ⋅ 点赞:(0)

1.FbxImporter.cpp

#include "FbxImporter.h"
#include "Geometry.h"
#include <cmath>


namespace primal::tools 
{

    namespace 
    {
    
        std::mutex fbx_mutex{};
    
    
    }

    bool
        fbx_context::initialize_fbx()
    {
    
        assert(!is_valid);
        _fbx_manager = FbxManager::Create();

        if (!_fbx_manager) 
        {
            return false;
        
        }

        FbxIOSettings* ios{ FbxIOSettings::Create(_fbx_manager,IOSROOT) };
        assert(ios);
        _fbx_manager->SetIOSettings(ios);
        return true;
    
    }

    void
        fbx_context::load_fbx_file(const char* file) 
    {
        assert(_fbx_manager && !_fbx_scene);
        _fbx_scene = FbxScene::Create(_fbx_manager, "Importer Scene");
        if (!_fbx_scene) 
        {
        
            return;
        
        }
        
        FbxImporter* importer{ FbxImporter::Create(_fbx_manager,"Importer") };
        if (!(importer &&
            importer->Initialize(file, -1, _fbx_manager->GetIOSettings()) &&
            importer->Import(_fbx_scene))) {
    
            return;
        
        }

        importer->Destroy();

        //Get scene scale in meters
        _scene_scale = (f32)_fbx_scene->GetGlobalSettings().GetSystemUnit().GetConversionFactorTo(FbxSystemUnit::m);

    
    }
    void
        fbx_context::get_scene(FbxNode* root) 
    {
        assert(is_valid);


        if (!root) 
        {
            root = _fbx_scene->GetRootNode();
            if (!root) return;
        
        
        }
        
        const s32 num_nodes{ root->GetChildCount() };
        for (s32 i{ 0 }; i < num_nodes; ++i) 
        {
            FbxNode* node{ root->GetChild(i) };
            if (!node) continue;

            if (node->GetMesh()) 
            {
                lod_group lod{};
                get_mesh(node, lod.meshes);
                if (lod.meshes.size()) 
                {
                    lod.name = lod.meshes[0].name;
                    _scene->lod_groups.emplace_back(lod);
                
                
                }
                else if(node->GetLodGroup())
                {
                
                    get_lod_group(node);
                
                
                }

                get_scene(node);
            
            
            }
        
        
        
        }

    
    }


    void fbx_context::get_mesh(FbxNode* node, utl::vector<mesh>& meshes)
    {

        assert(node);
        if (FbxMesh * fbx_mesh{ node->GetMesh() }) {

            if (fbx_mesh->RemoveBadPolygons() < 0) return;

            FbxGeometryConverter gc{ _fbx_manager };
            fbx_mesh = static_cast<FbxMesh*>(gc.Triangulate(fbx_mesh, true));

            if (!fbx_mesh || fbx_mesh->RemoveBadPolygons() < 0) return;

            mesh m;
            m.lod_id = (u32)meshes.size();
            m.lod_threshold = -1.f;
            m.name = (node->GetName()[0] != '\0') ? node->GetName() : fbx_mesh->GetName();

            if (get_mesh_data(fbx_mesh, m)) 
            {
                meshes.emplace_back(m);
            
            
            }
        
        }
    
    
    }
    void fbx_context::get_lod_group(FbxNode* node) 
    {
    
        assert(node);
        if (FbxLODGroup * lod_grp{ node->GetLodGroup() }) 
        {
            lod_group lod{};
            lod.name = (node->GetName()[0] != '\0') ? node->GetName() : lod_grp->GetName();
            
            const s32 num_lods{ lod_grp->GetNumThresholds() };
            const s32 num_nodes{ node->GetChildCount() };
            assert(num_lods > 0 && &num_nodes > 0);

            for (s32 i{ 0 }; i < num_nodes; ++i) 
            {
                get_mesh(node->GetChild(i), lod.meshes);
                if (lod.meshes.size() > 1 && lod.meshes.size() <= num_lods + 1 && lod.meshes.back().lod_threshold < 0.f) 
                {
                    FbxDistance threshold;
                    lod_grp->GetThreshold((u32)lod.meshes.size() - 2, threshold);
                    lod.meshes.back().lod_threshold = threshold.value() * _scene_scale;
                
                
                
                }
            
            
            
            }

            if (lod.meshes.size()) _scene->lod_groups.emplace_back(lod);


        
        }
    
    
    }

    bool fbx_context::get_mesh_data(FbxMesh* fbx_mesh, mesh& m) 
    {
        assert(fbx_mesh);

        const s32 num_polys{ fbx_mesh->GetPolygonCount() };
        if (num_polys <= 0) return false;

        //Get vertices
        const s32 num_vertices{ fbx_mesh->GetControlPointsCount() };
        FbxVector4* vertices{ fbx_mesh->GetControlPoints() };
        const s32 num_indices{ fbx_mesh->GetPolygonVertexCount() };
        s32* indices{ fbx_mesh->GetPolygonVertices() };

        assert(num_vertices > 0 && vertices && num_indices > 0 && indices);
        if (!(num_vertices > 0 && vertices && num_indices > 0 && indices)) return false;

        m.raw_indices.resize(num_indices);
        utl::vector<u32> vertex_ref(num_vertices, u32_invalid_id);
        for (s32 i{}; num_indices > 0; ++i) 
        {
        
            const u32 v_idx{ (u32)indices[i] };

            if (vertex_ref[v_idx] != u32_invalid_id) 
            {
                m.raw_indices[i] = vertex_ref[v_idx];
            
            
            }
            else 
            {
                FbxVector4 v = vertices[v_idx] * _scene_scale;
                m.raw_indices[i] = (u32)m.positions.size();
                vertex_ref[v_idx] = m.raw_indices[i];
                m.positions.emplace_back((f32)v[0], (f32)v[1], (f32)v[2]);
            
            
            }
        
        
        }


        assert(m.raw_indices.size() % 3 == 0);


        assert(num_polys > 0);
        FbxLayerElementArrayTemplate<s32>* mtl_indices;
        if (fbx_mesh->GetMaterialIndices(&mtl_indices)) 
        {
            for (s32 i{ 0 }; i < num_polys; ++i) 
            {
            
                const s32 mtl_index{ mtl_indices->GetAt(i) };
                assert(mtl_index >= 0);
                m.material_indices.emplace_back((u32)mtl_index);
                if (std::find(m.material_used.begin(), m.material_used.end(), (u32)mtl_index) == m.material_used.end()) 
                {
                    
                    m.material_used.emplace_back((u32)mtl_index);
                
                
                }
            
            
            
            }
            
        
        
        }
        //Importing normals is On by default
        const bool import_normals{ !_scene_data->settings.calculate_normals };
        //Importing tangents is OFF by default
        const bool import_tangents{ !_scene_data->settings.calculate_tangents };

        if (import_normals) 
        {
        
            FbxArray<FbxVector4> normals;

            if (fbx_mesh->GenerateNormals() && fbx_mesh->GetPolygonVertexNormals(normals) && normals.Size() > 0) 
            {
                    
                const s32 num_normals{ normals.Size() };
                for (s32 i{ 0 }; i < num_normals; ++i) 
                {
                    m.normals.emplace_back((f32)normals[i][0],(f32)normals[i][1],(f32)normals[i][2]);
                    
                
                }
                
            
            
            }
            else 
            {
            
                _scene_data->settings.calculate_normals = true;
            
            
            }

        
        }

        //Import tangents
        if (import_tangents) 
        {
        
            FbxLayerElementArrayTemplate<FbxVector4>* tangents{ nullptr };
            if (fbx_mesh->GenerateTangentsData() &&
                fbx_mesh->GetTangents(&tangents) &&
                tangents && tangents->GetCount() > 0
                ) {

                const s32 num_tangent{ tangents->GetCount() };
                for (s32 i{ 0 }; i < num_tangent; ++i) 
                {
                
                    FbxVector4 t{ tangents->GetAt(i) };
                    m.tangents.emplace_back((f32)t[0], (f32)t[1], (f32)t[2],(u32)t[3]);
                
                
                
                }

            }
            else 
            {
                _scene_data->settings.calculate_tangents = true;
            
            
            
            
            }
        
        }

        //Get Uvs
        FbxStringList uv_names;
        fbx_mesh->GetUVSetNames(uv_names);
        const s32 uv_set_count{ uv_names.GetCount() };

        m.uv_sets.resize(uv_set_count);

        for (s32 i{ 0 }; i < uv_set_count; ++i) 
        {
        
            FbxArray<FbxVector2> uvs;
            if (fbx_mesh->GetPolygonVertexUVs(uv_names.GetStringAt(i), uvs)) 
            {
                
                const s32 num_uvs{ uvs.Size() };
                for (s32 j{ 0 }; j < num_uvs; ++j) 
                {
                
                    m.uv_sets[i].emplace_back((f32)uvs[j][0], (f32)uvs[j][1]);
                
                
                }
            
            
            }
    
        
        
        }

        return true;


    }

    EDITOR_INTERFACE void
        ImportFbx(const char* file, scene_data* data) 
    {
        assert(file && data);
        scene scene{};

        {
        
            std::lock_guard lock{ fbx_mutex };

            fbx_context fbx_context{ file,&scene,data };

            if (fbx_context.is_valid()) 
            {
            
            }
            else 
            {
            
                return;
            
            }
        
        
        }


        process_scene(scene, data->settings);
        pack_data(scene, *data);
        
    
    
    }

}


网站公告

今日签到

点亮在社区的每一天
去签到