fbx_to_3dtiles/cpp_src/db_ops.cpp

254 lines
8.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <db_ops.h>
#include <string>
#include <cstring>
#include <tools.h>
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[%d]\n", sqlite3_errmsg(db), result_code);
sqlite3_close(db);
return NULL;
}
return db;
}
void create_tables(sqlite3 *db)
{
const char *sql_nodes = R"
CREATE TABLE IF NOT EXISTS nodes (
id INTEGER PRIMARY KEY,
unique_id INTEGER NOT NULL UNIQUE,
parent_id INTEGER,
name TEXT NOT NULL,
lcl_translation_x REAL,
lcl_translation_y REAL,
lcl_translation_z REAL,
lcl_rotation_x REAL,
lcl_rotation_y REAL,
lcl_rotation_z REAL,
lcl_scaling_x REAL,
lcl_scaling_y REAL,
lcl_scaling_z REAL,
properties TEXT,
FOREIGN KEY (parent_id) REFERENCES fbx_nodes(unique_id)
);
";
const char *sql_meshes = R"(
CREATE TABLE IF NOT EXISTS meshes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
pid INTEGER,
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,
vert_id INTEGER NOT NULL,
mesh_id INTEGER NOT NULL,
position_x REAL NOT NULL,
position_y REAL NOT NULL,
position_z REAL NOT NULL,
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,
index_id INTEGER NOT NULL,
mesh_id INTEGER NOT NULL,
position_x REAL NOT NULL,
position_y REAL NOT NULL,
position_z REAL 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
}
}
// 函数定义
int save_mesh_to_table(FttContext *ctx,
sqlite3 *db,
uint id,
uint pid,
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, pid, 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_int64(stmt, 2, pid);
sqlite3_bind_text(stmt, 3, name.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 4, vertex_count);
sqlite3_bind_int(stmt, 5, index_count);
sqlite3_bind_text(stmt, 6, 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;
}
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;
}
int save_mesh_indices(FttContext* ctx, uint mesh_id, std::vector<unsigned int> indices) {
if (!ctx->db) return -1;
printf("save indices: %d\n", indices.size());
for (int i = 0; i < indices.size(); i++)
{
printf("%d ", indices[i]);
}
// sqlite3_stmt *stmt = nullptr;
// const char *sql = "INSERT OR IGNORE INTO indices (mesh_id, index_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 < indices.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>(indices[i])); // 修正为double类型绑定
// sqlite3_bind_double(stmt, 4, std::get<1>(indices[i]));
// sqlite3_bind_double(stmt, 5, std::get<2>(indices[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;
}