Home

Resume

Blog

Teikitu


// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//  »Project«   Teikitu Gaming System (TgS) (∂)
//  »File«      TgS Render - Resource [Mesh].c
//  »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
//  »Version«   4.0
// ------------------------------------------------------------------------------------------------------------------------------ //
//  Copyright: © 2002-2010, Andrew Aye.  All Rights Reserved.
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
// == Render ==================================================================================================================== //

// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  File Local Functions and Variables
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

static TgRN_MESH_ID                         tgRN_Init_Mesh_Internal( C_TgUINT32, C_ETgRN_ALLOCATOR, PC_STg2_Input );




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  Public Functions
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

// ---- tgRN_Load_Mesh ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRN_MESH_ID tgRN_Load_Mesh( C_ETgRN_ALLOCATOR enAllocator, C_TgUINT32 uiHash, PC_STg2_Input psIN, C_TgUINTPTR uiParam0,
    TgVOID (*pfnCallback)( C_TgUINTPTR, C_TgRN_MESH_ID ) )
{
    C_TgRN_MESH_ID tiRet = tgRN_Init_Mesh_Internal( uiHash, enAllocator, psIN );

    if (!tgRN_MESH_ID_Is_Valid( &tiRet ))
    {
        TgLOGF( ETgCON_CHANEL_ERROR, TgT("%-16.16s(%-32.32s): [Fail] %-32.32s\n"), TgT("Render"), TgT("Mesh"),
            psIN->m_pszName ? psIN->m_pszName : TgT("") );
        return (KTgINVALID_RN_MESH_ID);
    };

#if TgS_STAT_RENDER
    g_uiRN_Stats_Memory_Mesh += g_uiRN_Size_Mesh[tiRet.m.iI];
#endif

#if TgS_DEBUG_RENDER
    TgLOGF( ETgCON_CHANEL_LOADING, TgT("%-16.16s(%-32.32s): [Load] %-32.32s          | id(% 4d) | % -9d BY\n"), TgT("Render"),
        TgT("Mesh"), psIN->m_pszName ? psIN->m_pszName : TgT(""), tiRet.m.iI, g_uiRN_Size_Mesh[tiRet.m.iI] );
#endif

#if TgS_DEBUG_RENDER && !defined(TGS_FINAL)
    if (0 != psIN->m_pszName) {
        tgSZ_Copy( g_szRN_Mesh[tiRet.m.iI], ETgRESOURCE_NAME_MAX, psIN->m_pszName ? psIN->m_pszName : TgT("") );
    } else {
        g_szRN_Mesh[tiRet.m.iI][0] = 0;
    };
#endif

    if (0 != pfnCallback)
    {
        pfnCallback( uiParam0, tiRet );
    };

    return (tiRet);
}


// ---- tgRN_Instance_Mesh ------------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRN_MESH_ID tgRN_Instance_Mesh( C_TgRN_MESH_ID tiMH )
{
    tgCM_UTM_SN_Lock_Spin( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );

    if (!tgRN_MESH_ID_Is_Valid( &tiMH ) || !tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ))
    {
        tgCM_UTM_SN_Signal( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );
        TgLOGF( ETgCON_CHANEL_WARNING, TgT("%-16.16s(%-32.32s): %-48.48s\n"), TgT("Render"), TgT("Mesh Instance"),
            TgT("Failed to find mesh to instance") );
        return (KTgINVALID_RN_MESH_ID);
    };

    ++g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef;
    tgCM_UTM_SN_Signal( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );
    return (tiMH);
}


// ---- tgRN_Hash_Instance_Mesh ------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRN_MESH_ID tgRN_Hash_Instance_Mesh( C_TgUINT32 uiHash )
{
    TgSINT32                            iIndex;

    if (KTgEMPTY_HASH == uiHash)
    {
        return (KTgINVALID_RN_MESH_ID);
    };

    tgCM_UTM_SN_Lock_Spin( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );

    for (iIndex = 0; iIndex < ETgRN_MAX_MESH; ++iIndex)
    {
        if (uiHash != g_uiRN_Hash_Mesh[iIndex])
        {
            continue;
        };

        ++g_asRN_Lib_Mesh_Data[iIndex].m_nuiRef;
        tgCM_UTM_SN_Signal( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );
        return (g_asRN_Lib_Mesh_Data[iIndex].m_tiMH);
    };

    tgCM_UTM_SN_Signal( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );
    TgLOGF( ETgCON_CHANEL_WARNING, TgT("%-16.16s(%-32.32s): %-48.48s\n"), TgT("Render"), TgT("Mesh Instance"),
        TgT("Failed to find mesh to instance") );
    return (KTgINVALID_RN_MESH_ID);
}


