Template Class HLODTree

Class Documentation

template<typename BaseVecT>
class HLODTree

A class for Hierarchical Level of Detail (HLOD) trees.

Level of Detail (LOD) means that a mesh and various simplified versions of it are used depending on the required resolution.

A Hierarchy of LODs (HLOD) is a tree structure where each leaf is a detailed mesh and their parent nodes contain the simplified versions of the combination of the leaves.

How to use this class:

  1. Create the Hierarchy. This can be done by calling one of the static partition functions or by manually creating nodes and adding children.

  2. Call finalize() to generate the LODs.

finalize is separate, since multiple trees from different meshes can be combined into one tree.

Note that LazyMesh is used everywhere, since HLODs are typically only used for very large meshes, and LazyMesh allows creating the LODs without loading the entire mesh and all its LODs into memory.

Public Types

using Ptr = std::unique_ptr<HLODTree>
using Mesh = LazyMesh<BaseVecT>
using ChunkMap = std::unordered_map<Vector3i, Ptr>

Public Functions

inline bool isLeaf() const

Returns if this is a leaf.

inline size_t depth() const

Returns the depth of the tree. Only accurate after refresh() has been called.

void refresh()

Updates bounding boxes and other internal values of the tree.

This method should be called every time the tree has been changed.

void finalize(AllowedMemoryUsage allowedMemUsage = AllowedMemoryUsage::Moderate, float reductionFactor = 0.2f, float normalDeviation = -1.0f)

Generates the LOD meshes.

This can only happen once, so the entire tree and all children should be created and arranged before calling this method. This will finalize this tree and all its children, marking them as finalized.

Parameters:
  • allowedMemUsage – The allowed memory usage.

  • reductionFactor – How much the meshes should be reduced at each level.

  • normalDeviation – Maximum angle in degrees that normals are allowed to change by. -1 means no angle limit.

inline boost::optional<Mesh&> mesh()

Returns a reference to the mesh on this level.

Returns none if this node is not a leaf and either a) finalize() has not been called yet. Or b) it should be skipped according to combineDepth.

Note that modifications to this won’t be reflected to higher levels if finalize() was called prior to the change.

inline boost::optional<const Mesh&> mesh() const

Returns a reference to the mesh on this level.

Returns none if this node is not a leaf and either a) finalize() has not been called yet. Or b) it should be skipped according to combineDepth.

inline const pmp::BoundingBox &bb() const

Returns a BoundingBox containing this node and all its children. Only accurate after refresh() has been called.

inline std::vector<Ptr> &children()

Returns the children of this node. Empty if this is a leaf.

Note: Make sure to call refresh() after making any changes to the children.

inline const std::vector<Ptr> &children() const

Returns the children of this node. Empty if this is a leaf.

Public Static Functions

static Ptr partition(Mesh &src, float chunkSize, int combineDepth = -1)

Partitions the mesh into chunks and arranges them in a hierarchy. finalize() must be called to create the actual LOD.

The combineDepth parameter is used because it is usually not desirable to generate all LODs, but only up to a certain depth. combineDepth < 0 means generate all LODs. combineDepth == 0 means no LODs are generated, only leafs have meshes. combineDepth == 1 means generate only one level. and so on.

Parameters:
  • src – The mesh to partition.

  • chunkSize – The size of each chunk.

  • combineDepth – The combination depth of the hierarchy.

static Ptr partition(std::vector<Ptr> &&subtrees, int combineDepth = -1)

Arranges the given subtrees into a hierarchy.

Parameters:
  • subtrees – The subtrees to combine.

  • combineDepth – The combination depth of the hierarchy. See partition(Mesh) for details.

static Ptr partition(std::unordered_map<Vector3i, Ptr> &&chunks, int combineDepth = -1)

Arranges the given chunks into a hierarchy.

If chunk boundaries are marked as vertex features, they will be recombined when merging the chunks for higher LOD levels.

Features can be marked using:

auto v_feature = <PMPMesh>.getSurfaceMesh().vertex_property<bool>("v:feature", false));
for (VertexHandle vH : boundaryVertices)
   v_feature[vH] = true;
Alternatively, if your chunks contain overlap, you may use trimChunkOverlap() to both remove the overlap and mark the vertices as features.

Parameters:
  • chunks – A map from chunk position to the chunk. Note that only adjacent chunks according to the integer position are combined.

  • combineDepth – The combination depth of the hierarchy. See partition(Mesh) for details.

static void trimChunkOverlap(PMPMesh<BaseVecT> &mesh, const pmp::BoundingBox &expectedBB)

Removes any parts of a mesh that are outside of the given bounding box. The boundary of the remaining mesh is marked as a feature.

Parameters:
  • mesh – The mesh to trim.

  • expectedBB – The bounding box to trim to.

static Ptr leaf(Mesh &&mesh, const pmp::BoundingBox &bb)

Create a leaf.

Parameters:
  • mesh – The mesh of the leaf.

  • bb – The bounding box of the leaf. Can be calculated using mesh.getSurfaceMesh().bounds().

static Ptr node(std::vector<Ptr> &&children, int combineDepth = -1)

Create a node with the given children.

Keeps the children directly at this level. Use partition() if the children should be arranged into a hierarchy.

Parameters:
  • children – The children of the node.

  • combineDepth – The combination depth of the hierarchy. See partition(Mesh) for details.

static Ptr node(int combineDepth = -1)

Create an empty node.

Parameters:

combineDepth – The combination depth of the hierarchy. See partition(Mesh) for details.