Hidden Lines Removal (polyhedral HLR)new

This simple tutorial focuses on a specific method that can be found on the RED::ITransformShape: this is RED::ITransformShape::BuildHLR. This method generates the set of visible and hidden lines of the current scene seen from the specified camera.

The HLR generated for a simple office scene used in other REDsdk tutorials.

Using BuildHLR

The RED::ITransformShape::BuildHLR method is pretty straightforward to use:

// Launching HLR calculations:
RED::Object* line_visible, *line_hidden, *root;
RC_TEST( icamera->GetRootShape( root ) );
RED::ITransformShape* itroot = root->As< RED::ITransformShape >();
RC_TEST( itroot->BuildHLR( line_visible, line_hidden, camera, 1e-4, iresmgr->GetState(), HLRProgress, NULL, HLRInterrupt, NULL ) );

Calling this method may take a bit of time, depending on the model to process. The entire scene graph below the calling shape is processed for the determination of hidden and visible lines. Results are stored in two separate line shape objects that implement the RED::ILineShape interface. Then, there's only to setup some materials to display the results and voila.

The scene graph accessed through the calling shape may contain any kind of shape. Only meshes and lines are processed for the determination of which lines are visible. The system always adds contour edges and faces frontier edges of processed geometries to the results as these are important visual clues.

To get a better visual result with edges, the tutorial sets alpha materials:

// Create the visible lines material once:
if( g_visible_mat == NULL )
{
  RC_TEST( iresmgr->CreateMaterial( g_visible_mat, iresmgr->GetState() ) );
  RED::IMaterial* imatr = g_visible_mat->As< RED::IMaterial >();

  RED::StateShader ssh;
  RC_TEST( ssh.SetBlendingMode( RED::StateShader::ADDITIVE ) );
  RC_TEST( ssh.SetLineWidth( 2.0f ) );
  RC_TEST( ssh.SetLineSmoothing( true ) );
  RC_TEST( ssh.SetDepthTest( RED::StateShader::OFF ) );
  RC_TEST( ssh.SetDepthMask( RED::StateShader::OFF ) );

  RC_TEST( imatr->RegisterShader( ssh, iresmgr->GetState() ) );
  RC_TEST( imatr->AddShaderToPass( ssh.GetID(), RED::MTL_PRELIT, RED::LIST_LAST, RED::LayerSet::ALL_LAYERS, iresmgr->GetState() ) );

  RED_RC rc;

  RED::RenderShaderSolid solid( RED::MTL_PRELIT, 
                                RED::Color::WHITE, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 
                                RED::Color::WHITE, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                resmgr, rc );
  RC_TEST( rc );

  RC_TEST( imatr->RegisterShader( solid, iresmgr->GetState() ) );
  RC_TEST( imatr->AddShaderToPass( solid.GetID(), RED::MTL_PRELIT, RED::LIST_LAST, RED::LayerSet::ALL_LAYERS, iresmgr->GetState() ) );
}

That kind of material setup produces smooth lines that render better.

Collapse or no collapse?

This is the 4th parameter of RED::ITransformShape::BuildHLR. If set to 0.0, then no RED::IMeshShape::Collapse operation is performed on input meshes (so the method goes a bit faster). Otherwise, input meshes are duplicated internally, collapsed, and the collapsed results are used to generate the HLR, instead of the original scene graph contents. This can eliminate various topological artifacts. Below we can see the differences between the use of a collapse or not on the starting scene of the tutorial:

Collapse on the left, no collapse on the right.

The rightmost picture reveals all topological breaks we have in our source data: these are frontier edges. It's kind of normal: a sphere or a torus are built as revolution shapes with overlapping first and last vertices, that are different for UV wrapping. So all these frontiers are expected on such shapes and the collapse operation can be used to remove them. Note that when collapsed, it may be needed to store faces borders in a separate shape in order to preserve them.