save mesh info

This commit is contained in:
dqn 2025-09-09 18:57:37 +08:00
parent cd6038ea13
commit 691109e12a
9 changed files with 150 additions and 50 deletions

View File

@ -7,9 +7,10 @@ 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");

View File

@ -1,7 +1,7 @@
#include <db_ops.h>
#include <string>
#include <cstring>
#include <tools.h>
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_msgsqlite3_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;
}

View File

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

View File

@ -1,29 +1,31 @@
#include "fbx_wrap.h"
#include <fbx_wrap.h>
#include <stdio.h>
#include <iostream>
#include <db_ops.h>
#include <tools.h>
using namespace std;
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<Triangle>& triangles) {
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<V3>& indices, std::vector<V3>& triangles) {
if (!attr || attr->GetAttributeType() != FbxNodeAttribute::eMesh) return false;
FbxMesh* mesh = static_cast<FbxMesh*>(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<int> polyIndices;
for (int j = 0; j < vertexCount; ++j) {
polyIndices.push_back(mesh->GetPolygonVertex(i, j));
}
return true;
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 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<Triangle> triangles;
int count = load_triangles(attr, triangles);
printf("triangles: %ld\n", triangles.size());
std::vector<V3> vertices;
std::vector<V3> 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());
}
}

View File

@ -1,6 +1,35 @@
#include <sqlite3.h>
#include <tools.h>
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);
/**
* @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_OKSQLite错误码(<0)
* @note 1. ctx/db非NULLname/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);

View File

@ -1,11 +1,8 @@
#include <fbxsdk.h>
#include <vector>
#include <tools.h>
#include <tuple>
using namespace std;
using Triangle = std::tuple<int, int, int>;
using V3 = std::tuple<int, int, int>;
/**
* FBX节点树结构
@ -14,7 +11,7 @@ using Triangle = std::tuple<int, int, int>;
* @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 -1attr为空或非Mesh类型
* @note
* @brief FBX网格属性加载顶点数据和三角化索引
* @param[in] attr FBX节点属性FbxMesh类型
* @param[out] vertices Triangle存储3个FbxVector4顶点
* @param[out] triangles Triangle存储3个顶点索引
* @return bool truefalse
* @note
*/
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<Triangle>& triangles);
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<V3>& indices, std::vector<V3>& triangles);

View File

@ -1,5 +1,14 @@
#ifndef _TOOLS_H_
#define _TOOLS_H_
#include <fbxsdk.h>
#include <tuple>
#include <vector>
#include <sqlite3.h>
#include <string>
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);

11
cpp_src/tools.cpp Normal file
View File

@ -0,0 +1,11 @@
#include <tools.h>
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;
}

View File

@ -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)]