Building a REDsdk application

Welcome to REDsdk! This book is one of the first you may want to read to get a practical overview of REDsdk. 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 REDsdk application using the base REDsdk classes (resource manager, windows, viewpoints, ...).

High level product review

Please refer to this page: REDsdk features at a glance for a high level review of REDsdk feature set. This chapter will provide you a summary of REDsdk 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:

Building a REDsdk application cluster

Basic REDsdk objects are detailed in their respective chapters indicated below:

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

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

The minimal set of REDsdk objects needed to run an application

The resource manager is a singleton, that is used to store and manage most resources in a REDsdk 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:

task

Task: 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 REDsdk can't start. If this arise, please check that a fresh REDsdk installation can start, otherwise please check your licensing.

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

task

Task: Creating a REDsdk 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:

task

Task: 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:

task

Task: Assembling a minimal REDsdk 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).