Building a HOOPS Luminate Application

Welcome to HOOPS Luminate! This book is one of the first you may want to read to get a practical overview of HOOPS Luminate. We’ll cover various topics in this book, which are divided into three categories: high level product review (feature set review, example applications), general informations (licensing, deployment, support) and finally how to assemble a HOOPS Luminate application using the base HOOPS Luminate classes (resource manager, windows, viewpoints, …).

High Level Product Review

Please refer to this page: HOOPS Luminate Features at a Glance for a high level review of HOOPS Luminate feature set. This chapter will provide you a summary of HOOPS Luminate capabilities in terms of real-time 2D and 3D rendering as well as for photo-realistic rendering.

General Informations

This part of the book covers all the stuff that may sound a bit boring, but that we have to put somewhere because it’s essential anyway:

  • Programming Language: HOOPS Luminate is a C++ API. Get all the details on using it here and have a look at our coding principles too!

  • Deployment: Here more informations on how to deploy a HOOPS Luminate based application. You can’t do something easier.

  • Error Tracking: Find here details on errors and error tracking in HOOPS Luminate.

  • Software Startup: HOOPS Luminate is a hybrid hardware / software engine. It can start in pure software or in pure hardware or in hybrid mode, using both rendering modes at the same time in an application. This is a very important feature of HOOPS Luminate. Learn all the details here!

  • Hardware Platforms: HOOPS Luminate has an API to identify the system graphics in use and also to query and recommend graphic driver updates whenever needed.

  • OpenGL: HOOPS Luminate uses OpenGL if it has to run using the graphic hardware. Get details on how OpenGL is used by HOOPS Luminate here!

  • Virtualization Platforms: HOOPS Luminate can run on virtualization platforms. This chapter provides some useful informations on how virtualization platforms behave with HOOPS Luminate.

Building a HOOPS Luminate Application Cluster

Basic HOOPS Luminate objects are detailed in their respective chapters indicated below:

  • Resource Manager: The resource manager is the first HOOPS Luminate object in charge of all graphics assets.

  • Windows: Windows are rendering areas, and connected to operating system windows.

  • Viewpoint Render Lists: Viewpoint Render Lists or VRLs for short are classes in charge of the display setup of cameras (viewport, draw order,…).

  • Viewpoints: The camera chapter that detail how camera can be manipulated in HOOPS Luminate.

  • Data Manager: This class is used to the management of loaded .red files.

  • Options: Learn how HOOPS Luminate engine options can be accessed and controlled.

Some more important topics must be covered for operating a HOOPS Luminate application cluster, so we’ll provide the links now:

  • Transaction Management: Learn how HOOPS Luminate uses transactions that define engine states for reading and writing.

  • Life Cycle of HOOPS Luminate Objects: Learn how HOOPS Luminate objects are created and terminated.

  • Picking: For many applications, picking is a must have, and HOOPS Luminate has a complete picking API, detailed in that chapter.

  • Backbone: Learn how to customize memory allocators, file system tools used by HOOPS Luminate.

Then, let’s start gathering all objects we need to run a HOOPS Luminate based program now! A minimal HOOPS Luminate application must - at least - contain the following objects:

../../_images/minimal_cluster.png

The minimal set of HOOPS Luminate objects needed to run an application

The resource manager is a singleton, that is used to store and manage most resources in a HOOPS Luminate based application. A window is the rendering area that we’ll need to display something onscreen or to render something offscreen. We’ll also need a viewpoint to define how we do observe a scene, that must be at least composed of a shape.

The resource manager is created using the code example below:

Creating or Accessing the Resource Manager

// Create the resource manager on first call or retrieve it on other calls:
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
if( !resmgr )
{
    // Handle critical startup errors here.
}

// Access the resource manager interface:
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();

The resource manager is a singleton. Therefore, the first call to the factory will create the object, and all subsequent calls will return the created object. So it’s a normal way of doing to access the resource manager object address by creating it again. The resource manager creation code should not fail otherwise HOOPS Luminate can’t start. If this arise, please check that a fresh HOOPS Luminate installation can start, otherwise please check your licensing.

