Index: code/plugins/Render/Home/orxRender.c =================================================================== --- code/plugins/Render/Home/orxRender.c (revision 2688) +++ code/plugins/Render/Home/orxRender.c (working copy) @@ -41,6 +41,7 @@ #define orxRENDER_KU32_STATIC_FLAG_READY 0x00000001 /**< Ready flag */ #define orxRENDER_KU32_STATIC_FLAG_RESET_MAXIMA 0x00000002 /**< Reset maxima flag */ +#define orxRENDER_KU32_STATIC_FLAG_TOP_BOTTOM 0x00000004 /**< Top-bottom render order flag */ #define orxRENDER_KU32_STATIC_MASK_ALL 0xFFFFFFFF /**< All mask */ @@ -73,6 +74,7 @@ { orxLINKLIST_NODE stNode; /**< Linklist node : 12 */ orxFLOAT fZ; /**< Z coordinate : 16 */ + orxFLOAT fYmax; /**< Max Y coordinate : 16 */ orxTEXTURE *pstTexture; /**< Texture pointer : 20 */ const orxSHADER *pstShader; /**< Shader pointer : 24 */ orxDISPLAY_BLEND_MODE eBlendMode; /**< Blend mode : 28 */ @@ -1282,6 +1284,8 @@ const orxSHADER *pstShader; orxSHADERPOINTER *pstShaderPointer; orxRENDER_NODE *pstNode; + orxOBOX stBoundingBox; + orxAABOX stExtrema; /* Gets shader pointer */ pstShaderPointer = orxOBJECT_GET_STRUCTURE(pstObject, SHADERPOINTER); @@ -1334,6 +1338,13 @@ /* Stores its Z coordinate */ pstRenderNode->fZ = vObjectPos.fZ; + /* Stores its Y maximum for top-bottom rendering */ + if(sstRender.u32Flags & orxRENDER_KU32_STATIC_FLAG_TOP_BOTTOM) { + orxObject_GetBoundingBox(pstObject, &stBoundingBox); + orxOBox_GetExtrema(&stExtrema, &stBoundingBox); + pstRenderNode->fYmax = stExtrema.vBR.fY; + } + /* Stores its depth coef */ pstRenderNode->fDepthCoef = fDepthCoef; @@ -1350,13 +1361,17 @@ (pstNode != orxNULL) && ((vObjectPos.fZ < pstNode->fZ) || ((vObjectPos.fZ == pstNode->fZ) - && ((pstTexture < pstNode->pstTexture) - || ((pstTexture == pstNode->pstTexture) - && ((pstShader < pstNode->pstShader) - || ((pstShader == pstNode->pstShader) - && (eBlendMode < pstNode->eBlendMode)) - || ((eBlendMode == pstNode->eBlendMode) - && (eSmoothing < pstNode->eSmoothing))))))); + && (((pstRenderNode->fYmax > pstNode->fYmax) + && (sstRender.u32Flags & orxRENDER_KU32_STATIC_FLAG_TOP_BOTTOM)) + || (((pstRenderNode->fYmax == pstNode->fYmax) + || !(sstRender.u32Flags & orxRENDER_KU32_STATIC_FLAG_TOP_BOTTOM)) + && ((pstTexture < pstNode->pstTexture) + || ((pstTexture == pstNode->pstTexture) + && ((pstShader < pstNode->pstShader) + || ((pstShader == pstNode->pstShader) + && (eBlendMode < pstNode->eBlendMode)) + || ((eBlendMode == pstNode->eBlendMode) + && (eSmoothing < pstNode->eSmoothing))))))))); pstNode = (orxRENDER_NODE *)orxLinkList_GetNext(&(pstNode->stNode))); /* End of list reached? */ @@ -1787,6 +1802,7 @@ { /* Cleans static controller */ orxMemory_Zero(&sstRender, sizeof(orxRENDER_STATIC)); + sstRender.u32Flags = orxRENDER_KU32_STATIC_FLAG_NONE; /* Creates rendering bank */ sstRender.pstRenderBank = orxBank_Create(orxRENDER_KU32_ORDER_BANK_SIZE, sizeof(orxRENDER_NODE), orxBANK_KU32_FLAG_NONE, orxMEMORY_TYPE_MAIN); @@ -1810,6 +1826,13 @@ orxClock_SetModifier(sstRender.pstClock, orxCLOCK_MOD_TYPE_MAXED, (fMinFrequency > orxFLOAT_0) ? (orxFLOAT_1 / fMinFrequency) : orxRENDER_KF_TICK_SIZE); } + /* Top-bottom rendering order enabled? */ + if((orxConfig_HasValue(orxRENDER_KZ_CONFIG_TOP_BOTTOM) == orxTRUE) + && (orxConfig_GetBool(orxRENDER_KZ_CONFIG_TOP_BOTTOM) == orxTRUE)) + { + sstRender.u32Flags |= orxRENDER_KU32_STATIC_FLAG_TOP_BOTTOM; + } + /* Pops config section */ orxConfig_PopSection(); @@ -1847,7 +1870,7 @@ if(eResult != orxSTATUS_FAILURE) { /* Inits Flags */ - sstRender.u32Flags = orxRENDER_KU32_STATIC_FLAG_READY; + sstRender.u32Flags |= orxRENDER_KU32_STATIC_FLAG_READY; } else { Index: code/include/render/orxRender.h =================================================================== --- code/include/render/orxRender.h (revision 2688) +++ code/include/render/orxRender.h (working copy) @@ -57,6 +57,7 @@ #define orxRENDER_KZ_CONFIG_SHOW_FPS "ShowFPS" #define orxRENDER_KZ_CONFIG_SHOW_PROFILER "ShowProfiler" #define orxRENDER_KZ_CONFIG_MIN_FREQUENCY "MinFrequency" +#define orxRENDER_KZ_CONFIG_TOP_BOTTOM "TopBottom" /** Event enum Index: code/include/math/orxOBox.h =================================================================== --- code/include/math/orxOBox.h (revision 2688) +++ code/include/math/orxOBox.h (working copy) @@ -46,6 +46,7 @@ #include "orxInclude.h" #include "math/orxVector.h" +#include "math/orxAABox.h" /** Public oriented box structure @@ -376,6 +377,44 @@ return bResult; } +/** Calculate an axis aligned bounding box (AABox) around given oriented bounding box (OBox) + * @param[in] _pstRes Resulting axis aligned bounding box + * @param[in] _pstBox Input oriented bounding box + * @return AABox that bounds the input OBox + */ +static orxINLINE orxAABOX* orxOBox_GetExtrema(orxAABOX* _pstRes, const orxOBOX *_pstBox) +{ + orxVECTOR vCorner[4]; + orxVECTOR vTL; + orxVECTOR vBR; + + /* Calculate the world positions of four corners of the _pstBox */ + orxVector_Sub(&vCorner[0], &(_pstBox->vPosition), &(_pstBox->vPivot)); + orxVector_Sub(&vCorner[1], orxVector_Add(&vCorner[1], &(_pstBox->vPosition), &(_pstBox->vX)), &(_pstBox->vPivot)); + orxVector_Sub(&vCorner[2], orxVector_Add(&vCorner[2], &(_pstBox->vPosition), &(_pstBox->vY)), &(_pstBox->vPivot)); + orxVector_Add(&vCorner[3], &(_pstBox->vPosition), orxVector_Add(&vCorner[3], &(_pstBox->vX), &(_pstBox->vY))); + orxVector_Sub(&vCorner[3], &vCorner[3], &(_pstBox->vPivot)); + + /* Set the minimum and maximum X,Y values to the position of Local CS origin in World CS */ + vTL.fX = vCorner[0].fX; + vBR.fX = vTL.fX; + vTL.fY = vCorner[0].fY; + vBR.fY = vTL.fY; + + /* Find the minimum and maximum X,Y values */ + orxU32 i; + for(i=1; i<4; i++) { + if(vTL.fX > vCorner[i].fX) vTL.fX = vCorner[i].fX; + if(vBR.fX < vCorner[i].fX) vBR.fX = vCorner[i].fX; + if(vTL.fY > vCorner[i].fY) vTL.fY = vCorner[i].fY; + if(vBR.fY < vCorner[i].fY) vBR.fY = vCorner[i].fY; + } + + orxAABox_Set(_pstRes, &vTL, &vBR); + + return _pstRes; +} + #endif /* _orxOBOX_H_ */ /** @} */