// ---- tgRN_Query_Mesh_Min_BA -------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVEC_F32_04 tgRN_Query_Mesh_Min_BA( C_TgRN_MESH_ID tiMH )
{
    TgASSERT((TgUINT32)tiMH.m.iI < ETgRN_MAX_MESH && 0u > g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef);
    TgASSERT_PARAM(tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ));
    return (g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_vMin_BA);
}


// ---- tgRN_Query_Mesh_Max_BA -------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVEC_F32_04 tgRN_Query_Mesh_Max_BA( C_TgRN_MESH_ID tiMH )
{
    TgASSERT((TgUINT32)tiMH.m.iI < ETgRN_MAX_MESH && 0u > g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef);
    TgASSERT_PARAM(tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ));
    return (g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_vMax_BA);
}




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  Internal Functions
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

// ---- tgRN_Load_Mesh_Internal ------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgRN_Load_Mesh_Internal( C_TgRN_MESH_ID tiMS, C_ETgRN_ALLOCATOR enAllocator, PC_STg2_Input psIN )
{
    return (TgE_FAIL);
}


// ---- tgRN_Release_Mesh ------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgUINT32 tgRN_Release_Mesh( C_TgRN_MESH_ID tiMH )
{
    TgUINT32                            nuiRef;

    TgASSERT_PARAM((TgUINT32)tiMH.m.iI < ETgRN_MAX_MESH && tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ));
    TgASSERT(0u > g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef);

    tgCM_UTM_SN_Lock_Spin( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );

    nuiRef = g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef - 1;
    --g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef;

    if (0 == nuiRef)
    {
    #if TgS_STAT_RENDER
        g_uiRN_Stats_Memory_Texture -= g_uiRN_Size_Mesh[tiMH.m.iI];
    #endif

    #if TgS_DEBUG_RENDER
    #if defined(TGS_FINAL)
        TgLOGF( ETgCON_CHANEL_LOADING, TgT("%-16.16s(%-32.32s): [Free] %-32.32s          | id(% 4d) | % -9d BY\n"), TgT("Render"),
            TgT("Texture Image"), TgT(""), tiMH.m.iI, g_uiRN_Size_Mesh[tiMH.m.iI] );
    #else
        TgLOGF( ETgCON_CHANEL_LOADING, TgT("%-16.16s(%-32.32s): [Free] %-32.32s          | id(% 4d) | % -9d BY\n"), TgT("Render"),
            TgT("Texture Image"), g_szRN_Mesh[tiMH.m.iI], tiMH.m.iI, g_uiRN_Size_Mesh[tiMH.m.iI] );
    #endif
    #endif

        g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH = KTgINVALID_RN_MESH_ID;
        g_uiRN_Hash_Mesh[tiMH.m.iI] = KTgEMPTY_HASH;
        tgAM_WRITE_FENCE();
        tgCM_UTM_SN_Signal( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );

        tgRN_Free_Mesh( tiMH );
        tgCM_UTM_ARRAY_Free_ID( &g_sRN_Lib_Mesh, tiMH.m.iI );
    }
    else
    {
        tgCM_UTM_SN_Signal( &g_sRN_Lib_Mesh_Ref_Lock.m_sLock );
    };

    return (nuiRef);
}


// ---- tgRN_Free_Mesh ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgRN_Free_Mesh( C_TgRN_MESH_ID tiMH )
{
    TgASSERT((TgUINT32)tiMH.m.iI < ETgRN_MAX_MESH && 0u > g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef);
    TgASSERT_PARAM(tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ));

    tgRN_PM_Free_Mesh( tiMH );
}


