===============
Level of detail
===============

Level-of-detail (LOD) is an essential element of large model visualization. It simplifies the representation of complex objects thus improving performance while maintaining visual integrity.  For instance, when you enable LOD in HOOPS, facetted shells are drawn with a smaller number of triangles while point clouds, which have no face list, are rendered with a smaller number of representative points. The LOD   implementation in HOOPS/3dGS balances speed with accuracy, so that visual degradation of the model is minimized. HOOPS/3dGS LOD support provides a flexible interface which includes a wide variety of configuration options.

Enabling LOD
============

Level of detail is enabled by calling:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0023.cpp
		   :start-after: //! [lod1]
		   :end-before: //! [lod1]
		   
...at which point alternative versions of geometry will be displayed according to the :ref:`switching options <prog_guide/3dgs/06_2_rendering_level_of_detail:Switching options>`. Level-of-Detail options, also know as "lodo", are set by calling:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0023.cpp
		   :start-after: //! [lod2]
		   :end-before: //! [lod2]


Controlling automatic LOD generation
====================================

LOD calculation can happen in one of the following 2 ways: either at draw time (during the ``Update_Display``) by specifying "preprocess" in the rendering options, or through a call to ``Regenerate_LOD`` which will do the calculation separately from the update process.  Various LOD options allow the user to control how LODs are generated. All but one of them ("mode" -- see below) are relevant to both the "lodo" suboptions list of ``Set_Rendering_Options`` and the options string of ``Regenerate_LOD``. They include: 

*levels* : Specifies how many levels should be calculated. The lowest level number is the most detailed, and the highest is the most compressed. The default number of levels is 2. 

*min triangle count* : Sets a lower bound on the number of triangles that a LOD representation can have. Simplification will halt at the final level above the given threshold. Quality of simplified representations degrades quickly as the number of triangles gets to be too low. Changes to this variable will not trigger recalculation of representations. The default is min triangle count = 50. This option will only apply to shells with a face list.

*ratio* : Specifies how many triangles or points, for point clouds, each LOD level should have in relation to the previous.  This number is expressed as one or more floating point values between 0 and 1. For example, a ratio of 0.25 would mean that level 1 would have 1 triangle for every 4 triangles in level 0 for a shell with a face list.  The default ratio is 0.50

*mode* : Specifies the scope of geometry to be considered during LOD generation, and to where the resulting LODs are to be attached. Choices for this are "segment" and the default, "geometry". Normally, LODs are attached to shells, generated only from one shell at a time. "segment" level LODs are useful for when multiple shells combine to form a single visually coherent body. Under that mode, the shells from an entire segment tree are merged for the purposes of LOD generation, and attached to the segment. Any attributes in segments below this setting are ignored. This option is only relevant in the context of a call to ``Regenerate_LOD``.


Suppressing LOD calculations
----------------------------

"Options" are available to instruct the LOD algorithm to not generate LODs if certain criteria are not met. The options include: 

*usefulness heuristic* : This specifies the function which is to be applied to a LOD result to determine whether it passes the LOD generation test.

*calculation usefulness cutoff* : This option sets the thresholds below which LODs will not be calculated. This can be specified as one global value to apply to all levels, or as a list of numbers, a different one for each level. 

*bounding* : Some of the aforementioned 'usefulness heuristic' options are specified as ratios of the current object to an external bounding volume. This option allows the user to specify what should be used as the external bounding volume.


Segment level LODs
------------------

LODs can be attached to a segment instead of to a piece of geometry, which can be useful when a group of geometry inside of a segment represents a single higher-level object. This is enabled by setting the 'mode' level of detail option to 'segment':

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0023.cpp
		   :start-after: //! [lod3]
		   :end-before: //! [lod3]
		   
If the mode is set to 'segment' then all LODs under that segment will be ignored during LOD switches. Furthermore, if you call Regenerate_LOD, 3dGS will try and collapse all shells contained in this portion of the segment tree into a single monolithic shell and generate LODs from it. 


Switching options
=================

The decision of which LOD to draw is also controlled by "LOD options". HOOPS/3dGS can either switch between different LODs based on view-dependent information, or it can be drawn a constant level of detail specified by the user. By default, HOOPS/3dGS will do the view-dependent switching.


