############
Hello World!
############


***********
Description
***********

This tutorial uses high-level HOOPS Luminate API to build a very simple scene and demonstrates matrix-based animation.

The mesh data are created using the ``RED::IMeshShape`` interface which provides some helpers to create basic primitives:

.. code:: cpp

    // Scene creation:
    // ---------------

    // Create a torus and a plane.
    RED::Object* torus = RED::Factory::CreateInstance( CID_REDMeshShape );
    if( torus == NULL )
        RC_TEST( RED_ALLOC_FAILURE );

    RED::IMeshShape* itorus = torus->As< RED::IMeshShape >();
    RC_TEST( itorus->Torus( RED::Vector3( 0, 0, 8 ), 20.f, 8.f, 64, 64, iresmgr->GetState() ) );

    RED::Object* plane = RED::Factory::CreateInstance( CID_REDMeshShape );
    if( plane == NULL )
        RC_TEST( RED_ALLOC_FAILURE );

    RED::IMeshShape* iplane = plane->As< RED::IMeshShape >();
    RC_TEST( iplane->Quad( RED::Vector3( 0, 0, 0 ), 100.f, 100.f, iresmgr->GetState() ) );

    // Compute the plan tangent vectors to apply bump mapping on it.
    RC_TEST( iplane->BuildTangents( RED::MCL_USER0, RED::MCL_TEX0, iresmgr->GetState() ) );


Note that we call ``RED::IMeshShape::BuildTangents`` on the plane mesh in order to compute plane tangents vector. Those vectors are required when bump mapping is applied to a geometry.
Materials are then created for each geometry, based on the HOOPS Luminate Generic material (see ``RED::IMaterial::SetupGenericMaterial``):

.. code:: cpp

    // Create materials.
    RED::Object* mat_torus;
    RC_TEST( iresmgr->CreateMaterial( mat_torus, iresmgr->GetState() ) );

    RED::IMaterial* imat = mat_torus->As< RED::IMaterial >();

    RED::LayerSet ls = RED::LayerSet::ALL_LAYERS;
    RC_TEST( imat->SetupGenericMaterial( false, false,                                           
                                        RED::Color::BLACK, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                        RED::Color( 0.1f, 0.25f, 0.5f ), NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                        RED::Color( 0.1f, 0.25f, 0.5f ), NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                        RED::Color::BLACK, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 0.f,
                                        RED::Color( 0.4f ), NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 0.f,
                                        true, false,
                                        NULL, RED::Matrix::IDENTITY,
                                        1.f, true,
                                        RED::Color::BLACK, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 0.f,
                                        NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, RED::MCL_USER0,
                                        &ls, NULL,
                                        RFK::TutorialApplication::GetResourceManager(), iresmgr->GetState() ) );

    RC_TEST( torus->As< RED::IShape >()->SetMaterial( mat_torus, iresmgr->GetState() ) )


    RED::Object* mat_plane;
    RC_TEST( iresmgr->CreateMaterial( mat_plane, iresmgr->GetState() ) );

    imat = mat_plane->As< RED::IMaterial >();

    RED::Object* bump = NULL, *texture = NULL;
    RC_TEST( iresmgr->CreateImage2D( bump, iresmgr->GetState() ) );
    RC_TEST( RED::ImageTools::Load( bump, "../resources/bump.jpg", RED::FMT_RGB, false, false, RED::TGT_TEX_2D, iresmgr->GetState() ) );

    RC_TEST( iresmgr->CreateImage2D( texture, iresmgr->GetState() ) );
    RC_TEST( RED::ImageTools::Load( texture, "../resources/hello_grid.png", RED::FMT_RGB, false, false, RED::TGT_TEX_2D, iresmgr->GetState() ) );

    // Bump textures are normal maps in RED. So, we convert the texture to a valid 
    // normal map before using it as a bump texture.
    RC_TEST( bump->As< RED::IImage2D >()->NormalMap( RED::FMT_RGB, RED::TGT_TEX_2D, 0.85f, bump, iresmgr->GetState() ) );

    RED::Matrix tex_mat;
    tex_mat.Scale( 4.f );
    RC_TEST( imat->SetupGenericBumpyDiffuseMaterial( false, 
                                                    RED::Color::GREY, texture, tex_mat, RED::MCL_TEX0, 
                                                    bump, tex_mat, RED::MCL_TEX0, RED::MCL_USER0,
                                                    &ls, NULL, 
                                                    RFK::TutorialApplication::GetResourceManager(), iresmgr->GetState() ) );

    RC_TEST( plane->As< RED::IShape >()->SetMaterial( mat_plane, iresmgr->GetState() ) );

We are almost done as we just need to build a light and a camera before being able to render our scene. This is covered in :doc:`/tasks/ta_ca/ta_ca_light/tk_setup_a_spot_light` and in :doc:`/tasks/ta_ca/ta_ca_application/tk_setting_up_a_simple_camera`.

The framework automatically sends a ``RFK::EVT_UPDATE`` event each time the main loop is evaluated. This is the perfect signal to handle to update our light animation. To catch this event, we simply register a custom callback on it:

.. code:: cpp

    RFK::TutorialApplication::SetEventCallback( RFK::EVT_UPDATE, OnIdle );

Then, in the OnIdle callback, we implement a basic light rotation using a time-based rotation matrix:

.. code:: cpp 

    RED::ILightShape* ilight = light->As< RED::ILightShape >();

    RED::Vector3 pos, newpos;
    RED::Vector3 sight, newsight;
    RED::Vector3 top, newtop;
    RED::Vector3 right, newright;

    RC_TEST( ilight->GetPos( pos ) );
    RC_TEST( ilight->GetSight( sight ) );
    RC_TEST( ilight->GetTop( top ) );
    RC_TEST( ilight->GetRight( right ) );

    RED::Matrix mrot;
    mrot.RotationAxisMatrix( RED::Vector3( 30.0f, 0.0f, 0.0f ), RED::Vector3( 0.0f, 0.0f, 1.0f ), 0.001f * ( RFK::TutorialApplication::GetTime() - time_elapsed ) );
    time_elapsed = RFK::TutorialApplication::GetTime();

    newpos = mrot * pos;
    newsight = mrot.RotateNormalize( sight );
    newtop = mrot.RotateNormalize( top );
    newright = mrot.RotateNormalize( right );

    RC_TEST( ilight->SetPos( newpos, iresmgr->GetState() ) );
    RC_TEST( ilight->SetSight( newsight, iresmgr->GetState() ) );
    RC_TEST( ilight->SetTop( newtop, iresmgr->GetState() ) );
    RC_TEST( ilight->SetRight( newright, iresmgr->GetState() ) );

.. figure:: wf_HelloWorld_details.jpg 
  :align: center
  
  **Bump mapping as well as environmental mapping are amongst the various effects natively supported by HOOPS Luminate.**
