feat: LOD mesh generation + incremental BVH
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include "vde/mesh/halfedge_mesh.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace vde::brep { class BrepModel; }
|
||||
|
||||
namespace vde::mesh {
|
||||
|
||||
/**
|
||||
* @brief Level-of-detail mesh with multiple detail levels
|
||||
*
|
||||
* Stores a sequence of simplified meshes from highest detail (index 0)
|
||||
* to lowest. Screen-space error thresholds determine which level to
|
||||
* use for rendering.
|
||||
*
|
||||
* @ingroup mesh
|
||||
*/
|
||||
struct LODMesh {
|
||||
std::string name;
|
||||
/// Meshes from highest detail (index 0) to lowest
|
||||
std::vector<HalfedgeMesh> levels;
|
||||
/// Screen-space error thresholds for each level (in pixels)
|
||||
std::vector<double> thresholds;
|
||||
|
||||
/**
|
||||
* @brief Get the appropriate LOD level for a given screen-space error
|
||||
*
|
||||
* Selects the lowest-detail level whose threshold is ≤ error.
|
||||
* Walks thresholds from coarsest to finest.
|
||||
*
|
||||
* @param error Screen-space error in pixels
|
||||
* @return LOD level index (0 = highest detail)
|
||||
*/
|
||||
[[nodiscard]] int level_for_error(double error) const;
|
||||
|
||||
/**
|
||||
* @brief Get the mesh at a specific LOD level (clamped)
|
||||
*
|
||||
* @param level Desired LOD level
|
||||
* @return Reference to the mesh at that level
|
||||
*/
|
||||
[[nodiscard]] const HalfedgeMesh& mesh_at(int level) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generate LOD meshes from a high-detail mesh
|
||||
*
|
||||
* Iteratively applies QEM simplification, reducing face count
|
||||
* by `reduction_ratio` at each level.
|
||||
*
|
||||
* @param mesh High-detail input mesh
|
||||
* @param num_levels Number of LOD levels (including base)
|
||||
* @param reduction_ratio Ratio of faces to keep at each level (0.5 = half)
|
||||
* @return LOD meshes with thresholds proportional to level index
|
||||
*
|
||||
* @code{.cpp}
|
||||
* auto lod = generate_lod(high_res, 4, 0.5);
|
||||
* int level = lod.level_for_error(screen_error);
|
||||
* render(lod.mesh_at(level));
|
||||
* @endcode
|
||||
*/
|
||||
[[nodiscard]] LODMesh generate_lod(const HalfedgeMesh& mesh,
|
||||
int num_levels = 3, double reduction_ratio = 0.5);
|
||||
|
||||
/**
|
||||
* @brief Generate LOD from B-Rep body (tessellate + simplify)
|
||||
*
|
||||
* Tessellates the B-Rep body with default deflection, then
|
||||
* generates LOD levels via QEM simplification.
|
||||
*
|
||||
* @param body B-Rep model
|
||||
* @param num_levels Number of LOD levels
|
||||
* @return LOD meshes
|
||||
*/
|
||||
[[nodiscard]] LODMesh generate_brep_lod(const brep::BrepModel& body,
|
||||
int num_levels = 3);
|
||||
|
||||
} // namespace vde::mesh
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include "vde/spatial/bvh.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace vde::spatial {
|
||||
|
||||
/**
|
||||
* @brief Incremental BVH that supports insert/remove without full rebuild
|
||||
*
|
||||
* Wraps the standard BVH with a dirty flag. Triangles can be inserted,
|
||||
* removed, or updated incrementally. The tree is lazily rebuilt on the
|
||||
* next query when dirty. Suitable for moderately dynamic scenes where
|
||||
* queries are less frequent than modifications.
|
||||
*
|
||||
* @ingroup spatial
|
||||
*/
|
||||
class IncrementalBVH {
|
||||
public:
|
||||
/// @brief Build from initial set of triangles
|
||||
void build(const std::vector<core::Triangle3D>& triangles);
|
||||
|
||||
/// @brief Insert a new triangle (marks dirty, no immediate rebuild)
|
||||
void insert(const core::Triangle3D& tri);
|
||||
|
||||
/// @brief Remove a triangle by index (marks dirty)
|
||||
void remove(size_t index);
|
||||
|
||||
/// @brief Update a triangle's geometry in-place (marks dirty)
|
||||
void update(size_t index, const core::Triangle3D& tri);
|
||||
|
||||
/**
|
||||
* @brief Ray query (rebuilds if dirty, then delegates to BVH)
|
||||
*
|
||||
* @param ray Query ray
|
||||
* @return All hit results (t, triangle, hit point)
|
||||
*/
|
||||
std::vector<BVH::HitResult> ray_query(const Ray3Dd& ray) const;
|
||||
|
||||
/// @brief Number of triangles
|
||||
[[nodiscard]] size_t size() const { return triangles_.size(); }
|
||||
|
||||
private:
|
||||
std::vector<core::Triangle3D> triangles_;
|
||||
std::vector<core::AABB3D> bboxes_;
|
||||
BVH bvh_;
|
||||
bool dirty_ = true;
|
||||
|
||||
void rebuild_if_dirty();
|
||||
};
|
||||
|
||||
} // namespace vde::spatial
|
||||
Reference in New Issue
Block a user