From a202d3c9eaf9bb42e4c4bb73444e32b32098d09c Mon Sep 17 00:00:00 2001 From: root Date: Fri, 5 Sep 2025 17:06:06 +0800 Subject: [PATCH] load fbx --- .gitignore | 2 + .vscode/settings.json | 35 +++++++++++++ build.rs | 1 + cpp_src/fbx_parse.cpp | 57 ++++++++------------- cpp_src/fbx_wrap.cpp | 101 +++++++++++++++++++++++++++++++++++++ cpp_src/include/fbx_wrap.h | 31 ++++++++++++ src/main.rs | 5 +- 7 files changed, 196 insertions(+), 36 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 cpp_src/fbx_wrap.cpp create mode 100644 cpp_src/include/fbx_wrap.h diff --git a/.gitignore b/.gitignore index ea8c4bf..5962b70 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +*.o +*.exe \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8f2b8b4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "files.associations": { + "*.dbclient-js": "javascript", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "cwchar": "cpp", + "exception": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iterator": "cpp", + "limits": "cpp", + "map": "cpp", + "new": "cpp", + "stdexcept": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "vector": "cpp", + "xmemory": "cpp", + "xstddef": "cpp", + "xstring": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "iostream": "cpp", + "ostream": "cpp" + }, + "C_Cpp.errorSquiggles": "disabled" +} \ No newline at end of file diff --git a/build.rs b/build.rs index c0f0e09..4a188d6 100644 --- a/build.rs +++ b/build.rs @@ -8,6 +8,7 @@ fn main() { .warnings(false) .include("./cpp_src/include") .file("./cpp_src/fbx_parse.cpp") + .file("./cpp_src/fbx_wrap.cpp") .compile("fbx_parse"); // ------------- println!("cargo:rustc-link-search=native=./cpp_src/lib"); diff --git a/cpp_src/fbx_parse.cpp b/cpp_src/fbx_parse.cpp index 3a08a97..f22a8c4 100644 --- a/cpp_src/fbx_parse.cpp +++ b/cpp_src/fbx_parse.cpp @@ -1,62 +1,49 @@ -#include +// external #include +// buz +#include + using namespace std; + extern "C" { // 定义给Rust调用的接口函数 - void fbx_parse(const char* fbx_path) { - std::printf("%s\n", fbx_path); + void fbx_parse(const char* fbx_path) + { + printf("%s\n", fbx_path); FbxManager* lSdkManager = FbxManager::Create(); if (lSdkManager){ - std::printf("FbxManager created successfully.\n"); + printf("FbxManager created\n"); } else{ - std::printf("FbxManager creation failed.\n"); + printf("FbxManager creation failed.\n"); } FbxScene* lScene = FbxScene::Create(lSdkManager, "myScene"); if (lScene){ - std::printf("FbxScene created successfully.\n"); + printf("FbxScene created\n"); } else{ - std::printf("FbxScene creation failed.\n"); + printf("FbxScene creation failed.\n"); } FbxImporter* lImporter = FbxImporter::Create(lSdkManager, ""); bool s = lImporter->Initialize(fbx_path, -1, lSdkManager->GetIOSettings()); if (s){ - std::printf("FbxImporter initialized successfully.\n"); + printf("FbxImporter initialized\n"); } else{ - std::printf("FbxImporter initialization failed.\n"); + printf("FbxImporter initialization failed.\n"); } lImporter->Import(lScene); lImporter->Destroy(); FbxNode* lRootNode = lScene->GetRootNode(); if (lRootNode) { - std::printf("Root node found. Node name: %s\n", lRootNode->GetName()); - int childCount = lRootNode->GetChildCount(); - std::printf("Number of child nodes: %d\n", childCount); - for (int i = 0; i < childCount; ++i) { - FbxNode* childNode = lRootNode->GetChild(i); - std::printf("Child node %d name: %s\n", i, childNode->GetName()); - } + each_node(lRootNode, 0); } else { - std::printf("No root node found in the scene.\n"); - } - - - if (lRootNode && lRootNode->GetNodeAttribute() && - lRootNode->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh) { - FbxMesh* lMesh = static_cast(lRootNode->GetNodeAttribute()); - int materialCount = lMesh->GetElementMaterialCount(); - std::printf("Number of materials in the mesh: %d\n", materialCount); - for (int i = 0; i < materialCount; ++i) { - FbxSurfaceMaterial* lMaterial = nullptr; - std::printf("Material name: %s\n", lMaterial->GetName()); - // lMesh->GetElementMaterial(0)->eMaterial(i, lMaterial); - // if (lMaterial) { - // std::printf("Material %d name: %s\n", i, lMaterial->GetName()); - // } - } - int controlPointCount = lMesh->GetControlPointsCount(); - std::printf("Number of vertices in the mesh: %d\n", controlPointCount); + printf("No root node found in the scene.\n"); } + } + void load_fbx_mesh_to_db(const char* fbx_path) + { + FbxNode* root = get_fbx_root_node(fbx_path); + + each_node(root, 0); } } diff --git a/cpp_src/fbx_wrap.cpp b/cpp_src/fbx_wrap.cpp new file mode 100644 index 0000000..abec411 --- /dev/null +++ b/cpp_src/fbx_wrap.cpp @@ -0,0 +1,101 @@ +#include "fbx_wrap.h" +#include +#include + +using namespace std; + +int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector& triangles) { + FbxMesh* mesh = static_cast(attr); + // 顶点数据 + // int ctrlPointCount = mesh->GetControlPointsCount(); + // vertices.assign(mesh->GetControlPoints(), mesh->GetControlPoints() + ctrlPointCount); + + // 三角化并提取三角形索引 + FbxGeometryConverter converter(mesh->GetFbxManager()); + if (!converter.Triangulate(mesh, true)) return false; // 强制三角化 + + int polyCount = mesh->GetPolygonCount(); + triangles.reserve(polyCount); + for (int i = 0; i < polyCount; ++i) { + if (mesh->GetPolygonSize(i) != 3) continue; // 跳过非三角形(理论上不会存在) + int i0 = mesh->GetPolygonVertex(i, 0); + int i1 = mesh->GetPolygonVertex(i, 1); + int i2 = mesh->GetPolygonVertex(i, 2); + triangles.emplace_back(i0, i1, i2); + } + return true; +} + +FbxNode* get_fbx_root_node(const char* fbx_path) +{ + printf("loading fbx file: %s\n", fbx_path); + FbxManager* lSdkManager = FbxManager::Create(); + if (lSdkManager){ + printf("FbxManager created successfully.\n"); + } else{ + printf("FbxManager creation failed.\n"); + } + FbxScene* lScene = FbxScene::Create(lSdkManager, "myScene"); + if (lScene){ + printf("FbxScene created successfully.\n"); + } else{ + printf("FbxScene creation failed.\n"); + } + FbxImporter* lImporter = FbxImporter::Create(lSdkManager, ""); + bool s = lImporter->Initialize(fbx_path, -1, lSdkManager->GetIOSettings()); + if (s){ + printf("FbxImporter initialized successfully.\n"); + } else{ + printf("FbxImporter initialization failed.\n"); + } + lImporter->Import(lScene); + lImporter->Destroy(); + + return lScene->GetRootNode(); +} + + +void each_node(FbxNode* parent_node, int level) +{ + // info + print_node_info(parent_node, level); + // data + for (int i = 0; i < parent_node->GetNodeAttributeCount(); i++) + { + FbxNodeAttribute* attr = parent_node->GetNodeAttributeByIndex(i); + if (attr && attr->GetAttributeType() == FbxNodeAttribute::eMesh) + { + std::vector triangles; + int count = load_triangles(attr, triangles); + printf("triangles: %ld;", triangles.size()); + std::cout << "(" + << get<0>(triangles[0]) << ", " + << get<1>(triangles[0]) << ", " + << get<2>(triangles[0]) << ")" + << std::endl; + } + + } + + // children + if (parent_node->GetChildCount()) + { + for (int i = 0; i < parent_node->GetChildCount(); i++) + { + FbxNode* child = parent_node->GetChild(i); + each_node(child, level + 1); + } + } +} + +void print_node_info(FbxNode* node, int level) +{ + // 打印一下节点信息 + printf("|"); + for (int i = 0; i < level; i++) + { + printf("-"); + } + printf("> "); + printf("[%ld]: %s\n", node->GetUniqueID(), node->GetNameOnly().Buffer()); +} \ No newline at end of file diff --git a/cpp_src/include/fbx_wrap.h b/cpp_src/include/fbx_wrap.h new file mode 100644 index 0000000..3e58362 --- /dev/null +++ b/cpp_src/include/fbx_wrap.h @@ -0,0 +1,31 @@ +#include +#include + +using namespace std; + +using Triangle = std::tuple; + +struct Context { + +}; + +/** + * 递归遍历FBX节点树结构 + * @param parent_node 起始父节点,从此节点开始向下遍历(若为nullptr则函数不执行任何操作) + * @param level 当前节点层级(用于缩进或层级标识,建议初始调用时传入0) + * @note 函数内部会递归访问parent_node的所有直接子节点和间接子节点 + * @warning 若输入的parent_node无效(如野指针)可能导致程序崩溃 + */ +void each_node(FbxNode* parent_node, int level); +/** + * 打印FBX节点的基本信息(含层级缩进) + * @param node 待打印信息的节点指针(nullptr时输出警告日志) + * @param level 节点层级(用于控制打印缩进,每级建议缩进4空格) + * @details 输出内容包含:节点名称、类型、子节点数量、层级深度 + * @example 层级2的节点打印格式:" |-- NodeName (Type: Mesh, Children: 3)" + */ +void print_node_info(FbxNode* node, int level); + +FbxNode* get_fbx_root_node(const char* fbx_path); + +int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector& triangles); diff --git a/src/main.rs b/src/main.rs index 2ea4ecc..cc043b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,12 +5,15 @@ fn main() { unsafe extern "C" { pub unsafe fn fbx_parse(name_in: *const u8); + pub unsafe fn load_fbx_mesh_to_db(path: *const u8); } fn convert_fbx_to_3dtiles(fbx_path: &str) { unsafe { - fbx_parse(fbx_path.as_ptr() as *const u8); + // fbx_parse(fbx_path.as_ptr() as *const u8); + // 1. load to disk + load_fbx_mesh_to_db(fbx_path.as_ptr() as *const u8); } // unsafe {