diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 3b11e16f..375e9d5b 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -3958,7 +3958,7 @@ CCam::Process_Debug(const CVector&, float, float, float) if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn) CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source, 12.0f, 0.0f, 0.0f, -12.0f, - 128, 128, 128, 128, 1000.0f, false, 1.0f); + 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false); if(CHud::m_Wants_To_Draw_Hud){ char str[256]; @@ -4103,7 +4103,7 @@ CCam::Process_Editor(const CVector&, float, float, float) if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn) CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source, 12.0f, 0.0f, 0.0f, -12.0f, - 128, 128, 128, 128, 1000.0f, false, 1.0f); + 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false); if(CHud::m_Wants_To_Draw_Hud){ char str[256]; diff --git a/src/core/Collision.h b/src/core/Collision.h index eb11d8c4..1dc29efb 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -88,6 +88,9 @@ struct CColTrianglePlane void Set(const CVector &va, const CVector &vb, const CVector &vc); void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); } void GetNormal(CVector &n) const { n = normal; } + float GetNormalX() const { return normal.x; } + float GetNormalY() const { return normal.y; } + float GetNormalZ() const { return normal.z; } float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; }; }; diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index e9332e8a..b27284bc 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -445,7 +445,7 @@ CEntity::PreRender(void) gpShadowExplosionTex, &pos, 8.0f, 0.0f, 0.0f, -8.0f, 255, 200.0f*flicker, 160.0f*flicker, 120.0f*flicker, - 20.0f, false, 1.0f); + 20.0f, false, 1.0f, nil, false); CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), 8.0f, @@ -483,7 +483,7 @@ CEntity::PreRender(void) CTimeCycle::GetShadowStrength(), CTimeCycle::GetShadowStrength(), CTimeCycle::GetShadowStrength(), - 20.0f, false, 1.0f); + 20.0f, false, 1.0f, nil, false); } // fall through case ENTITY_TYPE_DUMMY: diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 2d721e93..da20ea18 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -29,6 +29,15 @@ public: if(m_hasRwMatrix && m_attachment) RwMatrixDestroy(m_attachment); } +#ifdef RWCORE_H + operator RwMatrix (void) const { + return m_matrix; + } + + operator RwMatrix *(void) { + return &m_matrix; + } +#endif void Attach(RwMatrix *matrix, bool owner = false){ #ifdef FIX_BUGS if(m_attachment && m_hasRwMatrix) @@ -240,6 +249,15 @@ public: void CopyOnlyMatrix(CMatrix *other){ m_matrix = other->m_matrix; } + void CopyRwMatrix(RwMatrix *matrix){ + m_matrix = *matrix; + } + + void CopyToRwMatrix(RwMatrix *matrix){ + *matrix = m_matrix; + RwMatrixUpdate(matrix); + } + void SetUnity(void) { m_matrix.right.x = 1.0f; m_matrix.right.y = 0.0f; diff --git a/src/objects/CutsceneObject.cpp b/src/objects/CutsceneObject.cpp index adfec37c..8d1be357 100644 --- a/src/objects/CutsceneObject.cpp +++ b/src/objects/CutsceneObject.cpp @@ -11,7 +11,11 @@ #include "ModelIndices.h" #include "Shadows.h" #include "Timecycle.h" +#include "CutsceneShadow.h" #include "CutsceneObject.h" +#include "ModelIndices.h" +#include "RpAnimBlend.h" + CCutsceneObject::CCutsceneObject(void) { @@ -21,6 +25,19 @@ CCutsceneObject::CCutsceneObject(void) ObjectCreatedBy = CUTSCENE_OBJECT; m_fMass = 1.0f; m_fTurnMass = 1.0f; + + m_pAttachTo = nil; + m_pAttachmentObject = nil; + m_pShadow = nil; +} + +CCutsceneObject::~CCutsceneObject(void) +{ + if ( m_pShadow ) + { + delete m_pShadow; + m_pShadow = nil; + } } void @@ -33,22 +50,38 @@ CCutsceneObject::SetModelIndex(uint32 id) (*RPANIMBLENDCLUMPDATA(m_rwObject))->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION_3D; } +void +CCutsceneObject::CreateShadow(void) +{ + if ( IsPedModel(GetModelIndex()) ) + { + m_pShadow = new CCutsceneShadow(); + if (!m_pShadow->IsInitialized()) + m_pShadow->Create(m_rwObject, 6, true, 4, true); + } +} + void CCutsceneObject::ProcessControl(void) { CPhysical::ProcessControl(); - if(CTimer::GetTimeStep() < 1/100.0f) - m_vecMoveSpeed *= 100.0f; + if ( m_pAttachTo ) + { + if ( m_pAttachmentObject ) + GetMatrix() = CMatrix((RwMatrix*)m_pAttachTo); + else + GetMatrix() = CMatrix(RwFrameGetLTM((RwFrame*)m_pAttachTo)); + } else - m_vecMoveSpeed *= 1.0f/CTimer::GetTimeStep(); - - ApplyMoveSpeed(); - -#ifdef PED_SKIN - if(IsClumpSkinned(GetClump())) - UpdateRpHAnim(); -#endif + { + if(CTimer::GetTimeStep() < 1/100.0f) + m_vecMoveSpeed *= 100.0f; + else + m_vecMoveSpeed *= 1.0f/CTimer::GetTimeStep(); + + ApplyMoveSpeed(); + } } static RpMaterial* @@ -61,14 +94,52 @@ MaterialSetAlpha(RpMaterial *material, void *data) void CCutsceneObject::PreRender(void) { - if(IsPedModel(GetModelIndex())){ - CShadows::StoreShadowForPedObject(this, - CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); + if ( m_pAttachTo ) + { + if ( m_pAttachmentObject ) + { + m_pAttachmentObject->UpdateRpHAnim(); + GetMatrix() = CMatrix((RwMatrix*)m_pAttachTo); + } + else + GetMatrix() = CMatrix(RwFrameGetLTM((RwFrame*)m_pAttachTo)); + + if ( RwObjectGetType(m_rwObject) == rpCLUMP && IsClumpSkinned(GetClump()) ) + { + RpAtomic *atomic = GetFirstAtomic(GetClump()); + atomic->boundingSphere.center = (*RPANIMBLENDCLUMPDATA(GetClump()))->frames[0].hanimFrame->t; + } + } + + if ( RwObjectGetType(m_rwObject) == rpCLUMP ) + UpdateRpHAnim(); + + if(IsPedModel(GetModelIndex())) + { + if ( m_pShadow == nil ) + { + CShadows::StoreShadowForPedObject(this, + CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); + } + else + { + if ( m_pShadow->IsInitialized() ) + m_pShadow->UpdateForCutscene(); + + CShadows::StoreShadowForCutscenePedObject(this, + CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); + } + // For some reason xbox/android limbs are transparent here... RpGeometry *geometry = RpAtomicGetGeometry(GetFirstAtomic(GetClump())); RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR); @@ -79,7 +150,9 @@ CCutsceneObject::PreRender(void) void CCutsceneObject::Render(void) { + RwRenderStateSet(rwRENDERSTATECULLMODE, (void *)rwCULLMODECULLNONE); CObject::Render(); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void *)rwCULLMODECULLBACK); } bool diff --git a/src/objects/CutsceneObject.h b/src/objects/CutsceneObject.h index bb642f3e..af24c0a6 100644 --- a/src/objects/CutsceneObject.h +++ b/src/objects/CutsceneObject.h @@ -2,12 +2,20 @@ #include "Object.h" +class CCutsceneShadow; + class CCutsceneObject : public CObject { public: + CCutsceneShadow *m_pShadow; + void *m_pAttachTo; + CObject *m_pAttachmentObject; + CCutsceneObject(void); + ~CCutsceneObject(void); void SetModelIndex(uint32 id); + void CreateShadow(void); void ProcessControl(void); void PreRender(void); void Render(void); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 53c2b2c2..4e1c3c6d 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -63,6 +63,7 @@ #include "Debug.h" #include "GameLogic.h" #include "Bike.h" +#include "CutsceneShadow.h" #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) @@ -146,6 +147,9 @@ void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete(( // --MIAMI: Done CPed::~CPed(void) { +#if 1 + if ( m_pRTShadow ) delete m_pRTShadow; +#endif CWorld::Remove(this); if (m_attractor) GetPedAttractorManager()->DeRegisterPed(this, m_attractor); @@ -203,6 +207,9 @@ CPed::FlagToDestroyWhenNextProcessed(void) CPed::CPed(uint32 pedType) : m_pedIK(this) { +#if 1 + m_pRTShadow = NULL; +#endif m_type = ENTITY_TYPE_PED; bPedPhysics = true; bUseCollisionRecords = true; @@ -2788,6 +2795,13 @@ CPed::SetModelIndex(uint32 mi) if (IsClumpSkinned(GetClump())) // condition isn't there in VC UpdateRpHAnim(); #endif +#if 1 + if (!m_pRTShadow) + { + m_pRTShadow = new CCutsceneShadow; + m_pRTShadow->Create(m_rwObject, 10, 1, 1, 1); + } +#endif } // --MIAMI: Done diff --git a/src/peds/Ped.h b/src/peds/Ped.h index b3d2f71c..979eb29c 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -363,6 +363,9 @@ class CVehicle; class CPed : public CPhysical { public: +#if 1 + class CCutsceneShadow *m_pRTShadow; +#endif // 0x128 CStoredCollPoly m_collPoly; float m_fCollisionSpeed; diff --git a/src/render/CutsceneShadow.cpp b/src/render/CutsceneShadow.cpp new file mode 100644 index 00000000..8cb33896 --- /dev/null +++ b/src/render/CutsceneShadow.cpp @@ -0,0 +1,269 @@ +#include "common.h" +#include "main.h" +#include "rwcore.h" +#include "rwplcore.h" +#include "CutsceneShadow.h" +#include "RwHelper.h" + +#define DLIGHT_VALUE 0.8f /* Directional light intensity */ + + +CCutsceneShadow::CCutsceneShadow() +{ + m_pAtomic = nil; + m_nRwObjectType = -1; + m_pLight = nil; + m_nBlurPasses = 0; + m_bResample = false; + m_bGradient = false; +} + +CCutsceneShadow::~CCutsceneShadow() +{ + Destroy(); +} + +bool +CCutsceneShadow::Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient) +{ + ASSERT(object != nil); + + RwRGBAReal color; + RwFrame *frame; + + if (!object) + return false; + + m_pLight = RpLightCreate(rpLIGHTDIRECTIONAL); + ASSERT(m_pLight != nil); + + if (!m_pLight) + return false; + + color.red = color.green = color.blue = DLIGHT_VALUE; + color.alpha = 0.0f; + + RpLightSetColor(m_pLight, &color); + + frame = RwFrameCreate(); + ASSERT(frame != nil); + + RpLightSetFrame(m_pLight, frame); + + SetLightProperties(180.0f, 90.0f, false); + + m_pObject = object; + m_nRwObjectType = RwObjectGetType(m_pObject); + + switch ( m_nRwObjectType ) + { + case rpCLUMP: + { + RpClumpGetBoundingSphere(m_pClump, &m_BoundingSphere, 1); + m_BaseSphere.radius = m_BoundingSphere.radius; + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump))); + break; + } + + case rpATOMIC: + { + m_BoundingSphere = *RpAtomicGetBoundingSphere(m_pAtomic); + m_BaseSphere.radius = m_BoundingSphere.radius; + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic))); + break; + } + + default: + { + Destroy(); + return false; + break; + } + } + + if ( !m_Camera.Create(rasterSize) ) + { + Destroy(); + return false; + } + + m_nBlurPasses = blurPasses; + m_bResample = resample; + m_bGradient = gradient; + + if ( m_bResample && !m_ResampleCamera.Create(rasterSize - 1) ) + { + Destroy(); + return false; + } + + if ( m_nBlurPasses != 0 ) + { + if ( !m_BlurCamera.Create(resample ? rasterSize - 1 : rasterSize) ) + { + Destroy(); + return false; + } + } + + if ( m_bGradient ) + { + if ( !m_GradientCamera.Create(resample ? rasterSize - 1 : rasterSize) ) + { + Destroy(); + return false; + } + + m_GradientCamera.MakeGradientRaster(); + } + + m_Camera.SetLight(m_pLight); + + switch ( m_nRwObjectType ) + { + case rpATOMIC: + m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius); + break; + + case rpCLUMP: + m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius); + break; + } + + m_Camera.SetCenter(&m_BaseSphere.center); + return true; +} + +RwFrame * +CCutsceneShadow::SetLightProperties(float angleY, float angleX, bool setLight) +{ + ASSERT(m_pLight != nil); + + RwFrame *frame; + static RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; + static RwV3d Yaxis = { 0.0f, 1.0f, 0.0f }; + + frame = RpLightGetFrame(m_pLight); + ASSERT(frame != nil); + + if ( !frame ) + return nil; + + RwFrameRotate(frame, &Yaxis, angleY, rwCOMBINEREPLACE); + RwFrameRotate(frame, &Xaxis, angleX, rwCOMBINEPOSTCONCAT); + + if ( setLight ) + m_Camera.SetLight(m_pLight); + + return frame; +} + +bool +CCutsceneShadow::IsInitialized() +{ + return m_pObject != nil; +} + +void +CCutsceneShadow::Destroy() +{ + m_Camera.Destroy(); + m_ResampleCamera.Destroy(); + m_BlurCamera.Destroy(); + m_GradientCamera.Destroy(); + + m_pAtomic = nil; + + m_nRwObjectType = -1; + + if (m_pLight) + { + RwFrame *frame = RpLightGetFrame(m_pLight); + RpLightSetFrame(m_pLight, nil); + RwFrameDestroy(frame); + RpLightDestroy(m_pLight); + m_pLight = nil; + } +} + +RwRaster * +CCutsceneShadow::Update() +{ + switch ( m_nRwObjectType ) + { + case rpCLUMP: + ASSERT(m_pClump != nil); + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump))); + break; + + case rpATOMIC: + ASSERT(m_pAtomic != nil); + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic))); + break; + } + + m_Camera.SetCenter(&m_BaseSphere.center); + + switch ( m_nRwObjectType ) + { + case rpCLUMP: + m_Camera.Update(m_pClump); + break; + + case rpATOMIC: + m_Camera.Update(m_pAtomic); + break; + } + + RwRaster *raster = m_Camera.GetRwRenderRaster(); + ASSERT(raster != nil); + + if ( m_bResample ) + return m_ResampleCamera.RasterResample(raster); + + if ( m_nBlurPasses ) + return m_BlurCamera.RasterBlur(raster, m_nBlurPasses); + + if ( m_bGradient ) + return m_GradientCamera.RasterGradient(raster); + + return raster; +} + +RwTexture * +CCutsceneShadow::UpdateForCutscene() +{ + Update(); + return GetShadowRwTexture(); +} + +CShadowCamera * +CCutsceneShadow::GetShadowCamera(int32 camType) +{ + switch ( camType ) + { + case RESAMPLE: return &m_ResampleCamera; + case BLUR: return &m_BlurCamera; + case GRADIENT: return &m_GradientCamera; + } + + return &m_Camera; +} + +RwTexture * +CCutsceneShadow::GetShadowRwTexture() +{ + if ( m_bResample ) + return m_ResampleCamera.GetRwRenderTexture(); + else + return m_Camera.GetRwRenderTexture(); +} + +void +CCutsceneShadow::DrawBorderAroundTexture(RwRGBA const& color) +{ + if ( m_bResample ) + m_ResampleCamera.DrawOutlineBorder(color); + else + m_Camera.DrawOutlineBorder(color); +} \ No newline at end of file diff --git a/src/render/CutsceneShadow.h b/src/render/CutsceneShadow.h new file mode 100644 index 00000000..a59fe78f --- /dev/null +++ b/src/render/CutsceneShadow.h @@ -0,0 +1,52 @@ +#pragma once +#include "ShadowCamera.h" + +class CCutsceneShadow +{ +public: + enum + { + RASTER = 0, + RESAMPLE, + BLUR, + GRADIENT, + }; + + CShadowCamera m_Camera; + bool m_bResample; + CShadowCamera m_ResampleCamera; + int32 m_nBlurPasses; + CShadowCamera m_BlurCamera; + bool m_bGradient; + CShadowCamera m_GradientCamera; + + union + { + RwObject *m_pObject; + RpAtomic *m_pAtomic; + RpClump *m_pClump; + }; + + int32 m_nRwObjectType; + RpLight *m_pLight; + RwSphere m_BoundingSphere; + RwSphere m_BaseSphere; + + CCutsceneShadow(); + ~CCutsceneShadow(); + + RwSphere GetBaseSphere() + { + return m_BaseSphere; + } + + bool Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient); + RwFrame *SetLightProperties(float angleY, float angleX, bool setLight); + bool IsInitialized(); + void Destroy(); + RwRaster *Update(); + RwTexture *UpdateForCutscene(); + CShadowCamera *GetShadowCamera(int32 camType = RASTER); + RwTexture *GetShadowRwTexture(); + void DrawBorderAroundTexture(RwRGBA const& color); +}; diff --git a/src/render/ShadowCamera.cpp b/src/render/ShadowCamera.cpp new file mode 100644 index 00000000..ae94f8ac --- /dev/null +++ b/src/render/ShadowCamera.cpp @@ -0,0 +1,549 @@ +#include "common.h" +#include "rwcore.h" +#include "ShadowCamera.h" +#include "RwHelper.h" + +#define TEXELOFFSET 0.5f + +RpAtomic *ShadowRenderCallBack(RpAtomic *atomic, void *data) +{ + RpAtomicCallBackRender savedCB = RpAtomicGetRenderCallBack(atomic); + RpAtomicSetRenderCallBack(atomic, AtomicDefaultRenderCallBack); + RpAtomicRender(atomic); + RpAtomicSetRenderCallBack(atomic, savedCB); + return atomic; +} + +CShadowCamera::CShadowCamera() +{ + m_pCamera = nil; + m_pTexture = nil; +} + +CShadowCamera::~CShadowCamera() +{ + Destroy(); +} + +void +CShadowCamera::Destroy() +{ + if ( m_pCamera ) + { + RwRaster *raster; + RwFrame *frame; + + frame = RwCameraGetFrame(m_pCamera); + + if ( frame ) + { + RwCameraSetFrame(m_pCamera, nil); + RwFrameDestroy(frame); + } + + raster = RwCameraGetZRaster(m_pCamera); + if ( raster ) + { + RwCameraSetZRaster(m_pCamera, nil); + RwRasterDestroy(raster); + } + + raster = RwCameraGetRaster(m_pCamera); + if ( raster ) + { + RwCameraSetRaster(m_pCamera, nil); + RwRasterDestroy(raster); + } + + if ( m_pTexture ) + { + RwTextureSetRaster(m_pTexture, nil); + RwTextureDestroy(m_pTexture); + m_pTexture = nil; + } + + RwCameraDestroy(m_pCamera); + m_pCamera = nil; + } + return; +} + +RwCamera * +CShadowCamera::Create(int32 rasterSize) +{ + int32 size = 1 << rasterSize; + + m_pCamera = RwCameraCreate(); + ASSERT(m_pCamera != nil); + + if ( m_pCamera ) + { + RwCameraSetFrame(m_pCamera, RwFrameCreate()); + + if( RwCameraGetFrame(m_pCamera) ) + { + RwRaster *zRaster = RwRasterCreate(size, size, 0, rwRASTERTYPEZBUFFER); + ASSERT(zRaster != nil); + + if ( zRaster ) + { + RwCameraSetZRaster(m_pCamera, zRaster); + + RwRaster *raster = RwRasterCreate(size, size, 0, rwRASTERTYPECAMERATEXTURE); + ASSERT(raster != nil); + + if ( raster ) + { + RwCameraSetRaster(m_pCamera, raster); + m_pTexture = RwTextureCreate(raster); + ASSERT(m_pTexture != nil); + + if ( m_pTexture ) + { + RwTextureSetAddressing(m_pTexture, rwTEXTUREADDRESSCLAMP); + RwTextureSetFilterMode(m_pTexture, rwFILTERLINEAR); + RwCameraSetProjection(m_pCamera, rwPARALLEL); + return (m_pCamera); + } + } + } + } + } + + Destroy(); + + return (nil); +} + +RwCamera * +CShadowCamera::SetFrustum(float objectRadius) +{ + ASSERT(m_pCamera != nil); + + RwV2d vw; + + RwCameraSetFarClipPlane (m_pCamera, 2.0f * objectRadius); + RwCameraSetNearClipPlane(m_pCamera, 0.001f * objectRadius); + + vw.x = objectRadius; + vw.y = objectRadius; + RwCameraSetViewWindow(m_pCamera, &vw); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::SetLight(RpLight *light) +{ + ASSERT(light != nil); + ASSERT(m_pCamera != nil); + + RwFrame *camFrame = RwCameraGetFrame(m_pCamera); + RwMatrix *camMatrix = RwFrameGetMatrix(camFrame); + RwFrame *lightFrame = RpLightGetFrame(light); + RwMatrix *lightMatrix = RwFrameGetMatrix(lightFrame); + + *RwMatrixGetRight(camMatrix) = *RwMatrixGetRight(lightMatrix); + *RwMatrixGetUp(camMatrix) = *RwMatrixGetUp(lightMatrix); + *RwMatrixGetAt(camMatrix) = *RwMatrixGetAt(lightMatrix); + + RwMatrixUpdate(camMatrix); + RwFrameUpdateObjects(camFrame); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::SetCenter(RwV3d *center) +{ + ASSERT(center != nil); + ASSERT(m_pCamera != nil); + + RwFrame *camFrame = RwCameraGetFrame(m_pCamera); + RwMatrix *camMatrix = RwFrameGetMatrix(camFrame); + + *RwMatrixGetPos(camMatrix) = *center; + + RwV3dIncrementScaled(RwMatrixGetPos(camMatrix), RwMatrixGetAt(camMatrix), -0.5f * RwCameraGetFarClipPlane(m_pCamera)); + + RwMatrixUpdate(camMatrix); + RwFrameUpdateObjects(camFrame); + RwFrameOrthoNormalize(camFrame); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::Update(RpClump *clump) +{ + ASSERT(clump != nil); + ASSERT(m_pCamera != nil); + + RwUInt32 flags; + RpGeometry *geometry; + + RwRGBA bgColor = { 255, 255, 255, 0 }; + + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + geometry = GetFirstAtomic(clump)->geometry; + ASSERT(geometry != nil); + + flags = RpGeometryGetFlags(geometry); + + RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT + |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR)); + + RpClumpForAllAtomics(clump, ShadowRenderCallBack, nil); + + RpGeometrySetFlags(geometry, flags); + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + + return m_pCamera; +} + +RwCamera * +CShadowCamera::Update(RpAtomic *atomic) +{ + ASSERT(atomic != nil); + ASSERT(m_pCamera != nil); + + RwUInt32 flags; + RpGeometry *geometry; + + RwRGBA bgColor = { 255, 255, 255, 0 }; + + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + geometry = RpAtomicGetGeometry(atomic); + ASSERT(geometry != nil); + flags = RpGeometryGetFlags(geometry); + + RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT + |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYNORMALS)); + + ShadowRenderCallBack(atomic, nil); + + RpGeometrySetFlags(geometry, flags); + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + + return m_pCamera; +} + +void +CShadowCamera::InvertRaster() +{ + ASSERT(m_pCamera != nil); + + RwIm2DVertex vx[4]; + float crw, crh; + RwRaster *raster; + float recipZ; + + raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + crw = (float)RwRasterGetWidth(raster); + crh = (float)RwRasterGetHeight(raster); + + recipZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], 0.0f); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipZ); + RwIm2DVertexSetIntRGBA (&vx[0], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[1], 0.0f); + RwIm2DVertexSetScreenY (&vx[1], crh); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipZ); + RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[2], crw); + RwIm2DVertexSetScreenY (&vx[2], 0.0f); + RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ); + RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[3], crw); + RwIm2DVertexSetScreenY (&vx[3], crh); + RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ); + RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255); + + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + + RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); +} + +RwRaster * +CShadowCamera::MakeGradientRaster() +{ + ASSERT(m_pCamera != nil); + + RwIm2DVertex vx[2]; + + if ( !m_pCamera ) + return nil; + + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float width = (float)RwRasterGetWidth(raster); + float height = (float)RwRasterGetHeight(raster); + + if ( height < 1 ) + return nil; + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)rwFILTERNAFILTERMODE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT); + + float color = 255.0f; + float step = (-191.0f / height); + + for ( int32 i = 0; i < height; i++ ) + { + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], i); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + RwIm2DVertexSetIntRGBA (&vx[0], (uint32)color, (uint32)color, (uint32)color, (uint32)color); + + RwIm2DVertexSetScreenX (&vx[1], width - 1); + RwIm2DVertexSetScreenY (&vx[1], i); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + RwIm2DVertexSetIntRGBA (&vx[1], (uint32)color, (uint32)color, (uint32)color, (uint32)color); + + RwIm2DRenderLine(vx, 2, 0, 1); + + color += step; + } + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEGOURAUD); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} + +RwRaster * +CShadowCamera::RasterResample(RwRaster *dstRaster) +{ + ASSERT(dstRaster != nil); + ASSERT(m_pCamera != nil); + + if ( !m_pCamera ) + return nil; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float) RwRasterGetWidth(raster); + float uvOffset = TEXELOFFSET / size; + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster); + + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, uvOffset); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} + +RwRaster * +CShadowCamera::RasterBlur(RwRaster *dstRaster, int32 numPasses) +{ + ASSERT(dstRaster != nil); + ASSERT(m_pCamera != nil); + + if ( !m_pCamera ) + return nil; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float) RwRasterGetWidth(dstRaster); + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + for (int i = 0; i < numPasses; i++ ) + { + RwCameraSetRaster(m_pCamera, raster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + if ( i == 0 ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + } + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster); + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 1.0f / size); + RwCameraEndUpdate(m_pCamera); + } + + RwCameraSetRaster(m_pCamera, dstRaster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster); + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0); + + if ( i == numPasses - 1 ) + { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + } + + RwCameraEndUpdate(m_pCamera); + } + } + + RwCameraSetRaster(m_pCamera, raster); + + return dstRaster; +} + +RwRaster * +CShadowCamera::RasterGradient(RwRaster *dstRaster) +{ + ASSERT(dstRaster != nil); + ASSERT(m_pCamera != nil); + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float)RwRasterGetWidth(dstRaster); + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwCameraSetRaster(m_pCamera, dstRaster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDSRCCOLOR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster); + + Im2DRenderQuad(0, 0, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + RwCameraEndUpdate(m_pCamera); + } + + RwCameraSetRaster(m_pCamera, raster); + + return dstRaster; +} + +RwRaster *CShadowCamera::DrawOutlineBorder(RwRGBA const& color) +{ + ASSERT(m_pCamera != nil); + + RwIm2DVertex vx[4]; + RwImVertexIndex ix[5]; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float)RwRasterGetWidth(raster) - 1.0f; + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], 0.0f); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[0], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[1], size); + RwIm2DVertexSetScreenY (&vx[1], 0.0f); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[1], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[2], size); + RwIm2DVertexSetScreenY (&vx[2], size); + RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[2], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[3], 0.0f); + RwIm2DVertexSetScreenY (&vx[3], size); + RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[3], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ); + + ix[0] = 0; + ix[4] = 0; + ix[1] = 1; + ix[2] = 2; + ix[3] = 3; + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil); + + RwIm2DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, vx, 4, ix, 5); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} \ No newline at end of file diff --git a/src/render/ShadowCamera.h b/src/render/ShadowCamera.h new file mode 100644 index 00000000..a2149db7 --- /dev/null +++ b/src/render/ShadowCamera.h @@ -0,0 +1,54 @@ +#pragma once + + +class CShadowCamera +{ +public: + RwCamera *m_pCamera; + RwTexture *m_pTexture; + + CShadowCamera(); + ~CShadowCamera(); + + RwCamera *Create(int32 rasterSize); + void Destroy(); + + RwCamera *SetFrustum(float objectRadius); + RwCamera *SetLight(RpLight *light); + RwCamera *SetCenter(RwV3d *center); + + RwCamera *Update(RpClump *clump); + RwCamera *Update(RpAtomic *atomic); + + void InvertRaster(); + + RwRaster* GetRwRenderRaster() + { + return RwCameraGetRaster(m_pCamera); + } + + // ShadowRasterRender(RwV2d *) + // ApplyAlphaMapToRaster(void) + + RwRaster *MakeGradientRaster(); + + RwTexture *GetRwRenderTexture() + { + return m_pTexture; + } + + RwRaster* GetRwZRaster() + { + return RwCameraGetZRaster(m_pCamera); + } + + RwRaster *RasterResample(RwRaster *dstRaster); + RwRaster *RasterBlur(RwRaster *dstRaster, int32 numPasses); + RwRaster *RasterGradient(RwRaster *dstRaster); + RwRaster *DrawOutlineBorder(RwRGBA const& color); + + RwCamera *GetRwCamera() + { + return m_pCamera; + } +}; \ No newline at end of file diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index c4d14fdc..c22afa76 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" @@ -19,7 +20,11 @@ #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"); @@ -31,6 +36,8 @@ RwImVertexIndex ShadowIndexList[24]; RwTexture *gpShadowCarTex; RwTexture *gpShadowPedTex; RwTexture *gpShadowHeliTex; +RwTexture *gpShadowBikeTex; +RwTexture *gpShadowBaronTex; RwTexture *gpShadowExplosionTex; RwTexture *gpShadowHeadLightsTex; RwTexture *gpOutline1Tex; @@ -38,7 +45,6 @@ RwTexture *gpOutline2Tex; RwTexture *gpOutline3Tex; RwTexture *gpBloodPoolTex; RwTexture *gpReflectionTex; -RwTexture *gpGoalMarkerTex; RwTexture *gpWalkDontTex; RwTexture *gpCrackedGlassTex; RwTexture *gpPostShadowTex; @@ -60,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; @@ -129,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]; @@ -137,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]; } @@ -151,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); @@ -176,7 +187,6 @@ CShadows::Shutdown(void) RwTextureDestroy(gpOutline3Tex); RwTextureDestroy(gpBloodPoolTex); RwTextureDestroy(gpReflectionTex); - RwTextureDestroy(gpGoalMarkerTex); RwTextureDestroy(gpWalkDontTex); RwTextureDestroy(gpCrackedGlassTex); RwTextureDestroy(gpPostShadowTex); @@ -188,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 @@ -216,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 || fDistToCamSqr == 0.0f ) { - float fDistToCam = Sqrt(fDistToCamSqr); - - if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) + if ( fDistToCamSqr != 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 ) @@ -285,6 +298,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 false; } else { @@ -309,12 +324,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 ) @@ -338,9 +355,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 @@ -348,7 +369,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 ) { @@ -362,7 +383,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; } @@ -372,7 +393,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; } @@ -382,7 +403,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; } @@ -392,7 +413,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; } @@ -402,7 +423,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; } @@ -411,8 +432,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; } @@ -425,46 +446,64 @@ 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 ) { CVector CarPos = pCar->GetPosition(); - float fDistToCamSqr = (CarPos - TheCamera.GetPosition()).MagnitudeSqr(); + float fDistToCamSqr = (CarPos - TheCamera.GetPosition()).MagnitudeSqr2D(); 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) ) { @@ -472,46 +511,202 @@ 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); - CarPos.y -= pCar->GetForward().y * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y); - - if ( pCar->GetUp().z > 0.0f ) + + 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; + switch ( type ) { - 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); + 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; + } + + bool bDrawOnBuildings = false; + if ( pCar->GetModelIndex() == MI_RCBANDIT + || pCar->GetModelIndex() == MI_RCBARON + || pCar->GetModelIndex() == MI_RCRAIDER + || pCar->GetModelIndex() == MI_RCGOBLIN + || pCar == FindPlayerVehicle() ) + { + 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); + } } } } @@ -522,8 +717,8 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture, 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(); @@ -551,31 +746,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); + } } } } + +#if 1 +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 ) + { + #if 1 + 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); + } } } } @@ -583,8 +878,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(); @@ -592,7 +887,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 ) { @@ -615,7 +910,77 @@ 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) +{ + 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); } } } @@ -623,14 +988,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 ) { @@ -685,6 +1051,7 @@ CShadows::SetRenderModeForShadowType(uint8 ShadowType) } } + void CShadows::RenderStoredShadows(void) { @@ -693,17 +1060,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)); @@ -735,39 +1105,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); + } } } @@ -777,16 +1220,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) { @@ -812,19 +1256,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++ ) { @@ -858,6 +1302,7 @@ CShadows::RenderStaticShadows(void) RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); } + void CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) { @@ -884,7 +1329,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, @@ -915,50 +1360,162 @@ 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(); - - Bound = pEntity->GetBoundRect(); - - if ( fStartX < Bound.right - && fEndX > Bound.left - && fStartY < Bound.bottom - && fEndY > Bound.top ) + 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); + } + } + } + } + } + } +} + + +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; + + 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 ) + { + CastShadowEntityXY(pEntity, + fStartX, fStartY, + fEndX, fEndY, + pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch); + } + } + } + } + } + } +} + + +void +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); + } } } } @@ -967,20 +1524,20 @@ CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, } void -CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, +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 ) @@ -1026,12 +1583,12 @@ 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); if ( Abs(pColTriPlanes[i].normal.z) > 0.1f ) { CColTriangle *pColTri = pCol->triangles; - ASSERT(pColTri != NULL); + ASSERT(pColTri != nil); CVector PointA, PointB, PointC; @@ -1431,12 +1988,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; @@ -1461,8 +2018,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++ ) @@ -1486,12 +2043,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(); @@ -1514,13 +2281,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, @@ -1537,7 +2305,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, @@ -1552,6 +2320,9 @@ CShadows::UpdatePermanentShadows(void) aPermanentShadows[i].m_fZDistance, 1.0f, 40.0f, false, 0.0f); } + + if ( !bOk ) + aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; } } } @@ -1560,61 +2331,63 @@ 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; } void CShadows::CalcPedShadowValues(CVector vecLightDir, - float *pfDisplacementX, float *pfDisplacementY, float *pfFrontX, float *pfFrontY, - float *pfSideX, float *pfSideY) + float *pfSideX, float *pfSideY, + float *pfDisplacementX, float *pfDisplacementY) { - ASSERT(pfDisplacementX != NULL); - ASSERT(pfDisplacementY != NULL); - ASSERT(pfFrontX != NULL); - ASSERT(pfFrontY != NULL); - ASSERT(pfSideX != NULL); - ASSERT(pfSideY != NULL); + ASSERT(pfFrontX != nil); + ASSERT(pfFrontY != nil); + ASSERT(pfSideX != nil); + ASSERT(pfSideY != nil); + ASSERT(pfDisplacementX != nil); + ASSERT(pfDisplacementY != nil); + + *pfFrontX = -vecLightDir.x; + *pfFrontY = -vecLightDir.y; + + float fDist = Sqrt(*pfFrontY * *pfFrontY + *pfFrontX * *pfFrontX); + float fMult = (fDist + 1.0f) / fDist; + + *pfFrontX *= fMult; + *pfFrontY *= fMult; + + *pfSideX = -vecLightDir.y / fDist; + *pfSideY = vecLightDir.x / fDist; *pfDisplacementX = -vecLightDir.x; *pfDisplacementY = -vecLightDir.y; - float fDist = Sqrt(*pfDisplacementY * *pfDisplacementY + *pfDisplacementX * *pfDisplacementX); - float fMult = (fDist + 1.0f) / fDist; - - *pfDisplacementX *= fMult; - *pfDisplacementY *= fMult; - - *pfFrontX = -vecLightDir.y / fDist; - *pfFrontY = vecLightDir.x / fDist; - - *pfSideX = -vecLightDir.x; - *pfSideY = -vecLightDir.y; - - *pfDisplacementX /= 2; - *pfDisplacementY /= 2; - *pfFrontX /= 2; *pfFrontY /= 2; *pfSideX /= 2; *pfSideY /= 2; + + *pfDisplacementX /= 2; + *pfDisplacementY /= 2; + } + void CShadows::RenderExtraPlayerShadows(void) { @@ -1625,64 +2398,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 fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY; - - CalcPedShadowValues(vecLight, - &fDisplacementX, &fDisplacementY, - &fFrontX, &fFrontY, - &fSideX, &fSideY); - - CVector shadowPos = FindPlayerCoors(); - - shadowPos.x += fSideX; - shadowPos.y += fSideY; - - - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &shadowPos, - fDisplacementX, fDisplacementY, - fFrontX, fFrontY, - 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++ ) { @@ -1735,7 +2457,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 { @@ -1745,7 +2467,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); } } } @@ -1767,9 +2489,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, _TODOCONST(4), *pPosn, Max(fFrontX, -fSideY), + C3dMarkers::PlaceMarkerSet(nID, MARKERTYPE_CYLINDER, *pPosn, Max(fFrontX, -fSideY), SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0); } diff --git a/src/render/Shadows.h b/src/render/Shadows.h index 63aaaaf2..94b2981f 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -1,12 +1,19 @@ #pragma once #define MAX_STOREDSHADOWS 48 -#define MAX_POLYBUNCHES 300 -#define MAX_STATICSHADOWS 64 +#define MAX_POLYBUNCHES 380 +#define MAX_STATICSHADOWS 48 #define MAX_PERMAMENTSHADOWS 48 + class CEntity; +class CPtrList; +class CAutomobile; +class CVehicle; +class CPed; +class CCutsceneShadow; +class CCutsceneObject; enum eShadowType { @@ -27,6 +34,16 @@ enum eShadowTextureType SHADOWTEX_BLOOD }; +enum VEH_SHD_TYPE +{ + VEH_SHD_TYPE_CAR = 0, + VEH_SHD_TYPE_BIKE, + VEH_SHD_TYPE_HELI, + VEH_SHD_TYPE_SEAPLANE, + VEH_SHD_TYPE_RCPLANE, +}; + + class CStoredShadow { public: @@ -35,6 +52,8 @@ public: CVector2D m_vecSide; float m_fZDistance; float m_fScale; + RwTexture *m_pTexture; + CCutsceneShadow *m_pCutsceneShadow; int16 m_nIntensity; uint8 m_ShadowType; uint8 m_nRed; @@ -44,9 +63,9 @@ public: { uint8 bDrawOnWater : 1; uint8 bRendered : 1; - //uint8 bDrawOnBuildings : 1; + uint8 bDrawOnBuildings : 1; } m_nFlags; - RwTexture *m_pTexture; + CStoredShadow() { } @@ -57,11 +76,11 @@ VALIDATE_SIZE(CStoredShadow, 0x30); class CPolyBunch { public: - int16 m_nNumVerts; CVector m_aVerts[7]; + CPolyBunch *m_pNext; + int16 m_nNumVerts; uint8 m_aU[7]; uint8 m_aV[7]; - CPolyBunch *m_pNext; CPolyBunch() { } @@ -80,15 +99,16 @@ public: CVector2D m_vecSide; float m_fZDistance; float m_fScale; - uint8 m_nType; + RwTexture *m_pTexture; int16 m_nIntensity; // unsigned ? + uint8 m_nType; uint8 m_nRed; uint8 m_nGreen; uint8 m_nBlue; bool m_bJustCreated; bool m_bRendered; bool m_bTemp; - RwTexture *m_pTexture; + CStaticShadow() { } @@ -106,14 +126,14 @@ public: CVector2D m_vecSide; float m_fZDistance; float m_fScale; + uint32 m_nTimeCreated; + uint32 m_nLifeTime; + RwTexture *m_pTexture; int16 m_nIntensity; uint8 m_nType; // eShadowType uint8 m_nRed; uint8 m_nGreen; uint8 m_nBlue; - uint32 m_nTimeCreated; - uint32 m_nLifeTime; - RwTexture *m_pTexture; CPermanentShadow() { } @@ -121,60 +141,62 @@ public: VALIDATE_SIZE(CPermanentShadow, 0x38); -class CPtrList; -class CAutomobile; -class CPed; - class CShadows { public: -#if 1 static int16 ShadowsStoredToBeRendered; static CStoredShadow asShadowsStored [MAX_STOREDSHADOWS]; static CPolyBunch aPolyBunches [MAX_POLYBUNCHES]; static CStaticShadow aStaticShadows [MAX_STATICSHADOWS]; static CPolyBunch *pEmptyBunchList; static CPermanentShadow aPermanentShadows[MAX_PERMAMENTSHADOWS]; -#else - static int16 &ShadowsStoredToBeRendered; - static CStoredShadow (&asShadowsStored) [MAX_STOREDSHADOWS]; - static CPolyBunch (&aPolyBunches) [MAX_POLYBUNCHES]; - static CStaticShadow (&aStaticShadows) [MAX_STATICSHADOWS]; - static CPolyBunch *&pEmptyBunchList; - static CPermanentShadow (&aPermanentShadows)[MAX_PERMAMENTSHADOWS]; -#endif - static void Init (void); - static void Shutdown (void); - static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale); - static void 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); - static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue); - static void 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); - static void StoreShadowForCar (CAutomobile *pCar); - static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle); - static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); - static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); - static void StoreShadowForTree (CEntity *pTree); - static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID); - static void SetRenderModeForShadowType (uint8 ShadowType); - static void RenderStoredShadows (void); - static void RenderStaticShadows (void); - static void GeneratePolysForStaticShadow (int16 nStaticShadowID); - static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, + static void Init (void); + static void Shutdown (void); + static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale); + + static bool 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); + static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue); + static void 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, CCutsceneShadow *pShadow, bool bDrawOnBuildings); + static void StoreShadowForVehicle (CVehicle *pCar, VEH_SHD_TYPE type); + static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle); + static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); + static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); + static void StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); + static void StoreShadowForTree (CEntity *pTree); + static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID); + static void SetRenderModeForShadowType (uint8 ShadowType); + static void RenderStoredShadows (void); + static void RenderStaticShadows (void); + + static void GeneratePolysForStaticShadow (int16 nStaticShadowID); + static void 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); - static void CastShadowEntity (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, + + static void 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); + + static void 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); + + static void 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); - static void UpdateStaticShadows (void); - static void UpdatePermanentShadows (void); - static void CalcPedShadowValues (CVector vecLightDir, float *pfDisplacementX, float *pfDisplacementY, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY); - static void RenderExtraPlayerShadows (void); - static void TidyUpShadows (void); - static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity); + + static void 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); + + static void UpdateStaticShadows (void); + static void UpdatePermanentShadows (void); + static void CalcPedShadowValues (CVector vecLightDir, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY, float *pfDisplacementX, float *pfDisplacementY); + static void RenderExtraPlayerShadows (void); + static void TidyUpShadows (void); + static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity); }; extern RwTexture *gpShadowCarTex; extern RwTexture *gpShadowPedTex; extern RwTexture *gpShadowHeliTex; +extern RwTexture *gpShadowBikeTex; +extern RwTexture *gpShadowBaronTex; extern RwTexture *gpShadowExplosionTex; extern RwTexture *gpShadowHeadLightsTex; extern RwTexture *gpOutline1Tex; @@ -182,7 +204,6 @@ extern RwTexture *gpOutline2Tex; extern RwTexture *gpOutline3Tex; extern RwTexture *gpBloodPoolTex; extern RwTexture *gpReflectionTex; -extern RwTexture *gpGoalMarkerTex; extern RwTexture *gpWalkDontTex; extern RwTexture *gpCrackedGlassTex; extern RwTexture *gpPostShadowTex; diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 7ce1d4f5..58791ce2 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -399,6 +399,125 @@ RenderSkeleton(RpHAnimHierarchy *hier) } #endif + +RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset) +{ + RwIm2DVertex vx[4]; + + /* + * Render an opaque white 2D quad at the given coordinates and + * spanning a whole texture. + */ + + RwIm2DVertexSetScreenX(&vx[0], x1); + RwIm2DVertexSetScreenY(&vx[0], y1); + RwIm2DVertexSetScreenZ(&vx[0], z); + RwIm2DVertexSetIntRGBA(&vx[0], 255, 255, 255, 255); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + RwIm2DVertexSetU(&vx[0], uvOffset, recipCamZ); + RwIm2DVertexSetV(&vx[0], uvOffset, recipCamZ); + + RwIm2DVertexSetScreenX(&vx[1], x1); + RwIm2DVertexSetScreenY(&vx[1], y2); + RwIm2DVertexSetScreenZ(&vx[1], z); + RwIm2DVertexSetIntRGBA(&vx[1], 255, 255, 255, 255); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + RwIm2DVertexSetU(&vx[1], uvOffset, recipCamZ); + RwIm2DVertexSetV(&vx[1], 1.0f + uvOffset, recipCamZ); + + RwIm2DVertexSetScreenX(&vx[2], x2); + RwIm2DVertexSetScreenY(&vx[2], y1); + RwIm2DVertexSetScreenZ(&vx[2], z); + RwIm2DVertexSetIntRGBA(&vx[2], 255, 255, 255, 255); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ); + RwIm2DVertexSetU(&vx[2], 1.0f + uvOffset, recipCamZ); + RwIm2DVertexSetV(&vx[2], uvOffset, recipCamZ); + + RwIm2DVertexSetScreenX(&vx[3], x2); + RwIm2DVertexSetScreenY(&vx[3], y2); + RwIm2DVertexSetScreenZ(&vx[3], z); + RwIm2DVertexSetIntRGBA(&vx[3], 255, 255, 255, 255); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ); + RwIm2DVertexSetU(&vx[3], 1.0f + uvOffset, recipCamZ); + RwIm2DVertexSetV(&vx[3], 1.0f + uvOffset, recipCamZ); + + RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4); + + return TRUE; +} + +bool b_cbsUseLTM = true; + +RpAtomic *cbsCalcMeanBSphereRadiusCB(RpAtomic *atomic, void *data) +{ + RwV3d atomicPos; + + if ( b_cbsUseLTM ) + RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump))); + else + RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump))); + + RwV3d temp; + RwV3dSub(&temp, &atomicPos, &((RwSphere *)data)->center); + RwReal radius = RwV3dLength(&temp) + RpAtomicGetBoundingSphere(atomic)->radius; + + if ( ((RwSphere *)data)->radius < radius ) + ((RwSphere *)data)->radius = radius; + + return atomic; +} + +RpAtomic *cbsCalcMeanBSphereCenterCB(RpAtomic *atomic, void *data) +{ + RwV3d atomicPos; + + if ( b_cbsUseLTM ) + RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump))); + else + RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump))); + + RwV3dAdd(&((RwSphere *)data)->center, &((RwSphere *)data)->center, &atomicPos); + + return atomic; +} + +RpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM) +{ + RwMatrix matrix; + RwSphere result = { 0.0f, 0.0f, 0.0f, 0.0f }; + + b_cbsUseLTM = useLTM; + + if ( clump == nil || sphere == nil ) + return nil; + + sphere->radius = 0.0f; + sphere->center.x = 0.0f; + sphere->center.y = 0.0f; + sphere->center.z = 0.0f; + + RwInt32 numAtomics = RpClumpGetNumAtomics(clump); + if ( numAtomics < 1.0f ) + return nil; + + RpClumpForAllAtomics(clump, cbsCalcMeanBSphereCenterCB, &result); + + RwV3dScale(&result.center, &result.center, 1.0f/numAtomics); + + RpClumpForAllAtomics(clump, cbsCalcMeanBSphereRadiusCB, &result); + + if ( b_cbsUseLTM ) + RwMatrixInvert(&matrix, RwFrameGetLTM(RpClumpGetFrame(clump))); + else + RwMatrixInvert(&matrix, RwFrameGetMatrix(RpClumpGetFrame(clump))); + + RwV3dTransformPoints(&result.center, &result.center, 1, &matrix); + + *sphere = result; + + return clump; +} + void CameraSize(RwCamera * camera, RwRect * rect, RwReal viewWindow, RwReal aspectRatio) diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 1862c7f1..3f1a3d19 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -29,6 +29,9 @@ RpAtomic *AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data); void RenderSkeleton(RpHAnimHierarchy *hier); #endif +RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset); +RpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM); + RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream); RwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream); RwTexDictionary *RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 3f329251..e06ce03b 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -2505,8 +2505,12 @@ CAutomobile::PreRender(void) // end of lights } -//TODO(MIAMI): StoreShadowForVehicle once we have it - CShadows::StoreShadowForCar(this); + if (IsRealHeli()) + CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_HELI); + else if ( GetModelIndex() == MI_RCBARON) + CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_RCPLANE); + else + CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_CAR); DoSunGlare(); diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp index e52027f9..c32e72bc 100644 --- a/src/vehicles/Bike.cpp +++ b/src/vehicles/Bike.cpp @@ -1546,7 +1546,7 @@ CBike::PreRender(void) } AddDamagedVehicleParticles(); -//TODO(MIAMI): StoreShadowForVehicle once we have it + CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_BIKE); CMatrix mat; CVector pos; diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 00bb0023..a770f83d 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -557,6 +557,7 @@ CHeli::PreRender(void) { float radius = (GetPosition().z - FindPlayerCoors().z - 10.0f - 1.0f) * 0.3f + 10.0f; HeliDustGenerate(this, radius, FindPlayerCoors().z, Max(16.0f - 4.0f*CTimer::GetTimeStep(), 2.0f)); + CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_HELI); } void @@ -592,7 +593,7 @@ CHeli::PreRenderAlways(void) CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &shadowPos, 6.0f, 0.0f, 0.0f, -6.0f, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, - 50.0f, true, 1.0f); + 50.0f, true, 1.0f, nil, false); CVector front = GetMatrix() * CVector(0.0f, 7.0f, 0.0f); CVector toPlayer = FindPlayerCoors() - front;