3d游戏引擎的ContentTools的实现

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);

}

}

相关推荐
深海潜水员7 小时前
【Unity】背包系统 + 物品管理窗口 (上)
开发语言·vscode·游戏·unity·c#·游戏引擎
伽蓝_游戏7 小时前
Unity UI的未来之路:从UGUI到UI Toolkit的架构演进与特性剖析(6)
游戏·ui·unity·架构·c#·游戏引擎·.net
德育处主任Pro8 小时前
p5.js 用 beginGeometry () 和 endGeometry () 打造自定义 3D 模型
开发语言·javascript·3d
点云SLAM11 小时前
PyTorch 应用于3D 点云数据处理汇总和点云配准示例演示
人工智能·pytorch·深度学习·3d·点云目标检测·点云补全·点云分类
LetsonH16 小时前
⭐CVPR2025 FreeUV:无真值 3D 人脸纹理重建框架
人工智能·python·深度学习·计算机视觉·3d
YuhsiHu18 小时前
【论文简读】DIV-Loss
人工智能·深度学习·计算机视觉·3d
X_StarX18 小时前
【Unity笔记04】数据持久化
笔记·unity·游戏引擎·数据存储·数据持久化·大学生
AgilityBaby19 小时前
解决「CPU Virtualization Technology 未开启或被占用」弹窗问题
ue5·游戏引擎·无畏契约·cpu 虚拟化技术
AI_RSER1 天前
第一篇:【Python-geemap教程(三)上】3D地形渲染与Landsat NDVI计算
开发语言·python·3d·信息可视化·遥感·gee
-dzk-1 天前
【论文精读】3D Gaussian Splatting for Real-Time Radiance Field Rendering
数码相机·opencv·计算机视觉·3d·三维重建·3dgs·高斯