保存顶点
This commit is contained in:
parent
691109e12a
commit
91b0644129
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,33 +71,33 @@ 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
|
||||||
|
@ -90,13 +105,13 @@ void each_node(FttContext* ctx, FbxNode* parent_node, int level)
|
||||||
{
|
{
|
||||||
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());
|
||||||
}
|
}
|
|
@ -32,4 +32,6 @@ void create_tables(sqlite3* db);
|
||||||
* @note 1. 参数需确保有效:ctx/db非NULL,name/fbx_id非空
|
* @note 1. 参数需确保有效:ctx/db非NULL,name/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);
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
using V3 = std::tuple<int, int, int>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归遍历FBX节点树结构
|
* 递归遍历FBX节点树结构
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
Loading…
Reference in New Issue