This commit is contained in:
dqn 2025-09-09 16:50:02 +08:00
parent 72c0fdc1cb
commit cd6038ea13
9 changed files with 169 additions and 7 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
*.exe
.vscode/
.idea/
*.dump
out/

View File

@ -9,8 +9,10 @@ fn main() {
.include("./cpp_src/include")
.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");
}

118
cpp_src/db_ops.cpp Normal file
View File

@ -0,0 +1,118 @@
#include <db_ops.h>
#include <string>
#include <cstring>
using namespace std;
sqlite3 *create_db(const char *db_path, bool overwrite_file)
{
if (overwrite_file)
{
if (remove(db_path) != 0 && errno != ENOENT)
{
fprintf(stderr, "Failed to remove old DB file: %s\n", strerror(errno));
return NULL;
}
}
sqlite3 *db = NULL;
int result_code = sqlite3_open(db_path, &db);
if (result_code != SQLITE_OK)
{
fprintf(stderr, "Failed to open DB: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return NULL;
}
return db;
}
void create_tables(sqlite3 *db)
{
const char *sql_meshes = R"(
CREATE TABLE IF NOT EXISTS meshes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
vertex_count INTEGER NOT NULL,
index_count INTEGER NOT NULL,
fbx_id TEXT UNIQUE NOT NULL
);
)";
const char *sql_materials = R"(
CREATE TABLE IF NOT EXISTS materials (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
shader_name TEXT,
fbx_id TEXT UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
)";
const char *sql_vertices = R"(
CREATE TABLE IF NOT EXISTS vertices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
mesh_id INTEGER NOT NULL,
position_x REAL NOT NULL,
position_y REAL NOT NULL,
position_z REAL NOT NULL,
normal_x REAL,
normal_y REAL,
normal_z REAL,
uv_u REAL,
uv_v REAL,
FOREIGN KEY(mesh_id) REFERENCES meshes(id) ON DELETE CASCADE
);
)";
const char *sql_indices = R"(
CREATE TABLE IF NOT EXISTS indices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
mesh_id INTEGER NOT NULL,
value INTEGER NOT NULL,
FOREIGN KEY(mesh_id) REFERENCES meshes(id) ON DELETE CASCADE
);
)";
const char *sql_material_props = R"(
CREATE TABLE IF NOT EXISTS material_properties (
id INTEGER PRIMARY KEY AUTOINCREMENT,
material_id INTEGER NOT NULL,
key TEXT NOT NULL,
value TEXT NOT NULL,
type TEXT NOT NULL,
FOREIGN KEY(material_id) REFERENCES materials(id) ON DELETE CASCADE,
UNIQUE(material_id, key)
);
)";
const char *sql[] = {sql_meshes, sql_materials, sql_vertices, sql_indices, sql_material_props};
for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); ++i)
{
printf("开始执行:%s", sql[i]);
// 检查前置条件数据库连接和SQL语句必须有效
if (!db)
{
printf("db 是空的");
// 处理空连接错误如log.Fatalf("db connection is NULL")
return; // 或抛异常终止
}
if (!sql[i] || strlen(sql[i]) == 0)
{
printf("SQL Query 是空的");
// 处理空SQL错误如log.Errorf("sql[%d] is NULL/empty", i)
continue; // 或终止
}
char *err_msg = nullptr;
int ret = sqlite3_exec(db, sql[i], nullptr, nullptr, &err_msg);
printf("db ret: %d, err_msg: %s\n", ret, err_msg);
if (ret != SQLITE_OK)
{
// 必须处理错误记录具体SQL和错误信息
// log.Criticalf("SQL error (i=%d): %s, SQL: %s", i, err_msg ? err_msg : "unknown", sql[i]);
sqlite3_free(err_msg); // 释放错误信息
return; // 或根据场景决定是否继续
}
// 成功执行无需释放err_msgsqlite3_exec成功时err_msg为NULL
}
}

View File

@ -2,6 +2,7 @@
#include <stdio.h>
// buz
#include <fbx_wrap.h>
#include <db_ops.h>
using namespace std;
@ -40,8 +41,18 @@ extern "C" {
}
}
void load_fbx_mesh_to_db(const FttContext* ctx)
void load_fbx_mesh_to_db(FttContext* ctx)
{
// 按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;
// init db tables
create_tables(ctx->db);
FbxNode* root = get_fbx_root_node(ctx->fbx_file);
each_node(ctx, root, 0);
}

View File

@ -69,6 +69,8 @@ void each_node(const FttContext* ctx, FbxNode* parent_node, int level)
int count = load_triangles(attr, triangles);
printf("triangles: %ld\n", triangles.size());
// save data to database
sqlite3* db = ctx->db;
// todo save mesh into db
}
}

6
cpp_src/include/db_ops.h Normal file
View File

@ -0,0 +1,6 @@
#include <sqlite3.h>
sqlite3* create_db(const char* db_path, bool overwrite_file);
void create_tables(sqlite3* db);

View File

@ -23,7 +23,20 @@ void each_node(const FttContext* ctx, FbxNode* parent_node, int level);
* @example 2" |-- NodeName (Type: Mesh, Children: 3)"
*/
void print_node_info(FbxNode* node, int level);
/**
* FBX文件加载并返回根节点
* @param fbx_path FBX文件路径
* @return FbxNode* nullptr
* @note FBX SDK环境并自动释放资源
* @warning
*/
FbxNode* get_fbx_root_node(const char* fbx_path);
/**
* FBX属性提取三角形数据并填充到向量
* @param attr FBX节点属性指针Mesh类型Mesh类型返回0
* @param triangles
* @return int -1attr为空或非Mesh类型
* @note
*/
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<Triangle>& triangles);

View File

@ -1,5 +1,12 @@
#include <sqlite3.h>
typedef struct {
char* fbx_file;
char* out_dir;
sqlite3* db;
} FttContext;
void create_tables(sqlite3* db);

View File

@ -1,7 +1,8 @@
use std::{ffi::CString, os::raw::c_char};
fn main() {
convert_fbx_to_3dtiles("/root/data/绿科-三维视图-{三维}111.fbx", "/root/data/out");
convert_fbx_to_3dtiles("/root/data/绿科-三维视图-{三维}111.fbx",
"/root/data/out/lk");
}
#[repr(C)]