Compare commits
No commits in common. "691109e12abe6fc561167e5e364ca2d95c6b6d6b" and "0808672ba842cc7d9a9846d9e7d200839cd1a68e" have entirely different histories.
691109e12a
...
0808672ba8
|
@ -3,5 +3,3 @@
|
||||||
*.exe
|
*.exe
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
*.dump
|
|
||||||
out/
|
|
5
build.rs
5
build.rs
|
@ -7,13 +7,10 @@ fn main() {
|
||||||
// .flag("-std=c++11")
|
// .flag("-std=c++11")
|
||||||
.warnings(false)
|
.warnings(false)
|
||||||
.include("./cpp_src/include")
|
.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_parse.cpp")
|
||||||
.file("./cpp_src/fbx_wrap.cpp")
|
.file("./cpp_src/fbx_wrap.cpp")
|
||||||
.compile("fbx_parse");
|
.compile("fbx_parse");
|
||||||
// -------------
|
// -------------
|
||||||
println!("cargo:rustc-link-search=native=./cpp_src/lib");
|
println!("cargo:rustc-link-search=native=./cpp_src/lib");
|
||||||
println!("cargo:rustc-link-lib=fbxsdk");
|
println!("cargo:rustc-link-lib=fbxsdk");
|
||||||
println!("cargo:rustc-link-lib=sqlite3");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
#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_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_msg(sqlite3_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;
|
|
||||||
}
|
|
|
@ -2,15 +2,14 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
// buz
|
// buz
|
||||||
#include <fbx_wrap.h>
|
#include <fbx_wrap.h>
|
||||||
#include <db_ops.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// 定义给Rust调用的接口函数
|
// 定义给Rust调用的接口函数
|
||||||
void fbx_parse(FttContext* ctx)
|
void fbx_parse(const char* fbx_path)
|
||||||
{
|
{
|
||||||
printf("%s\n", ctx->fbx_file);
|
printf("%s\n", fbx_path);
|
||||||
FbxManager* lSdkManager = FbxManager::Create();
|
FbxManager* lSdkManager = FbxManager::Create();
|
||||||
if (lSdkManager){
|
if (lSdkManager){
|
||||||
printf("FbxManager created\n");
|
printf("FbxManager created\n");
|
||||||
|
@ -24,7 +23,7 @@ extern "C" {
|
||||||
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(fbx_path, -1, lSdkManager->GetIOSettings());
|
||||||
if (s){
|
if (s){
|
||||||
printf("FbxImporter initialized\n");
|
printf("FbxImporter initialized\n");
|
||||||
} else{
|
} else{
|
||||||
|
@ -35,29 +34,16 @@ extern "C" {
|
||||||
|
|
||||||
FbxNode* lRootNode = lScene->GetRootNode();
|
FbxNode* lRootNode = lScene->GetRootNode();
|
||||||
if (lRootNode) {
|
if (lRootNode) {
|
||||||
each_node(ctx, lRootNode, 0);
|
each_node(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(const char* fbx_path)
|
||||||
{
|
{
|
||||||
// get mutable data
|
FbxNode* root = get_fbx_root_node(fbx_path);
|
||||||
auto temp = ctx_from_const(ctx);
|
|
||||||
FttContext* mut_ctx = &temp;
|
|
||||||
|
|
||||||
// 按fbx名称生成 ${ctx.out_dir}/sqlite3.db
|
each_node(root, 0);
|
||||||
// 初始化db赋值到ctx.db
|
|
||||||
sqlite3* db = create_db((std::string(ctx->out_dir) + "/db.sqlite3").c_str(), true);
|
|
||||||
if (db == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mut_ctx->db = db;
|
|
||||||
// init db tables
|
|
||||||
create_tables(mut_ctx->db);
|
|
||||||
|
|
||||||
FbxNode* root = get_fbx_root_node(ctx->fbx_file);
|
|
||||||
each_node(mut_ctx, root, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
#include <fbx_wrap.h>
|
#include "fbx_wrap.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <db_ops.h>
|
|
||||||
#include <tools.h>
|
|
||||||
|
|
||||||
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<Triangle>& triangles) {
|
||||||
if (!attr || attr->GetAttributeType() != FbxNodeAttribute::eMesh) return false;
|
|
||||||
FbxMesh* mesh = static_cast<FbxMesh*>(attr);
|
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();
|
int polyCount = mesh->GetPolygonCount();
|
||||||
|
triangles.reserve(polyCount);
|
||||||
for (int i = 0; i < polyCount; ++i) {
|
for (int i = 0; i < polyCount; ++i) {
|
||||||
int vertexCount = mesh->GetPolygonSize(i);
|
if (mesh->GetPolygonSize(i) != 3) continue; // 跳过非三角形(理论上不会存在)
|
||||||
std::vector<int> polyIndices;
|
int i0 = mesh->GetPolygonVertex(i, 0);
|
||||||
for (int j = 0; j < vertexCount; ++j) {
|
int i1 = mesh->GetPolygonVertex(i, 1);
|
||||||
polyIndices.push_back(mesh->GetPolygonVertex(i, j));
|
int i2 = mesh->GetPolygonVertex(i, 2);
|
||||||
}
|
triangles.emplace_back(i0, i1, i2);
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FbxNode* get_fbx_root_node(const char* fbx_path)
|
FbxNode* get_fbx_root_node(const char* fbx_path)
|
||||||
|
@ -57,7 +55,7 @@ FbxNode* get_fbx_root_node(const char* fbx_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void each_node(FttContext* ctx, FbxNode* parent_node, int level)
|
void each_node(FbxNode* parent_node, int level)
|
||||||
{
|
{
|
||||||
// info
|
// info
|
||||||
print_node_info(parent_node, level);
|
print_node_info(parent_node, level);
|
||||||
|
@ -67,20 +65,14 @@ void each_node(FttContext* ctx, FbxNode* parent_node, int level)
|
||||||
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<Triangle> triangles;
|
||||||
std::vector<V3> triangles;
|
int count = load_triangles(attr, triangles);
|
||||||
int count = load_triangles(attr, vertices, triangles);
|
printf("triangles: %ld;", triangles.size());
|
||||||
uint id = attr->GetUniqueID();
|
std::cout << "("
|
||||||
printf("[%ld]triangles: %ld\n", id, triangles.size());
|
<< get<0>(triangles[0]) << ", "
|
||||||
// save data to database
|
<< get<1>(triangles[0]) << ", "
|
||||||
sqlite3* db = ctx->db;
|
<< get<2>(triangles[0]) << ")"
|
||||||
// todo save mesh into db
|
<< std::endl;
|
||||||
|
|
||||||
save_mesh_to_table(ctx, ctx->db,
|
|
||||||
id,
|
|
||||||
attr->GetName(),
|
|
||||||
vertices.size(), triangles.size(),
|
|
||||||
parent_node->GetNameOnly().Buffer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,7 +83,7 @@ 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(child, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#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_OK,失败返回SQLite错误码(<0)
|
|
||||||
* @note 1. 参数需确保有效:ctx/db非NULL,name/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);
|
|
|
@ -1,8 +1,13 @@
|
||||||
#include <tools.h>
|
#include <fbxsdk.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
using V3 = std::tuple<int, int, int>;
|
using Triangle = std::tuple<int, int, int>;
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归遍历FBX节点树结构
|
* 递归遍历FBX节点树结构
|
||||||
|
@ -11,7 +16,7 @@ using V3 = std::tuple<int, int, int>;
|
||||||
* @note 函数内部会递归访问parent_node的所有直接子节点和间接子节点
|
* @note 函数内部会递归访问parent_node的所有直接子节点和间接子节点
|
||||||
* @warning 若输入的parent_node无效(如野指针)可能导致程序崩溃
|
* @warning 若输入的parent_node无效(如野指针)可能导致程序崩溃
|
||||||
*/
|
*/
|
||||||
void each_node(FttContext* ctx, FbxNode* parent_node, int level);
|
void each_node(FbxNode* parent_node, int level);
|
||||||
/**
|
/**
|
||||||
* 打印FBX节点的基本信息(含层级缩进)
|
* 打印FBX节点的基本信息(含层级缩进)
|
||||||
* @param node 待打印信息的节点指针(nullptr时输出警告日志)
|
* @param node 待打印信息的节点指针(nullptr时输出警告日志)
|
||||||
|
@ -20,22 +25,7 @@ void each_node(FttContext* ctx, FbxNode* parent_node, int level);
|
||||||
* @example 层级2的节点打印格式:" |-- NodeName (Type: Mesh, Children: 3)"
|
* @example 层级2的节点打印格式:" |-- NodeName (Type: Mesh, Children: 3)"
|
||||||
*/
|
*/
|
||||||
void print_node_info(FbxNode* node, int level);
|
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);
|
FbxNode* get_fbx_root_node(const char* fbx_path);
|
||||||
|
|
||||||
|
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<Triangle>& triangles);
|
||||||
/**
|
|
||||||
* @brief 从FBX网格属性加载顶点数据和三角化索引
|
|
||||||
* @param[in] attr FBX节点属性,需为FbxMesh类型
|
|
||||||
* @param[out] vertices 输出顶点坐标数组(每个Triangle存储3个FbxVector4顶点)
|
|
||||||
* @param[out] triangles 输出三角形索引数组(每个Triangle存储3个顶点索引)
|
|
||||||
* @return bool 成功返回true,失败返回false
|
|
||||||
* @note 内部会强制三角化网格,非三角形多边形将被忽略
|
|
||||||
*/
|
|
||||||
int load_triangles(fbxsdk::FbxNodeAttribute* attr, std::vector<V3>& indices, std::vector<V3>& triangles);
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
#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;
|
|
||||||
char* out_dir;
|
|
||||||
|
|
||||||
sqlite3* db;
|
|
||||||
} FttContext;
|
|
||||||
|
|
||||||
FttContext ctx_from_const(const FttContext* ctx);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
29
src/main.rs
29
src/main.rs
|
@ -1,40 +1,19 @@
|
||||||
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("/mnt/f/BaiduNetdiskDownload/绿科模型/绿科-三维视图-{三维}111.fbx");
|
||||||
"/root/src/fbx_to_3dtiles/out/lk");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct FttContext {
|
|
||||||
pub fbx_file: *mut c_char,
|
|
||||||
pub out_dir: *mut c_char
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
pub unsafe fn fbx_parse(name_in: *const u8);
|
pub unsafe fn fbx_parse(name_in: *const u8);
|
||||||
pub unsafe fn load_fbx_mesh_to_db(ctx: *const FttContext);
|
pub unsafe fn load_fbx_mesh_to_db(path: *const u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_fbx_to_3dtiles(fbx_path: &str, out_dir: &str) {
|
fn convert_fbx_to_3dtiles(fbx_path: &str) {
|
||||||
|
|
||||||
|
|
||||||
let ctx = &FttContext{
|
|
||||||
fbx_file: CString::new(fbx_path).unwrap().into_raw(),
|
|
||||||
out_dir: CString::new(out_dir).unwrap().into_raw()
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// fbx_parse(fbx_path.as_ptr() as *const u8);
|
// fbx_parse(fbx_path.as_ptr() as *const u8);
|
||||||
// 1. load to disk
|
// 1. load to disk
|
||||||
// fbx_path.as_ptr() as *const u8
|
load_fbx_mesh_to_db(fbx_path.as_ptr() as *const u8);
|
||||||
load_fbx_mesh_to_db(ctx);
|
|
||||||
|
|
||||||
|
|
||||||
// free
|
|
||||||
let _ = CString::from_raw(ctx.fbx_file);
|
|
||||||
let _ = CString::from_raw(ctx.out_dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsafe {
|
// unsafe {
|
||||||
|
|
Loading…
Reference in New Issue