Example #1
0
/// Perform a non-blocking attempt to sync with an asynchronous shader variant load request.
///
/// @param[in]  loadId      Load request ID.
/// @param[out] rspVariant  Smart pointer set to the variant reference if loading has completed.
///
/// @return  True if loading has completed, false if not.  Note that if this returns true, the load request ID will
///          no longer be valid for its current load request and should not be reused.
///
/// @see BeginLoadVariant()
bool Shader::TryFinishLoadVariant( size_t loadId, ShaderVariantPtr& rspVariant )
{
    HELIUM_ASSERT( IsValid( loadId ) );

    // Use the try-finish-load override if one is registered.
    if( sm_pTryFinishLoadVariantOverride )
    {
        bool bFinished = sm_pTryFinishLoadVariantOverride( sm_pVariantLoadOverrideData, loadId, rspVariant );

        return bFinished;
    }

    // Attempt to sync the object load request.
    GameObjectLoader* pObjectLoader = GameObjectLoader::GetStaticInstance();
    HELIUM_ASSERT( pObjectLoader );

    GameObjectPtr spObject;
    bool bFinished = pObjectLoader->TryFinishLoad( loadId, spObject );
    if( bFinished )
    {
        rspVariant = Reflect::AssertCast< ShaderVariant >( spObject.Get() );
    }

    return bFinished;
}
Example #2
0
/// @copydoc Serializer::SerializeObjectReference()
void BinarySerializer::SerializeObjectReference( const GameObjectType* /*pType*/, GameObjectPtr& rspObject )
{
    if( ShouldSerializeCurrentProperty() )
    {
        HELIUM_ASSERT( m_bAllowObjectReferences );
        if( !m_bAllowObjectReferences )
        {
            HELIUM_TRACE(
                TRACE_ERROR,
                ( TXT( "BinarySerializer: Attempted to serialize an object reference using a serializer with " )
                TXT( "which it is not allowed.\n" ) ) );

            return;
        }

        uint32_t objectIndex;
        SetInvalid( objectIndex );

        GameObject* pObject = rspObject.Get();
        if( pObject )
        {
            objectIndex = ResolveObjectDependency( pObject->GetPath() );
            HELIUM_ASSERT( IsValid( objectIndex ) );
        }

        m_pPropertyStream->Write( &objectIndex, sizeof( objectIndex ), 1 );
    }
}
Example #3
0
/// Modify the name, owner, or instance index of this object.
///
/// @param[in] rParameters  Object rename parameters.
///
/// @return  True if this object was renamed successfully, false if not.
///
/// @see GetName(), GetOwner(), GetInstanceIndex()
bool GameObject::Rename( const RenameParameters& rParameters )
{
    Name name = rParameters.name;
    GameObject* pOwner = rParameters.spOwner;
    uint32_t instanceIndex = rParameters.instanceIndex;

    HELIUM_TRACE(
        TraceLevels::Debug,
        TXT("GameObject::Rename(): Renaming object \"%s\" to \"%s\" (Old Owner: \"%s\". New Owner: \"%s\".)\n"),
        *m_name,
        *rParameters.name,
        m_spOwner.ReferencesObject() ? *m_spOwner->GetPath().ToString() : TXT("[none]"),
        rParameters.spOwner.ReferencesObject() ? *rParameters.spOwner->GetPath().ToString() : TXT("[none]"));

    // Only allow setting an empty name if no owner or instance index are given and this object has no children.
    if( name.IsEmpty() )
    {
        HELIUM_ASSERT( !pOwner );
        HELIUM_ASSERT( IsInvalid( instanceIndex ) );
        if( pOwner || IsValid( instanceIndex ) )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                ( TXT( "GameObject::Rename(): Objects cannot have name information cleared if being assigned an " )
                  TXT( "owner or instance index.\n" ) ) );

            return false;
        }

        HELIUM_ASSERT( !m_wpFirstChild );
        if( m_wpFirstChild )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "GameObject::Rename(): Cannot clear name information for objects with children.\n" ) );

            return false;
        }
    }

    // Don't allow setting the owner to ourself.
    if( pOwner == this )
    {
        HELIUM_TRACE( TraceLevels::Error, TXT( "GameObject::Rename(): Cannot set the owner of an object to itself.\n" ) );

        return false;
    }

    // Don't allow setting the owner to an object with no name information.
    if( pOwner && pOwner->m_name.IsEmpty() )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "GameObject::Rename(): Cannot set the owner of an object to an object with no path information.\n" ) );

        return false;
    }

    if( IsPackage() )
    {
        // Don't allow package objects to be children of non-package objects.
        if( pOwner && !pOwner->IsPackage() )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "GameObject::Rename(): Cannot set a non-package as the owner of a package.\n" ) );

            return false;
        }

        // Don't allow instance indexing for packages.
        if( IsValid( instanceIndex ) )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "GameObject::Rename(): Instance indexing not supported for packages.\n" ) );

            return false;
        }
    }

    // Don't need to do anything if the name, owner, and instance index are not changing.
    if( name == m_name &&
        pOwner == m_spOwner &&
        ( instanceIndex == m_instanceIndex || ( instanceIndex == INSTANCE_INDEX_AUTO && IsValid( m_instanceIndex ) ) ) )
    {
        return true;
    }

    // Hold onto a reference to the current owner until we return from this function.  This is done in case this object
    // has the last strong reference to it, in which case we would encounter a deadlock if clearing its reference while
    // we still have a write lock on the object list (object destruction also requires acquiring a write lock).
    GameObjectPtr spOldOwner = m_spOwner;

    {
        // Acquire a write lock on the object list to prevent objects from being added and removed as well as keep
        // objects from being renamed while this object is being renamed.
        ScopeWriteLock scopeLock( sm_objectListLock );

        // Get the list of children belonging to the new owner.
        GameObjectWPtr& rwpOwnerFirstChild = ( pOwner ? pOwner->m_wpFirstChild : sm_wpFirstTopLevelObject );

        // Don't check for name clashes if we're clearing the object path name information.
        if( !name.IsEmpty() )
        {
            // Resolve name clashes either through the instance index lookup map (if an instance index will be assigned)
            // or through a child object search (if no instance index will be used).
            if( IsValid( instanceIndex ) )
            {
                // Get the instance index map for the requested object name.
                ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap();
                HELIUM_ASSERT( sm_pEmptyNameInstanceIndexMap );
                HELIUM_ASSERT( sm_pEmptyInstanceIndexSet );

                sm_pEmptyNameInstanceIndexMap->First() = ( pOwner ? pOwner->GetPath() : GameObjectPath( NULL_NAME ) );
                sm_pEmptyInstanceIndexSet->First() = name;

                ChildNameInstanceIndexMap::Accessor childNameMapAccessor;
                rNameInstanceIndexMap.Insert( childNameMapAccessor, *sm_pEmptyNameInstanceIndexMap );

                NameInstanceIndexMap::Accessor indexSetAccessor;
                childNameMapAccessor->Second().Insert( indexSetAccessor, *sm_pEmptyInstanceIndexSet );

                InstanceIndexSet& rIndexSet = indexSetAccessor->Second();
                InstanceIndexSet::ConstAccessor indexAccessor;

                if( instanceIndex == INSTANCE_INDEX_AUTO )
                {
                    // Pick an unused instance index.
                    instanceIndex = 0;
                    while( !rIndexSet.Insert( indexAccessor, instanceIndex ) )
                    {
                        ++instanceIndex;
                        HELIUM_ASSERT( instanceIndex < INSTANCE_INDEX_AUTO );
                    }
                }
                else
                {
                    // Attempt to acquire the specified instance index.
                    if( !rIndexSet.Insert( indexAccessor, instanceIndex ) )
                    {
                        HELIUM_TRACE(
                            TraceLevels::Error,
                            ( TXT( "GameObject::Rename(): Object already exists with the specified owner (%s), name " )
                              TXT( "(%s), and instance index (%" ) TPRIu32 TXT( ").\n" ) ),
                            ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ),
                            *name,
                            instanceIndex );

                        return false;
                    }
                }
            }
            else
            {
                // Check each child of the new owner for a name clash.
                for( GameObject* pChild = rwpOwnerFirstChild; pChild != NULL; pChild = pChild->m_wpNextSibling )
                {
                    if( pChild->m_name == name && pChild->m_instanceIndex == instanceIndex )
                    {
                        HELIUM_TRACE(
                            TraceLevels::Error,
                            ( TXT( "GameObject::Rename(): Object already exists with the specified owner (%s) and " )
                              TXT( "name (%s).\n" ) ),
                            ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ),
                            *name );

                        return false;
                    }
                }
            }
        }

        // Remove any old instance index tracking for the old path name.
        if( IsValid( m_instanceIndex ) )
        {
            GameObjectPath ownerPath = ( spOldOwner ? spOldOwner->GetPath() : GameObjectPath( NULL_NAME ) );

            ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap();

            ChildNameInstanceIndexMap::Accessor childMapAccessor;
            HELIUM_VERIFY( rNameInstanceIndexMap.Find( childMapAccessor, ownerPath ) );

            NameInstanceIndexMap& rNameMap = childMapAccessor->Second();
            NameInstanceIndexMap::Accessor nameMapAccessor;
            HELIUM_VERIFY( rNameMap.Find( nameMapAccessor, m_name ) );

            InstanceIndexSet& rIndexSet = nameMapAccessor->Second();
            HELIUM_VERIFY( rIndexSet.Remove( m_instanceIndex ) );

            /*
            if( rIndexSet.IsEmpty() )
            {
                HELIUM_VERIFY( rNameMap.Remove( nameMapAccessor ) );
                if( rNameMap.IsEmpty() )
                {
                    HELIUM_VERIFY( rNameInstanceIndexMap.Remove( childMapAccessor ) );
                }
            }
            */
        }

        // If the owner of this object is changing, remove this object from its old owner's list and add it to the new
        // owner.
        if( spOldOwner.Get() != pOwner || ( m_name.IsEmpty() ? !name.IsEmpty() : name.IsEmpty() ) )
        {
            // Object should not be in any child object lists if its name is empty.
            if( !m_name.IsEmpty() )
            {
                GameObjectWPtr& rwpOldOwnerFirstChild =
                    ( spOldOwner ? spOldOwner->m_wpFirstChild : sm_wpFirstTopLevelObject );

                GameObject* pPreviousChild = NULL;
                GameObject* pChild = rwpOldOwnerFirstChild;
                while( pChild )
                {
                    if( pChild == this )
                    {
                        ( pPreviousChild ? pPreviousChild->m_wpNextSibling : rwpOldOwnerFirstChild ) = m_wpNextSibling;
                        m_wpNextSibling.Release();

                        break;
                    }

                    pPreviousChild = pChild;
                    pChild = pChild->m_wpNextSibling;
                }
            }

            HELIUM_ASSERT( !m_wpNextSibling );

            // Only store the object in a child object list if it is being given a valid name.
            if( !name.IsEmpty() )
            {
                m_wpNextSibling = rwpOwnerFirstChild;
                rwpOwnerFirstChild = this;
            }
        }

        // Set the new path name.
        m_name = name;
        m_spOwner = pOwner;
        m_instanceIndex = instanceIndex;

        // Update path information for this object and its children.
        UpdatePath();
    }

    return true;
}
Example #4
0
/// Initialize all resources provided by this manager.
///
/// @see Shutdown(), PostConfigUpdate()
void RenderResourceManager::Initialize()
{
    // Release any existing resources.
    Shutdown();

    // Get the renderer and graphics configuration.
    Renderer* pRenderer = Renderer::GetStaticInstance();
    if( !pRenderer )
    {
        return;
    }

    Config& rConfig = Config::GetStaticInstance();
    StrongPtr< GraphicsConfig > spGraphicsConfig(
        rConfig.GetConfigObject< GraphicsConfig >( Name( TXT( "GraphicsConfig" ) ) ) );
    if( !spGraphicsConfig )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "RenderResourceManager::Initialize(): Initialization failed; missing GraphicsConfig.\n" ) );

        return;
    }

    // Create the standard rasterizer states.
    RRasterizerState::Description rasterizerStateDesc;

    rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_SOLID;
    rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK;
    rasterizerStateDesc.winding = RENDERER_WINDING_CLOCKWISE;
    rasterizerStateDesc.depthBias = 0;
    rasterizerStateDesc.slopeScaledDepthBias = 0.0f;
    m_rasterizerStates[ RASTERIZER_STATE_DEFAULT ] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
    HELIUM_ASSERT( m_rasterizerStates[ RASTERIZER_STATE_DEFAULT ] );

    rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_NONE;
    m_rasterizerStates[ RASTERIZER_STATE_DOUBLE_SIDED ] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
    HELIUM_ASSERT( m_rasterizerStates[ RASTERIZER_STATE_DOUBLE_SIDED ] );

    rasterizerStateDesc.depthBias = 1;
    rasterizerStateDesc.slopeScaledDepthBias = 2.0f;
    m_rasterizerStates[ RASTERIZER_STATE_SHADOW_DEPTH ] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
    HELIUM_ASSERT( m_rasterizerStates[ RASTERIZER_STATE_SHADOW_DEPTH ] );

    rasterizerStateDesc.depthBias = 0;
    rasterizerStateDesc.slopeScaledDepthBias = 0.0f;
    rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_WIREFRAME;
    m_rasterizerStates[ RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED ] = pRenderer->CreateRasterizerState(
        rasterizerStateDesc );
    HELIUM_ASSERT( m_rasterizerStates[ RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED ] );

    rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK;
    m_rasterizerStates[ RASTERIZER_STATE_WIREFRAME ] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
    HELIUM_ASSERT( m_rasterizerStates[ RASTERIZER_STATE_WIREFRAME ] );

    // Create the standard blend states.
    RBlendState::Description blendStateDesc;

    blendStateDesc.bBlendEnable = false;
    m_blendStates[ BLEND_STATE_OPAQUE ] = pRenderer->CreateBlendState( blendStateDesc );
    HELIUM_ASSERT( m_blendStates[ BLEND_STATE_OPAQUE ] );

    blendStateDesc.colorWriteMask = 0;
    m_blendStates[ BLEND_STATE_NO_COLOR ] = pRenderer->CreateBlendState( blendStateDesc );
    HELIUM_ASSERT( m_blendStates[ BLEND_STATE_NO_COLOR ] );

    blendStateDesc.colorWriteMask = RENDERER_COLOR_WRITE_MASK_FLAG_ALL;
    blendStateDesc.bBlendEnable = true;

    blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_SRC_ALPHA;
    blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_INV_SRC_ALPHA;
    blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD;
    m_blendStates[ BLEND_STATE_TRANSPARENT ] = pRenderer->CreateBlendState( blendStateDesc );
    HELIUM_ASSERT( m_blendStates[ BLEND_STATE_TRANSPARENT ] );

    blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_ONE;
    blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ONE;
    m_blendStates[ BLEND_STATE_ADDITIVE ] = pRenderer->CreateBlendState( blendStateDesc );
    HELIUM_ASSERT( m_blendStates[ BLEND_STATE_ADDITIVE ] );

    blendStateDesc.function = RENDERER_BLEND_FUNCTION_REVERSE_SUBTRACT;
    m_blendStates[ BLEND_STATE_SUBTRACTIVE ] = pRenderer->CreateBlendState( blendStateDesc );
    HELIUM_ASSERT( m_blendStates[ BLEND_STATE_SUBTRACTIVE ] );

    blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_DEST_COLOR;
    blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ZERO;
    blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD;
    m_blendStates[ BLEND_STATE_MODULATE ] = pRenderer->CreateBlendState( blendStateDesc );
    HELIUM_ASSERT( m_blendStates[ BLEND_STATE_MODULATE ] );

    // Create the standard depth/stencil states.
    RDepthStencilState::Description depthStateDesc;

    depthStateDesc.stencilWriteMask = 0;
    depthStateDesc.bStencilTestEnable = false;

    depthStateDesc.depthFunction = RENDERER_COMPARE_FUNCTION_LESS_EQUAL;
    depthStateDesc.bDepthTestEnable = true;
    depthStateDesc.bDepthWriteEnable = true;
    m_depthStencilStates[ DEPTH_STENCIL_STATE_DEFAULT ] = pRenderer->CreateDepthStencilState( depthStateDesc );
    HELIUM_ASSERT( m_depthStencilStates[ DEPTH_STENCIL_STATE_DEFAULT ] );

    depthStateDesc.bDepthWriteEnable = false;
    m_depthStencilStates[ DEPTH_STENCIL_STATE_TEST_ONLY ] = pRenderer->CreateDepthStencilState( depthStateDesc );
    HELIUM_ASSERT( m_depthStencilStates[ DEPTH_STENCIL_STATE_TEST_ONLY ] );

    depthStateDesc.bDepthTestEnable = false;
    m_depthStencilStates[ DEPTH_STENCIL_STATE_NONE ] = pRenderer->CreateDepthStencilState( depthStateDesc );
    HELIUM_ASSERT( m_depthStencilStates[ DEPTH_STENCIL_STATE_NONE ] );

    // Create the standard sampler states that are not dependent on configuration settings.
    RSamplerState::Description samplerStateDesc;
    samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_MIN_POINT_MAG_POINT_MIP_POINT;
    samplerStateDesc.addressModeW = RENDERER_TEXTURE_ADDRESS_MODE_CLAMP;
    samplerStateDesc.mipLodBias = 0;
    samplerStateDesc.maxAnisotropy = spGraphicsConfig->GetMaxAnisotropy();

    for( size_t addressModeIndex = 0; addressModeIndex < RENDERER_TEXTURE_ADDRESS_MODE_MAX; ++addressModeIndex )
    {
        ERendererTextureAddressMode addressMode = static_cast< ERendererTextureAddressMode >( addressModeIndex );
        samplerStateDesc.addressModeU = addressMode;
        samplerStateDesc.addressModeV = addressMode;
        samplerStateDesc.addressModeW = addressMode;

        m_samplerStates[ TEXTURE_FILTER_POINT ][ addressModeIndex ] = pRenderer->CreateSamplerState(
            samplerStateDesc );
        HELIUM_ASSERT( m_samplerStates[ TEXTURE_FILTER_POINT ][ addressModeIndex ] );
    }

    // Create the standard set of mesh vertex descriptions.
    RVertexDescription::Element vertexElements[ 6 ];

    vertexElements[ 0 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_3;
    vertexElements[ 0 ].semantic = RENDERER_VERTEX_SEMANTIC_POSITION;
    vertexElements[ 0 ].semanticIndex = 0;
    vertexElements[ 0 ].bufferIndex = 0;

    vertexElements[ 1 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 1 ].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
    vertexElements[ 1 ].semanticIndex = 0;
    vertexElements[ 1 ].bufferIndex = 0;

    vertexElements[ 2 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
    vertexElements[ 2 ].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
    vertexElements[ 2 ].semanticIndex = 0;
    vertexElements[ 2 ].bufferIndex = 0;

    vertexElements[ 3 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2;
    vertexElements[ 3 ].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
    vertexElements[ 3 ].semanticIndex = 1;
    vertexElements[ 3 ].bufferIndex = 0;

    m_spSimpleVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 2 );
    HELIUM_ASSERT( m_spSimpleVertexDescription );

    m_spSimpleTexturedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 );
    HELIUM_ASSERT( m_spSimpleTexturedVertexDescription );

    m_spProjectedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 4 );
    HELIUM_ASSERT( m_spProjectedVertexDescription );

    vertexElements[ 1 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 1 ].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL;
    vertexElements[ 1 ].semanticIndex = 0;
    vertexElements[ 1 ].bufferIndex = 0;

    vertexElements[ 2 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 2 ].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT;
    vertexElements[ 2 ].semanticIndex = 0;
    vertexElements[ 2 ].bufferIndex = 0;

    vertexElements[ 3 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 3 ].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
    vertexElements[ 3 ].semanticIndex = 0;
    vertexElements[ 3 ].bufferIndex = 0;

    vertexElements[ 4 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
    vertexElements[ 4 ].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
    vertexElements[ 4 ].semanticIndex = 0;
    vertexElements[ 4 ].bufferIndex = 0;

    vertexElements[ 5 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
    vertexElements[ 5 ].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
    vertexElements[ 5 ].semanticIndex = 1;
    vertexElements[ 5 ].bufferIndex = 0;

    m_staticMeshVertexDescriptions[ 0 ] = pRenderer->CreateVertexDescription( vertexElements, 5 );
    HELIUM_ASSERT( m_staticMeshVertexDescriptions[ 0 ] );

    m_staticMeshVertexDescriptions[ 1 ] = pRenderer->CreateVertexDescription( vertexElements, 6 );
    HELIUM_ASSERT( m_staticMeshVertexDescriptions[ 1 ] );

    vertexElements[ 1 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 1 ].semantic = RENDERER_VERTEX_SEMANTIC_BLENDWEIGHT;
    vertexElements[ 1 ].semanticIndex = 0;
    vertexElements[ 1 ].bufferIndex = 0;

    vertexElements[ 2 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4;
    vertexElements[ 2 ].semantic = RENDERER_VERTEX_SEMANTIC_BLENDINDICES;
    vertexElements[ 2 ].semanticIndex = 0;
    vertexElements[ 2 ].bufferIndex = 0;

    vertexElements[ 3 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 3 ].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL;
    vertexElements[ 3 ].semanticIndex = 0;
    vertexElements[ 3 ].bufferIndex = 0;

    vertexElements[ 4 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 4 ].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT;
    vertexElements[ 4 ].semanticIndex = 0;
    vertexElements[ 4 ].bufferIndex = 0;

    vertexElements[ 5 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
    vertexElements[ 5 ].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
    vertexElements[ 5 ].semanticIndex = 0;
    vertexElements[ 5 ].bufferIndex = 0;

    m_spSkinnedMeshVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 6 );
    HELIUM_ASSERT( m_spSkinnedMeshVertexDescription );

    vertexElements[ 0 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2;
    vertexElements[ 0 ].semantic = RENDERER_VERTEX_SEMANTIC_POSITION;
    vertexElements[ 0 ].semanticIndex = 0;
    vertexElements[ 0 ].bufferIndex = 0;

    vertexElements[ 1 ].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
    vertexElements[ 1 ].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
    vertexElements[ 1 ].semanticIndex = 0;
    vertexElements[ 1 ].bufferIndex = 0;

    vertexElements[ 2 ].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
    vertexElements[ 2 ].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
    vertexElements[ 2 ].semanticIndex = 0;
    vertexElements[ 2 ].bufferIndex = 0;

    m_spScreenVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 );
    HELIUM_ASSERT( m_spScreenVertexDescription );

    // Create configuration-dependent render resources.
    PostConfigUpdate();

    // Attempt to load the depth-only pre-pass shader.
#pragma TODO( "XXX TMC: Migrate to a more data-driven solution." )
    GameObjectLoader* pObjectLoader = GameObjectLoader::GetStaticInstance();
    HELIUM_ASSERT( pObjectLoader );

    GameObjectPath prePassShaderPath;
    HELIUM_VERIFY( prePassShaderPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "PrePass.hlsl" ) ) );

    GameObjectPtr spPrePassShader;
    HELIUM_VERIFY( pObjectLoader->LoadObject( prePassShaderPath, spPrePassShader ) );

    Shader* pPrePassShader = Reflect::SafeCast< Shader >( spPrePassShader.Get() );
    HELIUM_ASSERT( pPrePassShader );
    if( pPrePassShader )
    {
        size_t loadId = pPrePassShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pPrePassShader->TryFinishLoadVariant( loadId, m_spPrePassVertexShader ) )
            {
                pObjectLoader->Tick();
            }
        }
    }

    // Attempt to load the simple world-space, simple screen-space, and screen-space text shaders.
