summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFire_Head <Fire-Head@users.noreply.github.com>2019-07-24 19:59:16 +0200
committerGitHub <noreply@github.com>2019-07-24 19:59:16 +0200
commitb79f77634dbb33627c390243d7cf2e7611d35d0a (patch)
treed836f70678f2ce7b5d86a6745f34b45232ff71d0
parentimplemented cBuoyancy (diff)
parentupdate (diff)
downloadre3-b79f77634dbb33627c390243d7cf2e7611d35d0a.tar
re3-b79f77634dbb33627c390243d7cf2e7611d35d0a.tar.gz
re3-b79f77634dbb33627c390243d7cf2e7611d35d0a.tar.bz2
re3-b79f77634dbb33627c390243d7cf2e7611d35d0a.tar.lz
re3-b79f77634dbb33627c390243d7cf2e7611d35d0a.tar.xz
re3-b79f77634dbb33627c390243d7cf2e7611d35d0a.tar.zst
re3-b79f77634dbb33627c390243d7cf2e7611d35d0a.zip
-rw-r--r--src/core/Camera.h2
-rw-r--r--src/core/Game.cpp17
-rw-r--r--src/core/Pad.h17
-rw-r--r--src/core/common.h117
-rw-r--r--src/core/config.h3
-rw-r--r--src/core/main.cpp175
-rw-r--r--src/core/main.h3
-rw-r--r--src/core/re3.cpp50
-rw-r--r--src/entities/Entity.cpp6
-rw-r--r--src/math/maths.h3
-rw-r--r--src/render/Particle.cpp18
-rw-r--r--src/render/PointLights.h4
-rw-r--r--src/render/RenderBuffer.cpp4
-rw-r--r--src/render/RenderBuffer.h4
-rw-r--r--src/render/Shadows.cpp1824
-rw-r--r--src/render/Shadows.h176
-rw-r--r--src/render/SpecialFX.cpp3
-rw-r--r--src/render/SpecialFX.h6
-rw-r--r--src/render/Timecycle.h8
-rw-r--r--src/render/WaterLevel.cpp26
-rw-r--r--src/vehicles/Boat.cpp11
21 files changed, 2403 insertions, 74 deletions
diff --git a/src/core/Camera.h b/src/core/Camera.h
index d890db84..1a2aae79 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -442,7 +442,7 @@ int m_iModeObbeCamIsInForCar;
static bool &m_bUseMouse3rdPerson;
bool Get_Just_Switched_Status() { return m_bJust_Switched; }
- CMatrix &GetCameraMatrix(void) { return m_cameraMatrix; }
+ inline const CMatrix GetCameraMatrix(void) { return m_cameraMatrix; }
CVector &GetGameCamPosition(void) { return m_vecGameCamPos; }
bool IsPointVisible(const CVector &center, const CMatrix *mat);
bool IsSphereVisible(const CVector &center, float radius, const CMatrix *mat);
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index cbd55c48..e07106ce 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -1,6 +1,9 @@
#include "common.h"
#include "patcher.h"
#include "Game.h"
+#include "Main.h"
+#include "CdStream.h"
+#include "FileMgr.h"
eLevelName &CGame::currLevel = *(eLevelName*)0x941514;
bool &CGame::bDemoMode = *(bool*)0x5F4DD0;
@@ -11,9 +14,21 @@ bool &CGame::noProstitutes = *(bool*)0x95CDCF;
bool &CGame::playingIntro = *(bool*)0x95CDC2;
char *CGame::aDatFile = (char*)0x773A48;
+
+bool
+CGame::InitialiseOnceBeforeRW(void)
+{
+ CFileMgr::Initialise();
+ CdStreamInit(MAX_CDCHANNELS);
+ ValidateVersion();
+ return true;
+}
+
WRAPPER void CGame::Initialise(const char *datFile) { EAXJMP(0x48BED0); }
WRAPPER void CGame::Process(void) { EAXJMP(0x48C850); }
-WRAPPER bool CGame::InitialiseOnceBeforeRW(void) { EAXJMP(0x48BB80); }
+
+
+
WRAPPER bool CGame::InitialiseRenderWare(void) { EAXJMP(0x48BBA0); }
WRAPPER void CGame::ShutdownRenderWare(void) { EAXJMP(0x48BCB0); }
WRAPPER void CGame::FinalShutdown(void) { EAXJMP(0x48BEC0); }
diff --git a/src/core/Pad.h b/src/core/Pad.h
index e15399dd..4f129e85 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -369,12 +369,27 @@ public:
bool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); }
bool GetRightShoulder2JustDown() { return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); }
+/*
int32 GetLeftShoulder1(void) { return NewState.LeftShoulder1; }
int32 GetLeftShoulder2(void) { return NewState.LeftShoulder2; }
int32 GetRightShoulder1(void) { return NewState.RightShoulder1; }
int32 GetRightShoulder2(void) { return NewState.RightShoulder2; }
+*/
+
+ bool GetTriangle() { return !!NewState.Triangle; }
+ bool GetCircle() { return !!NewState.Circle; }
+ bool GetCross() { return !!NewState.Cross; }
+ bool GetSquare() { return !!NewState.Square; }
+ bool GetDPadUp() { return !!NewState.DPadUp; }
+ bool GetDPadDown() { return !!NewState.DPadDown; }
+ bool GetDPadLeft() { return !!NewState.DPadLeft; }
+ bool GetDPadRight() { return !!NewState.DPadRight; }
+ bool GetLeftShoulder1(void) { return !!NewState.LeftShoulder1; }
+ bool GetLeftShoulder2(void) { return !!NewState.LeftShoulder2; }
+ bool GetRightShoulder1(void) { return !!NewState.RightShoulder1; }
+ bool GetRightShoulder2(void) { return !!NewState.RightShoulder2; }
- bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; }
+ bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; }
};
VALIDATE_SIZE(CPad, 0xFC);
extern CPad *Pads; //[2]
diff --git a/src/core/common.h b/src/core/common.h
index 2ca64c1b..9a5683c6 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -180,3 +180,120 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define ABS(a) (((a) < 0) ? (-a) : (a))
+
+
+#define STRINGIFY(x) #x
+#define STR(x) STRINGIFY(x)
+#define CONCAT_(x,y) x##y
+#define CONCAT(x,y) CONCAT_(x,y)
+
+// Tweaking stuff for debugmenu
+#define TWEAKPATH ___tw___TWEAKPATH
+#define SETTWEAKPATH(path) static const char *___tw___TWEAKPATH = path;
+#define TWEAKFUNC(v) static CTweakFunc CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), TWEAKPATH);
+#define TWEAKFUNCN(v, name) static CTweakFunc CONCAT(___tw___tweak, __COUNTER__)(&v, name, TWEAKPATH);
+#define TWEAKBOOL(v) static CTweakBool CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), TWEAKPATH);
+#define TWEAKBOOLN(v, name) static CTweakBool CONCAT(___tw___tweak, __COUNTER__)(&v, name, TWEAKPATH);
+#define TWEAKINT32(v, lower, upper, step) static CTweakInt32 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKINT32N(v, lower, upper, step, name) static CTweakInt32 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKUINT32(v, lower, upper, step) static CTweakUInt32 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKUINT32N(v, lower, upper, step, name) static CTweakUInt32 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKINT16(v, lower, upper, step) static CTweakInt16 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKINT16N(v, lower, upper, step, name) static CTweakInt16 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKUINT16(v, lower, upper, step) static CTweakUInt16 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKUINT16N(v, lower, upper, step, name) static CTweakUInt16 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKINT8(v, lower, upper, step) static CTweakInt8 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKINT8N(v, lower, upper, step, name) static CTweakInt8 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKUINT8(v, lower, upper, step) static CTweakUInt8 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKUINT8N(v, lower, upper, step, name) static CTweakUInt8 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKFLOAT(v, lower, upper, step) static CTweakFloat CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);
+#define TWEAKFLOATN(v, lower, upper, step, name) static CTweakFloat CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);
+#define TWEAKSWITCH(v, lower, upper, str, f) static CTweakSwitch CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, str, f, TWEAKPATH);
+#define TWEAKSWITCHN(v, lower, upper, str, f, name) static CTweakSwitch CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, str, f, TWEAKPATH);
+
+// interface
+class CTweakVar
+{
+public:
+ virtual void AddDBG(const char *path) = 0;
+};
+
+class CTweakVars
+{
+public:
+ static void Add(CTweakVar *var);
+ static void AddDBG(const char *path);
+};
+
+class CTweakFunc : public CTweakVar
+{
+ const char *m_pPath, *m_pVarName;
+ void (*m_pFunc)();
+public:
+ CTweakFunc(void (*pFunc)(), const char *strName, const char *strPath) :
+ m_pFunc(pFunc), m_pVarName(strName), m_pPath(strPath)
+ {
+ CTweakVars::Add(this);
+ }
+
+ void AddDBG(const char *path);
+};
+
+class CTweakBool : public CTweakVar
+{
+ const char *m_pPath, *m_pVarName;
+ bool *m_pBoolVar;
+public:
+ CTweakBool(bool *pBool, const char *strName, const char *strPath) :
+ m_pBoolVar(pBool), m_pVarName(strName), m_pPath(strPath)
+ {
+ CTweakVars::Add(this);
+ }
+
+ void AddDBG(const char *path);
+};
+
+class CTweakSwitch : public CTweakVar
+{
+ const char *m_pPath, *m_pVarName;
+ void *m_pIntVar;
+ int32 m_nMin, m_nMax;
+ const char **m_aStr;
+ void (*m_pFunc)();
+public:
+ CTweakSwitch(void *pInt, const char *strName, int32 nMin, int32 nMax, const char **aStr, void (*pFunc)(), const char *strPath) :
+ m_pVarName(strName), m_pPath(strPath),
+ m_aStr(aStr), m_pIntVar(pInt), m_nMin(nMin), m_nMax(nMax)
+ {
+ CTweakVars::Add(this);
+ }
+
+ void AddDBG(const char *path);
+};
+
+#define _TWEEKCLASS(name, type) \
+class name : public CTweakVar \
+{ \
+public: \
+ const char *m_pPath, *m_pVarName; \
+ type *m_pIntVar, m_nLoawerBound, m_nUpperBound, m_nStep; \
+ \
+ name(type *pInt, const char *strName, type nLower, type nUpper, type nStep, const char *strPath) : \
+ m_pIntVar(pInt), m_nLoawerBound(nLower), m_nUpperBound(nUpper), m_nStep(nStep), \
+ m_pVarName(strName), m_pPath(strPath) \
+ { \
+ CTweakVars::Add(this); \
+ } \
+ \
+ void AddDBG(const char *path); \
+};
+
+_TWEEKCLASS(CTweakInt8, int8);
+_TWEEKCLASS(CTweakUInt8, uint8);
+_TWEEKCLASS(CTweakInt16, int16);
+_TWEEKCLASS(CTweakUInt16, uint16);
+_TWEEKCLASS(CTweakInt32, int32);
+_TWEEKCLASS(CTweakUInt32, uint32);
+_TWEEKCLASS(CTweakFloat, float);
+
+#undef _TWEEKCLASS
diff --git a/src/core/config.h b/src/core/config.h
index 0736d343..892a06b6 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -3,6 +3,7 @@
enum Config {
NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC)
MAX_CDIMAGES = 8, // additional cdimages
+ MAX_CDCHANNELS = 5,
MODELINFOSIZE = 5500,
TXDSTORESIZE = 850,
@@ -114,7 +115,7 @@ enum Config {
# define CHATTYSPLASH // print what the game is loading
#endif
-#define FIX_BUGS // fix bugs in the game, TODO: use this more
+//#define FIX_BUGS // fix bugs in the game, TODO: use this more
#define KANGAROO_CHEAT
#define ASPECT_RATIO_SCALE
#define USE_DEBUG_SCRIPT_LOADER \ No newline at end of file
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 1083adc3..04fee197 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -66,6 +66,12 @@ wchar *gUString2 = (wchar*)0x6EDD70;
bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8;
+char version_name[64];
+
+float FramesPerSecond = 30.0f;
+
+bool gbPrintShite = false;
+
bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
void DoRWStuffEndOfFrame(void);
@@ -173,9 +179,6 @@ Idle(void *arg)
}
RenderMenus();
-#ifndef FINAL
- PrintGameVersion();
-#endif
DoFade();
Render2dStuffAfterFade();
CCredits::Render();
@@ -211,9 +214,6 @@ FrontendIdle(void)
DefinedState();
RenderMenus();
-#ifndef FINAL
- PrintGameVersion();
-#endif
DoFade();
Render2dStuffAfterFade();
CFont::DrawFonts();
@@ -475,9 +475,137 @@ DoFade(void)
}
}
+float FramesPerSecondCounter;
+int32 FrameSamples;
+
+struct tZonePrint
+{
+ char name[12];
+ CRect rect;
+};
+
+tZonePrint ZonePrint[] =
+{
+ { "suburban", CRect(-1639.4f, 1014.3f, -226.23f, -1347.9f) },
+ { "comntop", CRect(-223.52f, 203.62f, 616.79f, -413.6f) },
+ { "comnbtm", CRect(-227.24f, -413.6f, 620.51f, -911.84f) },
+ { "comse", CRect( 200.35f, -911.84f, 620.51f, -1737.3f) },
+ { "comsw", CRect(-223.52f, -911.84f, 200.35f, -1737.3f) },
+ { "industsw", CRect( 744.05f, -473.0f, 1067.5f, -1331.5f) },
+ { "industne", CRect( 1067.5f, 282.19f, 1915.3f, -473.0f) },
+ { "industnw", CRect( 744.05f, 324.95f, 1067.5f, -473.0f) },
+ { "industse", CRect( 1070.3f, -473.0f, 1918.1f, -1331.5f) },
+ { "no zone", CRect( 0.0f, 0.0f, 0.0f, 0.0f) }
+};
+
+#ifndef MASTER
+void
+DisplayGameDebugText()
+{
+ static bool bDisplayPosn = false;
+ static bool bDisplayRate = false;
+
+ {
+ SETTWEAKPATH("GameDebugText");
+ TWEAKBOOL(bDisplayPosn);
+ TWEAKBOOL(bDisplayRate);
+ }
+
+
+ char str[200];
+ wchar ustr[200];
+ wchar ver[200];
+
+ AsciiToUnicode(version_name, ver);
+
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetScale(SCREEN_STRETCH_X(0.5f), SCREEN_STRETCH_Y(0.5f));
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ CFont::SetWrapx(SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetColor(CRGBA(255, 108, 0, 255));
+ CFont::PrintString(10.0f, 10.0f, ver);
+
+ FrameSamples++;
+ FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);
+ FramesPerSecond = FramesPerSecondCounter / FrameSamples;
+
+ if ( FrameSamples > 30 )
+ {
+ FramesPerSecondCounter = 0.0f;
+ FrameSamples = 0;
+ }
+
+ if ( !TheCamera.WorldViewerBeingUsed
+ && CPad::GetPad(1)->GetSquare()
+ && CPad::GetPad(1)->GetTriangle()
+ && CPad::GetPad(1)->GetLeftShoulder2JustDown() )
+ {
+ bDisplayPosn = !bDisplayPosn;
+ }
+
+ if ( CPad::GetPad(1)->GetSquare()
+ && CPad::GetPad(1)->GetTriangle()
+ && CPad::GetPad(1)->GetRightShoulder2JustDown() )
+ {
+ bDisplayRate = !bDisplayRate;
+ }
+
+ if ( bDisplayPosn || bDisplayRate )
+ {
+ CVector pos = FindPlayerCoors();
+ int32 ZoneId = ARRAY_SIZE(ZonePrint)-1; // no zone
+
+ for ( int32 i = 0; i < ARRAY_SIZE(ZonePrint)-1; i++ )
+ {
+ if ( pos.x > ZonePrint[i].rect.left
+ && pos.x < ZonePrint[i].rect.right
+ && pos.y > ZonePrint[i].rect.bottom
+ && pos.y < ZonePrint[i].rect.top )
+ {
+ ZoneId = i;
+ }
+ }
+
+ //NOTE: fps should be 30, but its 29 due to different fp2int conversion
+ if ( bDisplayRate )
+ sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, F-%d, %s", pos.x, pos.y, pos.z, (int32)FramesPerSecond, ZonePrint[ZoneId].name);
+ else
+ sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, %s", pos.x, pos.y, pos.z, ZonePrint[ZoneId].name);
+
+ AsciiToUnicode(str, ustr);
+
+ CFont::SetPropOff();
+ CFont::SetBackgroundOff();
+ CFont::SetScale(0.7f, 1.5f);
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ CFont::SetJustifyOff();
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetWrapx(640.0f);
+ CFont::SetFontStyle(FONT_HEADING);
+
+ CFont::SetColor(CRGBA(0, 0, 0, 255));
+ CFont::PrintString(42.0f, 42.0f, ustr);
+
+ CFont::SetColor(CRGBA(255, 108, 0, 255));
+ CFont::PrintString(40.0f, 40.0f, ustr);
+ }
+}
+#endif
+
void
Render2dStuffAfterFade(void)
{
+#ifndef MASTER
+ DisplayGameDebugText();
+ //PrintGameVersion();
+#endif
+
CHud::DrawAfterFade();
CFont::DrawFonts();
}
@@ -873,6 +1001,41 @@ void PrintGameVersion()
CFont::PrintString(SCREEN_SCALE_X(10.5f), SCREEN_SCALE_Y(8.0f), gUString);
}
+void
+ValidateVersion()
+{
+ int32 file = CFileMgr::OpenFile("models\\coll\\peds.col", "rb");
+ char buff[128];
+
+ if ( file != -1 )
+ {
+ CFileMgr::Seek(file, 100, SEEK_SET);
+
+ for ( int i = 0; i < 128; i++ )
+ {
+ CFileMgr::Read(file, &buff[i], sizeof(char));
+ buff[i] -= 23;
+ if ( buff[i] == '\0' )
+ break;
+ CFileMgr::Seek(file, 99, SEEK_CUR);
+ }
+
+ if ( !strncmp(buff, "grandtheftauto3", 15) )
+ {
+ strncpy(version_name, &buff[15], 64);
+ CFileMgr::CloseFile(file);
+ return;
+ }
+ }
+
+ LoadingScreen("Invalid version", NULL, NULL);
+
+ while(true)
+ {
+ ;
+ }
+}
+
STARTPATCHES
InjectHook(0x48E480, Idle, PATCH_JUMP);
InjectHook(0x48E700, FrontendIdle, PATCH_JUMP);
diff --git a/src/core/main.h b/src/core/main.h
index c546d085..9b3c27f5 100644
--- a/src/core/main.h
+++ b/src/core/main.h
@@ -17,6 +17,7 @@ extern char *gString2;
extern wchar *gUString;
extern wchar *gUString2;
extern bool &b_FoundRecentSavedGameWantToLoad;
+extern bool gbPrintShite;
class CSprite2d;
@@ -26,5 +27,5 @@ void LoadingIslandScreen(const char *levelName);
CSprite2d *LoadSplash(const char *name);
char *GetLevelSplashScreen(int level);
char *GetRandomSplashScreen(void);
-
void LittleTest(void);
+void ValidateVersion();
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 851baeaf..a0032bc6 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -18,6 +18,7 @@
#include "debugmenu_public.h"
#include <vector>
+#include <list>
std::vector<int32> usedAddresses;
@@ -177,6 +178,53 @@ static const char *carnames[] = {
"yankee", "escape", "borgnine", "toyz", "ghost",
};
+static std::list<CTweakVar *> TweakVarsList;
+static bool bAddTweakVarsNow = false;
+static const char *pTweakVarsDefaultPath = NULL;
+
+void CTweakVars::Add(CTweakVar *var)
+{
+ TweakVarsList.push_back(var);
+
+ if ( bAddTweakVarsNow )
+ var->AddDBG(pTweakVarsDefaultPath);
+}
+
+void CTweakVars::AddDBG(const char *path)
+{
+ pTweakVarsDefaultPath = path;
+
+ for(auto i = TweakVarsList.begin(); i != TweakVarsList.end(); ++i)
+ (*i)->AddDBG(pTweakVarsDefaultPath);
+
+ bAddTweakVarsNow = true;
+}
+
+void CTweakSwitch::AddDBG(const char *path)
+{
+ DebugMenuEntry *e = DebugMenuAddVar(m_pPath == NULL ? path : m_pPath, m_pVarName, (int32_t *)m_pIntVar, m_pFunc, 1, m_nMin, m_nMax, m_aStr);
+ DebugMenuEntrySetWrap(e, true);
+}
+
+void CTweakFunc::AddDBG (const char *path) { DebugMenuAddCmd (m_pPath == NULL ? path : m_pPath, m_pVarName, m_pFunc); }
+void CTweakBool::AddDBG (const char *path) { DebugMenuAddVarBool8(m_pPath == NULL ? path : m_pPath, m_pVarName, (int8_t *)m_pBoolVar, NULL); }
+void CTweakInt8::AddDBG (const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (int8_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }
+void CTweakUInt8::AddDBG (const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (uint8_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }
+void CTweakInt16::AddDBG (const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (int16_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }
+void CTweakUInt16::AddDBG(const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (uint16_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }
+void CTweakInt32::AddDBG (const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (int32_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }
+void CTweakUInt32::AddDBG(const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (uint32_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }
+void CTweakFloat::AddDBG (const char *path) { DebugMenuAddVar (m_pPath == NULL ? path : m_pPath, m_pVarName, (float *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound); }
+
+/*
+static const char *wt[] = {
+ "Sunny", "Cloudy", "Rainy", "Foggy"
+ };
+
+SETTWEAKPATH("TEST");
+TWEAKSWITCH(CWeather::NewWeatherType, 0, 3, wt, NULL);
+*/
+
void
DebugMenuPopulate(void)
{
@@ -266,6 +314,8 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop);
+
+ CTweakVars::AddDBG("Debug");
}
}
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index aa2114e8..b795931f 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -405,7 +405,7 @@ CEntity::PreRender(void)
}else if(GetModelIndex() == MI_MISSILE){
CVector pos = GetPosition();
float flicker = (CGeneral::GetRandomNumber() & 0xF)/(float)0x10;
- CShadows::StoreShadowToBeRendered(SHADOWTYPE_2,
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE,
gpShadowExplosionTex, &pos,
8.0f, 0.0f, 0.0f, -8.0f,
255, 200.0f*flicker, 160.0f*flicker, 120.0f*flicker,
@@ -758,7 +758,7 @@ CEntity::ProcessLightsForEntity(void)
// Light shadow
if(effect->light.shadowRange != 0.0f){
if(lightOn){
- CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_2,
+ CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
effect->light.shadow, &pos,
effect->light.shadowRange, 0.0f,
0.0f, -effect->light.shadowRange,
@@ -768,7 +768,7 @@ CEntity::ProcessLightsForEntity(void)
effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
15.0f, 1.0f, 40.0f, false, 0.0f);
}else if(lightFlickering){
- CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_2,
+ CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
effect->light.shadow, &pos,
effect->light.shadowRange, 0.0f,
0.0f, -effect->light.shadowRange,
diff --git a/src/math/maths.h b/src/math/maths.h
index a1c3f109..51b0ef10 100644
--- a/src/math/maths.h
+++ b/src/math/maths.h
@@ -12,5 +12,6 @@ inline float Atan(float x) { return atanf(x); }
inline float Atan2(float y, float x) { return atan2f(y, x); }
inline float Abs(float x) { return fabs(x); }
inline float Sqrt(float x) { return sqrtf(x); }
-inline float RecipSqrt(float x) { return 1.0f/Sqrt(x); }
+inline float RecipSqrt(float x, float y) { return x/Sqrt(y); }
+inline float RecipSqrt(float x) { return RecipSqrt(1.0f, x); }
inline float Pow(float x, float y) { return powf(x, y); }
diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp
index 63545dff..23e23f93 100644
--- a/src/render/Particle.cpp
+++ b/src/render/Particle.cpp
@@ -226,6 +226,10 @@ int32 Randomizer;
int32 nParticleCreationInterval = 1;
float fParticleScaleLimit = 0.5f;
+SETTWEAKPATH("Particle");
+TWEAKINT32(nParticleCreationInterval, 0, 5, 1);
+TWEAKFLOAT(fParticleScaleLimit, 0.0f, 1.0f, 0.1f);
+TWEAKFUNC(CParticle::ReloadConfig);
void CParticle::ReloadConfig()
{
@@ -1143,7 +1147,7 @@ void CParticle::Update()
{
bRemoveParticle = true;
- int32 randVal = int32(CGeneral::GetRandomNumber());
+ int32 randVal = CGeneral::GetRandomNumber();
if ( randVal & 1 )
{
@@ -1188,23 +1192,19 @@ void CParticle::Update()
if ( randVal == 5 )
{
- int32 randTime = int32(CGeneral::GetRandomNumber());
-
CShadows::AddPermanentShadow(1, gpBloodPoolTex, &vecPosn,
0.1f, 0.0f, 0.0f, -0.1f,
255,
255, 0, 0,
- 4.0f, (randTime & 0xFFF) + 2000, 1.0f);
+ 4.0f, (CGeneral::GetRandomNumber() & 4095) + 2000, 1.0f);
}
else if ( randVal == 2 )
{
- int32 randTime = int32(CGeneral::GetRandomNumber());
-
CShadows::AddPermanentShadow(1, gpBloodPoolTex, &vecPosn,
0.2f, 0.0f, 0.0f, -0.2f,
255,
255, 0, 0,
- 4.0f, (randTime & 0xFFF) + 8000, 1.0f);
+ 4.0f, (CGeneral::GetRandomNumber() & 4095) + 8000, 1.0f);
}
continue;
}
@@ -1600,7 +1600,7 @@ void CParticle::Render()
fTrailLength = fDist;
//Float fRot = Atan2( vecDist.x / fDist, Sqrt(1.0f - vecDist.x / fDist * (vecDist.x / fDist)) );
- float fRot = asinf(vecDist.x / fDist);
+ float fRot = Asin(vecDist.x / fDist);
fRotation = fRot;
@@ -1652,7 +1652,7 @@ void CParticle::Render()
fTrailLength = fDist;
//Float fRot = Atan2(vecDist.x / fDist, Sqrt(1.0f - vecDist.x / fDist * (vecDist.x / fDist)));
- float fRot = asinf(vecDist.x / fDist);
+ float fRot = Asin(vecDist.x / fDist);
fRotation = fRot;
diff --git a/src/render/PointLights.h b/src/render/PointLights.h
index c350e4c8..c1dad87f 100644
--- a/src/render/PointLights.h
+++ b/src/render/PointLights.h
@@ -17,10 +17,10 @@ static_assert(sizeof(CRegisteredPointLight) == 0x2C, "CRegisteredPointLight: err
class CPointLights
{
- // Probably have to make this public for shadows later
+public:
static int16 &NumLights;
static CRegisteredPointLight *aLights; //[NUMPOINTLIGHTS]
-public:
+
enum {
LIGHT_POINT,
LIGHT_DIRECTIONAL,
diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp
index 1b91156e..f6499451 100644
--- a/src/render/RenderBuffer.cpp
+++ b/src/render/RenderBuffer.cpp
@@ -8,8 +8,8 @@ int32 &TempBufferIndicesStored = *(int32*)0x8F1A4C;
RwIm3DVertex *TempBufferRenderVertices = (RwIm3DVertex*)0x862330;
RwImVertexIndex *TempBufferRenderIndexList = (RwImVertexIndex*)0x846288;
-int RenderBuffer::VerticesToBeStored;
-int RenderBuffer::IndicesToBeStored;
+int &RenderBuffer::VerticesToBeStored = *(int*)0x8F59C4;
+int &RenderBuffer::IndicesToBeStored = *(int*)0x8E28B0;
void
RenderBuffer::ClearRenderBuffer(void)
diff --git a/src/render/RenderBuffer.h b/src/render/RenderBuffer.h
index 28bfe157..2b8a9f86 100644
--- a/src/render/RenderBuffer.h
+++ b/src/render/RenderBuffer.h
@@ -1,8 +1,8 @@
class RenderBuffer
{
public:
- static int VerticesToBeStored;
- static int IndicesToBeStored;
+ static int &VerticesToBeStored;
+ static int &IndicesToBeStored;
static void ClearRenderBuffer(void);
static void StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, RwIm3DVertex **vertexStart);
static void StopStoring(void);
diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp
index 0852938f..6bc072ce 100644
--- a/src/render/Shadows.cpp
+++ b/src/render/Shadows.cpp
@@ -1,22 +1,1820 @@
#include "common.h"
#include "patcher.h"
+#include "main.h"
+#include "TxdStore.h"
+#include "Timer.h"
+#include "Camera.h"
+#include "TimeCycle.h"
+#include "CutsceneMgr.h"
+#include "Automobile.h"
+#include "Ped.h"
+#include "PlayerPed.h"
+#include "World.h"
+#include "Weather.h"
+#include "ModelIndices.h"
+#include "RenderBuffer.h"
+#include "PointLights.h"
+#include "SpecialFX.h"
#include "Shadows.h"
-WRAPPER void CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture* pTexture, CVector* pPosn, float fX1, float fY1, float fX2, float fY2, short nTransparency, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale) { EAXJMP(0x512FD0); }
-WRAPPER void CShadows::RenderStaticShadows(void) { EAXJMP(0x5145F0); }
-WRAPPER void CShadows::RenderStoredShadows(void) { EAXJMP(0x514010); }
-WRAPPER void CShadows::RenderExtraPlayerShadows(void) { EAXJMP(0x516F90); }
-WRAPPER void CShadows::CalcPedShadowValues(CVector light, float *frontX, float *frontY, float *sideX, float *sideY, float *dispX, float *dispY) { EAXJMP(0x516EB0); }
-WRAPPER void CShadows::StoreShadowForPole(CEntity *ent, float offsetX, float offsetY, float offsetZ, float poleHeight, float poleWidth, uint32 subId) { EAXJMP(0x513E10); }
-WRAPPER void CShadows::StoreShadowForPedObject(CEntity *ent, float dispX, float dispY, float frontX, float frontY, float sideX, float sideY) { EAXJMP(0x513CB0); }
-WRAPPER void CShadows::StoreStaticShadow(uint32 id, uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, float scale, float drawDistance, bool temporaryShadow, float upDistance) { EAXJMP(0x5130A0); }
-WRAPPER void CShadows::StoreShadowToBeRendered(uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, bool drawOnWater, float upDistance) { EAXJMP(0x513750); }
+SETTWEAKPATH("Shadows");
+TWEAKBOOL(gbPrintShite);
-RwTexture *&gpBloodPoolTex = *(RwTexture**)0x9415F8;
-RwTexture *&gpShadowExplosionTex = *(RwTexture**)0x8F2A00;
+#if 1
+RwImVertexIndex ShadowIndexList[24];
+#else
+RwImVertexIndex (&ShadowIndexList)[24] = *(RwImVertexIndex (*)[24])*(int *)0x649188;
+#endif
+
+RwTexture *&gpShadowCarTex = *(RwTexture **)0x8F2C90;
+RwTexture *&gpShadowPedTex = *(RwTexture **)0x8F59D0;
+RwTexture *&gpShadowHeliTex = *(RwTexture **)0x8E2A90;
+RwTexture *&gpShadowExplosionTex = *(RwTexture **)0x8F2A00;
+RwTexture *&gpShadowHeadLightsTex = *(RwTexture **)0x95CB98;
+RwTexture *&gpOutline1Tex = *(RwTexture **)0x8F1B24;
+RwTexture *&gpOutline2Tex = *(RwTexture **)0x8F1B04;
+RwTexture *&gpOutline3Tex = *(RwTexture **)0x8F1B08;
+RwTexture *&gpBloodPoolTex = *(RwTexture **)0x9415F8;
+RwTexture *&gpReflectionTex = *(RwTexture **)0x8F582C;
+RwTexture *&gpGoalMarkerTex = *(RwTexture **)0x94142C;
+RwTexture *&gpWalkDontTex = *(RwTexture **)0x95CB4C;
+RwTexture *&gpCrackedGlassTex = *(RwTexture **)0x95CB94;
+RwTexture *&gpPostShadowTex = *(RwTexture **)0x8F59D4;
+
+#if 1
+int16 CShadows::ShadowsStoredToBeRendered;
+CStoredShadow CShadows::asShadowsStored [MAX_STOREDSHADOWS];
+CPolyBunch CShadows::aPolyBunches [MAX_POLYBUNCHES];
+CStaticShadow CShadows::aStaticShadows [MAX_STATICSHADOWS];
+CPolyBunch *CShadows::pEmptyBunchList;
+CPermanentShadow CShadows::aPermanentShadows[MAX_PERMAMENTSHADOWS];
+#else
+int16 &CShadows::ShadowsStoredToBeRendered = *(int16*)0x95CCEE;
+CStoredShadow (&CShadows::asShadowsStored)[MAX_STOREDSHADOWS] = *(CStoredShadow (*)[MAX_STOREDSHADOWS])*(int *)0x779058;
+CPolyBunch (&CShadows::aPolyBunches)[MAX_POLYBUNCHES] = *(CPolyBunch (*)[MAX_POLYBUNCHES])*(int *)0x86F4C8;
+CStaticShadow (&CShadows::aStaticShadows)[MAX_STATICSHADOWS] = *(CStaticShadow (*)[MAX_STATICSHADOWS])*(int *)0x773BE8;
+CPolyBunch *&CShadows::pEmptyBunchList = *(CPolyBunch**)0x8F435C;
+CPermanentShadow (&CShadows::aPermanentShadows)[MAX_PERMAMENTSHADOWS] = *(CPermanentShadow (*)[MAX_PERMAMENTSHADOWS])*(int *)0x712040;
+#endif
+
+void
+CShadows::Init(void)
+{
+ CTxdStore::PushCurrentTxd();
+
+ 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);
+
+ 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);
+
+
+ ShadowIndexList[0] = 0;
+ ShadowIndexList[1] = 2;
+ ShadowIndexList[2] = 1;
+
+ ShadowIndexList[3] = 0;
+ ShadowIndexList[4] = 3;
+ ShadowIndexList[5] = 2;
+
+ ShadowIndexList[6] = 0;
+ ShadowIndexList[7] = 4;
+ ShadowIndexList[8] = 3;
+
+ ShadowIndexList[9] = 0;
+ ShadowIndexList[10] = 5;
+ ShadowIndexList[11] = 4;
+
+ ShadowIndexList[12] = 0;
+ ShadowIndexList[13] = 6;
+ ShadowIndexList[14] = 5;
+
+ ShadowIndexList[15] = 0;
+ ShadowIndexList[16] = 7;
+ ShadowIndexList[17] = 6;
+
+ ShadowIndexList[18] = 0;
+ ShadowIndexList[19] = 8;
+ ShadowIndexList[20] = 7;
+
+ ShadowIndexList[21] = 0;
+ ShadowIndexList[22] = 9;
+ ShadowIndexList[23] = 8;
+
+
+ for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
+ {
+ aStaticShadows[i].m_nId = 0;
+ aStaticShadows[i].m_pPolyBunch = NULL;
+ }
+
+ pEmptyBunchList = &aPolyBunches[0];
+
+ for ( int32 i = 0; i < MAX_POLYBUNCHES; i++ )
+ {
+ if ( i == MAX_POLYBUNCHES - 1 )
+ aPolyBunches[i].m_pNext = NULL;
+ else
+ aPolyBunches[i].m_pNext = &aPolyBunches[i + 1];
+ }
+
+ for ( int32 i = 0; i < MAX_PERMAMENTSHADOWS; i++ )
+ {
+ aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
+ }
+}
+
+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);
+
+ RwTextureDestroy(gpShadowCarTex);
+ RwTextureDestroy(gpShadowPedTex);
+ RwTextureDestroy(gpShadowHeliTex);
+ RwTextureDestroy(gpShadowExplosionTex);
+ RwTextureDestroy(gpShadowHeadLightsTex);
+ RwTextureDestroy(gpOutline1Tex);
+ RwTextureDestroy(gpOutline2Tex);
+ RwTextureDestroy(gpOutline3Tex);
+ RwTextureDestroy(gpBloodPoolTex);
+ RwTextureDestroy(gpReflectionTex);
+ RwTextureDestroy(gpGoalMarkerTex);
+ RwTextureDestroy(gpWalkDontTex);
+ RwTextureDestroy(gpCrackedGlassTex);
+ RwTextureDestroy(gpPostShadowTex);
+}
+
+void
+CShadows::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)
+{
+ ASSERT(pTexture != NULL);
+ ASSERT(pPosn != NULL);
+
+
+ // find free slot
+ int32 nSlot = 0;
+ while ( nSlot < MAX_PERMAMENTSHADOWS && aPermanentShadows[nSlot].m_nType != SHADOWTYPE_NONE )
+ nSlot++;
+
+ if ( nSlot < MAX_PERMAMENTSHADOWS )
+ {
+ aPermanentShadows[nSlot].m_nType = ShadowType;
+ aPermanentShadows[nSlot].m_pTexture = pTexture;
+ aPermanentShadows[nSlot].m_vecPos = *pPosn;
+ aPermanentShadows[nSlot].m_vecFront.x = fFrontX;
+ aPermanentShadows[nSlot].m_vecFront.y = fFrontY;
+ aPermanentShadows[nSlot].m_vecSide.x = fSideX;
+ aPermanentShadows[nSlot].m_vecSide.y = fSideY;
+ aPermanentShadows[nSlot].m_nIntensity = nIntensity;
+ aPermanentShadows[nSlot].m_nRed = nRed;
+ aPermanentShadows[nSlot].m_nGreen = nGreen;
+ aPermanentShadows[nSlot].m_nBlue = nBlue;
+ aPermanentShadows[nSlot].m_fZDistance = fZDistance;
+ aPermanentShadows[nSlot].m_nLifeTime = nTime;
+ aPermanentShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+ }
+}
+
+void
+CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, 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);
+
+ float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ if ( SQR(fDrawDistance) > fDistToCamSqr)
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+ 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) )
+ nSlot++;
+
+ if ( nSlot < MAX_STATICSHADOWS )
+ {
+ if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < fUpDistance
+ && Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < fUpDistance )
+ {
+ aStaticShadows[nSlot].m_bJustCreated = true;
+ aStaticShadows[nSlot].m_nType = ShadowType;
+ aStaticShadows[nSlot].m_pTexture = pTexture;
+ aStaticShadows[nSlot].m_nIntensity = nIntensity;
+ aStaticShadows[nSlot].m_nRed = nRed;
+ aStaticShadows[nSlot].m_nGreen = nGreen;
+ aStaticShadows[nSlot].m_nBlue = nBlue;
+ aStaticShadows[nSlot].m_fZDistance = fZDistance;
+ aStaticShadows[nSlot].m_fScale = fScale;
+ aStaticShadows[nSlot].m_bTemp = bTempShadow;
+ aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f
+ && Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < 0.05f
+ && Abs(pPosn->z - aStaticShadows[nSlot].m_vecPosn.z) < 2.0f
+
+ && fFrontX == aStaticShadows[nSlot].m_vecFront.x
+ && fFrontY == aStaticShadows[nSlot].m_vecFront.y
+ && fSideX == aStaticShadows[nSlot].m_vecSide.x
+ && fSideY == aStaticShadows[nSlot].m_vecSide.y )
+ {
+ aStaticShadows[nSlot].m_bJustCreated = true;
+ aStaticShadows[nSlot].m_nType = ShadowType;
+ aStaticShadows[nSlot].m_pTexture = pTexture;
+ aStaticShadows[nSlot].m_nIntensity = nIntensity;
+ aStaticShadows[nSlot].m_nRed = nRed;
+ aStaticShadows[nSlot].m_nGreen = nGreen;
+ aStaticShadows[nSlot].m_nBlue = nBlue;
+ aStaticShadows[nSlot].m_fZDistance = fZDistance;
+ aStaticShadows[nSlot].m_fScale = fScale;
+ aStaticShadows[nSlot].m_bTemp = bTempShadow;
+ aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+ }
+ else
+ {
+ aStaticShadows[nSlot].Free();
+
+ aStaticShadows[nSlot].m_nId = nID;
+ aStaticShadows[nSlot].m_nType = ShadowType;
+ aStaticShadows[nSlot].m_pTexture = pTexture;
+ aStaticShadows[nSlot].m_nIntensity = nIntensity;
+ aStaticShadows[nSlot].m_nRed = nRed;
+ aStaticShadows[nSlot].m_nGreen = nGreen;
+ aStaticShadows[nSlot].m_nBlue = nBlue;
+ aStaticShadows[nSlot].m_fZDistance = fZDistance;
+ aStaticShadows[nSlot].m_fScale = fScale;
+ aStaticShadows[nSlot].m_vecPosn = *pPosn;
+ aStaticShadows[nSlot].m_vecFront.x = fFrontX;
+ aStaticShadows[nSlot].m_vecFront.y = fFrontY;
+ aStaticShadows[nSlot].m_vecSide.x = fSideX;
+ aStaticShadows[nSlot].m_vecSide.y = fSideY;
+ aStaticShadows[nSlot].m_bJustCreated = true;
+ aStaticShadows[nSlot].m_bTemp = bTempShadow;
+ aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+
+ GeneratePolysForStaticShadow(nSlot);
+ }
+ }
+ else
+ {
+ nSlot = 0;
+ while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != NULL )
+ nSlot++;
+
+ if ( nSlot != MAX_STATICSHADOWS )
+ {
+ aStaticShadows[nSlot].m_nId = nID;
+ aStaticShadows[nSlot].m_nType = ShadowType;
+ aStaticShadows[nSlot].m_pTexture = pTexture;
+ aStaticShadows[nSlot].m_nIntensity = nIntensity;
+ aStaticShadows[nSlot].m_nRed = nRed;
+ aStaticShadows[nSlot].m_nGreen = nGreen;
+ aStaticShadows[nSlot].m_nBlue = nBlue;
+ aStaticShadows[nSlot].m_fZDistance = fZDistance;
+ aStaticShadows[nSlot].m_fScale = fScale;
+ aStaticShadows[nSlot].m_vecPosn = *pPosn;
+ aStaticShadows[nSlot].m_vecFront.x = fFrontX;
+ aStaticShadows[nSlot].m_vecFront.y = fFrontY;
+ aStaticShadows[nSlot].m_vecSide.x = fSideX;
+ aStaticShadows[nSlot].m_vecSide.y = fSideY;
+ aStaticShadows[nSlot].m_bJustCreated = true;
+ aStaticShadows[nSlot].m_bTemp = bTempShadow;
+ aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+
+ GeneratePolysForStaticShadow(nSlot);
+ }
+ }
+ }
+}
+
+void
+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);
+
+ switch ( ShadowTexture )
+ {
+ case SHADOWTEX_NONE:
+ {
+ break;
+ }
+
+ case SHADOWTEX_CAR:
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, pPosn,
+ fFrontX, fFrontY, fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ 15.0f, false, 1.0f);
+
+ break;
+ }
+
+ case SHADOWTEX_PED:
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, pPosn,
+ fFrontX, fFrontY, fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ 15.0f, false, 1.0f);
+
+ break;
+ }
+
+ case SHADOWTEX_EXPLOSION:
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, pPosn,
+ fFrontX, fFrontY, fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ 15.0f, false, 1.0f);
+
+ break;
+ }
+
+ case SHADOWTEX_HELI:
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowHeliTex, pPosn,
+ fFrontX, fFrontY, fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ 15.0f, false, 1.0f);
+
+ break;
+ }
+
+ case SHADOWTEX_HEADLIGHTS:
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowHeadLightsTex, pPosn,
+ fFrontX, fFrontY, fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ 15.0f, false, 1.0f);
+
+ break;
+ }
+
+ case SHADOWTEX_BLOOD:
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpBloodPoolTex, pPosn,
+ fFrontX, fFrontY, fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ 15.0f, false, 1.0f);
+
+ break;
+ }
+ }
+
+ ASSERT(false);
+}
+
+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)
+{
+ ASSERT(pTexture != NULL);
+ ASSERT(pPosn != NULL);
+
+ 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;
+
+ ShadowsStoredToBeRendered++;
+ }
+}
+
+void
+CShadows::StoreShadowForCar(CAutomobile *pCar)
+{
+ ASSERT(pCar != NULL);
+
+ if ( CTimeCycle::GetShadowStrength() != 0 )
+ {
+ CVector CarPos = pCar->GetPosition();
+ float fDistToCamSqr = (CarPos - TheCamera.GetPosition()).MagnitudeSqr();
+
+ if ( CCutsceneMgr::IsRunning() )
+ fDistToCamSqr /= SQR(TheCamera.LODDistMultiplier) * 4.0f;
+
+ float fDrawDistance = 18.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance) )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+ //fDistToCam == 0 -> 4
+ //fDistToCam == fDrawDistance -> 0
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))) );
+
+ int32 nColorStrength;
+
+ if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
+ nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ else
+ nColorStrength = CTimeCycle::GetShadowStrength();
+
+ float fVehicleHeight = pCar->GetColModel()->boundingBox.GetSize().y;
+ float fVehicleWidth = pCar->GetColModel()->boundingBox.GetSize().x;
+
+ 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 )
+ {
+ 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);
+ }
+ 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);
+ }
+ }
+ }
+}
+
+void
+CShadows::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)
+{
+ ASSERT(pCar != NULL);
+ ASSERT(pPosn != NULL);
+
+ float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ bool bSpecialCam = TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1
+ || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED
+ || CCutsceneMgr::IsRunning();
+
+ float fDrawDistance = 27.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance) || bSpecialCam )
+ {
+ if ( bSpecialCam || DotProduct2D(CVector2D(TheCamera.CamFrontXNorm, TheCamera.CamFrontYNorm),
+ *pPosn - TheCamera.GetPosition() ) > -fMaxViewAngle )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+#ifndef FIX_BUGS
+ if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) && !bSpecialCam ) // BUG: must be 3.0
+#else
+ if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/3.0f))) && !bSpecialCam )
+#endif
+ {
+ //fDistToCam == 0 -> 3
+ //fDistToCam == fDrawDistance -> 0
+ float fMult = 1.0f - (3.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/3.0f))) );
+
+ nRed = (int32)(nRed * fMult);
+ nGreen = (int32)(nGreen * fMult);
+ nBlue = (int32)(nBlue * fMult);
+ }
+
+ StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ 128, nRed, nGreen, nBlue,
+ 6.0f, false, 1.0f);
+
+ }
+ }
+}
+
+void
+CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacementY,
+ float fFrontX, float fFrontY, float fSideX, float fSideY)
+{
+ ASSERT(pPed != NULL);
+
+ if ( pPed->bIsVisible )
+ {
+ if ( !(pPed->bInVehicle && pPed->m_nPedState != PED_DRAG_FROM_CAR && pPed->m_nPedState != PED_EXIT_CAR) )
+ {
+ if ( CTimeCycle::GetShadowStrength() != 0 )
+ StoreShadowForPedObject(pPed,
+ fDisplacementX, fDisplacementY,
+ fFrontX, fFrontY,
+ fSideX, fSideY);
+ }
+ }
+}
+
+void
+CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, float fDisplacementY,
+ float fFrontX, float fFrontY, float fSideX, float fSideY)
+{
+ ASSERT(pPedObject != NULL);
+
+ CVector PedPos = pPedObject->GetPosition();
+
+ float fDistToCamSqr = (PedPos - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ float fDrawDistance = 26.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f)/*?*/ )
+ {
+ if ( pPedObject == FindPlayerPed() || TheCamera.IsSphereVisible(PedPos, 2.0f) != false )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+#ifndef FIX_BUGS
+ //fDistToCam == 0 -> 2
+ //fDistToCam == fDrawDistance -> -2
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f))); // BUG: negative
+#else
+ //fDistToCam == 0 -> 4
+ //fDistToCam == fDrawDistance -> 0
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))) );
+#endif
+ int32 nColorStrength;
+
+#ifndef FIX_BUGS
+ if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) ) // BUG: negative
+#else
+ if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
+#endif
+ nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ else
+ nColorStrength = CTimeCycle::GetShadowStrength();
+
+ PedPos.x += fDisplacementX;
+ PedPos.y += fDisplacementY;
+
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &PedPos,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.0f, false, 1.0f);
+ }
+ }
+}
+
+void
+CShadows::StoreShadowForTree(CEntity *pTree)
+{
+ ASSERT(pTree != NULL);
+}
+
+void
+CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ,
+ float fPoleHeight, float fPoleWidth, uint32 nID)
+{
+ ASSERT(pPole != NULL);
+
+ if ( CTimeCycle::GetShadowStrength() != 0 )
+ {
+ if ( pPole->GetUp().z < 0.5f )
+ return;
+
+ CVector PolePos = pPole->GetPosition();
+
+ PolePos.x += fOffsetX * pPole->GetRight().x + fOffsetY * pPole->GetForward().x;
+ PolePos.y += fOffsetX * pPole->GetRight().y + fOffsetY * pPole->GetForward().y;
+ PolePos.z += fOffsetZ;
+
+ PolePos.x += -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2);
+ PolePos.y += -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2);
+
+ StoreStaticShadow((uint32)pPole + nID + _TODOCONST(51), SHADOWTYPE_DARK, gpPostShadowTex, &PolePos,
+ -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2),
+ -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2),
+ CTimeCycle::GetShadowSideX() * fPoleWidth,
+ CTimeCycle::GetShadowSideY() * fPoleWidth,
+ 2 * (int32)((pPole->GetUp().z - 0.5f) * CTimeCycle::GetShadowStrength() * 2.0f) / 3,
+ 0, 0, 0,
+ 15.0f, 1.0f, 40.0f, false, 0.0f);
+ }
+}
+
+void
+CShadows::SetRenderModeForShadowType(uint8 ShadowType)
+{
+ switch ( ShadowType )
+ {
+ case SHADOWTYPE_DARK:
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ break;
+ }
+
+ case SHADOWTYPE_ADDITIVE:
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);
+ break;
+ }
+
+ case SHADOWTYPE_INVCOLOR:
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCCOLOR);
+ break;
+ }
+ }
+}
+
+void
+CShadows::RenderStoredShadows(void)
+{
+ RenderBuffer::ClearRenderBuffer();
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+
+ 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);
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(asShadowsStored[i].m_pTexture));
+
+ for ( int32 j = i; j < ShadowsStoredToBeRendered; j++ )
+ {
+ if ( asShadowsStored[i].m_ShadowType == asShadowsStored[j].m_ShadowType
+ && asShadowsStored[i].m_pTexture == asShadowsStored[j].m_pTexture )
+ {
+ float fWidth = Abs(asShadowsStored[j].m_vecFront.x) + Abs(asShadowsStored[j].m_vecSide.x);
+ float fHeight = Abs(asShadowsStored[j].m_vecFront.y) + Abs(asShadowsStored[j].m_vecSide.y);
+
+ CVector shadowPos = asShadowsStored[j].m_vecPos;
+
+ float fStartX = shadowPos.x - fWidth;
+ float fEndX = shadowPos.x + fWidth;
+ float fStartY = shadowPos.y - fHeight;
+ float fEndY = shadowPos.y + fHeight;
+
+ int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0);
+ int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0);
+ int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1);
+ int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1);
+
+ CWorld::AdvanceCurrentScanCode();
+
+ for ( int32 y = nStartY; y <= nEndY; y++ )
+ {
+ for ( int32 x = nStartX; x <= nEndX; x++ )
+ {
+ 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);
+ }
+ }
+
+ asShadowsStored[j].m_nFlags.bRendered = true;
+ }
+ }
+
+ RenderBuffer::RenderStuffInBuffer();
+ }
+
+ }
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+
+ ShadowsStoredToBeRendered = 0;
+}
+
+void
+CShadows::RenderStaticShadows(void)
+{
+ RenderBuffer::ClearRenderBuffer();
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
+
+ for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
+ aStaticShadows[i].m_bRendered = false;
+
+ for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
+ {
+ if ( aStaticShadows[i].m_pPolyBunch && !aStaticShadows[i].m_bRendered )
+ {
+ SetRenderModeForShadowType(aStaticShadows[i].m_nType);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aStaticShadows[i].m_pTexture));
+
+ // optimization trick, render all shadows with same renderstate and texture
+ for ( int32 j = i; j < MAX_STATICSHADOWS; j++ )
+ {
+ if ( aStaticShadows[j].m_pPolyBunch != NULL
+ && 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 )
+ {
+ RwImVertexIndex *pIndexes;
+ RwIm3DVertex *pVerts;
+
+ RenderBuffer::StartStoring(3 * (bunch->m_nNumVerts - 2), bunch->m_nNumVerts, &pIndexes, &pVerts);
+
+ ASSERT(pIndexes != NULL);
+ ASSERT(pVerts != NULL);
+
+ for ( int32 k = 0; k < bunch->m_nNumVerts; k++ )
+ {
+ RwIm3DVertexSetRGBA(&pVerts[k],
+ aStaticShadows[j].m_nRed,
+ aStaticShadows[j].m_nGreen,
+ aStaticShadows[j].m_nBlue,
+ (int32)(aStaticShadows[j].m_nIntensity * (1.0f - CWeather::Foggyness * 0.5f)));
+
+ RwIm3DVertexSetU (&pVerts[k], bunch->m_aU[k] / 200.0f);
+ RwIm3DVertexSetV (&pVerts[k], bunch->m_aV[k] / 200.0f);
+ RwIm3DVertexSetPos(&pVerts[k], bunch->m_aVerts[k].x, bunch->m_aVerts[k].y, bunch->m_aVerts[k].z + 0.03f);
+ }
+
+ for ( int32 k = 0; k < 3 * (bunch->m_nNumVerts - 2); k++ )
+ pIndexes[k] = ShadowIndexList[k];
+
+ RenderBuffer::StopStoring();
+ }
+
+ aStaticShadows[j].m_bRendered = true;
+ }
+ }
+
+ RenderBuffer::RenderStuffInBuffer();
+ }
+ }
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
+}
+
+void
+CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
+{
+ float fWidth = Abs(aStaticShadows[nStaticShadowID].m_vecFront.x) + Abs(aStaticShadows[nStaticShadowID].m_vecSide.x);
+ float fHeight = Abs(aStaticShadows[nStaticShadowID].m_vecFront.y) + Abs(aStaticShadows[nStaticShadowID].m_vecSide.y);
+
+ CVector shadowPos = aStaticShadows[nStaticShadowID].m_vecPosn;
+
+ float fStartX = shadowPos.x - fWidth;
+ float fEndX = shadowPos.x + fWidth;
+ float fStartY = shadowPos.y - fHeight;
+ float fEndY = shadowPos.y + fHeight;
+
+ int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0);
+ int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0);
+ int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1);
+ int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1);
+
+ CWorld::AdvanceCurrentScanCode();
+
+ for ( int32 y = nStartY; y <= nEndY; y++ )
+ {
+ for ( int32 x = nStartX; x <= nEndX; x++ )
+ {
+ CSector *pCurSector = CWorld::GetSector(x, y);
+
+ ASSERT(pCurSector != NULL);
+
+ CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ aStaticShadows[nStaticShadowID].m_vecFront.x,
+ aStaticShadows[nStaticShadowID].m_vecFront.y,
+ aStaticShadows[nStaticShadowID].m_vecSide.x,
+ aStaticShadows[nStaticShadowID].m_vecSide.y,
+ 0, 0, 0, 0,
+ aStaticShadows[nStaticShadowID].m_fZDistance,
+ aStaticShadows[nStaticShadowID].m_fScale,
+ &aStaticShadows[nStaticShadowID].m_pPolyBunch);
+
+ CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ aStaticShadows[nStaticShadowID].m_vecFront.x,
+ aStaticShadows[nStaticShadowID].m_vecFront.y,
+ aStaticShadows[nStaticShadowID].m_vecSide.x,
+ aStaticShadows[nStaticShadowID].m_vecSide.y,
+ 0, 0, 0, 0,
+ aStaticShadows[nStaticShadowID].m_fZDistance,
+ aStaticShadows[nStaticShadowID].m_fScale,
+ &aStaticShadows[nStaticShadowID].m_pPolyBunch);
+ }
+ }
+}
void
-CShadows::StoreShadowForTree(CEntity *ent)
+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)
{
- // empty
+ ASSERT(pPosn != NULL);
+
+ CPtrNode *pNode = PtrList.first;
+
+ CRect Bound;
+
+ while ( pNode != NULL )
+ {
+ CEntity *pEntity = (CEntity *)pNode->item;
+ uint16 nScanCode = pEntity->m_scanCode;
+ pNode = pNode->next;
+
+ ASSERT( pEntity != NULL );
+
+ if ( nScanCode != CWorld::GetCurrentScanCode() )
+ {
+ if ( pEntity->bUsesCollision && pEntity->IsBuilding() )
+ {
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ 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 )
+ {
+ CastShadowEntity(pEntity,
+ fStartX, fStartY,
+ fEndX, fEndY,
+ pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch);
+ }
+ }
+ }
+ }
+ }
}
+
+void
+CShadows::CastShadowEntity(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);
+
+ static CVector List [20];
+ static CVector Texture[20];
+ static CVector Points [4];
+
+ CColModel *pCol = pEntity->GetColModel();
+ ASSERT(pCol != NULL);
+
+#ifndef MASTER
+ if ( gbPrintShite )
+ printf("MI:%d Triangles:%d Coors:%f %f BBoxXY:%f %f\n",
+ pEntity->GetModelIndex(),
+ pCol->numTriangles,
+ pEntity->GetPosition().x,
+ pEntity->GetPosition().y,
+ pCol->boundingBox.GetSize().x,
+ pCol->boundingBox.GetSize().y);
+#endif
+
+ CCollision::CalculateTrianglePlanes(pCol);
+
+ float fFrontRight = DotProduct2D(CVector2D(fFrontX, fFrontY), pEntity->GetRight());
+ float fFrontForward = DotProduct2D(CVector2D(fFrontX, fFrontY), pEntity->GetForward());
+ float fSideRight = DotProduct2D(CVector2D(fSideX, fSideY), pEntity->GetRight());
+ float fSideForward = DotProduct2D(CVector2D(fSideX, fSideY), pEntity->GetForward());
+ float fLengthRight = DotProduct2D(*pPosn - pEntity->GetPosition(), pEntity->GetRight());
+ float fLengthForward = DotProduct2D(*pPosn - pEntity->GetPosition(), pEntity->GetForward());
+
+ Points[0].x = (fLengthRight + fFrontRight ) - fSideRight;
+ Points[0].y = (fLengthForward + fFrontForward) - fSideForward;
+
+ Points[1].x = fSideRight + (fLengthRight + fFrontRight);
+ Points[1].y = fSideForward + (fLengthForward + fFrontForward);
+
+ Points[2].x = fSideRight + (fLengthRight - fFrontRight);
+ Points[2].y = fSideForward + (fLengthForward - fFrontForward);
+
+ Points[3].x = (fLengthRight - fFrontRight) - fSideRight;
+ Points[3].y = (fLengthForward - fFrontForward) - fSideForward;
+
+ float MinX = min(min(Points[0].x, Points[1].x), min(Points[2].x, Points[3].x));
+ float MaxX = max(max(Points[0].x, Points[1].x), max(Points[2].x, Points[3].x));
+
+ float MinY = min(min(Points[0].y, Points[1].y), min(Points[2].y, Points[3].y));
+ float MaxY = max(max(Points[0].y, Points[1].y), max(Points[2].y, Points[3].y));
+
+ float MaxZ = pPosn->z - pEntity->GetPosition().z;
+ float MinZ = MaxZ - fZDistance;
+
+ for ( int32 i = 0; i < pCol->numTriangles; i++ )
+ {
+ CColTrianglePlane *pColTriPlanes = pCol->trianglePlanes;
+ ASSERT(pColTriPlanes != NULL);
+
+ if ( Abs(pColTriPlanes[i].normal.z) > 0.1f )
+ {
+ CColTriangle *pColTri = pCol->triangles;
+ ASSERT(pColTri != NULL);
+
+ CVector PointA, PointB, PointC;
+
+ pCol->GetTrianglePoint(PointA, pColTri[i].a);
+ pCol->GetTrianglePoint(PointB, pColTri[i].b);
+ pCol->GetTrianglePoint(PointC, pColTri[i].c);
+
+ if ( (PointA.x > MinX || PointB.x > MinX || PointC.x > MinX)
+ && (PointA.x < MaxX || PointB.x < MaxX || PointC.x < MaxX)
+ && (PointA.y > MinY || PointB.y > MinY || PointC.y > MinY)
+ && (PointA.y < MaxY || PointB.y < MaxY || PointC.y < MaxY)
+ && (PointA.z < MaxZ || PointB.z < MaxZ || PointC.z < MaxZ)
+ && (PointA.z > MinZ || PointB.z > MinZ || PointC.z > MinZ) )
+
+ {
+ List[0].x = Points[0].x;
+ List[0].y = Points[0].y;
+
+ List[1].x = Points[1].x;
+ List[1].y = Points[1].y;
+
+ List[2].x = Points[2].x;
+ List[2].y = Points[2].y;
+
+ List[3].x = Points[3].x;
+ List[3].y = Points[3].y;
+
+ Texture[0].x = 0.0f;
+ Texture[0].y = 0.0f;
+
+ Texture[1].x = 1.0f;
+ Texture[1].y = 0.0f;
+
+ Texture[2].x = 1.0f;
+ Texture[2].y = 1.0f;
+
+ Texture[3].x = 0.0f;
+ Texture[3].y = 1.0f;
+
+
+ CVector2D start;
+ CVector2D dist;
+
+ int32 numVerts1 = 0;
+ int16 vertType1 = 0;
+ {
+ for ( int32 j = 0; j < 4; j++ )
+ {
+ start = PointA;
+ dist = PointB - PointA;
+
+ int32 in = j;
+
+ float cp = CrossProduct2D(CVector2D(List[in]) - start, dist);
+
+ if ( cp > 0.0f )
+ {
+ switch ( vertType1 )
+ {
+ case 0:
+ {
+ int32 out = numVerts1++ + 10;
+
+ Texture[out].x = Texture[in].x;
+ Texture[out].y = Texture[in].y;
+ List[out].x = List[in].x;
+ List[out].y = List[in].y;
+
+ break;
+ }
+
+ case 1:
+ {
+ int32 out = numVerts1++ + 10;
+
+ Texture[out].x = Texture[in].x;
+ Texture[out].y = Texture[in].y;
+ List[out].x = List[in].x;
+ List[out].y = List[in].y;
+
+ break;
+ }
+
+ case 2:
+ {
+ float prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));
+ float Compl = 1.0f - Scale;
+
+ int32 out1 = numVerts1++ + 10;
+ int32 out2 = numVerts1++ + 10;
+
+ Texture[out1].x = Compl*Texture[in-1].x + Scale*Texture[in].x;
+ Texture[out1].y = Compl*Texture[in-1].y + Scale*Texture[in].y;
+ List[out1].x = Compl*List[in-1].x + Scale*List[in].x;
+ List[out1].y = Compl*List[in-1].y + Scale*List[in].y;
+
+ Texture[out2].x = Texture[in].x;
+ Texture[out2].y = Texture[in].y;
+ List[out2].x = List[in].x;
+ List[out2].y = List[in].y;
+
+ break;
+ }
+ }
+
+ vertType1 = 1;
+ }
+ else
+ {
+ switch ( vertType1 )
+ {
+ case 1:
+ {
+ float prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));
+ float Compl = 1.0f - Scale;
+
+ int32 out = numVerts1++ + 10;
+
+ Texture[out].x = Compl*Texture[in-1].x + Scale*Texture[in].x;
+ Texture[out].y = Compl*Texture[in-1].y + Scale*Texture[in].y;
+ List[out].x = Compl*List[in-1].x + Scale*List[in].x;
+ List[out].y = Compl*List[in-1].y + Scale*List[in].y;
+
+ break;
+ }
+ }
+
+ vertType1 = 2;
+ }
+ }
+
+ float cp1 = CrossProduct2D(CVector2D(List[0]) - start, dist);
+ if ( cp1 > 0.0f && vertType1 == 2 || cp1 <= 0.0f && vertType1 == 1 )
+ {
+ float cp2 = CrossProduct2D(CVector2D(List[3]) - start, dist);
+
+ float Scale = Abs(cp2) / (Abs(cp2) + Abs(cp1));
+ float Compl = 1.0f - Scale;
+
+ int32 out = numVerts1++ + 10;
+
+ Texture[out].x = Compl*Texture[3].x + Scale*Texture[0].x;
+ Texture[out].y = Compl*Texture[3].y + Scale*Texture[0].y;
+ List[out].x = Compl*List[3].x + Scale*List[0].x;
+ List[out].y = Compl*List[3].y + Scale*List[0].y;
+ }
+ }
+
+ int32 numVerts2 = 0;
+ int16 vertType2 = 0;
+ {
+ for ( int32 j = 0; j < numVerts1; j++ )
+ {
+ start = PointB;
+ dist = PointC - PointB;
+
+ int32 in = j + 10;
+ float cp = CrossProduct2D(CVector2D(List[in]) - start, dist);
+
+ if ( cp > 0.0f )
+ {
+ switch ( vertType2 )
+ {
+ case 0:
+ {
+ int32 out = numVerts2++;
+
+ Texture[out].x = Texture[in].x;
+ Texture[out].y = Texture[in].y;
+ List[out].x = List[in].x;
+ List[out].y = List[in].y;
+
+ break;
+ }
+
+ case 1:
+ {
+ int32 out = numVerts2++;
+
+ Texture[out].x = Texture[in].x;
+ Texture[out].y = Texture[in].y;
+ List[out].x = List[in].x;
+ List[out].y = List[in].y;
+
+ break;
+ }
+
+ case 2:
+ {
+ float prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));
+ float Compl = 1.0f - Scale;
+
+ int32 out1 = numVerts2++;
+ int32 out2 = numVerts2++;
+
+ Texture[out1].x = Compl*Texture[in-1].x + Scale*Texture[in].x;
+ Texture[out1].y = Compl*Texture[in-1].y + Scale*Texture[in].y;
+ List[out1].x = Compl*List[in-1].x + Scale*List[in].x;
+ List[out1].y = Compl*List[in-1].y + Scale*List[in].y;
+
+ Texture[out2].x = Texture[in].x;
+ Texture[out2].y = Texture[in].y;
+ List[out2].x = List[in].x;
+ List[out2].y = List[in].y;
+
+ break;
+ }
+ }
+
+ vertType2 = 1;
+ }
+ else
+ {
+ switch ( vertType2 )
+ {
+ case 1:
+ {
+ float prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));
+ float Compl = 1.0f - Scale;
+
+ int32 out = numVerts2++;
+
+ Texture[out].x = Compl*Texture[in-1].x + Scale*Texture[in].x;
+ Texture[out].y = Compl*Texture[in-1].y + Scale*Texture[in].y;
+ List[out].x = Compl*List[in-1].x + Scale*List[in].x;
+ List[out].y = Compl*List[in-1].y + Scale*List[in].y;
+
+ break;
+ }
+ }
+
+ vertType2 = 2;
+ }
+ }
+
+ float cp1 = CrossProduct2D(CVector2D(List[10]) - start, dist);
+ if ( cp1 > 0.0f && vertType2 == 2 || cp1 <= 0.0f && vertType2 == 1 )
+ {
+ int32 in = numVerts1 + 10;
+
+ float cp2 = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(cp2) / (Abs(cp2) + Abs(cp1));
+ float Compl = 1.0f - Scale;
+
+ int32 out = numVerts2++;
+
+ Texture[out].x = Compl*Texture[in-1].x + Scale*Texture[10].x;
+ Texture[out].y = Compl*Texture[in-1].y + Scale*Texture[10].y;
+ List[out].x = Compl*List[in-1].x + Scale*List[10].x;
+ List[out].y = Compl*List[in-1].y + Scale*List[10].y;
+ }
+ }
+
+ int32 numVerts3 = 0;
+ int16 vertType3 = 0;
+ {
+ for ( int32 j = 0; j < numVerts2; j++ )
+ {
+ start = PointC;
+ dist = PointA - PointC;
+
+ int32 in = j;
+ float cp = CrossProduct2D(CVector2D(List[in]) - start, dist);
+
+ if ( cp > 0.0f )
+ {
+ switch ( vertType3 )
+ {
+ case 0:
+ {
+ int32 out = numVerts3++ + 10;
+
+ Texture[out].x = Texture[in].x;
+ Texture[out].y = Texture[in].y;
+ List[out].x = List[in].x;
+ List[out].y = List[in].y;
+
+ break;
+ }
+
+ case 1:
+ {
+ int32 out = numVerts3++ + 10;
+
+ Texture[out].x = Texture[in].x;
+ Texture[out].y = Texture[in].y;
+ List[out].x = List[in].x;
+ List[out].y = List[in].y;
+
+ break;
+ }
+
+ case 2:
+ {
+ float prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));
+ float Compl = 1.0f - Scale;
+
+ int32 out1 = numVerts3++ + 10;
+ int32 out2 = numVerts3++ + 10;
+
+ Texture[out1].x = Compl*Texture[in-1].x + Scale*Texture[in].x;
+ Texture[out1].y = Compl*Texture[in-1].y + Scale*Texture[in].y;
+ List[out1].x = Compl*List[in-1].x + Scale*List[in].x;
+ List[out1].y = Compl*List[in-1].y + Scale*List[in].y;
+
+ Texture[out2].x = Texture[in].x;
+ Texture[out2].y = Texture[in].y;
+ List[out2].x = List[in].x;
+ List[out2].y = List[in].y;
+
+ break;
+ }
+ }
+
+ vertType3 = 1;
+ }
+ else
+ {
+ switch ( vertType3 )
+ {
+ case 1:
+ {
+ float prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));
+ float Compl = 1.0f - Scale;
+
+ int32 out = numVerts3++ + 10;
+
+ Texture[out].x = Compl*Texture[in-1].x + Scale*Texture[in].x;
+ Texture[out].y = Compl*Texture[in-1].y + Scale*Texture[in].y;
+ List[out].x = Compl*List[in-1].x + Scale*List[in].x;
+ List[out].y = Compl*List[in-1].y + Scale*List[in].y;
+
+ break;
+ }
+ }
+
+ vertType3 = 2;
+ }
+ }
+
+ float cp1 = CrossProduct2D(CVector2D(List[0]) - start, dist);
+ if ( cp1 > 0.0f && vertType3 == 2 || cp1 <= 0.0f && vertType3 == 1 )
+ {
+ int32 in = numVerts2;
+
+ float cp2 = CrossProduct2D(CVector2D(List[in-1]) - start, dist);
+
+ float Scale = Abs(cp2) / (Abs(cp2) + Abs(cp1));
+ float Compl = 1.0f - Scale;
+
+ int32 out = numVerts3++ + 10;
+
+ Texture[out].x = Compl*Texture[in-1].x + Scale*Texture[0].x;
+ Texture[out].y = Compl*Texture[in-1].y + Scale*Texture[0].y;
+ List[out].x = Compl*List[in-1].x + Scale*List[0].x;
+ List[out].y = Compl*List[in-1].y + Scale*List[0].y;
+ }
+ }
+
+ if ( numVerts3 >= 3 )
+ {
+ CVector norm;
+
+ pColTriPlanes[i].GetNormal(norm);
+
+ float dot = DotProduct(norm, PointA);
+
+ for ( int32 j = 0; j < numVerts3; j++ )
+ {
+ int32 idx = j + 10;
+
+ List[idx].z = -(DotProduct2D(norm, List[idx]) - dot) / norm.z;
+ }
+
+ for ( int32 j = 0; j < numVerts3; j++ )
+ {
+ int32 idx = j + 10;
+
+ CVector p = List[idx];
+
+ List[idx].x = p.y * pEntity->GetForward().x + p.x * pEntity->GetRight().x + pEntity->GetPosition().x;
+ List[idx].y = p.y * pEntity->GetForward().y + p.x * pEntity->GetRight().y + pEntity->GetPosition().y;
+ List[idx].z = p.z + pEntity->GetPosition().z;
+ }
+
+
+ if ( ppPolyBunch != NULL )
+ {
+ if ( pEmptyBunchList != NULL )
+ {
+ CPolyBunch *pBunch = pEmptyBunchList;
+ ASSERT(pBunch != NULL);
+ pEmptyBunchList = pEmptyBunchList->m_pNext;
+ pBunch->m_pNext = *ppPolyBunch;
+ *ppPolyBunch = pBunch;
+
+ pBunch->m_nNumVerts = numVerts3;
+
+ for ( int32 j = 0; j < numVerts3; j++ )
+ {
+ int32 in = j + 10;
+
+ pBunch->m_aVerts[j] = List[in];
+
+ pBunch->m_aU[j] = (int32)(Texture[in].x * 200.0f);
+ pBunch->m_aV[j] = (int32)(Texture[in].y * 200.0f);
+ }
+ }
+ }
+ else
+ {
+ RwImVertexIndex *pIndexes;
+ RwIm3DVertex *pVerts;
+
+ RenderBuffer::StartStoring(3 * (numVerts3 - 2), numVerts3, &pIndexes, &pVerts);
+
+ ASSERT(pIndexes != NULL);
+ ASSERT(pVerts != NULL);
+
+
+ for ( int32 j = 0; j < numVerts3; j++ )
+ {
+ int32 in = j + 10;
+
+ RwIm3DVertexSetRGBA(&pVerts[j], nRed, nGreen, nBlue, nIntensity);
+ RwIm3DVertexSetU (&pVerts[j], Texture[in].x*fScale);
+ RwIm3DVertexSetV (&pVerts[j], Texture[in].y*fScale);
+ RwIm3DVertexSetPos (&pVerts[j], List[in].x, List[in].y, List[in].z + 0.03f);
+ }
+
+ for ( int32 j = 0; j < 3*(numVerts3 - 2); j++ )
+ pIndexes[j] = ShadowIndexList[j];
+
+ RenderBuffer::StopStoring();
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CShadows::UpdateStaticShadows(void)
+{
+ for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
+ {
+ if ( aStaticShadows[i].m_pPolyBunch != NULL && !aStaticShadows[i].m_bJustCreated
+ && (!aStaticShadows[i].m_bTemp || CTimer::GetTimeInMilliseconds() > aStaticShadows[i].m_nTimeCreated + 5000) )
+ {
+ aStaticShadows[i].Free();
+ }
+
+ aStaticShadows[i].m_bJustCreated = false;
+ }
+}
+
+void
+CShadows::UpdatePermanentShadows(void)
+{
+ for ( int32 i = 0; i < MAX_PERMAMENTSHADOWS; i++ )
+ {
+ if ( aPermanentShadows[i].m_nType != SHADOWTYPE_NONE )
+ {
+ uint32 timePassed = CTimer::GetTimeInMilliseconds() - aPermanentShadows[i].m_nTimeCreated;
+
+ if ( timePassed >= aPermanentShadows[i].m_nLifeTime )
+ aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
+ else
+ {
+ if ( timePassed >= (aPermanentShadows[i].m_nLifeTime*(1-(1/4))) )
+ {
+ // timePassed == 0 -> 4
+ // timePassed == aPermanentShadows[i].m_nLifeTime -> 0
+ float fMult = 1.0f - (timePassed - (aPermanentShadows[i].m_nLifeTime*(1-(1/4)))) / (aPermanentShadows[i].m_nLifeTime / 4);
+
+ StoreStaticShadow((uint32)&aPermanentShadows[i],
+ aPermanentShadows[i].m_nType,
+ aPermanentShadows[i].m_pTexture,
+ &aPermanentShadows[i].m_vecPos,
+ aPermanentShadows[i].m_vecFront.x,
+ aPermanentShadows[i].m_vecFront.y,
+ aPermanentShadows[i].m_vecSide.x,
+ aPermanentShadows[i].m_vecSide.y,
+ (int32)(aPermanentShadows[i].m_nIntensity * fMult),
+ (int32)(aPermanentShadows[i].m_nRed * fMult),
+ (int32)(aPermanentShadows[i].m_nGreen * fMult),
+ (int32)(aPermanentShadows[i].m_nBlue * fMult),
+ aPermanentShadows[i].m_fZDistance,
+ 1.0f, 40.0f, false, 0.0f);
+ }
+ else
+ {
+ StoreStaticShadow((uint32)&aPermanentShadows[i],
+ aPermanentShadows[i].m_nType,
+ aPermanentShadows[i].m_pTexture,
+ &aPermanentShadows[i].m_vecPos,
+ aPermanentShadows[i].m_vecFront.x,
+ aPermanentShadows[i].m_vecFront.y,
+ aPermanentShadows[i].m_vecSide.x,
+ aPermanentShadows[i].m_vecSide.y,
+ aPermanentShadows[i].m_nIntensity,
+ aPermanentShadows[i].m_nRed,
+ aPermanentShadows[i].m_nGreen,
+ aPermanentShadows[i].m_nBlue,
+ aPermanentShadows[i].m_fZDistance,
+ 1.0f, 40.0f, false, 0.0f);
+ }
+ }
+ }
+ }
+}
+
+void
+CStaticShadow::Free(void)
+{
+ if ( m_pPolyBunch != NULL )
+ {
+ CPolyBunch *pFree = CShadows::pEmptyBunchList;
+ CShadows::pEmptyBunchList = m_pPolyBunch;
+
+ CPolyBunch *pUsed = m_pPolyBunch;
+ while (pUsed->m_pNext != NULL)
+ pUsed = pUsed->m_pNext;
+
+ pUsed->m_pNext = pFree;
+ }
+
+ m_pPolyBunch = NULL;
+
+ m_nId = 0;
+}
+
+void
+CShadows::CalcPedShadowValues(CVector vecLightDir,
+ float *pfDisplacementX, float *pfDisplacementY,
+ float *pfFrontX, float *pfFrontY,
+ float *pfSideX, float *pfSideY)
+{
+ ASSERT(pfDisplacementX != NULL);
+ ASSERT(pfDisplacementY != NULL);
+ ASSERT(pfFrontX != NULL);
+ ASSERT(pfFrontY != NULL);
+ ASSERT(pfSideX != NULL);
+ ASSERT(pfSideY != NULL);
+
+ *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;
+}
+
+void
+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 = CTimeCycle::GetLightShadowStrength();
+ else
+ nColorStrength = int32(CTimeCycle::GetLightShadowStrength() * 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);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pCar->GetModelIndex() != MI_RCBANDIT )
+ {
+ for ( int32 i = 0; i < CPointLights::NumLights; i++ )
+ {
+ if ( CPointLights::aLights[i].type == CPointLights::LIGHT_POINT
+ && CPointLights::aLights[i].castExtraShadows
+ &&(0.0f != CPointLights::aLights[i].red
+ || 0.0f != CPointLights::aLights[i].green
+ || 0.0f != CPointLights::aLights[i].blue) )
+ {
+ CVector vecLight = CPointLights::aLights[i].coors - FindPlayerCoors();
+ float fLightDist = vecLight.Magnitude();
+ float fRadius = CPointLights::aLights[i].radius;
+
+ if ( fLightDist < fRadius )
+ {
+ // fLightDist == 0 -> 2.0f
+ // fLightDist == fRadius -> 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;
+
+ CVector shadowPos = pCar->GetPosition();
+
+ shadowPos.x -= vecLight.x * 1.2f;
+ shadowPos.y -= vecLight.y * 1.2f;
+
+ float fVehicleWidth = pCar->GetColModel()->boundingBox.GetSize().x;
+ float fVehicleHeight = pCar->GetColModel()->boundingBox.GetSize().y;
+
+ shadowPos.x -= ((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)
+ * pCar->GetForward().x;
+
+ shadowPos.y -= ((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)
+ * pCar->GetForward().y;
+
+ if ( pCar->GetUp().z > 0.0f )
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &shadowPos,
+ pCar->GetForward().x * (fVehicleHeight/2),
+ pCar->GetForward().y * (fVehicleHeight/2),
+ pCar->GetRight().x * (fVehicleWidth/3),
+ pCar->GetRight().y * (fVehicleWidth/3),
+ nColorStrength, 0, 0, 0,
+ 4.5f, false, 1.0f);
+ }
+ else
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &shadowPos,
+ pCar->GetForward().x * (fVehicleHeight/2),
+ pCar->GetForward().y * (fVehicleHeight/2),
+ -pCar->GetRight().x * (fVehicleWidth/2),
+ -pCar->GetRight().y * (fVehicleWidth/2),
+ nColorStrength, 0, 0, 0,
+ 4.5f, false, 1.0f);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CShadows::TidyUpShadows(void)
+{
+ for ( int32 i = 0; i < MAX_PERMAMENTSHADOWS; i++ )
+ aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
+}
+
+void
+CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity)
+{
+ ASSERT(pPosn != NULL);
+
+ C3dMarkers::PlaceMarkerSet(nID, _TODOCONST(4), *pPosn, max(fFrontX, -fSideY),
+ 0, 128, 255, 128,
+ 2048, 0.2f, 0);
+}
+
+
+STARTPATCHES
+ InjectHook(0x512AB0, CShadows::Init, PATCH_JUMP);
+ InjectHook(0x512F20, CShadows::Shutdown, PATCH_JUMP);
+ InjectHook(0x512FD0, CShadows::AddPermanentShadow, PATCH_JUMP);
+ InjectHook(0x5130A0, CShadows::StoreStaticShadow, PATCH_JUMP);
+ InjectHook(0x513550, (void(*)(uint8, CVector *, float, float, float, float, int16, uint8, uint8, uint8))CShadows::StoreShadowToBeRendered, PATCH_JUMP);
+ InjectHook(0x513750, (void(*)(uint8, RwTexture *, CVector *, float, float, float, float, int16, uint8, uint8, uint8, float, bool, float))CShadows::StoreShadowToBeRendered, PATCH_JUMP);
+ InjectHook(0x513830, CShadows::StoreShadowForCar, PATCH_JUMP);
+ InjectHook(0x513A70, CShadows::StoreCarLightShadow, PATCH_JUMP);
+ InjectHook(0x513C50, CShadows::StoreShadowForPed, PATCH_JUMP);
+ InjectHook(0x513CB0, CShadows::StoreShadowForPedObject, PATCH_JUMP);
+ InjectHook(0x513E00, CShadows::StoreShadowForTree, PATCH_JUMP);
+ InjectHook(0x513E10, CShadows::StoreShadowForPole, PATCH_JUMP);
+ InjectHook(0x513FC0, CShadows::SetRenderModeForShadowType, PATCH_JUMP);
+ InjectHook(0x514010, CShadows::RenderStoredShadows, PATCH_JUMP);
+ InjectHook(0x5145F0, CShadows::RenderStaticShadows, PATCH_JUMP);
+ InjectHook(0x514910, CShadows::GeneratePolysForStaticShadow, PATCH_JUMP);
+ InjectHook(0x514C90, CShadows::CastShadowSectorList, PATCH_JUMP);
+ InjectHook(0x514E30, CShadows::CastShadowEntity, PATCH_JUMP);
+ InjectHook(0x516BE0, CShadows::UpdateStaticShadows, PATCH_JUMP);
+ InjectHook(0x516C40, CShadows::UpdatePermanentShadows, PATCH_JUMP);
+ InjectHook(0x516E70, &CStaticShadow::Free, PATCH_JUMP);
+ InjectHook(0x516EB0, CShadows::CalcPedShadowValues, PATCH_JUMP);
+ InjectHook(0x516F90, CShadows::RenderExtraPlayerShadows, PATCH_JUMP);
+ InjectHook(0x517570, CShadows::TidyUpShadows, PATCH_JUMP);
+ InjectHook(0x517810, CShadows::RenderIndicatorShadow, PATCH_JUMP);
+ //InjectHook(0x517900, &CPermanentShadow::CPermanentShadow, PATCH_JUMP);
+ //InjectHook(0x517910, &CStaticShadow::CStaticShadow, PATCH_JUMP);
+ //InjectHook(0x517920, &CPolyBunch::CPolyBunch, PATCH_JUMP);
+ //InjectHook(0x517940, &CStoredShadow::CStoredShadow, PATCH_JUMP);
+ENDPATCHES \ No newline at end of file
diff --git a/src/render/Shadows.h b/src/render/Shadows.h
index 37749de4..585518ee 100644
--- a/src/render/Shadows.h
+++ b/src/render/Shadows.h
@@ -1,26 +1,178 @@
#pragma once
+#define MAX_STOREDSHADOWS 48
+#define MAX_POLYBUNCHES 300
+#define MAX_STATICSHADOWS 64
+#define MAX_PERMAMENTSHADOWS 48
+
+
struct RwTexture;
class CEntity;
-enum
+enum eShadowType
+{
+ SHADOWTYPE_NONE = 0,
+ SHADOWTYPE_DARK,
+ SHADOWTYPE_ADDITIVE,
+ SHADOWTYPE_INVCOLOR
+};
+
+enum eShadowTextureType
+{
+ SHADOWTEX_NONE = 0,
+ SHADOWTEX_CAR,
+ SHADOWTEX_PED,
+ SHADOWTEX_EXPLOSION,
+ SHADOWTEX_HELI,
+ SHADOWTEX_HEADLIGHTS,
+ SHADOWTEX_BLOOD
+};
+
+class CStoredShadow
+{
+public:
+ CVector m_vecPos;
+ CVector2D m_vecFront;
+ CVector2D m_vecSide;
+ float m_fZDistance;
+ float m_fScale;
+ int16 m_nIntensity;
+ uint8 m_ShadowType;
+ uint8 m_nRed;
+ uint8 m_nGreen;
+ uint8 m_nBlue;
+ struct
+ {
+ uint8 bDrawOnWater : 1;
+ uint8 bRendered : 1;
+ //uint8 bDrawOnBuildings : 1;
+ } m_nFlags;
+ char _pad0;
+ RwTexture *m_pTexture;
+
+ CStoredShadow()
+ { }
+};
+VALIDATE_SIZE(CStoredShadow, 0x30);
+
+class CPolyBunch
{
- SHADOWTYPE_2 = 2
+public:
+ int16 m_nNumVerts;
+ char _pad0[2];
+ CVector m_aVerts[7];
+ uint8 m_aU[7];
+ uint8 m_aV[7];
+ char _pad1[2];
+ CPolyBunch *m_pNext;
+
+ CPolyBunch()
+ { }
+};
+VALIDATE_SIZE(CPolyBunch, 0x6C);
+
+class CStaticShadow
+{
+public:
+ uint32 m_nId;
+ CPolyBunch *m_pPolyBunch;
+ uint32 m_nTimeCreated;
+ CVector m_vecPosn;
+ CVector2D m_vecFront;
+ CVector2D m_vecSide;
+ float m_fZDistance;
+ float m_fScale;
+ uint8 m_nType;
+ char _pad0;
+ int16 m_nIntensity; // unsigned ?
+ uint8 m_nRed;
+ uint8 m_nGreen;
+ uint8 m_nBlue;
+ bool m_bJustCreated;
+ bool m_bRendered;
+ bool m_bTemp;
+ char _pad1[2];
+ RwTexture *m_pTexture;
+
+ CStaticShadow()
+ { }
+
+ void Free();
};
+VALIDATE_SIZE(CStaticShadow, 0x40);
+
+class CPermanentShadow
+{
+public:
+ CVector m_vecPos;
+ CVector2D m_vecFront;
+ CVector2D m_vecSide;
+ float m_fZDistance;
+ float m_fScale;
+ int16 m_nIntensity;
+ uint8 m_nType; // eShadowType
+ uint8 m_nRed;
+ uint8 m_nGreen;
+ uint8 m_nBlue;
+ char _pad0[2];
+ uint32 m_nTimeCreated;
+ uint32 m_nLifeTime;
+ RwTexture *m_pTexture;
+
+ CPermanentShadow()
+ { }
+};
+VALIDATE_SIZE(CPermanentShadow, 0x38);
+
+class CPtrList;
+class CAutomobile;
+class CPed;
class CShadows
{
public:
- static void AddPermanentShadow(uint8 ShadowType, RwTexture* pTexture, CVector* pPosn, float fX1, float fY1, float fX2, float fY2, short nTransparency, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale);
- static void RenderStaticShadows(void);
- static void RenderStoredShadows(void);
- static void RenderExtraPlayerShadows(void);
- static void CalcPedShadowValues(CVector light, float *frontX, float *frontY, float *sideX, float *sideY, float *dispX, float *dispY);
- static void StoreShadowForTree(CEntity *ent);
- static void StoreShadowForPole(CEntity *ent, float offsetX, float offsetY, float offsetZ, float poleHeight, float poleWidth, uint32 subId);
- static void StoreShadowForPedObject(CEntity *ent, float dispX, float dispY, float frontX, float frontY, float sideX, float sideY);
- static void StoreStaticShadow(uint32 id, uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, float scale, float drawDistance, bool temporaryShadow, float upDistance);;
- static void StoreShadowToBeRendered(uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, bool drawOnWater, float upDistance);
+#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, 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,
+ 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,
+ 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);
};
extern RwTexture *&gpBloodPoolTex;
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index a0731b1c..4fa2677a 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -10,3 +10,6 @@ WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint
CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x72B1B8;
WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }
+
+
+WRAPPER void C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { EAXJMP(0x51BB80); } \ No newline at end of file
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 1035b315..08f0f08a 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -28,3 +28,9 @@ public:
static void Init(void);
};
+
+class C3dMarkers
+{
+public:
+ static void PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
+}; \ No newline at end of file
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index 71ddedb7..235d559c 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -119,6 +119,8 @@ public:
static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }
static float GetSunSize(void) { return m_fCurrentSunSize; }
static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; }
+ static int GetShadowStrength(void) { return m_nCurrentShadowStrength; }
+ static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }
static float GetFarClip(void) { return m_fCurrentFarClip; }
static float GetFogStart(void) { return m_fCurrentFogStart; }
@@ -138,4 +140,10 @@ public:
static void Initialise(void);
static void Update(void);
static CVector &GetSunPosition(void) { return m_VectorToSun[m_CurrentStoredValue]; }
+ static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; }
+ static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; }
+ static float GetShadowSideX(void) { return m_fShadowSideX[m_CurrentStoredValue]; }
+ static float GetShadowSideY(void) { return m_fShadowSideY[m_CurrentStoredValue]; }
+ static float GetShadowDisplacementX(void) { return m_fShadowDisplacementX[m_CurrentStoredValue]; }
+ static float GetShadowDisplacementY(void) { return m_fShadowDisplacementY[m_CurrentStoredValue]; }
};
diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp
index 4f315cd0..247b9f3d 100644
--- a/src/render/WaterLevel.cpp
+++ b/src/render/WaterLevel.cpp
@@ -238,7 +238,7 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool
float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
- float fWave = sin
+ float fWave = Sin
(
/*( WATER_UNSIGN_Y(fY) - float(y) * MAX_HUGE_SECTORS + WATER_UNSIGN_X(fX) - float(x) * MAX_HUGE_SECTORS )*/ // VC
(float)( ((int32)fX & (MAX_HUGE_SECTORS-1)) + ((int32)fY & (MAX_HUGE_SECTORS-1)) )
@@ -306,7 +306,7 @@ _GetCamBounds(bool *bUseCamStartY, bool *bUseCamEndY, bool *bUseCamStartX, bool
{
if ( TheCamera.GetForward().z > -0.8f )
{
- if ( fabsf(TheCamera.GetForward().x) > fabsf(TheCamera.GetForward().y) )
+ if ( Abs(TheCamera.GetForward().x) > Abs(TheCamera.GetForward().y) )
{
if ( TheCamera.GetForward().x > 0.0f )
*bUseCamStartX = true;
@@ -323,10 +323,10 @@ _GetCamBounds(bool *bUseCamStartY, bool *bUseCamEndY, bool *bUseCamStartX, bool
}
}
-float
+inline float
SectorRadius(float fSize)
{
- return sqrtf(powf(fSize, 2) + powf(fSize, 2));
+ return Sqrt(Pow(fSize, 2) + Pow(fSize, 2));
}
void
@@ -424,7 +424,7 @@ CWaterLevel::RenderWater()
if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )
{
if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE),
- &CMatrix(TheCamera.GetCameraMatrix())) )
+ &TheCamera.GetCameraMatrix()) )
{
if ( fHugeSectorDistToCamSqr >= SQR(500.0f) /*fHugeSectorNearDist*/ )
{
@@ -466,7 +466,7 @@ CWaterLevel::RenderWater()
if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr )
{
if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE), //90.879997f,
- &CMatrix(TheCamera.GetCameraMatrix())) )
+ &TheCamera.GetCameraMatrix()) )
{
// Render four small(32x32) sectors, or one large(64x64).
@@ -629,7 +629,7 @@ CWaterLevel::RenderWater()
if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
{
if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &CMatrix(TheCamera.GetCameraMatrix())) )
+ &TheCamera.GetCameraMatrix()) )
{
RenderOneFlatExtraHugeWaterPoly(
vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
@@ -663,7 +663,7 @@ CWaterLevel::RenderWater()
if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
{
if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &CMatrix(TheCamera.GetCameraMatrix())) )
+ &TheCamera.GetCameraMatrix()) )
{
RenderOneFlatExtraHugeWaterPoly(
vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
@@ -687,7 +687,7 @@ CWaterLevel::RenderWater()
if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
{
if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &CMatrix(TheCamera.GetCameraMatrix())) )
+ &TheCamera.GetCameraMatrix()) )
{
RenderOneFlatExtraHugeWaterPoly(
vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
@@ -714,7 +714,7 @@ CWaterLevel::RenderWater()
static CVector prev_front(0.0f, 0.0f, 0.0f);
static int32 timecounter;
- if ( fabs(prev_pos.x - cur_pos.x) + fabs(prev_pos.y - cur_pos.y) + fabs(prev_pos.z - cur_pos.z) > 1.5f )
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
{
prev_pos = cur_pos;
timecounter = CTimer::GetTimeInMilliseconds();
@@ -962,8 +962,8 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col
RwRGBAAssign(&wavyPreLights[9*i+j], &color);
wavyVertices[9*i+j].z = ( CWeather::Wind * 0.7f + 0.3f )
- * ( sinf(float(i + j) * DEGTORAD(45.0f) + fAngle) )
- + ( CWeather::Wind * 0.2f * sinf(float(j - i) * PI + (2.0f * fAngle)) );
+ * ( Sin(float(i + j) * DEGTORAD(45.0f) + fAngle) )
+ + ( CWeather::Wind * 0.2f * Sin(float(j - i) * PI + (2.0f * fAngle)) );
}
}
@@ -1119,7 +1119,7 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY)
}
}
- return clamp(sqrt(fDistSqr) - 23.0f, 0.0f, fSectorMaxRenderDist);
+ return clamp(Sqrt(fDistSqr) - 23.0f, 0.0f, fSectorMaxRenderDist);
}
void
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 53a912b3..c18bad25 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -37,8 +37,8 @@ bool CBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoat
{
float fDist = (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[j]) * fShapeTime + float(j) * fShapeLength + fSize;
- if ( fabs(pBoat->m_avec2dWakePoints[j].x - sector.x) < fDist
- && fabs(pBoat->m_avec2dWakePoints[i].y - sector.y) < fDist )
+ if ( Abs(pBoat->m_avec2dWakePoints[j].x - sector.x) < fDist
+ && Abs(pBoat->m_avec2dWakePoints[i].y - sector.y) < fDist )
{
apBoats[numVerts] = pBoat;
numVerts = 1; // += ?
@@ -56,13 +56,12 @@ float CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat)
{
float fMaxDist = (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fShapeTime + float(i) * fShapeLength;
- float fX = pBoat->m_avec2dWakePoints[i].x - vecVertex.x;
- float fY = pBoat->m_avec2dWakePoints[i].y - vecVertex.y;
+ CVector2D vecDist = pBoat->m_avec2dWakePoints[i] - CVector2D(vecVertex);
- float fDist = fY * fY + fX * fX;
+ float fDist = vecDist.MagnitudeSqr();
if ( fDist < SQR(fMaxDist) )
- return 1.0f - min(fRangeMult * sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f);
+ return 1.0f - min(fRangeMult * Sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f);
}
return 0.0f;