// ---- tgRN_Get_Mesh =---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
P_STg2_RN_Mesh tgRN_Get_Mesh( C_TgRN_MESH_ID tiMH )
{
    TgASSERT((TgUINT32)tiMH.m.iI < ETgRN_MAX_MESH && 0u > g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef);
    TgASSERT_PARAM(tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ));

    return (g_asRN_Lib_Mesh_Data + tiMH.m.iI);
}


// ---- tgRN_Query_Mesh --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
CP_STg2_RN_Mesh tgRN_Query_Mesh( C_TgRN_MESH_ID tiMH )
{
    TgASSERT((TgUINT32)tiMH.m.iI < ETgRN_MAX_MESH && 0u > g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_nuiRef);
    TgASSERT_PARAM(tgEQ_RN_MESH_ID( &tiMH, &g_asRN_Lib_Mesh_Data[tiMH.m.iI].m_tiMH ));

    return (g_asRN_Lib_Mesh_Data + tiMH.m.iI);
}




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  File Local Functions and Variables
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

// ---- tgRN_Init_Mesh_Internal ------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
static TgRN_MESH_ID tgRN_Init_Mesh_Internal( C_TgUINT32 uiHash, C_ETgRN_ALLOCATOR enAllocator, PC_STg2_Input psIN )
{
    // Name of a texture is assumed to be an unique key.  Thus, if it exists already the texture is assumed to be instanced.

    C_TgRN_MESH_ID                      tiFound = tgRN_Hash_Instance_Mesh( uiHash );

    TgASSERT( ETgRN_ALLOCATOR_INVALID != enAllocator );

    if (tgRN_MESH_ID_Is_Valid( &tiFound ))
    {
        return (tiFound);
    }
    else
    {
        C_TgSINT32                          iID = tgCM_UTM_ARRAY_Get_Next_ID( &g_sRN_Lib_Mesh );
        TgRESULT                            iResult;

        if (0 > iID)
        {
            return (KTgINVALID_RN_MESH_ID);
        };

        TgASSERT(g_uiRN_Hash_Mesh[iID] == KTgEMPTY_HASH);

        // Clear the texture aggregate for use.
        g_asRN_Lib_Mesh_Data[iID].m_nuiRef = 0;
        g_asRN_Lib_Mesh_Data[iID].m_uiLoD = 0;
        g_asRN_Lib_Mesh_Data[iID].m_vMin_BA = KTgV_ZERO_F32_04;
        g_asRN_Lib_Mesh_Data[iID].m_vMax_BA = KTgV_ZERO_F32_04;
        g_asRN_Lib_Mesh_Data[iID].m_uiLastTouch = 0;
        g_asRN_Lib_Mesh_Data[iID].m_uiPriority = 0;
        g_asRN_Lib_Mesh_Data[iID].m_enAllocator = enAllocator;
        g_asRN_Lib_Mesh_Data[iID].m_niSection = 0;
        memset( g_asRN_Lib_Mesh_Data[iID].m_asSection, 0, sizeof(g_asRN_Lib_Mesh_Data[iID].m_asSection) );

        tgInit_RN_MESH_ID( &g_asRN_Lib_Mesh_Data[iID].m_tiMH, iID );
        tgRN_PM_Init_Mesh( g_asRN_Lib_Mesh_Data[iID].m_tiMH );

        // Use the loader to initialize the texture
        iResult = tgRN_Load_Mesh_Internal( g_asRN_Lib_Mesh_Data[iID].m_tiMH, enAllocator, psIN );

        // Check for failure, and return the id to the usage pool before returning with an error state.
        if (TgFAILED(iResult))
        {
            tgCM_UTM_ARRAY_Free_ID( &g_sRN_Lib_Mesh, iID );
            return (KTgINVALID_RN_MESH_ID);
        };

        // Store the texture name and hash.  The name can later be omitted for final builds to reduce footprint assuming a unique
        // one to one and onto mapping between hash and name.
        tgAM_WRITE_FENCE();
        TgASSERT(1 == g_asRN_Lib_Mesh_Data[iID].m_nuiRef);
        g_uiRN_Hash_Mesh[iID] = uiHash;

        return (g_asRN_Lib_Mesh_Data[iID].m_tiMH);
    }
}