diff options
Diffstat (limited to '')
-rw-r--r-- | src/render/Shadows.cpp | 1265 |
1 files changed, 996 insertions, 269 deletions
diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 8c892be3..a964ceb6 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -7,6 +7,7 @@ #include "Timecycle.h" #include "CutsceneMgr.h" #include "Automobile.h" +#include "Bike.h" #include "Ped.h" #include "PlayerPed.h" #include "World.h" @@ -18,7 +19,12 @@ #endif #include "PointLights.h" #include "SpecialFX.h" +#include "Script.h" +#include "TimeStep.h" #include "Shadows.h" +#include "CutsceneObject.h" +#include "CutsceneShadow.h" +#include "Clock.h" #ifdef DEBUGMENU SETTWEAKPATH("Shadows"); @@ -30,6 +36,8 @@ RwImVertexIndex ShadowIndexList[24]; RwTexture *gpShadowCarTex; RwTexture *gpShadowPedTex; RwTexture *gpShadowHeliTex; +RwTexture *gpShadowBikeTex; +RwTexture *gpShadowBaronTex; RwTexture *gpShadowExplosionTex; RwTexture *gpShadowHeadLightsTex; RwTexture *gpOutline1Tex; @@ -37,7 +45,6 @@ RwTexture *gpOutline2Tex; RwTexture *gpOutline3Tex; RwTexture *gpBloodPoolTex; RwTexture *gpReflectionTex; -RwTexture *gpGoalMarkerTex; RwTexture *gpWalkDontTex; RwTexture *gpCrackedGlassTex; RwTexture *gpPostShadowTex; @@ -59,37 +66,39 @@ CShadows::Init(void) int32 slut = CTxdStore::FindTxdSlot("particle"); CTxdStore::SetCurrentTxd(slut); - gpShadowCarTex = RwTextureRead("shad_car", NULL); - gpShadowPedTex = RwTextureRead("shad_ped", NULL); - gpShadowHeliTex = RwTextureRead("shad_heli", NULL); - gpShadowExplosionTex = RwTextureRead("shad_exp", NULL); - gpShadowHeadLightsTex = RwTextureRead("headlight", NULL); - gpOutline1Tex = RwTextureRead("outline_64", NULL); - gpOutline2Tex = RwTextureRead("outline2_64", NULL); - gpOutline3Tex = RwTextureRead("outline3_64", NULL); - gpBloodPoolTex = RwTextureRead("bloodpool_64", NULL); - gpReflectionTex = RwTextureRead("reflection01", NULL); - gpGoalMarkerTex = RwTextureRead("goal", NULL); - gpWalkDontTex = RwTextureRead("walk_dont", NULL); - gpCrackedGlassTex = RwTextureRead("wincrack_32", NULL); - gpPostShadowTex = RwTextureRead("lamp_shad_64", NULL); + gpShadowCarTex = RwTextureRead("shad_car", nil); + gpShadowPedTex = RwTextureRead("shad_ped", nil); + gpShadowHeliTex = RwTextureRead("shad_heli", nil); + gpShadowBikeTex = RwTextureRead("shad_bike", nil); + gpShadowBaronTex = RwTextureRead("shad_rcbaron", nil); + gpShadowExplosionTex = RwTextureRead("shad_exp", nil); + gpShadowHeadLightsTex = RwTextureRead("headlight", nil); + gpOutline1Tex = RwTextureRead("outline_64", nil); + gpOutline2Tex = RwTextureRead("outline2_64", nil); + gpOutline3Tex = RwTextureRead("outline3_64", nil); + gpBloodPoolTex = RwTextureRead("bloodpool_64", nil); + gpReflectionTex = RwTextureRead("reflection01", nil); + gpWalkDontTex = RwTextureRead("walk_dont", nil); + gpCrackedGlassTex = RwTextureRead("wincrack_32", nil); + gpPostShadowTex = RwTextureRead("lamp_shad_64", nil); CTxdStore::PopCurrentTxd(); - ASSERT(gpShadowCarTex != NULL); - ASSERT(gpShadowPedTex != NULL); - ASSERT(gpShadowHeliTex != NULL); - ASSERT(gpShadowExplosionTex != NULL); - ASSERT(gpShadowHeadLightsTex != NULL); - ASSERT(gpOutline1Tex != NULL); - ASSERT(gpOutline2Tex != NULL); - ASSERT(gpOutline3Tex != NULL); - ASSERT(gpBloodPoolTex != NULL); - ASSERT(gpReflectionTex != NULL); - ASSERT(gpGoalMarkerTex != NULL); - ASSERT(gpWalkDontTex != NULL); - ASSERT(gpCrackedGlassTex != NULL); - ASSERT(gpPostShadowTex != NULL); + ASSERT(gpShadowCarTex != nil); + ASSERT(gpShadowPedTex != nil); + ASSERT(gpShadowHeliTex != nil); + ASSERT(gpShadowBikeTex != nil); + ASSERT(gpShadowBaronTex != nil); + ASSERT(gpShadowExplosionTex != nil); + ASSERT(gpShadowHeadLightsTex != nil); + ASSERT(gpOutline1Tex != nil); + ASSERT(gpOutline2Tex != nil); + ASSERT(gpOutline3Tex != nil); + ASSERT(gpBloodPoolTex != nil); + ASSERT(gpReflectionTex != nil); + ASSERT(gpWalkDontTex != nil); + ASSERT(gpCrackedGlassTex != nil); + ASSERT(gpPostShadowTex != nil); ShadowIndexList[0] = 0; @@ -128,7 +137,7 @@ CShadows::Init(void) for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ ) { aStaticShadows[i].m_nId = 0; - aStaticShadows[i].m_pPolyBunch = NULL; + aStaticShadows[i].m_pPolyBunch = nil; } pEmptyBunchList = &aPolyBunches[0]; @@ -136,7 +145,7 @@ CShadows::Init(void) for ( int32 i = 0; i < MAX_POLYBUNCHES; i++ ) { if ( i == MAX_POLYBUNCHES - 1 ) - aPolyBunches[i].m_pNext = NULL; + aPolyBunches[i].m_pNext = nil; else aPolyBunches[i].m_pNext = &aPolyBunches[i + 1]; } @@ -150,24 +159,27 @@ CShadows::Init(void) void CShadows::Shutdown(void) { - ASSERT(gpShadowCarTex != NULL); - ASSERT(gpShadowPedTex != NULL); - ASSERT(gpShadowHeliTex != NULL); - ASSERT(gpShadowExplosionTex != NULL); - ASSERT(gpShadowHeadLightsTex != NULL); - ASSERT(gpOutline1Tex != NULL); - ASSERT(gpOutline2Tex != NULL); - ASSERT(gpOutline3Tex != NULL); - ASSERT(gpBloodPoolTex != NULL); - ASSERT(gpReflectionTex != NULL); - ASSERT(gpGoalMarkerTex != NULL); - ASSERT(gpWalkDontTex != NULL); - ASSERT(gpCrackedGlassTex != NULL); - ASSERT(gpPostShadowTex != NULL); + ASSERT(gpShadowCarTex != nil); + ASSERT(gpShadowPedTex != nil); + ASSERT(gpShadowHeliTex != nil); + ASSERT(gpShadowBikeTex != nil); + ASSERT(gpShadowBaronTex != nil); + ASSERT(gpShadowExplosionTex != nil); + ASSERT(gpShadowHeadLightsTex != nil); + ASSERT(gpOutline1Tex != nil); + ASSERT(gpOutline2Tex != nil); + ASSERT(gpOutline3Tex != nil); + ASSERT(gpBloodPoolTex != nil); + ASSERT(gpReflectionTex != nil); + ASSERT(gpWalkDontTex != nil); + ASSERT(gpCrackedGlassTex != nil); + ASSERT(gpPostShadowTex != nil); RwTextureDestroy(gpShadowCarTex); RwTextureDestroy(gpShadowPedTex); RwTextureDestroy(gpShadowHeliTex); + RwTextureDestroy(gpShadowBikeTex); + RwTextureDestroy(gpShadowBaronTex); RwTextureDestroy(gpShadowExplosionTex); RwTextureDestroy(gpShadowHeadLightsTex); RwTextureDestroy(gpOutline1Tex); @@ -175,7 +187,6 @@ CShadows::Shutdown(void) RwTextureDestroy(gpOutline3Tex); RwTextureDestroy(gpBloodPoolTex); RwTextureDestroy(gpReflectionTex); - RwTextureDestroy(gpGoalMarkerTex); RwTextureDestroy(gpWalkDontTex); RwTextureDestroy(gpCrackedGlassTex); RwTextureDestroy(gpPostShadowTex); @@ -187,8 +198,8 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale) { - ASSERT(pTexture != NULL); - ASSERT(pPosn != NULL); + ASSERT(pTexture != nil); + ASSERT(pPosn != nil); // find free slot @@ -215,36 +226,39 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo } } -void +bool CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D(); - if ( SQR(fDrawDistance) > fDistToCamSqr) + if ( SQR(fDrawDistance) > fDistToCamSqr || fDrawDistance == 0.0f ) { - float fDistToCam = Sqrt(fDistToCamSqr); - - if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) + if ( fDrawDistance != 0.0f ) { - //fDistToCam == 0 -> 4 - //fDistToCam == fDrawDistance -> 0 - float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))); + float fDistToCam = Sqrt(fDistToCamSqr); - nIntensity = (int32)(nIntensity * fMult); - nRed = (int32)(nRed * fMult); - nGreen = (int32)(nGreen * fMult); - nBlue = (int32)(nBlue * fMult); + if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) + { + //fDistToCam == 0 -> 4 + //fDistToCam == fDrawDistance -> 0 + float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))); + + nIntensity = (int32)(nIntensity * fMult); + nRed = (int32)(nRed * fMult); + nGreen = (int32)(nGreen * fMult); + nBlue = (int32)(nBlue * fMult); + } } int32 nSlot; nSlot = 0; - while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != NULL) ) + while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != nil) ) nSlot++; if ( nSlot < MAX_STATICSHADOWS ) @@ -263,8 +277,10 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_fScale = fScale; aStaticShadows[nSlot].m_bTemp = bTempShadow; aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); + + return true; } - else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f + else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f && Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < 0.05f && Abs(pPosn->z - aStaticShadows[nSlot].m_vecPosn.z) < 2.0f @@ -284,6 +300,8 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_fScale = fScale; aStaticShadows[nSlot].m_bTemp = bTempShadow; aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); + + return true; } else { @@ -308,12 +326,14 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); GeneratePolysForStaticShadow(nSlot); + + return aStaticShadows[nSlot].m_pPolyBunch != nil; } } else { nSlot = 0; - while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != NULL ) + while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != nil ) nSlot++; if ( nSlot != MAX_STATICSHADOWS ) @@ -337,9 +357,13 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); GeneratePolysForStaticShadow(nSlot); + + return aStaticShadows[nSlot].m_pPolyBunch != nil; } } } + + return true; } void @@ -347,7 +371,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); switch ( ShadowTexture ) { @@ -361,7 +385,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -371,7 +395,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -381,7 +405,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -391,7 +415,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowHeliTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -401,7 +425,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowHeadLightsTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -410,8 +434,8 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, { StoreShadowToBeRendered(SHADOWTYPE_DARK, gpBloodPoolTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, - nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + nIntensity, nRed, 150, 0, + 15.0f, false, 1.0f, nil, false); break; } @@ -424,36 +448,39 @@ void CShadows::StoreShadowToBeRendered(uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, - float fZDistance, bool bDrawOnWater, float fScale) + float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings) { - ASSERT(pTexture != NULL); - ASSERT(pPosn != NULL); + ASSERT(pTexture != nil); + ASSERT(pPosn != nil); if ( ShadowsStoredToBeRendered < MAX_STOREDSHADOWS ) { - asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType; - asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture; - asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn; - asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX; - asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY; - asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX; - asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY; - asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity; - asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed; - asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen; - asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue; - asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance; - asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater; - asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale; + asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType; + asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture; + asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn; + asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX; + asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY; + asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX; + asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY; + asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity; + asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed; + asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen; + asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue; + asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance; + asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater; + asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnBuildings = bDrawOnBuildings; + asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale; + asShadowsStored[ShadowsStoredToBeRendered].m_pCutsceneShadow = pShadow; ShadowsStoredToBeRendered++; } } + void -CShadows::StoreShadowForCar(CAutomobile *pCar) +CShadows::StoreShadowForVehicle(CVehicle *pCar, VEH_SHD_TYPE type) { - ASSERT(pCar != NULL); + ASSERT(pCar != nil); if ( CTimeCycle::GetShadowStrength() != 0 ) { @@ -463,7 +490,22 @@ CShadows::StoreShadowForCar(CAutomobile *pCar) if ( CCutsceneMgr::IsRunning() ) fDistToCamSqr /= SQR(TheCamera.LODDistMultiplier) * 4.0f; - float fDrawDistance = 18.0f; + float fDrawDistance; + switch ( type ) + { + case VEH_SHD_TYPE_SEAPLANE: + case VEH_SHD_TYPE_RCPLANE: + fDrawDistance = 144.0f; + break; + + case VEH_SHD_TYPE_HELI: + fDrawDistance = 144.0f; + break; + + default: + fDrawDistance = 18.0f; + break; + } if ( fDistToCamSqr < SQR(fDrawDistance) ) { @@ -471,58 +513,214 @@ CShadows::StoreShadowForCar(CAutomobile *pCar) //fDistToCam == 0 -> 4 //fDistToCam == fDrawDistance -> 0 - float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))) ); + float fMult = 1.0f - (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))) / (fDrawDistance*(1.0f/4.0f)); int32 nColorStrength; if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) - nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult); + nColorStrength = (int32)(fMult * CTimeCycle::GetShadowStrength()); else nColorStrength = CTimeCycle::GetShadowStrength(); - + + float fVehicleHeight = pCar->GetColModel()->boundingBox.GetSize().y; float fVehicleWidth = pCar->GetColModel()->boundingBox.GetSize().x; - - if ( pCar->GetModelIndex() == MI_DODO ) + + float size = 1.0f; + + if ( pCar->GetModelIndex() == MI_HUNTER ) + { + fVehicleWidth *= 3.0f; + fVehicleHeight *= 1.4f; + size *= 0.5f; + } + else if ( pCar->GetModelIndex() == MI_ANGEL ) + { + fVehicleHeight = fVehicleHeight * 1.5f; + size = 0.03f; + } + else if ( pCar->GetModelIndex() == MI_SEASPAR ) + { + fVehicleWidth *= 3.0f; + fVehicleHeight *= 1.4f; + size *= 0.5f; + } + else if ( pCar->GetModelIndex() == MI_PIZZABOY || pCar->GetModelIndex() == MI_PCJ600 || pCar->GetModelIndex() == MI_FAGGIO ) + { + fVehicleHeight *= 1.2f; + size = 0.05f; + } + else if ( pCar->GetModelIndex() == MI_FREEWAY ) + { + fVehicleHeight *= 1.5f; + size = 0.03f; + } + else if ( pCar->GetModelIndex() == MI_RCRAIDER ) + { + fVehicleHeight *= 1.5f; + fVehicleWidth *= 2.0f; + size = 0.2f; + } + else if ( pCar->GetModelIndex() == MI_SANCHEZ ) + { + fVehicleHeight *= 1.5f; + size = 0.03f; + } + else if ( pCar->GetModelIndex() == MI_SPARROW || pCar->GetModelIndex() == MI_MAVERICK || pCar->GetModelIndex() == MI_VCNMAV || pCar->GetModelIndex() == MI_POLMAV ) + { + fVehicleWidth *= 3.0f; + fVehicleHeight *= 1.4f; + size *= 0.5f; + } + else if ( pCar->GetModelIndex() == MI_RCGOBLIN ) + { + fVehicleHeight *= 1.5f; + fVehicleWidth *= 2.0f; + size = 0.2f; + } + else if ( pCar->GetModelIndex() == MI_DODO ) { fVehicleHeight *= 0.9f; fVehicleWidth *= 0.4f; } + + CarPos.x -= pCar->GetForward().x * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size); + CarPos.y -= pCar->GetForward().y * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size); + + RwTexture *tex = gpShadowCarTex; + switch ( type ) + { + case VEH_SHD_TYPE_BIKE: + { + float wheelZ = Abs(((CBike*)pCar)->m_fLeanLRAngle); + float mul = 5.092958f * wheelZ + 1.0f; + if (pCar->GetStatus() == STATUS_PHYSICS) + { + float z = pCar->GetRight().z; + if (z > 0.6f) + mul += 4.0f * z; + } + fVehicleWidth *= mul; + tex = gpShadowBikeTex; + break; + } + + case VEH_SHD_TYPE_HELI: + tex = gpShadowHeliTex; + break; + + case VEH_SHD_TYPE_SEAPLANE: + nColorStrength = CTimeCycle::GetShadowStrength(); + tex = gpShadowBaronTex; + break; + + case VEH_SHD_TYPE_RCPLANE: + tex = gpShadowBaronTex; + fVehicleHeight *= 1.5f; + fVehicleWidth *= 2.2f; + break; + + case VEH_SHD_TYPE_CAR: + tex = gpShadowCarTex; + break; + } + + float frontx = pCar->GetForward().x; + float fronty = pCar->GetForward().y; + float sidex = pCar->GetRight().x; + float sidey = pCar->GetRight().y; + + switch ( type ) + { + case VEH_SHD_TYPE_BIKE: + if ( Abs(pCar->GetRight().z) > 0.6f ) + { + sidex = pCar->GetUp().x; + sidey = pCar->GetUp().y; + } + break; + + case VEH_SHD_TYPE_HELI: + if ( Abs(pCar->GetRight().z) > 0.57f ) + { + sidex = pCar->GetUp().x; + sidey = pCar->GetUp().y; + } + if ( Abs(pCar->GetForward().z) > 0.57f ) + { + frontx = pCar->GetUp().x; + fronty = pCar->GetUp().y; + } + break; + } - CarPos.x -= pCar->GetForward().x * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y); - CarPos.y -= pCar->GetForward().y * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y); - - if ( pCar->GetUp().z > 0.0f ) + bool bDrawOnBuildings = false; + if ( pCar->GetModelIndex() == MI_RCBANDIT + || pCar->GetModelIndex() == MI_RCBARON + || pCar->GetModelIndex() == MI_RCRAIDER + || pCar->GetModelIndex() == MI_RCGOBLIN + || pCar == FindPlayerVehicle() ) { - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos, - pCar->GetForward().x * (fVehicleHeight / 2), - pCar->GetForward().y * (fVehicleHeight / 2), - pCar->GetRight().x * (fVehicleWidth / 2), - pCar->GetRight().y * (fVehicleWidth / 2), - nColorStrength, nColorStrength, nColorStrength, nColorStrength, - 4.5f, false, 1.0f); + bDrawOnBuildings = true; + } + + if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.1f || bDrawOnBuildings ) + { + if ( pCar->GetUp().z > 0.0f ) + { + StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + sidex * (fVehicleWidth / 2), + sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, false, 1.0f, nil, bDrawOnBuildings); + } + else + { + StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + -sidex * (fVehicleWidth / 2), + -sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, false, 1.0f, nil, bDrawOnBuildings); + } } else { - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos, - pCar->GetForward().x * (fVehicleHeight / 2), - pCar->GetForward().y * (fVehicleHeight / 2), - -pCar->GetRight().x * (fVehicleWidth / 2), - -pCar->GetRight().y * (fVehicleWidth / 2), - nColorStrength, nColorStrength, nColorStrength, nColorStrength, - 4.5f, false, 1.0f); + if ( pCar->GetUp().z > 0.0f ) + { + StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + sidex * (fVehicleWidth / 2), + sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, 1.0f, 0.0f, false, 0.1f); + } + else + { + StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + -sidex * (fVehicleWidth / 2), + -sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, 1.0f, 0.0f, false, 0.1f); + } } } } } void -CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, +CShadows::StoreCarLightShadow(CVehicle *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle) { - ASSERT(pCar != NULL); - ASSERT(pPosn != NULL); + ASSERT(pCar != nil); + ASSERT(pPosn != nil); float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D(); @@ -550,31 +748,131 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture, nBlue = (int32)(nBlue * fMult); } - StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn, - fFrontX, fFrontY, - fSideX, fSideY, - 128, nRed, nGreen, nBlue, - 6.0f, false, 1.0f); + if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.4f || pCar == FindPlayerVehicle() ) + { + StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + 128, nRed, nGreen, nBlue, + 6.0f, false, 1.0f, + nil, pCar == FindPlayerVehicle()); + } + else + { + StoreStaticShadow((uintptr)pCar + nID, SHADOWTYPE_ADDITIVE, pTexture, pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + 128, nRed, nGreen, nBlue, + 6.0f, 1.0f, 27.0f, + false, 0.4f); + } + } + } +} + +#ifdef USE_CUTSCENE_SHADOW_FOR_PED +void +StoreShadowForCutscenePedObject(CPed *pObject, float fDisplacementX, float fDisplacementY, + float fFrontX, float fFrontY, float fSideX, float fSideY) +{ + ASSERT(pObject != nil); + + CCutsceneShadow *shadow = pObject->m_pRTShadow; + + if ( shadow == nil ) + return; + + if ( !shadow->IsInitialized() ) + return; + + CVector pos = pObject->GetPosition(); + + float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D(); + + float fDrawDistance = 100.0f; + + if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) ) + { + if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) ) + { + float fDistToCam = Sqrt(fDistToCamSqr); + + float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f))); + int32 nColorStrength; + + if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) ) + nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult); + else + nColorStrength = CTimeCycle::GetShadowStrength(); + + int32 color = int32(nColorStrength * 0.8f); + + pos.x += fDisplacementX; + pos.y += fDisplacementY; + + RwTexture *texture = shadow->GetShadowRwTexture(); + ASSERT(texture); + RwRGBA bordercolor = {0, 0, 0, 0}; + shadow->DrawBorderAroundTexture(bordercolor); + + pos.x -= fDisplacementX; + pos.y -= fDisplacementY; + + float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes + +60*CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f)); + + RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true); + ASSERT(frame); + CVector at(RwFrameGetMatrix(frame)->at); + at.Normalise(); + + CShadows::CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY); + + pos.x -= 2.5f * fDisplacementX; + pos.y -= 2.5f * fDisplacementY; + + CShadows::StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos, + fFrontX * 1.5f, fFrontY * 1.5f, + fSideX * 1.5f, fSideY * 1.5f, + color, color, color, color, + 4.0f, false, 1.0f, shadow, false); } } } +#endif + void CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY) { - ASSERT(pPed != NULL); + ASSERT(pPed != nil); if ( pPed->bIsVisible ) { if ( !(pPed->bInVehicle && pPed->m_nPedState != PED_DRAG_FROM_CAR && pPed->m_nPedState != PED_EXIT_CAR) ) { if ( CTimeCycle::GetShadowStrength() != 0 ) + { +#ifdef USE_CUTSCENE_SHADOW_FOR_PED + CCutsceneShadow *pShadow = pPed->m_pRTShadow; + + if (pShadow) + { + if (pShadow->IsInitialized()) + pShadow->UpdateForCutscene(); + ::StoreShadowForCutscenePedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY); + } + + return; +#endif + StoreShadowForPedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY); + } } } } @@ -582,8 +880,8 @@ CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacemen void CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY) -{ - ASSERT(pPedObject != NULL); +{ + ASSERT(pPedObject != nil); CVector PedPos = pPedObject->GetPosition(); @@ -591,7 +889,7 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo float fDrawDistance = 26.0f; - if ( fDistToCamSqr < SQR(fDrawDistance*0.5f)/*?*/ ) + if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) ) { if ( pPedObject == FindPlayerPed() || TheCamera.IsSphereVisible(PedPos, 2.0f) != false ) { @@ -614,7 +912,80 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo fFrontX, fFrontY, fSideX, fSideY, nColorStrength, nColorStrength, nColorStrength, nColorStrength, - 4.0f, false, 1.0f); + 4.0f, false, 1.0f, nil, pPedObject == FindPlayerPed()); + } + } +} + + +void +CShadows::StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, + float fFrontX, float fFrontY, float fSideX, float fSideY) +{ +#ifdef DISABLE_CUTSCENE_SHADOWS + return; +#endif + ASSERT(pObject != nil); + + CCutsceneShadow *shadow = pObject->m_pShadow; + + if ( shadow == nil ) + return; + + if ( !shadow->IsInitialized() ) + return; + + CVector pos = pObject->GetPosition(); + + float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D(); + + float fDrawDistance = 100.0f; + + if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) ) + { + if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) ) + { + float fDistToCam = Sqrt(fDistToCamSqr); + + float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f))); + int32 nColorStrength; + + if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) ) + nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult); + else + nColorStrength = CTimeCycle::GetShadowStrength(); + + int32 color = int32(nColorStrength * 0.8f); + + pos.x += fDisplacementX; + pos.y += fDisplacementY; + + RwTexture *texture = shadow->GetShadowRwTexture(); + ASSERT(texture); + RwRGBA bordercolor = {0, 0, 0, 0}; + shadow->DrawBorderAroundTexture(bordercolor); + + pos.x -= fDisplacementX; + pos.y -= fDisplacementY; + + float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes+60* + CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f)); + + RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true); + ASSERT(frame); + CVector at(RwFrameGetMatrix(frame)->at); + at.Normalise(); + + CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY); + + pos.x -= 2.5f * fDisplacementX; + pos.y -= 2.5f * fDisplacementY; + + StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos, + fFrontX * 1.5f, fFrontY * 1.5f, + fSideX * 1.5f, fSideY * 1.5f, + color, color, color, color, + 4.0f, false, 1.0f, shadow, false); } } } @@ -622,14 +993,15 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo void CShadows::StoreShadowForTree(CEntity *pTree) { - ASSERT(pTree != NULL); + ASSERT(pTree != nil); } + void CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID) { - ASSERT(pPole != NULL); + ASSERT(pPole != nil); if ( CTimeCycle::GetShadowStrength() != 0 ) { @@ -684,6 +1056,7 @@ CShadows::SetRenderModeForShadowType(uint8 ShadowType) } } + void CShadows::RenderStoredShadows(void) { @@ -692,17 +1065,20 @@ CShadows::RenderStoredShadows(void) RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSCLAMP); + for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ ) asShadowsStored[i].m_nFlags.bRendered = false; + for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ ) { if ( !asShadowsStored[i].m_nFlags.bRendered ) { SetRenderModeForShadowType(asShadowsStored[i].m_ShadowType); - ASSERT(asShadowsStored[i].m_pTexture != NULL); + ASSERT(asShadowsStored[i].m_pTexture != nil); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(asShadowsStored[i].m_pTexture)); @@ -734,39 +1110,112 @@ CShadows::RenderStoredShadows(void) { CSector *pCurSector = CWorld::GetSector(x, y); - ASSERT(pCurSector != NULL); - - CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], - fStartX, fStartY, - fEndX, fEndY, - &shadowPos, - asShadowsStored[j].m_vecFront.x, - asShadowsStored[j].m_vecFront.y, - asShadowsStored[j].m_vecSide.x, - asShadowsStored[j].m_vecSide.y, - asShadowsStored[j].m_nIntensity, - asShadowsStored[j].m_nRed, - asShadowsStored[j].m_nGreen, - asShadowsStored[j].m_nBlue, - asShadowsStored[j].m_fZDistance, - asShadowsStored[j].m_fScale, - NULL); - - CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], - fStartX, fStartY, - fEndX, fEndY, - &shadowPos, - asShadowsStored[j].m_vecFront.x, - asShadowsStored[j].m_vecFront.y, - asShadowsStored[j].m_vecSide.x, - asShadowsStored[j].m_vecSide.y, - asShadowsStored[j].m_nIntensity, - asShadowsStored[j].m_nRed, - asShadowsStored[j].m_nGreen, - asShadowsStored[j].m_nBlue, - asShadowsStored[j].m_fZDistance, - asShadowsStored[j].m_fScale, - NULL); + ASSERT(pCurSector != nil); + + if ( asShadowsStored[j].m_pCutsceneShadow ) + { + CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil, + asShadowsStored[j].m_pCutsceneShadow); + + CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil, + asShadowsStored[j].m_pCutsceneShadow); + } + else if ( asShadowsStored[j].m_nFlags.bDrawOnBuildings ) + { + CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + + CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + } + else + { + CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + + CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + } } } @@ -776,16 +1225,17 @@ CShadows::RenderStoredShadows(void) RenderBuffer::RenderStuffInBuffer(); } - } RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSWRAP); ShadowsStoredToBeRendered = 0; } + void CShadows::RenderStaticShadows(void) { @@ -811,19 +1261,19 @@ CShadows::RenderStaticShadows(void) // optimization trick, render all shadows with same renderstate and texture for ( int32 j = i; j < MAX_STATICSHADOWS; j++ ) { - if ( aStaticShadows[j].m_pPolyBunch != NULL + if ( aStaticShadows[j].m_pPolyBunch != nil && aStaticShadows[i].m_nType == aStaticShadows[j].m_nType && aStaticShadows[i].m_pTexture == aStaticShadows[j].m_pTexture ) { - for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != NULL; bunch = bunch->m_pNext ) + for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != nil; bunch = bunch->m_pNext ) { RwImVertexIndex *pIndexes; RwIm3DVertex *pVerts; RenderBuffer::StartStoring(3 * (bunch->m_nNumVerts - 2), bunch->m_nNumVerts, &pIndexes, &pVerts); - ASSERT(pIndexes != NULL); - ASSERT(pVerts != NULL); + ASSERT(pIndexes != nil); + ASSERT(pVerts != nil); for ( int32 k = 0; k < bunch->m_nNumVerts; k++ ) { @@ -857,6 +1307,7 @@ CShadows::RenderStaticShadows(void) RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); } + void CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) { @@ -883,7 +1334,7 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) { CSector *pCurSector = CWorld::GetSector(x, y); - ASSERT(pCurSector != NULL); + ASSERT(pCurSector != nil); CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], fStartX, fStartY, @@ -914,50 +1365,109 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) } } + void CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); CPtrNode *pNode = PtrList.first; CRect Bound; - while ( pNode != NULL ) + while ( pNode != nil ) { CEntity *pEntity = (CEntity *)pNode->item; uint16 nScanCode = pEntity->m_scanCode; pNode = pNode->next; - ASSERT( pEntity != NULL ); + ASSERT( pEntity != nil ); if ( nScanCode != CWorld::GetCurrentScanCode() ) { - if ( pEntity->bUsesCollision && pEntity->IsBuilding() ) + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + + if ( pEntity->bUsesCollision && !pEntity->m_flagE2 ) { - pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + if ( IsAreaVisible(pEntity->m_area) ) + { + Bound = pEntity->GetBoundRect(); + + if ( fStartX < Bound.right + && fEndX > Bound.left + && fStartY < Bound.bottom + && fEndY > Bound.top ) + { + if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z + && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + { + CastShadowEntityXY(pEntity, + fStartX, fStartY, + fEndX, fEndY, + pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch); + } + } + } + } + } + } +} + + +void +CShadows::CastPlayerShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, + float fFrontX, float fFrontY, float fSideX, float fSideY, + int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, + float fZDistance, float fScale, CPolyBunch **ppPolyBunch) +{ + ASSERT(pPosn != nil); + + CPtrNode *pNode = PtrList.first; + + CRect Bound; + + while ( pNode != nil ) + { + CEntity *pEntity = (CEntity *)pNode->item; + uint16 nScanCode = pEntity->m_scanCode; + pNode = pNode->next; - Bound = pEntity->GetBoundRect(); + ASSERT( pEntity != nil ); - if ( fStartX < Bound.right - && fEndX > Bound.left - && fStartY < Bound.bottom - && fEndY > Bound.top ) + if ( nScanCode != CWorld::GetCurrentScanCode() ) + { + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + + if ( pEntity->bUsesCollision ) + { + if ( IsAreaVisible(pEntity->m_area) ) { - if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z - && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + Bound = pEntity->GetBoundRect(); + + if ( fStartX < Bound.right + && fEndX > Bound.left + && fStartY < Bound.bottom + && fEndY > Bound.top ) { - CastShadowEntity(pEntity, - fStartX, fStartY, - fEndX, fEndY, - pPosn, - fFrontX, fFrontY, - fSideX, fSideY, - nIntensity, nRed, nGreen, nBlue, - fZDistance, fScale, ppPolyBunch); + if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z + && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + { + CastShadowEntityXY(pEntity, + fStartX, fStartY, + fEndX, fEndY, + pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch); + } } } } @@ -965,21 +1475,74 @@ CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, } } + void -CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, +CShadows::CastCutsceneShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, + float fFrontX, float fFrontY, float fSideX, float fSideY, + int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, + float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow) +{ + ASSERT(pPosn != nil); + ASSERT(pShadow != nil); + + CPtrNode *pNode = PtrList.first; + + CRect Bound; + + while ( pNode != nil ) + { + CEntity *pEntity = (CEntity *)pNode->item; + uint16 nScanCode = pEntity->m_scanCode; + pNode = pNode->next; + + ASSERT( pEntity != nil ); + + if ( nScanCode != CWorld::GetCurrentScanCode() ) + { + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + + if ( pEntity->bUsesCollision ) + { + if ( IsAreaVisible(pEntity->m_area) ) + { + Bound = pEntity->GetBoundRect(); + + if ( fStartX < Bound.right + && fEndX > Bound.left + && fStartY < Bound.bottom + && fEndY > Bound.top ) + { + if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z + && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + { + CastShadowEntityXYZ(pEntity, pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch, pShadow); + } + } + } + } + } + } +} + +void +CShadows::CastShadowEntityXY(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch) -{ - ASSERT(pEntity != NULL); - ASSERT(pPosn != NULL); +{ + ASSERT(pEntity != nil); + ASSERT(pPosn != nil); static CVector List [20]; static CVector Texture[20]; static CVector Points [4]; CColModel *pCol = pEntity->GetColModel(); - ASSERT(pCol != NULL); + ASSERT(pCol != nil); #ifndef MASTER if ( gbPrintShite ) @@ -1025,14 +1588,14 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa for ( int32 i = 0; i < pCol->numTriangles; i++ ) { CColTrianglePlane *pColTriPlanes = pCol->trianglePlanes; - ASSERT(pColTriPlanes != NULL); + ASSERT(pColTriPlanes != nil); CVector normal; pColTriPlanes[i].GetNormal(normal); if ( Abs(normal.z) > 0.1f ) { CColTriangle *pColTri = pCol->triangles; - ASSERT(pColTri != NULL); + ASSERT(pColTri != nil); CVector PointA, PointB, PointC; @@ -1432,12 +1995,12 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa } - if ( ppPolyBunch != NULL ) + if ( ppPolyBunch != nil ) { - if ( pEmptyBunchList != NULL ) + if ( pEmptyBunchList != nil ) { CPolyBunch *pBunch = pEmptyBunchList; - ASSERT(pBunch != NULL); + ASSERT(pBunch != nil); pEmptyBunchList = pEmptyBunchList->m_pNext; pBunch->m_pNext = *ppPolyBunch; *ppPolyBunch = pBunch; @@ -1462,8 +2025,8 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa RenderBuffer::StartStoring(3 * (numVerts3 - 2), numVerts3, &pIndexes, &pVerts); - ASSERT(pIndexes != NULL); - ASSERT(pVerts != NULL); + ASSERT(pIndexes != nil); + ASSERT(pVerts != nil); for ( int32 j = 0; j < numVerts3; j++ ) @@ -1487,12 +2050,222 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa } } + +typedef struct _ProjectionParam +{ + RwV3d at; /* Camera at vector */ + RwMatrix invMatrix; /* Transforms to shadow camera space */ + RwUInt8 shadowValue; /* Shadow opacity value */ + RwBool fade; /* Shadow fades with distance */ + RwUInt32 numIm3DBatch; /* Number of buffer flushes */ + RwMatrix entityMatrix; +} +ProjectionParam; + +RwV3d *ShadowRenderTriangleCB(RwV3d *points, RwV3d *normal, ProjectionParam *param) +{ + RwV3d vIn[3]; + RwV3d vShad[3]; + + RwV3dTransformPoints(&vIn[0], points, 3, ¶m->entityMatrix); + + /* + * Reject backfacing triangles + * This reject the triangles parallel to the light as well + */ + if (RwV3dDotProduct(normal, ¶m->at) > 0.0f) + { + return points; + } + + RwV3dTransformPoints(&vShad[0], &vIn[0], 3, ¶m->invMatrix); + + /* + * Reject triangles behind the camera (z test). Note that any world + * triangles lying in front of the camera but before the object may + * have a shadow applied. To minimize such artefacts, this test could + * be modified to use a specific value rather than 0.0f, perhaps + * to reject triangles behind the center plane of the object. + * + * Reject triangles that lie entirely outside the shadow texture range + * (x,y test). + */ + if (((vShad[0].z < 0.0f) && (vShad[1].z < 0.0f) + && (vShad[2].z < 0.0f)) || ((vShad[0].x < 0.0f) + && (vShad[1].x < 0.0f) + && (vShad[2].x < 0.0f)) + || ((vShad[0].x > 1.0f) && (vShad[1].x > 1.0f) + && (vShad[2].x > 1.0f)) || ((vShad[0].y < 0.0f) + && (vShad[1].y < 0.0f) + && (vShad[2].y < 0.0f)) + || ((vShad[0].y > 1.0f) && (vShad[1].y > 1.0f) + && (vShad[2].y > 1.0f))) + { + return points; + } + + RwIm3DVertex *imv = nil; + RwImVertexIndex *imi = nil; + + RenderBuffer::StartStoring(3, 3, &imi, &imv); + + /* + * Set the immediate mode vertices for this triangle + */ + + RwIm3DVertexSetPos(imv, vIn[0].x, vIn[0].y, vIn[0].z); + RwIm3DVertexSetPos(imv + 1, vIn[1].x, vIn[1].y, vIn[1].z); + RwIm3DVertexSetPos(imv + 2, vIn[2].x, vIn[2].y, vIn[2].z); + + RwIm3DVertexSetU(imv, vShad[0].x); + RwIm3DVertexSetU(imv + 1, vShad[1].x); + RwIm3DVertexSetU(imv + 2, vShad[2].x); + + RwIm3DVertexSetV(imv, vShad[0].y); + RwIm3DVertexSetV(imv + 1, vShad[1].y); + RwIm3DVertexSetV(imv + 2, vShad[2].y); + + /* + * Do we fade out the shadow with distance? + */ + if (param->fade) + { + RwReal fadeVal; + RwUInt8 val; + + fadeVal = 1.0f - vShad[0].z * vShad[0].z; + val = + (fadeVal < + 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue); + RwIm3DVertexSetRGBA(imv, val, val, val, val); + + fadeVal = 1.0f - vShad[1].z * vShad[1].z; + val = + (fadeVal < + 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue); + RwIm3DVertexSetRGBA(imv + 1, val, val, val, val); + + fadeVal = 1.0f - vShad[2].z * vShad[2].z; + val = + (fadeVal < + 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue); + RwIm3DVertexSetRGBA(imv + 2, val, val, val, val); + } + else + { + RwUInt8 val = param->shadowValue; + + RwIm3DVertexSetRGBA(imv, val, val, val, val); + RwIm3DVertexSetRGBA(imv + 1, val, val, val, val); + RwIm3DVertexSetRGBA(imv + 2, val, val, val, val); + } + + /* + * Update buffer position + */ + imi[0] = 0; + imi[1] = 1; + imi[2] = 2; + + RenderBuffer::StopStoring(); + + return points; +} + +void +CShadows::CastShadowEntityXYZ(CEntity *pEntity, CVector *pPosn, + float fFrontX, float fFrontY, float fSideX, float fSideY, + int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, + float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow) +{ + ASSERT(pEntity != nil); + ASSERT(pPosn != nil); + + if ( pShadow ) + { + ProjectionParam proj; + RwV3d scl; + RwV3d tr; + + CShadowCamera *shadow = pShadow->GetShadowCamera(); + CColModel *collision = pEntity->GetColModel(); + + CCollision::CalculateTrianglePlanes(collision); + + RwMatrix mat; + mat = *RwFrameGetMatrix(RwCameraGetFrame(shadow->GetRwCamera())); + + RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; + + RwMatrixRotate(&mat, &Xaxis, -45.0f, rwCOMBINEPRECONCAT); + + proj.at = mat.at; + pEntity->GetMatrix().CopyToRwMatrix(&proj.entityMatrix); + + RwMatrixInvert(&proj.invMatrix, &mat); + RwReal radius = RwCameraGetViewWindow(shadow->GetRwCamera())->x; + + scl.x = scl.y = -0.5f / (radius*0.9f); + scl.z = 1.0f / (radius*0.8f); + RwMatrixScale(&proj.invMatrix, &scl, rwCOMBINEPOSTCONCAT); + + tr.x = 0.5f; + tr.y = tr.z = 0.0f; + RwMatrixTranslate(&proj.invMatrix, &tr, rwCOMBINEPOSTCONCAT); + + proj.shadowValue = nIntensity; + proj.fade = 0; + + RwMatrix matrix; + pEntity->GetMatrix().CopyToRwMatrix(&matrix); + RwMatrix invMatrix; + RwMatrixInvert(&invMatrix, &matrix); + + + CVector center(pShadow->GetBaseSphere().center); + center += CVector(-fFrontX * 1.1f, -fFrontY * 1.1f, -0.5f); + + CSphere sphere; + sphere.Set(2.0f, center); + + RwV3d point; + RwV3dTransformPoints(&point, center, 1, &invMatrix); + + CColSphere colSphere; + colSphere.Set(2.0f, CVector(point), 0, 0); + + int i = 0; + while ( i < collision->numTriangles ) + { + CVector p[3]; + + collision->GetTrianglePoint(p[0], collision->triangles[i].a); + collision->GetTrianglePoint(p[1], collision->triangles[i].b); + collision->GetTrianglePoint(p[2], collision->triangles[i].c); + + if ( CCollision::TestSphereTriangle(colSphere, collision->vertices, collision->triangles[i], collision->trianglePlanes[i]) ) + { + CVector n(collision->trianglePlanes[i].GetNormalX(), collision->trianglePlanes[i].GetNormalY(), collision->trianglePlanes[i].GetNormalZ()); + CVector offset = n * 0.028f; + + p[0] += offset; + p[1] += offset; + p[2] += offset; + + if ( !ShadowRenderTriangleCB((RwV3d *)p, n, &proj) ) + break; + } + i++; + } + } +} + void CShadows::UpdateStaticShadows(void) { for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ ) { - if ( aStaticShadows[i].m_pPolyBunch != NULL && !aStaticShadows[i].m_bJustCreated + if ( aStaticShadows[i].m_pPolyBunch != nil && !aStaticShadows[i].m_bJustCreated && (!aStaticShadows[i].m_bTemp || CTimer::GetTimeInMilliseconds() > aStaticShadows[i].m_nTimeCreated + 5000) ) { aStaticShadows[i].Free(); @@ -1515,13 +2288,14 @@ CShadows::UpdatePermanentShadows(void) aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; else { + bool bOk; if ( timePassed >= (aPermanentShadows[i].m_nLifeTime * 3 / 4) ) { // timePassed == 0 -> 4 // timePassed == aPermanentShadows[i].m_nLifeTime -> 0 float fMult = 1.0f - float(timePassed - (aPermanentShadows[i].m_nLifeTime * 3 / 4)) / (aPermanentShadows[i].m_nLifeTime / 4); - StoreStaticShadow((uintptr)&aPermanentShadows[i], + bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i], aPermanentShadows[i].m_nType, aPermanentShadows[i].m_pTexture, &aPermanentShadows[i].m_vecPos, @@ -1538,7 +2312,7 @@ CShadows::UpdatePermanentShadows(void) } else { - StoreStaticShadow((uintptr)&aPermanentShadows[i], + bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i], aPermanentShadows[i].m_nType, aPermanentShadows[i].m_pTexture, &aPermanentShadows[i].m_vecPos, @@ -1553,6 +2327,9 @@ CShadows::UpdatePermanentShadows(void) aPermanentShadows[i].m_fZDistance, 1.0f, 40.0f, false, 0.0f); } + + if ( !bOk ) + aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; } } } @@ -1561,19 +2338,19 @@ CShadows::UpdatePermanentShadows(void) void CStaticShadow::Free(void) { - if ( m_pPolyBunch != NULL ) + if ( m_pPolyBunch != nil ) { CPolyBunch *pFree = CShadows::pEmptyBunchList; CShadows::pEmptyBunchList = m_pPolyBunch; CPolyBunch *pUsed = m_pPolyBunch; - while (pUsed->m_pNext != NULL) + while (pUsed->m_pNext != nil) pUsed = pUsed->m_pNext; pUsed->m_pNext = pFree; } - m_pPolyBunch = NULL; + m_pPolyBunch = nil; m_nId = 0; } @@ -1617,6 +2394,7 @@ CShadows::CalcPedShadowValues(CVector vecLightDir, } + void CShadows::RenderExtraPlayerShadows(void) { @@ -1627,64 +2405,13 @@ CShadows::RenderExtraPlayerShadows(void) if ( CTimeCycle::GetLightShadowStrength() != 0 ) { CVehicle *pCar = FindPlayerVehicle(); - - if ( pCar == NULL ) - { - for ( int32 i = 0; i < CPointLights::NumLights; i++ ) - { - if ( 0.0f != CPointLights::aLights[i].red - || 0.0f != CPointLights::aLights[i].green - || 0.0f != CPointLights::aLights[i].blue ) - { - if ( CPointLights::aLights[i].castExtraShadows ) - { - CVector vecLight = CPointLights::aLights[i].coors - FindPlayerCoors(); - float fLightDist = vecLight.Magnitude(); - float fRadius = CPointLights::aLights[i].radius; - - if ( fLightDist < fRadius ) - { - // fLightDist == fRadius -> 2.0f - // fLightDist == 0 -> 0.0f - float fMult = (1.0f - (2.0f * fLightDist - fRadius) / fRadius); - - int32 nColorStrength; - if ( fLightDist < fRadius*0.5f ) - nColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8); - else - nColorStrength = int32((5*CTimeCycle::GetLightShadowStrength()/8) * fMult); - - float fInv = 1.0f / fLightDist; - vecLight.x *= fInv; - vecLight.y *= fInv; - vecLight.z *= fInv; - - float fFrontX, fFrontY, fSideX, fSideY, fDisplacementX, fDisplacementY; - - CalcPedShadowValues(vecLight, - &fFrontX, &fFrontY, - &fSideX, &fSideY, - &fDisplacementX, &fDisplacementY); - - CVector shadowPos = FindPlayerCoors(); - - shadowPos.x += fDisplacementX; - shadowPos.y += fDisplacementY; - - - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &shadowPos, - fFrontX, fFrontY, - fSideX, fSideY, - nColorStrength, 0, 0, 0, - 4.0f, false, 1.0f); - } - } - } - } - } + if ( pCar == nil ) + ; // R* cut it out for playerped else { - if ( pCar->GetModelIndex() != MI_RCBANDIT ) + if ( pCar->GetModelIndex() != MI_RCBANDIT + && pCar->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE + && !pCar->IsBike() && !pCar->IsPlane() && !pCar->IsBoat() ) { for ( int32 i = 0; i < CPointLights::NumLights; i++ ) { @@ -1737,7 +2464,7 @@ CShadows::RenderExtraPlayerShadows(void) pCar->GetRight().x * (fVehicleWidth/3), pCar->GetRight().y * (fVehicleWidth/3), nColorStrength, 0, 0, 0, - 4.5f, false, 1.0f); + 4.5f, false, 1.0f, nil, false); } else { @@ -1747,7 +2474,7 @@ CShadows::RenderExtraPlayerShadows(void) -pCar->GetRight().x * (fVehicleWidth/2), -pCar->GetRight().y * (fVehicleWidth/2), nColorStrength, 0, 0, 0, - 4.5f, false, 1.0f); + 4.5f, false, 1.0f, nil, false); } } } @@ -1769,9 +2496,9 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); C3dMarkers::PlaceMarkerSet(nID, MARKERTYPE_CYLINDER, *pPosn, Max(fFrontX, -fSideY), - 0, 128, 255, 128, - 2048, 0.2f, 0); + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, + SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0); } |