#include "dc_mesher.h"
#include "dc_octree.h"
#include "dc_pool.h"
DCMeshData dc_mesh_from_grid(const DensityGrid& grid, const DCMesherConfig& config) {
Pool<OctreeNode> pool;
int min[3] = {0, 0, 0};
int size = grid.grid_size;
OctreeNode* root = construct_octree_grid_pooled(min, size, grid, pool);
DCMeshData mesh;
if (root) {
float origin[3] = { grid.origin[0], grid.origin[1], grid.origin[2] };
dc_generate_mesh_grid(root, grid.voxel_scale, origin, grid, 0, mesh);
if (config.auto_smooth && mesh.positions.size() > 0) {
dc_auto_smooth(mesh, config.smooth_angle_deg);
}
if (config.laplacian_smooth && mesh.positions.size() > 0) {
dc_laplacian_smooth(mesh, config.laplacian_iterations,
config.laplacian_lambda,
config.smooth_angle_deg);
}
}
return mesh;
}
// Bridge: adapts DCGenerator::evaluate() to DensityGrid::fill()'s callback signature
struct GeneratorFillContext {
DCGenerator* gen;
float lod_voxel_size;
};
static float generator_fill_callback(float x, float y, float z, void* ud) {
auto* ctx = static_cast<GeneratorFillContext*>(ud);
return ctx->gen->evaluate(x, y, z, ctx->lod_voxel_size);
}
DCMeshData dc_mesh_from_generator(DCGenerator& gen, const float origin[3],
float voxel_size, int grid_size,
const DCMesherConfig& config) {
// Round up to next power of 2 — octree requires power-of-2 grid size
int po2 = 1;
while (po2 < grid_size) po2 <<= 1;
grid_size = po2;
// Fill grid for octree corner sampling
DensityGrid grid;
grid.allocate(grid_size, voxel_size, origin);
GeneratorFillContext ctx{&gen, voxel_size};
grid.fill(generator_fill_callback, &ctx);
// Build octree from grid
Pool<OctreeNode> pool;
int min[3] = {0, 0, 0};
OctreeNode* root = construct_octree_grid_pooled(min, grid_size, grid, pool);
DCMeshData mesh;
if (root) {
float org[3] = { grid.origin[0], grid.origin[1], grid.origin[2] };
// Direct evaluation for hermite data — preserves sharp features
dc_generate_mesh(root, grid.voxel_scale, org,
generator_fill_callback, &ctx, mesh);
if (config.auto_smooth && mesh.positions.size() > 0) {
dc_auto_smooth(mesh, config.smooth_angle_deg);
}
if (config.laplacian_smooth && mesh.positions.size() > 0) {
dc_laplacian_smooth(mesh, config.laplacian_iterations,
config.laplacian_lambda,
config.smooth_angle_deg);
}
}
return mesh;
}