View-dependent
--------------

*threshold* : A list of one or more floating point values to determine when switching should occur from one LOD level to the next. This value can be specified as one of:

* triangles per square centimeter for facetted shells(resolution independent) 
* triangles per square pixel for facetted shells(resolution dependent) 
* screen area percentage for point clouds and facetted shells(regardless of number of triangles)

Choosing which one is done by appending the values by tpcm2, tppix2 or % respectively. For example, "threshold = (100%, 10%, 0%)" would mean that LOD 0 will be used if the object covers the entire area of the screen, LOD 1 will be used if it covers 10 percent, and LOD 2 will be used otherwise.

Since LOD levels share bounding volumes (and thus "area" for the purpose of these calculations), screen area percentage requires one float value per LOD level for any meaningful results. Since the other two choices take the number of triangles into account, a single floating point value can be shared between levels. We have found screen area percentage to be useful for tight control over hand-tuned data. 


Clamping
--------

*clamp* : This will cause the LOD module to unconditionally display a certain level of detail. "clamp=0" will have the effect of forcing the original data to be displayed. This will have the same visual effect as turning it off. With clamping, no new levels of detail will be created unless the preprocess option is used (as opposed to when clamping is disabled, in which case levels of detail will be created as needed). If a requested level is not present, HOOPS will display the next lower resolution. If there is no lower resolution available, it will display the next higher resolution. 

*fallback* : The fallback option dictates switching behavior if and when LOD is clamped to a level that doesn't exist for a particular shell. When a higher LOD level is selected than is available (e.g. during interactive streaming), the next highest level will be selected for any fallback mode except "none".


User-specified LODs
===================

The command ``Open_LOD`` allows the user to open a LOD representation for the purpose of manually inserting a LOD. Once a LOD is opened, the developer can specify any HOOPS/3dGS geometric primitive as a LOD. For example, you could specify LOD level 3 of a HOOPS/3dGS shell to be a HOOPS/3dGS image. The pseudocode would be::

	HC_Open_Geometry(<shell_id>);
	  HC_Open_LOD(<lod_number>);
		HC_Insert_Image(<image_data>);
	  HC_Close_LOD();
	HC_Close_Geometry();

Then, if you set the "lod options" suboption of ``Set_Rendering_Options`` to "clamp=3", HOOPS/3dGS would draw an image in place of the shell. Similarly if you wanted to manually specify LODs on a segment level basis, you would first open the segment, and then open the desired LOD(s).
  
If the application is using a solid modeller to generate objects (typically called 'bodies'), it may be more advantageous to change the modelling kernel's facetting options to generate lower resolutions of the bodies and insert them as user-specified LODs, rather than have HOOPS/3dGS compute them. The solid modeller has more information to work with and may be able to produce a higher-quality LOD.
  
  
Choosing the LOD algorithm
==========================

Users of the HOOPS/3dGS LOD module have the choice of using a faster LOD calculation algorithm when visual integrity is not a priority. This is controlled via the 'algorithm' LOD option. Setting it to 'fast' uses a fast LOD algorithm, with some visual quality degradation. Setting it to 'nice' uses a LOD algorithm which requires extra generation time but produces data that has less visual degradation. Note that this option is only available for facetted shells.


Manually computing LODs
=======================

HOOPS/3dGS performs automatic LOD generation via ``Set_Rendering_Options``, but it may be useful to perform manual LOD calculations external to the HOOPS/3dGS scene-graph, especially when either an application or solid modelling kernel has higher-order information to work with than the raw triangles (e.g. cylinders or B-rep surfaces). The ``Compute_Optimized_Shell`` routine could be used for this purpose, since it provides support for computing LODs. LODs saved out to file, either as hmf or hsf, are restored by this path. After manually computing a LOD, you would insert it using :ref:`user-defined LOD capabilities <prog_guide/3dgs/06_2_rendering_level_of_detail:User-specified LODs>`. 


Vertex parameters
=================

The LOD algorithms will automatically interpolate any vertex data at different levels of detail. Specifically, vertex colors/normals/texture-coordinates will be interpolated and applied to the different levels of complexity. This allows better interaction with scenes containing large amounts of costly texture maps and color-interpolated geometry.