#pragma TODO( "XXX TMC: Migrate to a more data-driven solution." )
    GameObjectPath shaderPath;
    GameObjectPtr spShader;
    Shader* pShader;

    HELIUM_VERIFY( shaderPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "Simple.hlsl" ) ) );

    HELIUM_VERIFY( pObjectLoader->LoadObject( shaderPath, spShader ) );

    pShader = Reflect::SafeCast< Shader >( spShader.Get() );
    HELIUM_ASSERT( pShader );
    if( pShader )
    {
        size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpaceVertexShader ) )
            {
                pObjectLoader->Tick();
            }
        }

        loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpacePixelShader ) )
            {
                pObjectLoader->Tick();
            }
        }
    }

    HELIUM_VERIFY( shaderPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "ScreenSpaceTexture.hlsl" ) ) );

    HELIUM_VERIFY( pObjectLoader->LoadObject( shaderPath, spShader ) );

    pShader = Reflect::SafeCast< Shader >( spShader.Get() );
    HELIUM_ASSERT( pShader );
    if( pShader )
    {
        size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpaceVertexShader ) )
            {
                pObjectLoader->Tick();
            }
        }

        loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpacePixelShader ) )
            {
                pObjectLoader->Tick();
            }
        }
    }

    HELIUM_VERIFY( shaderPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "ScreenText.hlsl" ) ) );

    HELIUM_VERIFY( pObjectLoader->LoadObject( shaderPath, spShader ) );

    pShader = Reflect::SafeCast< Shader >( spShader.Get() );
    HELIUM_ASSERT( pShader );
    if( pShader )
    {
        size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextVertexShader ) )
            {
                pObjectLoader->Tick();
            }
        }

        loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
        HELIUM_ASSERT( IsValid( loadId ) );
        if( IsValid( loadId ) )
        {
            while( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextPixelShader ) )
            {
                pObjectLoader->Tick();
            }
        }
    }

    // Attempt to load the debug fonts.
