Files
ViewDesignEngine/src/foundation/io_gltf.cpp
T

92 lines
3.1 KiB
C++
Raw Normal View History

#include "vde/foundation/io_gltf.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cmath>
namespace vde::foundation {
namespace {
std::string vec3_to_json(double x, double y, double z) {
return "[" + std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + "]";
}
} // namespace
bool write_gltf(const std::string& filepath, const mesh::HalfedgeMesh& mesh) {
std::ofstream file(filepath);
if (!file) return false;
size_t nv = mesh.num_vertices();
size_t nf = mesh.num_faces();
// Count total indices (triangles * 3)
size_t index_count = nf * 3;
// Build min/max for accessor bounds
core::AABB3D bounds = mesh.bounds();
file << "{\n";
file << " \"asset\": {\"version\": \"2.0\", \"generator\": \"ViewDesignEngine\"},\n";
file << " \"scene\": 0,\n";
file << " \"scenes\": [{\"nodes\": [0]}],\n";
file << " \"nodes\": [{\"mesh\": 0}],\n";
file << " \"meshes\": [{\n";
file << " \"primitives\": [{\n";
file << " \"attributes\": {\"POSITION\": 0},\n";
file << " \"indices\": 1\n";
file << " }]\n";
file << " }],\n";
// Buffers and bufferViews
file << " \"buffers\": [{\"uri\": \"data:application/octet-stream;base64,";
// Write binary data as base64 (simplified: write inline as hex-ish)
// For simplicity, write a separate .bin file reference
file << "mesh.bin\",\"byteLength\": " << (nv*12 + index_count*4) << "}],\n";
file << " \"bufferViews\": [\n";
file << " {\"buffer\": 0, \"byteOffset\": 0, \"byteLength\": " << (nv*12) << "},\n";
file << " {\"buffer\": 0, \"byteOffset\": " << (nv*12) << ", \"byteLength\": " << (index_count*4) << "}\n";
file << " ],\n";
// Accessors
file << " \"accessors\": [\n";
file << " {\"bufferView\": 0, \"componentType\": 5126, \"count\": " << nv
<< ", \"type\": \"VEC3\", \"max\": " << vec3_to_json(bounds.max().x(),bounds.max().y(),bounds.max().z())
<< ", \"min\": " << vec3_to_json(bounds.min().x(),bounds.min().y(),bounds.min().z()) << "},\n";
file << " {\"bufferView\": 1, \"componentType\": 5125, \"count\": " << index_count
<< ", \"type\": \"SCALAR\"}\n";
file << " ]\n";
file << "}\n";
// Write binary data file
std::string binpath = filepath;
size_t dot = binpath.rfind(.);
if (dot != std::string::npos) binpath = binpath.substr(0, dot);
binpath += ".bin";
std::ofstream bin(binpath, std::ios::binary);
// Vertices (float32)
for (size_t i = 0; i < nv; ++i) {
const auto& v = mesh.vertex(i);
float fx=v.x(), fy=v.y(), fz=v.z();
bin.write(reinterpret_cast<const char*>(&fx),4);
bin.write(reinterpret_cast<const char*>(&fy),4);
bin.write(reinterpret_cast<const char*>(&fz),4);
}
// Indices (uint32)
for (size_t i = 0; i < nf; ++i) {
auto vis = mesh.face_vertices(static_cast<int>(i));
for (size_t j = 0; j < std::min(vis.size(), size_t(3)); ++j) {
uint32_t idx = vis[j];
bin.write(reinterpret_cast<const char*>(&idx),4);
}
}
return true;
}
} // namespace vde::foundation