保存顶点

This commit is contained in:
dengqn 2025-09-10 10:58:37 +08:00
parent 691109e12a
commit 91b0644129
8 changed files with 143 additions and 72 deletions

View File

@ -51,6 +51,7 @@ void create_tables(sqlite3 *db)
const char *sql_vertices = R"( const char *sql_vertices = R"(
CREATE TABLE IF NOT EXISTS vertices ( CREATE TABLE IF NOT EXISTS vertices (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
vert_id INTEGER NOT NULL,
mesh_id INTEGER NOT NULL, mesh_id INTEGER NOT NULL,
position_x REAL NOT NULL, position_x REAL NOT NULL,
position_y REAL NOT NULL, position_y REAL NOT NULL,
@ -117,22 +118,23 @@ void create_tables(sqlite3 *db)
} }
} }
// 函数定义 // 函数定义
int save_mesh_to_table(FttContext* ctx, int save_mesh_to_table(FttContext *ctx,
sqlite3* db, sqlite3 *db,
uint id, uint id,
const std::string& name, const std::string &name,
int vertex_count, int index_count, int vertex_count, int index_count,
const std::string& fbx_id) const std::string &fbx_id)
{ {
if (!db || name.empty() || fbx_id.empty()) return -1; if (!db || name.empty() || fbx_id.empty())
return -1;
sqlite3_stmt* stmt = nullptr; sqlite3_stmt *stmt = nullptr;
const char* sql = "INSERT OR IGNORE INTO meshes (id, name, vertex_count, index_count, fbx_id) VALUES (?, ?, ?, ?, ?);"; 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); int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK)
{
fprintf(stderr, "SQL prepare failed: %s\n", sqlite3_errmsg(db)); fprintf(stderr, "SQL prepare failed: %s\n", sqlite3_errmsg(db));
return rc; return rc;
} }
@ -144,10 +146,46 @@ int save_mesh_to_table(FttContext* ctx,
sqlite3_bind_text(stmt, 5, fbx_id.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 5, fbx_id.c_str(), -1, SQLITE_STATIC);
rc = sqlite3_step(stmt); rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE && rc != SQLITE_CONSTRAINT) { if (rc != SQLITE_DONE && rc != SQLITE_CONSTRAINT)
{
fprintf(stderr, "SQL step failed: %s\n", sqlite3_errmsg(db)); fprintf(stderr, "SQL step failed: %s\n", sqlite3_errmsg(db));
} }
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return rc == SQLITE_DONE ? 0 : -1; return rc == SQLITE_DONE ? 0 : -1;
} }
int save_mesh_vertices(FttContext *ctx, uint mesh_id, std::vector<V3> vertices) {
if (!ctx->db) return -1;
sqlite3_stmt *stmt = nullptr;
const char *sql = "INSERT OR IGNORE INTO vertices (mesh_id, vert_id, position_x, position_y, position_z) VALUES (?, ?, ?, ?, ?);";
int rc = sqlite3_prepare_v2(ctx->db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL prepare failed: %s\n", sqlite3_errmsg(ctx->db));
return rc;
}
sqlite3_exec(ctx->db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr); // 开启事务
for (int i = 0; i < vertices.size(); i++) {
sqlite3_reset(stmt); // 重置语句
sqlite3_bind_int64(stmt, 1, mesh_id);
sqlite3_bind_int64(stmt, 2, i); // vert_id使用索引
sqlite3_bind_double(stmt, 3, std::get<0>(vertices[i])); // 修正为double类型绑定
sqlite3_bind_double(stmt, 4, std::get<1>(vertices[i]));
sqlite3_bind_double(stmt, 5, std::get<2>(vertices[i]));
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE && rc != SQLITE_CONSTRAINT) {
fprintf(stderr, "SQL step failed at vertex %d: %s\n", i, sqlite3_errmsg(ctx->db));
sqlite3_exec(ctx->db, "ROLLBACK;", nullptr, nullptr, nullptr);
sqlite3_finalize(stmt);
return rc;
}
}
sqlite3_exec(ctx->db, "COMMIT;", nullptr, nullptr, nullptr); // 提交事务
sqlite3_finalize(stmt);
return 0;
}

View File

