diff --git a/build.rs b/build.rs index eef26d4..f037b2a 100644 --- a/build.rs +++ b/build.rs @@ -7,11 +7,12 @@ fn main() { // .flag("-std=c++11") .warnings(false) .include("./cpp_src/include") + .file("./cpp_src/tools.cpp") + .file("./cpp_src/db_ops.cpp") .file("./cpp_src/fbx_parse.cpp") .file("./cpp_src/fbx_wrap.cpp") - .file("./cpp_src/db_ops.cpp") .compile("fbx_parse"); - // ------------- + // ------------- println!("cargo:rustc-link-search=native=./cpp_src/lib"); println!("cargo:rustc-link-lib=fbxsdk"); println!("cargo:rustc-link-lib=sqlite3"); diff --git a/cpp_src/db_ops.cpp b/cpp_src/db_ops.cpp index fb8a7da..1a01092 100644 --- a/cpp_src/db_ops.cpp +++ b/cpp_src/db_ops.cpp @@ -1,7 +1,7 @@ #include #include #include - +#include using namespace std; sqlite3 *create_db(const char *db_path, bool overwrite_file) @@ -19,7 +19,7 @@ sqlite3 *create_db(const char *db_path, bool overwrite_file) int result_code = sqlite3_open(db_path, &db); if (result_code != SQLITE_OK) { - fprintf(stderr, "Failed to open DB: %s\n", sqlite3_errmsg(db)); + fprintf(stderr, "Failed to open DB: %s[%d]\n", sqlite3_errmsg(db), result_code); sqlite3_close(db); return NULL; } @@ -116,3 +116,38 @@ void create_tables(sqlite3 *db) // 成功执行无需释放err_msg(sqlite3_exec成功时err_msg为NULL) } } + + +// 函数定义 +int save_mesh_to_table(FttContext* ctx, + sqlite3* db, + uint id, + const std::string& name, + int vertex_count, int index_count, + const std::string& fbx_id) +{ + + if (!db || name.empty() || fbx_id.empty()) return -1; + + sqlite3_stmt* stmt = nullptr; + const char* sql = "INSERT OR IGNORE INTO meshes (id, name, vertex_count, index_count, fbx_id) VALUES (?, ?, ?, ?, ?);"; + int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); + if (rc != SQLITE_OK) { + fprintf(stderr, "SQL prepare failed: %s\n", sqlite3_errmsg(db)); + return rc; + } + + sqlite3_bind_int64(stmt, 1, id); + sqlite3_bind_text(stmt, 2, name.c_str(), -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 3, vertex_count); + sqlite3_bind_int(stmt, 4, index_count); + sqlite3_bind_text(stmt, 5, fbx_id.c_str(), -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE && rc != SQLITE_CONSTRAINT) { + fprintf(stderr, "SQL step failed: %s\n", sqlite3_errmsg(db)); + } + + sqlite3_finalize(stmt); + return rc == SQLITE_DONE ? 0 : -1; +} \ No newline at end of file diff --git a/cpp_src/fbx_parse.cpp b/cpp_src/fbx_parse.cpp index baed2b8..687f873 100644 --- a/cpp_src/fbx_parse.cpp +++ b/cpp_src/fbx_parse.cpp @@ -8,7 +8,7 @@ using namespace std; extern "C" { // 定义给Rust调用的接口函数 - void fbx_parse(const FttContext* ctx) + void fbx_parse(FttContext* ctx) { printf("%s\n", ctx->fbx_file); FbxManager* lSdkManager = FbxManager::Create(); @@ -41,19 +41,23 @@ extern "C" { } } - void load_fbx_mesh_to_db(FttContext* ctx) + void load_fbx_mesh_to_db( FttContext* ctx) { + // get mutable data + auto temp = ctx_from_const(ctx); + FttContext* mut_ctx = &temp; // 按fbx名称生成 ${ctx.out_dir}/sqlite3.db // 初始化db赋值到ctx.db sqlite3* db = create_db((std::string(ctx->out_dir) + "/db.sqlite3").c_str(), true); - printf("db---> %x\n", db); - ctx->db = db; + if (db == NULL) { + return; + } + mut_ctx->db = db; // init db tables - create_tables(ctx->db); - + create_tables(mut_ctx->db); FbxNode* root = get_fbx_root_node(ctx->fbx_file); - each_node(ctx, root, 0); + each_node(mut_ctx, root, 0); } } diff --git a/cpp_src/fbx_wrap.cpp b/cpp_src/fbx_wrap.cpp index 91cae15..c7aaf64 100644 --- a/cpp_src/fbx_wrap.cpp +++ b/cpp_src/fbx_wrap.cpp @@ -1,29 +1,31 @@ -#include "fbx_wrap.h" +#include #include #include +#include +#include using namespace std; -int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector& triangles) { +int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector& indices, std::vector& triangles) { + if (!attr || attr->GetAttributeType() != FbxNodeAttribute::eMesh) return false; 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); + int vertexCount = mesh->GetPolygonSize(i); + std::vector polyIndices; + for (int j = 0; j < vertexCount; ++j) { + polyIndices.push_back(mesh->GetPolygonVertex(i, j)); + } + for (int j = 2; j < vertexCount; ++j) { + indices.push_back({polyIndices[0], polyIndices[j-1], polyIndices[j]}); + for (int k : {0, j-1, j}) { + FbxVector4 pos = mesh->GetControlPointAt(polyIndices[k]); + triangles.push_back({(float)pos[0], (float)pos[1], (float)pos[2]}); + } + } } - return true; + return 0; } FbxNode* get_fbx_root_node(const char* fbx_path) @@ -55,7 +57,7 @@ FbxNode* get_fbx_root_node(const char* fbx_path) } -void each_node(const FttContext* ctx, FbxNode* parent_node, int level) +void each_node(FttContext* ctx, FbxNode* parent_node, int level) { // info print_node_info(parent_node, level); @@ -65,12 +67,20 @@ void each_node(const FttContext* ctx, FbxNode* parent_node, int level) FbxNodeAttribute* attr = parent_node->GetNodeAttributeByIndex(i); if (attr && attr->GetAttributeType() == FbxNodeAttribute::eMesh) { - std::vector triangles; - int count = load_triangles(attr, triangles); - printf("triangles: %ld\n", triangles.size()); + std::vector vertices; + std::vector triangles; + int count = load_triangles(attr, vertices, triangles); + uint id = attr->GetUniqueID(); + printf("[%ld]triangles: %ld\n", id, triangles.size()); // save data to database sqlite3* db = ctx->db; // todo save mesh into db + + save_mesh_to_table(ctx, ctx->db, + id, + attr->GetName(), + vertices.size(), triangles.size(), + parent_node->GetNameOnly().Buffer()); } } diff --git a/cpp_src/include/db_ops.h b/cpp_src/include/db_ops.h index cb99852..3a8f7b8 100644 --- a/cpp_src/include/db_ops.h +++ b/cpp_src/include/db_ops.h @@ -1,6 +1,35 @@ -#include - - +#include +using namespace std; +/** + * @brief 创建并打开SQLite数据库连接 + * @param db_path 数据库文件路径 + * @param overwrite_file 若为true则删除已有文件后创建新数据库 + * @return 成功返回sqlite3句柄,失败返回NULL + */ sqlite3* create_db(const char* db_path, bool overwrite_file); -void create_tables(sqlite3* db); \ No newline at end of file +/** + * @brief 在指定数据库中创建必要表结构 + * @param db 已打开的SQLite数据库句柄 + * @note 需确保db参数有效且已成功打开 + */ +void create_tables(sqlite3* db); + + +/////////////////////////// +//////// 数据保存 ///////// +/////////////////////////// + +/** + * @brief 将网格数据元信息保存到数据库表 + * @param ctx FTT上下文句柄,包含日志/错误处理等公共资源 + * @param db 已打开的SQLite数据库连接 + * @param name 网格名称(唯一标识) + * @param vertex_count 顶点数量 + * @param index_count 索引数量 + * @param fbx_id 关联的FBX文件ID + * @return 成功返回SQLITE_OK,失败返回SQLite错误码(<0) + * @note 1. 参数需确保有效:ctx/db非NULL,name/fbx_id非空 + * 2. 内部自动处理事务,重复name会触发唯一键冲突 + */ +int save_mesh_to_table(FttContext *ctx, sqlite3 *db, uint id, const std::string &name, int vertex_count, int index_count, const std::string &fbx_id); diff --git a/cpp_src/include/fbx_wrap.h b/cpp_src/include/fbx_wrap.h index fc51a4f..4acec55 100644 --- a/cpp_src/include/fbx_wrap.h +++ b/cpp_src/include/fbx_wrap.h @@ -1,11 +1,8 @@ -#include -#include #include -#include using namespace std; -using Triangle = std::tuple; +using V3 = std::tuple; /** * 递归遍历FBX节点树结构 @@ -14,7 +11,7 @@ using Triangle = std::tuple; * @note 函数内部会递归访问parent_node的所有直接子节点和间接子节点 * @warning 若输入的parent_node无效(如野指针)可能导致程序崩溃 */ -void each_node(const FttContext* ctx, FbxNode* parent_node, int level); +void each_node(FttContext* ctx, FbxNode* parent_node, int level); /** * 打印FBX节点的基本信息(含层级缩进) * @param node 待打印信息的节点指针(nullptr时输出警告日志) @@ -32,11 +29,13 @@ void print_node_info(FbxNode* node, int level); */ FbxNode* get_fbx_root_node(const char* fbx_path); + /** - * 从FBX属性提取三角形数据并填充到向量 - * @param attr FBX节点属性指针(需为Mesh类型,非Mesh类型返回0) - * @param triangles 输出三角形数据的向量引用(会自动清空原有数据) - * @return int 成功提取的三角形数量,失败返回-1(如attr为空或非Mesh类型) - * @note 仅处理三角形网格,四边形等多边形会被自动三角化 + * @brief 从FBX网格属性加载顶点数据和三角化索引 + * @param[in] attr FBX节点属性,需为FbxMesh类型 + * @param[out] vertices 输出顶点坐标数组(每个Triangle存储3个FbxVector4顶点) + * @param[out] triangles 输出三角形索引数组(每个Triangle存储3个顶点索引) + * @return bool 成功返回true,失败返回false + * @note 内部会强制三角化网格,非三角形多边形将被忽略 */ -int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector& triangles); \ No newline at end of file +int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector& indices, std::vector& triangles); diff --git a/cpp_src/include/tools.h b/cpp_src/include/tools.h index 2f88071..08ed26d 100644 --- a/cpp_src/include/tools.h +++ b/cpp_src/include/tools.h @@ -1,5 +1,14 @@ +#ifndef _TOOLS_H_ +#define _TOOLS_H_ + +#include +#include +#include #include +#include + +using namespace std; typedef struct { char* fbx_file; @@ -8,5 +17,7 @@ typedef struct { sqlite3* db; } FttContext; +FttContext ctx_from_const(const FttContext* ctx); + +#endif -void create_tables(sqlite3* db); \ No newline at end of file diff --git a/cpp_src/tools.cpp b/cpp_src/tools.cpp new file mode 100644 index 0000000..35c9706 --- /dev/null +++ b/cpp_src/tools.cpp @@ -0,0 +1,11 @@ +#include + +FttContext ctx_from_const(const FttContext* ctx) { + FttContext mut_ctx; + + mut_ctx.db = ctx->db; + mut_ctx.fbx_file = ctx->fbx_file; + mut_ctx.out_dir = ctx->out_dir; + + return mut_ctx; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index dda9da7..413bb89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ use std::{ffi::CString, os::raw::c_char}; fn main() { - convert_fbx_to_3dtiles("/root/data/绿科-三维视图-{三维}111.fbx", - "/root/data/out/lk"); + convert_fbx_to_3dtiles("/root/src/fbx_to_3dtiles/out/绿科-三维视图-{三维}111.fbx", + "/root/src/fbx_to_3dtiles/out/lk"); } #[repr(C)]