#pragma TODO( "XXX TMC: Migrate to a more data-driven solution." )
    GameObjectPath fontPath;
    GameObjectPtr spFont;

    HELIUM_VERIFY( fontPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Fonts" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "DebugSmall" ) ) );
    HELIUM_VERIFY( pObjectLoader->LoadObject( fontPath, spFont ) );
    m_debugFonts[ DEBUG_FONT_SIZE_SMALL ] = Reflect::SafeCast< Font >( spFont.Get() );
    spFont.Release();

    HELIUM_VERIFY( fontPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Fonts" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "DebugMedium" ) ) );
    HELIUM_VERIFY( pObjectLoader->LoadObject( fontPath, spFont ) );
    m_debugFonts[ DEBUG_FONT_SIZE_MEDIUM ] = Reflect::SafeCast< Font >( spFont.Get() );
    spFont.Release();

    HELIUM_VERIFY( fontPath.Set(
        HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Fonts" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "DebugLarge" ) ) );
    HELIUM_VERIFY( pObjectLoader->LoadObject( fontPath, spFont ) );
    m_debugFonts[ DEBUG_FONT_SIZE_LARGE ] = Reflect::SafeCast< Font >( spFont.Get() );
    spFont.Release();
}
Example #5
0
/// Create the default world instance.
///
/// @param[in] pType  World type.
///
/// @return  Default world instance.
World* WorldManager::CreateDefaultWorld( const GameObjectType* pType )
{
    HELIUM_ASSERT( pType );
    if( !pType )
    {
        HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): No world type specified.\n" ) );

        return NULL;
    }

    bool bIsWorldType = pType->GetClass()->IsType( World::GetStaticType()->GetClass() );
    HELIUM_ASSERT( bIsWorldType );
    if( !bIsWorldType )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "WorldManager::CreateDefaultWorld(): Type \"%s\" specified is not a World subtype.\n" ),
            *pType->GetName() );

        return NULL;
    }

    HELIUM_ASSERT( m_spWorldPackage );
    if( !m_spWorldPackage )
    {
        HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): World manager has not been initialized.\n" ) );

        return NULL;
    }

    HELIUM_ASSERT( m_worlds.IsEmpty() );
    if( !m_worlds.IsEmpty() )
    {
        HELIUM_TRACE( TRACE_ERROR, TXT( "WorldManager::CreateDefaultWorld(): Default world has already been created.\n" ) );

        return NULL;
    }

    GameObjectPtr spDefaultWorldObject;
    bool bCreateResult = GameObject::CreateObject(
        spDefaultWorldObject,
        pType,
        GetDefaultWorldName(),
        m_spWorldPackage );
    HELIUM_ASSERT( bCreateResult );
    if( !bCreateResult )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "WorldManager::CreateDefaultWorld(): Failed to create world of type \"%s\".\n" ),
            *pType->GetName() );

        return NULL;
    }

    WorldPtr spDefaultWorld( Reflect::AssertCast< World >( spDefaultWorldObject.Get() ) );
    HELIUM_ASSERT( spDefaultWorld );

    m_worlds.Push( spDefaultWorld );

    return spDefaultWorld;
}