@ -6,58 +6,72 @@
using namespace std; using namespace std;
extern "C" { extern "C"
{
// 定义给Rust调用的接口函数 // 定义给Rust调用的接口函数
void fbx_parse(FttContext* ctx) void fbx_parse(FttContext *ctx)
{ {
printf("%s\n", ctx->fbx_file); printf("%s\n", ctx->fbx_file);
FbxManager* lSdkManager = FbxManager::Create(); FbxManager *lSdkManager = FbxManager::Create();
if (lSdkManager){ if (lSdkManager)
{
printf("FbxManager created\n"); printf("FbxManager created\n");
} else{ }
else
{
printf("FbxManager creation failed.\n"); printf("FbxManager creation failed.\n");
} }
FbxScene* lScene = FbxScene::Create(lSdkManager, "myScene"); FbxScene *lScene = FbxScene::Create(lSdkManager, "myScene");
if (lScene){ if (lScene)
{
printf("FbxScene created\n"); printf("FbxScene created\n");
} else{ }
else
{
printf("FbxScene creation failed.\n"); printf("FbxScene creation failed.\n");
} }
FbxImporter* lImporter = FbxImporter::Create(lSdkManager, ""); FbxImporter *lImporter = FbxImporter::Create(lSdkManager, "");
bool s = lImporter->Initialize(ctx->fbx_file, -1, lSdkManager->GetIOSettings()); bool s = lImporter->Initialize(ctx->fbx_file, -1, lSdkManager->GetIOSettings());
if (s){ if (s)
{
printf("FbxImporter initialized\n"); printf("FbxImporter initialized\n");
} else{ }
else
{
printf("FbxImporter initialization failed.\n"); printf("FbxImporter initialization failed.\n");
} }
lImporter->Import(lScene); lImporter->Import(lScene);
lImporter->Destroy(); lImporter->Destroy();
FbxNode* lRootNode = lScene->GetRootNode(); FbxNode *lRootNode = lScene->GetRootNode();
if (lRootNode) { if (lRootNode)
{
each_node(ctx, lRootNode, 0); each_node(ctx, lRootNode, 0);
} else { }
else
{
printf("No root node found in the scene.\n"); printf("No root node found in the scene.\n");
} }
} }
void load_fbx_mesh_to_db( FttContext* ctx) void load_fbx_mesh_to_db(FttContext *ctx)
{ {
// get mutable data // get mutable data
auto temp = ctx_from_const(ctx); auto temp = ctx_from_const(ctx);
FttContext* mut_ctx = &temp; FttContext *mut_ctx = &temp;
// 按fbx名称生成 ${ctx.out_dir}/sqlite3.db // 按fbx名称生成 ${ctx.out_dir}/sqlite3.db
// 初始化db赋值到ctx.db // 初始化db赋值到ctx.db
sqlite3* db = create_db((std::string(ctx->out_dir) + "/db.sqlite3").c_str(), true); sqlite3 *db = create_db((std::string(ctx->out_dir) + "/db.sqlite3").c_str(), true);
if (db == NULL) { if (db == NULL)
{
return; return;
} }
mut_ctx->db = db; mut_ctx->db = db;
// init db tables // init db tables
create_tables(mut_ctx->db); create_tables(mut_ctx->db);
FbxNode* root = get_fbx_root_node(ctx->fbx_file); FbxNode *root = get_fbx_root_node(ctx->fbx_file);
each_node(mut_ctx, root, 0); each_node(mut_ctx, root, 0);
} }
} }

View File