Then, the window is created using similar means and the RED::Factory class:

Creating a HOOPS Luminate Window using the RED::Factory

// 'application_window' must be a valid application HWND pointer.
RED_RC rc;
HWND hwnd = application_window;
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
int width = 1920;
int height = 1080;

// Create a rendering window:
RED::Object* window = RED::Factory::CreateREDWindow( *resmgr, hwnd, width, height, NULL, rc );
if( !window )
{
    // Handle critical errors here.
}
if( rc != RED_OK )
{
    // Handle error codes here.
}

In this example, we only show the windows OS code. The window creation works similarly on Linux and MacOS, provided the operating specific parameters. See the RED::Factory::CreateREDWindow method for details. Please note that it’s mandatory to check the window creation return code to be sure that the operation has succeeded.

And to complete our schema, we’ll need to create a viewpoint and a shape to visualize some data. Both are also created using the RED::Factory again:

Creating and Destroying Objects using the RED::Factory

// Create a viewpoint for instance:
RED::Object* viewpoint = RED::Factory::CreateInstance( CID_REDViewpoint );
if( !viewpoint )
{
    // Handle allocation errors here.
}

// Create a shape (a light source here):
RED::Object* light = RED::Factory::CreateInstance( CID_REDLightShape );
if( !light )
{
    // Handle allocation errors here.
}


// Destroy objects when done. Here, as an example, we destroy the viewpoint:
// Get a pointer to the RED resource manager.
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();

RED_RC rc = RED::Factory::DeleteInstance( viewpoint, iresmgr->GetState() );
if( rc != RED_OK )
{
    // Handle errors here.
}

At this point in our setup we have created all the objects that we need: a resource manager in charge of the storage and management of all graphic assets of the application; a window for the display of our rendered images; and some data to visualize: a camera that define the observer parameters and some shapes with some graphic data to be visualized. So this is the minimal setup. Of course, from this we’ll complete our specification with the creation of materials, images, scene hierarchies, etc…but the basics are there: a resource manager + a window + a viewpoint + a shape.

The ‘live’ windows are automatically known to the resource manager, and can be accessed anytime using RED::IResourceManager::GetWindowList. Then viewpoints have to be linked to windows to be displayed, and shapes have to be linked to viewpoints to be seen either. We need to add these two links to complete our schema on top of this paragraph:

Assembling a Minimal HOOPS Luminate Application

// 1. Create a resource manager
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
if( !resmgr )
    RC_TEST( RED_FAIL );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();

// 2. Create a window (refer to the window task creation for details):
RED::Object* window = RED::Factory::CreateREDWindow( *resmgr, hwnd, width, height, NULL, rc );
if( !window )
    RC_TEST( RED_FAIL );
RC_TEST( rc );
RED::IWindow* iwindow = window->As< RED::IWindow >();

// 3. Create a viewpoint, add it for display to the window:
RED::Object* viewpoint = RED::Factory::CreateInstance( CID_REDViewpoint );
if( !viewpoint )
    RC_TEST( RED_FAIL );
RED::IViewpoint* iviewpoint = viewpoint->As< RED::IViewpoint >();

RC_TEST( iwindow->InsertViewpoint( viewpoint, iresmgr->GetState() ) );


// Create a shape (a mesh here):
RED::Object* mesh = RED::Factory::CreateInstance( CID_REDMeshShape );
if( !mesh )
    RC_TEST( RED_ALLOC_FAILURE );

RC_TEST( iviewpoint->AddShape( mesh, iresmgr->GetState() ) );

We need to add the viewpoint to the window and a shape to the viewpoint if we want to assemble a complete application able to render something visible. Note that for simplicity, here, we don’t see an intermediate class (the RED::IViewpointRenderList) that is in charge of controlling viewpoint’s viewport, anchoring and display order. This intermediate class is bypassed by the simple helper we use here (RED::IWindow::InsertViewpoint).