@ -6,20 +6,26 @@
using namespace std; using namespace std;
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<V3>& indices, std::vector<V3>& 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); if (!attr || attr->GetAttributeType() != FbxNodeAttribute::eMesh)
return false;
FbxMesh *mesh = static_cast<FbxMesh *>(attr);
int polyCount = mesh->GetPolygonCount(); int polyCount = mesh->GetPolygonCount();
for (int i = 0; i < polyCount; ++i) { for (int i = 0; i < polyCount; ++i)
{
int vertexCount = mesh->GetPolygonSize(i); int vertexCount = mesh->GetPolygonSize(i);
std::vector<int> polyIndices; std::vector<int> polyIndices;
for (int j = 0; j < vertexCount; ++j) { for (int j = 0; j < vertexCount; ++j)
{
polyIndices.push_back(mesh->GetPolygonVertex(i, j)); polyIndices.push_back(mesh->GetPolygonVertex(i, j));
} }
for (int j = 2; j < vertexCount; ++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}) { indices.push_back({polyIndices[0], polyIndices[j - 1], polyIndices[j]});
for (int k : {0, j - 1, j})
{
FbxVector4 pos = mesh->GetControlPointAt(polyIndices[k]); FbxVector4 pos = mesh->GetControlPointAt(polyIndices[k]);
triangles.push_back({(float)pos[0], (float)pos[1], (float)pos[2]}); triangles.push_back({(float)pos[0], (float)pos[1], (float)pos[2]});
} }
@ -28,26 +34,35 @@ int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<V3>& indices, std
return 0; return 0;
} }
FbxNode* get_fbx_root_node(const char* fbx_path) FbxNode *get_fbx_root_node(const char *fbx_path)
{ {
printf("loading fbx file: %s\n", fbx_path); printf("loading fbx file: %s\n", fbx_path);
FbxManager* lSdkManager = FbxManager::Create(); FbxManager *lSdkManager = FbxManager::Create();
if (lSdkManager){ if (lSdkManager)
{
printf("FbxManager created successfully.\n"); printf("FbxManager created successfully.\n");
} else{ }
else
{
printf("FbxManager creation failed.\n"); printf("FbxManager creation failed.\n");
} }
FbxScene* lScene = FbxScene::Create(lSdkManager, "myScene"); FbxScene *lScene = FbxScene::Create(lSdkManager, "myScene");
if (lScene){ if (lScene)
{
printf("FbxScene created successfully.\n"); printf("FbxScene created successfully.\n");
} else{ }
else
{
printf("FbxScene creation failed.\n"); printf("FbxScene creation failed.\n");
} }
FbxImporter* lImporter = FbxImporter::Create(lSdkManager, ""); FbxImporter *lImporter = FbxImporter::Create(lSdkManager, "");
bool s = lImporter->Initialize(fbx_path, -1, lSdkManager->GetIOSettings()); bool s = lImporter->Initialize(fbx_path, -1, lSdkManager->GetIOSettings());
if (s){ if (s)
{
printf("FbxImporter initialized successfully.\n"); printf("FbxImporter initialized successfully.\n");
} else{ }
else
{
printf("FbxImporter initialization failed.\n"); printf("FbxImporter initialization failed.\n");
} }
lImporter->Import(lScene); lImporter->Import(lScene);
@ -56,47 +71,47 @@ FbxNode* get_fbx_root_node(const char* fbx_path)
return lScene->GetRootNode(); return lScene->GetRootNode();
} }
void each_node(FttContext *ctx, FbxNode *parent_node, int level)
void each_node(FttContext* ctx, FbxNode* parent_node, int level)
{ {
// info // info
print_node_info(parent_node, level); print_node_info(parent_node, level);
// data // data
for (int i = 0; i < parent_node->GetNodeAttributeCount(); i++) for (int i = 0; i < parent_node->GetNodeAttributeCount(); i++)
{ {
FbxNodeAttribute* attr = parent_node->GetNodeAttributeByIndex(i); FbxNodeAttribute *attr = parent_node->GetNodeAttributeByIndex(i);
if (attr && attr->GetAttributeType() == FbxNodeAttribute::eMesh) if (attr && attr->GetAttributeType() == FbxNodeAttribute::eMesh)
{ {
std::vector<V3> vertices; std::vector<V3> vertices;
std::vector<V3> triangles; std::vector<V3> triangles;
int count = load_triangles(attr, vertices, triangles); int count = load_triangles(attr, vertices, triangles);
uint id = attr->GetUniqueID(); uint id = attr->GetUniqueID();
printf("[%ld]triangles: %ld\n", id, triangles.size()); printf("[%d]triangles: %ld\n", id, triangles.size());
// save data to database // save data to database
sqlite3* db = ctx->db; sqlite3 *db = ctx->db;
// todo save mesh into db // todo save mesh into db
save_mesh_to_table(ctx, ctx->db, save_mesh_to_table(ctx, ctx->db,
id, id,
attr->GetName(), attr->GetName(),
vertices.size(), triangles.size(), vertices.size(), triangles.size(),
parent_node->GetNameOnly().Buffer()); parent_node->GetNameOnly().Buffer());
save_mesh_vertices(ctx, id, vertices);
} }
} }
// children // children
if (parent_node->GetChildCount()) if (parent_node->GetChildCount())
{ {
for (int i = 0; i < parent_node->GetChildCount(); i++) for (int i = 0; i < parent_node->GetChildCount(); i++)
{ {
FbxNode* child = parent_node->GetChild(i); FbxNode *child = parent_node->GetChild(i);
each_node(ctx, child, level + 1); each_node(ctx, child, level + 1);
} }
} }
} }
void print_node_info(FbxNode* node, int level) void print_node_info(FbxNode *node, int level)
{ {
// 打印一下节点信息 // 打印一下节点信息
printf("|"); printf("|");
@ -105,5 +120,5 @@ void print_node_info(FbxNode* node, int level)
printf("-"); printf("-");
} }
printf("> "); printf("> ");
printf("[%ld]: %s\n", node->GetUniqueID(), node->GetNameOnly().Buffer()); printf("[%lld]: %s\n", node->GetUniqueID(), node->GetNameOnly().Buffer());
} }

View File

@ -32,4 +32,6 @@ void create_tables(sqlite3* db);
* @note 1. ctx/db非NULLname/fbx_id非空 * @note 1. ctx/db非NULLname/fbx_id非空
* 2. name会触发唯一键冲突 * 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); 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);
int save_mesh_vertices(FttContext* ctx, uint mesh_id, std::vector<V3> vertices);

View File

@ -2,7 +2,6 @@
using namespace std; using namespace std;
using V3 = std::tuple<int, int, int>;
/** /**
* FBX节点树结构 * FBX节点树结构

View File

@ -17,6 +17,8 @@ typedef struct {
sqlite3* db; sqlite3* db;
} FttContext; } FttContext;
using V3 = std::tuple<int, int, int>;
FttContext ctx_from_const(const FttContext* ctx); FttContext ctx_from_const(const FttContext* ctx);
#endif #endif

View File

@ -1,6 +1,7 @@
#include <tools.h> #include <tools.h>
FttContext ctx_from_const(const FttContext* ctx) { FttContext ctx_from_const(const FttContext *ctx)
{
FttContext mut_ctx; FttContext mut_ctx;
mut_ctx.db = ctx->db; mut_ctx.db = ctx->db;

View File

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