summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/2dEffect.h12
-rw-r--r--src/render/Antennas.cpp2
-rw-r--r--src/render/Clouds.cpp225
-rw-r--r--src/render/Clouds.h2
-rw-r--r--src/render/Console.cpp2
-rw-r--r--src/render/Coronas.cpp158
-rw-r--r--src/render/Coronas.h30
-rw-r--r--src/render/Credits.cpp56
-rw-r--r--src/render/CutsceneShadow.cpp269
-rw-r--r--src/render/CutsceneShadow.h52
-rw-r--r--src/render/Draw.cpp29
-rw-r--r--src/render/Draw.h6
-rw-r--r--src/render/Fluff.cpp669
-rw-r--r--src/render/Fluff.h107
-rw-r--r--src/render/Font.cpp547
-rw-r--r--src/render/Font.h49
-rw-r--r--src/render/Glass.h4
-rw-r--r--src/render/Hud.cpp925
-rw-r--r--src/render/Hud.h45
-rw-r--r--src/render/MBlur.cpp177
-rw-r--r--src/render/MBlur.h17
-rw-r--r--src/render/Occlusion.cpp478
-rw-r--r--src/render/Occlusion.h58
-rw-r--r--src/render/Particle.cpp1517
-rw-r--r--src/render/Particle.h35
-rw-r--r--src/render/ParticleMgr.cpp12
-rw-r--r--src/render/ParticleMgr.h26
-rw-r--r--src/render/ParticleType.h17
-rw-r--r--src/render/PointLights.cpp55
-rw-r--r--src/render/PointLights.h5
-rw-r--r--src/render/RenderBuffer.cpp2
-rw-r--r--src/render/RenderBuffer.h11
-rw-r--r--src/render/Renderer.cpp452
-rw-r--r--src/render/Renderer.h9
-rw-r--r--src/render/Rubbish.cpp67
-rw-r--r--src/render/Rubbish.h2
-rw-r--r--src/render/ShadowCamera.cpp549
-rw-r--r--src/render/ShadowCamera.h54
-rw-r--r--src/render/Shadows.cpp1263
-rw-r--r--src/render/Shadows.h108
-rw-r--r--src/render/Skidmarks.cpp101
-rw-r--r--src/render/Skidmarks.h25
-rw-r--r--src/render/SpecialFX.cpp43
-rw-r--r--src/render/SpecialFX.h3
-rw-r--r--src/render/Sprite.cpp8
-rw-r--r--src/render/Sprite.h3
-rw-r--r--src/render/Sprite2d.cpp388
-rw-r--r--src/render/Sprite2d.h21
-rw-r--r--src/render/Timecycle.cpp370
-rw-r--r--src/render/Timecycle.h133
-rw-r--r--src/render/WaterLevel.cpp2867
-rw-r--r--src/render/WaterLevel.h116
-rw-r--r--src/render/Weather.cpp187
-rw-r--r--src/render/Weather.h33
-rw-r--r--src/render/WindModifiers.cpp51
-rw-r--r--src/render/WindModifiers.h11
56 files changed, 9646 insertions, 2817 deletions
diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h
index 628d64c2..baf07342 100644
--- a/src/render/2dEffect.h
+++ b/src/render/2dEffect.h
@@ -3,7 +3,9 @@
enum {
EFFECT_LIGHT,
EFFECT_PARTICLE,
- EFFECT_ATTRACTOR
+ EFFECT_ATTRACTOR,
+ EFFECT_PED_ATTRACTOR,
+ EFFECT_SUNGLARE
};
enum {
@@ -34,6 +36,8 @@ enum {
// same order as CPointLights flags, must start at 2
LIGHTFLAG_FOG_NORMAL = 2, // can have light and fog
LIGHTFLAG_FOG_ALWAYS = 4, // fog only
+ LIGHTFLAG_HIDE_OBJECT = 8, // hide the object instead of rendering light (???)
+ LIGHTFLAG_LONG_DIST = 16,
LIGHTFLAG_FOG = (LIGHTFLAG_FOG_NORMAL|LIGHTFLAG_FOG_ALWAYS)
};
@@ -63,6 +67,11 @@ public:
int8 type;
uint8 probability;
};
+ struct PedAttractor {
+ CVector queueDir;
+ CVector useDir;
+ int8 type;
+ };
CVector pos;
CRGBA col;
@@ -71,6 +80,7 @@ public:
Light light;
Particle particle;
Attractor attractor;
+ PedAttractor pedattr;
};
C2dEffect(void) {}
diff --git a/src/render/Antennas.cpp b/src/render/Antennas.cpp
index 452069a0..b9da95cb 100644
--- a/src/render/Antennas.cpp
+++ b/src/render/Antennas.cpp
@@ -2,6 +2,8 @@
#include "Antennas.h"
+//--MIAMI: file done
+
CAntenna CAntennas::aAntennas[NUMANTENNAS];
void
diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp
index 05ddbcdc..15bae90b 100644
--- a/src/render/Clouds.cpp
+++ b/src/render/Clouds.cpp
@@ -3,6 +3,7 @@
#include "Sprite.h"
#include "Sprite2d.h"
#include "General.h"
+#include "Game.h"
#include "Coronas.h"
#include "Camera.h"
#include "TxdStore.h"
@@ -23,8 +24,10 @@ uint32 CClouds::IndividualRotation;
float CClouds::ms_cameraRoll;
float CClouds::ms_horizonZ;
+float CClouds::ms_HorizonTilt;
CRGBA CClouds::ms_colourTop;
CRGBA CClouds::ms_colourBottom;
+CRGBA CClouds::ms_colourBkGrd;
void
CClouds::Init(void)
@@ -44,25 +47,15 @@ void
CClouds::Shutdown(void)
{
RwTextureDestroy(gpCloudTex[0]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[0] = nil;
-#endif
RwTextureDestroy(gpCloudTex[1]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[1] = nil;
-#endif
RwTextureDestroy(gpCloudTex[2]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[2] = nil;
-#endif
RwTextureDestroy(gpCloudTex[3]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[3] = nil;
-#endif
RwTextureDestroy(gpCloudTex[4]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[4] = nil;
-#endif
}
void
@@ -70,15 +63,15 @@ CClouds::Update(void)
{
float s = Sin(TheCamera.Orientation - 0.85f);
#ifdef FIX_BUGS
- CloudRotation += CWeather::Wind*s*0.0025f*CTimer::GetTimeStepFix();
- IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f*CTimer::GetTimeStepFix()) * 60.0f;
+ CloudRotation += CWeather::Wind*s*0.001f*CTimer::GetTimeStepFix();
+ IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f*CTimer::GetTimeStepFix()) * 60.0f;
#else
- CloudRotation += CWeather::Wind*s*0.0025f;
- IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f) * 60.0f;
+ CloudRotation += CWeather::Wind*s*0.001f;
+ IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f;
#endif
}
-float StarCoorsX[9] = { 0.0f, 0.05f, 0.12f, 0.5f, 0.8f, 0.6f, 0.27f, 0.55f, 0.75f };
+float StarCoorsX[9] = { 0.0f, 0.05f, 0.13f, 0.4f, 0.7f, 0.6f, 0.27f, 0.55f, 0.75f };
float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f };
float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f };
@@ -123,6 +116,9 @@ CClouds::Render(void)
RwV3d screenpos;
RwV3d worldpos;
+ if(!CGame::CanSeeOutSideFromCurrArea())
+ return;
+
CCoronas::SunBlockedByClouds = false;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
@@ -132,25 +128,20 @@ CClouds::Render(void)
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
CSprite::InitSpriteBuffer();
- int minute = CClock::GetHours()*60 + CClock::GetMinutes();
+ float minute = CClock::GetHours()*60 + CClock::GetMinutes() + CClock::GetSeconds()/60.0f;
RwV3d campos = *(RwV3d*)&TheCamera.GetPosition();
// Moon
- int moonfadeout = Abs(minute - 180); // fully visible at 3AM
- if(moonfadeout < 180){ // fade in/out 3 hours
+ float moonfadeout = Abs(minute - 180.0f); // fully visible at 3AM
+ if((int)moonfadeout < 180){ // fade in/out 3 hours
float coverage = Max(CWeather::Foggyness, CWeather::CloudCoverage);
- int brightness = (1.0f - coverage) * (180 - moonfadeout);
+ int brightness = (1.0f - coverage) * (180 - (int)moonfadeout);
RwV3d pos = { 0.0f, -100.0f, 15.0f };
RwV3dAdd(&worldpos, &campos, &pos);
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2]));
- if(CCoronas::bSmallMoon){
- szx *= 4.0f;
- szy *= 4.0f;
- }else{
- szx *= 10.0f;
- szy *= 10.0f;
- }
+ szx *= CCoronas::MoonSize*2.0f + 4.0f;
+ szy *= CCoronas::MoonSize*2.0f + 4.0f;
CSprite::RenderOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,
szx, szy, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255);
}
@@ -199,7 +190,7 @@ CClouds::Render(void)
}
// Low clouds
- float lowcloudintensity = 1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage);
+ float lowcloudintensity = 1.0f - Max(Max(CWeather::Foggyness, CWeather::CloudCoverage), CWeather::ExtraSunnyness);
int r = CTimeCycle::GetLowCloudsRed() * lowcloudintensity;
int g = CTimeCycle::GetLowCloudsGreen() * lowcloudintensity;
int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity;
@@ -220,10 +211,10 @@ CClouds::Render(void)
// Fluffy clouds
float rot_sin = Sin(CloudRotation);
float rot_cos = Cos(CloudRotation);
- int fluffyalpha = 160 * (1.0f - CWeather::Foggyness);
+ int fluffyalpha = 160 * (1.0f - Max(CWeather::Foggyness, CWeather::ExtraSunnyness));
if(fluffyalpha != 0){
static bool bCloudOnScreen[37];
- float hilight;
+ float sundist, hilight;
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
@@ -235,15 +226,16 @@ CClouds::Render(void)
worldpos.z = pos.z;
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
- float sundist = Sqrt(sq(screenpos.x-CCoronas::SunScreenX) + sq(screenpos.y-CCoronas::SunScreenY));
+ sundist = Sqrt(sq(screenpos.x-CCoronas::SunScreenX) + sq(screenpos.y-CCoronas::SunScreenY));
int tr = CTimeCycle::GetFluffyCloudsTopRed();
int tg = CTimeCycle::GetFluffyCloudsTopGreen();
int tb = CTimeCycle::GetFluffyCloudsTopBlue();
int br = CTimeCycle::GetFluffyCloudsBottomRed();
int bg = CTimeCycle::GetFluffyCloudsBottomGreen();
int bb = CTimeCycle::GetFluffyCloudsBottomBlue();
- if(sundist < SCREEN_WIDTH/2){
- hilight = (1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage)) * (1.0f - sundist/(SCREEN_WIDTH/2));
+ int distLimit = (3*SCREEN_WIDTH)/4;
+ if(sundist < distLimit){
+ hilight = (1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage)) * (1.0f - sundist/(float)distLimit);
tr = tr*(1.0f-hilight) + 255*hilight;
tg = tg*(1.0f-hilight) + 190*hilight;
tb = tb*(1.0f-hilight) + 190*hilight;
@@ -277,8 +269,7 @@ CClouds::Render(void)
worldpos.y = campos.x*rot_sin + campos.y*rot_cos + pos.y;
worldpos.z = pos.z;
if(bCloudOnScreen[i] && CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
- // BUG: this is stupid....would have to do this for each cloud individually
- if(hilight > 0.0f){
+ if(sundist < SCREEN_WIDTH/3){
CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(screenpos.x, screenpos.y, screenpos.z,
szx*30.0f, szy*30.0f,
200*hilight, 0, 0, 255, 1.0f/screenpos.z,
@@ -322,14 +313,17 @@ void
CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue,
int16 botred, int16 botgreen, int16 botblue, int16 alpha)
{
- CVector left = TheCamera.GetRight();
- float c = left.Magnitude2D();
+ CVector right = CrossProduct(TheCamera.GetUp(), TheCamera.GetForward());
+ right.Normalise();
+ float c = right.Magnitude2D();
if(c > 1.0f)
c = 1.0f;
ms_cameraRoll = Acos(c);
- if(left.z < 0.0f)
+ if(right.z < 0.0f)
ms_cameraRoll = -ms_cameraRoll;
+ ms_HorizonTilt = SCREEN_WIDTH/2.0f * Tan(ms_cameraRoll);
+
if(UseDarkBackground()){
ms_colourTop.r = 50;
ms_colourTop.g = 50;
@@ -352,75 +346,74 @@ CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue,
}else{
ms_horizonZ = CSprite::CalcHorizonCoors();
+ int fogr = (topred + 2 * botred) / 3;
+ int fogg = (topgreen + 2 * botgreen) / 3;
+ int fogb = (topblue + 2 * botblue) / 3;
+
// Draw top/bottom gradient
float gradheight = SCREEN_HEIGHT/2.0f;
- float topedge = ms_horizonZ - gradheight;
- float botpos, toppos;
- if(ms_horizonZ > 0.0f && topedge < SCREEN_HEIGHT){
- ms_colourTop.r = topred;
- ms_colourTop.g = topgreen;
- ms_colourTop.b = topblue;
- ms_colourTop.a = alpha;
- ms_colourBottom.r = botred;
- ms_colourBottom.g = botgreen;
- ms_colourBottom.b = botblue;
- ms_colourBottom.a = alpha;
-
- if(ms_horizonZ < SCREEN_HEIGHT)
- botpos = ms_horizonZ;
- else{
- float f = (ms_horizonZ - SCREEN_HEIGHT)/gradheight;
- ms_colourBottom.r = topred*f + (1.0f-f)*botred;
- ms_colourBottom.g = topgreen*f + (1.0f-f)*botgreen;
- ms_colourBottom.b = topblue*f + (1.0f-f)*botblue;
- botpos = SCREEN_HEIGHT;
- }
- if(topedge >= 0.0f)
- toppos = topedge;
- else{
- float f = (0.0f - topedge)/gradheight;
- ms_colourTop.r = botred*f + (1.0f-f)*topred;
- ms_colourTop.g = botgreen*f + (1.0f-f)*topgreen;
- ms_colourTop.b = botblue*f + (1.0f-f)*topblue;
- toppos = 0.0f;
- }
- CSprite2d::DrawRect(CRect(0, toppos, SCREEN_WIDTH, botpos),
- ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
- }
+
+ ms_colourTop.r = topred;
+ ms_colourTop.g = topgreen;
+ ms_colourTop.b = topblue;
+ ms_colourTop.a = alpha;
+ ms_colourBottom.r = botred;
+ ms_colourBottom.g = botgreen;
+ ms_colourBottom.b = botblue;
+ ms_colourBottom.a = alpha;
+
+ float botright = ms_horizonZ - ms_HorizonTilt;
+ float botleft = ms_horizonZ + ms_HorizonTilt;
+ float topright = botright - gradheight;
+ float topleft = botleft - gradheight;
+
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom);
// draw the small stripe (whatever it's supposed to be)
- if(ms_horizonZ > -SMALLSTRIPHEIGHT && ms_horizonZ < SCREEN_HEIGHT){
- // Same colour as fog
- ms_colourTop.r = (topred + 2 * botred) / 3;
- ms_colourTop.g = (topgreen + 2 * botgreen) / 3;
- ms_colourTop.b = (topblue + 2 * botblue) / 3;
- CSprite2d::DrawRect(CRect(0, ms_horizonZ, SCREEN_WIDTH, ms_horizonZ+SMALLSTRIPHEIGHT),
- ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop);
- }
+ ms_colourTop.r = fogr;
+ ms_colourTop.g = fogg;
+ ms_colourTop.b = fogb;
+ ms_colourTop.a = alpha;
+ topright = ms_horizonZ - ms_HorizonTilt;
+ topleft = ms_horizonZ + ms_HorizonTilt;
+ botright = topright + SMALLSTRIPHEIGHT;
+ botleft = topleft + SMALLSTRIPHEIGHT;
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop);
// Only top
- if(topedge > 0.0f){
+ if(ms_horizonZ + ms_HorizonTilt - gradheight > 0.0f ||
+ ms_horizonZ - ms_HorizonTilt - gradheight > 0.0f){
ms_colourTop.r = topred;
ms_colourTop.g = topgreen;
ms_colourTop.b = topblue;
ms_colourTop.a = alpha;
- ms_colourBottom.r = topred;
- ms_colourBottom.g = topgreen;
- ms_colourBottom.b = topblue;
- ms_colourBottom.a = alpha;
-
- botpos = Min(SCREEN_HEIGHT, topedge);
- CSprite2d::DrawRect(CRect(0, 0, SCREEN_WIDTH, botpos),
- ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
+
+ if(ms_horizonZ - Abs(ms_HorizonTilt) - gradheight > SCREEN_HEIGHT){
+ // only top is visible
+ topleft = 0.0f;
+ topright = 0.0f;
+ botleft = SCREEN_HEIGHT;
+ botright = SCREEN_HEIGHT;
+ }else{
+ botright = ms_horizonZ - ms_HorizonTilt - gradheight;
+ botleft = ms_horizonZ + ms_HorizonTilt - gradheight;
+ topright = Min(ms_horizonZ - ms_HorizonTilt - 2*SCREEN_HEIGHT, 0.0f);
+ topleft = Min(ms_horizonZ + ms_HorizonTilt - 2*SCREEN_HEIGHT, 0.0f);
+ }
+
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop);
}
// Set both to fog colour for RenderHorizon
- ms_colourTop.r = (topred + 2 * botred) / 3;
- ms_colourTop.g = (topgreen + 2 * botgreen) / 3;
- ms_colourTop.b = (topblue + 2 * botblue) / 3;
- ms_colourBottom.r = (topred + 2 * botred) / 3;
- ms_colourBottom.g = (topgreen + 2 * botgreen) / 3;
- ms_colourBottom.b = (topblue + 2 * botblue) / 3;
+ ms_colourTop.r = fogr;
+ ms_colourTop.g = fogg;
+ ms_colourTop.b = fogb;
+ ms_colourBottom.r = fogr;
+ ms_colourBottom.g = fogg;
+ ms_colourBottom.b = fogb;
}
}
@@ -433,21 +426,35 @@ CClouds::RenderHorizon(void)
ms_colourBottom.a = 230;
ms_colourTop.a = 80;
- if(ms_horizonZ > SCREEN_HEIGHT)
- return;
+ float topright = ms_horizonZ - ms_HorizonTilt;
+ float topleft = ms_horizonZ + ms_HorizonTilt;
+ float botright = topright + SMALLSTRIPHEIGHT;
+ float botleft = topleft + SMALLSTRIPHEIGHT;
+
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom);
+
+
+ ms_colourBkGrd.r = 128.0f*CTimeCycle::GetAmbientRed();
+ ms_colourBkGrd.g = 128.0f*CTimeCycle::GetAmbientGreen();
+ ms_colourBkGrd.b = 128.0f*CTimeCycle::GetAmbientBlue();
+ ms_colourBkGrd.a = 255;
+
+ float horzstrip = SCREEN_STRETCH_Y(HORIZSTRIPHEIGHT);
+ topright = botright;
+ topleft = botleft;
+ botright = topright + horzstrip;
+ botleft = topleft + horzstrip;
+
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourBottom, ms_colourBottom, ms_colourBkGrd, ms_colourBkGrd);
+
+
+ topright = botright;
+ topleft = botleft;
+ botright = Max(topright, SCREEN_HEIGHT);
+ botleft = Max(topleft, SCREEN_HEIGHT);
- float z1 = Min(ms_horizonZ + SMALLSTRIPHEIGHT, SCREEN_HEIGHT);
- CSprite2d::DrawRectXLU(CRect(0, ms_horizonZ, SCREEN_WIDTH, z1),
- ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
-
- // This is just weird
- float a = SCREEN_HEIGHT/400.0f * HORIZSTRIPHEIGHT +
- SCREEN_HEIGHT/300.0f * Max(TheCamera.GetPosition().z, 0.0f);
- float b = TheCamera.GetUp().z < 0.0f ?
- SCREEN_HEIGHT :
- SCREEN_HEIGHT * Abs(TheCamera.GetRight().z);
- float z2 = z1 + (a + b)*TheCamera.LODDistMultiplier;
- z2 = Min(z2, SCREEN_HEIGHT);
- CSprite2d::DrawRect(CRect(0, z1, SCREEN_WIDTH, z2),
- ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd);
}
diff --git a/src/render/Clouds.h b/src/render/Clouds.h
index 4d8cd2c8..ef33030b 100644
--- a/src/render/Clouds.h
+++ b/src/render/Clouds.h
@@ -8,8 +8,10 @@ public:
static float ms_cameraRoll;
static float ms_horizonZ;
+ static float ms_HorizonTilt;
static CRGBA ms_colourTop;
static CRGBA ms_colourBottom;
+ static CRGBA ms_colourBkGrd;
static void Init(void);
static void Shutdown(void);
diff --git a/src/render/Console.cpp b/src/render/Console.cpp
index 8ea5b7a3..244bfb17 100644
--- a/src/render/Console.cpp
+++ b/src/render/Console.cpp
@@ -63,7 +63,7 @@ CConsole::Display()
CFont::SetJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
#ifndef FIX_BUGS
CFont::SetPropOff(); // not sure why this is here anyway
#endif
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index d2d229f9..2d621d18 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -2,6 +2,7 @@
#include "main.h"
#include "General.h"
+#include "RenderBuffer.h"
#include "TxdStore.h"
#include "Camera.h"
#include "Sprite.h"
@@ -12,6 +13,8 @@
#include "Timecycle.h"
#include "Coronas.h"
+//--MIAMI: file done
+
struct FlareDef
{
float position;
@@ -53,7 +56,7 @@ RwTexture *gpCoronaTexture[9] = { nil, nil, nil, nil, nil, nil, nil, nil, nil };
float CCoronas::LightsMult = 1.0f;
float CCoronas::SunScreenX;
float CCoronas::SunScreenY;
-bool CCoronas::bSmallMoon;
+int CCoronas::MoonSize;
bool CCoronas::SunBlockedByClouds;
int CCoronas::bChangeBrightnessImmediately;
@@ -129,13 +132,22 @@ CCoronas::Update(void)
void
CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, RwTexture *tex,
- int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle)
+ int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
+ bool useNearDist, float nearDist)
{
int i;
if(sq(drawDist) < (TheCamera.GetPosition() - coors).MagnitudeSqr2D())
return;
+ if(useNearDist){
+ float dist = (TheCamera.GetPosition() - coors).Magnitude();
+ if(dist < 35.0f)
+ return;
+ if(dist < 50.0f)
+ alpha *= (dist - 35.0f)/(50.0f - 35.0f);
+ }
+
for(i = 0; i < NUMCORONAS; i++)
if(aCoronas[i].id == id)
break;
@@ -188,15 +200,19 @@ CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 al
aCoronas[i].reflection = reflection;
aCoronas[i].LOScheck = LOScheck;
aCoronas[i].drawStreak = drawStreak;
+ aCoronas[i].useNearDist = useNearDist;
+ aCoronas[i].nearDist = nearDist;
}
void
CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
- const CVector &coors, float size, float drawDist, uint8 type,
- int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle)
+ const CVector &coors, float size, float drawDist, uint8 type,
+ int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
+ bool useNearDist, float nearDist)
{
RegisterCorona(id, red, green, blue, alpha, coors, size, drawDist,
- gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle);
+ gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle,
+ useNearDist, nearDist);
}
void
@@ -309,7 +325,7 @@ CCoronas::Render(void)
if(CCoronas::aCoronas[i].id == SUN_CORE)
spriteCoors.z = 0.95f * RwCameraGetFarClipPlane(Scene.camera);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aCoronas[i].texture));
- spriteCoors.z -= 1.5f;
+ spriteCoors.z -= aCoronas[i].nearDist;
if(aCoronas[i].texture == gpCoronaTexture[8]){
// what's this?
@@ -371,7 +387,7 @@ CCoronas::Render(void)
}
}
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
@@ -423,9 +439,7 @@ CCoronas::RenderReflections(void)
CEntity *entity;
if(CWeather::WetRoads > 0.0f){
-#ifdef FIX_BUGS
CSprite::InitSpriteBuffer();
-#endif
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
@@ -502,6 +516,130 @@ CCoronas::RenderReflections(void)
}
}
+void
+CCoronas::RenderSunReflection(void)
+{
+ float sunZDir = CTimeCycle::GetSunDirection().z;
+ if(sunZDir > -0.05f){
+ float intensity = (0.3f - Abs(sunZDir - 0.25f))/0.3f *
+ (1.0f - CWeather::CloudCoverage) *
+ (1.0f - CWeather::Foggyness) *
+ (1.0f - CWeather::Wind);
+ if(intensity > 0.0f){
+ int r = (CTimeCycle::GetSunCoreRed() + CTimeCycle::GetSunCoronaRed())*intensity*0.25f;
+ int g = (CTimeCycle::GetSunCoreGreen() + CTimeCycle::GetSunCoronaGreen())*intensity*0.25f;
+ int b = (CTimeCycle::GetSunCoreBlue() + CTimeCycle::GetSunCoronaBlue())*intensity*0.25f;
+
+ CVector sunPos = 40.0f*CTimeCycle::GetSunDirection() + TheCamera.GetPosition();
+ sunPos.z = 0.5f*CWeather::Wind + 6.1f;
+ CVector sunDir = CTimeCycle::GetSunDirection();
+ sunDir.z = 0.0;
+ sunDir.Normalise();
+
+ TempBufferIndicesStored = 6;
+ TempBufferRenderIndexList[0] = 2;
+ TempBufferRenderIndexList[1] = 1;
+ TempBufferRenderIndexList[2] = 0;
+ TempBufferRenderIndexList[3] = 2;
+ TempBufferRenderIndexList[4] = 3;
+ TempBufferRenderIndexList[5] = 1;
+
+ // 60 unit square in sun direction
+ TempBufferVerticesStored = 4;
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[0],
+ sunPos.x + 30.0f*sunDir.y,
+ sunPos.y - 30.0f*sunDir.x,
+ sunPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[1],
+ sunPos.x - 30.0f*sunDir.y,
+ sunPos.y + 30.0f*sunDir.x,
+ sunPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[2], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[2],
+ sunPos.x + 60.0f*sunDir.x + 30.0f*sunDir.y,
+ sunPos.y + 60.0f*sunDir.y - 30.0f*sunDir.x,
+ sunPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[3], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[3],
+ sunPos.x + 60.0f*sunDir.x - 30.0f*sunDir.y,
+ sunPos.y + 60.0f*sunDir.y + 30.0f*sunDir.x,
+ sunPos.z);
+
+ RwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[0], 1.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[1], 1.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[2], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[2], 0.5f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[3], 1.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[3], 0.5f);
+
+ int timeInc = 0;
+ int sideInc = 0;
+ int fwdInc = 0;
+ for(int i = 0; i < 20; i++){
+ TempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored-1;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored-2;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored+1;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored-1;
+ TempBufferIndicesStored += 6;
+
+ // What a weird way to do it...
+ float fwdLen = fwdInc/20 + 60;
+ float sideLen = sideInc/20 + 30;
+ sideLen += 10.0f*Sin((float)(CTimer::GetTimeInMilliseconds()+timeInc & 0x7FF)/0x800*TWOPI);
+ timeInc += 900;
+ sideInc += 970;
+ fwdInc += 1440;
+
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0],
+ sunPos.x + fwdLen*sunDir.x + sideLen*sunDir.y,
+ sunPos.y + fwdLen*sunDir.y - sideLen*sunDir.x,
+ sunPos.z);
+
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1],
+ sunPos.x + fwdLen*sunDir.x - sideLen*sunDir.y,
+ sunPos.y + fwdLen*sunDir.y + sideLen*sunDir.x,
+ sunPos.z);
+
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.5f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 0.5f);
+ TempBufferVerticesStored += 2;
+ }
+
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[4]));
+ if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
+ RwIm3DEnd();
+ }
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+ }
+ }
+}
+
void
CCoronas::DoSunAndMoon(void)
{
@@ -518,7 +656,7 @@ CCoronas::DoSunAndMoon(void)
255, sunCoors, size,
999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f);
- if(CTimeCycle::GetSunDirection().z > 0.0f)
+ if(CTimeCycle::GetSunDirection().z > 0.0f && !CGame::IsInInterior())
RegisterCorona(SUN_CORONA,
CTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(),
255, sunCoors, 25.0f * CTimeCycle::GetSunSize(),
diff --git a/src/render/Coronas.h b/src/render/Coronas.h
index 46eb4315..45f027d8 100644
--- a/src/render/Coronas.h
+++ b/src/render/Coronas.h
@@ -4,19 +4,21 @@ extern RwTexture *gpCoronaTexture[9];
struct CRegisteredCorona
{
+ CVector coors;
uint32 id;
uint32 lastLOScheck;
RwTexture *texture;
+ float size;
+ float someAngle;
+ float drawDist;
+ float nearDist;
+ float heightAboveRoad;
uint8 red;
uint8 green;
uint8 blue;
uint8 alpha; // alpha when fully visible
uint8 fadeAlpha; // actual value used for rendering, faded
- CVector coors;
- float size;
- float someAngle;
bool registeredThisFrame;
- float drawDist;
int8 flareType;
int8 reflection;
@@ -25,12 +27,11 @@ struct CRegisteredCorona
uint8 firstUpdate : 1;
uint8 drawStreak : 1;
uint8 sightClear : 1;
+ uint8 useNearDist : 1;
+ uint8 renderReflection : 1;
- bool renderReflection;
- float heightAboveRoad;
-
- float prevX[6];
- float prevY[6];
+ int16 prevX[6];
+ int16 prevY[6];
uint8 prevRed[6];
uint8 prevGreen[6];
uint8 prevBlue[6];
@@ -39,7 +40,7 @@ struct CRegisteredCorona
void Update(void);
};
-VALIDATE_SIZE(CRegisteredCorona, 0x80);
+VALIDATE_SIZE(CRegisteredCorona, 0x68);
class CCoronas
{
@@ -81,7 +82,7 @@ public:
static float LightsMult;
static float SunScreenY;
static float SunScreenX;
- static bool bSmallMoon;
+ static int MoonSize;
static bool SunBlockedByClouds;
static int bChangeBrightnessImmediately;
@@ -90,12 +91,15 @@ public:
static void Update(void);
static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, RwTexture *tex,
- int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle);
+ int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
+ bool useNearDist = false, float nearDist = 1.5f);
static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, uint8 type,
- int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle);
+ int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
+ bool useNearDist = false, float nearDist = 1.5f);
static void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle);
static void Render(void);
static void RenderReflections(void);
+ static void RenderSunReflection(void);
static void DoSunAndMoon(void);
};
diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp
index 2cfdba90..26b333fc 100644
--- a/src/render/Credits.cpp
+++ b/src/render/Credits.cpp
@@ -128,12 +128,12 @@ CCredits::Render(void)
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED040"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
PrintCreditText(1.4f, 0.82f, TheText.Get("CRED041"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED042"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
PrintCreditText(1.7f, 1.0f, TheText.Get("CRED043"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED044"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
@@ -176,7 +176,7 @@ CCredits::Render(void)
PrintCreditSpace(2.0f, lineoffset);
PrintCreditSpace(2.0f, lineoffset);
PrintCreditText(1.7f, 1.0f, TheText.Get("CRED061"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED062"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
@@ -191,7 +191,7 @@ CCredits::Render(void)
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED068"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
PrintCreditText(1.7f, 1.0f, TheText.Get("CRED069"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED070"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
@@ -220,7 +220,7 @@ CCredits::Render(void)
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED262"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
PrintCreditText(1.7f, 1.0f, TheText.Get("CRED085"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.7f, 1.7f, TheText.Get("CRED086"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
@@ -265,76 +265,76 @@ CCredits::Render(void)
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED108"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED109"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED110"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
PrintCreditText(1.7f, 1.0f, TheText.Get("CRED111"), lineoffset, scrolloffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED112"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED113"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED114"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED115"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED116"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED117"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED118"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED119"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED120"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED121"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED122"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED123"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED124"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED125"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED126"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED127"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED128"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED129"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED130"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED131"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED132"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED133"), lineoffset, scrolloffset);
- if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
+ if(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.0f, 1.0f, TheText.Get("CRED134"), lineoffset, scrolloffset);
PrintCreditSpace(2.0f, lineoffset);
diff --git a/src/render/CutsceneShadow.cpp b/src/render/CutsceneShadow.cpp
new file mode 100644
index 00000000..8cb33896
--- /dev/null
+++ b/src/render/CutsceneShadow.cpp
@@ -0,0 +1,269 @@
+#include "common.h"
+#include "main.h"
+#include "rwcore.h"
+#include "rwplcore.h"
+#include "CutsceneShadow.h"
+#include "RwHelper.h"
+
+#define DLIGHT_VALUE 0.8f /* Directional light intensity */
+
+
+CCutsceneShadow::CCutsceneShadow()
+{
+ m_pAtomic = nil;
+ m_nRwObjectType = -1;
+ m_pLight = nil;
+ m_nBlurPasses = 0;
+ m_bResample = false;
+ m_bGradient = false;
+}
+
+CCutsceneShadow::~CCutsceneShadow()
+{
+ Destroy();
+}
+
+bool
+CCutsceneShadow::Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient)
+{
+ ASSERT(object != nil);
+
+ RwRGBAReal color;
+ RwFrame *frame;
+
+ if (!object)
+ return false;
+
+ m_pLight = RpLightCreate(rpLIGHTDIRECTIONAL);
+ ASSERT(m_pLight != nil);
+
+ if (!m_pLight)
+ return false;
+
+ color.red = color.green = color.blue = DLIGHT_VALUE;
+ color.alpha = 0.0f;
+
+ RpLightSetColor(m_pLight, &color);
+
+ frame = RwFrameCreate();
+ ASSERT(frame != nil);
+
+ RpLightSetFrame(m_pLight, frame);
+
+ SetLightProperties(180.0f, 90.0f, false);
+
+ m_pObject = object;
+ m_nRwObjectType = RwObjectGetType(m_pObject);
+
+ switch ( m_nRwObjectType )
+ {
+ case rpCLUMP:
+ {
+ RpClumpGetBoundingSphere(m_pClump, &m_BoundingSphere, 1);
+ m_BaseSphere.radius = m_BoundingSphere.radius;
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump)));
+ break;
+ }
+
+ case rpATOMIC:
+ {
+ m_BoundingSphere = *RpAtomicGetBoundingSphere(m_pAtomic);
+ m_BaseSphere.radius = m_BoundingSphere.radius;
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));
+ break;
+ }
+
+ default:
+ {
+ Destroy();
+ return false;
+ break;
+ }
+ }
+
+ if ( !m_Camera.Create(rasterSize) )
+ {
+ Destroy();
+ return false;
+ }
+
+ m_nBlurPasses = blurPasses;
+ m_bResample = resample;
+ m_bGradient = gradient;
+
+ if ( m_bResample && !m_ResampleCamera.Create(rasterSize - 1) )
+ {
+ Destroy();
+ return false;
+ }
+
+ if ( m_nBlurPasses != 0 )
+ {
+ if ( !m_BlurCamera.Create(resample ? rasterSize - 1 : rasterSize) )
+ {
+ Destroy();
+ return false;
+ }
+ }
+
+ if ( m_bGradient )
+ {
+ if ( !m_GradientCamera.Create(resample ? rasterSize - 1 : rasterSize) )
+ {
+ Destroy();
+ return false;
+ }
+
+ m_GradientCamera.MakeGradientRaster();
+ }
+
+ m_Camera.SetLight(m_pLight);
+
+ switch ( m_nRwObjectType )
+ {
+ case rpATOMIC:
+ m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius);
+ break;
+
+ case rpCLUMP:
+ m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius);
+ break;
+ }
+
+ m_Camera.SetCenter(&m_BaseSphere.center);
+ return true;
+}
+
+RwFrame *
+CCutsceneShadow::SetLightProperties(float angleY, float angleX, bool setLight)
+{
+ ASSERT(m_pLight != nil);
+
+ RwFrame *frame;
+ static RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+ static RwV3d Yaxis = { 0.0f, 1.0f, 0.0f };
+
+ frame = RpLightGetFrame(m_pLight);
+ ASSERT(frame != nil);
+
+ if ( !frame )
+ return nil;
+
+ RwFrameRotate(frame, &Yaxis, angleY, rwCOMBINEREPLACE);
+ RwFrameRotate(frame, &Xaxis, angleX, rwCOMBINEPOSTCONCAT);
+
+ if ( setLight )
+ m_Camera.SetLight(m_pLight);
+
+ return frame;
+}
+
+bool
+CCutsceneShadow::IsInitialized()
+{
+ return m_pObject != nil;
+}
+
+void
+CCutsceneShadow::Destroy()
+{
+ m_Camera.Destroy();
+ m_ResampleCamera.Destroy();
+ m_BlurCamera.Destroy();
+ m_GradientCamera.Destroy();
+
+ m_pAtomic = nil;
+
+ m_nRwObjectType = -1;
+
+ if (m_pLight)
+ {
+ RwFrame *frame = RpLightGetFrame(m_pLight);
+ RpLightSetFrame(m_pLight, nil);
+ RwFrameDestroy(frame);
+ RpLightDestroy(m_pLight);
+ m_pLight = nil;
+ }
+}
+
+RwRaster *
+CCutsceneShadow::Update()
+{
+ switch ( m_nRwObjectType )
+ {
+ case rpCLUMP:
+ ASSERT(m_pClump != nil);
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump)));
+ break;
+
+ case rpATOMIC:
+ ASSERT(m_pAtomic != nil);
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));
+ break;
+ }
+
+ m_Camera.SetCenter(&m_BaseSphere.center);
+
+ switch ( m_nRwObjectType )
+ {
+ case rpCLUMP:
+ m_Camera.Update(m_pClump);
+ break;
+
+ case rpATOMIC:
+ m_Camera.Update(m_pAtomic);
+ break;
+ }
+
+ RwRaster *raster = m_Camera.GetRwRenderRaster();
+ ASSERT(raster != nil);
+
+ if ( m_bResample )
+ return m_ResampleCamera.RasterResample(raster);
+
+ if ( m_nBlurPasses )
+ return m_BlurCamera.RasterBlur(raster, m_nBlurPasses);
+
+ if ( m_bGradient )
+ return m_GradientCamera.RasterGradient(raster);
+
+ return raster;
+}
+
+RwTexture *
+CCutsceneShadow::UpdateForCutscene()
+{
+ Update();
+ return GetShadowRwTexture();
+}
+
+CShadowCamera *
+CCutsceneShadow::GetShadowCamera(int32 camType)
+{
+ switch ( camType )
+ {
+ case RESAMPLE: return &m_ResampleCamera;
+ case BLUR: return &m_BlurCamera;
+ case GRADIENT: return &m_GradientCamera;
+ }
+
+ return &m_Camera;
+}
+
+RwTexture *
+CCutsceneShadow::GetShadowRwTexture()
+{
+ if ( m_bResample )
+ return m_ResampleCamera.GetRwRenderTexture();
+ else
+ return m_Camera.GetRwRenderTexture();
+}
+
+void
+CCutsceneShadow::DrawBorderAroundTexture(RwRGBA const& color)
+{
+ if ( m_bResample )
+ m_ResampleCamera.DrawOutlineBorder(color);
+ else
+ m_Camera.DrawOutlineBorder(color);
+} \ No newline at end of file
diff --git a/src/render/CutsceneShadow.h b/src/render/CutsceneShadow.h
new file mode 100644
index 00000000..a59fe78f
--- /dev/null
+++ b/src/render/CutsceneShadow.h
@@ -0,0 +1,52 @@
+#pragma once
+#include "ShadowCamera.h"
+
+class CCutsceneShadow
+{
+public:
+ enum
+ {
+ RASTER = 0,
+ RESAMPLE,
+ BLUR,
+ GRADIENT,
+ };
+
+ CShadowCamera m_Camera;
+ bool m_bResample;
+ CShadowCamera m_ResampleCamera;
+ int32 m_nBlurPasses;
+ CShadowCamera m_BlurCamera;
+ bool m_bGradient;
+ CShadowCamera m_GradientCamera;
+
+ union
+ {
+ RwObject *m_pObject;
+ RpAtomic *m_pAtomic;
+ RpClump *m_pClump;
+ };
+
+ int32 m_nRwObjectType;
+ RpLight *m_pLight;
+ RwSphere m_BoundingSphere;
+ RwSphere m_BaseSphere;
+
+ CCutsceneShadow();
+ ~CCutsceneShadow();
+
+ RwSphere GetBaseSphere()
+ {
+ return m_BaseSphere;
+ }
+
+ bool Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient);
+ RwFrame *SetLightProperties(float angleY, float angleX, bool setLight);
+ bool IsInitialized();
+ void Destroy();
+ RwRaster *Update();
+ RwTexture *UpdateForCutscene();
+ CShadowCamera *GetShadowCamera(int32 camType = RASTER);
+ RwTexture *GetShadowRwTexture();
+ void DrawBorderAroundTexture(RwRGBA const& color);
+};
diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp
index db87e76d..ab360aac 100644
--- a/src/render/Draw.cpp
+++ b/src/render/Draw.cpp
@@ -21,24 +21,23 @@ uint8 CDraw::FadeGreen;
uint8 CDraw::FadeBlue;
float
-CDraw::FindAspectRatio(void)
+CDraw::CalculateAspectRatio(void)
{
-#ifndef ASPECT_RATIO_SCALE
- if(FrontEndMenuManager.m_PrefsUseWideScreen)
- return 16.0f/9.0f;
- else
- return 4.0f/3.0f;
+ if (FrontEndMenuManager.m_PrefsUseWideScreen) {
+ if (TheCamera.m_WideScreenOn)
+ CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki
+ else
+#ifdef ASPECT_RATIO_SCALE
+ CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? SCREEN_WIDTH / SCREEN_HEIGHT : 16.f / 9.f;
#else
- switch (FrontEndMenuManager.m_PrefsUseWideScreen) {
- case AR_AUTO:
- return SCREEN_WIDTH / SCREEN_HEIGHT;
- default:
- case AR_4_3:
- return 4.0f / 3.0f;
- case AR_16_9:
- return 16.0f / 9.0f;
- };
+ CDraw::ms_fAspectRatio = 16.f / 9.f;
#endif
+ } else if (TheCamera.m_WideScreenOn) {
+ CDraw::ms_fAspectRatio = 5.f/4.f;
+ } else {
+ CDraw::ms_fAspectRatio = 4.f/3.f;
+ }
+ return CDraw::ms_fAspectRatio;
}
#ifdef ASPECT_RATIO_SCALE
diff --git a/src/render/Draw.h b/src/render/Draw.h
index 5c4f95b1..2976dc34 100644
--- a/src/render/Draw.h
+++ b/src/render/Draw.h
@@ -44,12 +44,10 @@ public:
static float GetScaledFOV(void) { return ms_fFOV; }
#endif
- static float FindAspectRatio(void);
+ static float CalculateAspectRatio(void);
#ifdef ASPECT_RATIO_SCALE
static float ConvertFOV(float fov);
+#endif
static float GetAspectRatio(void) { return ms_fAspectRatio; }
static void SetAspectRatio(float ratio) { ms_fAspectRatio = ratio; }
-#else
- static float GetAspectRatio(void) { return FindAspectRatio(); }
-#endif
};
diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp
index 690a1d3f..14c80a63 100644
--- a/src/render/Fluff.cpp
+++ b/src/render/Fluff.cpp
@@ -1,11 +1,15 @@
#include "common.h"
#include "main.h"
+#include "RenderBuffer.h"
#include "Entity.h"
#include "Fluff.h"
#include "Camera.h"
#include "Sprite.h"
#include "Coronas.h"
+#include "PointLights.h"
+#include "Rubbish.h"
+#include "Timecycle.h"
#include "General.h"
#include "Timer.h"
#include "Clock.h"
@@ -13,6 +17,292 @@
#include "Stats.h"
#include "maths.h"
#include "Frontend.h"
+#include "CutsceneMgr.h"
+#include "PlayerPed.h"
+#include "Bones.h"
+#include "World.h"
+#include "Replay.h"
+
+CPlaneTrail CPlaneTrails::aArray[6];
+RwImVertexIndex TrailIndices[32] = {
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+ 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16
+};
+
+void
+CPlaneTrail::Init(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(m_time); i++)
+ m_time[i] = 0;
+}
+
+void
+CPlaneTrail::Render(float visibility)
+{
+ int i;
+ int numVerts = 0;
+ if(!TheCamera.IsSphereVisible(m_pos[0], 1000.0f))
+ return;
+
+ int alpha = visibility*110.0f;
+ if(alpha == 0)
+ return;
+
+ for(i = 0; i < ARRAY_SIZE(m_pos); i++){
+ int32 time = CTimer::GetTimeInMilliseconds() - m_time[i];
+ if(time > 30000)
+ m_time[i] = 0;
+ if(m_time[i] != 0){
+ float fade = (30000.0f - time) / 10000.0f;
+ fade = Min(fade, 1.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[numVerts], 255, 255, 255, (int)(alpha*fade));
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[numVerts], m_pos[i].x, m_pos[i].y, m_pos[i].z);
+ numVerts++;
+ }
+ }
+ if(numVerts > 1){
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+
+ if(RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, TrailIndices, (numVerts-1)*2);
+ RwIm3DEnd();
+ }
+ }
+}
+
+void
+CPlaneTrail::RegisterPoint(CVector pos)
+{
+ int i;
+ bool bNewPoint = false;
+ if(m_time[0] != 0 && CTimer::GetTimeInMilliseconds() - m_time[0] > 2000){
+ bNewPoint = true;
+ for(i = ARRAY_SIZE(m_pos)-1; i > 0; i--){
+ m_pos[i] = m_pos[i-1];
+ m_time[i] = m_time[i-1];
+ }
+ }
+ m_pos[0] = pos;
+ if(bNewPoint || m_time[0] == 0)
+ m_time[0] = CTimer::GetTimeInMilliseconds();
+}
+
+void
+CPlaneTrails::Init(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(aArray); i++)
+ aArray[i].Init();
+}
+
+void
+CPlaneTrails::Update(void)
+{
+ CVector planePos;
+
+ planePos.x = 1590.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);
+ planePos.y = 1200.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);
+ planePos.z = 550.0f;
+ RegisterPoint(planePos, 3);
+ if(CClock::GetHours() > 22 || CClock::GetHours() < 7){
+ if(CTimer::GetTimeInMilliseconds() & 0x200)
+ CCoronas::RegisterCorona(101, 255, 0, 0, 255, planePos, 5.0f, 2000.0f,
+ CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ else
+ CCoronas::UpdateCoronaCoors(101, planePos, 2000.0f, 0.0f);
+ }
+
+ planePos.x = 1000.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);
+ planePos.y = -1600.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);
+ planePos.z = 500.0f;
+ RegisterPoint(planePos, 4);
+ if(CClock::GetHours() > 22 || CClock::GetHours() < 7){
+ if(CTimer::GetTimeInMilliseconds() & 0x200)
+ CCoronas::RegisterCorona(102, 255, 0, 0, 255, planePos, 5.0f, 2000.0f,
+ CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ else
+ CCoronas::UpdateCoronaCoors(102, planePos, 2000.0f, 0.0f);
+ }
+
+ planePos.x = 1100.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);
+ planePos.y = 700.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);
+ planePos.z = 600.0f;
+ RegisterPoint(planePos, 5);
+ if(CClock::GetHours() > 22 || CClock::GetHours() < 7){
+ if(CTimer::GetTimeInMilliseconds() & 0x200)
+ CCoronas::RegisterCorona(103, 255, 0, 0, 255, planePos, 5.0f, 2000.0f,
+ CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ else
+ CCoronas::UpdateCoronaCoors(103, planePos, 2000.0f, 0.0f);
+ }
+}
+
+void
+CPlaneTrails::Render(void)
+{
+ int i;
+ float visibility = Min(1.0f-CWeather::Foggyness, 1.0f-CWeather::CloudCoverage);
+ visibility = Min(visibility, 1.0f-CWeather::Rain);
+ visibility = Min(Max(Max(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen()), CTimeCycle::GetSkyTopBlue())/256.0f, visibility);
+ if(visibility > 0.0001f)
+ for(i = 0; i < ARRAY_SIZE(aArray); i++)
+ aArray[i].Render(visibility);
+}
+
+void
+CPlaneTrails::RegisterPoint(CVector pos, uint32 id)
+{
+ aArray[id].RegisterPoint(pos);
+}
+
+
+
+CPlaneBanner CPlaneBanners::aArray[5];
+
+void
+CPlaneBanner::Init(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(m_pos); i++){
+ m_pos[i].x = i;
+ m_pos[i].y = 0.0f;
+ m_pos[i].z = -60.0f;
+ }
+}
+
+void
+CPlaneBanner::Update(void)
+{
+ int i;
+ if(m_pos[0].z > -50.0f){
+ m_pos[0].z -= 0.05f*CTimer::GetTimeStep();
+ m_pos[0].z = Max(m_pos[0].z, -100.0f);
+ for(i = 1; i < ARRAY_SIZE(m_pos); i++){
+ CVector dist = m_pos[i] - m_pos[i-1];
+ float len = dist.Magnitude();
+ if(len > 8.0f)
+ m_pos[i] = m_pos[i-1] + dist/len*8.0f;
+ }
+ }
+}
+
+void
+CPlaneBanner::Render(void)
+{
+ int i;
+ if(m_pos[0].z > -50.0f){
+ float camDist = (TheCamera.GetPosition() - m_pos[0]).Magnitude();
+ if(TheCamera.IsSphereVisible(m_pos[4], 32.0f) && camDist < 300.0f){
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+ int alpha = camDist < 250.0f ? 160 : (300.0f-camDist)/(300.0f-250.0f)*160;
+
+ TempBufferVerticesStored += 2;
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, alpha);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, alpha);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[0], m_pos[2].x, m_pos[2].y, m_pos[2].z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[1], m_pos[2].x, m_pos[2].y, m_pos[2].z - 4.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[0], 0.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[1], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f);
+ for(i = 2; i < 8; i++){
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], 255, 255, 255, alpha);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], 255, 255, 255, alpha);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0], m_pos[i].x, m_pos[i].y, m_pos[i].z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1], m_pos[i].x, m_pos[i].y, m_pos[i].z - 4.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], (i-2)/5.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], (i-2)/5.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f);
+ TempBufferRenderIndexList[TempBufferIndicesStored+0] = TempBufferVerticesStored-2;
+ TempBufferRenderIndexList[TempBufferIndicesStored+1] = TempBufferVerticesStored-1;
+ TempBufferRenderIndexList[TempBufferIndicesStored+2] = TempBufferVerticesStored+1;
+ TempBufferRenderIndexList[TempBufferIndicesStored+3] = TempBufferVerticesStored-2;
+ TempBufferRenderIndexList[TempBufferIndicesStored+4] = TempBufferVerticesStored+1;
+ TempBufferRenderIndexList[TempBufferIndicesStored+5] = TempBufferVerticesStored;
+ TempBufferVerticesStored += 2;
+ TempBufferIndicesStored += 6;
+ }
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[2]));
+
+#ifdef FIX_BUGS
+ if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV|rwIM3D_VERTEXRGBA)){
+#else
+ if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 0)){
+#endif
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
+ RwIm3DEnd();
+ }
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+ }
+ }
+}
+
+void
+CPlaneBanner::RegisterPoint(CVector pos)
+{
+ m_pos[0] = pos;
+}
+
+void
+CPlaneBanners::Init(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(aArray); i++)
+ aArray[i].Init();
+}
+
+void
+CPlaneBanners::Update(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(aArray); i++)
+ aArray[i].Update();
+}
+
+void
+CPlaneBanners::Render(void)
+{
+ int i;
+ for(i = 0; i < ARRAY_SIZE(aArray); i++)
+ aArray[i].Render();
+}
+
+void
+CPlaneBanners::RegisterPoint(CVector pos, uint32 id)
+{
+ aArray[id].RegisterPoint(pos);
+}
+
+bool CSmokeTrails::CigOn = false;
+CSmokeTrail CSmokeTrails::aSmoke[3];
+
+RwImVertexIndex SmokeTrailIndices[32] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 };
+
+float RandomSmoke[16] = { 10.0f, 5.0f, -1.0f, -9.0f, -7.0f, -1.0f, 0.0f, 3.0f, 6.0f, 7.0f, 4.0f, 2.0f,
+5.0f, 7.0f };
uint8 ScrollCharSet[59][5] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' '
@@ -99,12 +389,20 @@ CMovingThing CMovingThings::aMovingThings[NUMMOVINGTHINGS];
void CMovingThings::Init()
{
+ CPlaneTrails::Init();
+ CSmokeTrails::Init();
+ CPlaneBanners::Init();
+ CPointLights::Init();
+
StartCloseList.m_pNext = &CMovingThings::EndCloseList;
StartCloseList.m_pPrev = nil;
EndCloseList.m_pNext = nil;
EndCloseList.m_pPrev = &CMovingThings::StartCloseList;
Num = 0;
-
+
+ CEscalators::Init();
+
+#ifndef MIAMI // something is still used here actually
// Initialize scroll bars
aScrollBars[0].Init(CVector( 228.3f, -669.0f, 39.0f ), SCROLL_BUSINESS, 0.0f, 0.5f, 0.5f, 255, 128, 0, 0.3f);
aScrollBars[1].Init(CVector( 772.0f, 164.0f, -9.5f ), SCROLL_TRAFFIC, 0.0f, 0.5f, 0.25f, 128, 255, 0, 0.3f);
@@ -137,6 +435,7 @@ void CMovingThings::Init()
CVector(58.145f - sz.y * 0.05f - sz.x * 0.3f, -1079.268f + sz.x * 0.05f - sz.y * 0.3f, 32.803f),
-sz.x, -sz.y, 0, 255, 0, 100.0f, 0.8f
);
+#endif
}
void CMovingThings::Shutdown()
@@ -144,18 +443,25 @@ void CMovingThings::Shutdown()
int i;
for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i)
aScrollBars[i].SetVisibility(false);
+/*
for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i)
aTowerClocks[i].SetVisibility(false);
for (i = 0; i < ARRAY_SIZE(aDigitalClocks); ++i)
aDigitalClocks[i].SetVisibility(false);
+*/
+ CEscalators::Shutdown();
}
void CMovingThings::Update()
{
- int16 i;
-#ifndef SQUEEZE_PERFORMANCE
+ CPlaneBanners::Update();
+ CPlaneTrails::Update();
+ CEscalators::Update();
+
const int TIME_SPAN = 64; // frames to process all aMovingThings
+ int16 i;
+
int block = CTimer::GetFrameCounter() % TIME_SPAN;
for (i = (block * NUMMOVINGTHINGS) / TIME_SPAN; i < ((block + 1) * NUMMOVINGTHINGS) / TIME_SPAN; i++) {
@@ -167,8 +473,7 @@ void CMovingThings::Update()
if (aMovingThings[i].m_nHidden == 0)
aMovingThings[i].Update();
}
-#endif
-
+ /* I don't think these are done yet?
for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i)
{
if (aScrollBars[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0)
@@ -184,16 +489,20 @@ void CMovingThings::Update()
if (aDigitalClocks[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0)
aDigitalClocks[i].Update();
}
+ */
}
void CMovingThings::Render()
{
+ CSmokeTrails::Update();
+
int i;
for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i)
{
if (aScrollBars[i].IsVisible())
aScrollBars[i].Render();
}
+/*
for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i)
{
if (aTowerClocks[i].IsVisible())
@@ -204,6 +513,11 @@ void CMovingThings::Render()
if (aDigitalClocks[i].IsVisible())
aDigitalClocks[i].Render();
}
+*/
+
+ CPlaneTrails::Render();
+ CSmokeTrails::Render();
+ CPlaneBanners::Render();
}
// ---------- CMovingThing ----------
@@ -382,7 +696,7 @@ void CScrollBar::Update()
m_pMessage = FindTimeMessage();
break;
case 6:
- if (CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN)
+ if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN)
m_pMessage = FindTimeMessage();
else
m_pMessage = "WWW.GRANDTHEFTAUTO3.COM ";
@@ -602,7 +916,7 @@ void CScrollBar::Update()
m_pMessage = "FREE FLUFFY DICE WITH ALL PURCHASES. . .";
break;
case 9:
- if (CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN)
+ if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN)
m_pMessage = "QUICK, TAKE A LOOK AT OUR CURRENT STOCK )CAUSE THESE AUTOS ARE MOVIN) FAST . . . ";
else
m_pMessage = "HTTP:((ROCKSTARGAMES.COM(GRANDTHEFTAUTO3(CAPITALAUTOS ";
@@ -866,3 +1180,344 @@ void CDigitalClock::Render()
CSprite::FlushSpriteBuffer();
}
}
+
+void
+CSmokeTrail::RegisterPoint(CVector regPosition, float opacity) {
+ bool bAddedNewPoint = false;
+
+ if (m_time[0] && CTimer::GetTimeInMilliseconds() - m_time[0] > 150) {
+ bAddedNewPoint = true;
+ for (int32 i = 15; i > 0; i--) {
+ m_pos[i] = m_pos[i - 1];
+ m_time[i] = m_time[i - 1];
+ m_opacity[i] = m_opacity[i - 1];
+ }
+ ++m_seed;
+ }
+ m_pos[0] = regPosition;
+
+ if (bAddedNewPoint || !m_time[0]) {
+ m_time[0] = CTimer::GetTimeInMilliseconds();
+ float density = 0.1f / (m_pos[1] - m_pos[2]).Magnitude();
+ m_opacity[1] = opacity * Min(density, 1.0f);
+ }
+ m_opacity[0] = 0.0f;
+}
+
+void
+CSmokeTrail::Init(int num) {
+ for (int32 i = 0; i < 16; i++)
+ m_time[i] = 0;
+ m_seed = num * 2;
+}
+
+void
+CSmokeTrails::Init(void) {
+ for (int32 i = 0; i < 3; i++)
+ aSmoke[i].Init(i);
+}
+
+void
+CSmokeTrails::Render(void) {
+ for (int32 i = 0; i < 3; i++)
+ aSmoke[i].Render();
+}
+
+void
+CSmokeTrail::Render(void) {
+ int numVerts = 0;
+
+ if (TheCamera.IsSphereVisible(m_pos[0], 10.0f)) {
+ for (int32 i = 0; i < 16; i++) {
+ int timeSinceSpawned = CTimer::GetTimeInMilliseconds() - m_time[i];
+
+ if (timeSinceSpawned > 2250)
+ m_time[i] = 0;
+
+ if (m_time[i]) {
+ int alpha = (1.0f - timeSinceSpawned / 2250.0f) * 110.0f * m_opacity[i];
+ float offset = timeSinceSpawned * CWeather::Wind * 0.0001f;
+ float posX = (m_pos[i].x + timeSinceSpawned * RandomSmoke[(i - m_seed) & 0xF] * 0.00001f) - offset;
+ float posY = (m_pos[i].y + timeSinceSpawned * RandomSmoke[(i - m_seed + 5) & 0xF] * 0.00001f) - offset;
+ float posZ = m_pos[i].z + timeSinceSpawned * 0.0004f;
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 200, 200, 200, alpha);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[i], posX, posY, posZ);
+ numVerts++;
+ }
+ }
+ }
+
+ if (numVerts > 1) {
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+
+ if (RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) {
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2 * (numVerts - 1));
+ RwIm3DEnd();
+ }
+ }
+}
+
+void
+CSmokeTrails::Update(void) {
+
+ if (!CSmokeTrails::CigOn || TheCamera.Using1stPersonWeaponMode() || !FindPlayerPed() ||
+ FindPlayerVehicle() || CCutsceneMgr::IsRunning() || !FindPlayerPed()->GetClump())
+ return;
+
+ RwV3d startPos = { 0.026f, 0.15f, 0.02f };
+ RwV3d endPos = { 0.026f, 0.05f, 0.02f };
+
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(FindPlayerPed()->GetClump());
+ int32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD));
+ RwMatrix *head = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
+ RwV3dTransformPoints(&startPos, &startPos, 1, head);
+ RwV3dTransformPoints(&endPos, &endPos, 1, head);
+
+ aSmoke[0].RegisterPoint(startPos, 1.0f);
+ aSmoke[1].RegisterPoint(startPos, 0.75f);
+ aSmoke[2].RegisterPoint(startPos, 0.5f);
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[0], startPos.x, startPos.y, startPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[1], endPos.x, endPos.y, endPos.z);
+
+ if (RwIm3DTransform(TempBufferRenderVertices, 2, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) {
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2);
+ RwIm3DEnd();
+ }
+}
+
+CEscalator CEscalators::aEscalators[NUM_ESCALATORS];
+int32 CEscalators::NumEscalators;
+
+CEscalator::CEscalator() {
+ m_bIsActive = false;
+
+ for (int i = 0; i < 24; i++) {
+ m_pSteps[i] = nil;
+ }
+}
+
+void
+CEscalator::AddThisOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown) {
+ m_pos0 = pos0;
+ m_pos1 = pos1;
+ m_pos2 = pos2;
+ m_pos3 = pos3;
+
+ float escalatorStepHeight = CModelInfo::GetModelInfo(MI_ESCALATORSTEP)->GetColModel()->boundingBox.max.z;
+ m_pos0.z -= escalatorStepHeight;
+ m_pos1.z -= escalatorStepHeight;
+ m_pos2.z -= escalatorStepHeight;
+ m_pos3.z -= escalatorStepHeight;
+
+ float magnitudes[3];
+ magnitudes[0] = (m_pos0 - m_pos1).Magnitude();
+ magnitudes[1] = (m_pos1 - m_pos2).Magnitude();
+ magnitudes[2] = (m_pos2 - m_pos3).Magnitude();
+
+ float length = magnitudes[0] + magnitudes[1] + magnitudes[2];
+
+ m_lowerEnd = magnitudes[0] / length;
+ m_upperEnd = (magnitudes[0] + magnitudes[1]) / length;
+
+ m_stepsCount = Max(24.0f, length / 0.6f);
+
+ CVector direction(m_pos0.x - m_pos1.x, m_pos0.y - m_pos1.y, 0.0f);
+ direction.Normalise();
+
+ m_matrix.GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ m_matrix.GetForward() = CVector(direction.x, direction.y, 0.0f);
+ m_matrix.GetRight() = CVector(direction.y, -direction.x, 0.0f);
+ m_matrix.GetPosition() = CVector(0.0f, 0.0f, 0.0f);
+
+ m_bIsMovingDown = b_isMovingDown;
+
+ m_midPoint = (m_pos0 + m_pos3) / 2.0f;
+
+ m_radius = (m_pos0 - m_midPoint).Magnitude();
+}
+
+void
+CEscalator::Update(void) {
+ if (!m_bIsActive) {
+ if ((TheCamera.GetPosition() - m_midPoint).Magnitude() < 25.0f) {
+ if (TheCamera.IsSphereVisible(m_midPoint, m_radius) && (m_stepsCount + 10 < CPools::GetObjectPool()->GetNoOfFreeSpaces())) {
+ m_bIsActive = true;
+ for (int i = 0; i < m_stepsCount; i++) {
+ m_pSteps[i] = new CObject(MI_ESCALATORSTEP, TRUE);
+ if (m_pSteps[i]) {
+ m_pSteps[i]->SetPosition(m_pos1);
+ CWorld::Add(m_pSteps[i]);
+ m_pSteps[i]->ObjectCreatedBy = ESCALATOR_OBJECT;
+ }
+ }
+ }
+ }
+ }
+
+ if (m_bIsActive) {
+ float time = (CTimer::GetTimeInMilliseconds() % 16384) / 16384.0f;
+ for (int i = 0; i < m_stepsCount; i++) {
+ if (m_pSteps[i]) {
+ float t = i / (float)m_stepsCount + time;
+
+ if (t > 1.0f)
+ t -= 1.0f;
+
+ if (m_bIsMovingDown)
+ t = 1.0f - t;
+
+ CVector oldPosition = m_pSteps[i]->GetPosition();
+ m_pSteps[i]->GetMatrix() = m_matrix;
+
+ CVector newPosition;
+ if (t < m_lowerEnd) {
+ float ratio = t / m_lowerEnd;
+ newPosition = (ratio * m_pos1) + ((1.0f - ratio) * m_pos0);
+ }
+ else if (t < m_upperEnd) {
+ float ratio = (t - m_lowerEnd) / (m_upperEnd - m_lowerEnd);
+ newPosition = (ratio * m_pos2) + ((1.0f - ratio) * m_pos1);
+ }
+ else {
+ float ratio = (t - m_upperEnd) / (1.0f - m_upperEnd);
+ newPosition = (ratio * m_pos3) + ((1.0f - ratio) * m_pos2);
+ }
+
+ m_pSteps[i]->SetPosition(newPosition);
+ m_pSteps[i]->m_vecMoveSpeed = (newPosition - oldPosition) / Max(CTimer::GetTimeStep(), 1.0f);
+ m_pSteps[i]->GetMatrix().UpdateRW();
+ m_pSteps[i]->UpdateRwFrame();
+ }
+ if ((TheCamera.GetPosition() - m_midPoint).Magnitude() > 28.0f || !TheCamera.IsSphereVisible(m_midPoint, m_radius))
+ SwitchOff();
+ }
+ }
+}
+
+bool deletingEscalator;
+
+void
+CEscalator::SwitchOff(void) {
+ if (m_bIsActive) {
+ for (int i = 0; i < m_stepsCount; i++) {
+ if (m_pSteps[i]) {
+ CWorld::Remove(m_pSteps[i]);
+ deletingEscalator = true;
+ delete m_pSteps[i];
+ m_pSteps[i] = nil;
+ deletingEscalator = false;
+ }
+ }
+ m_bIsActive = false;
+ }
+}
+
+void
+CEscalators::AddOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown) {
+ aEscalators[NumEscalators++].AddThisOne(pos0, pos1, pos2, pos3, b_isMovingDown);
+}
+
+void
+CEscalators::Init(void) {
+ Shutdown();
+ NumEscalators = 0;
+
+ AddOne(CVector(-9.82999f, -938.04498f, 9.4219f), CVector(-8.573f, -938.04498f, 9.4219f),
+ CVector(-0.747f, -938.045f, 15.065f), CVector(0.88f, -938.045f, 15.065f), TRUE);
+
+ AddOne(CVector(-9.83f, -939.966f, 9.422f), CVector(-8.573f, -939.966f, 9.422f),
+ CVector(-0.747f, -939.966f, 15.065f), CVector(0.880f, -939.966f, 15.065f), FALSE);
+
+ AddOne(CVector(408.116f, 1058.36f, 18.261f), CVector(408.094f, 1057.04f, 18.261f),
+ CVector(408.116f, 1048.0f, 24.765f), CVector(408.094f, 1046.57f, 24.799f), TRUE);
+
+ AddOne(CVector(406.195f, 1058.36f, 18.261f), CVector(406.173f, 1057.04f, 18.261f),
+ CVector(406.195f, 1048.0f, 24.729f), CVector(406.173f, 1046.57f, 24.79f), FALSE);
+
+ AddOne(CVector(421.729f, 1058.3789f, 18.075f), CVector(421.707f, 1057.052f, 18.099f),
+ CVector(421.729f, 1048.016f, 24.604f), CVector(421.707f, 1046.589f, 24.637f), TRUE);
+
+ AddOne(CVector(419.808f, 1058.378f, 18.099f), CVector(419.786f, 1057.052f, 18.099f),
+ CVector(419.808f, 1048.016f, 24.568f), CVector(419.786f, 1046.589f, 24.637f), FALSE);
+
+ AddOne(CVector(412.69901f, 1102.729f, 17.569f), CVector(412.72198f, 1104.057f, 17.57f),
+ CVector(412.69901f, 1113.092f, 24.073f), CVector(412.72198f, 1114.3201f, 24.108f), TRUE);
+
+ AddOne(CVector(414.62f, 1102.729f, 17.569f), CVector(414.64301f, 1104.057f, 17.57f),
+ CVector(414.62f, 1113.092f, 24.037001f), CVector(414.64301f, 1114.3201f, 24.099001f), FALSE);
+
+ AddOne(CVector(414.64301f, 1145.589f, 17.57f), CVector(414.62f, 1144.261f, 17.569f),
+ CVector(414.64301f, 1135.226f, 24.073999f), CVector(414.62f, 1133.798f, 24.107f), TRUE);
+
+ AddOne(CVector(412.72198f, 1145.589f, 17.57f), CVector(412.69901f, 1144.261f, 17.569f),
+ CVector(412.72198f, 1135.226f, 24.038f), CVector(412.69901f, 1133.798f, 24.098f), FALSE);
+
+ AddOne(CVector(406.05099f, 1193.4771f, 18.016001f), CVector(406.07401f, 1194.8051f, 18.017f),
+ CVector(406.05099f, 1203.84f, 24.52f), CVector(406.07401f, 1205.2679f, 24.555f), TRUE);
+
+ AddOne(CVector(407.97198f, 1193.4771f, 18.016001f), CVector(407.995f, 1194.8051f, 18.017f),
+ CVector(407.97198f, 1203.84f, 24.483999f), CVector(407.995f, 1205.2679f, 24.546f), FALSE);
+
+ AddOne(CVector(419.659f, 1193.479f, 17.979f), CVector(419.68201f, 1194.807f, 17.98f),
+ CVector(419.659f, 1203.842f, 24.483f), CVector(419.68201f, 1205.27f, 24.518f), TRUE);
+
+ AddOne(CVector(421.57999f, 1193.479f, 17.979f), CVector(421.603f, 1194.807f, 17.98f),
+ CVector(421.57999f, 1203.842f, 24.447001f), CVector(421.603f, 1205.27f, 24.509001f), FALSE);
+
+ AddOne(CVector(406.23199f, 1022.857f, 17.917f), CVector(406.23199f, 1024.1851f, 17.917f),
+ CVector(406.23199f, 1033.22f, 24.521f), CVector(406.23199f, 1034.647f, 24.555f), TRUE);
+
+ AddOne(CVector(408.15302f, 1022.857f, 17.917f), CVector(408.15302f, 1024.1851f, 17.916f),
+ CVector(408.15302f, 1033.22f, 24.486f), CVector(408.15302f, 1034.647f, 24.52f), FALSE);
+
+ AddOne(CVector(-1506.39f, -813.13f, 13.834f), CVector(-1506.177f, -814.51703f, 13.834f),
+ CVector(-1504.566f, -823.20898f, 19.836f), CVector(-1504.329f, -824.48499f, 19.837f), FALSE);
+
+ AddOne(CVector(-1481.951f, -859.05402f, 13.834f), CVector(-1482.7791f, -858.22498f, 13.834f),
+ CVector(-1489.03f, -851.974f, 19.836f), CVector(-1489.948f, -851.05701f, 19.837f), TRUE);
+
+ AddOne(CVector(-1461.743f, -871.35901f, 13.834f), CVector(-1460.62f, -871.69202f, 13.834f),
+ CVector(-1452.144f, -874.20203f, 19.836f), CVector(-1450.9f, -874.57098f, 19.837f), FALSE);
+
+ AddOne(CVector(-1409.889f, -871.41498f, 13.834f), CVector(-1411.0129f, -871.74701f, 13.834f),
+ CVector(-1419.489f, -874.258f, 19.836f), CVector(-1420.733f, -874.62701f, 19.837f), TRUE);
+
+ AddOne(CVector(-1389.577f, -858.89301f, 13.834f), CVector(-1388.7271f, -858.08698f, 13.834f),
+ CVector(-1382.314f, -852.00201f, 19.836f), CVector(-1381.373f, -851.10797f, 19.837f), FALSE);
+
+ AddOne(CVector(-1364.981f, -813.13f, 13.834f), CVector(-1365.204f, -814.28003f, 13.834f),
+ CVector(-1366.891f, -822.95801f, 19.83f), CVector(-1367.139f, -824.23199f, 19.837f), TRUE);
+
+ for (int i = 0; i < NUM_ESCALATORS; i++) {
+ aEscalators[i].SwitchOff();
+ }
+}
+
+void
+CEscalators::Update(void) {
+ if (CReplay::IsPlayingBack())
+ return;
+
+ for (int i = 0; i < NUM_ESCALATORS; i++) {
+ aEscalators[i].Update();
+ }
+}
+
+void
+CEscalators::Shutdown(void) {
+ for (int i = 0; i < NUM_ESCALATORS; i++) {
+ aEscalators[i].SwitchOff();
+ }
+ NumEscalators = 0;
+} \ No newline at end of file
diff --git a/src/render/Fluff.h b/src/render/Fluff.h
index fe3ab256..a938a4fe 100644
--- a/src/render/Fluff.h
+++ b/src/render/Fluff.h
@@ -1,6 +1,92 @@
#pragma once
#include "common.h"
#include "Vector.h"
+#include "Object.h"
+
+// TODO
+class CScriptPath
+{
+public:
+};
+
+// TODO
+class CScriptPaths
+{
+public:
+};
+
+class CPlaneTrail
+{
+ CVector m_pos[16];
+ int32 m_time[16];
+public:
+ void Init(void);
+ void Render(float visibility);
+ void RegisterPoint(CVector pos);
+};
+
+class CPlaneTrails
+{
+ static CPlaneTrail aArray[6]; // NB: 3 CPlanes and 3 hardcoded far away ones
+public:
+ static void Init(void);
+ static void Update(void);
+ static void Render(void);
+ static void RegisterPoint(CVector pos, uint32 id);
+};
+
+class CPlaneBanner
+{
+ CVector m_pos[8];
+public:
+ void Init(void);
+ void Update(void);
+ void Render(void);
+ void RegisterPoint(CVector pos);
+};
+
+class CPlaneBanners
+{
+ static CPlaneBanner aArray[5];
+public:
+ static void Init(void);
+ static void Update(void);
+ static void Render(void);
+ static void RegisterPoint(CVector pos, uint32 id);
+};
+
+class CEscalator
+{
+ CVector m_pos0;
+ CVector m_pos1;
+ CVector m_pos2;
+ CVector m_pos3;
+ CMatrix m_matrix;
+ bool m_bIsActive;
+ bool m_bIsMovingDown;
+ int32 m_stepsCount;
+ float m_lowerEnd;
+ float m_upperEnd;
+ CVector m_midPoint;
+ float m_radius;
+ CObject *m_pSteps[24];
+public:
+ CEscalator();
+ void Update(void);
+ void SwitchOff(void);
+ void AddThisOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown);
+};
+
+class CEscalators
+{
+ static CEscalator aEscalators[NUM_ESCALATORS];
+public:
+ static int32 NumEscalators;
+ static void Init(void);
+ static void Update(void);
+ static void AddOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown);
+ static void Shutdown(void);
+};
class CMovingThing
{
@@ -103,4 +189,25 @@ public:
void Init(CVector, float, float, uint8, uint8, uint8, float, float);
void Update();
void Render();
+};
+
+class CSmokeTrail {
+ CVector m_pos[16];
+ float m_opacity[16];
+ int m_time[16];
+ char m_unused[536];
+ int m_seed;
+public:
+ void Render(void);
+ void RegisterPoint(CVector position, float a);
+ void Init(int num);
+};
+
+class CSmokeTrails {
+ static CSmokeTrail aSmoke[3];
+public:
+ static bool CigOn;
+ static void Update(void);
+ static void Render(void);
+ static void Init(void);
}; \ No newline at end of file
diff --git a/src/render/Font.cpp b/src/render/Font.cpp
index de7de81a..1e60083b 100644
--- a/src/render/Font.cpp
+++ b/src/render/Font.cpp
@@ -3,68 +3,39 @@
#include "Sprite2d.h"
#include "TxdStore.h"
#include "Font.h"
+#include "Timer.h"
CFontDetails CFont::Details;
int16 CFont::NewLine;
CSprite2d CFont::Sprite[MAX_FONTS];
+CFontRenderState CFont::RenderState;
#ifdef MORE_LANGUAGES
uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS;
int32 CFont::Slot = -1;
#define JAP_TERMINATION (0x8000 | '~')
-int16 CFont::Size[LANGSET_MAX][MAX_FONTS][193] = {
+int16 CFont::Size[LANGSET_MAX][MAX_FONTS][210] = {
{
#else
-int16 CFont::Size[MAX_FONTS][193] = {
+int16 CFont::Size[MAX_FONTS][210] = {
#endif
- {
- 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31,
- 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26,
- 30, 26, 24, 23, 24, 22, 21, 24, 26, 10, 20, 26, 22, 29, 26, 25,
- 23, 25, 24, 24, 22, 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37,
- 35, 21, 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21, 21,
- 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 33, 33, 33, 33, 35,
- 27, 27, 27, 27, 32, 24, 23, 23, 23, 23, 11, 11, 11, 11, 26, 26,
- 26, 26, 26, 26, 26, 25, 26, 21, 21, 21, 21, 32, 23, 22, 22, 22,
- 22, 11, 11, 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 26, 21, 24,
- 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 20
- },
-
- {
- 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11, 17, 13, 33,
- 28, 14, 22, 21, 24, 23, 23, 21, 23, 22, 10, 35, 13, 35, 13, 33,
- 5, 25, 22, 23, 24, 21, 21, 24, 24, 9, 20, 24, 21, 27, 25, 25,
- 22, 25, 23, 20, 23, 23, 23, 31, 23, 23, 23, 37, 33, 37, 35, 37,
- 35, 21, 19, 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21,
- 20, 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33, 33, 35,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 16
- },
-
- {
- 15, 14, 16, 25, 19, 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27,
- 19, 18, 19, 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35,
- 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29, 19, 20,
- 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 33, 31, 39, 37, 39,
- 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23, 23,
- 20, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35, 35, 35, 35, 37,
- 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 30, 19, 19, 19, 19,
- 19, 10, 10, 10, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 35,
- 12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19
- }
+ {
+ 12, 9, 22, 17, 19, 19, 25, 4, 33, 33, 25, 35, 11, 10, 6, 33, 18, 10, 17, 17, 17, 17, 17, 15, 12, 16, 5, 30, 30, 30, 30, 30, 12, 16, 19,
+ 16, 19, 18, 18, 17, 22, 11, 17, 18, 18, 30, 22, 19, 22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 19, 19, 12, 14, 11, 11, 16, 11,
+ 12, 14, 14, 10, 13, 12, 10, 19, 18, 12, 16, 13, 13, 11, 12, 15, 12, 15, 13, 12, 12, 37, 33, 37, 35, 37, 16, 16, 16, 16, 33, 17, 18, 18, 18,
+ 18, 11, 11, 11, 11, 19, 19, 19, 19, 19, 19, 19, 19, 15, 14, 14, 14, 14, 20, 14, 11, 11, 11, 11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15,
+ 15, 24, 18, 21, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16
+ },
+ {
+ 15, 7, 31, 25, 20, 23, 21, 7, 11, 10, 26, 14, 6, 12, 6, 26, 20, 7, 20, 20, 21, 20, 20, 19, 21, 20, 8, 30, 24, 30, 24, 19, 20, 22, 22, 21, 22, 18, 18, 22,
+ 22, 9, 14, 21, 18, 27, 21, 24, 22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30, 10, 19, 10, 17, 17, 16, 17, 17, 11, 17, 17, 7, 7, 18, 7, 25, 17,
+ 17, 17, 17, 11, 17, 11, 17, 18, 25, 19, 18, 17, 28, 26, 20, 15, 15, 20, 20, 20, 20, 29, 22, 19, 19, 19, 19, 9, 9, 9, 9, 23, 23, 23, 23, 24, 24, 24, 24,
+ 20, 19, 17, 17, 17, 30, 16, 17, 17, 17, 17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 19, 20, 20, 20, 18, 19, 19, 21, 19, 19, 19, 19, 19, 16, 19,
+ 19, 19, 20, 19, 16, 19, 19, 9, 19, 20, 14, 29, 19, 19, 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, 10, 9, 10, 20
+ }
#ifdef MORE_LANGUAGES
},
{
@@ -198,6 +169,21 @@ wchar foreign_table[128] = {
0, 174, 165, 166, 167, 0, 168, 0, 0, 169, 170, 171, 172, 0, 0, 0,
};
+union tFontRenderStatePointer
+{
+ CFontRenderState *pRenderState;
+ wchar *pStr;
+
+ void Align()
+ {
+ if ((uintptr)pStr % 4)
+ pStr++;
+ }
+};
+
+tFontRenderStatePointer FontRenderStatePointer;
+uint8 FontRenderStateBuf[1024];
+
void
CFont::Initialise(void)
{
@@ -228,16 +214,14 @@ CFont::Initialise(void)
CTxdStore::AddRef(slot);
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(slot);
- Sprite[0].SetTexture("font2", "font2_mask");
+ Sprite[0].SetTexture("font2", "font2m");
#ifdef MORE_LANGUAGES
if (IsJapanese()) {
Sprite[1].SetTexture("FONTJAP", "FONTJAP_mask");
Sprite[3].SetTexture("FONTJAP", "FONTJAP_mask");
}
- else
#endif // MORE_LANGUAGES
- Sprite[1].SetTexture("pager", "pager_mask");
- Sprite[2].SetTexture("font1", "font1_mask");
+ Sprite[1].SetTexture("font1", "font1m");
SetScale(1.0f, 1.0f);
SetSlantRefPoint(SCREEN_WIDTH, 0.0f);
SetSlant(0.0f);
@@ -305,7 +289,6 @@ CFont::Shutdown(void)
{
Sprite[0].Delete();
Sprite[1].Delete();
- Sprite[2].Delete();
#ifdef MORE_LANGUAGES
if (IsJapanese())
Sprite[3].Delete();
@@ -319,13 +302,9 @@ CFont::Shutdown(void)
void
CFont::InitPerFrame(void)
{
- Details.bank = CSprite2d::GetBank(30, Sprite[0].m_pTexture);
- CSprite2d::GetBank(15, Sprite[1].m_pTexture);
- CSprite2d::GetBank(15, Sprite[2].m_pTexture);
-#ifdef MORE_LANGUAGES
- if (IsJapanese())
- CSprite2d::GetBank(15, Sprite[3].m_pTexture);
-#endif
+ RenderState.style = -1;
+ Details.anonymous_25 = 0;
+ FontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf;
SetDropShadowPosition(0);
NewLine = 0;
}
@@ -333,11 +312,15 @@ CFont::InitPerFrame(void)
void
CFont::PrintChar(float x, float y, wchar c)
{
+ bool bDontPrint = false;
if(x <= 0.0f || x > SCREEN_WIDTH ||
y <= 0.0f || y > SCREEN_HEIGHT) // BUG: game uses SCREENW again
return;
+ bDontPrint = c == '\0';
float w = GetCharacterWidth(c) / 32.0f;
+ if (Details.bFontHalfTexture && c == 208)
+ c = '\0';
float xoff = c % 16;
float yoff = c / 16;
#ifdef MORE_LANGUAGES
@@ -348,28 +331,40 @@ CFont::PrintChar(float x, float y, wchar c)
}
#endif
- if(Details.style == FONT_BANK || Details.style == FONT_HEADING){
- if(Details.dropShadowPosition != 0){
- CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
- CRect(x + SCREEN_SCALE_X(Details.dropShadowPosition),
- y + SCREEN_SCALE_Y(Details.dropShadowPosition),
- x + SCREEN_SCALE_X(Details.dropShadowPosition) + 32.0f * Details.scaleX * 1.0f,
- y + SCREEN_SCALE_Y(Details.dropShadowPosition) + 40.0f * Details.scaleY * 0.5f),
- Details.dropColor,
- xoff/16.0f, yoff/12.8f,
- (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f,
- xoff/16.0f, (yoff+1.0f)/12.8f,
- (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.0001f);
- }
- CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
- CRect(x, y,
- x + 32.0f * Details.scaleX * 1.0f,
- y + 40.0f * Details.scaleY * 0.5f),
- Details.color,
- xoff/16.0f, yoff/12.8f,
- (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f,
- xoff/16.0f, (yoff+1.0f)/12.8f - 0.002f,
- (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.002f);
+ if(Details.style == FONT_BANK || Details.style == FONT_STANDARD){
+ if (bDontPrint) return;
+ if (RenderState.slant == 0.0f) {
+ if (c < 193) {
+ CSprite2d::AddToBuffer(
+ CRect(x, y,
+ x + 32.0f * RenderState.scaleX * 1.0f,
+ y + 40.0f * RenderState.scaleY * 0.5f),
+ RenderState.color,
+ xoff / 16.0f, yoff / 12.8f + 0.0021f,
+ (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f,
+ xoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.0021f,
+ (xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.0021f);
+ } else {
+ CSprite2d::AddToBuffer(
+ CRect(x, y,
+ x + 32.0f * RenderState.scaleX * 1.0f,
+ y + 33.0f * RenderState.scaleY * 0.5f),
+ RenderState.color,
+ xoff / 16.0f, yoff / 12.8f,
+ (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f - 0.017f,
+ xoff / 16.0f, (yoff + 1.0f) / 12.8f,
+ (xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.017f);
+ }
+ } else
+ CSprite2d::AddToBuffer(
+ CRect(x, y,
+ x + 32.0f * RenderState.scaleX * 1.0f,
+ y + 40.0f * RenderState.scaleY * 0.5f),
+ RenderState.color,
+ xoff / 16.0f, yoff / 12.8f + 0.00055f,
+ (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f + 0.01f,
+ xoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.009f,
+ (xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.0021f + 0.01f);
#ifdef MORE_LANGUAGES
}else if (IsJapaneseFont()) {
if (Details.dropShadowPosition != 0) {
@@ -394,16 +389,18 @@ CFont::PrintChar(float x, float y, wchar c)
xoff * w / 1024.0f, (yoff + 1.0f) / 25.6f - 0.002f,
xoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, (yoff + 1.0f) / 25.6f - 0.0001f);
#endif
- }else
- CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
+ } else {
+ if (bDontPrint) return;
+ CSprite2d::AddToBuffer(
CRect(x, y,
- x + 32.0f * Details.scaleX * w,
- y + 32.0f * Details.scaleY * 0.5f),
- Details.color,
- xoff/16.0f, yoff/16.0f,
- (xoff+w)/16.0f, yoff/16.0f,
- xoff/16.0f, (yoff+1.0f)/16.0f,
- (xoff+w)/16.0f - 0.0001f, (yoff+1.0f)/16.0f - 0.0001f);
+ x + 32.0f * RenderState.scaleX * w,
+ y + 32.0f * RenderState.scaleY * 0.5f),
+ RenderState.color,
+ xoff / 16.0f, yoff / 16.0f,
+ (xoff + w) / 16.0f, yoff / 16.0f,
+ xoff / 16.0f, (yoff + 1.0f) / 16.0f,
+ (xoff + w) / 16.0f - 0.0001f, (yoff + 1.0f) / 16.0f - 0.0001f);
+ }
}
#ifdef MORE_LANGUAGES
@@ -484,7 +481,7 @@ CFont::PrintString(float xstart, float ystart, wchar *s)
#ifdef MORE_LANGUAGES
PrintString(xleft, y, start, s, spaceWidth, xstart);
#else
- PrintString(xleft, y, start, s, spaceWidth);
+ PrintString(xleft, y, Details.anonymous_25, start, s, spaceWidth);
#endif
// reset things
lineLength = 0.0f;
@@ -564,7 +561,7 @@ CFont::PrintString(float xstart, float ystart, wchar *s)
lineLength = 0.0f;
}
#else
- PrintString(xleft, y, start, s, 0.0f);
+ PrintString(xleft, y, Details.anonymous_25, start, s, 0.0f);
#endif
}
}
@@ -805,24 +802,81 @@ CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, f
}
#else
void
-CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth)
+CFont::PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth)
{
- wchar *s, c, unused;
+ wchar *s;
- for(s = start; s < end; s++){
- if(*s == '~')
- s = ParseToken(s, &unused);
- c = *s - ' ';
- if(Details.slant != 0.0f)
- y = (Details.slantRefX - x)*Details.slant + Details.slantRefY;
- PrintChar(x, y, c);
- x += GetCharacterSize(c);
- if(c == 0) // space
- x += spwidth;
+ if (RenderState.style != Details.style) {
+ RenderFontBuffer();
+ RenderState.style = Details.style;
+ }
+
+ float dropShadowPosition = Details.dropShadowPosition;
+ if (dropShadowPosition != 0.0f && (Details.style == FONT_BANK || Details.style == FONT_STANDARD)) {
+ CRGBA color = Details.color;
+ Details.color = Details.dropColor;
+ Details.dropShadowPosition = 0;
+ Details.bIsShadow = true;
+ if (Details.slant != 0.0f) {
+ Details.slantRefX += SCREEN_SCALE_X(dropShadowPosition);
+ Details.slantRefY += SCREEN_SCALE_Y(dropShadowPosition);
+ PrintString(SCREEN_SCALE_X(dropShadowPosition) + x, SCREEN_SCALE_Y(dropShadowPosition) + y, Details.anonymous_25, start, end, spwidth);
+ Details.slantRefX -= SCREEN_SCALE_X(dropShadowPosition);
+ Details.slantRefY -= SCREEN_SCALE_Y(dropShadowPosition);
+ } else {
+ PrintString(SCREEN_SCALE_X(dropShadowPosition) + x, SCREEN_SCALE_Y(dropShadowPosition) + y, Details.anonymous_25, start, end, spwidth);
+ }
+ Details.color = color;
+ Details.dropShadowPosition = dropShadowPosition;
+ Details.bIsShadow = false;
}
+ if (FontRenderStatePointer.pStr >= (wchar*)&FontRenderStateBuf[ARRAY_SIZE(FontRenderStateBuf)] - (end - start + 26)) // why 26?
+ RenderFontBuffer();
+ CFontRenderState *pRenderState = FontRenderStatePointer.pRenderState;
+ pRenderState->fTextPosX = x;
+ pRenderState->fTextPosY = y;
+ pRenderState->scaleX = Details.scaleX;
+ pRenderState->scaleY = Details.scaleY;
+ pRenderState->color = Details.color;
+ pRenderState->fExtraSpace = spwidth;
+ pRenderState->slant = Details.slant;
+ pRenderState->slantRefX = Details.slantRefX;
+ pRenderState->slantRefY = Details.slantRefY;
+ pRenderState->bFontHalfTexture = Details.bFontHalfTexture;
+ pRenderState->proportional = Details.proportional;
+ pRenderState->style = Details.style;
+ pRenderState->bIsShadow = Details.bIsShadow;
+ FontRenderStatePointer.pRenderState++;
+
+ for(s = start; s < end;){
+ if (*s == '~') {
+ for (wchar *i = ParseToken(s); s != i; FontRenderStatePointer.pStr++) {
+ *FontRenderStatePointer.pStr = *(s++);
+ }
+ if (Details.bFlash) {
+ if (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) {
+ Details.bFlashState = !Details.bFlashState;
+ Details.nFlashTimer = CTimer::GetTimeInMilliseconds();
+ }
+ Details.color.a = Details.bFlashState ? 0 : 255;
+ }
+ } else
+ *(FontRenderStatePointer.pStr++) = *(s++);
+ }
+ *(FontRenderStatePointer.pStr++) = '\0';
+ FontRenderStatePointer.Align();
}
#endif
+void
+CFont::PrintStringFromBottom(float x, float y, wchar *str)
+{
+ y -= (32.0f * Details.scaleY / 2.0f + 2.0f * Details.scaleY) * GetNumberLines(x, y, str);
+ if (Details.slant == 0.0f)
+ y -= ((Details.slantRefX - x) * Details.slant + Details.slantRefY);
+ PrintString(x, y, str);
+}
+
float
CFont::GetCharacterWidth(wchar c)
{
@@ -863,7 +917,7 @@ CFont::GetCharacterWidth(wchar c)
if (Details.proportional)
return Size[Details.style][c];
else
- return Size[Details.style][192];
+ return Size[Details.style][209];
#endif // MORE_LANGUAGES
}
@@ -875,7 +929,7 @@ CFont::GetCharacterSize(wchar c)
if (IsJapanese())
{
if (!Details.proportional)
- return Size[0][Details.style][192] * Details.scaleX;
+ return Size[0][Details.style][209] * Details.scaleX;
if (c <= 94 || Details.style == FONT_HEADING || Details.style == FONT_BANK) {
switch (Details.style)
{
@@ -903,12 +957,14 @@ CFont::GetCharacterSize(wchar c)
else if(Details.proportional)
return Size[LanguageSet][Details.style][c] * Details.scaleX;
else
- return Size[LanguageSet][Details.style][192] * Details.scaleX;
+ return Size[LanguageSet][Details.style][209] * Details.scaleX;
#else
+ if (Details.bFontHalfTexture)
+ c = FindNewCharacter(c);
if (Details.proportional)
return Size[Details.style][c] * Details.scaleX;
else
- return Size[Details.style][192] * Details.scaleX;
+ return Size[Details.style][209] * Details.scaleX;
#endif // MORE_LANGUAGES
}
@@ -938,15 +994,28 @@ CFont::GetStringWidth(wchar *s, bool spaces)
} else
#endif
{
- for (; (*s != ' ' || spaces) && *s != '\0'; s++) {
- if (*s == '~') {
- s++;
- while (*s != '~') s++;
+ for (wchar c = *s; (c != ' ' || spaces) && c != '\0'; c = *(++s)) {
+ if (c == '~') {
+
+ // This is original code
+#if 0
s++;
- if (*s == ' ' && !spaces)
- break;
+ while (*s != '~') {
+ s++;
+ }
+#else
+ // TODO(Miami): This is my code to prevent fuck up until InsertPlayerControlKeysInString is done
+ if (*(s + 1) != '~') {
+ s++;
+ while (*s != '~') {
+ s++;
+ }
+ }
+#endif
+ }
+ else {
+ w += GetCharacterSize(c - ' ');
}
- w += GetCharacterSize(*s - ' ');
}
}
return w;
@@ -1000,9 +1069,6 @@ CFont::GetNextSpace(wchar *s)
if(*s == '~'){
s++;
while(*s != '~') s++;
- s++;
- if(*s == ' ')
- break;
}
}
return s;
@@ -1010,7 +1076,7 @@ CFont::GetNextSpace(wchar *s)
#ifdef MORE_LANGUAGES
wchar*
-CFont::ParseToken(wchar *s, wchar*, bool japShit)
+CFont::ParseToken(wchar *s, bool japShit)
{
s++;
if ((Details.color.r || Details.color.g || Details.color.b) && !japShit) {
@@ -1040,39 +1106,244 @@ CFont::ParseToken(wchar *s, wchar*, bool japShit)
}
#else
wchar*
-CFont::ParseToken(wchar *s, wchar*)
+CFont::ParseToken(wchar *s)
{
+ Details.anonymous_23 = false;
s++;
if(Details.color.r || Details.color.g || Details.color.b)
switch(*s){
+ case 'B':
+ Details.bBold = !Details.bBold;
case 'N':
case 'n':
NewLine = 1;
break;
- case 'b': SetColor(CRGBA(0x80, 0xA7, 0xF3, 0xFF)); break;
- case 'g': SetColor(CRGBA(0x5F, 0xA0, 0x6A, 0xFF)); break;
- case 'h': SetColor(CRGBA(0xE1, 0xE1, 0xE1, 0xFF)); break;
- case 'l': SetColor(CRGBA(0x00, 0x00, 0x00, 0xFF)); break;
- case 'p': SetColor(CRGBA(0xA8, 0x6E, 0xFC, 0xFF)); break;
- case 'r': SetColor(CRGBA(0x71, 0x2B, 0x49, 0xFF)); break;
- case 'w': SetColor(CRGBA(0xAF, 0xAF, 0xAF, 0xFF)); break;
- case 'y': SetColor(CRGBA(0xD2, 0xC4, 0x6A, 0xFF)); break;
+ case 'b': SetColor(CRGBA(27, 89, 130, 255)); Details.anonymous_23 = true; break;
+ case 'f':
+ Details.bFlash = !Details.bFlash;
+ if (Details.bFlash)
+ Details.color.a = 255;
+ break;
+ case 'g': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break;
+ case 'h': SetColor(CRGBA(225, 225, 225, 255)); Details.anonymous_23 = true; break;
+ case 'l': SetColor(CRGBA(0, 0, 0, 255)); Details.anonymous_23 = true; break;
+ case 'o': SetColor(CRGBA(229, 125, 126, 255)); Details.anonymous_23 = true; break;
+ case 'p': SetColor(CRGBA(168, 110, 252, 255)); Details.anonymous_23 = true; break;
+ case 'q': SetColor(CRGBA(199, 144, 203, 255)); Details.anonymous_23 = true; break;
+ case 'r': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break;
+ case 't': SetColor(CRGBA(86, 212, 146, 255)); Details.anonymous_23 = true; break;
+ case 'w': SetColor(CRGBA(175, 175, 175, 255)); Details.anonymous_23 = true; break;
+#ifdef FIX_BUGS
+ case 'x': SetColor(CRGBA(0, 255, 255, 255)); Details.anonymous_23 = true; break;
+#else
+ case 'x': SetColor(CRGBA(132, 146, 197, 255)); Details.anonymous_23 = true; break;
+#endif
+ case 'y': SetColor(CRGBA(255, 227, 79, 255)); Details.anonymous_23 = true; break;
}
while(*s != '~') s++;
- return s+1;
+ if (*(++s) == '~')
+ s = ParseToken(s);
+ return s;
}
#endif
+wchar*
+CFont::ParseToken(wchar* str, CRGBA &color, bool &flash, bool &bold)
+{
+ Details.anonymous_23 = false;
+ wchar *s = str + 1;
+ if (Details.color.r || Details.color.g || Details.color.b)
+ {
+ switch (*s)
+ {
+ case 'B':
+ bold = !bold;
+ break;
+ case 'b':
+ color.r = 27;
+ color.g = 89;
+ color.b = 130;
+ break;
+ case 'f':
+ flash = !flash;
+ break;
+ case 'g':
+ color.r = 255;
+ color.g = 150;
+ color.b = 225;
+ break;
+ case 'h':
+ color.r = 225;
+ color.g = 225;
+ color.b = 225;
+ break;
+ case 'l':
+ color.r = 0;
+ color.g = 0;
+ color.b = 0;
+ break;
+ case 'o':
+ color.r = 229;
+ color.g = 125;
+ color.b = 126;
+ break;
+ case 'p':
+ color.r = 168;
+ color.g = 110;
+ color.b = 252;
+ break;
+ case 'q':
+ color.r = 199;
+ color.g = 144;
+ color.b = 203;
+ break;
+ case 'r':
+ color.r = 255;
+ color.g = 150;
+ color.b = 225;
+ break;
+ case 't':
+ color.r = 86;
+ color.g = 212;
+ color.b = 146;
+ break;
+ case 'w':
+ color.r = 175;
+ color.g = 175;
+ color.b = 175;
+ break;
+#ifdef FIX_BUGS
+ case 'x':
+ color.r = 0;
+ color.g = 255;
+ color.b = 255;
+ break;
+#else
+ case 'x':
+ color.r = 132;
+ color.g = 146;
+ color.b = 197;
+ break;
+#endif
+ case 'y':
+ color.r = 255;
+ color.g = 227;
+ color.b = 79;
+ break;
+ default:
+ break;
+ }
+ }
+ while (*s != '~')
+ ++s;
+ if (*(++s) == '~')
+ s = ParseToken(s, color, flash, bold);
+ return s;
+}
+
void
CFont::DrawFonts(void)
{
- CSprite2d::DrawBank(Details.bank);
- CSprite2d::DrawBank(Details.bank+1);
- CSprite2d::DrawBank(Details.bank+2);
-#ifdef MORE_LANGUAGES
- if (IsJapanese())
- CSprite2d::DrawBank(Details.bank+3);
-#endif
+ RenderFontBuffer();
+}
+
+void
+CFont::RenderFontBuffer()
+{
+ if (FontRenderStatePointer.pRenderState == (CFontRenderState*)FontRenderStateBuf) return;
+
+ float textPosX;
+ float textPosY;
+ CRGBA color;
+ bool bBold = false;
+ bool bFlash = false;
+
+ Sprite[RenderState.style].SetRenderState();
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RenderState = *(CFontRenderState*)&FontRenderStateBuf[0];
+ textPosX = RenderState.fTextPosX;
+ textPosY = RenderState.fTextPosY;
+ tFontRenderStatePointer pRenderStateBufPointer;
+ pRenderStateBufPointer.pRenderState = (CFontRenderState*)&FontRenderStateBuf[0];
+ for (++pRenderStateBufPointer.pRenderState; pRenderStateBufPointer.pStr < FontRenderStatePointer.pStr; pRenderStateBufPointer.pStr++) {
+ if (*pRenderStateBufPointer.pStr == '\0') {
+ tFontRenderStatePointer tmpPointer = pRenderStateBufPointer;
+ tmpPointer.pStr++;
+ tmpPointer.Align();
+ if (tmpPointer.pStr >= FontRenderStatePointer.pStr)
+ break;
+
+ RenderState = *(tmpPointer.pRenderState++);
+
+ pRenderStateBufPointer = tmpPointer;
+
+ textPosX = RenderState.fTextPosX;
+ textPosY = RenderState.fTextPosY;
+ color = RenderState.color;
+ }
+ if (*pRenderStateBufPointer.pStr == '~') {
+ pRenderStateBufPointer.pStr = ParseToken(pRenderStateBufPointer.pStr, color, bFlash, bBold);
+ if (bFlash) {
+ if (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) {
+ Details.bFlashState = !Details.bFlashState;
+ Details.nFlashTimer = CTimer::GetTimeInMilliseconds();
+ }
+ Details.color.alpha = Details.bFlashState ? 0 : 255;
+ }
+ if (!RenderState.bIsShadow)
+ RenderState.color = color;
+ }
+ wchar c = *pRenderStateBufPointer.pStr;
+ c -= ' ';
+ if (RenderState.bFontHalfTexture)
+ c = FindNewCharacter(c);
+ else if (c > 155)
+ c = 0;
+
+ if (RenderState.slant != 0.0f)
+ textPosY = (RenderState.slantRefX - textPosX) * RenderState.slant + RenderState.slantRefY;
+ PrintChar(textPosX, textPosY, c);
+ if (bBold) {
+ PrintChar(textPosX + 1.0f, textPosY, c);
+ PrintChar(textPosX + 2.0f, textPosY, c);
+ textPosX += 2.0f;
+ }
+ textPosX += RenderState.scaleX * (RenderState.proportional ? Size[RenderState.style][c] : Size[RenderState.style][209]);
+ if (c == '\0')
+ textPosX += RenderState.fExtraSpace;
+ }
+ CSprite2d::RenderVertexBuffer();
+ FontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf;
+}
+
+
+void
+CFont::SetFontStyle(int16 style)
+{
+ if (style == FONT_HEADING) {
+ Details.style = FONT_STANDARD;
+ Details.bFontHalfTexture = true;
+ } else {
+ Details.style = style;
+ Details.bFontHalfTexture = false;
+ }
+}
+
+wchar CFont::FindNewCharacter(wchar c)
+{
+ if (c >= 16 && c <= 26) return c + 128;
+ if (c >= 8 && c <= 9) return c + 86;
+ if (c == 4) return c + 89;
+ if (c == 7) return 206;
+ if (c == 14) return 207;
+ if (c >= 33 && c <= 58) return c + 122;
+ if (c >= 65 && c <= 90) return c + 90;
+ if (c >= 96 && c <= 118) return c + 85;
+ if (c >= 119 && c <= 140) return c + 62;
+ if (c >= 141 && c <= 142) return 204;
+ if (c == 143) return 205;
+ if (c == 1) return 208;
+ return c;
}
wchar
diff --git a/src/render/Font.h b/src/render/Font.h
index 48f5703d..ca0ed7d0 100644
--- a/src/render/Font.h
+++ b/src/render/Font.h
@@ -14,27 +14,54 @@ struct CFontDetails
bool background;
bool backgroundOnlyText;
bool proportional;
+ bool bIsShadow;
+ bool bFlash;
+ bool bBold;
float alphaFade;
CRGBA backgroundColor;
float wrapX;
float centreSize;
float rightJustifyWrap;
int16 style;
- int32 bank;
+ bool bFontHalfTexture;
+ uint32 bank;
int16 dropShadowPosition;
CRGBA dropColor;
+ bool bFlashState;
+ int nFlashTimer;
+ bool anonymous_23;
+ uint32 anonymous_25;
+};
+
+struct CFontRenderState
+{
+ uint32 anonymous_0;
+ float fTextPosX;
+ float fTextPosY;
+ float scaleX;
+ float scaleY;
+ CRGBA color;
+ float fExtraSpace;
+ float slant;
+ float slantRefX;
+ float slantRefY;
+ bool bIsShadow;
+ bool bFontHalfTexture;
+ bool proportional;
+ bool anonymous_14;
+ int16 style;
};
class CSprite2d;
enum {
FONT_BANK,
- FONT_PAGER,
+ FONT_STANDARD,
FONT_HEADING,
#ifdef MORE_LANGUAGES
FONT_JAPANESE,
#endif
- MAX_FONTS
+ MAX_FONTS = FONT_HEADING
};
enum {
@@ -65,12 +92,13 @@ class CFont
static uint8 LanguageSet;
static int32 Slot;
#else
- static int16 Size[MAX_FONTS][193];
+ static int16 Size[MAX_FONTS][210];
#endif
static int16 NewLine;
public:
static CSprite2d Sprite[MAX_FONTS];
static CFontDetails Details;
+ static CFontRenderState RenderState;
static void Initialise(void);
static void Shutdown(void);
@@ -82,8 +110,9 @@ public:
#ifdef MORE_LANGUAGES
static bool PrintString(float x, float y, wchar *start, wchar* &end, float spwidth, float japX);
#else
- static void PrintString(float x, float y, wchar *start, wchar *end, float spwidth);
+ static void PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth);
#endif
+ static void PrintStringFromBottom(float x, float y, wchar *str);
static float GetCharacterWidth(wchar c);
static float GetCharacterSize(wchar c);
static float GetStringWidth(wchar *s, bool spaces = false);
@@ -92,11 +121,13 @@ public:
#endif
static uint16 *GetNextSpace(wchar *s);
#ifdef MORE_LANGUAGES
- static uint16 *ParseToken(wchar *s, wchar*, bool japShit = false);
+ static uint16 *ParseToken(wchar *s, bool japShit = false);
#else
- static uint16 *ParseToken(wchar *s, wchar*);
+ static uint16 *ParseToken(wchar *s);
+ static uint16* ParseToken(wchar *s, CRGBA &color, bool &flash, bool &bold);
#endif
static void DrawFonts(void);
+ static void RenderFontBuffer(void);
static uint16 character_code(uint8 c);
static CFontDetails GetDetails() { return Details; }
@@ -155,14 +186,14 @@ public:
static void SetBackGroundOnlyTextOff(void) { Details.backgroundOnlyText = false; }
static void SetPropOn(void) { Details.proportional = true; }
static void SetPropOff(void) { Details.proportional = false; }
- static void SetFontStyle(int16 style) { Details.style = style; }
+ static void SetFontStyle(int16 style);
static void SetRightJustifyWrap(float wrap) { Details.rightJustifyWrap = wrap; }
static void SetAlphaFade(float fade) { Details.alphaFade = fade; }
static void SetDropShadowPosition(int16 pos) { Details.dropShadowPosition = pos; }
static void SetBackgroundColor(CRGBA col);
static void SetColor(CRGBA col);
static void SetDropColor(CRGBA col);
-
+ static wchar FindNewCharacter(wchar c);
#ifdef MORE_LANGUAGES
static void ReloadFonts(uint8 set);
diff --git a/src/render/Glass.h b/src/render/Glass.h
index 51c5aae9..736e5205 100644
--- a/src/render/Glass.h
+++ b/src/render/Glass.h
@@ -1,6 +1,7 @@
#pragma once
class CEntity;
+class CVehicle;
class CFallingGlassPane : public CMatrix
{
@@ -49,4 +50,7 @@ public:
static void WindowRespondsToSoftCollision(CEntity *entity, float amount);
static void WasGlassHitByBullet(CEntity *entity, CVector point);
static void WindowRespondsToExplosion(CEntity *entity, CVector point);
+
+//TODO(MIAMI)
+ static void CarWindscreenShatters(CVehicle *vehicle, bool unk) {}
}; \ No newline at end of file
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index 08c0cb85..cbf3c7f2 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -20,25 +20,28 @@
#include "TxdStore.h"
#include "User.h"
#include "World.h"
+#include "CutsceneMgr.h"
// Game has colors inlined in code.
// For easier modification we collect them here:
-CRGBA MONEY_COLOR(89, 115, 150, 255);
-CRGBA AMMO_COLOR(0, 0, 0, 255);
-CRGBA HEALTH_COLOR(186, 101, 50, 255);
-CRGBA ARMOUR_COLOR(124, 140, 95, 255);
-CRGBA WANTED_COLOR(193, 164, 120, 255);
-CRGBA ZONE_COLOR(152, 154, 82, 255);
-CRGBA VEHICLE_COLOR(194, 165, 120, 255);
-CRGBA CLOCK_COLOR(194, 165, 120, 255);
-CRGBA TIMER_COLOR(186, 101, 50, 255);
-CRGBA COUNTER_COLOR(0, 106, 164, 255);
+CRGBA MONEY_COLOR(0, 207, 133, 255);
+CRGBA AMMO_COLOR(255, 150, 225, 255);
+CRGBA HEALTH_COLOR(255, 150, 225, 255);
+CRGBA ARMOUR_COLOR(185, 185, 185, 255);
+CRGBA NOTWANTED_COLOR(27, 89, 130, 255);
+CRGBA WANTED_COLOR_FLASH(62, 141, 181, 255);
+CRGBA WANTED_COLOR(97, 194, 247, 255);
+CRGBA ZONE_COLOR(45, 155, 90, 255);
+CRGBA VEHICLE_COLOR(97, 194, 247, 255);
+CRGBA CLOCK_COLOR(97, 194, 247, 255);
+CRGBA TIMER_COLOR(97, 194, 247, 255);
+CRGBA COUNTER_COLOR(97, 194, 247, 255);
CRGBA PAGER_COLOR(32, 162, 66, 205);
-CRGBA RADARDISC_COLOR(0, 0, 0, 255);
-CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255);
-CRGBA WASTEDBUSTED_COLOR(170, 123, 87, 255);
-CRGBA ODDJOB_COLOR(89, 115, 150, 255);
-CRGBA ODDJOB2_COLOR(156, 91, 40, 255);
+CRGBA RADARDISC_COLOR(255, 255, 255, 255);
+CRGBA BIGMESSAGE_COLOR(255, 150, 225, 255);
+CRGBA WASTEDBUSTED_COLOR(0, 207, 133, 255);
+CRGBA ODDJOB_COLOR(0, 207, 133, 255);
+CRGBA ODDJOB2_COLOR(97, 194, 247, 255);
CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255);
wchar CHud::m_HelpMessage[256];
@@ -67,6 +70,8 @@ bool CHud::m_Wants_To_Draw_Hud;
bool CHud::m_Wants_To_Draw_3dMarkers;
wchar CHud::m_BigMessage[6][128];
int16 CHud::m_ItemToFlash;
+bool CHud::m_HideRadar;
+int32 CHud::m_DrawClock;
// These aren't really in CHud
float CHud::BigMessageInUse[6];
@@ -86,6 +91,22 @@ float CHud::PagerXOffset;
int16 CHud::PagerTimer;
int16 CHud::PagerOn;
+uint32 CHud::m_WantedFadeTimer;
+uint32 CHud::m_WantedState;
+uint32 CHud::m_WantedTimer;
+uint32 CHud::m_EnergyLostFadeTimer;
+uint32 CHud::m_EnergyLostState;
+uint32 CHud::m_EnergyLostTimer;
+uint32 CHud::m_DisplayScoreFadeTimer;
+uint32 CHud::m_DisplayScoreState;
+uint32 CHud::m_DisplayScoreTimer;
+uint32 CHud::m_WeaponFadeTimer;
+uint32 CHud::m_WeaponState;
+uint32 CHud::m_WeaponTimer;
+
+uint32 CHud::m_LastDisplayScore;
+uint32 CHud::m_LastWanted;
+
CSprite2d CHud::Sprites[NUM_HUD_SPRITES];
struct
@@ -123,6 +144,10 @@ RwTexture *gpRocketSightTex;
void CHud::Draw()
{
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+
// disable hud via second controller
if (CPad::GetPad(1)->GetStartJustDown())
m_Wants_To_Draw_Hud = !m_Wants_To_Draw_Hud;
@@ -134,22 +159,27 @@ void CHud::Draw()
bool DrawCrossHair = false;
bool DrawCrossHairPC = false;
- int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType;
+ CPlayerPed *playerPed = FindPlayerPed();
+ eWeaponType WeaponType = playerPed->GetWeapon()->m_eWeaponType;
int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
- if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON)
+ if ((Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON || Mode == CCam::MODE_CAMERA)
+ && playerPed && !playerPed->GetWeapon()->IsTypeMelee())
DrawCrossHair = true;
+
if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
DrawCrossHairPC = true;
-
- /*
- Draw Crosshairs
- */
- if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() &&
- (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) {
- if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) {
- if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER)
- DrawCrossHairPC = true;
+ if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage)
+ || Mode == CCam::MODE_1STPERSON_RUNABOUT) {
+ if (playerPed) {
+ if (playerPed->m_nPedState != PED_ENTER_CAR && playerPed->m_nPedState != PED_CARJACK) {
+
+ if (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_RUGER
+ || WeaponType == WEAPONTYPE_M60 || WeaponType == WEAPONTYPE_MINIGUN
+ || WeaponType == WEAPONTYPE_FLAMETHROWER) {
+ DrawCrossHairPC = 1;
+ }
+ }
}
}
@@ -169,7 +199,7 @@ void CHud::Draw()
#ifdef ASPECT_RATIO_SCALE
f3rdY -= SCREEN_SCALE_Y(2.0f);
#endif
- if (FindPlayerPed() && WeaponType == WEAPONTYPE_M16) {
+ if (playerPed && (WeaponType == WEAPONTYPE_M4 || WeaponType == WEAPONTYPE_RUGER || WeaponType == WEAPONTYPE_M60)) {
rect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.6f);
rect.top = f3rdY - SCREEN_SCALE_Y(32.0f * 0.6f);
rect.right = f3rdX + SCREEN_SCALE_X(32.0f * 0.6f);
@@ -187,8 +217,7 @@ void CHud::Draw()
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255),
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
}
- }
- else {
+ } else {
if (Mode == CCam::MODE_M16_1STPERSON ||
Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
Mode == CCam::MODE_HELICANNON_1STPERSON) {
@@ -198,7 +227,6 @@ void CHud::Draw()
rect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f);
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255),
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
-
}
else if (Mode == CCam::MODE_1STPERSON_RUNABOUT) {
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f);
@@ -218,8 +246,11 @@ void CHud::Draw()
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex));
CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
}
else {
+
+ // TODO(Miami)
// Sniper
rect.left = SCREEN_WIDTH/2 - SCREEN_SCALE_X(210.0f);
rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f);
@@ -250,9 +281,9 @@ void CHud::Draw()
0.99f, 0.99f, 0.01f, 0.99f, 0.99f, 0.01f, 0.1f, 0.01f);
}
}
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
else {
SpriteBrightness = 0;
@@ -261,35 +292,49 @@ void CHud::Draw()
/*
DrawMoneyCounter
*/
+
wchar sPrint[16];
wchar sPrintIcon[16];
char sTemp[16];
+ float alpha;
- sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
- AsciiToUnicode(sTemp, sPrint);
-
- CFont::SetPropOff();
- CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
- CFont::SetCentreOff();
- CFont::SetRightJustifyOn();
- CFont::SetRightJustifyWrap(0.0f);
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_HEADING);
- CFont::SetPropOff();
- CFont::SetColor(CRGBA(0, 0, 0, 255));
+ if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) {
+ alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 0);
+ } else {
+ alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 1);
+ m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
+ }
+ if (m_DisplayScoreState != FADED_OUT) {
+ sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
+ AsciiToUnicode(sTemp, sPrint);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(43.0f + 2.0f), sPrint);
+ CFont::SetPropOff();
+ CFont::SetBackgroundOff();
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOn();
+ CFont::SetRightJustifyWrap(0.0f);
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetFontStyle(FONT_HEADING);
+ CFont::SetPropOff();
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, alpha));
+ MONEY_COLOR.a = alpha;
+ CFont::SetColor(MONEY_COLOR);
- CFont::SetColor(MONEY_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint);
+ if (FrontEndMenuManager.m_PrefsShowHud) {
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint);
+ }
+ }
/*
DrawAmmo
*/
- uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition;
- uint32 AmmoInClip = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoInClip;
- uint32 TotalAmmo = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoTotal;
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType);
+ CWeapon *weapon = playerPed->GetWeapon();
+ uint32 AmmoAmount = weaponInfo->m_nAmountofAmmunition;
+ uint32 AmmoInClip = weapon->m_nAmmoInClip;
+ uint32 TotalAmmo = weapon->m_nAmmoTotal;
uint32 Ammo, Clip;
if (AmmoAmount <= 1 || AmmoAmount >= 1000)
@@ -320,70 +365,91 @@ void CHud::Draw()
/*
DrawWeaponIcon
*/
- Sprites[WeaponType].Draw(
- CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)),
- CRGBA(255, 255, 255, 255),
- 0.015f,
- 0.015f,
- 1.0f,
- 0.0f,
- 0.015f,
- 1.0f,
- 1.0f,
- 1.0f);
+
+ if (weaponInfo->m_nModelId <= 0) {
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ Sprites[WeaponType].Draw(
+ CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)),
+ CRGBA(255, 255, 255, 255),
+ 0.015f,
+ 0.015f,
+ 1.0f,
+ 0.0f,
+ 0.015f,
+ 1.0f,
+ 1.0f,
+ 1.0f);
+ } else {
+ CBaseModelInfo *weaponModel = CModelInfo::GetModelInfo(weaponInfo->m_nModelId);
+ RwTexDictionary *weaponTxd = CTxdStore::GetSlot(weaponModel->GetTxdSlot())->texDict;
+ if (weaponTxd) {
+ RwTexture *weaponIcon = RwTexDictionaryFindNamedTexture(weaponTxd, weaponModel->GetName());
+ if (weaponIcon) {
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon));
+ const float xSize = SCREEN_SCALE_X(64.0f / 2.0f);
+ const float ySize = SCREEN_SCALE_X(64.0f / 2.0f);
+ CSprite::RenderOneXLUSprite(SCREEN_SCALE_FROM_RIGHT(99.0f) + xSize, SCREEN_SCALE_Y(25.0f) + ySize, 1.0f, xSize, ySize,
+ 255, 255, 255, 255, 1.0f, 255);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ }
+ }
+ }
CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f));
+ CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f));
CFont::SetJustifyOff();
CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_SCALE_X(640.0f));
+ CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
CFont::SetPropOn();
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetDropShadowPosition(0);
+ CFont::SetFontStyle(FONT_STANDARD);
- if (!CDarkel::FrenzyOnGoing() && WeaponType != WEAPONTYPE_UNARMED && WeaponType != WEAPONTYPE_BASEBALLBAT) {
+ if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) {
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetColor(AMMO_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(73.0f), sPrint);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint);
+ CFont::SetDropShadowPosition(0);
}
/*
DrawHealth
*/
CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetJustifyOff();
CFont::SetCentreOff();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetRightJustifyOn();
CFont::SetPropOff();
CFont::SetFontStyle(FONT_HEADING);
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8
|| m_ItemToFlash != ITEM_HEALTH
- || FindPlayerPed()->m_fHealth < 10
+ || playerPed->m_fHealth < 10
&& CTimer::GetFrameCounter() & 8) {
- if (FindPlayerPed()->m_fHealth >= 10
- || FindPlayerPed()->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) {
+ if (playerPed->m_fHealth >= 10
+ || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) {
AsciiToUnicode("{", sPrintIcon);
#ifdef FIX_BUGS
- sprintf(sTemp, "%03d", int32(FindPlayerPed()->m_fHealth + 0.5f));
+ sprintf(sTemp, "%03d", int32(playerPed->m_fHealth + 0.5f));
#else
- sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fHealth);
+ sprintf(sTemp, "%03d", (int32)playerPed->m_fHealth);
#endif
AsciiToUnicode(sTemp, sPrint);
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrint);
-
- if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) {
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(164.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon);
- }
CFont::SetColor(HEALTH_COLOR);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint);
if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) {
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(164.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon);
+ // CFont::SetColor(HEALTH_COLOR);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 54.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon);
}
}
}
@@ -392,29 +458,23 @@ void CHud::Draw()
DrawArmour
*/
if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) {
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
- if (FindPlayerPed()->m_fArmour > 1.0f) {
- AsciiToUnicode("[", sPrintIcon);
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
+ if (playerPed->m_fArmour > 1.0f) {
+ AsciiToUnicode("<", sPrintIcon);
#ifdef FIX_BUGS
- sprintf(sTemp, "%03d", int32(FindPlayerPed()->m_fArmour + 0.5f));
+ sprintf(sTemp, "%03d", int32(playerPed->m_fArmour + 0.5f));
#else
- sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fArmour);
+ sprintf(sTemp, "%03d", (int32)playerPed->m_fArmour);
#endif
AsciiToUnicode(sTemp, sPrint);
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrint);
-
- if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 4) {
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(234.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon);
- }
-
CFont::SetColor(ARMOUR_COLOR);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint);
if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 1) {
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(234.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon);
+ // CFont::SetColor(ARMOUR_COLOR);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon);
}
}
}
@@ -422,25 +482,45 @@ void CHud::Draw()
/*
DrawWantedLevel
*/
- CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
- CFont::SetJustifyOff();
- CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
- CFont::SetPropOn();
- CFont::SetFontStyle(FONT_HEADING);
+ if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel)
+ alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 0);
+ else {
+ alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 1);
+ m_LastWanted = playerPed->m_pWanted->m_nWantedLevel;
+ }
+
+ if (m_WantedState != FADED_OUT) {
+ CFont::SetBackgroundOff();
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
+ CFont::SetJustifyOff();
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOn();
+ CFont::SetPropOn();
+ CFont::SetFontStyle(FONT_STANDARD);
- AsciiToUnicode("]", sPrintIcon);
+ AsciiToUnicode(">", sPrintIcon);
- for (int i = 0; i < 6; i++) {
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString(2.0f + SCREEN_SCALE_FROM_RIGHT(60.0f - 2.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f + 2.0f), sPrintIcon);
- if (FindPlayerPed()->m_pWanted->m_nWantedLevel > i
- && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange
- + 2000 || CTimer::GetFrameCounter() & 4)) {
+ for (int i = 0; i < 6; i++) {
+ if (FrontEndMenuManager.m_PrefsShowHud) {
+ if (playerPed->m_pWanted->m_nWantedLevel > i
+ && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange
+ + 2000 || CTimer::GetFrameCounter() & 4)) {
+
+ WANTED_COLOR.a = alpha;
+ CFont::SetColor(WANTED_COLOR);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
- CFont::SetColor(WANTED_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(60.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
+ } else if (playerPed->m_pWanted->m_nMinWantedLevel > i && CTimer::GetFrameCounter() & 4) {
+ WANTED_COLOR_FLASH.a = alpha;
+ CFont::SetColor(WANTED_COLOR_FLASH);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
+
+ } else if (playerPed->m_pWanted->m_nWantedLevel <= i) {
+ NOTWANTED_COLOR.a = alpha;
+ CFont::SetColor(NOTWANTED_COLOR);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
+ }
+ }
}
}
@@ -448,7 +528,6 @@ void CHud::Draw()
DrawZoneName
*/
if (m_pZoneName) {
- float fZoneAlpha = 255.0f;
if (m_pZoneName != m_pLastZoneName) {
switch (m_ZoneState) {
@@ -457,6 +536,8 @@ void CHud::Draw()
m_ZoneToPrint = m_pZoneName;
m_ZoneNameTimer = 0;
m_ZoneFadeTimer = 0;
+ if (m_VehicleState == 1 || m_VehicleState == 2)
+ m_VehicleState = 3;
break;
case 1:
case 2:
@@ -471,19 +552,20 @@ void CHud::Draw()
m_pLastZoneName = m_pZoneName;
}
+ float fZoneAlpha = 255.0f;
if (m_ZoneState) {
switch (m_ZoneState) {
case 1:
+ fZoneAlpha = 255.0f;
m_ZoneFadeTimer = 1000;
- if (m_ZoneNameTimer > 10000) {
+ if (m_ZoneNameTimer > 10000.0f) {
m_ZoneFadeTimer = 1000;
m_ZoneState = 3;
}
- fZoneAlpha = 255.0f;
break;
case 2:
m_ZoneFadeTimer += CTimer::GetTimeStepInMilliseconds();
- if (m_ZoneFadeTimer > 1000) {
+ if (m_ZoneFadeTimer > 1000.0f) {
m_ZoneState = 1;
m_ZoneFadeTimer = 1000;
}
@@ -491,7 +573,7 @@ void CHud::Draw()
break;
case 3:
m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds();
- if (m_ZoneFadeTimer < 0) {
+ if (m_ZoneFadeTimer < 0.0f) {
m_ZoneState = 0;
m_ZoneFadeTimer = 0;
}
@@ -499,7 +581,7 @@ void CHud::Draw()
break;
case 4:
m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds();
- if (m_ZoneFadeTimer < 0) {
+ if (m_ZoneFadeTimer < 0.0f) {
m_ZoneFadeTimer = 0;
m_ZoneToPrint = m_pLastZoneName;
m_ZoneState = 2;
@@ -511,30 +593,35 @@ void CHud::Draw()
}
-#ifndef HUD_ENHANCEMENTS
- if (!m_Message[0]) {
-#else
- if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide zone name if wasted/busted text is displaying
-#endif
+ if (!m_Message[0] && BigMessageInUse[1] == 0.0f && BigMessageInUse[2] == 0.0f) {
+
m_ZoneNameTimer += CTimer::GetTimeStepInMilliseconds();
CFont::SetJustifyOff();
CFont::SetPropOn();
CFont::SetBackgroundOff();
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
- CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.8f), SCREEN_SCALE_Y(1.2f));
+ CFont::SetScale(SCREEN_SCALE_X(1.7f * 0.8f), SCREEN_SCALE_Y(1.8f));
else
- CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
+ CFont::SetScale(SCREEN_SCALE_X(1.7f), SCREEN_SCALE_Y(1.8f));
+
+ CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f));
+ CFont::SetSlant(0.15f);
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff();
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, fZoneAlpha));
CFont::SetFontStyle(FONT_BANK);
- CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint);
-
CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint);
+
+ if (!CTheScripts::bPlayerIsInTheStatium)
+ CFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint);
+
+ CFont::SetSlant(0.f);
+ } else {
+ m_ZoneState = 3;
}
}
}
@@ -552,6 +639,8 @@ void CHud::Draw()
m_pVehicleNameToPrint = m_VehicleName;
m_VehicleNameTimer = 0;
m_VehicleFadeTimer = 0;
+ if (m_ZoneState == 1 || m_ZoneState == 2)
+ m_ZoneState = 3;
break;
case 1:
case 2:
@@ -616,19 +705,24 @@ void CHud::Draw()
CFont::SetBackgroundOff();
if (FrontEndMenuManager.m_PrefsLanguage != CMenuManager::LANGUAGE_ITALIAN && FrontEndMenuManager.m_PrefsLanguage != CMenuManager::LANGUAGE_SPANISH)
- CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
+ CFont::SetScale(SCREEN_SCALE_X(1.7f), SCREEN_SCALE_Y(1.8f));
else
- CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f));
+ CFont::SetScale(SCREEN_SCALE_X(1.7f * 0.85f), SCREEN_SCALE_Y(1.8f));
+
+ CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f));
+ CFont::SetSlant(0.15f);
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK);
- CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint);
-
+ CFont::SetDropShadowPosition(2);
CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint);
+ CFont::SetDropColor(CRGBA(0, 0, 0, fVehicleAlpha));
+
+ CFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f), m_pVehicleNameToPrint);
+
+ CFont::SetSlant(0.f);
}
}
}
@@ -642,25 +736,26 @@ void CHud::Draw()
/*
DrawClock
*/
- CFont::SetJustifyOff();
- CFont::SetCentreOff();
- CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetPropOff();
- CFont::SetFontStyle(FONT_HEADING);
- CFont::SetRightJustifyOn();
- CFont::SetRightJustifyWrap(0.0f);
-
- sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes());
- AsciiToUnicode(sTemp, sPrint);
-
- CFont::SetColor(CRGBA(0, 0, 0, 255));
+ if (m_DrawClock) {
+ CFont::SetJustifyOff();
+ CFont::SetCentreOff();
+ CFont::SetBackgroundOff();
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetPropOff();
+ CFont::SetFontStyle(FONT_HEADING);
+ CFont::SetRightJustifyOn();
+ CFont::SetRightJustifyWrap(0.0f);
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), sPrint);
+ sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes());
+ AsciiToUnicode(sTemp, sPrint);
- CFont::SetColor(CLOCK_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint);
+ CFont::SetColor(CLOCK_COLOR);
+ if (FrontEndMenuManager.m_PrefsShowHud)
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint);
+ }
/*
DrawOnScreenTimer
@@ -694,7 +789,7 @@ void CHud::Draw()
AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer);
CFont::SetPropOn();
CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
@@ -702,7 +797,7 @@ void CHud::Draw()
CFont::SetBackGroundOnlyTextOn();
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer);
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetColor(TIMER_COLOR);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer);
@@ -734,7 +829,7 @@ void CHud::Draw()
CFont::SetPropOn();
CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetCentreOff();
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
@@ -760,7 +855,7 @@ void CHud::Draw()
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) {
CFont::SetPropOn();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
+ CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText));
@@ -817,23 +912,32 @@ void CHud::Draw()
CFont::SetCentreOff();
CFont::SetJustifyOff();
CFont::SetPropOff();
- CFont::SetFontStyle(FONT_PAGER);
+ CFont::SetFontStyle(FONT_STANDARD);
CFont::PrintString(SCREEN_SCALE_X(52.0f - PagerXOffset), SCREEN_SCALE_Y(54.0f), m_PagerMessage);
}
/*
DrawRadar
*/
- if (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR) {
+ if (FrontEndMenuManager.m_PrefsRadarMode != 2 &&
+ !m_HideRadar && (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR)) {
+
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
CRadar::DrawMap();
- CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT));
+ if (FrontEndMenuManager.m_PrefsRadarMode != 1) {
+ CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT));
#ifdef FIX_BUGS
- rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));
+ rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));
#else
- rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));
+ rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));
#endif
- rect.Grow(4.0f);
- Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR);
+
+ rect.Grow(6.0f);
+ rect.Translate(0.0f, 2.0f);
+ Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255));
+ rect.Translate(0.0f, -2.0f);
+ Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR);
+ }
CRadar::DrawBlips();
}
}
@@ -922,30 +1026,164 @@ void CHud::Draw()
/*
DrawSubtitles
*/
- if (m_Message[0] && !m_BigMessage[2][0] && (FrontEndMenuManager.m_PrefsShowSubtitles == 1 || !TheCamera.m_WideScreenOn)) {
+ if (m_Message[0] && !m_BigMessage[2][0]) {
+ if (m_VehicleState != 0)
+ m_VehicleState = 3;
+ if (m_ZoneState != 0)
+ m_ZoneState = 3;
+
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
- CFont::SetScale(SCREEN_SCALE_X(0.48f), SCREEN_SCALE_Y(1.120f));
CFont::SetCentreOn();
CFont::SetPropOn();
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
+ CFont::SetDropShadowPosition(0);
+ CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
+ CFont::SetColor(CRGBA(225, 225, 225, 255));
+
+ static bool onceItWasWidescreen = false;
+
+ if (TheCamera.m_WideScreenOn) {
+ onceItWasWidescreen = true;
+
+ if (FrontEndMenuManager.m_PrefsShowSubtitles || !CCutsceneMgr::IsRunning()) {
+ CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(60.0f));
+ CFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.2f));
+ CFont::PrintString(SCREEN_WIDTH / 2.f, SCREEN_SCALE_FROM_BOTTOM(80.0f), m_Message);
+ }
+ } else {
+ if (onceItWasWidescreen)
+ m_Message[0] = '\0';
- float offsetX = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f);
- float center = SCREEN_SCALE_FROM_RIGHT(50.0f) - SCREEN_SCALE_X(8.0f) - offsetX;
- CFont::SetCentreSize(center);
+ onceItWasWidescreen = false;
+ CFont::DrawFonts();
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
+ CFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.22f));
- const int16 shadow = 1;
- CFont::SetDropShadowPosition(shadow);
- CFont::SetDropColor(CRGBA(0, 0, 0, 255));
- CFont::SetColor(CRGBA(235, 235, 235, 255));
+ float offsetX = SCREEN_SCALE_X(140.0f) + SCREEN_SCALE_X(8.0f);
+ float center = SCREEN_SCALE_FROM_RIGHT(20.0f) - SCREEN_SCALE_X(8.0f) - offsetX;
+ CFont::SetCentreSize(center);
- // I'm not sure shadow substaction was intentional here, might be a leftover if CFont::PrintString was used for a shadow draw call
- CFont::PrintString(center / 2.0f + offsetX - SCREEN_SCALE_X(shadow), SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(68.0f) - SCREEN_SCALE_Y(shadow), m_Message);
+ CFont::PrintString(center / 2.0f + offsetX, SCREEN_SCALE_FROM_BOTTOM(105.f + 2.0f), m_Message);
+ }
CFont::SetDropShadowPosition(0);
}
/*
+ HelpMessage
+ */
+
+ if (m_HelpMessage[0]) {
+ if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) {
+ switch (m_HelpMessageState) {
+ case 0:
+ m_HelpMessageFadeTimer = 0;
+ m_HelpMessageState = 2;
+ m_HelpMessageTimer = 0;
+ CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256);
+ m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f;
+
+ if (TheCamera.m_ScreenReductionPercentage == 0.0f)
+ DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0);
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ m_HelpMessageTimer = 5;
+ m_HelpMessageState = 4;
+ break;
+ default:
+ break;
+ }
+ CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256);
+ }
+
+ float fAlpha = 225.0f;
+
+ if (m_HelpMessageState != 0) {
+ switch (m_HelpMessageState) {
+ case 1:
+ fAlpha = 225.0f;
+ m_HelpMessageFadeTimer = 600;
+ if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) {
+ m_HelpMessageFadeTimer = 600;
+ m_HelpMessageState = 3;
+ }
+ break;
+ case 2:
+ if (TheCamera.m_WideScreenOn)
+ break;
+
+ m_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds();
+ if (m_HelpMessageFadeTimer > 0) {
+ m_HelpMessageState = 1;
+ m_HelpMessageFadeTimer = 0;
+ }
+ fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
+ break;
+ case 3:
+ m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds();
+ if (m_HelpMessageFadeTimer < 0 || TheCamera.m_WideScreenOn) {
+ m_HelpMessageState = 0;
+ m_HelpMessageFadeTimer = 0;
+ }
+ fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
+ break;
+ case 4:
+ m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds();
+ if (m_HelpMessageFadeTimer < 0) {
+ m_HelpMessageState = 2;
+ m_HelpMessageFadeTimer = 0;
+ CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256);
+ }
+ fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
+ break;
+ default:
+ break;
+ }
+
+ if (!TheCamera.m_WideScreenOn) {
+ m_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds();
+
+ CFont::SetAlphaFade(fAlpha);
+ CFont::SetCentreOff();
+ CFont::SetPropOn();
+
+ if (CGame::germanGame)
+ CFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f));
+#ifdef MORE_LANGUAGES
+ else if (CFont::IsJapanese())
+ CFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f);
+#endif
+ else
+ CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f));
+
+ CFont::DrawFonts();
+ // CFont::SetColor(CRGBA(175, 175, 175, 255));
+ CFont::SetJustifyOff();
+#ifdef MORE_LANGUAGES
+ if (CFont::IsJapanese())
+ CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 34.0f - 4.0f));
+ else
+#endif
+ CFont::SetWrapx(SCREEN_SCALE_X(200.0f + 34.0f - 4.0f));
+ CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
+ CFont::SetBackgroundOn();
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetDropShadowPosition(0);
+ CFont::SetColor(CRGBA(175, 175, 175, 255));
+ CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f));
+ CFont::PrintString(SCREEN_SCALE_X(34.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), CHud::m_HelpMessageToPrint);
+ CFont::SetAlphaFade(255.0f);
+ CFont::SetWrapx(SCREEN_WIDTH);
+ }
+ }
+ } else
+ m_HelpMessageState = 0;
+
+ /*
DrawBigMessage
*/
// MissionCompleteFailedText
@@ -954,10 +1192,15 @@ void CHud::Draw()
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
CFont::SetBackGroundOnlyTextOff();
- CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f));
+ if (CGame::frenchGame || CGame::germanGame) {
+ CFont::SetScale(SCREEN_SCALE_X(1.6f), SCREEN_SCALE_Y(1.8f));
+ } else {
+ CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f));
+ }
CFont::SetPropOn();
CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_SCALE_X(615.0f));
+ CFont::SetCentreSize(SCREEN_SCALE_X(590.0f));
+ CFont::SetColor(CRGBA(255, 255, 0, BigMessageAlpha[0])); // unused color
CFont::SetFontStyle(FONT_HEADING);
if (BigMessageX[0] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) {
@@ -980,14 +1223,9 @@ void CHud::Draw()
if (BigMessageAlpha[0] > 255.0f)
BigMessageAlpha[0] = 255.0f;
}
-
- CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[0]));
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]);
-#else
- CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]);
-#endif
-
+ CFont::DrawFonts();
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[0]));
CFont::SetColor(CRGBA(BIGMESSAGE_COLOR.r, BIGMESSAGE_COLOR.g, BIGMESSAGE_COLOR.b, BigMessageAlpha[0]));
CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]);
}
@@ -1027,8 +1265,12 @@ void CHud::Draw()
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]);
}
else {
- BigMessageAlpha[2] = 0.0f;
BigMessageInUse[2] = 1.0f;
+ BigMessageAlpha[2] = 0.0f;
+ if (CHud::m_VehicleState != 0)
+ CHud::m_VehicleState = 0;
+ if (CHud::m_ZoneState != 0)
+ CHud::m_ZoneState = 0;
}
}
else {
@@ -1039,108 +1281,13 @@ void CHud::Draw()
void CHud::DrawAfterFade()
{
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+
if (CTimer::GetIsUserPaused() || CReplay::IsPlayingBack())
return;
- if (m_HelpMessage[0]) {
- if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) {
- switch (m_HelpMessageState) {
- case 0:
- m_HelpMessageFadeTimer = 0;
- m_HelpMessageState = 2;
- m_HelpMessageTimer = 0;
- CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256);
- m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f;
-
- if (TheCamera.m_ScreenReductionPercentage == 0.0f)
- DMAudio.PlayFrontEndSound(SOUND_HUD, 0);
- break;
- case 1:
- case 2:
- case 3:
- case 4:
- m_HelpMessageTimer = 5;
- m_HelpMessageState = 4;
- break;
- default:
- break;
- }
- CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256);
- }
-
- float fAlpha = 225.0f;
-
- if (m_HelpMessageState != 0) {
- switch (m_HelpMessageState) {
- case 1:
- fAlpha = 225.0f;
- m_HelpMessageFadeTimer = 600;
- if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) {
- m_HelpMessageFadeTimer = 600;
- m_HelpMessageState = 3;
- }
- break;
- case 2:
- m_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds();
- if (m_HelpMessageFadeTimer > 0) {
- m_HelpMessageState = 1;
- m_HelpMessageFadeTimer = 0;
- }
- fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
- break;
- case 3:
- m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds();
- if (m_HelpMessageFadeTimer < 0) {
- m_HelpMessageState = 0;
- m_HelpMessageFadeTimer = 0;
- }
- fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
- break;
- case 4:
- m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds();
- if (m_HelpMessageFadeTimer < 0) {
- m_HelpMessageState = 2;
- m_HelpMessageFadeTimer = 0;
- CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256);
- }
- fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
- break;
- default:
- break;
- }
-
- m_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds();
-
- CFont::SetAlphaFade(fAlpha);
- CFont::SetCentreOff();
- CFont::SetPropOn();
-
- if (CGame::germanGame)
- CFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f));
-#ifdef MORE_LANGUAGES
- else if (CFont::IsJapanese())
- CFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f);
-#endif
- else
- CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f));
-
- CFont::SetColor(CRGBA(175, 175, 175, 255));
- CFont::SetJustifyOff();
-#ifdef MORE_LANGUAGES
- if (CFont::IsJapanese())
- CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 26.0f - 4.0f));
- else
-#endif
- CFont::SetWrapx(SCREEN_SCALE_X(200.0f + 26.0f - 4.0f));
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
- CFont::SetBackgroundOn();
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f));
- CFont::PrintString(SCREEN_SCALE_X(26.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), CHud::m_HelpMessageToPrint);
- CFont::SetAlphaFade(255.0f);
- }
- }
-
for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) {
intro_text_line &line = CTheScripts::IntroTextLines[i];
if (line.m_Text[0] != '\0' && !line.m_bTextBeforeFade) {
@@ -1210,13 +1357,11 @@ void CHud::DrawAfterFade()
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetCentreSize(SCREEN_SCALE_X(600.0f));
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
-
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[3]);
-
+ CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetColor(ODDJOB_COLOR);
- CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[3]);
+ CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f) - SCREEN_SCALE_Y(16.0f), m_BigMessage[3]);
}
if (!m_BigMessage[1][0] && m_BigMessage[4][0]) {
@@ -1226,13 +1371,11 @@ void CHud::DrawAfterFade()
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetCentreSize(SCREEN_SCALE_X(620.0f));
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
-
- CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[4]);
-
+ CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetColor(ODDJOB_COLOR);
- CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[4]);
+ CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f), m_BigMessage[4]);
}
// Oddjob result
@@ -1284,7 +1427,7 @@ void CHud::DrawAfterFade()
CFont::SetPropOn();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f));
CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
+ CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
#ifdef BETA_SLIDING_TEXT
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f) - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]);
@@ -1314,9 +1457,9 @@ void CHud::DrawAfterFade()
CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f));
CFont::SetPropOn();
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(-500.0f));
+ CFont::SetRightJustifyWrap(0.0f);
CFont::SetRightJustifyOn();
- CFont::SetFontStyle(FONT_HEADING);
+ CFont::SetFontStyle(FONT_BANK);
if (BigMessageX[1] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) {
BigMessageInUse[1] += CTimer::GetTimeStep();
@@ -1336,8 +1479,10 @@ void CHud::DrawAfterFade()
BigMessageAlpha[1] = 255.0f;
}
- CFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1]));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[1]);
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(40, 40, 40, BigMessageAlpha[1]));
+ //CFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1]));
+ //CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[1]);
CFont::SetColor(CRGBA(MISSIONTITLE_COLOR.r, MISSIONTITLE_COLOR.g, MISSIONTITLE_COLOR.b, BigMessageAlpha[1]));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), m_BigMessage[1]);
@@ -1346,6 +1491,7 @@ void CHud::DrawAfterFade()
BigMessageAlpha[1] = 0.0f;
BigMessageX[1] = -60.0f;
BigMessageInUse[1] = 1.0f;
+ m_ZoneState = 0;
}
}
else {
@@ -1389,6 +1535,30 @@ void CHud::GetRidOfAllHudMessages()
}
}
+#ifdef RELOADABLES
+void CHud::ReloadTXD()
+{
+ for (int i = 0; i < NUM_HUD_SPRITES; ++i) {
+ Sprites[i].Delete();
+ }
+
+ int HudTXD = CTxdStore::FindTxdSlot("hud");
+ CTxdStore::RemoveTxdSlot(HudTXD);
+
+ debug("Reloading HUD.TXD...\n");
+
+ HudTXD = CTxdStore::AddTxdSlot("hud");
+ CTxdStore::LoadTxd(HudTXD, "MODELS/HUD.TXD");
+ CTxdStore::AddRef(HudTXD);
+ CTxdStore::PopCurrentTxd();
+ CTxdStore::SetCurrentTxd(HudTXD);
+
+ for (int i = 0; i < NUM_HUD_SPRITES; i++) {
+ Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask);
+ }
+}
+#endif
+
void CHud::Initialise()
{
m_Wants_To_Draw_Hud = true;
@@ -1411,6 +1581,7 @@ void CHud::Initialise()
if (gpRocketSightTex == nil)
gpRocketSightTex = RwTextureRead("siterocket", nil);
+ m_DrawClock = 1;
CounterOnLastFrame = false;
m_ItemToFlash = ITEM_NONE;
OddJob2Timer = 0;
@@ -1426,6 +1597,30 @@ void CHud::Initialise()
PagerSoundPlayed = 0;
PagerXOffset = 150.0f;
+#ifdef HUD_AUTO_FADE
+ m_EnergyLostState = START_FADE_OUT;
+ m_WantedState = START_FADE_OUT;
+ m_DisplayScoreState = START_FADE_OUT;
+ m_WeaponState = START_FADE_OUT;
+#else
+ m_EnergyLostState = FADE_DISABLED;
+ m_WantedState = FADE_DISABLED;
+ m_DisplayScoreState = FADE_DISABLED;
+ m_WeaponState = FADE_DISABLED;
+#endif
+ m_WantedFadeTimer = 0;
+ m_WantedTimer = 0;
+ m_EnergyLostFadeTimer = 0;
+ m_EnergyLostTimer = 0;
+ m_DisplayScoreFadeTimer = 0;
+ m_DisplayScoreTimer = 0;
+ m_WeaponFadeTimer = 0;
+ m_WeaponTimer = 0;
+
+ m_HideRadar = false;
+ m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
+ m_LastWanted = 0;
+
CTxdStore::PopCurrentTxd();
}
@@ -1437,6 +1632,7 @@ void CHud::ReInitialise() {
CounterOnLastFrame = false;
m_ItemToFlash = ITEM_NONE;
+ m_DrawClock = 1;
OddJob2Timer = 0;
OddJob2OffTimer = 0.0f;
OddJob2On = 0;
@@ -1449,6 +1645,30 @@ void CHud::ReInitialise() {
PagerTimer = 0;
PagerSoundPlayed = 0;
PagerXOffset = 150.0f;
+
+#ifdef HUD_AUTO_FADE
+ m_EnergyLostState = START_FADE_OUT;
+ m_WantedState = START_FADE_OUT;
+ m_DisplayScoreState = START_FADE_OUT;
+ m_WeaponState = START_FADE_OUT;
+#else
+ m_EnergyLostState = FADE_DISABLED;
+ m_WantedState = FADE_DISABLED;
+ m_DisplayScoreState = FADE_DISABLED;
+ m_WeaponState = FADE_DISABLED;
+#endif
+ m_WantedFadeTimer = 0;
+ m_WantedTimer = 0;
+ m_EnergyLostFadeTimer = 0;
+ m_EnergyLostTimer = 0;
+ m_DisplayScoreFadeTimer = 0;
+ m_DisplayScoreTimer = 0;
+ m_WeaponFadeTimer = 0;
+ m_WeaponTimer = 0;
+
+ m_HideRadar = false;
+ m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
+ m_LastWanted = 0;
}
wchar LastBigMessage[6][128];
@@ -1496,6 +1716,12 @@ void CHud::SetHelpMessage(wchar *message, bool quick)
}
}
+bool CHud::IsHelpMessageBeingDisplayed(void)
+{
+ return m_HelpMessageState != 0;
+}
+
+
void CHud::SetMessage(wchar *message)
{
int i = 0;
@@ -1545,3 +1771,106 @@ void CHud::Shutdown()
int HudTXD = CTxdStore::FindTxdSlot("hud");
CTxdStore::RemoveTxdSlot(HudTXD);
}
+
+float CHud::DrawFadeState(DRAW_FADE_STATE fadingElement, int forceFadingIn)
+{
+ float alpha = 255.0f;
+ uint32 operation, timer;
+ int32 fadeTimer;
+
+ switch (fadingElement) {
+ case HUD_WANTED_FADING:
+ fadeTimer = m_WantedFadeTimer;
+ operation = m_WantedState;
+ timer = m_WantedTimer;
+ break;
+ case HUD_ENERGY_FADING:
+ fadeTimer = m_EnergyLostFadeTimer;
+ operation = m_EnergyLostState;
+ timer = m_EnergyLostTimer;
+ break;
+ case HUD_SCORE_FADING:
+ fadeTimer = m_DisplayScoreFadeTimer;
+ operation = m_DisplayScoreState;
+ timer = m_DisplayScoreTimer;
+ break;
+ case HUD_WEAPON_FADING:
+ fadeTimer = m_WeaponFadeTimer;
+ operation = m_WeaponState;
+ timer = m_WeaponTimer;
+ break;
+ default:
+ break;
+ }
+ if (forceFadingIn) {
+ switch (operation) {
+ case FADED_OUT:
+ fadeTimer = 0;
+ case START_FADE_OUT:
+ case FADING_OUT:
+ timer = 5;
+ operation = FADING_IN;
+ break;
+ default:
+ break;
+ }
+ }
+ if (operation != FADED_OUT && operation != FADE_DISABLED) {
+ switch (operation) {
+ case START_FADE_OUT:
+ fadeTimer = 1000;
+ alpha = 255.0f;
+ if (timer > 10000) {
+ fadeTimer = 3000;
+ operation = FADING_OUT;
+ }
+ break;
+ case FADING_IN:
+ fadeTimer += CTimer::GetTimeStepInMilliseconds();
+ if (fadeTimer > 1000.0f) {
+ operation = START_FADE_OUT;
+ fadeTimer = 1000;
+ }
+ alpha = fadeTimer / 1000.0f * 255.0f;
+ break;
+ case FADING_OUT:
+ fadeTimer -= CTimer::GetTimeStepInMilliseconds();
+ if (fadeTimer < 0.0f) {
+ fadeTimer = 0;
+ operation = FADED_OUT;
+ }
+ alpha = fadeTimer / 1000.0f * 255.0f;
+ break;
+ default:
+ break;
+ }
+ timer += CTimer::GetTimeStepInMilliseconds();
+ }
+
+ switch (fadingElement) {
+ case HUD_WANTED_FADING:
+ m_WantedFadeTimer = fadeTimer;
+ m_WantedState = operation;
+ m_WantedTimer = timer;
+ break;
+ case HUD_ENERGY_FADING:
+ m_EnergyLostFadeTimer = fadeTimer;
+ m_EnergyLostState = operation;
+ m_EnergyLostTimer = timer;
+ break;
+ case HUD_SCORE_FADING:
+ m_DisplayScoreFadeTimer = fadeTimer;
+ m_DisplayScoreState = operation;
+ m_DisplayScoreTimer = timer;
+ break;
+ case HUD_WEAPON_FADING:
+ m_WeaponFadeTimer = fadeTimer;
+ m_WeaponState = operation;
+ m_WeaponTimer = timer;
+ break;
+ default:
+ break;
+ }
+
+ return clamp(alpha, 0.0f, 255.0f);
+}
diff --git a/src/render/Hud.h b/src/render/Hud.h
index 701e47e2..4dd52aa8 100644
--- a/src/render/Hud.h
+++ b/src/render/Hud.h
@@ -9,6 +9,25 @@ enum eItems
ITEM_RADAR = 8
};
+// Thanks for vague name, R*
+enum DRAW_FADE_STATE
+{
+ HUD_WANTED_FADING = 0,
+ HUD_ENERGY_FADING,
+ HUD_SCORE_FADING,
+ HUD_WEAPON_FADING,
+};
+
+// My name
+enum eFadeOperation
+{
+ FADED_OUT = 0,
+ START_FADE_OUT,
+ FADING_IN,
+ FADING_OUT,
+ FADE_DISABLED = 5,
+};
+
enum eSprites
{
HUD_FIST,
@@ -32,6 +51,9 @@ enum eSprites
NUM_HUD_SPRITES,
};
+#define HUD_TEXT_SCALE_X 0.7f
+#define HUD_TEXT_SCALE_Y 1.25f
+
class CHud
{
public:
@@ -63,6 +85,8 @@ public:
static bool m_Wants_To_Draw_3dMarkers;
static wchar m_BigMessage[6][128];
static int16 m_ItemToFlash;
+ static bool m_HideRadar;
+ static int32 m_DrawClock;
// These aren't really in CHud
static float BigMessageInUse[6];
@@ -82,17 +106,38 @@ public:
static int16 PagerTimer;
static int16 PagerOn;
+ static uint32 m_WantedFadeTimer;
+ static uint32 m_WantedState;
+ static uint32 m_WantedTimer;
+ static uint32 m_EnergyLostFadeTimer;
+ static uint32 m_EnergyLostState;
+ static uint32 m_EnergyLostTimer;
+ static uint32 m_DisplayScoreFadeTimer;
+ static uint32 m_DisplayScoreState;
+ static uint32 m_DisplayScoreTimer;
+ static uint32 m_WeaponFadeTimer;
+ static uint32 m_WeaponState;
+ static uint32 m_WeaponTimer;
+
+ static uint32 m_LastDisplayScore;
+ static uint32 m_LastWanted;
+
public:
static void Draw();
static void DrawAfterFade();
static void GetRidOfAllHudMessages();
+#ifdef RELOADABLES
+ static void ReloadTXD();
+#endif
static void Initialise();
static void ReInitialise();
static void SetBigMessage(wchar *message, int16 style);
static void SetHelpMessage(wchar *message, bool quick);
+ static bool IsHelpMessageBeingDisplayed(void);
static void SetMessage(wchar *message);
static void SetPagerMessage(wchar *message);
static void SetVehicleName(wchar *name);
static void SetZoneName(wchar *name);
static void Shutdown();
+ static float DrawFadeState(DRAW_FADE_STATE, int);
};
diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp
index de15358e..08298a1f 100644
--- a/src/render/MBlur.cpp
+++ b/src/render/MBlur.cpp
@@ -10,6 +10,7 @@
#include "RwHelper.h"
#include "Camera.h"
#include "MBlur.h"
+#include "Timer.h"
#include "postfx.h"
// Originally taken from RW example 'mblur'
@@ -18,8 +19,10 @@ RwRaster *CMBlur::pFrontBuffer;
bool CMBlur::ms_bJustInitialised;
bool CMBlur::ms_bScaledBlur;
bool CMBlur::BlurOn;
+float CMBlur::Drunkness;
static RwIm2DVertex Vertex[4];
+static RwIm2DVertex Vertex2[4];
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
#ifndef LIBRW
@@ -201,6 +204,43 @@ CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect)
RwIm2DVertexSetU(&Vertex[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255);
+
+
+ RwIm2DVertexSetScreenX(&Vertex2[0], zero + 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[0], zero + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[0], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[0], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[1], 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[1], ymax + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[1], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[1], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[2], xmax + 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[2], ymax + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[2], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[2], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[2], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[3], xmax + 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[3], zero + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[3], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[3], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[3], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], 255, 255, 255, 255);
}
void
@@ -214,23 +254,24 @@ CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, u
if( pFrontBuffer )
OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
#else
+ if(ms_bJustInitialised)
+ ms_bJustInitialised = false;
+ else
+ OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
if(BlurOn){
- if(pFrontBuffer){
- if(ms_bJustInitialised)
- ms_bJustInitialised = false;
- else
- OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
- }
RwRasterPushContext(pFrontBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext();
- }else{
- OverlayRender(cam, nil, color, type, bluralpha);
}
#endif
#endif
}
+static uint8 DrunkBlurRed = 128;
+static uint8 DrunkBlurGreen = 128;
+static uint8 DrunkBlurBlue = 128;
+static int32 DrunkBlurIncrement = 1;
+
void
CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha)
{
@@ -278,41 +319,104 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type,
}
if(!BlurOn){
- r = Min(r*0.6f, 255.0f);
- g = Min(g*0.6f, 255.0f);
- b = Min(b*0.6f, 255.0f);
- if(type != MOTION_BLUR_SNIPER)
- a = Min(a*0.6f, 255.0f);
- // game clamps to 255 here, but why?
+ // gta clamps these to 255 (probably a macro or inlined function)
+ int ovR = r * 0.6f;
+ int ovG = g * 0.6f;
+ int ovB = b * 0.6f;
+ int ovA = type == MOTION_BLUR_SNIPER ? a : a*0.6f;
+ RwIm2DVertexSetIntRGBA(&Vertex[0], ovR, ovG, ovB, ovA);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], ovR, ovG, ovB, ovA);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], ovR, ovG, ovB, ovA);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], ovR, ovG, ovB, ovA);
+ }else{
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);
}
- RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);
- RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);
- RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);
- RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, BlurOn ? raster : nil);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
+ if(BlurOn){
+ if(type == MOTION_BLUR_SNIPER){
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, 80);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ // TODO(MIAMI): pBufVertCount = 0;
+ }else{
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r*2, g*2, b*2, 30);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6);
- a = bluralpha/2;
- if(a < 30)
- a = 30;
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6);
+ }
+ }
- if(BlurOn && a != 0){ // the second condition should always be true
- RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, a);
- RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, a);
- RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, a);
- RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, a);
+ int DrunkBlurAlpha = 175.0f * Drunkness;
+ if(DrunkBlurAlpha != 0){
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ if(BlurOn){
+ RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, DrunkBlurAlpha);
+ }else{
+ RwIm2DVertexSetIntRGBA(&Vertex[0], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ if(DrunkBlurIncrement){
+ if(DrunkBlurRed < 255) DrunkBlurRed++;
+ if(DrunkBlurGreen < 255) DrunkBlurGreen++;
+ if(DrunkBlurBlue < 255) DrunkBlurBlue++;
+ if(DrunkBlurRed == 255)
+ DrunkBlurIncrement = 0;
+ }else{
+ if(DrunkBlurRed > 128) DrunkBlurRed--;
+ if(DrunkBlurGreen > 128) DrunkBlurGreen--;
+ if(DrunkBlurBlue > 128) DrunkBlurBlue--;
+ if(DrunkBlurRed == 128)
+ DrunkBlurIncrement = 1;
+ }
+ }
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
}
+ // TODO(MIAMI): OverlayRenderFx
+
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
@@ -321,3 +425,16 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type,
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}
+
+void
+CMBlur::SetDrunkBlur(float drunkness)
+{
+ Drunkness = clamp(drunkness, 0.0f, 1.0f);
+}
+
+void
+CMBlur::ClearDrunkBlur()
+{
+ Drunkness = 0.0f;
+ CTimer::SetTimeScale(1.0f);
+} \ No newline at end of file
diff --git a/src/render/MBlur.h b/src/render/MBlur.h
index e2e5d38c..c2572256 100644
--- a/src/render/MBlur.h
+++ b/src/render/MBlur.h
@@ -1,5 +1,15 @@
#pragma once
+enum FxType
+{
+ FXTYPE_0 = 0,
+ FXTYPE_1,
+ FXTYPE_2,
+ FXTYPE_3,
+ FXTYPE_4,
+ FXTYPE_5,
+};
+
class CMBlur
{
public:
@@ -7,6 +17,7 @@ public:
static bool ms_bJustInitialised;
static bool ms_bScaledBlur;
static bool BlurOn;
+ static float Drunkness;
public:
static RwBool MotionBlurOpen(RwCamera *cam);
@@ -14,4 +25,10 @@ public:
static void CreateImmediateModeData(RwCamera *cam, RwRect *rect);
static void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha);
static void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha);
+ static void SetDrunkBlur(float drunkness);
+ static void ClearDrunkBlur();
+
+ //TODO
+ static void AddRenderFx(RwCamera *,RwRect *,float,FxType)
+ {}
};
diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp
new file mode 100644
index 00000000..c2f220e9
--- /dev/null
+++ b/src/render/Occlusion.cpp
@@ -0,0 +1,478 @@
+#include "common.h"
+
+#include "main.h"
+#include "Occlusion.h"
+#include "Game.h"
+#include "Camera.h"
+#include "Vector.h"
+#include "Draw.h"
+#include "Timer.h"
+#include "RwHelper.h"
+
+int32 COcclusion::NumOccludersOnMap;
+int16 COcclusion::FarAwayList;
+int16 COcclusion::NearbyList;
+int16 COcclusion::ListWalkThroughFA;
+int16 COcclusion::PreviousListWalkThroughFA;
+int16 COcclusion::NumActiveOccluders;
+COccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES];
+CActiveOccluder COcclusion::aActiveOccluders[NUMACTIVEOCCLUDERS];
+
+CVector gCenterOnScreen;
+
+float gMinYInOccluder;
+float gMinXInOccluder;
+float gMaxYInOccluder;
+float gMaxXInOccluder;
+
+bool gOccluderCoorsValid[8];
+CVector gOccluderCoorsOnScreen[8];
+CVector gOccluderCoors[8];
+
+bool bDisplayOccDebugStuff;
+
+void
+COcclusion::Init(void)
+{
+ NumOccludersOnMap = 0;
+ FarAwayList = -1;
+ NearbyList = -1;
+ ListWalkThroughFA = -1;
+ PreviousListWalkThroughFA = -1;
+ bDisplayOccDebugStuff = false;
+}
+
+void
+COcclusion::AddOne(float x, float y, float z, float width, float length, float height, float angle)
+{
+ if(NumOccludersOnMap >= NUMOCCLUSIONVOLUMES)
+ return;
+
+ aOccluders[NumOccludersOnMap].x = x;
+ aOccluders[NumOccludersOnMap].y = y;
+ aOccluders[NumOccludersOnMap].z = z;
+ aOccluders[NumOccludersOnMap].width = width;
+ aOccluders[NumOccludersOnMap].length = length;
+ aOccluders[NumOccludersOnMap].height = height;
+ while(angle < 0.0f) angle += 360.0f;
+ while(angle > 360.0f) angle -= 360.0f;
+ aOccluders[NumOccludersOnMap].angle = angle/360.0f * UINT16_MAX;
+ aOccluders[NumOccludersOnMap].listIndex = FarAwayList;
+ FarAwayList = NumOccludersOnMap++;
+}
+
+bool
+COccluder::NearCamera() {
+ return (TheCamera.GetPosition() - CVector(x, y, z)).Magnitude() - (Max(width, length) / 2.0f) < 250.0f;
+}
+
+bool
+DoesInfiniteLineCrossFiniteLine(float p1X, float p1Y, float p2X, float p2Y, float lineX, float lineY, float lineDX, float lineDY)
+{
+ float side1 = (p1X - lineX) * lineDY - (p1Y - lineY) * lineDX;
+ float side2 = (p2X - lineX) * lineDY - (p2Y - lineY) * lineDX;
+ return side1 * side2 < 0.0f; // if points lie on opposite sides of the infinte line, the line between them crosses it
+}
+
+bool DoesInfiniteLineTouchScreen(float lineX, float lineY, float lineDX, float lineDY) {
+ if (lineX > 0.0f && lineY > 0.0f && SCREEN_WIDTH > lineX && SCREEN_HEIGHT > lineY)
+ return true;
+
+ return (DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, lineX, lineY, lineDX, lineDY) ||
+ DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, 0.0f, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) ||
+ DoesInfiniteLineCrossFiniteLine(SCREEN_WIDTH, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) ||
+ DoesInfiniteLineCrossFiniteLine(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY));
+}
+
+bool IsPointInsideLine(float lineX, float lineY, float lineDX, float lineDY, float pX, float pY, float area = 0.0f) {
+ return (pX - lineX) * lineDY - (pY - lineY) * lineDX >= area;
+}
+
+bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh) {
+ *out = TheCamera.m_viewMatrix * in;
+
+ if (out->z <= 1.0f) return false;
+
+ float recip = 1.0f / out->z;
+ out->x *= SCREEN_WIDTH * recip;
+ out->y *= SCREEN_HEIGHT * recip;
+
+ float fovScale = DefaultFOV / CDraw::GetFOV();
+
+ *outw = fovScale * recip * SCREEN_WIDTH;
+ *outh = fovScale * recip * SCREEN_HEIGHT;
+
+ return true;
+}
+
+bool CalcScreenCoors(CVector const &in, CVector *out) {
+ *out = TheCamera.m_viewMatrix * in;
+
+ if (out->z <= 1.0f) return false;
+
+ float recip = 1.0f / out->z;
+ out->x *= SCREEN_WIDTH * recip;
+ out->y *= SCREEN_HEIGHT * recip;
+
+ return true;
+}
+
+bool
+COccluder::ProcessLineSegment(int corner1, int corner2, CActiveOccluder *occl) {
+ if (!gOccluderCoorsValid[corner1] && !gOccluderCoorsValid[corner2])
+ return false;
+
+ float x1, y1, x2, y2;
+
+ CVector p1, p2;
+ if (!gOccluderCoorsValid[corner1]) {
+ float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f);
+ float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f);
+ float ratio = clipDist2 / (clipDist1 + clipDist2);
+ CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1];
+
+ if (!CalcScreenCoors(clippedCoors, &p1, &x1, &y1))
+ return true;
+ }
+ else {
+ p1 = gOccluderCoorsOnScreen[corner1];
+ }
+
+ if (!gOccluderCoorsValid[corner2]) {
+ float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f);
+ float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f);
+ float ratio = clipDist1 / (clipDist1 + clipDist2);
+ CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1];
+
+ if (!CalcScreenCoors(clippedCoors, &p2, &x2, &y2))
+ return true;
+ }
+ else {
+ p2 = gOccluderCoorsOnScreen[corner2];
+ }
+
+ gMinXInOccluder = Min(Min(gMinXInOccluder, p1.x), p2.x);
+ gMaxXInOccluder = Max(Max(gMaxXInOccluder, p1.x), p2.x);
+ gMinYInOccluder = Min(Min(gMinYInOccluder, p1.y), p2.y);
+ gMaxYInOccluder = Max(Max(gMaxYInOccluder, p1.y), p2.y);
+
+ CVector2D origin = p1;
+ CVector2D direction = p2 - p1;
+
+ // Make sure lines are counter-clockwise around center
+ if (!IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, gCenterOnScreen.x, gCenterOnScreen.y, 0.0f)) {
+ origin += direction;
+ direction *= -1.0f;
+ }
+
+ float magnitude = direction.Magnitude();
+
+ occl->lines[occl->linesCount].origin = origin;
+ occl->lines[occl->linesCount].direction = direction / magnitude;
+ occl->lines[occl->linesCount].length = magnitude;
+
+ if (!DoesInfiniteLineTouchScreen(origin.x, origin.y, direction.x, direction.y))
+ return !IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f, 0.0f);
+
+ occl->linesCount++;
+
+ return false;
+}
+
+bool
+COccluder::ProcessOneOccluder(CActiveOccluder *occl) {
+ float outX, outY;
+
+ occl->linesCount = 0;
+ CVector pos(x, y, z);
+
+ if (!CalcScreenCoors(pos, &gCenterOnScreen, &outX, &outY) || gCenterOnScreen.z < -150.0f || gCenterOnScreen.z > 300.0f) {
+ return false;
+ }
+
+ occl->radius = Max(width, length) * 0.35f + gCenterOnScreen.z;
+
+ CVector vec[3];
+
+ vec[0].x = length / 2.0f * Sin(GetAngle());
+ vec[0].y = -length / 2.0f * Cos(GetAngle());
+ vec[0].z = 0.0f;
+
+ vec[1].x = width / 2.0f * Cos(GetAngle());
+ vec[1].y = width / 2.0f * Sin(GetAngle());
+ vec[1].z = 0.0f;
+
+ vec[2].x = 0.0f;
+ vec[2].y = 0.0f;
+ vec[2].z = height / 2.0f;
+
+ // Figure out if we see the front or back of a face
+ bool bFrontFace[6];
+ for (int i = 0; i < 3; i++) {
+ bFrontFace[i*2+0] = DotProduct((pos + vec[i] - TheCamera.GetPosition()), vec[i]) < 0.0f;
+ bFrontFace[i*2+1] = DotProduct((pos - vec[i] - TheCamera.GetPosition()), -vec[i]) < 0.0f;
+ }
+
+ //calculating vertices of a box
+ gOccluderCoors[0] = pos + vec[0] + vec[1] + vec[2];
+ gOccluderCoors[1] = pos - vec[0] + vec[1] + vec[2];
+ gOccluderCoors[2] = pos + vec[0] - vec[1] + vec[2];
+ gOccluderCoors[3] = pos - vec[0] - vec[1] + vec[2];
+ gOccluderCoors[4] = pos + vec[0] + vec[1] - vec[2];
+ gOccluderCoors[5] = pos - vec[0] + vec[1] - vec[2];
+ gOccluderCoors[6] = pos + vec[0] - vec[1] - vec[2];
+ gOccluderCoors[7] = pos - vec[0] - vec[1] - vec[2];
+
+ for(int i = 0; i < 8; i++)
+ gOccluderCoorsValid[i] = CalcScreenCoors(gOccluderCoors[i], &gOccluderCoorsOnScreen[i], &outX, &outY);
+
+ gMinYInOccluder = 999999.875f;
+ gMinXInOccluder = 999999.875f;
+ gMaxYInOccluder = -999999.875f;
+ gMaxXInOccluder = -999999.875f;
+
+ // Between two differently facing sides we see an edge, so process those
+ if (bFrontFace[2] != bFrontFace[0] && ProcessLineSegment(0, 4, occl))
+ return false;
+ if (bFrontFace[3] != bFrontFace[0] && ProcessLineSegment(2, 6, occl))
+ return false;
+ if (bFrontFace[4] != bFrontFace[0] && ProcessLineSegment(0, 2, occl))
+ return false;
+ if (bFrontFace[5] != bFrontFace[0] && ProcessLineSegment(4, 6, occl))
+ return false;
+ if (bFrontFace[2] != bFrontFace[1] && ProcessLineSegment(1, 5, occl))
+ return false;
+ if (bFrontFace[3] != bFrontFace[1] && ProcessLineSegment(3, 7, occl))
+ return false;
+ if (bFrontFace[4] != bFrontFace[1] && ProcessLineSegment(1, 3, occl))
+ return false;
+ if (bFrontFace[5] != bFrontFace[1] && ProcessLineSegment(5, 7, occl))
+ return false;
+ if (bFrontFace[4] != bFrontFace[2] && ProcessLineSegment(0, 1, occl))
+ return false;
+ if (bFrontFace[3] != bFrontFace[4] && ProcessLineSegment(2, 3, occl))
+ return false;
+ if (bFrontFace[5] != bFrontFace[3] && ProcessLineSegment(6, 7, occl))
+ return false;
+ if (bFrontFace[2] != bFrontFace[5] && ProcessLineSegment(4, 5, occl))
+ return false;
+
+ if (gMaxXInOccluder - gMinXInOccluder < SCREEN_WIDTH * 0.1f ||
+ gMaxYInOccluder - gMinYInOccluder < SCREEN_HEIGHT * 0.07f)
+ return false;
+
+ return true;
+}
+
+bool
+COcclusion::OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2) {
+ for (int i = 0; i < occl1->linesCount; i++) {
+ for (int j = 0; j < occl2->linesCount; j++) {
+ if (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x,
+ occl2->lines[j].direction.y, occl1->lines[i].origin.x, occl1->lines[i].origin.y, 0.0f))
+ return false;
+
+
+ if (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x,
+ occl2->lines[j].direction.y, (occl1->lines[i].origin.x + occl1->lines[i].direction.x * occl1->lines[i].length),
+ (occl1->lines[i].origin.y + occl1->lines[i].direction.y * occl1->lines[i].length), 0.0f))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+COcclusion::ProcessBeforeRendering(void)
+{
+ NumActiveOccluders = 0;
+
+ if (CGame::currArea != AREA_MAIN_MAP)
+ return;
+
+ if (ListWalkThroughFA == -1) {
+ PreviousListWalkThroughFA = -1;
+ ListWalkThroughFA = FarAwayList;
+ }
+
+ int i;
+ for (i = 0; i < 16 && ListWalkThroughFA != -1; i++) {
+ if (aOccluders[ListWalkThroughFA].NearCamera()) {
+ int prevListWalkThroughFA = ListWalkThroughFA;
+
+ if (PreviousListWalkThroughFA == -1) {
+ FarAwayList = aOccluders[ListWalkThroughFA].listIndex;
+ }
+ else {
+ aOccluders[PreviousListWalkThroughFA].listIndex = aOccluders[ListWalkThroughFA].listIndex;
+ }
+
+ int prevNearbyList = NearbyList;
+ ListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex;
+ NearbyList = prevListWalkThroughFA;
+ aOccluders[prevListWalkThroughFA].listIndex = prevNearbyList;
+ }
+ else {
+ PreviousListWalkThroughFA = ListWalkThroughFA;
+ ListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex;
+ }
+ }
+
+ int prevNearbyList = -1;
+ int tmpNearbyList = NearbyList;
+ int indexTmpNearbyList, storeTmpNearbyList, prevFarAwayList;
+ while (tmpNearbyList != -1)
+ {
+ if (NumActiveOccluders < NUMACTIVEOCCLUDERS && aOccluders[tmpNearbyList].ProcessOneOccluder(&aActiveOccluders[NumActiveOccluders]))
+ ++NumActiveOccluders;
+
+ indexTmpNearbyList = tmpNearbyList;
+ if (aOccluders[indexTmpNearbyList].NearCamera())
+ {
+ prevNearbyList = tmpNearbyList;
+ tmpNearbyList = aOccluders[indexTmpNearbyList].listIndex;
+
+ }
+ else
+ {
+ storeTmpNearbyList = tmpNearbyList;
+ if (prevNearbyList == -1) {
+ NearbyList = aOccluders[indexTmpNearbyList].listIndex;
+ }
+ else {
+ aOccluders[prevNearbyList].listIndex = aOccluders[indexTmpNearbyList].listIndex;
+ }
+ tmpNearbyList = aOccluders[indexTmpNearbyList].listIndex;
+ prevFarAwayList = FarAwayList;
+ FarAwayList = storeTmpNearbyList;
+ aOccluders[storeTmpNearbyList].listIndex = prevFarAwayList;
+ }
+ }
+
+ for (i = 0; i < NumActiveOccluders; i++) {
+ for (int j = 0; j < NumActiveOccluders; j++) {
+ if (i != j && aActiveOccluders[j].radius < aActiveOccluders[i].radius) {
+ if (OccluderHidesBehind(&aActiveOccluders[i], &aActiveOccluders[j])) {
+ for (int k = i; k < NumActiveOccluders - 1; k++) {
+ for (int l = 0; l < aActiveOccluders[k + 1].linesCount; l++)
+ aActiveOccluders[k].lines[l] = aActiveOccluders[k + 1].lines[l];
+ aActiveOccluders[k].linesCount = aActiveOccluders[k + 1].linesCount;
+ aActiveOccluders[k].radius = aActiveOccluders[k + 1].radius;
+ }
+ NumActiveOccluders--;
+ i--;
+ }
+ }
+ }
+ }
+}
+
+bool CActiveOccluder::IsPointWithinOcclusionArea(float pX, float pY, float area) {
+ for (int i = 0; i < linesCount; i++) {
+ if (!IsPointInsideLine(lines[i].origin.x, lines[i].origin.y, lines[i].direction.x, lines[i].direction.y, pX, pY, area))
+ return false;
+ }
+
+ return true;
+}
+
+bool COcclusion::IsAABoxOccluded(CVector pos, float width, float length, float height) {
+
+ CVector coors;
+ float outW, outH;
+
+ if (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &outW, &outH))
+ return false;
+
+ float side = CVector(width, length, height).Magnitude() / 4.0f;
+ float area = Max(outW, outH) * side;
+
+ CVector minCorner, maxCorner;
+
+ minCorner.x = pos.x - width / 2.0f;
+ minCorner.y = pos.y - length / 2.0f;
+ minCorner.z = pos.z - height / 2.0f;
+
+ maxCorner.x = pos.x + width / 2.0f;
+ maxCorner.y = pos.y + length / 2.0f;
+ maxCorner.z = pos.z + height / 2.0f;
+
+ for (int i = 0; i < NumActiveOccluders; i++) {
+ if (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) {
+ if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area))
+ return true;
+
+ if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) {
+ if (CalcScreenCoors(minCorner, &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+ if (CalcScreenCoors(CVector(maxCorner.x, maxCorner.y, minCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+ if (CalcScreenCoors(CVector(maxCorner.x, minCorner.y, maxCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+ if (CalcScreenCoors(CVector(minCorner.x, maxCorner.y, maxCorner.z), &coors, &outW, &outH) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool COcclusion::IsPositionOccluded(CVector pos, float side) {
+
+ CVector coors;
+ float width, height;
+
+ if (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &width, &height))
+ return false;
+
+ float area = Max(width, height) * side;
+
+ for (int i = 0; i < NumActiveOccluders; i++) {
+ if (coors.z - (side * 0.85f) > aActiveOccluders[i].radius)
+ if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area))
+ return true;
+ }
+
+ return false;
+}
+
+#include "Lines.h"
+
+RwIm2DVertex vertexbufferT[2];
+
+void COcclusion::Render() {
+ if (!bDisplayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200))
+ return;
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, FALSE);
+
+ float recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera);
+ for (int i = 0; i < NumActiveOccluders; i++) {
+ for (int j = 0; j < aActiveOccluders[i].linesCount; j++) {
+ RwIm2DVertexSetScreenX(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.x);
+ RwIm2DVertexSetScreenY(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.y);
+ RwIm2DVertexSetScreenZ(&vertexbufferT[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&vertexbufferT[0], RwCameraGetNearClipPlane(Scene.camera));
+ RwIm2DVertexSetRecipCameraZ(&vertexbufferT[0], recipz);
+
+ RwIm2DVertexSetScreenX(&vertexbufferT[1],
+ aActiveOccluders[i].lines[j].origin.x + aActiveOccluders[i].lines[j].direction.x * aActiveOccluders[i].lines[j].length);
+ RwIm2DVertexSetScreenY(&vertexbufferT[1],
+ aActiveOccluders[i].lines[j].origin.y + aActiveOccluders[i].lines[j].direction.y * aActiveOccluders[i].lines[j].length);
+ RwIm2DVertexSetScreenZ(&vertexbufferT[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&vertexbufferT[1], RwCameraGetNearClipPlane(Scene.camera));
+ RwIm2DVertexSetRecipCameraZ(&vertexbufferT[1], recipz);
+
+ RwIm2DVertexSetIntRGBA(&vertexbufferT[0], 255, 255, 0, 255);
+ RwIm2DVertexSetIntRGBA(&vertexbufferT[1], 255, 255, 0, 255);
+ RwIm2DRenderLine(vertexbufferT, 2, 0, 1);
+ }
+ }
+
+ DefinedState();
+}
diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h
new file mode 100644
index 00000000..9a415f88
--- /dev/null
+++ b/src/render/Occlusion.h
@@ -0,0 +1,58 @@
+#pragma once
+
+struct ActiveOccluderLine {
+ CVector2D origin;
+ CVector2D direction;
+ float length;
+};
+
+class CActiveOccluder {
+
+public:
+ ActiveOccluderLine lines[6];
+ int32 linesCount;
+ float radius;
+
+ bool IsPointWithinOcclusionArea(float x, float y, float area);
+};
+
+class COccluder
+{
+public:
+ int16 length, width, height;
+ int16 x, y, z;
+ uint16 angle;
+ int16 listIndex;
+
+ bool NearCamera();
+ bool ProcessOneOccluder(CActiveOccluder *occl);
+ bool ProcessLineSegment(int corner1, int corner2, CActiveOccluder* occl);
+ float GetAngle(void) { return angle*TWOPI/UINT16_MAX; }
+};
+
+class COcclusion
+{
+public:
+ static int32 NumOccludersOnMap;
+ static int16 FarAwayList;
+ static int16 NearbyList;
+ static int16 ListWalkThroughFA;
+ static int16 PreviousListWalkThroughFA;
+ static int16 NumActiveOccluders;
+
+ static COccluder aOccluders[NUMOCCLUSIONVOLUMES];
+ static CActiveOccluder aActiveOccluders[NUMACTIVEOCCLUDERS];
+
+ static void Init(void);
+ static void AddOne(float x, float y, float z, float width, float length, float height, float angle);
+ static void ProcessBeforeRendering(void);
+ static bool OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2);
+ static bool IsAABoxOccluded(CVector pos, float width, float length, float height);
+ static bool IsPositionOccluded(CVector pos, float side);
+ static void Render();
+};
+
+bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh);
+bool CalcScreenCoors(CVector const &in, CVector *out);
+
+extern bool bDisplayOccDebugStuff;
diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp
index a867ae13..db40781e 100644
--- a/src/render/Particle.cpp
+++ b/src/render/Particle.cpp
@@ -5,23 +5,27 @@
#include "TxdStore.h"
#include "Sprite.h"
#include "Camera.h"
+#include "Clock.h"
#include "Collision.h"
#include "World.h"
#include "Shadows.h"
+#include "Replay.h"
+#include "Stats.h"
+#include "Weather.h"
+#include "MBlur.h"
+#include "main.h"
#include "AudioScriptObject.h"
#include "ParticleObject.h"
#include "Particle.h"
#include "soundlist.h"
-#define MAX_PARTICLES_ON_SCREEN (1000)
+#define MAX_PARTICLES_ON_SCREEN (750)
//(5)
#define MAX_SMOKE_FILES ARRAY_SIZE(SmokeFiles)
-//(5)
-#define MAX_SMOKE2_FILES ARRAY_SIZE(Smoke2Files)
//(5)
#define MAX_RUBBER_FILES ARRAY_SIZE(RubberFiles)
//(5)
@@ -36,16 +40,16 @@
#define MAX_RAINSPLASHUP_FILES ARRAY_SIZE(RainSplashupFiles)
//(4)
#define MAX_BIRDFRONT_FILES ARRAY_SIZE(BirdfrontFiles)
+//(8)
+#define MAX_BOAT_FILES ARRAY_SIZE(BoatFiles)
//(4)
#define MAX_CARDEBRIS_FILES ARRAY_SIZE(CardebrisFiles)
//(4)
#define MAX_CARSPLASH_FILES ARRAY_SIZE(CarsplashFiles)
-//(4)
-#define MAX_RAINDROP_FILES ARRAY_SIZE(RaindropFiles)
-
-
+#define MAX_RAINDRIP_FILES (2)
+
const char SmokeFiles[][6+1] =
{
"smoke1",
@@ -56,15 +60,6 @@ const char SmokeFiles[][6+1] =
};
-const char Smoke2Files[][9+1] =
-{
- "smokeII_1",
- "smokeII_2",
- "smokeII_3",
- "smokeII_4",
- "smokeII_5"
-};
-
const char RubberFiles[][7+1] =
{
"rubber1",
@@ -108,14 +103,6 @@ const char GunFlashFiles[][9+1] =
"gunflash4"
};
-const char RaindropFiles[][9+1] =
-{
- "raindrop1",
- "raindrop2",
- "raindrop3",
- "raindrop4"
-};
-
const char RainSplashupFiles[][10+1] =
{
"splash_up1",
@@ -130,6 +117,18 @@ const char BirdfrontFiles[][8+1] =
"birdf_04"
};
+const char BoatFiles[][8+1] =
+{
+ "boats_01",
+ "boats_02",
+ "boats_03",
+ "boats_04",
+ "boats_05",
+ "boats_06",
+ "boats_07",
+ "boats_08"
+};
+
const char CardebrisFiles[][12+1] =
{
"cardebris_01",
@@ -149,7 +148,7 @@ const char CarsplashFiles[][12+1] =
CParticle gParticleArray[MAX_PARTICLES_ON_SCREEN];
RwTexture *gpSmokeTex[MAX_SMOKE_FILES];
-RwTexture *gpSmoke2Tex[MAX_SMOKE2_FILES];
+RwTexture *gpSmoke2Tex;
RwTexture *gpRubberTex[MAX_RUBBER_FILES];
RwTexture *gpRainSplashTex[MAX_RAINSPLASH_FILES];
RwTexture *gpWatersprayTex[MAX_WATERSPRAY_FILES];
@@ -157,26 +156,27 @@ RwTexture *gpExplosionMediumTex[MAX_EXPLOSIONMEDIUM_FILES];
RwTexture *gpGunFlashTex[MAX_GUNFLASH_FILES];
RwTexture *gpRainSplashupTex[MAX_RAINSPLASHUP_FILES];
RwTexture *gpBirdfrontTex[MAX_BIRDFRONT_FILES];
+RwTexture *gpBoatTex[MAX_BOAT_FILES];
RwTexture *gpCarDebrisTex[MAX_CARDEBRIS_FILES];
RwTexture *gpCarSplashTex[MAX_CARSPLASH_FILES];
+RwTexture *gpBoatWakeTex;
RwTexture *gpFlame1Tex;
RwTexture *gpFlame5Tex;
RwTexture *gpRainDropSmallTex;
RwTexture *gpBloodTex;
RwTexture *gpLeafTex;
-RwTexture *gpCloudTex1; // unused
+RwTexture *gpCloudTex1;
RwTexture *gpCloudTex4;
RwTexture *gpBloodSmallTex;
RwTexture *gpGungeTex;
RwTexture *gpCollisionSmokeTex;
RwTexture *gpBulletHitTex;
RwTexture *gpGunShellTex;
-RwTexture *gpWakeOldTex;
RwTexture *gpPointlightTex;
RwRaster *gpSmokeRaster[MAX_SMOKE_FILES];
-RwRaster *gpSmoke2Raster[MAX_SMOKE2_FILES];
+RwRaster *gpSmoke2Raster;
RwRaster *gpRubberRaster[MAX_RUBBER_FILES];
RwRaster *gpRainSplashRaster[MAX_RAINSPLASH_FILES];
RwRaster *gpWatersprayRaster[MAX_WATERSPRAY_FILES];
@@ -184,45 +184,62 @@ RwRaster *gpExplosionMediumRaster[MAX_EXPLOSIONMEDIUM_FILES];
RwRaster *gpGunFlashRaster[MAX_GUNFLASH_FILES];
RwRaster *gpRainSplashupRaster[MAX_RAINSPLASHUP_FILES];
RwRaster *gpBirdfrontRaster[MAX_BIRDFRONT_FILES];
+RwRaster *gpBoatRaster[MAX_BOAT_FILES];
RwRaster *gpCarDebrisRaster[MAX_CARDEBRIS_FILES];
RwRaster *gpCarSplashRaster[MAX_CARSPLASH_FILES];
+RwRaster *gpBoatWakeRaster;
RwRaster *gpFlame1Raster;
RwRaster *gpFlame5Raster;
RwRaster *gpRainDropSmallRaster;
RwRaster *gpBloodRaster;
RwRaster *gpLeafRaster;
-RwRaster *gpCloudRaster1; // unused
+RwRaster *gpCloudRaster1;
RwRaster *gpCloudRaster4;
RwRaster *gpBloodSmallRaster;
RwRaster *gpGungeRaster;
RwRaster *gpCollisionSmokeRaster;
RwRaster *gpBulletHitRaster;
RwRaster *gpGunShellRaster;
-RwRaster *gpWakeOldRaster;
-
-
-RwRaster *gpPointlightRaster; // CPointLights::RenderFogEffect
-
-RwTexture *gpRainDropTex[MAX_RAINDROP_FILES]; // CWeather::RenderRainStreaks
-
-
-RwRaster *gpRainDropRaster[MAX_RAINDROP_FILES];
+RwRaster *gpPointlightRaster;
+
+RwTexture *gpRainDropTex;
+RwRaster *gpRainDropRaster;
+
+RwTexture *gpLetterTex;
+RwRaster *gpLetterRaster;
+
+RwTexture *gpSparkTex;
+RwTexture *gpNewspaperTex;
+RwTexture *gpGunSmokeTex;
+RwTexture *gpDotTex;
+RwTexture *gpHeathazeTex;
+RwTexture *gpBeastieTex;
+RwTexture *gpRaindripTex1[MAX_RAINDRIP_FILES];
+RwTexture *gpRaindripTex2[MAX_RAINDRIP_FILES];
+
+RwRaster *gpSparkRaster;
+RwRaster *gpNewspaperRaster;
+RwRaster *gpGunSmokeRaster;
+RwRaster *gpDotRaster;
+RwRaster *gpHeathazeRaster;
+RwRaster *gpBeastieRaster;
+RwRaster *gpRaindripRaster1[MAX_RAINDRIP_FILES];
+RwRaster *gpRaindripRaster2[MAX_RAINDRIP_FILES];
float CParticle::ms_afRandTable[CParticle::RAND_TABLE_SIZE];
-
-
CParticle *CParticle::m_pUnusedListHead;
-
-
float CParticle::m_SinTable[CParticle::SIN_COS_TABLE_SIZE];
float CParticle::m_CosTable[CParticle::SIN_COS_TABLE_SIZE];
int32 Randomizer;
-
int32 nParticleCreationInterval = 1;
+float PARTICLE_WIND_TEST_SCALE = 0.002f;
float fParticleScaleLimit = 0.5f;
+bool clearWaterDrop;
+int32 numWaterDropOnScreen;
+
#ifdef DEBUGMENU
SETTWEAKPATH("Particle");
TWEAKINT32(nParticleCreationInterval, 0, 5, 1);
@@ -230,6 +247,8 @@ TWEAKFLOAT(fParticleScaleLimit, 0.0f, 1.0f, 0.1f);
TWEAKFUNC(CParticle::ReloadConfig);
#endif
+
+
void CParticle::ReloadConfig()
{
debug("Initialising CParticleMgr...");
@@ -302,8 +321,8 @@ void CParticle::Initialise()
{
float angle = DEGTORAD(float(i) * float(360.0f / SIN_COS_TABLE_SIZE));
- m_SinTable[i] = Sin(angle);
- m_CosTable[i] = Cos(angle);
+ m_SinTable[i] = ::Sin(angle);
+ m_CosTable[i] = ::Cos(angle);
}
int32 slot = CTxdStore::FindTxdSlot("particle");
@@ -317,11 +336,8 @@ void CParticle::Initialise()
gpSmokeRaster[i] = RwTextureGetRaster(gpSmokeTex[i]);
}
- for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ )
- {
- gpSmoke2Tex[i] = RwTextureRead(Smoke2Files[i], nil);
- gpSmoke2Raster[i] = RwTextureGetRaster(gpSmoke2Tex[i]);
- }
+ gpSmoke2Tex = RwTextureRead("smokeII_3", nil);
+ gpSmoke2Raster = RwTextureGetRaster(gpSmoke2Tex);
for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ )
{
@@ -349,15 +365,13 @@ void CParticle::Initialise()
for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ )
{
- gpGunFlashTex[i] = RwTextureRead(GunFlashFiles[i], NULL);
+ gpGunFlashTex[i] = RwTextureRead(GunFlashFiles[i], nil);
gpGunFlashRaster[i] = RwTextureGetRaster(gpGunFlashTex[i]);
}
- for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ )
- {
- gpRainDropTex[i] = RwTextureRead(RaindropFiles[i], nil);
- gpRainDropRaster[i] = RwTextureGetRaster(gpRainDropTex[i]);
- }
+ gpRainDropTex = RwTextureRead("raindrop4", nil);
+ gpRainDropRaster = RwTextureGetRaster(gpRainDropTex);
+
for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ )
{
@@ -367,10 +381,16 @@ void CParticle::Initialise()
for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ )
{
- gpBirdfrontTex[i] = RwTextureRead(BirdfrontFiles[i], NULL);
+ gpBirdfrontTex[i] = RwTextureRead(BirdfrontFiles[i], nil);
gpBirdfrontRaster[i] = RwTextureGetRaster(gpBirdfrontTex[i]);
}
+ for ( int32 i = 0; i < MAX_BOAT_FILES; i++ )
+ {
+ gpBoatTex[i] = RwTextureRead(BoatFiles[i], nil);
+ gpBoatRaster[i] = RwTextureGetRaster(gpBoatTex[i]);
+ }
+
for ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ )
{
gpCarDebrisTex[i] = RwTextureRead(CardebrisFiles[i], nil);
@@ -383,7 +403,10 @@ void CParticle::Initialise()
gpCarSplashRaster[i] = RwTextureGetRaster(gpCarSplashTex[i]);
}
- gpFlame1Tex = RwTextureRead("flame1", NULL);
+ gpBoatWakeTex = RwTextureRead("boatwake2", nil);
+ gpBoatWakeRaster = RwTextureGetRaster(gpBoatWakeTex);
+
+ gpFlame1Tex = RwTextureRead("flame1", nil);
gpFlame1Raster = RwTextureGetRaster(gpFlame1Tex);
gpFlame5Tex = RwTextureRead("flame5", nil);
@@ -402,6 +425,9 @@ void CParticle::Initialise()
gpLeafTex = RwTextureRead("gameleaf01_64", nil);
gpLeafRaster = RwTextureGetRaster(gpLeafTex);
+
+ gpLetterTex = RwTextureRead("letter", nil);
+ gpLetterRaster = RwTextureGetRaster(gpLetterTex);
gpCloudTex1 = RwTextureRead("cloud3", nil);
gpCloudRaster1 = RwTextureGetRaster(gpCloudTex1);
@@ -424,12 +450,39 @@ void CParticle::Initialise()
gpGunShellTex = RwTextureRead("gunshell", nil);
gpGunShellRaster = RwTextureGetRaster(gpGunShellTex);
- gpWakeOldTex = RwTextureRead("wake_old", nil);
- gpWakeOldRaster = RwTextureGetRaster(gpWakeOldTex);
-
gpPointlightTex = RwTextureRead("pointlight", nil);
gpPointlightRaster = RwTextureGetRaster(gpPointlightTex);
+ gpSparkTex = RwTextureRead("spark", nil);
+ gpSparkRaster = RwTextureGetRaster(gpSparkTex);
+
+ gpNewspaperTex = RwTextureRead("newspaper02_64", nil);
+ gpNewspaperRaster = RwTextureGetRaster(gpNewspaperTex);
+
+ gpGunSmokeTex = RwTextureRead("gunsmoke3", nil);
+ gpGunSmokeRaster = RwTextureGetRaster(gpGunSmokeTex);
+
+ gpDotTex = RwTextureRead("dot", nil);
+ gpDotRaster = RwTextureGetRaster(gpDotTex);
+
+ gpHeathazeTex = RwTextureRead("heathaze", nil);
+ gpHeathazeRaster = RwTextureGetRaster(gpHeathazeTex);
+
+ gpBeastieTex = RwTextureRead("beastie", nil);
+ gpBeastieRaster = RwTextureGetRaster(gpBeastieTex);
+
+ gpRaindripTex1[0] = RwTextureRead("raindrip64", nil);
+ gpRaindripRaster1[0] = RwTextureGetRaster(gpRaindripTex1[0]);
+
+ gpRaindripTex1[1] = RwTextureRead("raindripb64", nil);
+ gpRaindripRaster1[1] = RwTextureGetRaster(gpRaindripTex1[1]);
+
+ gpRaindripTex2[0] = RwTextureRead("raindrip64_d", nil);
+ gpRaindripRaster2[0] = RwTextureGetRaster(gpRaindripTex2[0]);
+
+ gpRaindripTex2[1] = RwTextureRead("raindripb64_d", nil);
+ gpRaindripRaster2[1] = RwTextureGetRaster(gpRaindripTex2[1]);
+
CTxdStore::PopCurrentTxd();
for ( int32 i = 0; i < MAX_PARTICLES; i++ )
@@ -438,145 +491,180 @@ void CParticle::Initialise()
switch ( i )
{
+ case PARTICLE_SPARK:
+ case PARTICLE_SPARK_SMALL:
+ case PARTICLE_RAINDROP_SMALL:
+ case PARTICLE_HELI_ATTACK:
+ entry->m_ppRaster = &gpRainDropSmallRaster;
+ break;
+
+ case PARTICLE_WATER_SPARK:
+ entry->m_ppRaster = &gpSparkRaster;
+ break;
+
+ case PARTICLE_WHEEL_DIRT:
+ case PARTICLE_SAND:
+ case PARTICLE_STEAM2:
+ case PARTICLE_STEAM_NY:
+ case PARTICLE_STEAM_NY_SLOWMOTION:
+ case PARTICLE_GROUND_STEAM:
+ case PARTICLE_ENGINE_STEAM:
+ case PARTICLE_PEDFOOT_DUST:
+ case PARTICLE_CAR_DUST:
+ case PARTICLE_EXHAUST_FUMES:
+ entry->m_ppRaster = &gpSmoke2Raster;
+ break;
+
+ case PARTICLE_WHEEL_WATER:
+ case PARTICLE_WATER:
+ case PARTICLE_SMOKE:
+ case PARTICLE_SMOKE_SLOWMOTION:
+ case PARTICLE_DRY_ICE:
+ case PARTICLE_GARAGEPAINT_SPRAY:
+ case PARTICLE_STEAM:
+ case PARTICLE_WATER_CANNON:
+ case PARTICLE_EXTINGUISH_STEAM:
+ case PARTICLE_HELI_DUST:
+ case PARTICLE_PAINT_SMOKE:
+ case PARTICLE_BULLETHIT_SMOKE:
+ entry->m_ppRaster = gpSmokeRaster;
+ break;
+
case PARTICLE_BLOOD:
entry->m_ppRaster = &gpBloodRaster;
break;
-
+
case PARTICLE_BLOOD_SMALL:
case PARTICLE_BLOOD_SPURT:
entry->m_ppRaster = &gpBloodSmallRaster;
break;
-
+
+ case PARTICLE_DEBRIS:
+ case PARTICLE_TREE_LEAVES:
+ entry->m_ppRaster = &gpLeafRaster;
+ break;
+
case PARTICLE_DEBRIS2:
entry->m_ppRaster = &gpGungeRaster;
break;
-
+
+ case PARTICLE_FLYERS:
+ entry->m_ppRaster = &gpNewspaperRaster;
+ break;
+
+ case PARTICLE_FLAME:
+ case PARTICLE_CARFLAME:
+ entry->m_ppRaster = &gpFlame1Raster;
+ break;
+
+ case PARTICLE_FIREBALL:
+ entry->m_ppRaster = &gpFlame5Raster;
+ break;
+
case PARTICLE_GUNFLASH:
case PARTICLE_GUNFLASH_NOANIM:
entry->m_ppRaster = gpGunFlashRaster;
break;
-
+
+
case PARTICLE_GUNSMOKE:
- case PARTICLE_SPLASH:
+ case PARTICLE_WATERDROP:
+ case PARTICLE_BLOODDROP:
+ case PARTICLE_HEATHAZE:
+ case PARTICLE_HEATHAZE_IN_DIST:
entry->m_ppRaster = nil;
break;
-
- case PARTICLE_FLAME:
- case PARTICLE_CARFLAME:
- entry->m_ppRaster = &gpFlame1Raster;
+
+ case PARTICLE_GUNSMOKE2:
+ case PARTICLE_BOAT_THRUSTJET:
+ case PARTICLE_RUBBER_SMOKE:
+ entry->m_ppRaster = gpRubberRaster;
break;
-
- case PARTICLE_FIREBALL:
- entry->m_ppRaster = &gpFlame5Raster;
+
+ case PARTICLE_CIGARETTE_SMOKE:
+ entry->m_ppRaster = &gpGunSmokeRaster;
break;
-
+
+ case PARTICLE_TEARGAS:
+ entry->m_ppRaster = &gpHeathazeRaster;
+ break;
+
+ case PARTICLE_SHARD:
+ case PARTICLE_RAINDROP:
+ case PARTICLE_RAINDROP_2D:
+ entry->m_ppRaster = &gpRainDropRaster;
+ break;
+
+ case PARTICLE_SPLASH:
+ case PARTICLE_PED_SPLASH:
+ case PARTICLE_CAR_SPLASH:
+ case PARTICLE_WATER_HYDRANT:
+ entry->m_ppRaster = gpCarSplashRaster;
+ break;
+
case PARTICLE_RAIN_SPLASH:
case PARTICLE_RAIN_SPLASH_BIGGROW:
entry->m_ppRaster = gpRainSplashRaster;
break;
-
+
case PARTICLE_RAIN_SPLASHUP:
entry->m_ppRaster = gpRainSplashupRaster;
break;
-
+
case PARTICLE_WATERSPRAY:
entry->m_ppRaster = gpWatersprayRaster;
break;
-
- case PARTICLE_SHARD:
- case PARTICLE_RAINDROP:
- case PARTICLE_RAINDROP_2D:
- entry->m_ppRaster = gpRainDropRaster;
- break;
-
+
case PARTICLE_EXPLOSION_MEDIUM:
case PARTICLE_EXPLOSION_LARGE:
case PARTICLE_EXPLOSION_MFAST:
case PARTICLE_EXPLOSION_LFAST:
entry->m_ppRaster = gpExplosionMediumRaster;
break;
-
- case PARTICLE_BOAT_WAKE:
- entry->m_ppRaster = &gpWakeOldRaster;
- break;
-
- case PARTICLE_CAR_SPLASH:
- case PARTICLE_WATER_HYDRANT:
- case PARTICLE_PED_SPLASH:
- entry->m_ppRaster = gpCarSplashRaster;
- break;
-
- case PARTICLE_SPARK:
- case PARTICLE_SPARK_SMALL:
- case PARTICLE_RAINDROP_SMALL:
- case PARTICLE_HELI_ATTACK:
- entry->m_ppRaster = &gpRainDropSmallRaster;
- break;
-
- case PARTICLE_DEBRIS:
- case PARTICLE_TREE_LEAVES:
- entry->m_ppRaster = &gpLeafRaster;
- break;
-
- case PARTICLE_CAR_DEBRIS:
- case PARTICLE_HELI_DEBRIS:
- entry->m_ppRaster = gpCarDebrisRaster;
- break;
-
- case PARTICLE_WHEEL_DIRT:
- case PARTICLE_STEAM2:
- case PARTICLE_STEAM_NY:
- case PARTICLE_STEAM_NY_SLOWMOTION:
- case PARTICLE_ENGINE_STEAM:
- case PARTICLE_BOAT_THRUSTJET:
- case PARTICLE_PEDFOOT_DUST:
- case PARTICLE_EXHAUST_FUMES:
- entry->m_ppRaster = gpSmoke2Raster;
+
+ case PARTICLE_BOAT_SPLASH:
+ entry->m_ppRaster = &gpBoatWakeRaster;
break;
-
- case PARTICLE_GUNSMOKE2:
- case PARTICLE_RUBBER_SMOKE:
- entry->m_ppRaster = gpRubberRaster;
+
+ case PARTICLE_ENGINE_SMOKE:
+ case PARTICLE_ENGINE_SMOKE2:
+ case PARTICLE_CARFLAME_SMOKE:
+ case PARTICLE_FIREBALL_SMOKE:
+ case PARTICLE_ROCKET_SMOKE:
+ case PARTICLE_TEST:
+ entry->m_ppRaster = &gpCloudRaster4;
break;
-
+
case PARTICLE_CARCOLLISION_DUST:
case PARTICLE_BURNINGRUBBER_SMOKE:
entry->m_ppRaster = &gpCollisionSmokeRaster;
break;
-
- case PARTICLE_WHEEL_WATER:
- case PARTICLE_WATER:
- case PARTICLE_SMOKE:
- case PARTICLE_SMOKE_SLOWMOTION:
- case PARTICLE_GARAGEPAINT_SPRAY:
- case PARTICLE_STEAM:
- case PARTICLE_BOAT_SPLASH:
- case PARTICLE_WATER_CANNON:
- case PARTICLE_EXTINGUISH_STEAM:
- case PARTICLE_HELI_DUST:
- case PARTICLE_PAINT_SMOKE:
- case PARTICLE_BULLETHIT_SMOKE:
- entry->m_ppRaster = gpSmokeRaster;
+
+ case PARTICLE_CAR_DEBRIS:
+ case PARTICLE_HELI_DEBRIS:
+ case PARTICLE_BIRD_DEBRIS:
+ entry->m_ppRaster = gpCarDebrisRaster;
break;
-
+
case PARTICLE_GUNSHELL_FIRST:
case PARTICLE_GUNSHELL:
case PARTICLE_GUNSHELL_BUMP1:
case PARTICLE_GUNSHELL_BUMP2:
entry->m_ppRaster = &gpGunShellRaster;
break;
-
- case PARTICLE_ENGINE_SMOKE:
- case PARTICLE_ENGINE_SMOKE2:
- case PARTICLE_CARFLAME_SMOKE:
- case PARTICLE_FIREBALL_SMOKE:
- case PARTICLE_TEST:
- entry->m_ppRaster = &gpCloudRaster4;
- break;
-
+
+
case PARTICLE_BIRD_FRONT:
entry->m_ppRaster = gpBirdfrontRaster;
break;
+
+ case PARTICLE_SHIP_SIDE:
+ entry->m_ppRaster = gpBoatRaster;
+ break;
+
+ case PARTICLE_BEASTIE:
+ entry->m_ppRaster = &gpBeastieRaster;
+ break;
}
}
@@ -590,168 +678,145 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_SMOKE_FILES; i++ )
{
RwTextureDestroy(gpSmokeTex[i]);
-#ifdef GTA3_1_1_PATCH
gpSmokeTex[i] = nil;
-#endif
}
- for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ )
- {
- RwTextureDestroy(gpSmoke2Tex[i]);
-#ifdef GTA3_1_1_PATCH
- gpSmoke2Tex[i] = nil;
-#endif
- }
+ RwTextureDestroy(gpSmoke2Tex);
+ gpSmoke2Tex = nil;
for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ )
{
RwTextureDestroy(gpRubberTex[i]);
-#ifdef GTA3_1_1_PATCH
gpRubberTex[i] = nil;
-#endif
}
for ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ )
{
RwTextureDestroy(gpRainSplashTex[i]);
-#ifdef GTA3_1_1_PATCH
gpRainSplashTex[i] = nil;
-#endif
}
for ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ )
{
RwTextureDestroy(gpWatersprayTex[i]);
-#ifdef GTA3_1_1_PATCH
gpWatersprayTex[i] = nil;
-#endif
}
for ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ )
{
RwTextureDestroy(gpExplosionMediumTex[i]);
-#ifdef GTA3_1_1_PATCH
gpExplosionMediumTex[i] = nil;
-#endif
}
for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ )
{
RwTextureDestroy(gpGunFlashTex[i]);
-#ifdef GTA3_1_1_PATCH
gpGunFlashTex[i] = nil;
-#endif
}
- for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ )
- {
- RwTextureDestroy(gpRainDropTex[i]);
-#ifdef GTA3_1_1_PATCH
- gpRainDropTex[i] = nil;
-#endif
- }
+ RwTextureDestroy(gpRainDropTex);
+ gpRainDropTex = nil;
for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ )
{
RwTextureDestroy(gpRainSplashupTex[i]);
-#ifdef GTA3_1_1_PATCH
gpRainSplashupTex[i] = nil;
-#endif
}
for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ )
{
RwTextureDestroy(gpBirdfrontTex[i]);
-#ifdef GTA3_1_1_PATCH
gpBirdfrontTex[i] = nil;
-#endif
+ }
+
+ for ( int32 i = 0; i < MAX_BOAT_FILES; i++ )
+ {
+ RwTextureDestroy(gpBoatTex[i]);
+ gpBoatTex[i] = nil;
}
for ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ )
{
RwTextureDestroy(gpCarDebrisTex[i]);
-#ifdef GTA3_1_1_PATCH
gpCarDebrisTex[i] = nil;
-#endif
}
for ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ )
{
RwTextureDestroy(gpCarSplashTex[i]);
-#ifdef GTA3_1_1_PATCH
gpCarSplashTex[i] = nil;
-#endif
}
+ for ( int32 i = 0; i < MAX_RAINDRIP_FILES; i++ )
+ {
+ RwTextureDestroy(gpRaindripTex1[i]);
+ gpRaindripTex1[i] = nil;
+
+ RwTextureDestroy(gpRaindripTex2[i]);
+ gpRaindripTex2[i] = nil;
+ }
+
+ RwTextureDestroy(gpBoatWakeTex);
+ gpBoatWakeTex = nil;
+
RwTextureDestroy(gpFlame1Tex);
-#ifdef GTA3_1_1_PATCH
gpFlame1Tex = nil;
-#endif
RwTextureDestroy(gpFlame5Tex);
-#ifdef GTA3_1_1_PATCH
gpFlame5Tex = nil;
-#endif
RwTextureDestroy(gpRainDropSmallTex);
-#ifdef GTA3_1_1_PATCH
gpRainDropSmallTex = nil;
-#endif
RwTextureDestroy(gpBloodTex);
-#ifdef GTA3_1_1_PATCH
gpBloodTex = nil;
-#endif
RwTextureDestroy(gpLeafTex);
-#ifdef GTA3_1_1_PATCH
gpLeafTex = nil;
-#endif
+
+ RwTextureDestroy(gpLetterTex);
+ gpLetterTex = nil;
RwTextureDestroy(gpCloudTex1);
-#ifdef GTA3_1_1_PATCH
gpCloudTex1 = nil;
-#endif
RwTextureDestroy(gpCloudTex4);
-#ifdef GTA3_1_1_PATCH
gpCloudTex4 = nil;
-#endif
RwTextureDestroy(gpBloodSmallTex);
-#ifdef GTA3_1_1_PATCH
gpBloodSmallTex = nil;
-#endif
RwTextureDestroy(gpGungeTex);
-#ifdef GTA3_1_1_PATCH
gpGungeTex = nil;
-#endif
RwTextureDestroy(gpCollisionSmokeTex);
-#ifdef GTA3_1_1_PATCH
gpCollisionSmokeTex = nil;
-#endif
RwTextureDestroy(gpBulletHitTex);
-#ifdef GTA3_1_1_PATCH
gpBulletHitTex = nil;
-#endif
RwTextureDestroy(gpGunShellTex);
-#ifdef GTA3_1_1_PATCH
gpGunShellTex = nil;
-#endif
-
- RwTextureDestroy(gpWakeOldTex);
-#ifdef GTA3_1_1_PATCH
- gpWakeOldTex = nil;
-#endif
RwTextureDestroy(gpPointlightTex);
-#ifdef GTA3_1_1_PATCH
gpPointlightTex = nil;
-#endif
+
+ RwTextureDestroy(gpSparkTex);
+ gpSparkTex = nil;
+
+ RwTextureDestroy(gpNewspaperTex);
+ gpNewspaperTex = nil;
+
+ RwTextureDestroy(gpGunSmokeTex);
+ gpGunSmokeTex = nil;
+
+ RwTextureDestroy(gpDotTex);
+ gpDotTex = nil;
+ RwTextureDestroy(gpHeathazeTex);
+ gpHeathazeTex = nil;
+
+ RwTextureDestroy(gpBeastieTex);
+ gpBeastieTex = nil;
int32 slot;
@@ -761,6 +826,40 @@ void CParticle::Shutdown()
debug("CParticle shut down");
}
+
+void CParticle::AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)
+{
+ CVector vecDist = vecEnd - vecStart;
+ float fDist = vecDist.Magnitude();
+ float fSteps = Max(fDist / fPower, 1.0f);
+ int32 nSteps = (int32)fSteps;
+
+ CVector vecStep = vecDist * (1.0f / (float)nSteps);
+
+ for ( int32 i = 0; i < nSteps; i++ )
+ {
+ CVector vecPos = float(i) * vecStep + vecStart;
+ AddParticle(type, vecPos, vecDir, pEntity, fSize, nRotationSpeed, nRotation, nCurFrame, nLifeSpan);
+ }
+}
+
+void CParticle::AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)
+{
+ CVector vecDist = vecEnd - vecStart;
+ float fDist = vecDist.Magnitude();
+ float fSteps = Max(fDist / fPower, 1.0f);
+ int32 nSteps = (int32)fSteps;
+
+ CVector vecStep = vecDist * (1.0f / (float)nSteps);
+
+ for ( int32 i = 0; i < nSteps; i++ )
+ {
+ CVector vecPos = float(i) * vecStep + vecStart;
+
+ AddParticle(type, vecPos, vecDir, pEntity, fSize, color, nRotationSpeed, nRotation, nCurFrame, nLifeSpan);
+ }
+}
+
CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)
{
CRGBA color(0, 0, 0, 0);
@@ -770,9 +869,8 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)
{
if ( CTimer::GetIsPaused() )
- return NULL;
+ return nil;
-#ifdef PC_PARTICLE
if ( ( type == PARTICLE_ENGINE_SMOKE
|| type == PARTICLE_ENGINE_SMOKE2
|| type == PARTICLE_ENGINE_STEAM
@@ -785,8 +883,10 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
{
return nil;
}
-#endif
+ if ( !CReplay::IsPlayingBack() )
+ CReplay::RecordParticle(type, vecPos, vecDir, fSize, color);
+
CParticle *pParticle = m_pUnusedListHead;
if ( pParticle == nil )
@@ -807,7 +907,19 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
pParticle->m_nTimeWhenWillBeDestroyed = CTimer::GetTimeInMilliseconds() + psystem->m_nLifeSpan;
pParticle->m_nColorIntensity = psystem->m_nFadeToBlackInitialIntensity;
+
+ pParticle->m_nFadeToBlackTimer = psystem->m_nFadeToBlackAmount;
+
+ if ( psystem->m_nFadeToBlackTime )
+ pParticle->m_nFadeToBlackTimer /= psystem->m_nFadeToBlackTime;
+
pParticle->m_nAlpha = psystem->m_nFadeAlphaInitialIntensity;
+
+ pParticle->m_nFadeAlphaTimer = psystem->m_nFadeAlphaAmount;
+
+ if ( psystem->m_nFadeAlphaTime )
+ pParticle->m_nFadeAlphaTimer /= psystem->m_nFadeAlphaTime;
+
pParticle->m_nCurrentZRotation = psystem->m_nZRotationInitialAngle;
pParticle->m_fCurrentZRadius = psystem->m_fInitialZRadius;
@@ -816,14 +928,29 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
else
pParticle->m_nCurrentFrame = psystem->m_nStartAnimationFrame;
- pParticle->m_nFadeToBlackTimer = 0;
- pParticle->m_nFadeAlphaTimer = 0;
+
pParticle->m_nZRotationTimer = 0;
pParticle->m_nZRadiusTimer = 0;
pParticle->m_nAnimationSpeedTimer = 0;
pParticle->m_fZGround = 0.0f;
- pParticle->m_vecPosition = vecPos;
+
+ if ( type != PARTICLE_HEATHAZE )
+ pParticle->m_vecPosition = vecPos;
+ else
+ {
+ CVector screen;
+ float w, h;
+
+ if ( !CSprite::CalcScreenCoors(vecPos, screen, &w, &h, true) )
+ return nil;
+
+ pParticle->m_vecPosition = screen;
+ psystem->m_vecTextureStretch.x = w;
+ psystem->m_vecTextureStretch.y = h;
+ }
+
pParticle->m_vecVelocity = vecDir;
+
pParticle->m_vecParticleMovementOffset = CVector(0.0f, 0.0f, 0.0f);
pParticle->m_nTimeWhenColorWillBeChanged = 0;
@@ -831,7 +958,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
RwRGBAAssign(&pParticle->m_Color, &color);
else
{
- RwRGBAAssign(&pParticle->m_Color, &psystem->m_RenderColouring);
+ RwRGBAAssign(&pParticle->m_Color, psystem->m_RenderColouring);
if ( psystem->m_ColorFadeTime != 0 )
pParticle->m_nTimeWhenColorWillBeChanged = CTimer::GetTimeInMilliseconds() + psystem->m_ColorFadeTime;
@@ -839,7 +966,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
if ( psystem->m_InitialColorVariation != 0 )
{
int32 ColorVariation = CGeneral::GetRandomNumberInRange(-psystem->m_InitialColorVariation, psystem->m_InitialColorVariation);
- //Float ColorVariation = CGeneral::GetRandomNumberInRange((float)-psystem->m_InitialColorVariation, (float)psystem->m_InitialColorVariation);
+ //float ColorVariation = CGeneral::GetRandomNumberInRange((float)-psystem->m_InitialColorVariation, (float)psystem->m_InitialColorVariation);
pParticle->m_Color.red = clamp(pParticle->m_Color.red +
PERCENT(pParticle->m_Color.red, ColorVariation),
@@ -856,13 +983,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
}
pParticle->m_nRotation = nRotation;
-
-// PC only
- if ( pParticle->m_nRotation >= 360 )
- pParticle->m_nRotation -= 360;
- else if ( pParticle->m_nRotation < 0 )
- pParticle->m_nRotation += 360;
-
+
if ( nRotationSpeed != 0 )
pParticle->m_nRotationStep = nRotationSpeed;
else
@@ -871,8 +992,6 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
if ( CGeneral::GetRandomNumber() & 1 )
pParticle->m_nRotationStep = -pParticle->m_nRotationStep;
- pParticle->m_vecScreenPosition.x = 0.0f; // bug ?
-
if ( psystem->m_fPositionRandomError != 0.0f )
{
pParticle->m_vecPosition.x += psystem->m_fPositionRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];
@@ -891,7 +1010,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe
pParticle->m_vecVelocity.z += psystem->m_fVelocityRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];
}
- if ( psystem->m_fExpansionRateError != 0.0f )
+ if ( psystem->m_fExpansionRateError != 0.0f && !(psystem->Flags & SCREEN_TRAIL) )
pParticle->m_fExpansionRate += psystem->m_fExpansionRateError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE] + psystem->m_fExpansionRateError;
if ( psystem->m_nRotationRateError != 0 )
@@ -1015,6 +1134,25 @@ void CParticle::Update()
float fFricDeccel99 = pow(0.99f, CTimer::GetTimeStep());
CParticleObject::UpdateAll();
+
+ // ejaculation at 23:00, 23:15, 23:30, 23:45
+ if ( CClock::ms_nGameClockHours == 23 &&
+ ( CClock::ms_nGameClockMinutes == 0
+ || CClock::ms_nGameClockMinutes == 15
+ || CClock::ms_nGameClockMinutes == 30
+ || CClock::ms_nGameClockMinutes == 45 ) )
+ {
+ AddParticle(PARTICLE_CAR_SPLASH,
+ CVector(557.03f, -4.0f, 151.46f),
+ CVector(0.0f, 0.0f, 2.5f),
+ NULL,
+ 2.0f,
+ CRGBA(255, 255, 255, 255),
+ 0,
+ 0,
+ 1,
+ 1000);
+ }
for ( int32 i = 0; i < MAX_PARTICLES; i++ )
{
@@ -1028,9 +1166,199 @@ void CParticle::Update()
for ( ; particle != nil; _Next(particle, prevParticle, psystem, bRemoveParticle) )
{
+ CVector vecWind(0.0f, 0.0f, 0.0f);
+
bRemoveParticle = false;
- CVector moveStep = particle->m_vecPosition + ( particle->m_vecVelocity * CTimer::GetTimeStep() );
+ CVector vecMoveStep = particle->m_vecVelocity * CTimer::GetTimeStep();
+ CVector vecPos = particle->m_vecPosition;
+
+ if ( numWaterDropOnScreen == 0 )
+ clearWaterDrop = false;
+
+ if ( psystem->m_Type == PARTICLE_WATERDROP )
+ {
+ if ( CGame::IsInInterior() || clearWaterDrop == true )
+ {
+ bRemoveParticle = true;
+ continue;
+ }
+
+ static uint8 nWaterDropCount;
+
+ if ( nWaterDropCount == 5 )
+ {
+ vecMoveStep = CVector(0.0f, 0.0f, 0.0f);
+ particle->m_nTimeWhenWillBeDestroyed += 1250;
+ nWaterDropCount = 0;
+ }
+ else
+ {
+ if ( TheCamera.m_CameraAverageSpeed > 0.35f )
+ {
+ if ( vecMoveStep.Magnitude() > 0.5f )
+ {
+ if ( vecMoveStep.Magnitude() > 0.4f && vecMoveStep.Magnitude() < 0.8f )
+ {
+ vecMoveStep.x += TheCamera.m_CameraAverageSpeed * 1.5f;
+ vecMoveStep.y += TheCamera.m_CameraAverageSpeed * 1.5f;
+ }
+ else if ( vecMoveStep.Magnitude() != 0.0f )
+ {
+ vecMoveStep.x += CGeneral::GetRandomNumberInRange(0.01f, 0.05f);
+ vecMoveStep.y += CGeneral::GetRandomNumberInRange(0.01f, 0.05f);
+ }
+ }
+ }
+
+ nWaterDropCount++;
+ }
+
+ if ( vecPos.z <= 1.5f )
+ vecMoveStep.z = 0.0f;
+ }
+
+ if ( psystem->m_Type == PARTICLE_HEATHAZE || psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST )
+ {
+ int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE;
+
+ vecMoveStep.x = Sin(nSinCosIndex);
+ vecMoveStep.y = Sin(nSinCosIndex);
+
+ if ( psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST )
+ particle->m_nRotation = int16((float)particle->m_nRotation + 0.75f);
+ else
+ particle->m_nRotation = int16((float)particle->m_nRotation + 1.0f);
+ }
+
+ if ( psystem->m_Type == PARTICLE_BEASTIE )
+ {
+ int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE;
+
+ particle->m_vecVelocity.x = 0.50f * Cos(nSinCosIndex);
+ particle->m_vecVelocity.y = Cos(nSinCosIndex);
+ particle->m_vecVelocity.z = 0.25f * Sin(nSinCosIndex);
+
+ if ( particle->m_vecVelocity.Magnitude() > 2.0f
+ || vecPos.z > 40.0f
+ || (TheCamera.GetPosition() - vecPos).Magnitude() < 60.0f
+ )
+ {
+ bRemoveParticle = true;
+ continue;
+ }
+ }
+
+ vecPos += vecMoveStep;
+
+ if ( psystem->m_Type == PARTICLE_FIREBALL )
+ {
+ AddParticle(PARTICLE_HEATHAZE, particle->m_vecPosition, CVector(0.0f, 0.0f, 0.0f),
+ nil, particle->m_fSize * 5.0f);
+ }
+
+ if ( psystem->m_Type == PARTICLE_GUNSMOKE2 )
+ {
+ if ( CTimer::GetFrameCounter() & 10 )
+ {
+ if ( FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN )
+ {
+ AddParticle(PARTICLE_HEATHAZE, particle->m_vecPosition, CVector(0.0f, 0.0f, 0.0f));
+ }
+ }
+ }
+
+ if ( CWeather::Wind > 0.0f )
+ {
+ if ( vecMoveStep.Magnitude() != 0.0f )
+ {
+ vecWind.x = CGeneral::GetRandomNumberInRange(0.75f, 1.25f) * -CWeather::Wind;
+ vecWind.y = CGeneral::GetRandomNumberInRange(0.75f, 1.25f) * -CWeather::Wind;
+ vecWind *= PARTICLE_WIND_TEST_SCALE * psystem->m_fWindFactor * CTimer::GetTimeStep();
+ particle->m_vecVelocity += vecWind;
+ }
+ }
+
+ if ( psystem->m_Type == PARTICLE_RAINDROP
+ || psystem->m_Type == PARTICLE_RAINDROP_SMALL
+ || psystem->m_Type == PARTICLE_RAIN_SPLASH
+ || psystem->m_Type == PARTICLE_RAIN_SPLASH_BIGGROW
+ || psystem->m_Type == PARTICLE_CAR_SPLASH
+ || psystem->m_Type == PARTICLE_BOAT_SPLASH
+ || psystem->m_Type == PARTICLE_RAINDROP_2D )
+ {
+ int32 nMaxDrops = int32(6.0f * TheCamera.m_CameraAverageSpeed + 1.0f);
+ float fDistToCam = 0.0f;
+
+ if ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH )
+ {
+ if ( vecPos.z + particle->m_fSize < 5.0f )
+ {
+ bRemoveParticle = true;
+ continue;
+ }
+
+ switch ( TheCamera.GetLookDirection() )
+ {
+ case LOOKING_LEFT:
+ case LOOKING_RIGHT:
+ case LOOKING_FORWARD:
+ nMaxDrops /= 2;
+ break;
+
+ default:
+ nMaxDrops = 0;
+ break;
+ }
+
+ fDistToCam = (TheCamera.GetPosition() - vecPos).Magnitude();
+ }
+
+ if ( numWaterDropOnScreen < nMaxDrops && numWaterDropOnScreen < 63
+ && fDistToCam < 10.0f
+ && clearWaterDrop == false
+ && !CGame::IsInInterior() )
+ {
+ CVector vecWaterdropTarget
+ (
+ CGeneral::GetRandomNumberInRange(-0.25f, 0.25f),
+ CGeneral::GetRandomNumberInRange(0.1f, 0.75f),
+ -0.01f
+ );
+
+ CVector vecWaterdropPos;
+
+ if ( TheCamera.m_CameraAverageSpeed < 0.35f )
+ vecWaterdropPos.x = (float)CGeneral::GetRandomNumberInRange(50, int32(SCREEN_WIDTH) - 50);
+ else
+ vecWaterdropPos.x = (float)CGeneral::GetRandomNumberInRange(200, int32(SCREEN_WIDTH) - 200);
+
+ if ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH )
+ vecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT / 2, SCREEN_HEIGHT);
+ else
+ {
+ if ( TheCamera.m_CameraAverageSpeed < 0.35f )
+ vecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(0, int32(SCREEN_HEIGHT));
+ else
+ vecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(150, int32(SCREEN_HEIGHT) - 200);
+ }
+
+ vecWaterdropPos.z = 2.0f;
+
+ if ( AddParticle(PARTICLE_WATERDROP,
+ vecWaterdropPos,
+ vecWaterdropTarget,
+ nil,
+ CGeneral::GetRandomNumberInRange(0.1f, 0.15f),
+ 0,
+ 0,
+ CGeneral::GetRandomNumber() & 1,
+ 0) != nil )
+ {
+ numWaterDropOnScreen++;
+ }
+ }
+ }
if ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed || particle->m_nAlpha == 0 )
{
@@ -1057,7 +1385,7 @@ void CParticle::Update()
0, 255);
}
else
- RwRGBAAssign(&particle->m_Color, &psystem->m_FadeDestinationColor);
+ RwRGBAAssign(&particle->m_Color, psystem->m_FadeDestinationColor);
}
if ( psystem->Flags & CLIPOUT2D )
@@ -1070,16 +1398,41 @@ void CParticle::Update()
}
}
- float size = particle->m_fSize + particle->m_fExpansionRate;
-
- if ( size < 0.0f )
+ if ( !(psystem->Flags & SCREEN_TRAIL) )
{
- bRemoveParticle = true;
- continue;
+ float size;
+
+ if ( particle->m_fExpansionRate > 0.0f )
+ {
+ float speed = Max(vecWind.Magnitude(), vecMoveStep.Magnitude());
+
+ if ( psystem->m_Type == PARTICLE_EXHAUST_FUMES || psystem->m_Type == PARTICLE_ENGINE_STEAM )
+ speed *= 2.0f;
+
+ if ( ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH )
+ && particle->m_fSize > 1.2f )
+ {
+ size = particle->m_fSize - (1.0f + speed) * particle->m_fExpansionRate;
+ particle->m_vecVelocity.z -= 0.15f;
+ }
+ else
+ size = particle->m_fSize + (1.0f + speed) * particle->m_fExpansionRate;
+ }
+ else
+ size = particle->m_fSize + particle->m_fExpansionRate;
+
+ if ( psystem->m_Type == PARTICLE_WATERDROP )
+ size = (size - Abs(vecMoveStep.x) * 0.000150000007f) + (Abs(vecMoveStep.z) * 0.0500000007f); //TODO:
+
+ if ( size < 0.0f )
+ {
+ bRemoveParticle = true;
+ continue;
+ }
+
+ particle->m_fSize = size;
}
- particle->m_fSize = size;
-
switch ( psystem->m_nFrictionDecceleration )
{
case 50:
@@ -1199,7 +1552,7 @@ void CParticle::Update()
if ( randVal == 5 )
{
- CShadows::AddPermanentShadow(1, gpBloodPoolTex, &vecPosn,
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &vecPosn,
0.1f, 0.0f, 0.0f, -0.1f,
255,
255, 0, 0,
@@ -1207,7 +1560,7 @@ void CParticle::Update()
}
else if ( randVal == 2 )
{
- CShadows::AddPermanentShadow(1, gpBloodPoolTex, &vecPosn,
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &vecPosn,
0.2f, 0.0f, 0.0f, -0.2f,
255,
255, 0, 0,
@@ -1225,12 +1578,12 @@ void CParticle::Update()
CColPoint point;
CEntity *entity;
- if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, moveStep.z, point, entity,
+ if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, vecPos.z, point, entity,
true, true, false, false, true, false, nil) )
{
- if ( moveStep.z <= point.point.z )
+ if ( vecPos.z <= point.point.z )
{
- moveStep.z = point.point.z;
+ vecPos.z = point.point.z;
if ( psystem->m_Type == PARTICLE_DEBRIS2 )
{
particle->m_vecVelocity.x *= 0.8f;
@@ -1317,16 +1670,16 @@ void CParticle::Update()
CColPoint point;
CEntity *entity;
- if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, moveStep.z, point, entity,
+ if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, vecPos.z, point, entity,
true, false, false, false, true, false, nil) )
{
- if ( moveStep.z <= point.point.z )
+ if ( vecPos.z <= point.point.z )
{
- moveStep.z = point.point.z;
+ vecPos.z = point.point.z;
if ( psystem->m_Type == PARTICLE_HELI_ATTACK )
{
bRemoveParticle = true;
- AddParticle(PARTICLE_STEAM, moveStep, CVector(0.0f, 0.0f, 0.05f), nil, 0.2f, 0, 0, 0, 0);
+ AddParticle(PARTICLE_STEAM, vecPos, CVector(0.0f, 0.0f, 0.05f), nil, 0.2f, 0, 0, 0, 0);
continue;
}
}
@@ -1335,37 +1688,21 @@ void CParticle::Update()
}
}
- if ( psystem->m_nFadeToBlackAmount != 0 )
+ if ( particle->m_nFadeToBlackTimer != 0 )
{
- if ( particle->m_nFadeToBlackTimer >= psystem->m_nFadeToBlackTime )
- {
- particle->m_nFadeToBlackTimer = 0;
-
- particle->m_nColorIntensity = clamp(particle->m_nColorIntensity - psystem->m_nFadeToBlackAmount,
+ particle->m_nColorIntensity = clamp(particle->m_nColorIntensity - particle->m_nFadeToBlackTimer,
0, 255);
- }
- else
- ++particle->m_nFadeToBlackTimer;
}
- if ( psystem->m_nFadeAlphaAmount != 0 )
+ if ( particle->m_nFadeAlphaTimer != 0 )
{
- if ( particle->m_nFadeAlphaTimer >= psystem->m_nFadeAlphaTime )
- {
- particle->m_nFadeAlphaTimer = 0;
-
- particle->m_nAlpha = clamp(particle->m_nAlpha - psystem->m_nFadeAlphaAmount,
+ particle->m_nAlpha = clamp(particle->m_nAlpha - particle->m_nFadeAlphaTimer,
0, 255);
-#ifdef PC_PARTICLE
- if ( particle->m_nAlpha == 0 )
- {
- bRemoveParticle = true;
- continue;
- }
-#endif
+ if ( particle->m_nAlpha == 0 )
+ {
+ bRemoveParticle = true;
+ continue;
}
- else
- ++particle->m_nFadeAlphaTimer;
}
if ( psystem->m_nZRotationAngleChangeAmount != 0 )
@@ -1409,31 +1746,24 @@ void CParticle::Update()
}
if ( particle->m_nRotationStep != 0 )
- {
particle->m_nRotation += particle->m_nRotationStep;
-
- if ( particle->m_nRotation >= 360 )
- particle->m_nRotation -= 360;
- else if ( particle->m_nRotation < 0 )
- particle->m_nRotation += 360;
- }
if ( particle->m_fCurrentZRadius != 0.0f )
{
- int32 nRot = particle->m_nCurrentZRotation % (SIN_COS_TABLE_SIZE - 1);
+ int32 nSinCosIndex = particle->m_nCurrentZRotation % SIN_COS_TABLE_SIZE;
- float fX = (Cos(nRot) - Sin(nRot)) * particle->m_fCurrentZRadius;
+ float fX = (Cos(nSinCosIndex) - Sin(nSinCosIndex)) * particle->m_fCurrentZRadius;
- float fY = (Sin(nRot) + Cos(nRot)) * particle->m_fCurrentZRadius;
+ float fY = (Sin(nSinCosIndex) + Cos(nSinCosIndex)) * particle->m_fCurrentZRadius;
- moveStep -= particle->m_vecParticleMovementOffset;
+ vecPos -= particle->m_vecParticleMovementOffset;
- moveStep += CVector(fX, fY, 0.0f);
+ vecPos += CVector(fX, fY, 0.0f);
particle->m_vecParticleMovementOffset = CVector(fX, fY, 0.0f);
}
- particle->m_vecPosition = moveStep;
+ particle->m_vecPosition = vecPos;
}
}
}
@@ -1457,13 +1787,10 @@ void CParticle::Render()
for ( int32 i = 0; i < MAX_PARTICLES; i++ )
{
tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[i];
-#ifdef PC_PARTICLE
bool particleBanned = false;
-#endif
CParticle *particle = psystem->m_pParticles;
RwRaster **frames = psystem->m_ppRaster;
-#ifdef PC_PARTICLE
tParticleType type = psystem->m_Type;
if ( type == PARTICLE_ENGINE_SMOKE
@@ -1477,7 +1804,6 @@ void CParticle::Render()
{
particleBanned = true;
}
-#endif
if ( particle )
{
@@ -1519,11 +1845,10 @@ void CParticle::Render()
while ( particle != nil )
{
bool canDraw = true;
-#ifdef PC_PARTICLE
if ( particle->m_nAlpha == 0 )
canDraw = false;
-#endif
+
if ( canDraw && psystem->m_nFinalAnimationFrame != 0 && frames != nil )
{
RwRaster *curFrame = frames[particle->m_nCurrentFrame];
@@ -1537,28 +1862,153 @@ void CParticle::Render()
if ( canDraw && psystem->Flags & DRAWTOP2D )
{
- if ( particle->m_nRotation != 0 )
+ float screenZ = (particle->m_vecPosition.z - CDraw::GetNearClipZ())
+ * (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ())
+ * CDraw::GetFarClipZ()
+ / ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * particle->m_vecPosition.z )
+ + CSprite::GetNearScreenZ();
+
+ float stretchTexW;
+ float stretchTexH;
+
+ if ( i == PARTICLE_RAINDROP || i == PARTICLE_RAINDROP_SMALL || i == PARTICLE_RAINDROP_2D )
{
- CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(
- particle->m_vecPosition.x,
- particle->m_vecPosition.y,
- particle->m_fSize * 63.0f,
- particle->m_fSize * 63.0f,
- particle->m_Color,
- particle->m_nColorIntensity,
- (float)particle->m_nRotation, //DEGTORAD((float)particle->m_nRotation) ps2
- particle->m_nAlpha);
+ stretchTexW = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x * (float)particle->m_nCurrentFrame + 63.0f;
+ stretchTexH = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y * (float)particle->m_nCurrentFrame + 63.0f;
}
else
{
- CSprite::RenderBufferedOneXLUSprite2D(
- particle->m_vecPosition.x,
- particle->m_vecPosition.y,
- particle->m_fSize * 63.0f,
- particle->m_fSize * 63.0f,
- particle->m_Color,
- particle->m_nColorIntensity,
- particle->m_nAlpha);
+ stretchTexW = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x + 63.0f;
+ stretchTexH = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y + 63.0f;
+ }
+
+
+ if ( i == PARTICLE_WATERDROP )
+ {
+ int32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed;
+
+ stretchTexH += (1.0f - (float)timeLeft ) * psystem->m_vecTextureStretch.y;
+
+ RwRect rect;
+
+ rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));
+ rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));
+ rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));
+ rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));
+
+ FxType fxtype;
+
+ if ( particle->m_nCurrentFrame != 0 )
+ fxtype = FXTYPE_1;
+ else
+ fxtype = FXTYPE_0;
+
+ CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, fxtype);
+
+ canDraw = false;
+ }
+
+ if ( i == PARTICLE_BLOODDROP )
+ {
+ int32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed;
+
+ stretchTexH += (1.0f + (float)timeLeft) * psystem->m_vecTextureStretch.y;
+ stretchTexW += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.x;
+
+ RwRect rect;
+
+ rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));
+ rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));
+ rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));
+ rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));
+
+ FxType fxtype;
+
+ if ( particle->m_nCurrentFrame )
+ fxtype = FXTYPE_3;
+ else
+ fxtype = FXTYPE_2;
+
+ CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, fxtype);
+
+ canDraw = false;
+ }
+
+ if ( i == PARTICLE_HEATHAZE_IN_DIST )
+ {
+ RwRect rect;
+
+ rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));
+ rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH * 0.15f));
+ rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));
+ rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH * 0.15f));
+
+ CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_4);
+
+ canDraw = false;
+ }
+
+ if ( i == PARTICLE_HEATHAZE )
+ {
+ RwRect rect;
+
+ switch ( TheCamera.GetLookDirection() )
+ {
+ case LOOKING_LEFT:
+ rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x * 2.0f));
+ rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));
+ rect.w = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));
+ rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));
+
+ break;
+
+ case LOOKING_RIGHT:
+ rect.x = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));
+ rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));
+ rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x * 4.0f));
+ rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));
+
+ break;
+
+ default:
+ rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));
+ rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));
+ rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));
+ rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));
+
+ break;
+ }
+
+ CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_4);
+
+ canDraw = false;
+ }
+
+ if ( canDraw )
+ {
+ if ( particle->m_nRotation != 0 )
+ {
+ CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(
+ particle->m_vecPosition.x,
+ particle->m_vecPosition.y,
+ particle->m_fSize * stretchTexW,
+ particle->m_fSize * stretchTexH,
+ particle->m_Color,
+ particle->m_nColorIntensity,
+ DEGTORAD((float)particle->m_nRotation),
+ particle->m_nAlpha);
+ }
+ else
+ {
+ CSprite::RenderBufferedOneXLUSprite2D(
+ particle->m_vecPosition.x,
+ particle->m_vecPosition.y,
+ particle->m_fSize * stretchTexW,
+ particle->m_fSize * stretchTexH,
+ particle->m_Color,
+ particle->m_nColorIntensity,
+ particle->m_nAlpha);
+ }
}
canDraw = false;
@@ -1572,174 +2022,234 @@ void CParticle::Render()
if ( CSprite::CalcScreenCoors(particle->m_vecPosition, coors, &w, &h, true) )
{
-#ifdef PC_PARTICLE
- if ( (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w)
- && SCREEN_HEIGHT * fParticleScaleLimit >= h )
-#endif
+
+ if ( i == PARTICLE_ENGINE_STEAM
+ || i == PARTICLE_ENGINE_SMOKE
+ || i == PARTICLE_ENGINE_SMOKE2
+ || i == PARTICLE_CARFLAME_SMOKE
+ || i == PARTICLE_CARCOLLISION_DUST
+ || i == PARTICLE_EXHAUST_FUMES
+ || i == PARTICLE_RUBBER_SMOKE
+ || i == PARTICLE_BURNINGRUBBER_SMOKE )
{
- if ( particle->m_nRotation != 0 )
- {
- CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,
- particle->m_fSize * w, particle->m_fSize * h,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- float(particle->m_nRotation), // DEGTORAD((float)particle->m_nRotation) ps2
- particle->m_nAlpha);
+ switch ( TheCamera.GetLookDirection() )
+ {
+ case LOOKING_LEFT:
+ case LOOKING_RIGHT:
+ w += CGeneral::GetRandomNumberInRange(1.0f, 7.5f) * psystem->m_vecTextureStretch.x;
+ h += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y;
+ break;
+
+ default:
+ w += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x;
+ h += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y;
+ break;
}
- else if ( psystem->Flags & SCREEN_TRAIL )
+ }
+ else if ( i == PARTICLE_WATER_HYDRANT )
+ {
+ int32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed;
+
+ w += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.x;
+ h += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.y;
+ }
+ else if ( i == PARTICLE_FLYERS )
+ {
+ w += psystem->m_vecTextureStretch.x;
+ h += psystem->m_vecTextureStretch.y;
+
+ w = Max(w, 12.0f);
+ h = Max(h, 12.0f);
+ }
+ else
+ {
+ w += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x;
+ h += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y;
+ }
+
+ if ( i == PARTICLE_WATER_HYDRANT
+ || (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w)
+ && SCREEN_HEIGHT * fParticleScaleLimit >= h )
+ {
+ if ( i == PARTICLE_WATER_HYDRANT )
{
- float fRotation;
- float fTrailLength;
+ RwRect rect;
- if ( particle->m_vecScreenPosition.x == 0.0f )
+ if ( w > 0.0f )
{
- fTrailLength = 0.0f;
- fRotation = 0.0f;
+ rect.x = int32(coors.x - SCREEN_STRETCH_X(particle->m_fSize * w));
+ rect.w = int32(coors.x + SCREEN_STRETCH_X(particle->m_fSize * w));
}
else
{
- CVector2D vecDist
- (
- coors.x - particle->m_vecScreenPosition.x,
- coors.y - particle->m_vecScreenPosition.y
- );
-
- float fDist = vecDist.Magnitude();
-
- fTrailLength = fDist;
-
- float fRot = Asin(vecDist.x / fDist);
-
- fRotation = fRot;
-
- if ( vecDist.y < 0.0f )
- fRotation = -1.0f * fRot + DEGTORAD(180.0f);
-
- fRotation = RADTODEG(fRotation);
-
- if ( fRotation < 0.0f )
- fRotation += 360.0f;
-
- float fSpeed = particle->m_vecVelocity.Magnitude();
-
- float fNewTrailLength = fSpeed * CTimer::GetTimeStep() * w * 2.0f;
-
- if ( fDist > fNewTrailLength )
- fTrailLength = fNewTrailLength;
+ rect.w = int32(coors.x - SCREEN_STRETCH_X(particle->m_fSize * w));
+ rect.x = int32(coors.x + SCREEN_STRETCH_X(particle->m_fSize * w));
}
- CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,
- particle->m_fSize * w,
- particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- fRotation,
- particle->m_nAlpha);
-
- particle->m_vecScreenPosition = coors;
+ if ( h > 0.0f )
+ {
+ rect.y = int32(coors.y - SCREEN_STRETCH_Y(particle->m_fSize * h));
+ rect.h = int32(coors.y + SCREEN_STRETCH_Y(particle->m_fSize * h));
+ }
+ else
+ {
+ rect.h = int32(coors.y - SCREEN_STRETCH_Y(particle->m_fSize * h));
+ rect.y = int32(coors.y + SCREEN_STRETCH_Y(particle->m_fSize * h));
+ }
+
+ float screenZ = (coors.z - CDraw::GetNearClipZ())
+ * (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ()) * CDraw::GetFarClipZ()
+ / ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * coors.z ) + CSprite::GetNearScreenZ();
+
+ CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_5);
}
- else if ( psystem->Flags & SPEED_TRAIL )
+ else
{
- CVector vecPrevPos = particle->m_vecPosition - particle->m_vecVelocity;
- float fRotation;
- float fTrailLength;
-
- if ( CSprite::CalcScreenCoors(vecPrevPos, particle->m_vecScreenPosition, &fTrailLength, &fRotation, true) )
+ if ( particle->m_nRotation != 0 && i != PARTICLE_BEASTIE )
+ {
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,
+ particle->m_fSize * w, particle->m_fSize * h,
+ particle->m_Color.red,
+ particle->m_Color.green,
+ particle->m_Color.blue,
+ particle->m_nColorIntensity,
+ 1.0f / coors.z,
+ DEGTORAD((float)particle->m_nRotation),
+ particle->m_nAlpha);
+ }
+ else if ( psystem->Flags & SCREEN_TRAIL )
{
- CVector2D vecDist
- (
- coors.x - particle->m_vecScreenPosition.x,
- coors.y - particle->m_vecScreenPosition.y
- );
-
- float fDist = vecDist.Magnitude();
-
- fTrailLength = fDist;
+ float fRotation;
+ float fTrailLength;
- float fRot = Asin(vecDist.x / fDist);
-
- fRotation = fRot;
+ if ( particle->m_fZGround == 0.0f )
+ {
+ fTrailLength = 0.0f;
+ fRotation = 0.0f;
+ }
+ else
+ {
+ CVector2D vecDist
+ (
+ coors.x - particle->m_fZGround,
+ coors.y - particle->m_fExpansionRate
+ );
+
+ float fDist = vecDist.Magnitude();
+
+ fTrailLength = fDist;
+
+ float fRot = Asin(vecDist.x / fDist);
+
+ fRotation = fRot;
+
+ if ( vecDist.y < 0.0f )
+ fRotation = -1.0f * fRot + DEGTORAD(180.0f);
+
+ float fSpeed = particle->m_vecVelocity.Magnitude();
+
+ float fNewTrailLength = fSpeed * CTimer::GetTimeStep() * w * 2.0f;
+
+ if ( fDist > fNewTrailLength )
+ fTrailLength = fNewTrailLength;
+ }
- if ( vecDist.y < 0.0f )
- fRotation = -1.0f * fRot + DEGTORAD(180.0f);
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,
+ particle->m_fSize * w,
+ particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier,
+ particle->m_Color.red,
+ particle->m_Color.green,
+ particle->m_Color.blue,
+ particle->m_nColorIntensity,
+ 1.0f / coors.z,
+ fRotation,
+ particle->m_nAlpha);
+
+ particle->m_fZGround = coors.x; // WTF ?
+ particle->m_fExpansionRate = coors.y; // WTF ?
+ }
+ else if ( psystem->Flags & SPEED_TRAIL )
+ {
+ CVector vecPrevPos = particle->m_vecPosition - particle->m_vecVelocity;
+ float fRotation;
+ float fTrailLength;
+ CVector vecScreenPosition;
- fRotation = RADTODEG(fRotation);
+ if ( CSprite::CalcScreenCoors(vecPrevPos, vecScreenPosition, &fTrailLength, &fRotation, true) )
+ {
+ CVector2D vecDist
+ (
+ coors.x - vecScreenPosition.x,
+ coors.y - vecScreenPosition.y
+ );
+
+ float fDist = vecDist.Magnitude();
+
+ fTrailLength = fDist;
+
+ float fRot = Asin(vecDist.x / fDist);
+
+ fRotation = fRot;
+
+ if ( vecDist.y < 0.0f )
+ fRotation = -1.0f * fRot + DEGTORAD(180.0f);
+ }
+ else
+ {
+ fRotation = 0.0f;
+ fTrailLength = 0.0f;
+ }
- if ( fRotation < 0.0f )
- fRotation += 360.0f;
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,
+ particle->m_fSize * w,
+ particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier,
+ particle->m_Color.red,
+ particle->m_Color.green,
+ particle->m_Color.blue,
+ particle->m_nColorIntensity,
+ 1.0f / coors.z,
+ fRotation,
+ particle->m_nAlpha);
}
- else
+ else if ( psystem->Flags & VERT_TRAIL )
{
- fRotation = 0.0f;
- fTrailLength = 0.0f;
+ float fTrailLength = fabsf(particle->m_vecVelocity.z * 10.0f);
+
+ CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
+ particle->m_fSize * w,
+ (particle->m_fSize + fTrailLength * psystem->m_fTrailLengthMultiplier) * h,
+ particle->m_Color.red,
+ particle->m_Color.green,
+ particle->m_Color.blue,
+ particle->m_nColorIntensity,
+ 1.0f / coors.z,
+ particle->m_nAlpha);
+ }
+ else if ( i == PARTICLE_RAINDROP_SMALL )
+ {
+ CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
+ particle->m_fSize * w * 0.05f,
+ particle->m_fSize * h,
+ particle->m_Color.red,
+ particle->m_Color.green,
+ particle->m_Color.blue,
+ particle->m_nColorIntensity,
+ 1.0f / coors.z,
+ particle->m_nAlpha);
+ }
+ /*else if ( i == PARTICLE_BOAT_WAKE )*/
+ else
+ {
+ CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
+ particle->m_fSize * w,
+ particle->m_fSize * h,
+ particle->m_Color.red,
+ particle->m_Color.green,
+ particle->m_Color.blue,
+ particle->m_nColorIntensity,
+ 1.0f / coors.z,
+ particle->m_nAlpha);
}
-
- CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,
- particle->m_fSize * w,
- particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- fRotation,
- particle->m_nAlpha);
- }
- else if ( psystem->Flags & VERT_TRAIL )
- {
- float fTrailLength = fabsf(particle->m_vecVelocity.z * 10.0f);
-
- CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
- particle->m_fSize * w,
- (particle->m_fSize + fTrailLength * psystem->m_fTrailLengthMultiplier) * h,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- particle->m_nAlpha);
- }
- else if ( i == PARTICLE_RAINDROP_SMALL )
- {
- CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
- particle->m_fSize * w * 0.05f,
- particle->m_fSize * h,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- particle->m_nAlpha);
- }
- else if ( i == PARTICLE_BOAT_WAKE )
- {
- CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
- particle->m_fSize * w,
- psystem->m_fDefaultInitialRadius * h,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- particle->m_nAlpha);
- }
- else
- {
- CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,
- particle->m_fSize * w,
- particle->m_fSize * h,
- particle->m_Color.red,
- particle->m_Color.green,
- particle->m_Color.blue,
- particle->m_nColorIntensity,
- 1.0f / coors.z,
- particle->m_nAlpha);
}
}
}
@@ -1769,6 +2279,9 @@ void CParticle::RemovePSystem(tParticleType type)
void CParticle::RemoveParticle(CParticle *pParticle, CParticle *pPrevParticle, tParticleSystemData *pPSystemData)
{
+ if ( pPSystemData->m_Type == PARTICLE_WATERDROP )
+ --numWaterDropOnScreen;
+
if ( pPrevParticle )
pPrevParticle->m_pNext = pParticle->m_pNext;
else
@@ -1857,3 +2370,89 @@ void CParticle::AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatr
0.3f, color, 0, 0, 0, 0);
}
}
+
+void CParticle::CalWindDir(CVector *vecDirIn, CVector *vecDirOut)
+{
+ vecDirOut->x = (Cos(128) * vecDirIn->x) + (Sin(128) * vecDirIn->y);
+
+ vecDirOut->x = (Cos(128) * vecDirIn->x) + (Sin(128) * vecDirIn->y) * CWeather::Wind;
+ vecDirOut->y = (Sin(128) * vecDirIn->x) - (Cos(128) * vecDirIn->y) * CWeather::Wind;
+}
+
+void CParticle::HandleShipsAtHorizonStuff()
+{
+ tParticleSystemData *psystemdata = &mod_ParticleSystemManager.m_aParticles[PARTICLE_SHIP_SIDE];
+
+ for ( CParticle *particle = psystemdata->m_pParticles; particle; particle = particle->m_pNext )
+ {
+ if ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed - 32000
+ && CTimer::GetTimeInMilliseconds() < particle->m_nTimeWhenWillBeDestroyed - 22000 )
+ {
+ particle->m_nAlpha = Min(particle->m_nAlpha + 1, 96);
+ }
+ if ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed - 10000 )
+ particle->m_nFadeAlphaTimer = 1;
+ }
+}
+
+void CParticle::HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos)
+{
+ float fHeadingRad = entity->GetForward().Heading();
+ float fHeading = RADTODEG(fHeadingRad);
+ float fBirdAngle = Cos(DEGTORAD(1.5f));
+
+ tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[PARTICLE_BIRD_FRONT];
+ CParticle *particle = psystem->m_pParticles;
+ CParticle *prevParticle = nil;
+ bool bRemoveParticle;
+
+ for ( ; particle != nil; _Next(particle, prevParticle, psystem, bRemoveParticle) )
+ {
+ bRemoveParticle = false;
+
+ CVector2D vecPos(particle->m_vecPosition.x, particle->m_vecPosition.y);
+ CVector2D vecCamPos(camPos.x, camPos.y);
+
+ CVector2D vecDist = vecPos - vecCamPos;
+ vecDist.Normalise();
+
+ float fHead = DEGTORAD(fHeading);
+
+ CVector2D vecDir(-::Sin(fHead), ::Cos(fHead));
+ vecDir.Normalise();
+
+ float fDot = DotProduct2D(vecDir, vecDist);
+
+ if ( fDot > 0.0f && fDot > fBirdAngle )
+ {
+ if ( (camPos - particle->m_vecPosition).MagnitudeSqr() < 40000.0f )
+ {
+ CStats::SeagullsKilled++;
+
+ bRemoveParticle = true;
+
+ for ( int32 i = 0; i < 8; i++ )
+ {
+ CParticle *pBirdDerbis = AddParticle(PARTICLE_BIRD_DEBRIS,
+ particle->m_vecPosition,
+ CVector
+ (
+ CGeneral::GetRandomNumberInRange(-3.0f, 3.0f),
+ CGeneral::GetRandomNumberInRange(-3.0f, 3.0f),
+ CGeneral::GetRandomNumberInRange(-3.0f, 3.0f)
+ ),
+ nil,
+ 0.3f,
+ particle->m_Color,
+ CGeneral::GetRandomNumberInRange(20, 40),
+ 0,
+ CGeneral::GetRandomNumber() & 3,
+ 200);
+ if ( pBirdDerbis )
+ pBirdDerbis->m_nAlpha = particle->m_nAlpha;
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/render/Particle.h b/src/render/Particle.h
index 7f02e318..9c496fe1 100644
--- a/src/render/Particle.h
+++ b/src/render/Particle.h
@@ -15,25 +15,24 @@ public:
CVector m_vecPosition;
CVector m_vecVelocity;
- CVector m_vecScreenPosition;
- uint32 m_nTimeWhenWillBeDestroyed;
- uint32 m_nTimeWhenColorWillBeChanged;
+ uint32 m_nTimeWhenWillBeDestroyed;
+ uint32 m_nTimeWhenColorWillBeChanged;
float m_fZGround;
CVector m_vecParticleMovementOffset;
int16 m_nCurrentZRotation;
- uint16 m_nZRotationTimer;
+ uint16 m_nZRotationTimer;
float m_fCurrentZRadius;
- uint16 m_nZRadiusTimer;
- float m_fSize;
- float m_fExpansionRate;
- uint16 m_nFadeToBlackTimer;
- uint16 m_nFadeAlphaTimer;
+ uint16 m_nZRadiusTimer;
uint8 m_nColorIntensity;
uint8 m_nAlpha;
- uint16 m_nCurrentFrame;
+ float m_fSize;
+ float m_fExpansionRate;
+ int16 m_nFadeToBlackTimer;
+ int16 m_nFadeAlphaTimer;
int16 m_nAnimationSpeedTimer;
int16 m_nRotationStep;
int16 m_nRotation;
+ uint8 m_nCurrentFrame;
RwRGBA m_Color;
CParticle *m_pNext;
@@ -60,8 +59,11 @@ public:
static void Initialise();
static void Shutdown();
- static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity = nil, float fSize = 0.0f, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);
- static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);
+ static void AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity = nil, float fSize = 0.0f, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);
+ static void AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, RwRGBA const&color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);
+
+ static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity = nil, float fSize = 0.0f, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);
+ static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);
static void Update();
static void Render();
@@ -89,6 +91,13 @@ public:
static void AddJetExplosion(CVector const &vecPos, float fPower, float fSize);
static void AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatrix);
+ static void CalWindDir(CVector *vecDirIn, CVector *vecDirOut);
+
+ static void HandleShipsAtHorizonStuff();
+ static void HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos);
};
-VALIDATE_SIZE(CParticle, 0x68);
+extern bool clearWaterDrop;
+extern int32 numWaterDropOnScreen;
+
+VALIDATE_SIZE(CParticle, 0x58);
diff --git a/src/render/ParticleMgr.cpp b/src/render/ParticleMgr.cpp
index 3387d471..f6919435 100644
--- a/src/render/ParticleMgr.cpp
+++ b/src/render/ParticleMgr.cpp
@@ -216,6 +216,18 @@ void cParticleSystemMgr::LoadParticleData()
case CFG_PARAM_TRAIL_LENGTH_MULTIPLIER:
entry->m_fTrailLengthMultiplier = atof(value);
break;
+
+ case CFG_PARAM_STRETCH_VALUE_X:
+ entry->m_vecTextureStretch.x = atof(value);
+ break;
+
+ case CFG_PARAM_STRETCH_VALUE_Y:
+ entry->m_vecTextureStretch.y = atof(value);
+ break;
+
+ case CFG_PARAM_WIND_FACTOR:
+ entry->m_fWindFactor = atof(value);
+ break;
case CFG_PARAM_PARTICLE_CREATE_RANGE:
entry->m_fCreateRange = SQR(atof(value));
diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h
index 0100bb65..f4afc018 100644
--- a/src/render/ParticleMgr.h
+++ b/src/render/ParticleMgr.h
@@ -36,14 +36,14 @@ struct tParticleSystemData
uint16 m_nZRadiusChangeTime;
float m_fInitialZRadius;
float m_fZRadiusChangeAmount;
- uint16 m_nFadeToBlackTime;
- int16 m_nFadeToBlackAmount;
+ int16 m_nFadeToBlackTime;
uint8 m_nFadeToBlackInitialIntensity;
+ int16 m_nFadeToBlackAmount;
uint8 m_nFadeAlphaInitialIntensity;
- uint16 m_nFadeAlphaTime;
+ int16 m_nFadeAlphaTime;
int16 m_nFadeAlphaAmount;
- uint16 m_nStartAnimationFrame;
- uint16 m_nFinalAnimationFrame;
+ uint8 m_nStartAnimationFrame;
+ uint8 m_nFinalAnimationFrame;
uint16 m_nAnimationSpeed;
uint16 m_nRotationSpeed;
float m_fGravitationalAcceleration;
@@ -56,16 +56,19 @@ struct tParticleSystemData
uint32 m_nLifeSpanErrorShape;
float m_fTrailLengthMultiplier;
uint32 Flags;
- RwRGBA m_RenderColouring;
+ CRGBA m_RenderColouring;
uint8 m_InitialColorVariation;
- RwRGBA m_FadeDestinationColor;
+ CRGBA m_FadeDestinationColor;
uint32 m_ColorFadeTime;
+
+ CVector2D m_vecTextureStretch;
+ float m_fWindFactor;
RwRaster **m_ppRaster;
CParticle *m_pParticles;
};
-VALIDATE_SIZE(tParticleSystemData, 0x88);
+VALIDATE_SIZE(tParticleSystemData, 0x94);
class cParticleSystemMgr
{
@@ -107,6 +110,11 @@ class cParticleSystemMgr
CFG_PARAM_ROTATION_RATE_ERROR,
CFG_PARAM_LIFE_SPAN_ERROR_SHAPE,
CFG_PARAM_TRAIL_LENGTH_MULTIPLIER,
+
+ CFG_PARAM_STRETCH_VALUE_X,
+ CFG_PARAM_STRETCH_VALUE_Y,
+ CFG_PARAM_WIND_FACTOR,
+
CFG_PARAM_PARTICLE_CREATE_RANGE,
CFG_PARAM_FLAGS,
@@ -125,6 +133,6 @@ public:
void RangeCheck(tParticleSystemData *pData) { }
};
-VALIDATE_SIZE(cParticleSystemMgr, 0x2420);
+VALIDATE_SIZE(cParticleSystemMgr, 0x2FFC);
extern cParticleSystemMgr mod_ParticleSystemManager;
diff --git a/src/render/ParticleType.h b/src/render/ParticleType.h
index 8d352c44..0af9a1e1 100644
--- a/src/render/ParticleType.h
+++ b/src/render/ParticleType.h
@@ -4,13 +4,16 @@ enum tParticleType
{
PARTICLE_SPARK = 0,
PARTICLE_SPARK_SMALL,
+ PARTICLE_WATER_SPARK,
PARTICLE_WHEEL_DIRT,
+ PARTICLE_SAND,
PARTICLE_WHEEL_WATER,
PARTICLE_BLOOD,
PARTICLE_BLOOD_SMALL,
PARTICLE_BLOOD_SPURT,
PARTICLE_DEBRIS,
PARTICLE_DEBRIS2,
+ PARTICLE_FLYERS,
PARTICLE_WATER,
PARTICLE_FLAME,
PARTICLE_FIREBALL,
@@ -18,8 +21,11 @@ enum tParticleType
PARTICLE_GUNFLASH_NOANIM,
PARTICLE_GUNSMOKE,
PARTICLE_GUNSMOKE2,
+ PARTICLE_CIGARETTE_SMOKE,
PARTICLE_SMOKE,
PARTICLE_SMOKE_SLOWMOTION,
+ PARTICLE_DRY_ICE,
+ PARTICLE_TEARGAS,
PARTICLE_GARAGEPAINT_SPRAY,
PARTICLE_SHARD,
PARTICLE_SPLASH,
@@ -28,6 +34,7 @@ enum tParticleType
PARTICLE_STEAM2,
PARTICLE_STEAM_NY,
PARTICLE_STEAM_NY_SLOWMOTION,
+ PARTICLE_GROUND_STEAM,
PARTICLE_ENGINE_STEAM,
PARTICLE_RAINDROP,
PARTICLE_RAINDROP_SMALL,
@@ -35,6 +42,8 @@ enum tParticleType
PARTICLE_RAIN_SPLASH_BIGGROW,
PARTICLE_RAIN_SPLASHUP,
PARTICLE_WATERSPRAY,
+ PARTICLE_WATERDROP,
+ PARTICLE_BLOODDROP,
PARTICLE_EXPLOSION_MEDIUM,
PARTICLE_EXPLOSION_LARGE,
PARTICLE_EXPLOSION_MFAST,
@@ -42,12 +51,12 @@ enum tParticleType
PARTICLE_CAR_SPLASH,
PARTICLE_BOAT_SPLASH,
PARTICLE_BOAT_THRUSTJET,
- PARTICLE_BOAT_WAKE,
PARTICLE_WATER_HYDRANT,
PARTICLE_WATER_CANNON,
PARTICLE_EXTINGUISH_STEAM,
PARTICLE_PED_SPLASH,
PARTICLE_PEDFOOT_DUST,
+ PARTICLE_CAR_DUST,
PARTICLE_HELI_DUST,
PARTICLE_HELI_ATTACK,
PARTICLE_ENGINE_SMOKE,
@@ -58,6 +67,7 @@ enum tParticleType
PARTICLE_TREE_LEAVES,
PARTICLE_CARCOLLISION_DUST,
PARTICLE_CAR_DEBRIS,
+ PARTICLE_BIRD_DEBRIS,
PARTICLE_HELI_DEBRIS,
PARTICLE_EXHAUST_FUMES,
PARTICLE_RUBBER_SMOKE,
@@ -67,9 +77,14 @@ enum tParticleType
PARTICLE_GUNSHELL,
PARTICLE_GUNSHELL_BUMP1,
PARTICLE_GUNSHELL_BUMP2,
+ PARTICLE_ROCKET_SMOKE,
PARTICLE_TEST,
PARTICLE_BIRD_FRONT,
+ PARTICLE_SHIP_SIDE,
+ PARTICLE_BEASTIE,
PARTICLE_RAINDROP_2D,
+ PARTICLE_HEATHAZE,
+ PARTICLE_HEATHAZE_IN_DIST,
MAX_PARTICLES,
PARTICLE_FIRST = PARTICLE_SPARK,
diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp
index 0713dc6d..b09b07bd 100644
--- a/src/render/PointLights.cpp
+++ b/src/render/PointLights.cpp
@@ -1,6 +1,7 @@
#include "common.h"
#include "main.h"
+#include "CutsceneMgr.h"
#include "Lights.h"
#include "Camera.h"
#include "Weather.h"
@@ -10,8 +11,23 @@
#include "Timer.h"
#include "PointLights.h"
+//--MIAMI: file done
+
int16 CPointLights::NumLights;
CRegisteredPointLight CPointLights::aLights[NUMPOINTLIGHTS];
+CVector CPointLights::aCachedMapReads[32];
+float CPointLights::aCachedMapReadResults[32];
+int32 CPointLights::NextCachedValue;
+
+void
+CPointLights::Init(void)
+{
+ for(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++){
+ aCachedMapReads[i] = CVector(0.0f, 0.0f, 0.0f);
+ aCachedMapReadResults[i] = 0.0f;
+ }
+ NextCachedValue = 0;
+}
void
CPointLights::InitPerFrame(void)
@@ -142,12 +158,17 @@ CPointLights::RenderFogEffect(void)
CVector spriteCoors;
float spritew, spriteh;
+ if(CCutsceneMgr::IsRunning())
+ return;
+
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpPointlightRaster);
+ CSprite::InitSpriteBuffer();
+
for(i = 0; i < NumLights; i++){
if(aLights[i].fogType != FOG_NORMAL && aLights[i].fogType != FOG_ALWAYS)
continue;
@@ -221,7 +242,7 @@ CPointLights::RenderFogEffect(void)
if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){
float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x2000;
float size = FogSizes[r>>1];
- CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * size, spriteh * size,
aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,
intensity, 1/spriteCoors.z, rotation, 255);
@@ -233,9 +254,8 @@ CPointLights::RenderFogEffect(void)
}
}else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS){
- if(CWorld::ProcessVerticalLine(aLights[i].coors, aLights[i].coors.z - 20.0f,
- point, entity, true, false, false, false, true, false, nil)){
-
+ float groundZ;
+ if(ProcessVerticalLineUsingCache(aLights[i].coors, &groundZ)){
xmin = aLights[i].coors.x - FOG_AREA_RADIUS;
ymin = aLights[i].coors.y - FOG_AREA_RADIUS;
xmax = aLights[i].coors.x + FOG_AREA_RADIUS;
@@ -266,11 +286,11 @@ CPointLights::RenderFogEffect(void)
// more intensity the closer to light source
intensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS);
- CVector fogcoors(xi, yi, point.point.z + 1.6f);
+ CVector fogcoors(xi, yi, groundZ + 1.6f);
if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){
float rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x4000;
float size = FogSizes[r>>1];
- CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * size, spriteh * size,
aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,
intensity, 1/spriteCoors.z, rotation, 255);
@@ -282,4 +302,27 @@ CPointLights::RenderFogEffect(void)
}
}
}
+
+ CSprite::FlushSpriteBuffer();
+}
+
+bool
+CPointLights::ProcessVerticalLineUsingCache(CVector coors, float *groundZ)
+{
+ for(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++)
+ if(aCachedMapReads[i] == coors){
+ *groundZ = aCachedMapReadResults[i];
+ return true;
+ }
+
+ CColPoint point;
+ CEntity *entity;
+ if(CWorld::ProcessVerticalLine(coors, coors.z - 20.0f, point, entity, true, false, false, false, true, false, nil)){
+ aCachedMapReads[NextCachedValue] = coors;
+ aCachedMapReadResults[NextCachedValue] = point.point.z;
+ NextCachedValue = (NextCachedValue+1) % ARRAY_SIZE(aCachedMapReads);
+ *groundZ = point.point.z;
+ return true;
+ }
+ return false;
}
diff --git a/src/render/PointLights.h b/src/render/PointLights.h
index 9e94328f..827200b9 100644
--- a/src/render/PointLights.h
+++ b/src/render/PointLights.h
@@ -20,6 +20,9 @@ class CPointLights
public:
static int16 NumLights;
static CRegisteredPointLight aLights[NUMPOINTLIGHTS];
+ static CVector aCachedMapReads[32];
+ static float aCachedMapReadResults[32];
+ static int32 NextCachedValue;
enum {
LIGHT_POINT,
@@ -37,9 +40,11 @@ public:
FOG_ALWAYS
};
+ static void Init(void);
static void InitPerFrame(void);
static void AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows);
static float GenerateLightsAffectingObject(Const CVector *objCoors);
static void RemoveLightsAffectingObject(void);
static void RenderFogEffect(void);
+ static bool ProcessVerticalLineUsingCache(CVector coors, float *groundZ);
};
diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp
index 6120dfe2..687cc76b 100644
--- a/src/render/RenderBuffer.cpp
+++ b/src/render/RenderBuffer.cpp
@@ -5,7 +5,7 @@
int32 TempBufferVerticesStored;
int32 TempBufferIndicesStored;
-RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE];
+VertexBufferUnion TempVertexBuffer;
RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE];
int RenderBuffer::VerticesToBeStored;
diff --git a/src/render/RenderBuffer.h b/src/render/RenderBuffer.h
index 485d24e3..a0f3e7b9 100644
--- a/src/render/RenderBuffer.h
+++ b/src/render/RenderBuffer.h
@@ -9,10 +9,17 @@ public:
static void RenderStuffInBuffer(void);
};
-#define TEMPBUFFERVERTSIZE 256
+#define TEMPBUFFERVERTSIZE 512
#define TEMPBUFFERINDEXSIZE 1024
+struct VertexBufferUnion
+{
+ RwIm2DVertex im2d[TEMPBUFFERVERTSIZE];
+ RwIm3DVertex im3d[TEMPBUFFERVERTSIZE];
+};
+
extern int32 TempBufferVerticesStored;
extern int32 TempBufferIndicesStored;
-extern RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE];
+extern VertexBufferUnion TempVertexBuffer;
+#define TempBufferRenderVertices (TempVertexBuffer.im3d)
extern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; \ No newline at end of file
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 7ae29a2f..66c12dd9 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -7,6 +7,7 @@
#include "Ped.h"
#include "Vehicle.h"
#include "Heli.h"
+#include "Bike.h"
#include "Object.h"
#include "PathFind.h"
#include "Collision.h"
@@ -18,13 +19,13 @@
#include "Streaming.h"
#include "Shadows.h"
#include "PointLights.h"
+#include "Occlusion.h"
#include "Renderer.h"
-bool gbShowPedRoadGroups;
-bool gbShowCarRoadGroups;
+//--MIAMI: file done
+
bool gbShowCollisionPolys;
bool gbShowCollisionLines;
-bool gbShowCullZoneDebugStuff;
bool gbBigWhiteDebugLightSwitchedOn;
bool gbDontRenderBuildings;
@@ -146,8 +147,11 @@ CRenderer::RenderOneNonRoad(CEntity *e)
resetLights = e->SetupLighting();
- if(e->IsVehicle())
+ if(e->IsVehicle()){
+ // unfortunately can't use GetClump here
+ CVisibilityPlugins::SetupVehicleVariables((RpClump*)e->m_rwObject);
CVisibilityPlugins::InitAlphaAtomicList();
+ }
// Render Peds in vehicle before vehicle itself
if(e->IsVehicle()){
@@ -157,6 +161,7 @@ CRenderer::RenderOneNonRoad(CEntity *e)
for(i = 0; i < 8; i++)
if(veh->pPassengers[i] && veh->pPassengers[i]->m_nPedState == PED_DRIVING)
veh->pPassengers[i]->Render();
+ SetCullMode(rwCULLMODECULLNONE);
}
e->Render();
@@ -164,6 +169,7 @@ CRenderer::RenderOneNonRoad(CEntity *e)
e->bImBeingRendered = true;
CVisibilityPlugins::RenderAlphaAtomics();
e->bImBeingRendered = false;
+ SetCullMode(rwCULLMODECULLBACK);
}
e->RemoveLighting(resetLights);
@@ -184,38 +190,40 @@ CRenderer::RenderFirstPersonVehicle(void)
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
}
+inline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CSimpleModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->m_wetRoadReflection; }
+
void
CRenderer::RenderRoads(void)
{
int i;
- CTreadable *t;
+ CEntity *e;
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
DeActivateDirectional();
SetAmbientColours();
for(i = 0; i < ms_nNoOfVisibleEntities; i++){
- t = (CTreadable*)ms_aVisibleEntityPtrs[i];
- if(t->IsBuilding() && t->GetIsATreadable()){
-#ifndef MASTER
- if(gbShowCarRoadGroups || gbShowPedRoadGroups){
- int ind = 0;
- if(gbShowCarRoadGroups)
- ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_CAR][0]].group;
- if(gbShowPedRoadGroups)
- ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group;
- SetAmbientColoursToIndicateRoadGroup(ind);
- }
-#endif
- RenderOneRoad(t);
-#ifndef MASTER
- if(gbShowCarRoadGroups || gbShowPedRoadGroups)
- ReSetAmbientAndDirectionalColours();
-#endif
- }
+ e = ms_aVisibleEntityPtrs[i];
+ if(IsRoad(e))
+ RenderOneRoad(e);
}
}
+inline bool PutIntoSortedVehicleList(CVehicle *veh)
+{
+ if(veh->IsBoat()){
+ int mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
+ if(mode == CCam::MODE_WHEELCAM ||
+ mode == CCam::MODE_1STPERSON && TheCamera.GetLookDirection() != LOOKING_FORWARD && TheCamera.GetLookDirection() != LOOKING_BEHIND ||
+ CVisibilityPlugins::GetClumpAlpha(veh->GetClump()) != 255)
+ return false;
+ return true;
+ }else
+ return veh->bTouchingWater;
+}
+
void
CRenderer::RenderEverythingBarRoads(void)
{
@@ -224,17 +232,20 @@ CRenderer::RenderEverythingBarRoads(void)
CVector dist;
EntityInfo ei;
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
gSortedVehiclesAndPeds.Clear();
for(i = 0; i < ms_nNoOfVisibleEntities; i++){
e = ms_aVisibleEntityPtrs[i];
- if(e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable())
+ if(IsRoad(e))
continue;
if(e->IsVehicle() ||
e->IsPed() && CVisibilityPlugins::GetClumpAlpha((RpClump*)e->m_rwObject) != 255){
- if(e->IsVehicle() && ((CVehicle*)e)->IsBoat()){
+ if(e->IsVehicle() && PutIntoSortedVehicleList((CVehicle*)e)){
ei.ent = e;
dist = ms_vecCameraPosition - e->GetPosition();
ei.sort = dist.MagnitudeSqr();
@@ -252,34 +263,19 @@ CRenderer::RenderEverythingBarRoads(void)
}
void
-CRenderer::RenderVehiclesButNotBoats(void)
-{
- // This function doesn't do anything
- // because only boats are inserted into the list
- CLink<EntityInfo> *node;
-
- for(node = gSortedVehiclesAndPeds.tail.prev;
- node != &gSortedVehiclesAndPeds.head;
- node = node->prev){
- // only boats in this list
- CVehicle *v = (CVehicle*)node->item.ent;
- if(!v->IsBoat())
- RenderOneNonRoad(v);
- }
-}
-
-void
CRenderer::RenderBoats(void)
{
CLink<EntityInfo> *node;
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
+
for(node = gSortedVehiclesAndPeds.tail.prev;
node != &gSortedVehiclesAndPeds.head;
node = node->prev){
- // only boats in this list
CVehicle *v = (CVehicle*)node->item.ent;
- if(v->IsBoat())
- RenderOneNonRoad(v);
+ RenderOneNonRoad(v);
}
}
@@ -287,12 +283,22 @@ void
CRenderer::RenderFadingInEntities(void)
{
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
DeActivateDirectional();
SetAmbientColours();
CVisibilityPlugins::RenderFadingEntities();
}
void
+CRenderer::RenderFadingInUnderwaterEntities(void)
+{
+ DeActivateDirectional();
+ SetAmbientColours();
+ CVisibilityPlugins::RenderFadingUnderwaterEntities();
+}
+
+void
CRenderer::RenderCollisionLines(void)
{
int i;
@@ -340,7 +346,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
float dist;
bool request = true;
- if (mi->GetModelType() == MITYPE_TIME) {
+ if(mi->GetModelType() == MITYPE_TIME){
ti = (CTimeModelInfo*)mi;
other = ti->GetOtherTimeModel();
if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){
@@ -356,25 +362,35 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
request = false;
}
}else{
- if (mi->GetModelType() != MITYPE_SIMPLE) {
+ if(mi->GetModelType() != MITYPE_SIMPLE && mi->GetModelType() != MITYPE_WEAPON){
if(FindPlayerVehicle() == ent &&
- TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){
+ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON &&
+ !(FindPlayerVehicle()->IsBike() && ((CBike*)FindPlayerVehicle())->bWheelieCam)){
// Player's vehicle in first person mode
- if(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD ||
+ CVehicle *veh = (CVehicle*)ent;
+ int model = veh->GetModelIndex();
+ int direction = TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking;
+ if(direction == LOOKING_FORWARD ||
ent->GetModelIndex() == MI_RHINO ||
ent->GetModelIndex() == MI_COACH ||
- TheCamera.m_bInATunnelAndABigVehicle){
+ TheCamera.m_bInATunnelAndABigVehicle ||
+ direction == LOOKING_BEHIND && veh->pHandling->Flags & HANDLING_UNKNOWN){
ent->bNoBrightHeadLights = true;
- }else{
+ return VIS_OFFSCREEN;
+ }
+
+ if(direction != LOOKING_BEHIND ||
+ !veh->IsBoat() || model == MI_REEFER || model == MI_TROPIC || model == MI_PREDATOR || model == MI_SKIMMER){
m_pFirstPersonVehicle = (CVehicle*)ent;
ent->bNoBrightHeadLights = false;
+ return VIS_OFFSCREEN;
}
- return VIS_OFFSCREEN;
}
+
// All sorts of Clumps
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
- if(!ent->GetIsOnScreen())
+ if(!ent->GetIsOnScreen() || ent->IsEntityOccluded())
return VIS_OFFSCREEN;
if(ent->bDrawLast){
dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
@@ -384,22 +400,38 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
}
return VIS_VISIBLE;
}
- if(ent->IsObject() &&
- ((CObject*)ent)->ObjectCreatedBy == TEMP_OBJECT){
+ if(ent->bDontStream){
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
- return ent->GetIsOnScreen() ? VIS_VISIBLE : VIS_OFFSCREEN;
+ if(!ent->GetIsOnScreen() || ent->IsEntityOccluded())
+ return VIS_OFFSCREEN;
+ if(ent->bDrawLast){
+ dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
+ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ ent->bDistanceFade = false;
+ return VIS_INVISIBLE;
+ }
+ return VIS_VISIBLE;
}
}
// Simple ModelInfo
+ if(!IsAreaVisible(ent->m_area))
+ return VIS_INVISIBLE;
+
dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
- // This can only happen with multi-atomic models (e.g. railtracks)
- // but why do we bump up the distance? can only be fading...
- if(LOD_DISTANCE + STREAM_DISTANCE < dist && dist < mi->GetLargestLodDistance())
- dist = mi->GetLargestLodDistance();
+#ifndef FIX_BUGS
+ // Whatever this is supposed to do, it breaks fading for objects
+ // whose draw dist is > LOD_DISTANCE-FADE_DISTANCE, i.e. 280
+ // because decreasing dist here makes the object visible above LOD_DISTANCE
+ // before fading normally once below LOD_DISTANCE.
+ // aha! this must be a workaround for the fact that we're not taking
+ // the LOD multiplier into account here anywhere
+ if(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE)
+ dist += mi->GetLargestLodDistance() - LOD_DISTANCE;
+#endif
if(ent->IsObject() && ent->bRenderDamaged)
mi->m_isDamaged = true;
@@ -419,7 +451,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
- if(!ent->GetIsOnScreen()){
+ if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()){
mi->m_alpha = 255;
return VIS_OFFSCREEN;
}
@@ -431,9 +463,10 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
}
if(mi->m_drawLast || ent->bDrawLast){
- CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
- ent->bDistanceFade = false;
- return VIS_INVISIBLE;
+ if(CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist)){
+ ent->bDistanceFade = false;
+ return VIS_INVISIBLE;
+ }
}
return VIS_VISIBLE;
}
@@ -469,7 +502,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
- if(!ent->GetIsOnScreen()){
+ if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()){
mi->m_alpha = 255;
return VIS_OFFSCREEN;
}else{
@@ -482,19 +515,32 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
int32
CRenderer::SetupBigBuildingVisibility(CEntity *ent)
{
- CSimpleModelInfo *mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());
+ CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex);
CTimeModelInfo *ti;
int32 other;
- if (mi->GetModelType() == MITYPE_TIME) {
- ti = (CTimeModelInfo*)mi;
+ if(!IsAreaVisible(ent->m_area))
+ return VIS_INVISIBLE;
+
+ bool request = true;
+ if(mi->GetModelType() == MITYPE_TIME){
+ ti = (CTimeModelInfo*)mi;
other = ti->GetOtherTimeModel();
- // Hide objects not in time range if possible
- if(CANTIMECULL)
- if(!CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff()))
+ if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){
+ // don't fade in, or between time objects
+ if(CANTIMECULL)
+ ti->m_alpha = 255;
+ }else{
+ // Hide if possible
+ if(CANTIMECULL){
+ ent->DeleteRwObject();
return VIS_INVISIBLE;
- // Draw like normal
- } else if (mi->GetModelType() == MITYPE_VEHICLE)
+ }
+ // can't cull, so we'll try to draw this one, but don't request
+ // it since what we really want is the other one.
+ request = false;
+ }
+ }else if(mi->GetModelType() == MITYPE_VEHICLE)
return ent->IsVisible() ? VIS_VISIBLE : VIS_INVISIBLE;
float dist = (ms_vecCameraPosition-ent->GetPosition()).Magnitude();
@@ -503,7 +549,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
// Find out whether to draw below near distance.
// This is only the case if there is a non-LOD which is either not
// loaded or not completely faded in yet.
- if(dist < mi->GetNearDistance() && dist < LOD_DISTANCE + STREAM_DISTANCE){
+ if(dist < mi->GetNearDistance() && dist < LOD_DISTANCE){
// No non-LOD or non-LOD is completely visible.
if(nonLOD == nil ||
nonLOD->GetRwObject() && nonLOD->m_alpha == 255)
@@ -511,7 +557,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
// But if it is a time object, we'd rather draw the wrong
// non-LOD than the right LOD.
- if (nonLOD->GetModelType() == MITYPE_TIME) {
+ if(nonLOD->GetModelType() == MITYPE_TIME){
ti = (CTimeModelInfo*)nonLOD;
other = ti->GetOtherTimeModel();
if(other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject())
@@ -519,7 +565,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
}
}
- RpAtomic *a = mi->GetAtomicFromDistance(dist);
+ RpAtomic *a = mi->GetFirstAtomicFromDistance(dist);
if(a){
if(ent->m_rwObject == nil)
ent->CreateRwObject();
@@ -530,8 +576,18 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
// that of an atomic for another draw distance.
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- if(!ent->IsVisibleComplex())
+ mi->IncreaseAlpha();
+ if(!ent->IsVisibleComplex() || ent->IsEntityOccluded()){
+ mi->m_alpha = 255;
return VIS_INVISIBLE;
+ }
+
+ if(mi->m_alpha != 255){
+ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ ent->bDistanceFade = true;
+ return VIS_INVISIBLE;
+ }
+
if(mi->m_drawLast){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = false;
@@ -547,10 +603,14 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
// get faded atomic
- a = mi->GetAtomicFromDistance(dist - FADE_DISTANCE);
+ a = mi->GetFirstAtomicFromDistance(dist - FADE_DISTANCE);
if(a == nil){
- ent->DeleteRwObject();
- return VIS_INVISIBLE;
+ if(ent->bStreamBIGBuilding && dist-STREAM_DISTANCE < mi->GetLodDistance(0) && request){
+ return ent->GetIsOnScreen() ? VIS_STREAMME : VIS_INVISIBLE;
+ }else{
+ ent->DeleteRwObject();
+ return VIS_INVISIBLE;
+ }
}
// Fade...
@@ -560,14 +620,21 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- if(ent->IsVisibleComplex())
- CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ mi->IncreaseAlpha();
+ if(!ent->IsVisibleComplex() || ent->IsEntityOccluded()){
+ mi->m_alpha = 255;
+ return VIS_INVISIBLE;
+ }
+ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ ent->bDistanceFade = true;
return VIS_INVISIBLE;
}
void
CRenderer::ConstructRenderList(void)
{
+ COcclusion::ProcessBeforeRendering();
+
ms_nNoOfVisibleEntities = 0;
ms_nNoOfInVisibleEntities = 0;
ms_vecCameraPosition = TheCamera.GetPosition();
@@ -627,6 +694,15 @@ CRenderer::ScanWorld(void)
CVisibilityPlugins::InitAlphaEntityList();
CWorld::AdvanceCurrentScanCode();
+ // unused
+ static CVector prevPos;
+ static CVector prevFwd;
+ static bool smallMovement;
+ smallMovement = (TheCamera.GetPosition() - prevPos).MagnitudeSqr() < SQR(4.0f) &&
+ DotProduct(TheCamera.GetForward(), prevFwd) > 0.98f;
+ prevPos = TheCamera.GetPosition();
+ prevFwd = TheCamera.GetForward();
+
if(cammatrix->at.z > 0.0f){
// looking up, bottom corners are further away
vectors[CORNER_LOD_LEFT] = vectors[CORNER_FAR_BOTLEFT] * LOD_DISTANCE/f;
@@ -672,6 +748,7 @@ CRenderer::ScanWorld(void)
for(int y = y1; y <= y2; y++)
ScanSectorList(CWorld::GetSector(x1, y)->m_lists);
}else{
+#ifdef GTA_TRAIN
CVehicle *train = FindPlayerTrain();
if(train && train->GetPosition().z < 0.0f){
poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);
@@ -681,7 +758,9 @@ CRenderer::ScanWorld(void)
poly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x);
poly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y);
ScanSectorPoly(poly, 3, ScanSectorList_Subway);
- }else{
+ }else
+#endif
+ {
if(f > LOD_DISTANCE){
// priority
poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);
@@ -709,16 +788,8 @@ CRenderer::ScanWorld(void)
poly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y);
ScanSectorPoly(poly, 3, ScanSectorList);
}
-#ifdef NO_ISLAND_LOADING
- ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL));
- ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_COMMERCIAL));
- ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_SUBURBAN));
-#else
- #ifdef FIX_BUGS
- if (CCollision::ms_collisionInMemory != LEVEL_GENERIC)
- #endif
- ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory));
-#endif
+
+ ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel));
ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC));
}
}
@@ -750,6 +821,7 @@ CRenderer::RequestObjectsInFrustum(void)
cammatrix = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
CWorld::AdvanceCurrentScanCode();
+ ms_vecCameraPosition = TheCamera.GetPosition();
if(cammatrix->at.z > 0.0f){
// looking up, bottom corners are further away
@@ -967,11 +1039,26 @@ CRenderer::ScanBigBuildingList(CPtrList &list)
{
CPtrNode *node;
CEntity *ent;
+ int vis;
+ int f = CTimer::GetFrameCounter() & 3;
for(node = list.first; node; node = node->next){
ent = (CEntity*)node->item;
- if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE)
+ if(ent->bOffscreen || (ent->m_randomSeed&3) != f){
+ ent->bOffscreen = true;
+ vis = SetupBigBuildingVisibility(ent);
+ }else
+ vis = VIS_VISIBLE;
+ switch(vis){
+ case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ ent->bOffscreen = false;
+ break;
+ case VIS_STREAMME:
+ if(!CStreaming::ms_disableStreaming)
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ break;
+ }
}
}
@@ -991,35 +1078,30 @@ CRenderer::ScanSectorList(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
+ ent->bOffscreen = false;
- if(IsEntityCullZoneVisible(ent))
- switch(SetupEntityVisibility(ent)){
- case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
- break;
- case VIS_INVISIBLE:
- if(!IsGlass(ent->GetModelIndex()))
- break;
- // fall through
- case VIS_OFFSCREEN:
- dx = ms_vecCameraPosition.x - ent->GetPosition().x;
- dy = ms_vecCameraPosition.y - ent->GetPosition().y;
- if(dx > -65.0f && dx < 65.0f &&
- dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
- ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
- break;
- case VIS_STREAMME:
- if(!CStreaming::ms_disableStreaming)
- if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ switch(SetupEntityVisibility(ent)){
+ case VIS_VISIBLE:
+ ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ break;
+ case VIS_INVISIBLE:
+ if(!IsGlass(ent->GetModelIndex()))
break;
- }
- else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
+ // fall through
+ case VIS_OFFSCREEN:
+ ent->bOffscreen = true;
+ dx = ms_vecCameraPosition.x - ent->GetPosition().x;
+ dy = ms_vecCameraPosition.y - ent->GetPosition().y;
+ if(dx > -30.0f && dx < 30.0f &&
+ dy > -30.0f && dy < 30.0f &&
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
+ ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
+ break;
+ case VIS_STREAMME:
if(!CStreaming::ms_disableStreaming)
- if(SetupEntityVisibility(ent) == VIS_STREAMME)
- if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ break;
}
}
}
@@ -1041,41 +1123,38 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
+ ent->bOffscreen = false;
- if(IsEntityCullZoneVisible(ent))
- switch(SetupEntityVisibility(ent)){
- case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
- break;
- case VIS_INVISIBLE:
- if(!IsGlass(ent->GetModelIndex()))
- break;
- // fall through
- case VIS_OFFSCREEN:
- dx = ms_vecCameraPosition.x - ent->GetPosition().x;
- dy = ms_vecCameraPosition.y - ent->GetPosition().y;
- if(dx > -65.0f && dx < 65.0f &&
- dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
- ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
- break;
- case VIS_STREAMME:
- if(!CStreaming::ms_disableStreaming){
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
- if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)
- m_loadingPriority = true;
- }
+ switch(SetupEntityVisibility(ent)){
+ case VIS_VISIBLE:
+ ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ break;
+ case VIS_INVISIBLE:
+ if(!IsGlass(ent->GetModelIndex()))
break;
+ // fall through
+ case VIS_OFFSCREEN:
+ ent->bOffscreen = true;
+ dx = ms_vecCameraPosition.x - ent->GetPosition().x;
+ dy = ms_vecCameraPosition.y - ent->GetPosition().y;
+ if(dx > -30.0f && dx < 30.0f &&
+ dy > -30.0f && dy < 30.0f &&
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
+ ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
+ break;
+ case VIS_STREAMME:
+ if(!CStreaming::ms_disableStreaming){
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)
+ m_loadingPriority = true;
}
- else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
- if(!CStreaming::ms_disableStreaming)
- if(SetupEntityVisibility(ent) == VIS_STREAMME)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ break;
}
}
}
}
+#ifdef GTA_TRAIN
void
CRenderer::ScanSectorList_Subway(CPtrList *lists)
{
@@ -1092,15 +1171,17 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
+ ent->bOffscreen = false;
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
break;
case VIS_OFFSCREEN:
+ ent->bOffscreen = true;
dx = ms_vecCameraPosition.x - ent->GetPosition().x;
dy = ms_vecCameraPosition.y - ent->GetPosition().y;
- if(dx > -65.0f && dx < 65.0f &&
- dy > -65.0f && dy < 65.0f &&
+ if(dx > -30.0f && dx < 30.0f &&
+ dy > -30.0f && dy < 30.0f &&
ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
break;
@@ -1108,6 +1189,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists)
}
}
}
+#endif
void
CRenderer::ScanSectorList_RequestModels(CPtrList *lists)
@@ -1124,8 +1206,7 @@ CRenderer::ScanSectorList_RequestModels(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
- if(IsEntityCullZoneVisible(ent))
- if(ShouldModelBeStreamed(ent))
+ if(ShouldModelBeStreamed(ent, ms_vecCameraPosition))
CStreaming::RequestModel(ent->GetModelIndex(), 0);
}
}
@@ -1160,70 +1241,29 @@ CRenderer::SortBIGBuildingsForSectorList(CPtrList *list)
}
bool
-CRenderer::ShouldModelBeStreamed(CEntity *ent)
+CRenderer::ShouldModelBeStreamed(CEntity *ent, const CVector &campos)
{
- CSimpleModelInfo *mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());
- float dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
+ if(!IsAreaVisible(ent->m_area))
+ return false;
+ CTimeModelInfo *mi = (CTimeModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());
+ if(mi->GetModelType() == MITYPE_TIME)
+ if(!CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))
+ return false;
+ float dist = (ent->GetPosition() - campos).Magnitude();
if(mi->m_noFade)
return dist - STREAM_DISTANCE < mi->GetLargestLodDistance();
else
return dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance();
}
-bool
-CRenderer::IsEntityCullZoneVisible(CEntity *ent)
-{
- CPed *ped;
- CObject *obj;
-
- if(ent->bZoneCulled)
- return false;
-
- switch(ent->GetType()){
- case ENTITY_TYPE_VEHICLE:
- return IsVehicleCullZoneVisible(ent);
- case ENTITY_TYPE_PED:
- ped = (CPed*)ent;
- if (ped->bInVehicle) {
- if (ped->m_pMyVehicle)
- return IsVehicleCullZoneVisible(ped->m_pMyVehicle);
- else
- return true;
- }
- return !(ped->m_pCurSurface && ped->m_pCurSurface->bZoneCulled2);
- case ENTITY_TYPE_OBJECT:
- obj = (CObject*)ent;
- if(!obj->IsStatic())
- return true;
- return !(obj->m_pCurSurface && obj->m_pCurSurface->bZoneCulled2);
- default: break;
- }
- return true;
-}
-
-bool
-CRenderer::IsVehicleCullZoneVisible(CEntity *ent)
-{
- CVehicle *v = (CVehicle*)ent;
- switch(v->GetStatus()) {
- case STATUS_SIMPLE:
- case STATUS_PHYSICS:
- case STATUS_ABANDONED:
- case STATUS_WRECKED:
- return !(v->m_pCurGroundEntity && v->m_pCurGroundEntity->bZoneCulled2);
- default: break;
- }
- return true;
-}
-
void
CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset)
{
- if(ent->bRenderScorched){
- WorldReplaceScorchedLightsWithNormal(Scene.world);
- return;
+ if(!ent->bRenderScorched){
+ CPointLights::RemoveLightsAffectingObject();
+ if(reset)
+ ReSetAmbientAndDirectionalColours();
}
- CPointLights::RemoveLightsAffectingObject();
- if(reset)
- ReSetAmbientAndDirectionalColours();
+ SetAmbientColours();
+ DeActivateDirectional();
}
diff --git a/src/render/Renderer.h b/src/render/Renderer.h
index 362741e3..e9f82078 100644
--- a/src/render/Renderer.h
+++ b/src/render/Renderer.h
@@ -2,11 +2,8 @@
class CEntity;
-extern bool gbShowPedRoadGroups;
-extern bool gbShowCarRoadGroups;
extern bool gbShowCollisionPolys;
extern bool gbShowCollisionLines;
-extern bool gbShowCullZoneDebugStuff;
extern bool gbBigWhiteDebugLightSwitchedOn;
extern bool gbDontRenderBuildings;
@@ -38,8 +35,8 @@ public:
static void RenderRoads(void);
static void RenderFadingInEntities(void);
+ static void RenderFadingInUnderwaterEntities(void);
static void RenderEverythingBarRoads(void);
- static void RenderVehiclesButNotBoats(void);
static void RenderBoats(void);
static void RenderOneRoad(CEntity *);
static void RenderOneNonRoad(CEntity *);
@@ -63,9 +60,7 @@ public:
static void SortBIGBuildings(void);
static void SortBIGBuildingsForSectorList(CPtrList *list);
- static bool ShouldModelBeStreamed(CEntity *ent);
- static bool IsEntityCullZoneVisible(CEntity *ent);
- static bool IsVehicleCullZoneVisible(CEntity *ent);
+ static bool ShouldModelBeStreamed(CEntity *ent, const CVector &campos);
static void RemoveVehiclePedLights(CEntity *ent, bool reset);
};
diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp
index bfd50c07..dada2439 100644
--- a/src/render/Rubbish.cpp
+++ b/src/render/Rubbish.cpp
@@ -8,17 +8,18 @@
#include "World.h"
#include "Vehicle.h"
#include "ZoneCull.h"
+#include "Stats.h"
#include "TxdStore.h"
#include "RenderBuffer.h"
#include "Rubbish.h"
-#define RUBBISH_MAX_DIST (18.0f)
-#define RUBBISH_FADE_DIST (16.5f)
+//--MIAMI: file done
+
+#define RUBBISH_MAX_DIST (23.0f)
+#define RUBBISH_FADE_DIST (20.0f)
RwTexture *gpRubbishTexture[4];
RwImVertexIndex RubbishIndexList[6];
-RwImVertexIndex RubbishIndexList2[6]; // unused
-RwIm3DVertex RubbishVertices[4];
bool CRubbish::bRubbishInvisible;
int CRubbish::RubbishVisibility;
COneSheet CRubbish::aSheets[NUM_RUBBISH_SHEETS];
@@ -52,12 +53,16 @@ CRubbish::Render(void)
{
int type;
+ if(RubbishVisibility == 0)
+ return;
+
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
for(type = 0; type < 4; type++){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type]));
+ if(type < 3 || CStats::PamphletMissionPassed)
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type]));
TempBufferIndicesStored = 0;
TempBufferVerticesStored = 0;
@@ -69,7 +74,7 @@ CRubbish::Render(void)
if(sheet->m_state == 0)
continue;
- uint32 alpha = 128;
+ uint32 alpha = 100;
CVector pos;
if(sheet->m_state == 1){
pos = sheet->m_basePos;
@@ -82,7 +87,7 @@ CRubbish::Render(void)
float t = (float)(CTimer::GetTimeInMilliseconds() - sheet->m_moveStart)/sheet->m_moveDuration;
float f1 = sheet->m_isVisible ? 1.0f-t : 0.0f;
float f2 = sheet->m_targetIsVisible ? t : 0.0f;
- alpha = 128 * (f1+f2);
+ alpha = 100 * (f1+f2);
}
}
@@ -92,17 +97,27 @@ CRubbish::Render(void)
alpha -= alpha*(camDist-RUBBISH_FADE_DIST)/(RUBBISH_MAX_DIST-RUBBISH_FADE_DIST);
alpha = (RubbishVisibility*alpha)/256;
- float vx = Sin(sheet->m_angle) * 0.4f;
- float vy = Cos(sheet->m_angle) * 0.4f;
+ float vx1, vy1, vx2, vy2;
+ if(type == 0 || type == 1){
+ vx1 = 0.9f*Sin(sheet->m_angle);
+ vy1 = 0.9f*Cos(sheet->m_angle);
+ vx2 = 0.3f*Cos(sheet->m_angle);
+ vy2 = -0.3f*Sin(sheet->m_angle);
+ }else{
+ vx1 = 0.3f*Sin(sheet->m_angle);
+ vy1 = 0.3f*Cos(sheet->m_angle);
+ vx2 = 0.3f*Cos(sheet->m_angle);
+ vy2 = -0.3f*Sin(sheet->m_angle);
+ }
int v = TempBufferVerticesStored;
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx, pos.y + vy, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx1 + vx2, pos.y + vy1 + vy2, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x + vx1 - vx2, pos.y + vy1 - vy2, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x - vx1 + vx2, pos.y - vy1 + vy2, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx1 - vx2, pos.y - vy1 - vy2, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], 255, 255, 255, alpha);
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x - vy, pos.y + vx, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], 255, 255, 255, alpha);
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x + vy, pos.y - vx, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], 255, 255, 255, alpha);
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx, pos.y - vy, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], 255, 255, 255, alpha);
RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], 0.0f);
RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], 0.0f);
@@ -373,24 +388,6 @@ CRubbish::Init(void)
EndMoversList.m_next = nil;
EndMoversList.m_prev = &StartMoversList;
- // unused
- RwIm3DVertexSetU(&RubbishVertices[0], 0.0f);
- RwIm3DVertexSetV(&RubbishVertices[0], 0.0f);
- RwIm3DVertexSetU(&RubbishVertices[1], 1.0f);
- RwIm3DVertexSetV(&RubbishVertices[1], 0.0f);
- RwIm3DVertexSetU(&RubbishVertices[2], 0.0f);
- RwIm3DVertexSetV(&RubbishVertices[2], 1.0f);
- RwIm3DVertexSetU(&RubbishVertices[3], 1.0f);
- RwIm3DVertexSetV(&RubbishVertices[3], 1.0f);
-
- // unused
- RubbishIndexList2[0] = 0;
- RubbishIndexList2[1] = 2;
- RubbishIndexList2[2] = 1;
- RubbishIndexList2[3] = 1;
- RubbishIndexList2[4] = 2;
- RubbishIndexList2[5] = 3;
-
RubbishIndexList[0] = 0;
RubbishIndexList[1] = 1;
RubbishIndexList[2] = 2;
@@ -414,19 +411,11 @@ void
CRubbish::Shutdown(void)
{
RwTextureDestroy(gpRubbishTexture[0]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[0] = nil;
-#endif
RwTextureDestroy(gpRubbishTexture[1]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[1] = nil;
-#endif
RwTextureDestroy(gpRubbishTexture[2]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[2] = nil;
-#endif
RwTextureDestroy(gpRubbishTexture[3]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[3] = nil;
-#endif
}
diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h
index 37f895f3..5a4e479b 100644
--- a/src/render/Rubbish.h
+++ b/src/render/Rubbish.h
@@ -53,3 +53,5 @@ public:
static void Init(void);
static void Shutdown(void);
};
+
+extern RwTexture *gpRubbishTexture[4];
diff --git a/src/render/ShadowCamera.cpp b/src/render/ShadowCamera.cpp
new file mode 100644
index 00000000..f69c234f
--- /dev/null
+++ b/src/render/ShadowCamera.cpp
@@ -0,0 +1,549 @@
+#include "common.h"
+#include "rwcore.h"
+#include "ShadowCamera.h"
+#include "RwHelper.h"
+
+#define TEXELOFFSET 0.5f
+
+RpAtomic *ShadowRenderCallBack(RpAtomic *atomic, void *data)
+{
+ RpAtomicCallBackRender savedCB = RpAtomicGetRenderCallBack(atomic);
+ RpAtomicSetRenderCallBack(atomic, AtomicDefaultRenderCallBack);
+ RpAtomicRender(atomic);
+ RpAtomicSetRenderCallBack(atomic, savedCB);
+ return atomic;
+}
+
+CShadowCamera::CShadowCamera()
+{
+ m_pCamera = nil;
+ m_pTexture = nil;
+}
+
+CShadowCamera::~CShadowCamera()
+{
+ Destroy();
+}
+
+void
+CShadowCamera::Destroy()
+{
+ if ( m_pCamera )
+ {
+ RwRaster *raster;
+ RwFrame *frame;
+
+ frame = RwCameraGetFrame(m_pCamera);
+
+ if ( frame )
+ {
+ RwCameraSetFrame(m_pCamera, nil);
+ RwFrameDestroy(frame);
+ }
+
+ raster = RwCameraGetZRaster(m_pCamera);
+ if ( raster )
+ {
+ RwCameraSetZRaster(m_pCamera, nil);
+ RwRasterDestroy(raster);
+ }
+
+ raster = RwCameraGetRaster(m_pCamera);
+ if ( raster )
+ {
+ RwCameraSetRaster(m_pCamera, nil);
+ RwRasterDestroy(raster);
+ }
+
+ if ( m_pTexture )
+ {
+ RwTextureSetRaster(m_pTexture, nil);
+ RwTextureDestroy(m_pTexture);
+ m_pTexture = nil;
+ }
+
+ RwCameraDestroy(m_pCamera);
+ m_pCamera = nil;
+ }
+ return;
+}
+
+RwCamera *
+CShadowCamera::Create(int32 rasterSize)
+{
+ int32 size = 1 << rasterSize;
+
+ m_pCamera = RwCameraCreate();
+ ASSERT(m_pCamera != nil);
+
+ if ( m_pCamera )
+ {
+ RwCameraSetFrame(m_pCamera, RwFrameCreate());
+
+ if( RwCameraGetFrame(m_pCamera) )
+ {
+ RwRaster *zRaster = RwRasterCreate(size, size, 0, rwRASTERTYPEZBUFFER);
+ ASSERT(zRaster != nil);
+
+ if ( zRaster )
+ {
+ RwCameraSetZRaster(m_pCamera, zRaster);
+
+ RwRaster *raster = RwRasterCreate(size, size, 0, rwRASTERTYPECAMERATEXTURE);
+ ASSERT(raster != nil);
+
+ if ( raster )
+ {
+ RwCameraSetRaster(m_pCamera, raster);
+ m_pTexture = RwTextureCreate(raster);
+ ASSERT(m_pTexture != nil);
+
+ if ( m_pTexture )
+ {
+ RwTextureSetAddressing(m_pTexture, rwTEXTUREADDRESSCLAMP);
+ RwTextureSetFilterMode(m_pTexture, rwFILTERLINEAR);
+ RwCameraSetProjection(m_pCamera, rwPARALLEL);
+ return (m_pCamera);
+ }
+ }
+ }
+ }
+ }
+
+ Destroy();
+
+ return (nil);
+}
+
+RwCamera *
+CShadowCamera::SetFrustum(float objectRadius)
+{
+ ASSERT(m_pCamera != nil);
+
+ RwV2d vw;
+
+ RwCameraSetFarClipPlane (m_pCamera, 2.0f * objectRadius);
+ RwCameraSetNearClipPlane(m_pCamera, 0.001f * objectRadius);
+
+ vw.x = objectRadius;
+ vw.y = objectRadius;
+ RwCameraSetViewWindow(m_pCamera, &vw);
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::SetLight(RpLight *light)
+{
+ ASSERT(light != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwFrame *camFrame = RwCameraGetFrame(m_pCamera);
+ RwMatrix *camMatrix = RwFrameGetMatrix(camFrame);
+ RwFrame *lightFrame = RpLightGetFrame(light);
+ RwMatrix *lightMatrix = RwFrameGetMatrix(lightFrame);
+
+ *RwMatrixGetRight(camMatrix) = *RwMatrixGetRight(lightMatrix);
+ *RwMatrixGetUp(camMatrix) = *RwMatrixGetUp(lightMatrix);
+ *RwMatrixGetAt(camMatrix) = *RwMatrixGetAt(lightMatrix);
+
+ RwMatrixUpdate(camMatrix);
+ RwFrameUpdateObjects(camFrame);
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::SetCenter(RwV3d *center)
+{
+ ASSERT(center != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwFrame *camFrame = RwCameraGetFrame(m_pCamera);
+ RwMatrix *camMatrix = RwFrameGetMatrix(camFrame);
+
+ *RwMatrixGetPos(camMatrix) = *center;
+
+ RwV3dIncrementScaled(RwMatrixGetPos(camMatrix), RwMatrixGetAt(camMatrix), -0.5f * RwCameraGetFarClipPlane(m_pCamera));
+
+ RwMatrixUpdate(camMatrix);
+ RwFrameUpdateObjects(camFrame);
+ RwFrameOrthoNormalize(camFrame);
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::Update(RpClump *clump)
+{
+ ASSERT(clump != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwUInt32 flags;
+ RpGeometry *geometry;
+
+ RwRGBA bgColor = { 255, 255, 255, 0 };
+
+ RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ geometry = RpAtomicGetGeometry(GetFirstAtomic(clump));
+ ASSERT(geometry != nil);
+
+ flags = RpGeometryGetFlags(geometry);
+
+ RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT
+ |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR));
+
+ RpClumpForAllAtomics(clump, ShadowRenderCallBack, nil);
+
+ RpGeometrySetFlags(geometry, flags);
+
+ InvertRaster();
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::Update(RpAtomic *atomic)
+{
+ ASSERT(atomic != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwUInt32 flags;
+ RpGeometry *geometry;
+
+ RwRGBA bgColor = { 255, 255, 255, 0 };
+
+ RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ geometry = RpAtomicGetGeometry(atomic);
+ ASSERT(geometry != nil);
+ flags = RpGeometryGetFlags(geometry);
+
+ RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT
+ |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYNORMALS));
+
+ ShadowRenderCallBack(atomic, nil);
+
+ RpGeometrySetFlags(geometry, flags);
+
+ InvertRaster();
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return m_pCamera;
+}
+
+void
+CShadowCamera::InvertRaster()
+{
+ ASSERT(m_pCamera != nil);
+
+ RwIm2DVertex vx[4];
+ float crw, crh;
+ RwRaster *raster;
+ float recipZ;
+
+ raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ crw = (float)RwRasterGetWidth(raster);
+ crh = (float)RwRasterGetHeight(raster);
+
+ recipZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwIm2DVertexSetScreenX (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[0], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX (&vx[1], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[1], crh);
+ RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX (&vx[2], crw);
+ RwIm2DVertexSetScreenY (&vx[2], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX (&vx[3], crw);
+ RwIm2DVertexSetScreenY (&vx[3], crh);
+ RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255);
+
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+
+ RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+}
+
+RwRaster *
+CShadowCamera::MakeGradientRaster()
+{
+ ASSERT(m_pCamera != nil);
+
+ RwIm2DVertex vx[2];
+
+ if ( !m_pCamera )
+ return nil;
+
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float width = (float)RwRasterGetWidth(raster);
+ float height = (float)RwRasterGetHeight(raster);
+
+ if ( height < 1 )
+ return nil;
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)rwFILTERNAFILTERMODE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT);
+
+ float color = 255.0f;
+ float step = (-191.0f / height);
+
+ for ( int32 i = 0; i < height; i++ )
+ {
+ RwIm2DVertexSetScreenX (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[0], i);
+ RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);
+ RwIm2DVertexSetIntRGBA (&vx[0], (uint32)color, (uint32)color, (uint32)color, (uint32)color);
+
+ RwIm2DVertexSetScreenX (&vx[1], width - 1);
+ RwIm2DVertexSetScreenY (&vx[1], i);
+ RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);
+ RwIm2DVertexSetIntRGBA (&vx[1], (uint32)color, (uint32)color, (uint32)color, (uint32)color);
+
+ RwIm2DRenderLine(vx, 2, 0, 1);
+
+ color += step;
+ }
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEGOURAUD);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return raster;
+}
+
+RwRaster *
+CShadowCamera::RasterResample(RwRaster *dstRaster)
+{
+ ASSERT(dstRaster != nil);
+ ASSERT(m_pCamera != nil);
+
+ if ( !m_pCamera )
+ return nil;
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float) RwRasterGetWidth(raster);
+ float uvOffset = TEXELOFFSET / size;
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster);
+
+ Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, uvOffset);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return raster;
+}
+
+RwRaster *
+CShadowCamera::RasterBlur(RwRaster *dstRaster, int32 numPasses)
+{
+ ASSERT(dstRaster != nil);
+ ASSERT(m_pCamera != nil);
+
+ if ( !m_pCamera )
+ return nil;
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float) RwRasterGetWidth(dstRaster);
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ for (int i = 0; i < numPasses; i++ )
+ {
+ RwCameraSetRaster(m_pCamera, raster);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ if ( i == 0 )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ }
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster);
+ Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 1.0f / size);
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ RwCameraSetRaster(m_pCamera, dstRaster);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster);
+ Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0);
+
+ if ( i == numPasses - 1 )
+ {
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ }
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+ }
+
+ RwCameraSetRaster(m_pCamera, raster);
+
+ return dstRaster;
+}
+
+RwRaster *
+CShadowCamera::RasterGradient(RwRaster *dstRaster)
+{
+ ASSERT(dstRaster != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float)RwRasterGetWidth(dstRaster);
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwCameraSetRaster(m_pCamera, dstRaster);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDSRCCOLOR);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster);
+
+ Im2DRenderQuad(0, 0, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ RwCameraSetRaster(m_pCamera, raster);
+
+ return dstRaster;
+}
+
+RwRaster *CShadowCamera::DrawOutlineBorder(RwRGBA const& color)
+{
+ ASSERT(m_pCamera != nil);
+
+ RwIm2DVertex vx[4];
+ RwImVertexIndex ix[5];
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float)RwRasterGetWidth(raster) - 1.0f;
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwIm2DVertexSetScreenX (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[0], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);
+
+ RwIm2DVertexSetScreenX (&vx[1], size);
+ RwIm2DVertexSetScreenY (&vx[1], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[1], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);
+
+ RwIm2DVertexSetScreenX (&vx[2], size);
+ RwIm2DVertexSetScreenY (&vx[2], size);
+ RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[2], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);
+
+ RwIm2DVertexSetScreenX (&vx[3], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[3], size);
+ RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[3], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);
+
+ ix[0] = 0;
+ ix[4] = 0;
+ ix[1] = 1;
+ ix[2] = 2;
+ ix[3] = 3;
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, vx, 4, ix, 5);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return raster;
+} \ No newline at end of file
diff --git a/src/render/ShadowCamera.h b/src/render/ShadowCamera.h
new file mode 100644
index 00000000..a2149db7
--- /dev/null
+++ b/src/render/ShadowCamera.h
@@ -0,0 +1,54 @@
+#pragma once
+
+
+class CShadowCamera
+{
+public:
+ RwCamera *m_pCamera;
+ RwTexture *m_pTexture;
+
+ CShadowCamera();
+ ~CShadowCamera();
+
+ RwCamera *Create(int32 rasterSize);
+ void Destroy();
+
+ RwCamera *SetFrustum(float objectRadius);
+ RwCamera *SetLight(RpLight *light);
+ RwCamera *SetCenter(RwV3d *center);
+
+ RwCamera *Update(RpClump *clump);
+ RwCamera *Update(RpAtomic *atomic);
+
+ void InvertRaster();
+
+ RwRaster* GetRwRenderRaster()
+ {
+ return RwCameraGetRaster(m_pCamera);
+ }
+
+ // ShadowRasterRender(RwV2d *)
+ // ApplyAlphaMapToRaster(void)
+
+ RwRaster *MakeGradientRaster();
+
+ RwTexture *GetRwRenderTexture()
+ {
+ return m_pTexture;
+ }
+
+ RwRaster* GetRwZRaster()
+ {
+ return RwCameraGetZRaster(m_pCamera);
+ }
+
+ RwRaster *RasterResample(RwRaster *dstRaster);
+ RwRaster *RasterBlur(RwRaster *dstRaster, int32 numPasses);
+ RwRaster *RasterGradient(RwRaster *dstRaster);
+ RwRaster *DrawOutlineBorder(RwRGBA const& color);
+
+ RwCamera *GetRwCamera()
+ {
+ return m_pCamera;
+ }
+}; \ No newline at end of file
diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp
index 8c892be3..5bb6a734 100644
--- a/src/render/Shadows.cpp
+++ b/src/render/Shadows.cpp
@@ -7,6 +7,7 @@
#include "Timecycle.h"
#include "CutsceneMgr.h"
#include "Automobile.h"
+#include "Bike.h"
#include "Ped.h"
#include "PlayerPed.h"
#include "World.h"
@@ -18,7 +19,12 @@
#endif
#include "PointLights.h"
#include "SpecialFX.h"
+#include "Script.h"
+#include "TimeStep.h"
#include "Shadows.h"
+#include "CutsceneObject.h"
+#include "CutsceneShadow.h"
+#include "Clock.h"
#ifdef DEBUGMENU
SETTWEAKPATH("Shadows");
@@ -30,6 +36,8 @@ RwImVertexIndex ShadowIndexList[24];
RwTexture *gpShadowCarTex;
RwTexture *gpShadowPedTex;
RwTexture *gpShadowHeliTex;
+RwTexture *gpShadowBikeTex;
+RwTexture *gpShadowBaronTex;
RwTexture *gpShadowExplosionTex;
RwTexture *gpShadowHeadLightsTex;
RwTexture *gpOutline1Tex;
@@ -37,7 +45,6 @@ RwTexture *gpOutline2Tex;
RwTexture *gpOutline3Tex;
RwTexture *gpBloodPoolTex;
RwTexture *gpReflectionTex;
-RwTexture *gpGoalMarkerTex;
RwTexture *gpWalkDontTex;
RwTexture *gpCrackedGlassTex;
RwTexture *gpPostShadowTex;
@@ -59,37 +66,39 @@ CShadows::Init(void)
int32 slut = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slut);
- gpShadowCarTex = RwTextureRead("shad_car", NULL);
- gpShadowPedTex = RwTextureRead("shad_ped", NULL);
- gpShadowHeliTex = RwTextureRead("shad_heli", NULL);
- gpShadowExplosionTex = RwTextureRead("shad_exp", NULL);
- gpShadowHeadLightsTex = RwTextureRead("headlight", NULL);
- gpOutline1Tex = RwTextureRead("outline_64", NULL);
- gpOutline2Tex = RwTextureRead("outline2_64", NULL);
- gpOutline3Tex = RwTextureRead("outline3_64", NULL);
- gpBloodPoolTex = RwTextureRead("bloodpool_64", NULL);
- gpReflectionTex = RwTextureRead("reflection01", NULL);
- gpGoalMarkerTex = RwTextureRead("goal", NULL);
- gpWalkDontTex = RwTextureRead("walk_dont", NULL);
- gpCrackedGlassTex = RwTextureRead("wincrack_32", NULL);
- gpPostShadowTex = RwTextureRead("lamp_shad_64", NULL);
+ gpShadowCarTex = RwTextureRead("shad_car", nil);
+ gpShadowPedTex = RwTextureRead("shad_ped", nil);
+ gpShadowHeliTex = RwTextureRead("shad_heli", nil);
+ gpShadowBikeTex = RwTextureRead("shad_bike", nil);
+ gpShadowBaronTex = RwTextureRead("shad_rcbaron", nil);
+ gpShadowExplosionTex = RwTextureRead("shad_exp", nil);
+ gpShadowHeadLightsTex = RwTextureRead("headlight", nil);
+ gpOutline1Tex = RwTextureRead("outline_64", nil);
+ gpOutline2Tex = RwTextureRead("outline2_64", nil);
+ gpOutline3Tex = RwTextureRead("outline3_64", nil);
+ gpBloodPoolTex = RwTextureRead("bloodpool_64", nil);
+ gpReflectionTex = RwTextureRead("reflection01", nil);
+ gpWalkDontTex = RwTextureRead("walk_dont", nil);
+ gpCrackedGlassTex = RwTextureRead("wincrack_32", nil);
+ gpPostShadowTex = RwTextureRead("lamp_shad_64", nil);
CTxdStore::PopCurrentTxd();
- ASSERT(gpShadowCarTex != NULL);
- ASSERT(gpShadowPedTex != NULL);
- ASSERT(gpShadowHeliTex != NULL);
- ASSERT(gpShadowExplosionTex != NULL);
- ASSERT(gpShadowHeadLightsTex != NULL);
- ASSERT(gpOutline1Tex != NULL);
- ASSERT(gpOutline2Tex != NULL);
- ASSERT(gpOutline3Tex != NULL);
- ASSERT(gpBloodPoolTex != NULL);
- ASSERT(gpReflectionTex != NULL);
- ASSERT(gpGoalMarkerTex != NULL);
- ASSERT(gpWalkDontTex != NULL);
- ASSERT(gpCrackedGlassTex != NULL);
- ASSERT(gpPostShadowTex != NULL);
+ ASSERT(gpShadowCarTex != nil);
+ ASSERT(gpShadowPedTex != nil);
+ ASSERT(gpShadowHeliTex != nil);
+ ASSERT(gpShadowBikeTex != nil);
+ ASSERT(gpShadowBaronTex != nil);
+ ASSERT(gpShadowExplosionTex != nil);
+ ASSERT(gpShadowHeadLightsTex != nil);
+ ASSERT(gpOutline1Tex != nil);
+ ASSERT(gpOutline2Tex != nil);
+ ASSERT(gpOutline3Tex != nil);
+ ASSERT(gpBloodPoolTex != nil);
+ ASSERT(gpReflectionTex != nil);
+ ASSERT(gpWalkDontTex != nil);
+ ASSERT(gpCrackedGlassTex != nil);
+ ASSERT(gpPostShadowTex != nil);
ShadowIndexList[0] = 0;
@@ -128,7 +137,7 @@ CShadows::Init(void)
for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
{
aStaticShadows[i].m_nId = 0;
- aStaticShadows[i].m_pPolyBunch = NULL;
+ aStaticShadows[i].m_pPolyBunch = nil;
}
pEmptyBunchList = &aPolyBunches[0];
@@ -136,7 +145,7 @@ CShadows::Init(void)
for ( int32 i = 0; i < MAX_POLYBUNCHES; i++ )
{
if ( i == MAX_POLYBUNCHES - 1 )
- aPolyBunches[i].m_pNext = NULL;
+ aPolyBunches[i].m_pNext = nil;
else
aPolyBunches[i].m_pNext = &aPolyBunches[i + 1];
}
@@ -150,24 +159,27 @@ CShadows::Init(void)
void
CShadows::Shutdown(void)
{
- ASSERT(gpShadowCarTex != NULL);
- ASSERT(gpShadowPedTex != NULL);
- ASSERT(gpShadowHeliTex != NULL);
- ASSERT(gpShadowExplosionTex != NULL);
- ASSERT(gpShadowHeadLightsTex != NULL);
- ASSERT(gpOutline1Tex != NULL);
- ASSERT(gpOutline2Tex != NULL);
- ASSERT(gpOutline3Tex != NULL);
- ASSERT(gpBloodPoolTex != NULL);
- ASSERT(gpReflectionTex != NULL);
- ASSERT(gpGoalMarkerTex != NULL);
- ASSERT(gpWalkDontTex != NULL);
- ASSERT(gpCrackedGlassTex != NULL);
- ASSERT(gpPostShadowTex != NULL);
+ ASSERT(gpShadowCarTex != nil);
+ ASSERT(gpShadowPedTex != nil);
+ ASSERT(gpShadowHeliTex != nil);
+ ASSERT(gpShadowBikeTex != nil);
+ ASSERT(gpShadowBaronTex != nil);
+ ASSERT(gpShadowExplosionTex != nil);
+ ASSERT(gpShadowHeadLightsTex != nil);
+ ASSERT(gpOutline1Tex != nil);
+ ASSERT(gpOutline2Tex != nil);
+ ASSERT(gpOutline3Tex != nil);
+ ASSERT(gpBloodPoolTex != nil);
+ ASSERT(gpReflectionTex != nil);
+ ASSERT(gpWalkDontTex != nil);
+ ASSERT(gpCrackedGlassTex != nil);
+ ASSERT(gpPostShadowTex != nil);
RwTextureDestroy(gpShadowCarTex);
RwTextureDestroy(gpShadowPedTex);
RwTextureDestroy(gpShadowHeliTex);
+ RwTextureDestroy(gpShadowBikeTex);
+ RwTextureDestroy(gpShadowBaronTex);
RwTextureDestroy(gpShadowExplosionTex);
RwTextureDestroy(gpShadowHeadLightsTex);
RwTextureDestroy(gpOutline1Tex);
@@ -175,7 +187,6 @@ CShadows::Shutdown(void)
RwTextureDestroy(gpOutline3Tex);
RwTextureDestroy(gpBloodPoolTex);
RwTextureDestroy(gpReflectionTex);
- RwTextureDestroy(gpGoalMarkerTex);
RwTextureDestroy(gpWalkDontTex);
RwTextureDestroy(gpCrackedGlassTex);
RwTextureDestroy(gpPostShadowTex);
@@ -187,8 +198,8 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, uint32 nTime, float fScale)
{
- ASSERT(pTexture != NULL);
- ASSERT(pPosn != NULL);
+ ASSERT(pTexture != nil);
+ ASSERT(pPosn != nil);
// find free slot
@@ -215,36 +226,39 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo
}
}
-void
+bool
CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();
- if ( SQR(fDrawDistance) > fDistToCamSqr)
+ if ( SQR(fDrawDistance) > fDistToCamSqr || fDrawDistance == 0.0f )
{
- float fDistToCam = Sqrt(fDistToCamSqr);
-
- if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
+ if ( fDrawDistance != 0.0f )
{
- //fDistToCam == 0 -> 4
- //fDistToCam == fDrawDistance -> 0
- float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))));
+ float fDistToCam = Sqrt(fDistToCamSqr);
- nIntensity = (int32)(nIntensity * fMult);
- nRed = (int32)(nRed * fMult);
- nGreen = (int32)(nGreen * fMult);
- nBlue = (int32)(nBlue * fMult);
+ if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
+ {
+ //fDistToCam == 0 -> 4
+ //fDistToCam == fDrawDistance -> 0
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))));
+
+ nIntensity = (int32)(nIntensity * fMult);
+ nRed = (int32)(nRed * fMult);
+ nGreen = (int32)(nGreen * fMult);
+ nBlue = (int32)(nBlue * fMult);
+ }
}
int32 nSlot;
nSlot = 0;
- while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != NULL) )
+ while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != nil) )
nSlot++;
if ( nSlot < MAX_STATICSHADOWS )
@@ -263,8 +277,10 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_fScale = fScale;
aStaticShadows[nSlot].m_bTemp = bTempShadow;
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+
+ return true;
}
- else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f
+ else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f
&& Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < 0.05f
&& Abs(pPosn->z - aStaticShadows[nSlot].m_vecPosn.z) < 2.0f
@@ -284,6 +300,8 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_fScale = fScale;
aStaticShadows[nSlot].m_bTemp = bTempShadow;
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+
+ return true;
}
else
{
@@ -308,12 +326,14 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
GeneratePolysForStaticShadow(nSlot);
+
+ return aStaticShadows[nSlot].m_pPolyBunch != nil;
}
}
else
{
nSlot = 0;
- while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != NULL )
+ while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != nil )
nSlot++;
if ( nSlot != MAX_STATICSHADOWS )
@@ -337,9 +357,13 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
GeneratePolysForStaticShadow(nSlot);
+
+ return aStaticShadows[nSlot].m_pPolyBunch != nil;
}
}
}
+
+ return true;
}
void
@@ -347,7 +371,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
switch ( ShadowTexture )
{
@@ -361,7 +385,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -371,7 +395,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -381,7 +405,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -391,7 +415,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowHeliTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -401,7 +425,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowHeadLightsTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -410,8 +434,8 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
{
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpBloodPoolTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
- nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ nIntensity, nRed, 150, 0,
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -424,36 +448,39 @@ void
CShadows::StoreShadowToBeRendered(uint8 ShadowType, RwTexture *pTexture, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
- float fZDistance, bool bDrawOnWater, float fScale)
+ float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings)
{
- ASSERT(pTexture != NULL);
- ASSERT(pPosn != NULL);
+ ASSERT(pTexture != nil);
+ ASSERT(pPosn != nil);
if ( ShadowsStoredToBeRendered < MAX_STOREDSHADOWS )
{
- asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType;
- asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY;
- asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity;
- asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed;
- asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen;
- asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue;
- asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance;
- asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater;
- asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale;
+ asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType;
+ asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue;
+ asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnBuildings = bDrawOnBuildings;
+ asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale;
+ asShadowsStored[ShadowsStoredToBeRendered].m_pCutsceneShadow = pShadow;
ShadowsStoredToBeRendered++;
}
}
+
void
-CShadows::StoreShadowForCar(CAutomobile *pCar)
+CShadows::StoreShadowForVehicle(CVehicle *pCar, VEH_SHD_TYPE type)
{
- ASSERT(pCar != NULL);
+ ASSERT(pCar != nil);
if ( CTimeCycle::GetShadowStrength() != 0 )
{
@@ -463,7 +490,22 @@ CShadows::StoreShadowForCar(CAutomobile *pCar)
if ( CCutsceneMgr::IsRunning() )
fDistToCamSqr /= SQR(TheCamera.LODDistMultiplier) * 4.0f;
- float fDrawDistance = 18.0f;
+ float fDrawDistance;
+ switch ( type )
+ {
+ case VEH_SHD_TYPE_SEAPLANE:
+ case VEH_SHD_TYPE_RCPLANE:
+ fDrawDistance = 144.0f;
+ break;
+
+ case VEH_SHD_TYPE_HELI:
+ fDrawDistance = 144.0f;
+ break;
+
+ default:
+ fDrawDistance = 18.0f;
+ break;
+ }
if ( fDistToCamSqr < SQR(fDrawDistance) )
{
@@ -471,46 +513,202 @@ CShadows::StoreShadowForCar(CAutomobile *pCar)
//fDistToCam == 0 -> 4
//fDistToCam == fDrawDistance -> 0
- float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))) );
+ float fMult = 1.0f - (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))) / (fDrawDistance*(1.0f/4.0f));
int32 nColorStrength;
if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
- nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ nColorStrength = (int32)(fMult * CTimeCycle::GetShadowStrength());
else
nColorStrength = CTimeCycle::GetShadowStrength();
-
+
+
float fVehicleHeight = pCar->GetColModel()->boundingBox.GetSize().y;
float fVehicleWidth = pCar->GetColModel()->boundingBox.GetSize().x;
-
- if ( pCar->GetModelIndex() == MI_DODO )
+
+ float size = 1.0f;
+
+ if ( pCar->GetModelIndex() == MI_HUNTER )
+ {
+ fVehicleWidth *= 3.0f;
+ fVehicleHeight *= 1.4f;
+ size *= 0.5f;
+ }
+ else if ( pCar->GetModelIndex() == MI_ANGEL )
+ {
+ fVehicleHeight = fVehicleHeight * 1.5f;
+ size = 0.03f;
+ }
+ else if ( pCar->GetModelIndex() == MI_SEASPAR )
+ {
+ fVehicleWidth *= 3.0f;
+ fVehicleHeight *= 1.4f;
+ size *= 0.5f;
+ }
+ else if ( pCar->GetModelIndex() == MI_PIZZABOY || pCar->GetModelIndex() == MI_PCJ600 || pCar->GetModelIndex() == MI_FAGGIO )
+ {
+ fVehicleHeight *= 1.2f;
+ size = 0.05f;
+ }
+ else if ( pCar->GetModelIndex() == MI_FREEWAY )
+ {
+ fVehicleHeight *= 1.5f;
+ size = 0.03f;
+ }
+ else if ( pCar->GetModelIndex() == MI_RCRAIDER )
+ {
+ fVehicleHeight *= 1.5f;
+ fVehicleWidth *= 2.0f;
+ size = 0.2f;
+ }
+ else if ( pCar->GetModelIndex() == MI_SANCHEZ )
+ {
+ fVehicleHeight *= 1.5f;
+ size = 0.03f;
+ }
+ else if ( pCar->GetModelIndex() == MI_SPARROW || pCar->GetModelIndex() == MI_MAVERICK || pCar->GetModelIndex() == MI_VCNMAV || pCar->GetModelIndex() == MI_POLMAV )
+ {
+ fVehicleWidth *= 3.0f;
+ fVehicleHeight *= 1.4f;
+ size *= 0.5f;
+ }
+ else if ( pCar->GetModelIndex() == MI_RCGOBLIN )
+ {
+ fVehicleHeight *= 1.5f;
+ fVehicleWidth *= 2.0f;
+ size = 0.2f;
+ }
+ else if ( pCar->GetModelIndex() == MI_DODO )
{
fVehicleHeight *= 0.9f;
fVehicleWidth *= 0.4f;
}
+
+ CarPos.x -= pCar->GetForward().x * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size);
+ CarPos.y -= pCar->GetForward().y * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size);
+
+ RwTexture *tex = gpShadowCarTex;
+ switch ( type )
+ {
+ case VEH_SHD_TYPE_BIKE:
+ {
+ float wheelZ = Abs(((CBike*)pCar)->m_fLeanLRAngle);
+ float mul = 5.092958f * wheelZ + 1.0f;
+ if (pCar->GetStatus() == STATUS_PHYSICS)
+ {
+ float z = pCar->GetRight().z;
+ if (z > 0.6f)
+ mul += 4.0f * z;
+ }
+ fVehicleWidth *= mul;
+ tex = gpShadowBikeTex;
+ break;
+ }
+
+ case VEH_SHD_TYPE_HELI:
+ tex = gpShadowHeliTex;
+ break;
+
+ case VEH_SHD_TYPE_SEAPLANE:
+ nColorStrength = CTimeCycle::GetShadowStrength();
+ tex = gpShadowBaronTex;
+ break;
+
+ case VEH_SHD_TYPE_RCPLANE:
+ tex = gpShadowBaronTex;
+ fVehicleHeight *= 1.5f;
+ fVehicleWidth *= 2.2f;
+ break;
+
+ case VEH_SHD_TYPE_CAR:
+ tex = gpShadowCarTex;
+ break;
+ }
+
+ float frontx = pCar->GetForward().x;
+ float fronty = pCar->GetForward().y;
+ float sidex = pCar->GetRight().x;
+ float sidey = pCar->GetRight().y;
+
+ switch ( type )
+ {
+ case VEH_SHD_TYPE_BIKE:
+ if ( Abs(pCar->GetRight().z) > 0.6f )
+ {
+ sidex = pCar->GetUp().x;
+ sidey = pCar->GetUp().y;
+ }
+ break;
+
+ case VEH_SHD_TYPE_HELI:
+ if ( Abs(pCar->GetRight().z) > 0.57f )
+ {
+ sidex = pCar->GetUp().x;
+ sidey = pCar->GetUp().y;
+ }
+ if ( Abs(pCar->GetForward().z) > 0.57f )
+ {
+ frontx = pCar->GetUp().x;
+ fronty = pCar->GetUp().y;
+ }
+ break;
+ }
- CarPos.x -= pCar->GetForward().x * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y);
- CarPos.y -= pCar->GetForward().y * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y);
-
- if ( pCar->GetUp().z > 0.0f )
+ bool bDrawOnBuildings = false;
+ if ( pCar->GetModelIndex() == MI_RCBANDIT
+ || pCar->GetModelIndex() == MI_RCBARON
+ || pCar->GetModelIndex() == MI_RCRAIDER
+ || pCar->GetModelIndex() == MI_RCGOBLIN
+ || pCar == FindPlayerVehicle() )
{
- StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos,
- pCar->GetForward().x * (fVehicleHeight / 2),
- pCar->GetForward().y * (fVehicleHeight / 2),
- pCar->GetRight().x * (fVehicleWidth / 2),
- pCar->GetRight().y * (fVehicleWidth / 2),
- nColorStrength, nColorStrength, nColorStrength, nColorStrength,
- 4.5f, false, 1.0f);
+ bDrawOnBuildings = true;
+ }
+
+ if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.1f || bDrawOnBuildings )
+ {
+ if ( pCar->GetUp().z > 0.0f )
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ sidex * (fVehicleWidth / 2),
+ sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, false, 1.0f, nil, bDrawOnBuildings);
+ }
+ else
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ -sidex * (fVehicleWidth / 2),
+ -sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, false, 1.0f, nil, bDrawOnBuildings);
+ }
}
else
{
- StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos,
- pCar->GetForward().x * (fVehicleHeight / 2),
- pCar->GetForward().y * (fVehicleHeight / 2),
- -pCar->GetRight().x * (fVehicleWidth / 2),
- -pCar->GetRight().y * (fVehicleWidth / 2),
- nColorStrength, nColorStrength, nColorStrength, nColorStrength,
- 4.5f, false, 1.0f);
+ if ( pCar->GetUp().z > 0.0f )
+ {
+ StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ sidex * (fVehicleWidth / 2),
+ sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, 1.0f, 0.0f, false, 0.1f);
+ }
+ else
+ {
+ StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ -sidex * (fVehicleWidth / 2),
+ -sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, 1.0f, 0.0f, false, 0.1f);
+ }
}
}
}
@@ -521,8 +719,8 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture,
float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fMaxViewAngle)
{
- ASSERT(pCar != NULL);
- ASSERT(pPosn != NULL);
+ ASSERT(pCar != nil);
+ ASSERT(pPosn != nil);
float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();
@@ -550,31 +748,131 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture,
nBlue = (int32)(nBlue * fMult);
}
- StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn,
- fFrontX, fFrontY,
- fSideX, fSideY,
- 128, nRed, nGreen, nBlue,
- 6.0f, false, 1.0f);
+ if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.4f || pCar == FindPlayerVehicle() )
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ 128, nRed, nGreen, nBlue,
+ 6.0f, false, 1.0f,
+ nil, pCar == FindPlayerVehicle());
+ }
+ else
+ {
+ StoreStaticShadow((uintptr)pCar + nID, SHADOWTYPE_ADDITIVE, pTexture, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ 128, nRed, nGreen, nBlue,
+ 6.0f, 1.0f, 27.0f,
+ false, 0.4f);
+ }
+ }
+ }
+}
+
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+void
+StoreShadowForCutscenePedObject(CPed *pObject, float fDisplacementX, float fDisplacementY,
+ float fFrontX, float fFrontY, float fSideX, float fSideY)
+{
+ ASSERT(pObject != nil);
+
+ CCutsceneShadow *shadow = pObject->m_pRTShadow;
+
+ if ( shadow == nil )
+ return;
+
+ if ( !shadow->IsInitialized() )
+ return;
+
+ CVector pos = pObject->GetPosition();
+
+ float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ float fDrawDistance = 100.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )
+ {
+ if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f)));
+ int32 nColorStrength;
+
+ if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) )
+ nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ else
+ nColorStrength = CTimeCycle::GetShadowStrength();
+
+ int32 color = int32(nColorStrength * 0.8f);
+
+ pos.x += fDisplacementX;
+ pos.y += fDisplacementY;
+
+ RwTexture *texture = shadow->GetShadowRwTexture();
+ ASSERT(texture);
+ RwRGBA bordercolor = {0, 0, 0, 0};
+ shadow->DrawBorderAroundTexture(bordercolor);
+
+ pos.x -= fDisplacementX;
+ pos.y -= fDisplacementY;
+
+ float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes
+ +60*CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f));
+
+ RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true);
+ ASSERT(frame);
+ CVector at(RwFrameGetMatrix(frame)->at);
+ at.Normalise();
+
+ CShadows::CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY);
+
+ pos.x -= 2.5f * fDisplacementX;
+ pos.y -= 2.5f * fDisplacementY;
+
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos,
+ fFrontX * 1.5f, fFrontY * 1.5f,
+ fSideX * 1.5f, fSideY * 1.5f,
+ color, color, color, color,
+ 4.0f, false, 1.0f, shadow, false);
}
}
}
+#endif
+
void
CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacementY,
float fFrontX, float fFrontY, float fSideX, float fSideY)
{
- ASSERT(pPed != NULL);
+ ASSERT(pPed != nil);
if ( pPed->bIsVisible )
{
if ( !(pPed->bInVehicle && pPed->m_nPedState != PED_DRAG_FROM_CAR && pPed->m_nPedState != PED_EXIT_CAR) )
{
if ( CTimeCycle::GetShadowStrength() != 0 )
+ {
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+ CCutsceneShadow *pShadow = pPed->m_pRTShadow;
+
+ if (pShadow)
+ {
+ if (pShadow->IsInitialized())
+ pShadow->UpdateForCutscene();
+ ::StoreShadowForCutscenePedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY);
+ }
+
+ return;
+#endif
+
StoreShadowForPedObject(pPed,
fDisplacementX, fDisplacementY,
fFrontX, fFrontY,
fSideX, fSideY);
+ }
}
}
}
@@ -582,8 +880,8 @@ CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacemen
void
CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, float fDisplacementY,
float fFrontX, float fFrontY, float fSideX, float fSideY)
-{
- ASSERT(pPedObject != NULL);
+{
+ ASSERT(pPedObject != nil);
CVector PedPos = pPedObject->GetPosition();
@@ -591,7 +889,7 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo
float fDrawDistance = 26.0f;
- if ( fDistToCamSqr < SQR(fDrawDistance*0.5f)/*?*/ )
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )
{
if ( pPedObject == FindPlayerPed() || TheCamera.IsSphereVisible(PedPos, 2.0f) != false )
{
@@ -614,7 +912,80 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo
fFrontX, fFrontY,
fSideX, fSideY,
nColorStrength, nColorStrength, nColorStrength, nColorStrength,
- 4.0f, false, 1.0f);
+ 4.0f, false, 1.0f, nil, pPedObject == FindPlayerPed());
+ }
+ }
+}
+
+
+void
+CShadows::StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY,
+ float fFrontX, float fFrontY, float fSideX, float fSideY)
+{
+#ifdef DISABLE_CUTSCENE_SHADOWS
+ return;
+#endif
+ ASSERT(pObject != nil);
+
+ CCutsceneShadow *shadow = pObject->m_pShadow;
+
+ if ( shadow == nil )
+ return;
+
+ if ( !shadow->IsInitialized() )
+ return;
+
+ CVector pos = pObject->GetPosition();
+
+ float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ float fDrawDistance = 100.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )
+ {
+ if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f)));
+ int32 nColorStrength;
+
+ if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) )
+ nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ else
+ nColorStrength = CTimeCycle::GetShadowStrength();
+
+ int32 color = int32(nColorStrength * 0.8f);
+
+ pos.x += fDisplacementX;
+ pos.y += fDisplacementY;
+
+ RwTexture *texture = shadow->GetShadowRwTexture();
+ ASSERT(texture);
+ RwRGBA bordercolor = {0, 0, 0, 0};
+ shadow->DrawBorderAroundTexture(bordercolor);
+
+ pos.x -= fDisplacementX;
+ pos.y -= fDisplacementY;
+
+ float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes+60*
+ CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f));
+
+ RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true);
+ ASSERT(frame);
+ CVector at(RwFrameGetMatrix(frame)->at);
+ at.Normalise();
+
+ CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY);
+
+ pos.x -= 2.5f * fDisplacementX;
+ pos.y -= 2.5f * fDisplacementY;
+
+ StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos,
+ fFrontX * 1.5f, fFrontY * 1.5f,
+ fSideX * 1.5f, fSideY * 1.5f,
+ color, color, color, color,
+ 4.0f, false, 1.0f, shadow, false);
}
}
}
@@ -622,14 +993,15 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo
void
CShadows::StoreShadowForTree(CEntity *pTree)
{
- ASSERT(pTree != NULL);
+ ASSERT(pTree != nil);
}
+
void
CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ,
float fPoleHeight, float fPoleWidth, uint32 nID)
{
- ASSERT(pPole != NULL);
+ ASSERT(pPole != nil);
if ( CTimeCycle::GetShadowStrength() != 0 )
{
@@ -684,6 +1056,7 @@ CShadows::SetRenderModeForShadowType(uint8 ShadowType)
}
}
+
void
CShadows::RenderStoredShadows(void)
{
@@ -692,17 +1065,20 @@ CShadows::RenderStoredShadows(void)
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSCLAMP);
+
for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ )
asShadowsStored[i].m_nFlags.bRendered = false;
+
for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ )
{
if ( !asShadowsStored[i].m_nFlags.bRendered )
{
SetRenderModeForShadowType(asShadowsStored[i].m_ShadowType);
- ASSERT(asShadowsStored[i].m_pTexture != NULL);
+ ASSERT(asShadowsStored[i].m_pTexture != nil);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(asShadowsStored[i].m_pTexture));
@@ -734,39 +1110,112 @@ CShadows::RenderStoredShadows(void)
{
CSector *pCurSector = CWorld::GetSector(x, y);
- ASSERT(pCurSector != NULL);
-
- CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
- fStartX, fStartY,
- fEndX, fEndY,
- &shadowPos,
- asShadowsStored[j].m_vecFront.x,
- asShadowsStored[j].m_vecFront.y,
- asShadowsStored[j].m_vecSide.x,
- asShadowsStored[j].m_vecSide.y,
- asShadowsStored[j].m_nIntensity,
- asShadowsStored[j].m_nRed,
- asShadowsStored[j].m_nGreen,
- asShadowsStored[j].m_nBlue,
- asShadowsStored[j].m_fZDistance,
- asShadowsStored[j].m_fScale,
- NULL);
-
- CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
- fStartX, fStartY,
- fEndX, fEndY,
- &shadowPos,
- asShadowsStored[j].m_vecFront.x,
- asShadowsStored[j].m_vecFront.y,
- asShadowsStored[j].m_vecSide.x,
- asShadowsStored[j].m_vecSide.y,
- asShadowsStored[j].m_nIntensity,
- asShadowsStored[j].m_nRed,
- asShadowsStored[j].m_nGreen,
- asShadowsStored[j].m_nBlue,
- asShadowsStored[j].m_fZDistance,
- asShadowsStored[j].m_fScale,
- NULL);
+ ASSERT(pCurSector != nil);
+
+ if ( asShadowsStored[j].m_pCutsceneShadow )
+ {
+ CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil,
+ asShadowsStored[j].m_pCutsceneShadow);
+
+ CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil,
+ asShadowsStored[j].m_pCutsceneShadow);
+ }
+ else if ( asShadowsStored[j].m_nFlags.bDrawOnBuildings )
+ {
+ CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+
+ CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+ }
+ else
+ {
+ CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+
+ CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+ }
}
}
@@ -776,16 +1225,17 @@ CShadows::RenderStoredShadows(void)
RenderBuffer::RenderStuffInBuffer();
}
-
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSWRAP);
ShadowsStoredToBeRendered = 0;
}
+
void
CShadows::RenderStaticShadows(void)
{
@@ -811,19 +1261,19 @@ CShadows::RenderStaticShadows(void)
// optimization trick, render all shadows with same renderstate and texture
for ( int32 j = i; j < MAX_STATICSHADOWS; j++ )
{
- if ( aStaticShadows[j].m_pPolyBunch != NULL
+ if ( aStaticShadows[j].m_pPolyBunch != nil
&& aStaticShadows[i].m_nType == aStaticShadows[j].m_nType
&& aStaticShadows[i].m_pTexture == aStaticShadows[j].m_pTexture )
{
- for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != NULL; bunch = bunch->m_pNext )
+ for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != nil; bunch = bunch->m_pNext )
{
RwImVertexIndex *pIndexes;
RwIm3DVertex *pVerts;
RenderBuffer::StartStoring(3 * (bunch->m_nNumVerts - 2), bunch->m_nNumVerts, &pIndexes, &pVerts);
- ASSERT(pIndexes != NULL);
- ASSERT(pVerts != NULL);
+ ASSERT(pIndexes != nil);
+ ASSERT(pVerts != nil);
for ( int32 k = 0; k < bunch->m_nNumVerts; k++ )
{
@@ -857,6 +1307,7 @@ CShadows::RenderStaticShadows(void)
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
}
+
void
CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
{
@@ -883,7 +1334,7 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
{
CSector *pCurSector = CWorld::GetSector(x, y);
- ASSERT(pCurSector != NULL);
+ ASSERT(pCurSector != nil);
CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
fStartX, fStartY,
@@ -914,50 +1365,109 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
}
}
+
void
CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, float fScale, CPolyBunch **ppPolyBunch)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
CPtrNode *pNode = PtrList.first;
CRect Bound;
- while ( pNode != NULL )
+ while ( pNode != nil )
{
CEntity *pEntity = (CEntity *)pNode->item;
uint16 nScanCode = pEntity->m_scanCode;
pNode = pNode->next;
- ASSERT( pEntity != NULL );
+ ASSERT( pEntity != nil );
if ( nScanCode != CWorld::GetCurrentScanCode() )
{
- if ( pEntity->bUsesCollision && pEntity->IsBuilding() )
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if ( pEntity->bUsesCollision && !pEntity->m_flagE2 )
{
- pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+ if ( IsAreaVisible(pEntity->m_area) )
+ {
+ Bound = pEntity->GetBoundRect();
+
+ if ( fStartX < Bound.right
+ && fEndX > Bound.left
+ && fStartY < Bound.bottom
+ && fEndY > Bound.top )
+ {
+ if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
+ && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ {
+ CastShadowEntityXY(pEntity,
+ fStartX, fStartY,
+ fEndX, fEndY,
+ pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void
+CShadows::CastPlayerShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch)
+{
+ ASSERT(pPosn != nil);
+
+ CPtrNode *pNode = PtrList.first;
+
+ CRect Bound;
+
+ while ( pNode != nil )
+ {
+ CEntity *pEntity = (CEntity *)pNode->item;
+ uint16 nScanCode = pEntity->m_scanCode;
+ pNode = pNode->next;
- Bound = pEntity->GetBoundRect();
+ ASSERT( pEntity != nil );
- if ( fStartX < Bound.right
- && fEndX > Bound.left
- && fStartY < Bound.bottom
- && fEndY > Bound.top )
+ if ( nScanCode != CWorld::GetCurrentScanCode() )
+ {
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if ( pEntity->bUsesCollision )
+ {
+ if ( IsAreaVisible(pEntity->m_area) )
{
- if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
- && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ Bound = pEntity->GetBoundRect();
+
+ if ( fStartX < Bound.right
+ && fEndX > Bound.left
+ && fStartY < Bound.bottom
+ && fEndY > Bound.top )
{
- CastShadowEntity(pEntity,
- fStartX, fStartY,
- fEndX, fEndY,
- pPosn,
- fFrontX, fFrontY,
- fSideX, fSideY,
- nIntensity, nRed, nGreen, nBlue,
- fZDistance, fScale, ppPolyBunch);
+ if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
+ && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ {
+ CastShadowEntityXY(pEntity,
+ fStartX, fStartY,
+ fEndX, fEndY,
+ pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch);
+ }
}
}
}
@@ -965,21 +1475,74 @@ CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY,
}
}
+
void
-CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
+CShadows::CastCutsceneShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)
+{
+ ASSERT(pPosn != nil);
+ ASSERT(pShadow != nil);
+
+ CPtrNode *pNode = PtrList.first;
+
+ CRect Bound;
+
+ while ( pNode != nil )
+ {
+ CEntity *pEntity = (CEntity *)pNode->item;
+ uint16 nScanCode = pEntity->m_scanCode;
+ pNode = pNode->next;
+
+ ASSERT( pEntity != nil );
+
+ if ( nScanCode != CWorld::GetCurrentScanCode() )
+ {
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if ( pEntity->bUsesCollision )
+ {
+ if ( IsAreaVisible(pEntity->m_area) )
+ {
+ Bound = pEntity->GetBoundRect();
+
+ if ( fStartX < Bound.right
+ && fEndX > Bound.left
+ && fStartY < Bound.bottom
+ && fEndY > Bound.top )
+ {
+ if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
+ && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ {
+ CastShadowEntityXYZ(pEntity, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch, pShadow);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CShadows::CastShadowEntityXY(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, float fScale, CPolyBunch **ppPolyBunch)
-{
- ASSERT(pEntity != NULL);
- ASSERT(pPosn != NULL);
+{
+ ASSERT(pEntity != nil);
+ ASSERT(pPosn != nil);
static CVector List [20];
static CVector Texture[20];
static CVector Points [4];
CColModel *pCol = pEntity->GetColModel();
- ASSERT(pCol != NULL);
+ ASSERT(pCol != nil);
#ifndef MASTER
if ( gbPrintShite )
@@ -1025,14 +1588,14 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
for ( int32 i = 0; i < pCol->numTriangles; i++ )
{
CColTrianglePlane *pColTriPlanes = pCol->trianglePlanes;
- ASSERT(pColTriPlanes != NULL);
+ ASSERT(pColTriPlanes != nil);
CVector normal;
pColTriPlanes[i].GetNormal(normal);
if ( Abs(normal.z) > 0.1f )
{
CColTriangle *pColTri = pCol->triangles;
- ASSERT(pColTri != NULL);
+ ASSERT(pColTri != nil);
CVector PointA, PointB, PointC;
@@ -1432,12 +1995,12 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
}
- if ( ppPolyBunch != NULL )
+ if ( ppPolyBunch != nil )
{
- if ( pEmptyBunchList != NULL )
+ if ( pEmptyBunchList != nil )
{
CPolyBunch *pBunch = pEmptyBunchList;
- ASSERT(pBunch != NULL);
+ ASSERT(pBunch != nil);
pEmptyBunchList = pEmptyBunchList->m_pNext;
pBunch->m_pNext = *ppPolyBunch;
*ppPolyBunch = pBunch;
@@ -1462,8 +2025,8 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
RenderBuffer::StartStoring(3 * (numVerts3 - 2), numVerts3, &pIndexes, &pVerts);
- ASSERT(pIndexes != NULL);
- ASSERT(pVerts != NULL);
+ ASSERT(pIndexes != nil);
+ ASSERT(pVerts != nil);
for ( int32 j = 0; j < numVerts3; j++ )
@@ -1487,12 +2050,222 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
}
}
+
+typedef struct _ProjectionParam
+{
+ RwV3d at; /* Camera at vector */
+ RwMatrix invMatrix; /* Transforms to shadow camera space */
+ RwUInt8 shadowValue; /* Shadow opacity value */
+ RwBool fade; /* Shadow fades with distance */
+ RwUInt32 numIm3DBatch; /* Number of buffer flushes */
+ RwMatrix entityMatrix;
+}
+ProjectionParam;
+
+RwV3d *ShadowRenderTriangleCB(RwV3d *points, RwV3d *normal, ProjectionParam *param)
+{
+ RwV3d vIn[3];
+ RwV3d vShad[3];
+
+ RwV3dTransformPoints(&vIn[0], points, 3, &param->entityMatrix);
+
+ /*
+ * Reject backfacing triangles
+ * This reject the triangles parallel to the light as well
+ */
+ if (RwV3dDotProduct(normal, &param->at) > 0.0f)
+ {
+ return points;
+ }
+
+ RwV3dTransformPoints(&vShad[0], &vIn[0], 3, &param->invMatrix);
+
+ /*
+ * Reject triangles behind the camera (z test). Note that any world
+ * triangles lying in front of the camera but before the object may
+ * have a shadow applied. To minimize such artefacts, this test could
+ * be modified to use a specific value rather than 0.0f, perhaps
+ * to reject triangles behind the center plane of the object.
+ *
+ * Reject triangles that lie entirely outside the shadow texture range
+ * (x,y test).
+ */
+ if (((vShad[0].z < 0.0f) && (vShad[1].z < 0.0f)
+ && (vShad[2].z < 0.0f)) || ((vShad[0].x < 0.0f)
+ && (vShad[1].x < 0.0f)
+ && (vShad[2].x < 0.0f))
+ || ((vShad[0].x > 1.0f) && (vShad[1].x > 1.0f)
+ && (vShad[2].x > 1.0f)) || ((vShad[0].y < 0.0f)
+ && (vShad[1].y < 0.0f)
+ && (vShad[2].y < 0.0f))
+ || ((vShad[0].y > 1.0f) && (vShad[1].y > 1.0f)
+ && (vShad[2].y > 1.0f)))
+ {
+ return points;
+ }
+
+ RwIm3DVertex *imv = nil;
+ RwImVertexIndex *imi = nil;
+
+ RenderBuffer::StartStoring(3, 3, &imi, &imv);
+
+ /*
+ * Set the immediate mode vertices for this triangle
+ */
+
+ RwIm3DVertexSetPos(imv, vIn[0].x, vIn[0].y, vIn[0].z);
+ RwIm3DVertexSetPos(imv + 1, vIn[1].x, vIn[1].y, vIn[1].z);
+ RwIm3DVertexSetPos(imv + 2, vIn[2].x, vIn[2].y, vIn[2].z);
+
+ RwIm3DVertexSetU(imv, vShad[0].x);
+ RwIm3DVertexSetU(imv + 1, vShad[1].x);
+ RwIm3DVertexSetU(imv + 2, vShad[2].x);
+
+ RwIm3DVertexSetV(imv, vShad[0].y);
+ RwIm3DVertexSetV(imv + 1, vShad[1].y);
+ RwIm3DVertexSetV(imv + 2, vShad[2].y);
+
+ /*
+ * Do we fade out the shadow with distance?
+ */
+ if (param->fade)
+ {
+ RwReal fadeVal;
+ RwUInt8 val;
+
+ fadeVal = 1.0f - vShad[0].z * vShad[0].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv, val, val, val, val);
+
+ fadeVal = 1.0f - vShad[1].z * vShad[1].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv + 1, val, val, val, val);
+
+ fadeVal = 1.0f - vShad[2].z * vShad[2].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv + 2, val, val, val, val);
+ }
+ else
+ {
+ RwUInt8 val = param->shadowValue;
+
+ RwIm3DVertexSetRGBA(imv, val, val, val, val);
+ RwIm3DVertexSetRGBA(imv + 1, val, val, val, val);
+ RwIm3DVertexSetRGBA(imv + 2, val, val, val, val);
+ }
+
+ /*
+ * Update buffer position
+ */
+ imi[0] = 0;
+ imi[1] = 1;
+ imi[2] = 2;
+
+ RenderBuffer::StopStoring();
+
+ return points;
+}
+
+void
+CShadows::CastShadowEntityXYZ(CEntity *pEntity, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)
+{
+ ASSERT(pEntity != nil);
+ ASSERT(pPosn != nil);
+
+ if ( pShadow )
+ {
+ ProjectionParam proj;
+ RwV3d scl;
+ RwV3d tr;
+
+ CShadowCamera *shadow = pShadow->GetShadowCamera();
+ CColModel *collision = pEntity->GetColModel();
+
+ CCollision::CalculateTrianglePlanes(collision);
+
+ RwMatrix mat;
+ mat = *RwFrameGetMatrix(RwCameraGetFrame(shadow->GetRwCamera()));
+
+ RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+
+ RwMatrixRotate(&mat, &Xaxis, -45.0f, rwCOMBINEPRECONCAT);
+
+ proj.at = mat.at;
+ pEntity->GetMatrix().CopyToRwMatrix(&proj.entityMatrix);
+
+ RwMatrixInvert(&proj.invMatrix, &mat);
+ RwReal radius = RwCameraGetViewWindow(shadow->GetRwCamera())->x;
+
+ scl.x = scl.y = -0.5f / (radius*0.9f);
+ scl.z = 1.0f / (radius*0.8f);
+ RwMatrixScale(&proj.invMatrix, &scl, rwCOMBINEPOSTCONCAT);
+
+ tr.x = 0.5f;
+ tr.y = tr.z = 0.0f;
+ RwMatrixTranslate(&proj.invMatrix, &tr, rwCOMBINEPOSTCONCAT);
+
+ proj.shadowValue = nIntensity;
+ proj.fade = 0;
+
+ RwMatrix matrix;
+ pEntity->GetMatrix().CopyToRwMatrix(&matrix);
+ RwMatrix invMatrix;
+ RwMatrixInvert(&invMatrix, &matrix);
+
+
+ CVector center(pShadow->GetBaseSphere().center);
+ center += CVector(-fFrontX * 1.1f, -fFrontY * 1.1f, -0.5f);
+
+ CSphere sphere;
+ sphere.Set(2.0f, center);
+
+ RwV3d point;
+ RwV3dTransformPoints(&point, center, 1, &invMatrix);
+
+ CColSphere colSphere;
+ colSphere.Set(2.0f, CVector(point), 0, 0);
+
+ int i = 0;
+ while ( i < collision->numTriangles )
+ {
+ CVector p[3];
+
+ collision->GetTrianglePoint(p[0], collision->triangles[i].a);
+ collision->GetTrianglePoint(p[1], collision->triangles[i].b);
+ collision->GetTrianglePoint(p[2], collision->triangles[i].c);
+
+ if ( CCollision::TestSphereTriangle(colSphere, collision->vertices, collision->triangles[i], collision->trianglePlanes[i]) )
+ {
+ CVector n(collision->trianglePlanes[i].GetNormalX(), collision->trianglePlanes[i].GetNormalY(), collision->trianglePlanes[i].GetNormalZ());
+ CVector offset = n * 0.028f;
+
+ p[0] += offset;
+ p[1] += offset;
+ p[2] += offset;
+
+ if ( !ShadowRenderTriangleCB((RwV3d *)p, n, &proj) )
+ break;
+ }
+ i++;
+ }
+ }
+}
+
void
CShadows::UpdateStaticShadows(void)
{
for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
{
- if ( aStaticShadows[i].m_pPolyBunch != NULL && !aStaticShadows[i].m_bJustCreated
+ if ( aStaticShadows[i].m_pPolyBunch != nil && !aStaticShadows[i].m_bJustCreated
&& (!aStaticShadows[i].m_bTemp || CTimer::GetTimeInMilliseconds() > aStaticShadows[i].m_nTimeCreated + 5000) )
{
aStaticShadows[i].Free();
@@ -1515,13 +2288,14 @@ CShadows::UpdatePermanentShadows(void)
aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
else
{
+ bool bOk;
if ( timePassed >= (aPermanentShadows[i].m_nLifeTime * 3 / 4) )
{
// timePassed == 0 -> 4
// timePassed == aPermanentShadows[i].m_nLifeTime -> 0
float fMult = 1.0f - float(timePassed - (aPermanentShadows[i].m_nLifeTime * 3 / 4)) / (aPermanentShadows[i].m_nLifeTime / 4);
- StoreStaticShadow((uintptr)&aPermanentShadows[i],
+ bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i],
aPermanentShadows[i].m_nType,
aPermanentShadows[i].m_pTexture,
&aPermanentShadows[i].m_vecPos,
@@ -1538,7 +2312,7 @@ CShadows::UpdatePermanentShadows(void)
}
else
{
- StoreStaticShadow((uintptr)&aPermanentShadows[i],
+ bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i],
aPermanentShadows[i].m_nType,
aPermanentShadows[i].m_pTexture,
&aPermanentShadows[i].m_vecPos,
@@ -1553,6 +2327,9 @@ CShadows::UpdatePermanentShadows(void)
aPermanentShadows[i].m_fZDistance,
1.0f, 40.0f, false, 0.0f);
}
+
+ if ( !bOk )
+ aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
}
}
}
@@ -1561,19 +2338,19 @@ CShadows::UpdatePermanentShadows(void)
void
CStaticShadow::Free(void)
{
- if ( m_pPolyBunch != NULL )
+ if ( m_pPolyBunch != nil )
{
CPolyBunch *pFree = CShadows::pEmptyBunchList;
CShadows::pEmptyBunchList = m_pPolyBunch;
CPolyBunch *pUsed = m_pPolyBunch;
- while (pUsed->m_pNext != NULL)
+ while (pUsed->m_pNext != nil)
pUsed = pUsed->m_pNext;
pUsed->m_pNext = pFree;
}
- m_pPolyBunch = NULL;
+ m_pPolyBunch = nil;
m_nId = 0;
}
@@ -1617,6 +2394,7 @@ CShadows::CalcPedShadowValues(CVector vecLightDir,
}
+
void
CShadows::RenderExtraPlayerShadows(void)
{
@@ -1627,64 +2405,13 @@ CShadows::RenderExtraPlayerShadows(void)
if ( CTimeCycle::GetLightShadowStrength() != 0 )
{
CVehicle *pCar = FindPlayerVehicle();
-
- if ( pCar == NULL )
- {
- for ( int32 i = 0; i < CPointLights::NumLights; i++ )
- {
- if ( 0.0f != CPointLights::aLights[i].red
- || 0.0f != CPointLights::aLights[i].green
- || 0.0f != CPointLights::aLights[i].blue )
- {
- if ( CPointLights::aLights[i].castExtraShadows )
- {
- CVector vecLight = CPointLights::aLights[i].coors - FindPlayerCoors();
- float fLightDist = vecLight.Magnitude();
- float fRadius = CPointLights::aLights[i].radius;
-
- if ( fLightDist < fRadius )
- {
- // fLightDist == fRadius -> 2.0f
- // fLightDist == 0 -> 0.0f
- float fMult = (1.0f - (2.0f * fLightDist - fRadius) / fRadius);
-
- int32 nColorStrength;
- if ( fLightDist < fRadius*0.5f )
- nColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8);
- else
- nColorStrength = int32((5*CTimeCycle::GetLightShadowStrength()/8) * fMult);
-
- float fInv = 1.0f / fLightDist;
- vecLight.x *= fInv;
- vecLight.y *= fInv;
- vecLight.z *= fInv;
-
- float fFrontX, fFrontY, fSideX, fSideY, fDisplacementX, fDisplacementY;
-
- CalcPedShadowValues(vecLight,
- &fFrontX, &fFrontY,
- &fSideX, &fSideY,
- &fDisplacementX, &fDisplacementY);
-
- CVector shadowPos = FindPlayerCoors();
-
- shadowPos.x += fDisplacementX;
- shadowPos.y += fDisplacementY;
-
-
- StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &shadowPos,
- fFrontX, fFrontY,
- fSideX, fSideY,
- nColorStrength, 0, 0, 0,
- 4.0f, false, 1.0f);
- }
- }
- }
- }
- }
+ if ( pCar == nil )
+ ; // R* cut it out for playerped
else
{
- if ( pCar->GetModelIndex() != MI_RCBANDIT )
+ if ( pCar->GetModelIndex() != MI_RCBANDIT
+ && pCar->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE
+ && !pCar->IsBike() && !pCar->IsPlane() && !pCar->IsBoat() )
{
for ( int32 i = 0; i < CPointLights::NumLights; i++ )
{
@@ -1737,7 +2464,7 @@ CShadows::RenderExtraPlayerShadows(void)
pCar->GetRight().x * (fVehicleWidth/3),
pCar->GetRight().y * (fVehicleWidth/3),
nColorStrength, 0, 0, 0,
- 4.5f, false, 1.0f);
+ 4.5f, false, 1.0f, nil, false);
}
else
{
@@ -1747,7 +2474,7 @@ CShadows::RenderExtraPlayerShadows(void)
-pCar->GetRight().x * (fVehicleWidth/2),
-pCar->GetRight().y * (fVehicleWidth/2),
nColorStrength, 0, 0, 0,
- 4.5f, false, 1.0f);
+ 4.5f, false, 1.0f, nil, false);
}
}
}
@@ -1769,9 +2496,9 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
C3dMarkers::PlaceMarkerSet(nID, MARKERTYPE_CYLINDER, *pPosn, Max(fFrontX, -fSideY),
- 0, 128, 255, 128,
- 2048, 0.2f, 0);
+ SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B,
+ SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0);
}
diff --git a/src/render/Shadows.h b/src/render/Shadows.h
index 8c909df3..94b2981f 100644
--- a/src/render/Shadows.h
+++ b/src/render/Shadows.h
@@ -1,12 +1,19 @@
#pragma once
#define MAX_STOREDSHADOWS 48
-#define MAX_POLYBUNCHES 300
-#define MAX_STATICSHADOWS 64
+#define MAX_POLYBUNCHES 380
+#define MAX_STATICSHADOWS 48
#define MAX_PERMAMENTSHADOWS 48
+
class CEntity;
+class CPtrList;
+class CAutomobile;
+class CVehicle;
+class CPed;
+class CCutsceneShadow;
+class CCutsceneObject;
enum eShadowType
{
@@ -27,6 +34,16 @@ enum eShadowTextureType
SHADOWTEX_BLOOD
};
+enum VEH_SHD_TYPE
+{
+ VEH_SHD_TYPE_CAR = 0,
+ VEH_SHD_TYPE_BIKE,
+ VEH_SHD_TYPE_HELI,
+ VEH_SHD_TYPE_SEAPLANE,
+ VEH_SHD_TYPE_RCPLANE,
+};
+
+
class CStoredShadow
{
public:
@@ -35,6 +52,8 @@ public:
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
+ RwTexture *m_pTexture;
+ CCutsceneShadow *m_pCutsceneShadow;
int16 m_nIntensity;
uint8 m_ShadowType;
uint8 m_nRed;
@@ -44,9 +63,9 @@ public:
{
uint8 bDrawOnWater : 1;
uint8 bRendered : 1;
- //uint8 bDrawOnBuildings : 1;
+ uint8 bDrawOnBuildings : 1;
} m_nFlags;
- RwTexture *m_pTexture;
+
CStoredShadow()
{ }
@@ -57,11 +76,11 @@ VALIDATE_SIZE(CStoredShadow, 0x30);
class CPolyBunch
{
public:
- int16 m_nNumVerts;
CVector m_aVerts[7];
+ CPolyBunch *m_pNext;
+ int16 m_nNumVerts;
uint8 m_aU[7];
uint8 m_aV[7];
- CPolyBunch *m_pNext;
CPolyBunch()
{ }
@@ -80,15 +99,16 @@ public:
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
- uint8 m_nType;
+ RwTexture *m_pTexture;
int16 m_nIntensity; // unsigned ?
+ uint8 m_nType;
uint8 m_nRed;
uint8 m_nGreen;
uint8 m_nBlue;
bool m_bJustCreated;
bool m_bRendered;
bool m_bTemp;
- RwTexture *m_pTexture;
+
CStaticShadow()
{ }
@@ -106,14 +126,14 @@ public:
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
+ uint32 m_nTimeCreated;
+ uint32 m_nLifeTime;
+ RwTexture *m_pTexture;
int16 m_nIntensity;
uint8 m_nType; // eShadowType
uint8 m_nRed;
uint8 m_nGreen;
uint8 m_nBlue;
- uint32 m_nTimeCreated;
- uint32 m_nLifeTime;
- RwTexture *m_pTexture;
CPermanentShadow()
{ }
@@ -121,10 +141,6 @@ public:
VALIDATE_SIZE(CPermanentShadow, 0x38);
-class CPtrList;
-class CAutomobile;
-class CPed;
-
class CShadows
{
public:
@@ -135,37 +151,52 @@ public:
static CPolyBunch *pEmptyBunchList;
static CPermanentShadow aPermanentShadows[MAX_PERMAMENTSHADOWS];
- static void Init (void);
- static void Shutdown (void);
- static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale);
- static void StoreStaticShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance);
- static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue);
- static void StoreShadowToBeRendered ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale);
- static void StoreShadowForCar (CAutomobile *pCar);
- static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle);
- static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
- static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
- static void StoreShadowForTree (CEntity *pTree);
- static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID);
- static void SetRenderModeForShadowType (uint8 ShadowType);
- static void RenderStoredShadows (void);
- static void RenderStaticShadows (void);
- static void GeneratePolysForStaticShadow (int16 nStaticShadowID);
- static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
+ static void Init (void);
+ static void Shutdown (void);
+ static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale);
+
+ static bool StoreStaticShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance);
+ static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue);
+ static void StoreShadowToBeRendered ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings);
+ static void StoreShadowForVehicle (CVehicle *pCar, VEH_SHD_TYPE type);
+ static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle);
+ static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
+ static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
+ static void StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
+ static void StoreShadowForTree (CEntity *pTree);
+ static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID);
+ static void SetRenderModeForShadowType (uint8 ShadowType);
+ static void RenderStoredShadows (void);
+ static void RenderStaticShadows (void);
+
+ static void GeneratePolysForStaticShadow (int16 nStaticShadowID);
+ static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch);
- static void CastShadowEntity (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY,
+
+ static void CastPlayerShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
+ CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch);
+
+ static void CastCutsceneShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
+ CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);
+
+ static void CastShadowEntityXY (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY,
CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch);
- static void UpdateStaticShadows (void);
- static void UpdatePermanentShadows (void);
+
+ static void CastShadowEntityXYZ (CEntity *pEntity, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);
+
+ static void UpdateStaticShadows (void);
+ static void UpdatePermanentShadows (void);
static void CalcPedShadowValues (CVector vecLightDir, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY, float *pfDisplacementX, float *pfDisplacementY);
- static void RenderExtraPlayerShadows (void);
- static void TidyUpShadows (void);
- static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);
+ static void RenderExtraPlayerShadows (void);
+ static void TidyUpShadows (void);
+ static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);
};
extern RwTexture *gpShadowCarTex;
extern RwTexture *gpShadowPedTex;
extern RwTexture *gpShadowHeliTex;
+extern RwTexture *gpShadowBikeTex;
+extern RwTexture *gpShadowBaronTex;
extern RwTexture *gpShadowExplosionTex;
extern RwTexture *gpShadowHeadLightsTex;
extern RwTexture *gpOutline1Tex;
@@ -173,7 +204,6 @@ extern RwTexture *gpOutline2Tex;
extern RwTexture *gpOutline3Tex;
extern RwTexture *gpBloodPoolTex;
extern RwTexture *gpReflectionTex;
-extern RwTexture *gpGoalMarkerTex;
extern RwTexture *gpWalkDontTex;
extern RwTexture *gpCrackedGlassTex;
extern RwTexture *gpPostShadowTex;
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index 5d521041..f2a66db1 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -6,13 +6,13 @@
#include "Replay.h"
#include "Skidmarks.h"
+//--MIAMI: file done
+
CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];
RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];
RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2];
RwTexture *gpSkidTex;
-RwTexture *gpSkidBloodTex;
-RwTexture *gpSkidMudTex;
void
CSkidmarks::Init(void)
@@ -22,8 +22,6 @@ CSkidmarks::Init(void)
slot = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slot);
gpSkidTex = RwTextureRead("particleskid", nil);
- gpSkidBloodTex = RwTextureRead("particleskidblood", nil);
- gpSkidMudTex = RwTextureRead("particleskidmud", nil);
CTxdStore::PopCurrentTxd();
for(i = 0; i < NUMSKIDMARKS; i++){
@@ -41,30 +39,13 @@ CSkidmarks::Init(void)
SkidmarkIndexList[i*6+5] = ix+3;
ix += 2;
}
-
- for(i = 0; i < SKIDMARK_LENGTH; i++){
- RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 0], 0.0f);
- RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 0], i*5.01f);
- RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 1], 1.0f);
- RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 1], i*5.01f);
- }
}
void
CSkidmarks::Shutdown(void)
{
RwTextureDestroy(gpSkidTex);
-#ifdef GTA3_1_1_PATCH
gpSkidTex = nil;
-#endif
- RwTextureDestroy(gpSkidBloodTex);
-#ifdef GTA3_1_1_PATCH
- gpSkidBloodTex = nil;
-#endif
- RwTextureDestroy(gpSkidMudTex);
-#ifdef GTA3_1_1_PATCH
- gpSkidMudTex = nil;
-#endif
}
void
@@ -116,32 +97,23 @@ void
CSkidmarks::Render(void)
{
int i, j;
- RwTexture *lastTex = nil;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));
for(i = 0; i < NUMSKIDMARKS; i++){
if(aSkidmarks[i].m_state == 0 || aSkidmarks[i].m_last < 1)
continue;
- if(aSkidmarks[i].m_isBloody){
- if(lastTex != gpSkidBloodTex){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidBloodTex));
- lastTex = gpSkidBloodTex;
- }
- }else if(aSkidmarks[i].m_isMuddy){
- if(lastTex != gpSkidMudTex){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidMudTex));
- lastTex = gpSkidMudTex;
- }
- }else{
- if(lastTex != gpSkidTex){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));
- lastTex = gpSkidTex;
- }
+ CRGBA color(0, 0, 0, 255);
+ switch(aSkidmarks[i].m_type){
+ case SKIDMARK_NORMAL: color = CRGBA(0, 0, 0, 255); break;
+ case SKIDMARK_MUDDY: color = CRGBA(90, 62, 9, 255); break;
+ case SKIDMARK_SANDY: color = CRGBA(108, 108, 96, 255); break;
+ case SKIDMARK_BLOODY: color = CRGBA(132, 34, 11, 255); break;
}
uint32 fade, alpha;
@@ -156,12 +128,20 @@ CSkidmarks::Render(void)
alpha = 0;
alpha = alpha*fade/256;
- CVector p1 = aSkidmarks[i].m_pos[j] + aSkidmarks[i].m_side[j];
- CVector p2 = aSkidmarks[i].m_pos[j] - aSkidmarks[i].m_side[j];
- RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], 255, 255, 255, alpha);
+ CVector p1 = aSkidmarks[i].m_pos[j];
+ p1.x += aSkidmarks[i].m_sideX[j];
+ p1.y += aSkidmarks[i].m_sideY[j];
+ CVector p2 = aSkidmarks[i].m_pos[j];
+ p2.x -= aSkidmarks[i].m_sideX[j];
+ p2.y -= aSkidmarks[i].m_sideY[j];
+ RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], color.red, color.green, color.blue, alpha);
RwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f);
- RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], 255, 255, 255, alpha);
+ RwIm3DVertexSetU(&SkidmarkVertices[j*2+0], 0.0f);
+ RwIm3DVertexSetV(&SkidmarkVertices[j*2+0], j*5.01f);
+ RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], color.red, color.green, color.blue, alpha);
RwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f);
+ RwIm3DVertexSetU(&SkidmarkVertices[j*2+1], 1.0f);
+ RwIm3DVertexSetV(&SkidmarkVertices[j*2+1], j*5.01f);
}
LittleTest();
@@ -177,7 +157,20 @@ CSkidmarks::Render(void)
}
void
-CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody)
+CSkidmarks::RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody)
+{
+ eSkidmarkType type;
+ if(*isBloody)
+ type = SKIDMARK_BLOODY;
+ else if(*isMuddy)
+ type = SKIDMARK_MUDDY;
+ else
+ type = SKIDMARK_NORMAL;
+ RegisterOne(id, pos, fwdX, fwdY, type, isBloody);
+}
+
+void
+CSkidmarks::RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, eSkidmarkType type, bool *isBloody)
{
int i;
CVector2D fwd(fwdX, fwdY);
@@ -193,7 +186,7 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i
if(i < NUMSKIDMARKS){
// Continue this one
- if(aSkidmarks[i].m_isBloody != *isBloody){
+ if((aSkidmarks[i].m_type==SKIDMARK_BLOODY) != *isBloody){
// Blood-status changed, end this one
aSkidmarks[i].m_state = 2;
aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;
@@ -223,14 +216,17 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i
aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1];
- dist.NormaliseSafe();
- fwd.NormaliseSafe();
+ dist.Normalise();
+ fwd.Normalise();
CVector2D right(dist.y, -dist.x);
float turn = DotProduct2D(fwd, right);
turn = Abs(turn) + 1.0f;
- aSkidmarks[i].m_side[aSkidmarks[i].m_last] = CVector(right.x, right.y, 0.0f) * turn * 0.125f;
- if(aSkidmarks[i].m_last == 1)
- aSkidmarks[i].m_side[0] = aSkidmarks[i].m_side[1];
+ aSkidmarks[i].m_sideX[aSkidmarks[i].m_last] = right.x * turn * 0.125f;
+ aSkidmarks[i].m_sideY[aSkidmarks[i].m_last] = right.y * turn * 0.125f;
+ if(aSkidmarks[i].m_last == 1){
+ aSkidmarks[i].m_sideX[0] = aSkidmarks[i].m_sideX[1];
+ aSkidmarks[i].m_sideY[0] = aSkidmarks[i].m_sideY[1];
+ }
if(aSkidmarks[i].m_last > 8)
*isBloody = false; // stop blood marks after 8
@@ -246,12 +242,15 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i
aSkidmarks[i].m_state = 1;
aSkidmarks[i].m_id = id;
aSkidmarks[i].m_pos[0] = pos;
- aSkidmarks[i].m_side[0] = CVector(0.0f, 0.0f, 0.0f);
+ aSkidmarks[i].m_sideX[0] = 0.0f;
+ aSkidmarks[i].m_sideY[0] = 0.0f;
aSkidmarks[i].m_wasUpdated = true;
aSkidmarks[i].m_last = 0;
aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds() - 1000;
- aSkidmarks[i].m_isBloody = *isBloody;
- aSkidmarks[i].m_isMuddy = *isMuddy;
+ if(*isBloody)
+ aSkidmarks[i].m_type = SKIDMARK_BLOODY;
+ else
+ aSkidmarks[i].m_type = type;
}else
*isBloody = false; // stop blood marks if no space
}
diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h
index c061782d..28082f08 100644
--- a/src/render/Skidmarks.h
+++ b/src/render/Skidmarks.h
@@ -2,20 +2,28 @@
enum { SKIDMARK_LENGTH = 16 };
+enum eSkidmarkType
+{
+ SKIDMARK_NORMAL,
+ SKIDMARK_MUDDY,
+ SKIDMARK_SANDY,
+ SKIDMARK_BLOODY
+};
+
class CSkidmark
{
public:
- uint8 m_state;
- bool m_wasUpdated;
- bool m_isBloody;
- bool m_isMuddy;
+ CVector m_pos[SKIDMARK_LENGTH];
+ float m_sideX[SKIDMARK_LENGTH];
+ float m_sideY[SKIDMARK_LENGTH];
uintptr m_id;
- int16 m_last;
uint32 m_lastUpdate;
uint32 m_fadeStart;
uint32 m_fadeEnd;
- CVector m_pos[SKIDMARK_LENGTH];
- CVector m_side[SKIDMARK_LENGTH];
+ uint32 m_type;
+ int16 m_last;
+ uint8 m_state;
+ bool m_wasUpdated;
};
class CSkidmarks
@@ -28,5 +36,6 @@ public:
static void Clear(void);
static void Update(void);
static void Render(void);
- static void RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody);
+ static void RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, eSkidmarkType type, bool *isBloody);
+ static void RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody);
};
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 7e08fbad..e9079bef 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -21,6 +21,9 @@
#include "Camera.h"
#include "Shadows.h"
#include "main.h"
+#include "ColStore.h"
+#include "Coronas.h"
+#include "Script.h"
RwIm3DVertex StreakVertices[4];
RwImVertexIndex StreakIndexList[12];
@@ -28,6 +31,7 @@ RwImVertexIndex StreakIndexList[12];
RwIm3DVertex TraceVertices[6];
RwImVertexIndex TraceIndexList[12];
+bool CSpecialFX::bSnapShotActive;
void
CSpecialFX::Init(void)
@@ -369,6 +373,8 @@ MarkerAtomicCB(RpAtomic *atomic, void *data)
return atomic;
}
+// --MIAMI: C3dMarker and C3dMarkers done
+
bool
C3dMarker::AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
{
@@ -413,6 +419,7 @@ C3dMarker::DeleteMarkerObject()
m_nIdentifier = 0;
m_nStartTime = 0;
m_bIsUsed = false;
+ m_bFindZOnNextPlacement = false;
m_nType = MARKERTYPE_INVALID;
frame = RpAtomicGetFrame(m_pAtomic);
@@ -456,6 +463,7 @@ C3dMarkers::Init()
m_aMarkerArray[i].m_pAtomic = nil;
m_aMarkerArray[i].m_nType = MARKERTYPE_INVALID;
m_aMarkerArray[i].m_bIsUsed = false;
+ m_aMarkerArray[i].m_bFindZOnNextPlacement = false;
m_aMarkerArray[i].m_nIdentifier = 0;
m_aMarkerArray[i].m_Color.red = 255;
m_aMarkerArray[i].m_Color.green = 255;
@@ -501,8 +509,15 @@ C3dMarkers::Render()
ActivateDirectional();
for (int i = 0; i < NUM3DMARKERS; i++) {
if (m_aMarkerArray[i].m_bIsUsed) {
- if (m_aMarkerArray[i].m_fCameraRange < 120.0f)
+ if (m_aMarkerArray[i].m_fCameraRange < 150.0f) {
m_aMarkerArray[i].Render();
+ if (m_aMarkerArray[i].m_nType == MARKERTYPE_ARROW) {
+ CCoronas::RegisterCorona((uintptr)&m_aMarkerArray[i],
+ SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, 192,
+ m_aMarkerArray[i].m_Matrix.GetPosition(), 1.2f * m_aMarkerArray[i].m_fSize, 50.0f * TheCamera.LODDistMultiplier,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f, false);
+ }
+ }
NumActiveMarkers++;
m_aMarkerArray[i].m_bIsUsed = false;
} else if (m_aMarkerArray[i].m_pAtomic != nil) {
@@ -515,9 +530,9 @@ C3dMarker *
C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
{
C3dMarker *pMarker;
-
+ CVector2D playerPos = FindPlayerCentreOfWorld(0);
pMarker = nil;
- float dist = Sqrt((pos.x - FindPlayerCentreOfWorld(0).x) * (pos.x - FindPlayerCentreOfWorld(0).x) + (pos.y - FindPlayerCentreOfWorld(0).y) * (pos.y - FindPlayerCentreOfWorld(0).y));
+ float dist = ((CVector2D)pos - playerPos).Magnitude();
if (type != MARKERTYPE_ARROW && type != MARKERTYPE_CYLINDER) return nil;
@@ -590,6 +605,15 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size
}
if (type == MARKERTYPE_ARROW)
pMarker->m_Matrix.GetPosition() = pos;
+
+ if (pMarker->m_bFindZOnNextPlacement) {
+ if ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) {
+ float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);
+ if (z != 0.0f)
+ pMarker->m_Matrix.GetPosition().z = z - 0.05f * size;
+ pMarker->m_bFindZOnNextPlacement = false;
+ }
+ }
pMarker->m_bIsUsed = true;
return pMarker;
}
@@ -599,9 +623,14 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size
pMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate);
if (type == MARKERTYPE_CYLINDER || type == MARKERTYPE_0 || type == MARKERTYPE_2) {
- float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);
- if (z != 0.0f)
- pos.z = z - 0.05f * size;
+ if ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) {
+ float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);
+ if (z != 0.0f)
+ pos.z = z - 0.05f * size;
+ pMarker->m_bFindZOnNextPlacement = false;
+ } else {
+ pMarker->m_bFindZOnNextPlacement = true;
+ }
}
pMarker->m_Matrix.SetTranslate(pos.x, pos.y, pos.z);
if (type == MARKERTYPE_2) {
@@ -1049,7 +1078,7 @@ CMoneyMessage::Render()
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity));
CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
CFont::PrintString(vecOut.x, vecOut.y, m_aText);
}
}
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 2d9f18b1..8c79856b 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -3,6 +3,8 @@
class CSpecialFX
{
public:
+ static bool bSnapShotActive;
+
static void Render(void);
static void Update(void);
static void Init(void);
@@ -77,6 +79,7 @@ public:
RpMaterial *m_pMaterial;
uint16 m_nType;
bool m_bIsUsed;
+ bool m_bFindZOnNextPlacement;
uint32 m_nIdentifier;
RwRGBA m_Color;
uint16 m_nPulsePeriod;
diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp
index 9ec7b002..f26f8e63 100644
--- a/src/render/Sprite.cpp
+++ b/src/render/Sprite.cpp
@@ -263,8 +263,8 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z,
{
m_bFlushSpriteBufferSwitchZTest = 0;
// TODO: replace with lookup
- float c = Cos(DEGTORAD(rotation));
- float s = Sin(DEGTORAD(rotation));
+ float c = Cos(rotation);
+ float s = Sin(rotation);
float xs[4];
float ys[4];
@@ -576,8 +576,8 @@ CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w
{
m_bFlushSpriteBufferSwitchZTest = 1;
CRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha);
- float c = Cos(DEGTORAD(rotation));
- float s = Sin(DEGTORAD(rotation));
+ float c = Cos(rotation);
+ float s = Sin(rotation);
Set6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex],
x + c*w - s*h,
diff --git a/src/render/Sprite.h b/src/render/Sprite.h
index ec4c1d1b..fae6684e 100644
--- a/src/render/Sprite.h
+++ b/src/render/Sprite.h
@@ -7,6 +7,9 @@ class CSprite
static float m_fRecipNearClipPlane;
static int32 m_bFlushSpriteBufferSwitchZTest;
public:
+ static float GetNearScreenZ(void) { return m_f2DNearScreenZ; }
+ static float GetFarScreenZ(void) { return m_f2DFarScreenZ; }
+
static float CalcHorizonCoors(void);
static bool CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip);
static void InitSpriteBuffer(void);
diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp
index 98bb6eb2..7dcedb26 100644
--- a/src/render/Sprite2d.cpp
+++ b/src/render/Sprite2d.cpp
@@ -5,79 +5,32 @@
#include "Camera.h"
#include "Sprite2d.h"
#include "Font.h"
+#include "RenderBuffer.h"
-RwIm2DVertex CSprite2d::maVertices[8];
float CSprite2d::RecipNearClip;
-int32 CSprite2d::mCurrentBank;
-RwTexture *CSprite2d::mpBankTextures[10];
-int32 CSprite2d::mCurrentSprite[10];
-int32 CSprite2d::mBankStart[10];
-RwIm2DVertex CSprite2d::maBankVertices[500];
+float CSprite2d::NearScreenZ;
+float CSprite2d::NearCamZ;
+int CSprite2d::nextBufferVertex;
+int CSprite2d::nextBufferIndex;
+RwIm2DVertex CSprite2d::maVertices[8];
void
CSprite2d::SetRecipNearClip(void)
{
- RecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera);
+ // Used but empty in VC, instead they set in InitPerFrame. Isn't that great?
}
void
CSprite2d::InitPerFrame(void)
{
- int i;
-
- mCurrentBank = 0;
- for(i = 0; i < 10; i++)
- mCurrentSprite[i] = 0;
-#ifndef SQUEEZE_PERFORMANCE
- for(i = 0; i < 10; i++)
- mpBankTextures[i] = nil;
-#endif
-}
-
-int32
-CSprite2d::GetBank(int32 n, RwTexture *tex)
-{
-#ifndef SQUEEZE_PERFORMANCE
- mpBankTextures[mCurrentBank] = tex;
-#endif
- mCurrentSprite[mCurrentBank] = 0;
- mBankStart[mCurrentBank+1] = mBankStart[mCurrentBank] + n;
- return mCurrentBank++;
-}
-
-void
-CSprite2d::AddSpriteToBank(int32 bank, const CRect &rect, const CRGBA &col,
- float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
-{
- SetVertices(&maBankVertices[6 * (mCurrentSprite[bank] + mBankStart[bank])],
- rect, col, col, col, col,
- u0, v0, u1, v1, u2, v2, u3, v3);
- mCurrentSprite[bank]++;
- if(mCurrentSprite[bank] + mBankStart[bank] >= mBankStart[bank+1]){
- DrawBank(bank);
- mCurrentSprite[bank] = 0;
- }
-}
-
-void
-CSprite2d::DrawBank(int32 bank)
-{
- if(mCurrentSprite[bank] == 0)
- return;
-#ifndef SQUEEZE_PERFORMANCE
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER,
- mpBankTextures[bank] ? RwTextureGetRaster(mpBankTextures[bank]) : nil);
-#else
- CFont::Sprite[bank].SetRenderState();
-#endif
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
- RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, &maBankVertices[6*mBankStart[bank]], 6*mCurrentSprite[bank]);
- mCurrentSprite[bank] = 0;
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ nextBufferVertex = 0;
+ nextBufferIndex = 0;
+ RecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera);
+ NearScreenZ = RwIm2DGetNearScreenZ();
+ // not original but you're supposed to set camera z too
+ // wrapping all this in FIX_BUGS is too ugly
+ NearCamZ = RwCameraGetNearClipPlane(Scene.camera);
}
-
-
void
CSprite2d::Delete(void)
{
@@ -122,7 +75,7 @@ CSprite2d::SetRenderState(void)
void
CSprite2d::Draw(float x, float y, float w, float h, const CRGBA &col)
{
- SetVertices(CRect(x, y, x + w, y + h), col, col, col, col, 0);
+ SetVertices(CRect(x, y, x + w, y + h), col, col, col, col);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
@@ -130,7 +83,7 @@ CSprite2d::Draw(float x, float y, float w, float h, const CRGBA &col)
void
CSprite2d::Draw(const CRect &rect, const CRGBA &col)
{
- SetVertices(rect, col, col, col, col, 0);
+ SetVertices(rect, col, col, col, col);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
@@ -147,7 +100,7 @@ CSprite2d::Draw(const CRect &rect, const CRGBA &col,
void
CSprite2d::Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
- SetVertices(rect, c0, c1, c2, c3, 0);
+ SetVertices(rect, c0, c1, c2, c3);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
@@ -160,185 +113,154 @@ CSprite2d::Draw(float x1, float y1, float x2, float y2, float x3, float y3, floa
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
-
// Arguments:
// 2---3
// | |
// 0---1
void
-CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far)
+CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
- float screenz, z, recipz;
-
- if(far){
- screenz = RwIm2DGetFarScreenZ();
- z = RwCameraGetFarClipPlane(Scene.camera);
- }else{
- screenz = RwIm2DGetNearScreenZ();
- z = 1.0f/RecipNearClip;
- }
- recipz = 1.0f/z;
- float offset = 1.0f/1024.0f;
-
// This is what we draw:
// 0---1
// | / |
// 3---2
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
RwIm2DVertexSetScreenY(&maVertices[0], r.top);
- RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[0], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
- RwIm2DVertexSetU(&maVertices[0], 0.0f+offset, recipz);
- RwIm2DVertexSetV(&maVertices[0], 0.0f+offset, recipz);
+ RwIm2DVertexSetU(&maVertices[0], 0.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[0], 0.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
RwIm2DVertexSetScreenY(&maVertices[1], r.top);
- RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[1], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
- RwIm2DVertexSetU(&maVertices[1], 1.0f+offset, recipz);
- RwIm2DVertexSetV(&maVertices[1], 0.0f+offset, recipz);
+ RwIm2DVertexSetU(&maVertices[1], 1.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[1], 0.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
RwIm2DVertexSetScreenY(&maVertices[2], r.bottom);
- RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[2], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
- RwIm2DVertexSetU(&maVertices[2], 1.0f+offset, recipz);
- RwIm2DVertexSetV(&maVertices[2], 1.0f+offset, recipz);
+ RwIm2DVertexSetU(&maVertices[2], 1.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[2], 1.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
RwIm2DVertexSetScreenY(&maVertices[3], r.bottom);
- RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[3], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
- RwIm2DVertexSetU(&maVertices[3], 0.0f+offset, recipz);
- RwIm2DVertexSetV(&maVertices[3], 1.0f+offset, recipz);
+ RwIm2DVertexSetU(&maVertices[3], 0.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[3], 1.0f, RecipNearClip);
}
void
CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
{
- float screenz, z, recipz;
-
- screenz = RwIm2DGetNearScreenZ();
- z = 1.0f/RecipNearClip;
- recipz = 1.0f/z;
-
// This is what we draw:
// 0---1
// | / |
// 3---2
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
RwIm2DVertexSetScreenY(&maVertices[0], r.top);
- RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[0], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
- RwIm2DVertexSetU(&maVertices[0], u0, recipz);
- RwIm2DVertexSetV(&maVertices[0], v0, recipz);
+ RwIm2DVertexSetU(&maVertices[0], u0, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[0], v0, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
RwIm2DVertexSetScreenY(&maVertices[1], r.top);
- RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[1], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
- RwIm2DVertexSetU(&maVertices[1], u1, recipz);
- RwIm2DVertexSetV(&maVertices[1], v1, recipz);
+ RwIm2DVertexSetU(&maVertices[1], u1, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[1], v1, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
RwIm2DVertexSetScreenY(&maVertices[2], r.bottom);
- RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[2], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
- RwIm2DVertexSetU(&maVertices[2], u2, recipz);
- RwIm2DVertexSetV(&maVertices[2], v2, recipz);
+ RwIm2DVertexSetU(&maVertices[2], u2, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[2], v2, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
RwIm2DVertexSetScreenY(&maVertices[3], r.bottom);
- RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[3], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
- RwIm2DVertexSetU(&maVertices[3], u3, recipz);
- RwIm2DVertexSetV(&maVertices[3], v3, recipz);
+ RwIm2DVertexSetU(&maVertices[3], u3, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[3], v3, RecipNearClip);
}
void
CSprite2d::SetVertices(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
- float screenz, recipz;
- float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
-
- screenz = RwIm2DGetNearScreenZ();
- recipz = RecipNearClip;
-
RwIm2DVertexSetScreenX(&maVertices[0], x3);
RwIm2DVertexSetScreenY(&maVertices[0], y3);
- RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[0], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
- RwIm2DVertexSetU(&maVertices[0], 0.0f, recipz);
- RwIm2DVertexSetV(&maVertices[0], 0.0f, recipz);
+ RwIm2DVertexSetU(&maVertices[0], 0.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[0], 0.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[1], x4);
RwIm2DVertexSetScreenY(&maVertices[1], y4);
- RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[1], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
- RwIm2DVertexSetU(&maVertices[1], 1.0f, recipz);
- RwIm2DVertexSetV(&maVertices[1], 0.0f, recipz);
+ RwIm2DVertexSetU(&maVertices[1], 1.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[1], 0.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[2], x2);
RwIm2DVertexSetScreenY(&maVertices[2], y2);
- RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[2], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
- RwIm2DVertexSetU(&maVertices[2], 1.0f, recipz);
- RwIm2DVertexSetV(&maVertices[2], 1.0f, recipz);
+ RwIm2DVertexSetU(&maVertices[2], 1.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[2], 1.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[3], x1);
RwIm2DVertexSetScreenY(&maVertices[3], y1);
- RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[3], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
- RwIm2DVertexSetU(&maVertices[3], 0.0f, recipz);
- RwIm2DVertexSetV(&maVertices[3], 1.0f, recipz);
+ RwIm2DVertexSetU(&maVertices[3], 0.0f, RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[3], 1.0f, RecipNearClip);
}
void
CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col)
{
int i;
- float screenz, recipz, z;
-
- screenz = RwIm2DGetNearScreenZ();
- recipz = RecipNearClip;
- z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
-
for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
RwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]);
- RwIm2DVertexSetScreenZ(&maVertices[i], screenz + 0.0001f);
- RwIm2DVertexSetCameraZ(&maVertices[i], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ + 0.0001f);
+ RwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[i], col.r, col.g, col.b, col.a);
- RwIm2DVertexSetU(&maVertices[i], uvs[i*2 + 0], recipz);
- RwIm2DVertexSetV(&maVertices[i], uvs[i*2 + 1], recipz);
+ RwIm2DVertexSetU(&maVertices[i], uvs[i*2 + 0], RecipNearClip);
+ RwIm2DVertexSetV(&maVertices[i], uvs[i*2 + 1], RecipNearClip);
}
}
@@ -346,18 +268,13 @@ void
CSprite2d::SetMaskVertices(int n, float *positions)
{
int i;
- float screenz, recipz, z;
-
- screenz = RwIm2DGetNearScreenZ();
- recipz = RecipNearClip;
- z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
RwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]);
- RwIm2DVertexSetScreenZ(&maVertices[i], screenz);
- RwIm2DVertexSetCameraZ(&maVertices[i], z);
- RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz);
+ RwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip);
RwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255); // 0, 0, 0, 0 on PC
}
}
@@ -366,72 +283,47 @@ void
CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
{
- float screenz, recipz, z;
-
- screenz = RwIm2DGetNearScreenZ();
- recipz = RecipNearClip;
- z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
-
RwIm2DVertexSetScreenX(&verts[0], r.left);
RwIm2DVertexSetScreenY(&verts[0], r.top);
- RwIm2DVertexSetScreenZ(&verts[0], screenz);
- RwIm2DVertexSetCameraZ(&verts[0], z);
- RwIm2DVertexSetRecipCameraZ(&verts[0], recipz);
+ RwIm2DVertexSetScreenZ(&verts[0], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&verts[0], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&verts[0], RecipNearClip);
RwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a);
- RwIm2DVertexSetU(&verts[0], u0, recipz);
- RwIm2DVertexSetV(&verts[0], v0, recipz);
-
- RwIm2DVertexSetScreenX(&verts[1], r.left);
- RwIm2DVertexSetScreenY(&verts[1], r.bottom);
- RwIm2DVertexSetScreenZ(&verts[1], screenz);
- RwIm2DVertexSetCameraZ(&verts[1], z);
- RwIm2DVertexSetRecipCameraZ(&verts[1], recipz);
- RwIm2DVertexSetIntRGBA(&verts[1], c0.r, c0.g, c0.b, c0.a);
- RwIm2DVertexSetU(&verts[1], u2, recipz);
- RwIm2DVertexSetV(&verts[1], v2, recipz);
+ RwIm2DVertexSetU(&verts[0], u0, RecipNearClip);
+ RwIm2DVertexSetV(&verts[0], v0, RecipNearClip);
+
+ RwIm2DVertexSetScreenX(&verts[1], r.right);
+ RwIm2DVertexSetScreenY(&verts[1], r.top);
+ RwIm2DVertexSetScreenZ(&verts[1], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&verts[1], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&verts[1], RecipNearClip);
+ RwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a);
+ RwIm2DVertexSetU(&verts[1], u1, RecipNearClip);
+ RwIm2DVertexSetV(&verts[1], v1, RecipNearClip);
RwIm2DVertexSetScreenX(&verts[2], r.right);
RwIm2DVertexSetScreenY(&verts[2], r.bottom);
- RwIm2DVertexSetScreenZ(&verts[2], screenz);
- RwIm2DVertexSetCameraZ(&verts[2], z);
- RwIm2DVertexSetRecipCameraZ(&verts[2], recipz);
+ RwIm2DVertexSetScreenZ(&verts[2], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&verts[2], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&verts[2], RecipNearClip);
RwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);
- RwIm2DVertexSetU(&verts[2], u3, recipz);
- RwIm2DVertexSetV(&verts[2], v3, recipz);
+ RwIm2DVertexSetU(&verts[2], u2, RecipNearClip);
+ RwIm2DVertexSetV(&verts[2], v2, RecipNearClip);
RwIm2DVertexSetScreenX(&verts[3], r.left);
- RwIm2DVertexSetScreenY(&verts[3], r.top);
- RwIm2DVertexSetScreenZ(&verts[3], screenz);
- RwIm2DVertexSetCameraZ(&verts[3], z);
- RwIm2DVertexSetRecipCameraZ(&verts[3], recipz);
- RwIm2DVertexSetIntRGBA(&verts[3], c2.r, c2.g, c2.b, c2.a);
- RwIm2DVertexSetU(&verts[3], u0, recipz);
- RwIm2DVertexSetV(&verts[3], v0, recipz);
-
- RwIm2DVertexSetScreenX(&verts[4], r.right);
- RwIm2DVertexSetScreenY(&verts[4], r.bottom);
- RwIm2DVertexSetScreenZ(&verts[4], screenz);
- RwIm2DVertexSetCameraZ(&verts[4], z);
- RwIm2DVertexSetRecipCameraZ(&verts[4], recipz);
- RwIm2DVertexSetIntRGBA(&verts[4], c1.r, c1.g, c1.b, c1.a);
- RwIm2DVertexSetU(&verts[4], u3, recipz);
- RwIm2DVertexSetV(&verts[4], v3, recipz);
-
- RwIm2DVertexSetScreenX(&verts[5], r.right);
- RwIm2DVertexSetScreenY(&verts[5], r.top);
- RwIm2DVertexSetScreenZ(&verts[5], screenz);
- RwIm2DVertexSetCameraZ(&verts[5], z);
- RwIm2DVertexSetRecipCameraZ(&verts[5], recipz);
- RwIm2DVertexSetIntRGBA(&verts[5], c3.r, c3.g, c3.b, c3.a);
- RwIm2DVertexSetU(&verts[5], u1, recipz);
- RwIm2DVertexSetV(&verts[5], v1, recipz);
-
+ RwIm2DVertexSetScreenY(&verts[3], r.bottom);
+ RwIm2DVertexSetScreenZ(&verts[3], NearScreenZ);
+ RwIm2DVertexSetCameraZ(&verts[3], NearCamZ);
+ RwIm2DVertexSetRecipCameraZ(&verts[3], RecipNearClip);
+ RwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a);
+ RwIm2DVertexSetU(&verts[3], u3, RecipNearClip);
+ RwIm2DVertexSetV(&verts[3], v3, RecipNearClip);
}
void
CSprite2d::DrawRect(const CRect &r, const CRGBA &col)
{
- SetVertices(r, col, col, col, col, false);
+ SetVertices(r, col, col, col, col);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
@@ -446,7 +338,7 @@ CSprite2d::DrawRect(const CRect &r, const CRGBA &col)
void
CSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
- SetVertices(r, c0, c1, c2, c3, false);
+ SetVertices(r, c0, c1, c2, c3);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
@@ -459,7 +351,7 @@ CSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGB
void
CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
- SetVertices(r, c0, c1, c2, c3, false);
+ SetVertices(r, c0, c1, c2, c3);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
@@ -471,6 +363,22 @@ CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
+void
+CSprite2d::DrawAnyRect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
+ const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
+{
+ SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, c0, c1, c2, c3);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(c0.alpha != 255 || c1.alpha != 255 || c2.alpha != 255 || c3.alpha != 255));
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
+}
+
void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color)
{
SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
@@ -484,3 +392,37 @@ void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3,
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
}
+
+void
+CSprite2d::AddToBuffer(const CRect &r, const CRGBA &c, float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
+{
+ SetVertices(&TempVertexBuffer.im2d[nextBufferVertex], r, c, c, c, c, u0, v0, u1, v1, u3, v3, u2, v2);
+ RwImVertexIndex *pIndexList = &TempBufferRenderIndexList[nextBufferIndex];
+ pIndexList[0] = nextBufferVertex;
+ pIndexList[1] = nextBufferVertex + 1;
+ pIndexList[2] = nextBufferVertex + 2;
+ pIndexList[3] = nextBufferVertex + 3;
+ pIndexList[4] = nextBufferVertex;
+ pIndexList[5] = nextBufferVertex + 2;
+ nextBufferIndex += 6;
+ nextBufferVertex += 4;
+ if (IsVertexBufferFull())
+ RenderVertexBuffer();
+}
+
+bool
+CSprite2d::IsVertexBufferFull()
+{
+ return (nextBufferVertex > TEMPBUFFERVERTSIZE-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6);
+}
+
+void
+CSprite2d::RenderVertexBuffer()
+{
+ if (nextBufferVertex > 0) {
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempVertexBuffer.im2d, nextBufferVertex, TempBufferRenderIndexList, nextBufferIndex);
+ nextBufferVertex = 0;
+ nextBufferIndex = 0;
+ }
+} \ No newline at end of file
diff --git a/src/render/Sprite2d.h b/src/render/Sprite2d.h
index 0e12d441..5abd8d71 100644
--- a/src/render/Sprite2d.h
+++ b/src/render/Sprite2d.h
@@ -3,21 +3,16 @@
class CSprite2d
{
static float RecipNearClip;
- static int32 mCurrentBank;
- static RwTexture *mpBankTextures[10];
- static int32 mCurrentSprite[10];
- static int32 mBankStart[10];
- static RwIm2DVertex maBankVertices[500];
+ static float NearScreenZ;
+ static float NearCamZ; // not original
+ static int nextBufferVertex;
+ static int nextBufferIndex;
static RwIm2DVertex maVertices[8];
public:
RwTexture *m_pTexture;
static void SetRecipNearClip(void);
static void InitPerFrame(void);
- static int32 GetBank(int32 n, RwTexture *tex);
- static void AddSpriteToBank(int32 bank, const CRect &rect, const CRGBA &col,
- float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2);
- static void DrawBank(int32 bank);
CSprite2d(void) : m_pTexture(nil) {};
~CSprite2d(void) { Delete(); };
@@ -33,7 +28,7 @@ public:
void Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
void Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &col);
- static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far);
+ static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2);
static void SetVertices(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
@@ -46,8 +41,14 @@ public:
static void DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
static void DrawRect(const CRect &r, const CRGBA &col);
static void DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
+ static void DrawAnyRect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
+ const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
static void Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color);
static RwIm2DVertex* GetVertices() { return maVertices; };
+
+ static bool IsVertexBufferFull();
+ static void AddToBuffer(const CRect &a1, const CRGBA &a2, float a3, float a4, float a5, float a6, float a7, float a8, float a9, float a10);
+ static void RenderVertexBuffer();
};
diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp
index 0d94dbd6..b20a2443 100644
--- a/src/render/Timecycle.cpp
+++ b/src/render/Timecycle.cpp
@@ -10,50 +10,74 @@
#include "FileMgr.h"
#include "Timecycle.h"
-int32 CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
-int16 CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS];
-int16 CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
-int16 CTimeCycle::m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
-int32 CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurAlpha[NUMHOURS][NUMWEATHERS];
+//--MIAMI: done
+
+uint8 CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
+int8 CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS];
+int8 CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS];
+int8 CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
+int16 CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS];
+int16 CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
+
float CTimeCycle::m_fCurrentAmbientRed;
float CTimeCycle::m_fCurrentAmbientGreen;
float CTimeCycle::m_fCurrentAmbientBlue;
+float CTimeCycle::m_fCurrentAmbientRed_Obj;
+float CTimeCycle::m_fCurrentAmbientGreen_Obj;
+float CTimeCycle::m_fCurrentAmbientBlue_Obj;
+float CTimeCycle::m_fCurrentAmbientRed_Bl;
+float CTimeCycle::m_fCurrentAmbientGreen_Bl;
+float CTimeCycle::m_fCurrentAmbientBlue_Bl;
+float CTimeCycle::m_fCurrentAmbientRed_Obj_Bl;
+float CTimeCycle::m_fCurrentAmbientGreen_Obj_Bl;
+float CTimeCycle::m_fCurrentAmbientBlue_Obj_Bl;
float CTimeCycle::m_fCurrentDirectionalRed;
float CTimeCycle::m_fCurrentDirectionalGreen;
float CTimeCycle::m_fCurrentDirectionalBlue;
@@ -74,7 +98,7 @@ float CTimeCycle::m_fCurrentSpriteSize;
float CTimeCycle::m_fCurrentSpriteBrightness;
int32 CTimeCycle::m_nCurrentShadowStrength;
int32 CTimeCycle::m_nCurrentLightShadowStrength;
-int32 CTimeCycle::m_nCurrentTreeShadowStrength;
+int32 CTimeCycle::m_nCurrentPoleShadowStrength;
float CTimeCycle::m_fCurrentFogStart;
float CTimeCycle::m_fCurrentFarClip;
float CTimeCycle::m_fCurrentLightsOnGroundBrightness;
@@ -90,12 +114,18 @@ int32 CTimeCycle::m_nCurrentFluffyCloudsBottomBlue;
float CTimeCycle::m_fCurrentBlurRed;
float CTimeCycle::m_fCurrentBlurGreen;
float CTimeCycle::m_fCurrentBlurBlue;
-float CTimeCycle::m_fCurrentBlurAlpha;
+float CTimeCycle::m_fCurrentWaterRed;
+float CTimeCycle::m_fCurrentWaterGreen;
+float CTimeCycle::m_fCurrentWaterBlue;
+float CTimeCycle::m_fCurrentWaterAlpha;
int32 CTimeCycle::m_nCurrentFogColourRed;
int32 CTimeCycle::m_nCurrentFogColourGreen;
int32 CTimeCycle::m_nCurrentFogColourBlue;
int32 CTimeCycle::m_FogReduction;
+int32 CTimeCycle::m_bExtraColourOn;
+int32 CTimeCycle::m_ExtraColour;
+float CTimeCycle::m_ExtraColourInter;
int32 CTimeCycle::m_CurrentStoredValue;
CVector CTimeCycle::m_VectorToSun[16];
@@ -106,7 +136,6 @@ float CTimeCycle::m_fShadowSideY[16];
float CTimeCycle::m_fShadowDisplacementX[16];
float CTimeCycle::m_fShadowDisplacementY[16];
-
void
CTimeCycle::Initialise(void)
{
@@ -115,18 +144,22 @@ CTimeCycle::Initialise(void)
char line[1040];
int ambR, ambG, ambB;
+ int ambobjR, ambobjG, ambobjB;
+ int ambblR, ambblG, ambblB;
+ int ambobjblR, ambobjblG, ambobjblB;
int dirR, dirG, dirB;
int skyTopR, skyTopG, skyTopB;
int skyBotR, skyBotG, skyBotB;
int sunCoreR, sunCoreG, sunCoreB;
int sunCoronaR, sunCoronaG, sunCoronaB;
float sunSz, sprSz, sprBght;
- int shad, lightShad, treeShad;
+ int shad, lightShad, poleShad;
float farClp, fogSt, lightGnd;
int cloudR, cloudG, cloudB;
int fluffyTopR, fluffyTopG, fluffyTopB;
int fluffyBotR, fluffyBotG, fluffyBotB;
- float blurR, blurG, blurB, blurA;
+ float blurR, blurG, blurB;
+ float waterR, waterG, waterB, waterA;
debug("Intialising CTimeCycle...\n");
@@ -144,31 +177,49 @@ CTimeCycle::Initialise(void)
bi++;
bi++;
}
- while(work_buff[bi] != '\n')
+ while(work_buff[bi] != '\n'
+#ifdef FIX_BUGS
+ && work_buff[bi] != '\0'
+#endif
+ )
line[li++] = work_buff[bi++];
line[li] = '\0';
bi++;
sscanf(line, "%d %d %d %d %d %d %d %d %d %d %d %d "
+ "%d %d %d %d %d %d %d %d %d "
"%d %d %d %d %d %d %f %f %f %d %d %d %f %f %f "
- "%d %d %d %d %d %d %d %d %d %f %f %f %f",
+ "%d %d %d %d %d %d %d %d %d %f %f %f %f %f %f %f",
&ambR, &ambG, &ambB,
- &dirR, &dirG, &dirB,
+ &ambobjR, &ambobjG, &ambobjB,
+ &ambblR, &ambblG, &ambblB,
+ &ambobjblR, &ambobjblG, &ambobjblB,
+ &dirR, &dirG, &dirB,
&skyTopR, &skyTopG, &skyTopB,
&skyBotR, &skyBotG, &skyBotB,
&sunCoreR, &sunCoreG, &sunCoreB,
&sunCoronaR, &sunCoronaG, &sunCoronaB,
&sunSz, &sprSz, &sprBght,
- &shad, &lightShad, &treeShad,
+ &shad, &lightShad, &poleShad,
&farClp, &fogSt, &lightGnd,
&cloudR, &cloudG, &cloudB,
&fluffyTopR, &fluffyTopG, &fluffyTopB,
&fluffyBotR, &fluffyBotG, &fluffyBotB,
- &blurR, &blurG, &blurB, &blurA);
+ &blurR, &blurG, &blurB,
+ &waterR, &waterG, &waterB, &waterA);
m_nAmbientRed[h][w] = ambR;
m_nAmbientGreen[h][w] = ambG;
m_nAmbientBlue[h][w] = ambB;
+ m_nAmbientRed_Obj[h][w] = ambobjR;
+ m_nAmbientGreen_Obj[h][w] = ambobjG;
+ m_nAmbientBlue_Obj[h][w] = ambobjB;
+ m_nAmbientRed_Bl[h][w] = ambblR;
+ m_nAmbientGreen_Bl[h][w] = ambblG;
+ m_nAmbientBlue_Bl[h][w] = ambblB;
+ m_nAmbientRed_Obj_Bl[h][w] = ambobjblR;
+ m_nAmbientGreen_Obj_Bl[h][w] = ambobjblG;
+ m_nAmbientBlue_Obj_Bl[h][w] = ambobjblB;
m_nDirectionalRed[h][w] = dirR;
m_nDirectionalGreen[h][w] = dirG;
m_nDirectionalBlue[h][w] = dirB;
@@ -184,15 +235,15 @@ CTimeCycle::Initialise(void)
m_nSunCoronaRed[h][w] = sunCoronaR;
m_nSunCoronaGreen[h][w] = sunCoronaG;
m_nSunCoronaBlue[h][w] = sunCoronaB;
- m_fSunSize[h][w] = sunSz;
- m_fSpriteSize[h][w] = sprSz;
- m_fSpriteBrightness[h][w] = sprBght;
+ m_fSunSize[h][w] = sunSz * 10.0f;
+ m_fSpriteSize[h][w] = sprSz * 10.0f;
+ m_fSpriteBrightness[h][w] = sprBght * 10.0f;
m_nShadowStrength[h][w] = shad;
m_nLightShadowStrength[h][w] = lightShad;
- m_nTreeShadowStrength[h][w] = treeShad;
+ m_nPoleShadowStrength[h][w] = poleShad;
m_fFarClip[h][w] = farClp;
m_fFogStart[h][w] = fogSt;
- m_fLightsOnGroundBrightness[h][w] = lightGnd;
+ m_fLightsOnGroundBrightness[h][w] = lightGnd * 10.0f;
m_nLowCloudsRed[h][w] = cloudR;
m_nLowCloudsGreen[h][w] = cloudG;
m_nLowCloudsBlue[h][w] = cloudB;
@@ -205,7 +256,10 @@ CTimeCycle::Initialise(void)
m_fBlurRed[h][w] = blurR;
m_fBlurGreen[h][w] = blurG;
m_fBlurBlue[h][w] = blurB;
- m_fBlurAlpha[h][w] = blurA;
+ m_fWaterRed[h][w] = waterR;
+ m_fWaterGreen[h][w] = waterG;
+ m_fWaterBlue[h][w] = waterB;
+ m_fWaterAlpha[h][w] = waterA;
}
m_FogReduction = 0;
@@ -213,6 +267,51 @@ CTimeCycle::Initialise(void)
debug("CTimeCycle ready\n");
}
+static float interp_c0, interp_c1, interp_c2, interp_c3;
+
+float CTimeCycle::Interpolate(int8 *a, int8 *b)
+{
+ return a[CWeather::OldWeatherType] * interp_c0 +
+ b[CWeather::OldWeatherType] * interp_c1 +
+ a[CWeather::NewWeatherType] * interp_c2 +
+ b[CWeather::NewWeatherType] * interp_c3;
+}
+
+float CTimeCycle::Interpolate(uint8 *a, uint8 *b)
+{
+ return a[CWeather::OldWeatherType] * interp_c0 +
+ b[CWeather::OldWeatherType] * interp_c1 +
+ a[CWeather::NewWeatherType] * interp_c2 +
+ b[CWeather::NewWeatherType] * interp_c3;
+}
+
+float CTimeCycle::Interpolate(int16 *a, int16 *b)
+{
+ return a[CWeather::OldWeatherType] * interp_c0 +
+ b[CWeather::OldWeatherType] * interp_c1 +
+ a[CWeather::NewWeatherType] * interp_c2 +
+ b[CWeather::NewWeatherType] * interp_c3;
+}
+
+void
+CTimeCycle::StartExtraColour(int32 c, bool fade)
+{
+ m_bExtraColourOn = true;
+ m_ExtraColour = c;
+ if(fade)
+ m_ExtraColourInter = 0.0f;
+ else
+ m_ExtraColourInter = 1.0f;
+}
+
+void
+CTimeCycle::StopExtraColour(bool fade)
+{
+ m_bExtraColourOn = false;
+ if(!fade)
+ m_ExtraColourInter = 0.0f;
+}
+
void
CTimeCycle::Update(void)
{
@@ -220,14 +319,14 @@ CTimeCycle::Update(void)
int h2 = (h1+1)%24;
int w1 = CWeather::OldWeatherType;
int w2 = CWeather::NewWeatherType;
- float timeInterp = CClock::GetMinutes()/60.0f;
+ float timeInterp = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f;
// coefficients for a bilinear interpolation
- float c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue);
- float c1 = timeInterp * (1.0f-CWeather::InterpolationValue);
- float c2 = (1.0f-timeInterp) * CWeather::InterpolationValue;
- float c3 = timeInterp * CWeather::InterpolationValue;
+ interp_c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue);
+ interp_c1 = timeInterp * (1.0f-CWeather::InterpolationValue);
+ interp_c2 = (1.0f-timeInterp) * CWeather::InterpolationValue;
+ interp_c3 = timeInterp * CWeather::InterpolationValue;
-#define INTERP(v) v[h1][w1]*c0 + v[h2][w1]*c1 + v[h1][w2]*c2 + v[h2][w2]*c3
+#define INTERP(v) Interpolate(v[h1], v[h2])
m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed);
m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen);
@@ -240,16 +339,22 @@ CTimeCycle::Update(void)
m_fCurrentAmbientRed = INTERP(m_nAmbientRed);
m_fCurrentAmbientGreen = INTERP(m_nAmbientGreen);
m_fCurrentAmbientBlue = INTERP(m_nAmbientBlue);
- m_fCurrentAmbientRed /= 255.0f;
- m_fCurrentAmbientGreen /= 255.0f;
- m_fCurrentAmbientBlue /= 255.0f;
+
+ m_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj);
+ m_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj);
+ m_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj);
+
+ m_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl);
+ m_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl);
+ m_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl);
+
+ m_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl);
+ m_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl);
+ m_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl);
m_fCurrentDirectionalRed = INTERP(m_nDirectionalRed);
m_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen);
m_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue);
- m_fCurrentDirectionalRed /= 255.0f;
- m_fCurrentDirectionalGreen /= 255.0f;
- m_fCurrentDirectionalBlue /= 255.0f;
m_nCurrentSunCoreRed = INTERP(m_nSunCoreRed);
m_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen);
@@ -259,15 +364,15 @@ CTimeCycle::Update(void)
m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen);
m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue);
- m_fCurrentSunSize = INTERP(m_fSunSize);
- m_fCurrentSpriteSize = INTERP(m_fSpriteSize);
- m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness);
+ m_fCurrentSunSize = INTERP(m_fSunSize)/10.0f;
+ m_fCurrentSpriteSize = INTERP(m_fSpriteSize)/10.0f;
+ m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness)/10.0f;
m_nCurrentShadowStrength = INTERP(m_nShadowStrength);
m_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength);
- m_nCurrentTreeShadowStrength = INTERP(m_nTreeShadowStrength);
+ m_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength);
m_fCurrentFarClip = INTERP(m_fFarClip);
m_fCurrentFogStart = INTERP(m_fFogStart);
- m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness);
+ m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness)/10.0f;
m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed);
m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen);
@@ -284,26 +389,131 @@ CTimeCycle::Update(void)
m_fCurrentBlurRed = INTERP(m_fBlurRed);
m_fCurrentBlurGreen = INTERP(m_fBlurGreen);
m_fCurrentBlurBlue = INTERP(m_fBlurBlue);
- m_fCurrentBlurAlpha = INTERP(m_fBlurAlpha);
- if(TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE)
- TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, m_fCurrentBlurAlpha, MOTION_BLUR_LIGHT_SCENE);
+ m_fCurrentWaterRed = INTERP(m_fWaterRed);
+ m_fCurrentWaterGreen = INTERP(m_fWaterGreen);
+ m_fCurrentWaterBlue = INTERP(m_fWaterBlue);
+ m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha);
+#undef INTERP
if(m_FogReduction != 0)
m_fCurrentFarClip = Max(m_fCurrentFarClip, m_FogReduction/64.0f * 650.0f);
- m_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3;
- m_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3;
- m_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3;
m_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF;
- float sunAngle = 2*PI*(CClock::GetMinutes() + CClock::GetHours()*60)/(24*60);
+ float sunAngle = 2*PI*(CClock::GetSeconds()/60.0f + CClock::GetMinutes() + CClock::GetHours()*60)/(24*60);
CVector &sunPos = GetSunDirection();
sunPos.x = Sin(sunAngle);
sunPos.y = 1.0f;
sunPos.z = 0.2f - Cos(sunAngle);
sunPos.Normalise();
+ if(m_bExtraColourOn)
+ m_ExtraColourInter = Min(1.0f, m_ExtraColourInter + CTimer::GetTimeStep()/120.0f);
+ else
+ m_ExtraColourInter = Max(-.0f, m_ExtraColourInter - CTimer::GetTimeStep()/120.0f);
+ if(m_ExtraColourInter > 0.0f){
+#define INTERP(extra,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS] + (1.0f-m_ExtraColourInter)*cur)
+#define INTERPscl(extra,scl,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS]/scl + (1.0f-m_ExtraColourInter)*cur)
+ if(m_nSkyTopRed[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 ||
+ m_nSkyTopGreen[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 ||
+ m_nSkyTopBlue[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0){
+ m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed,m_nCurrentSkyTopRed);
+ m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen,m_nCurrentSkyTopGreen);
+ m_nCurrentSkyTopBlue = INTERP(m_nSkyTopBlue,m_nCurrentSkyTopBlue);
+
+ m_nCurrentSkyBottomRed = INTERP(m_nSkyBottomRed,m_nCurrentSkyBottomRed);
+ m_nCurrentSkyBottomGreen = INTERP(m_nSkyBottomGreen,m_nCurrentSkyBottomGreen);
+ m_nCurrentSkyBottomBlue = INTERP(m_nSkyBottomBlue,m_nCurrentSkyBottomBlue);
+
+ m_nCurrentSunCoreRed = INTERP(m_nSunCoreRed,m_nCurrentSunCoreRed);
+ m_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen,m_nCurrentSunCoreGreen);
+ m_nCurrentSunCoreBlue = INTERP(m_nSunCoreBlue,m_nCurrentSunCoreBlue);
+
+ m_nCurrentSunCoronaRed = INTERP(m_nSunCoronaRed,m_nCurrentSunCoronaRed);
+ m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen,m_nCurrentSunCoronaGreen);
+ m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue,m_nCurrentSunCoronaBlue);
+
+ m_fCurrentSunSize = INTERPscl(m_fSunSize,10.0f,m_fCurrentSunSize);
+
+ m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed,m_nCurrentLowCloudsRed);
+ m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen,m_nCurrentLowCloudsGreen);
+ m_nCurrentLowCloudsBlue = INTERP(m_nLowCloudsBlue,m_nCurrentLowCloudsBlue);
+
+ m_nCurrentFluffyCloudsTopRed = INTERP(m_nFluffyCloudsTopRed,m_nCurrentFluffyCloudsTopRed);
+ m_nCurrentFluffyCloudsTopGreen = INTERP(m_nFluffyCloudsTopGreen,m_nCurrentFluffyCloudsTopGreen);
+ m_nCurrentFluffyCloudsTopBlue = INTERP(m_nFluffyCloudsTopBlue,m_nCurrentFluffyCloudsTopBlue);
+
+ m_nCurrentFluffyCloudsBottomRed = INTERP(m_nFluffyCloudsBottomRed,m_nCurrentFluffyCloudsBottomRed);
+ m_nCurrentFluffyCloudsBottomGreen = INTERP(m_nFluffyCloudsBottomGreen,m_nCurrentFluffyCloudsBottomGreen);
+ m_nCurrentFluffyCloudsBottomBlue = INTERP(m_nFluffyCloudsBottomBlue,m_nCurrentFluffyCloudsBottomBlue);
+
+ m_fCurrentWaterRed = INTERP(m_fWaterRed,m_fCurrentWaterRed);
+ m_fCurrentWaterGreen = INTERP(m_fWaterGreen,m_fCurrentWaterGreen);
+ m_fCurrentWaterBlue = INTERP(m_fWaterBlue,m_fCurrentWaterBlue);
+ m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha,m_fCurrentWaterAlpha);
+ }
+
+ m_fCurrentAmbientRed = INTERP(m_nAmbientRed,m_fCurrentAmbientRed);
+ m_fCurrentAmbientGreen = INTERP(m_nAmbientGreen,m_fCurrentAmbientGreen);
+ m_fCurrentAmbientBlue = INTERP(m_nAmbientBlue,m_fCurrentAmbientBlue);
+
+ m_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj,m_fCurrentAmbientRed_Obj);
+ m_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj,m_fCurrentAmbientGreen_Obj);
+ m_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj,m_fCurrentAmbientBlue_Obj);
+
+ m_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl,m_fCurrentAmbientRed_Bl);
+ m_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl,m_fCurrentAmbientGreen_Bl);
+ m_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl,m_fCurrentAmbientBlue_Bl);
+
+ m_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl,m_fCurrentAmbientRed_Obj_Bl);
+ m_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl,m_fCurrentAmbientGreen_Obj_Bl);
+ m_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl,m_fCurrentAmbientBlue_Obj_Bl);
+
+ m_fCurrentDirectionalRed = INTERP(m_nDirectionalRed,m_fCurrentDirectionalRed);
+ m_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen,m_fCurrentDirectionalGreen);
+ m_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue,m_fCurrentDirectionalBlue);
+
+ m_fCurrentSpriteSize = INTERPscl(m_fSpriteSize,10.0f,m_fCurrentSpriteSize);
+ m_fCurrentSpriteBrightness = INTERPscl(m_fSpriteBrightness,10.0f,m_fCurrentSpriteBrightness);
+ m_nCurrentShadowStrength = INTERP(m_nShadowStrength,m_nCurrentShadowStrength);
+ m_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength,m_nCurrentLightShadowStrength);
+ m_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength,m_nCurrentPoleShadowStrength);
+ m_fCurrentFarClip = INTERP(m_fFarClip,m_fCurrentFarClip);
+ m_fCurrentFogStart = INTERP(m_fFogStart,m_fCurrentFogStart);
+ m_fCurrentLightsOnGroundBrightness = INTERPscl(m_fLightsOnGroundBrightness,10.0f,m_fCurrentLightsOnGroundBrightness);
+
+ m_fCurrentBlurRed = INTERP(m_fBlurRed,m_fCurrentBlurRed);
+ m_fCurrentBlurGreen = INTERP(m_fBlurGreen,m_fCurrentBlurGreen);
+ m_fCurrentBlurBlue = INTERP(m_fBlurBlue,m_fCurrentBlurBlue);
+
+#undef INTERP
+#undef INTERPscl
+ }
+
+ if(TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE)
+ TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, 5, MOTION_BLUR_LIGHT_SCENE);
+
+ m_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3;
+ m_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3;
+ m_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3;
+
+ m_fCurrentAmbientRed /= 255.0f;
+ m_fCurrentAmbientGreen /= 255.0f;
+ m_fCurrentAmbientBlue /= 255.0f;
+ m_fCurrentAmbientRed_Obj /= 255.0f;
+ m_fCurrentAmbientGreen_Obj /= 255.0f;
+ m_fCurrentAmbientBlue_Obj /= 255.0f;
+ m_fCurrentAmbientRed_Bl /= 255.0f;
+ m_fCurrentAmbientGreen_Bl /= 255.0f;
+ m_fCurrentAmbientBlue_Bl /= 255.0f;
+ m_fCurrentAmbientRed_Obj_Bl /= 255.0f;
+ m_fCurrentAmbientGreen_Obj_Bl /= 255.0f;
+ m_fCurrentAmbientBlue_Obj_Bl /= 255.0f;
+ m_fCurrentDirectionalRed /= 255.0f;
+ m_fCurrentDirectionalGreen /= 255.0f;
+ m_fCurrentDirectionalBlue /= 255.0f;
+
CShadows::CalcPedShadowValues(sunPos,
&m_fShadowFrontX[m_CurrentStoredValue], &m_fShadowFrontY[m_CurrentStoredValue],
&m_fShadowSideX[m_CurrentStoredValue], &m_fShadowSideY[m_CurrentStoredValue],
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index d5d7b67a..da911b75 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -2,50 +2,71 @@
class CTimeCycle
{
- static int32 m_nAmbientRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
- static float m_fSunSize[NUMHOURS][NUMWEATHERS];
- static float m_fSpriteSize[NUMHOURS][NUMWEATHERS];
- static float m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
- static int16 m_nShadowStrength[NUMHOURS][NUMWEATHERS];
- static int16 m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
- static int16 m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS];
- static float m_fFogStart[NUMHOURS][NUMWEATHERS];
- static float m_fFarClip[NUMHOURS][NUMWEATHERS];
- static float m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
- static int32 m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
- static int32 m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
- static int32 m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
- static int32 m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
- static float m_fBlurRed[NUMHOURS][NUMWEATHERS];
- static float m_fBlurGreen[NUMHOURS][NUMWEATHERS];
- static float m_fBlurBlue[NUMHOURS][NUMWEATHERS];
- static float m_fBlurAlpha[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
+ static int8 m_fSunSize[NUMHOURS][NUMWEATHERS];
+ static int8 m_fSpriteSize[NUMHOURS][NUMWEATHERS];
+ static int8 m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nShadowStrength[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
+ static int16 m_fFogStart[NUMHOURS][NUMWEATHERS];
+ static int16 m_fFarClip[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fBlurRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fBlurGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fBlurBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
static float m_fCurrentAmbientRed;
static float m_fCurrentAmbientGreen;
static float m_fCurrentAmbientBlue;
+ static float m_fCurrentAmbientRed_Obj;
+ static float m_fCurrentAmbientGreen_Obj;
+ static float m_fCurrentAmbientBlue_Obj;
+ static float m_fCurrentAmbientRed_Bl;
+ static float m_fCurrentAmbientGreen_Bl;
+ static float m_fCurrentAmbientBlue_Bl;
+ static float m_fCurrentAmbientRed_Obj_Bl;
+ static float m_fCurrentAmbientGreen_Obj_Bl;
+ static float m_fCurrentAmbientBlue_Obj_Bl;
static float m_fCurrentDirectionalRed;
static float m_fCurrentDirectionalGreen;
static float m_fCurrentDirectionalBlue;
@@ -66,7 +87,7 @@ class CTimeCycle
static float m_fCurrentSpriteBrightness;
static int32 m_nCurrentShadowStrength;
static int32 m_nCurrentLightShadowStrength;
- static int32 m_nCurrentTreeShadowStrength;
+ static int32 m_nCurrentPoleShadowStrength;
static float m_fCurrentFogStart;
static float m_fCurrentFarClip;
static float m_fCurrentLightsOnGroundBrightness;
@@ -82,7 +103,10 @@ class CTimeCycle
static float m_fCurrentBlurRed;
static float m_fCurrentBlurGreen;
static float m_fCurrentBlurBlue;
- static float m_fCurrentBlurAlpha;
+ static float m_fCurrentWaterRed;
+ static float m_fCurrentWaterGreen;
+ static float m_fCurrentWaterBlue;
+ static float m_fCurrentWaterAlpha;
static int32 m_nCurrentFogColourRed;
static int32 m_nCurrentFogColourGreen;
static int32 m_nCurrentFogColourBlue;
@@ -90,6 +114,9 @@ class CTimeCycle
static int32 m_FogReduction;
public:
+ static int32 m_bExtraColourOn;
+ static int32 m_ExtraColour;
+ static float m_ExtraColourInter;
static int32 m_CurrentStoredValue;
static CVector m_VectorToSun[16];
static float m_fShadowFrontX[16];
@@ -102,6 +129,15 @@ public:
static float GetAmbientRed(void) { return m_fCurrentAmbientRed; }
static float GetAmbientGreen(void) { return m_fCurrentAmbientGreen; }
static float GetAmbientBlue(void) { return m_fCurrentAmbientBlue; }
+ static float GetAmbientRed_Obj(void) { return m_fCurrentAmbientRed_Obj; }
+ static float GetAmbientGreen_Obj(void) { return m_fCurrentAmbientGreen_Obj; }
+ static float GetAmbientBlue_Obj(void) { return m_fCurrentAmbientBlue_Obj; }
+ static float GetAmbientRed_Bl(void) { return m_fCurrentAmbientRed_Bl; }
+ static float GetAmbientGreen_Bl(void) { return m_fCurrentAmbientGreen_Bl; }
+ static float GetAmbientBlue_Bl(void) { return m_fCurrentAmbientBlue_Bl; }
+ static float GetAmbientRed_Obj_Bl(void) { return m_fCurrentAmbientRed_Obj_Bl; }
+ static float GetAmbientGreen_Obj_Bl(void) { return m_fCurrentAmbientGreen_Obj_Bl; }
+ static float GetAmbientBlue_Obj_Bl(void) { return m_fCurrentAmbientBlue_Obj_Bl; }
static float GetDirectionalRed(void) { return m_fCurrentDirectionalRed; }
static float GetDirectionalGreen(void) { return m_fCurrentDirectionalGreen; }
static float GetDirectionalBlue(void) { return m_fCurrentDirectionalBlue; }
@@ -140,8 +176,21 @@ public:
static int32 GetFogBlue(void) { return m_nCurrentFogColourBlue; }
static int32 GetFogReduction(void) { return m_FogReduction; }
+ static int32 GetBlurRed(void) { return m_fCurrentBlurRed; }
+ static int32 GetBlurGreen(void) { return m_fCurrentBlurGreen; }
+ static int32 GetBlurBlue(void) { return m_fCurrentBlurBlue; }
+ static int32 GetWaterRed(void) { return m_fCurrentWaterRed; }
+ static int32 GetWaterGreen(void) { return m_fCurrentWaterGreen; }
+ static int32 GetWaterBlue(void) { return m_fCurrentWaterBlue; }
+ static int32 GetWaterAlpha(void) { return m_fCurrentWaterAlpha; }
+
static void Initialise(void);
static void Update(void);
+ static float Interpolate(int8 *a, int8 *b);
+ static float Interpolate(uint8 *a, uint8 *b);
+ static float Interpolate(int16 *a, int16 *b);
+ static void StartExtraColour(int32 c, bool fade);
+ static void StopExtraColour(bool fade);
static CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; }
static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; }
static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; }
diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp
index 6133b1d7..13f52334 100644
--- a/src/render/WaterLevel.cpp
+++ b/src/render/WaterLevel.cpp
@@ -6,6 +6,7 @@
#include "Weather.h"
#include "Camera.h"
#include "Vehicle.h"
+#include "PlayerPed.h"
#include "Boat.h"
#include "World.h"
#include "General.h"
@@ -19,46 +20,101 @@
#include "CdStream.h"
#include "Pad.h"
#include "RenderBuffer.h"
+#include <rwcore.h>
#include <rpworld.h>
+#include <rpmatfx.h>
+#include "Occlusion.h"
+#include "Replay.h"
#include "WaterLevel.h"
+#include "SurfaceTable.h"
+#define RwIm3DVertexSet_RGBA(vert, rgba) RwIm3DVertexSetRGBA(vert, rgba.red, rgba.green, rgba.blue, rgba.alpha) // (RwRGBAAssign(&(_dst)->color, &_src))
float TEXTURE_ADDU;
float TEXTURE_ADDV;
+float _TEXTURE_MASK_ADDU;
+float _TEXTURE_MASK_ADDV;
+
+float _TEXTURE_WAKE_ADDU;
+float _TEXTURE_WAKE_ADDV;
+
int32 CWaterLevel::ms_nNoOfWaterLevels;
float CWaterLevel::ms_aWaterZs[48];
CRect CWaterLevel::ms_aWaterRects[48];
-uint8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE];
-uint8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE];
+uint8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SECTORS][WATER_BLOCK_SECTORS];
+uint8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SECTORS][WATER_FINEBLOCK_SECTORS];
bool CWaterLevel::WavesCalculatedThisFrame;
+
+
+bool CWaterLevel::RequireWavySector;
+bool CWaterLevel::MaskCalculatedThisFrame;
+CVector CWaterLevel::PreCalculatedMaskPosn;
+bool CWaterLevel::m_bRenderSeaBed;
+int32 CWaterLevel::m_nRenderWaterLayers;
+
RpAtomic *CWaterLevel::ms_pWavyAtomic;
-RpGeometry *CWaterLevel::apGeomArray[8];
-int16 CWaterLevel::nGeomUsed;
+RpAtomic *CWaterLevel::ms_pMaskAtomic;
//"Custom" Don´t Render Water Toggle
bool gbDontRenderWater;
-//RwTexture *gpWaterTex;
-//RwRaster *gpWaterRaster;
RwTexture *gpWaterTex;
-RwRaster *gpWaterRaster;
+RwTexture *gpWaterEnvTex;
+RwTexture *gpWaterEnvBaseTex;
+RwTexture *gpWaterWakeTex;
+RwRaster *gpWaterRaster;
+RwRaster *gpWaterEnvRaster;
+RwRaster *gpWaterEnvBaseRaster;
+RwRaster *gpWaterWakeRaster;
-const float fAdd1 = 180.0f;
-const float fAdd2 = 80.0f;
-const float fRedMult = 0.6f;
-const float fGreenMult = 1.0f;
-const float fBlueMult = 1.4f;
+bool _bSeaLife;
+float _fWaterZOffset = 0.5f;
+#ifdef PC_WATER
+float fEnvScale = 0.25f;
+#else
+float fEnvScale = 0.5f;
+#endif
+float fWave2InvLength = 0.03f;
+float fWave2NormScale = 0.5f;
+float fWave2Ampl = 0.1f;
+uint8 nWaterAlpha = 192;
+uint8 nWakeAlpha = 192;
+float fUnder1 = 4.0;
+float fUnder2 = 2.5;
+float fUnder3 = 1.5;
+int nMaskAlpha = 230;
+float fAdd1 = 180.0f;
+float fAdd2 = 80.0;
+float fRedMult = 0.6f;
+float fGreenMult = 1.0f;
+float fBlueMult = 1.4f;
+float fAlphaMult = 500.0f;
+float fAlphaBase = 30.0f;
+float fRandomMoveDiv = 8.0f;
+float fRandomDamp = 0.99f;
+float fNormMult = 2.0f;
+float fNormMultB = 1.0f;
+float fBumpScale = 1.5;
+float fBumpTexRepeat = 2.0;
+float fNormalDirectionScalar1 = 2.0f;
+float fNormalDirectionScalar2 = 1.0f;
+bool bTestDoNormals = true;
+float fSeaBedZ = 25.0f;
+float aAlphaFade[5] = { 0.4f, 1.0f, 0.2f, 1.0f, 0.4f}; //CWaterLevel::RenderWakeSegment
+float fFlatWaterBlendRange = 0.05f;
+float fStartBlendDistanceAdd = 64.0f;
+float fMinWaterAlphaMult = -30.0f;
void
-CWaterLevel::Initialise(Const char *pWaterDat)
+WaterLevelInitialise(Const char *pWaterDat)
{
- ms_nNoOfWaterLevels = 0;
+ CWaterLevel::ms_nNoOfWaterLevels = 0;
- int32 hFile = -1;
+ int32 hFile;
do
{
@@ -70,11 +126,11 @@ CWaterLevel::Initialise(Const char *pWaterDat)
{
if ( hFile >= 0 )
{
- CFileMgr::Read(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels));
- CFileMgr::Read(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs));
- CFileMgr::Read(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects));
- CFileMgr::Read(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList));
- CFileMgr::Read(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList));
+ CFileMgr::Read(hFile, (char *)&CWaterLevel::ms_nNoOfWaterLevels, sizeof(CWaterLevel::ms_nNoOfWaterLevels));
+ CFileMgr::Read(hFile, (char *)CWaterLevel::ms_aWaterZs, sizeof(CWaterLevel::ms_aWaterZs));
+ CFileMgr::Read(hFile, (char *)CWaterLevel::ms_aWaterRects, sizeof(CWaterLevel::ms_aWaterRects));
+ CFileMgr::Read(hFile, (char *)CWaterLevel::aWaterBlockList, sizeof(CWaterLevel::aWaterBlockList));
+ CFileMgr::Read(hFile, (char *)CWaterLevel::aWaterFineBlockList, sizeof(CWaterLevel::aWaterFineBlockList));
}
CFileMgr::CloseFile(hFile);
@@ -85,14 +141,27 @@ CWaterLevel::Initialise(Const char *pWaterDat)
int32 slot = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slot);
- if ( gpWaterTex == NULL )
- gpWaterTex = RwTextureRead("water_old", NULL);
+ if ( gpWaterTex == nil )
+ gpWaterTex = RwTextureRead("waterclear256", nil);
gpWaterRaster = RwTextureGetRaster(gpWaterTex);
+ if ( gpWaterEnvTex == nil )
+ gpWaterEnvTex = RwTextureRead("waterreflection2", nil);
+ gpWaterEnvRaster = RwTextureGetRaster(gpWaterEnvTex);
+
+#ifdef PC_WATER
+ if ( gpWaterEnvBaseTex == nil )
+ gpWaterEnvBaseTex = RwTextureRead("sandywater", nil);
+ gpWaterEnvBaseRaster = RwTextureGetRaster(gpWaterEnvBaseTex);
+#endif
+
+ if ( gpWaterWakeTex == nil )
+ gpWaterWakeTex = RwTextureRead("waterwake", nil);
+ gpWaterWakeRaster = RwTextureGetRaster(gpWaterWakeTex);
+
CTxdStore::PopCurrentTxd();
- CreateWavyAtomic();
- FreeBoatWakeArray();
+ CWaterLevel::CreateWavyAtomic();
printf("Done Initing waterlevels\n");
}
@@ -100,92 +169,153 @@ CWaterLevel::Initialise(Const char *pWaterDat)
void
CWaterLevel::Shutdown()
{
- FreeBoatWakeArray();
DestroyWavyAtomic();
- if ( gpWaterTex != NULL )
- {
- RwTextureDestroy(gpWaterTex);
- gpWaterTex = NULL;
- }
+#define _DELETE_TEXTURE(t) if ( t ) \
+ { \
+ RwTextureDestroy(t); \
+ t = nil; \
+ }
+
+ _DELETE_TEXTURE(gpWaterTex);
+ _DELETE_TEXTURE(gpWaterEnvTex);
+ _DELETE_TEXTURE(gpWaterEnvBaseTex);
+
+#undef _DELETE_TEXTURE
}
void
CWaterLevel::CreateWavyAtomic()
{
RpGeometry *wavyGeometry;
+ RpGeometry *maskGeometry;
RpMaterial *wavyMaterial;
- RpTriangle *wavyTriangles;
+ RpMaterial *maskMaterial;
+
+ RpTriangle *wavytlist;
+ RpTriangle *masktlist;
+
RpMorphTarget *wavyMorphTarget;
- RwSphere boundingSphere;
+ RpMorphTarget *maskMorphTarget;
+
+ RwSphere boundingSphere;
+
RwV3d *wavyVert;
-
+ RwV3d *wavyNormal;
+
+ RwV3d *maskVert;
+ RwV3d *maskNormal;
+
RwFrame *wavyFrame;
+ RwFrame *maskFrame;
{
- wavyGeometry = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP
+ wavyGeometry = RpGeometryCreate(17*17, 512, rpGEOMETRYTRISTRIP
|rpGEOMETRYTEXTURED
|rpGEOMETRYPRELIT
+ |rpGEOMETRYNORMALS
|rpGEOMETRYMODULATEMATERIALCOLOR);
-
- ASSERT(wavyGeometry != NULL);
-
+#ifdef PC_WATER
+ RpGeometryAddMorphTarget(wavyGeometry);
+#endif
+ }
+
+ {
+ maskGeometry = RpGeometryCreate(33*33, 2048, rpGEOMETRYTRISTRIP
+ |rpGEOMETRYTEXTURED
+ |rpGEOMETRYPRELIT
+ |rpGEOMETRYNORMALS
+ |rpGEOMETRYMODULATEMATERIALCOLOR);
+#ifdef PC_WATER
+ RpGeometryAddMorphTarget(maskGeometry);
+#endif
}
{
wavyMaterial = RpMaterialCreate();
-
- ASSERT(wavyMaterial != NULL);
- ASSERT(gpWaterTex != NULL);
-
RpMaterialSetTexture(wavyMaterial, gpWaterTex);
+ RwRGBA watercolor = { 255, 255, 255, 192 };
+ RpMaterialSetColor(wavyMaterial, &watercolor);
}
{
- wavyTriangles = RpGeometryGetTriangles(wavyGeometry);
-
- ASSERT(wavyTriangles != NULL);
- /*
- [B] [C]
- ***********
- * * *
- * * *
- * * *
- * * *
- ***********
- [A] [D]
- */
+ maskMaterial = RpMaterialCreate();
+#ifdef PC_WATER
+ RpMaterialSetTexture(maskMaterial, gpWaterEnvBaseTex);
+#else
+ RpMaterialSetTexture(maskMaterial, gpWaterTex);
+#endif
+ RwRGBA watercolor = { 255, 255, 255, 192 };
+ RpMaterialSetColor(maskMaterial, &watercolor);
+ }
+
+ {
+ wavytlist = RpGeometryGetTriangles(wavyGeometry);
- for ( int32 i = 0; i < 8; i++ )
+ for ( int32 i = 0; i < 16; i++ )
{
- for ( int32 j = 0; j < 8; j++ )
- {
+ for ( int32 j = 0; j < 16; j++ )
+ {
+ const RwUInt16 base = (RwUInt16)((16 + 1)*i+j);
+
+ RpGeometryTriangleSetVertexIndices(wavyGeometry,
+ wavytlist, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+16+2));
+
RpGeometryTriangleSetVertexIndices(wavyGeometry,
- &wavyTriangles[2 * 8*i + 2*j + 0], /*A*/9*i+j+0, /*B*/9*i+j+1, /*C*/9*i+j+9+1);
-
- RpGeometryTriangleSetVertexIndices(wavyGeometry,
- &wavyTriangles[2 * 8*i + 2*j + 1], /*A*/9*i+j+0, /*C*/9*i+j+9+1, /*D*/9*i+j+9 );
+ (wavytlist+1), (RwInt16)base, (RwInt16)(base+16+2), (RwInt16)(base+16+1));
- RpGeometryTriangleSetMaterial(wavyGeometry, &wavyTriangles[2 * 8*i + 2*j + 0], wavyMaterial);
- RpGeometryTriangleSetMaterial(wavyGeometry, &wavyTriangles[2 * 8*i + 2*j + 1], wavyMaterial);
+ RpGeometryTriangleSetMaterial(wavyGeometry, wavytlist, wavyMaterial);
+
+ RpGeometryTriangleSetMaterial(wavyGeometry, (wavytlist+1), wavyMaterial);
+
+ wavytlist+=2;
}
}
}
+ {
+ masktlist = RpGeometryGetTriangles(maskGeometry);
+
+ for ( int32 i = 0; i < 32; i++ )
+ {
+ for ( int32 j = 0; j < 32; j++ )
+ {
+ const RwUInt16 base = (RwUInt16)((32 + 1)*i+j);
+
+ RpGeometryTriangleSetVertexIndices(maskGeometry,
+ masktlist, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+32+2));
+
+ RpGeometryTriangleSetVertexIndices(maskGeometry,
+ (masktlist+1), (RwInt16)base, (RwInt16)(base+32+2), (RwInt16)(base+32+1));
+
+ RpGeometryTriangleSetMaterial(maskGeometry, masktlist, maskMaterial);
+
+ RpGeometryTriangleSetMaterial(maskGeometry, (masktlist+1), maskMaterial);
+
+ masktlist+=2;
+ }
+ }
+ }
{
wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0);
- ASSERT(wavyMorphTarget != NULL);
- wavyVert = RpMorphTargetGetVertices(wavyMorphTarget);
- ASSERT(wavyVert != NULL);
+ wavyVert = RpMorphTargetGetVertices(wavyMorphTarget);
+ wavyNormal = RpMorphTargetGetVertexNormals(wavyMorphTarget);
- for ( int32 i = 0; i < 9; i++ )
+ for ( int32 i = 0; i < 17; i++ )
{
- for ( int32 j = 0; j < 9; j++ )
+ for ( int32 j = 0; j < 17; j++ )
{
- wavyVert[9*i+j].x = (float)i * 4.0f;
- wavyVert[9*i+j].y = (float)j * 4.0f;
- wavyVert[9*i+j].z = 0.0f;
+ (*wavyVert).x = (float)i * 2.0f;
+ (*wavyVert).y = (float)j * 2.0f;
+ (*wavyVert).z = 0.0f;
+
+ (*wavyNormal).x = 0.0f;
+ (*wavyNormal).y = 0.0f;
+ (*wavyNormal).z = 1.0f;
+
+ wavyVert++;
+ wavyNormal++;
}
}
@@ -194,60 +324,112 @@ CWaterLevel::CreateWavyAtomic()
RpGeometryUnlock(wavyGeometry);
}
-
{
- wavyFrame = RwFrameCreate();
- ASSERT( wavyFrame != NULL );
+ maskMorphTarget = RpGeometryGetMorphTarget(maskGeometry, 0);
+ maskVert = RpMorphTargetGetVertices(maskMorphTarget);
+ maskNormal = RpMorphTargetGetVertexNormals(maskMorphTarget);
- ms_pWavyAtomic = RpAtomicCreate();
- ASSERT( ms_pWavyAtomic != NULL );
+ for ( int32 i = 0; i < 33; i++ )
+ {
+ for ( int32 j = 0; j < 33; j++ )
+ {
+ (*maskVert).x = (float)i * 2.0f;
+ (*maskVert).y = (float)j * 2.0f;
+ (*maskVert).z = 0.0f;
+
+ (*maskNormal).x = 0.0f;
+ (*maskNormal).y = 0.0f;
+ (*maskNormal).z = 1.0f;
+
+ maskVert++;
+ maskNormal++;
+ }
+ }
+ RpMorphTargetCalcBoundingSphere(maskMorphTarget, &boundingSphere);
+ RpMorphTargetSetBoundingSphere(maskMorphTarget, &boundingSphere);
+ RpGeometryUnlock(maskGeometry);
+ }
+
+ {
+ wavyFrame = RwFrameCreate();
+ ms_pWavyAtomic = RpAtomicCreate();
RpAtomicSetGeometry(ms_pWavyAtomic, wavyGeometry, 0);
RpAtomicSetFrame(ms_pWavyAtomic, wavyFrame);
RpMaterialDestroy(wavyMaterial);
RpGeometryDestroy(wavyGeometry);
}
+
+ {
+ maskFrame = RwFrameCreate();
+ ms_pMaskAtomic = RpAtomicCreate();
+ RpAtomicSetGeometry(ms_pMaskAtomic, maskGeometry, 0);
+ RpAtomicSetFrame(ms_pMaskAtomic, maskFrame);
+ RpMaterialDestroy(maskMaterial);
+ RpGeometryDestroy(maskGeometry);
+ }
+
+ static RwFrame *wakeEnvFrame;
+
+ if ( wakeEnvFrame == nil )
+ {
+ wakeEnvFrame = RwFrameCreate();
+ RwMatrixSetIdentity(RwFrameGetMatrix(wakeEnvFrame));
+ RwFrameUpdateObjects(wakeEnvFrame);
+ }
+
+ RpMatFXMaterialSetEffects(maskMaterial, rpMATFXEFFECTENVMAP);
+ RpMatFXMaterialSetupEnvMap(maskMaterial, gpWaterEnvTex, wakeEnvFrame, TRUE, fEnvScale);
+ RpMatFXAtomicEnableEffects(ms_pMaskAtomic);
}
void
CWaterLevel::DestroyWavyAtomic()
{
- RwFrame *frame;
-
- frame = RpAtomicGetFrame(ms_pWavyAtomic);
-
- RpAtomicDestroy(ms_pWavyAtomic);
+#define _DELETE_ATOMIC(a) \
+ { \
+ RwFrame *frame; \
+ frame = RpAtomicGetFrame(a); \
+ RpAtomicDestroy(a); \
+ RwFrameDestroy(frame); \
+ }
+
+ _DELETE_ATOMIC(ms_pWavyAtomic);
+ _DELETE_ATOMIC(ms_pMaskAtomic);
- RwFrameDestroy(frame);
+#undef _DELETE_ATOMIC
}
bool
CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ)
{
- int32 x = WATER_HUGE_X(fX);
- int32 y = WATER_HUGE_Y(fY);
-
- ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE );
- ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE );
+ int32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET);
+ int32 y = WATER_TO_SMALL_SECTOR_Y(fY);
+
+#ifdef FIX_BUGS
+ if ( x < 0 || x >= MAX_SMALL_SECTORS ) return false;
+ if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;
+#endif
uint8 nBlock = aWaterFineBlockList[x][y];
- if ( nBlock == 128 )
+ if ( nBlock == 0x80 )
return false;
- ASSERT( pfOutLevel != NULL );
+ ASSERT( pfOutLevel != nil );
*pfOutLevel = ms_aWaterZs[nBlock];
float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
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)) )
- * (TWOPI / MAX_HUGE_SECTORS ) + fAngle
+ ( WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE
+ + WATER_UNSIGN_X(fX + WATER_X_OFFSET) - x*SMALL_SECTOR_SIZE )
+
+ * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle
);
- float fWindFactor = CWeather::Wind * 0.7f + 0.3f;
+ float fWindFactor = CWeather::WindClipped * 0.4f + 0.2f;
*pfOutLevel += fWave * fWindFactor;
@@ -263,35 +445,69 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool
bool
CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel)
{
- int32 x = WATER_HUGE_X(fX);
- int32 y = WATER_HUGE_Y(fY);
-
- ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE );
- ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE );
+ int32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET);
+ int32 y = WATER_TO_SMALL_SECTOR_Y(fY);
+
+#ifdef FIX_BUGS
+ if ( x < 0 || x >= MAX_SMALL_SECTORS ) return false;
+ if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;
+#endif
uint8 nBlock = aWaterFineBlockList[x][y];
- if ( nBlock == 128 )
+ if ( nBlock == 0x80 )
return false;
- ASSERT( pfOutLevel != NULL );
+ ASSERT( pfOutLevel != nil );
*pfOutLevel = ms_aWaterZs[nBlock];
return true;
}
-inline float
-_GetWaterDrawDist()
+float
+CWaterLevel::GetWaterWavesOnly(short x, short y)
{
- // if z less then 15.0f return 1200.0f
- if ( TheCamera.GetPosition().z < 15.0f )
- return 1200.0f;
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+
+ float fWindFactor = CWeather::WindClipped * 0.7f + 0.3f;
+
+ float fWave = Sin( float(float(4 * y + 4 * x) * (TWOPI / SMALL_SECTOR_SIZE )) + fAngle );
+
+ return fWave * fWindFactor;
+}
+
+CVector
+CWaterLevel::GetWaterNormal(float fX, float fY)
+{
+ //TODO: BUG ? no x offset
+
+ int32 x = WATER_TO_SMALL_SECTOR_X(fX);
+ int32 y = WATER_TO_SMALL_SECTOR_Y(fY);
+
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+ float fWindFactor = CWeather::WindClipped * 0.4f + 0.2f;
+
+ //TODO:
+ float _fWave = (WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE + WATER_UNSIGN_X(fX) - x*SMALL_SECTOR_SIZE)
+ * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle;
+
+ CVector vA(1.0f, 0.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave));
+ CVector vB(0.0f, 1.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave));
+
+ CVector norm = CrossProduct(vA, vB);
+
+ norm.Normalise();
+
+ return norm;
+}
- // if z greater then 60.0f return 2000.0f;
- if ( TheCamera.GetPosition().z > 60.0f )
- return 2000.0f;
- return (TheCamera.GetPosition().z + -15.0f) * 800.0f / 45.0f + 1200.0f;
+inline float
+_GetWaterDrawDist()
+{
+ if ( TheCamera.GetPosition().z < 15.0f ) return 1200.0f;
+ if ( TheCamera.GetPosition().z > 60.0f ) return 2000.0f;
+ return ( TheCamera.GetPosition().z + -15.0f ) * 800.0f / 45.0f + 1200.0f;
}
inline float
@@ -325,6 +541,49 @@ _GetCamBounds(bool *bUseCamStartY, bool *bUseCamEndY, bool *bUseCamStartX, bool
}
}
+
+inline bool
+_IsColideWithBlock(int32 x, int32 y, int32 &block)
+{
+ block = CWaterLevel::aWaterFineBlockList[x + 0][y + 0];
+ if (!(block & 0x80))
+ return true;
+
+ block = CWaterLevel::aWaterFineBlockList[x + 0][y + 1];
+ if (!(block & 0x80))
+ {
+ block = CWaterLevel::aWaterFineBlockList[x + 0][y + 2];
+ if (!(block & 0x80))
+ return true;
+ }
+
+ block = CWaterLevel::aWaterFineBlockList[x + 1][y + 0];
+ if (!(block & 0x80))
+ return true;
+
+ block = CWaterLevel::aWaterFineBlockList[x + 1][y + 1];
+ if (!(block & 0x80))
+ {
+ block = CWaterLevel::aWaterFineBlockList[x + 1][y + 2];
+ if (!(block & 0x80))
+ return true;
+ }
+
+ block = CWaterLevel::aWaterFineBlockList[x + 2][y + 0];
+ if (!(block & 0x80))
+ return true;
+
+ block = CWaterLevel::aWaterFineBlockList[x + 2][y + 1];
+ if (!(block & 0x80))
+ {
+ block = CWaterLevel::aWaterFineBlockList[x + 2][y + 2];
+ if (!(block & 0x80))
+ return true;
+ }
+
+ return false;
+}
+
inline float
SectorRadius(float fSize)
{
@@ -345,64 +604,85 @@ CWaterLevel::RenderWater()
bool bUseCamStartX = false;
bool bUseCamEndY = false;
- float fWavySectorMaxRenderDist = _GetWavyDrawDist();
- float fWavySectorMaxRenderDistSqr = SQR(fWavySectorMaxRenderDist);
+ if ( !CGame::CanSeeWaterFromCurrArea() )
+ return;
_GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX);
float fHugeSectorMaxRenderDist = _GetWaterDrawDist();
float fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist);
- float windAddUV = CWeather::Wind * 0.0015f + 0.0005f;
+ float windAddUV = CWeather::WindClipped * 0.0005f + 0.0006f;
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
if ( !CTimer::GetIsPaused() )
{
-#ifdef FIX_BUGS
- TEXTURE_ADDU += (CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV) * CTimer::GetTimeStepFix();
- TEXTURE_ADDV += (CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV) * CTimer::GetTimeStepFix();
-#else
- TEXTURE_ADDU += CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV;
- TEXTURE_ADDV += CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV;
-#endif
+ TEXTURE_ADDU += windAddUV;
+ TEXTURE_ADDV += windAddUV;
+
+ _TEXTURE_MASK_ADDU += Sin(fAngle) * 0.0005f + 1.1f * windAddUV;
+ _TEXTURE_MASK_ADDV -= Cos(fAngle * 1.3f) * 0.0005f + 1.2f * windAddUV;
+
+ _TEXTURE_WAKE_ADDU -= Sin(fAngle) * 0.0003f + windAddUV;
+ _TEXTURE_WAKE_ADDV += Cos(fAngle * 0.7f) * 0.0003f + windAddUV;
}
+ if ( _TEXTURE_MASK_ADDU >= 1.0f )
+ _TEXTURE_MASK_ADDU = 0.0f;
+ if ( _TEXTURE_MASK_ADDV >= 1.0f )
+ _TEXTURE_MASK_ADDV = 0.0f;
+
+ if ( _TEXTURE_WAKE_ADDU >= 1.0f )
+ _TEXTURE_WAKE_ADDU = 0.0f;
+ if ( _TEXTURE_WAKE_ADDV >= 1.0f )
+ _TEXTURE_WAKE_ADDV = 0.0f;
+
if ( TEXTURE_ADDU >= 1.0f )
TEXTURE_ADDU = 0.0f;
if ( TEXTURE_ADDV >= 1.0f )
TEXTURE_ADDV = 0.0f;
- WavesCalculatedThisFrame = false;
+#ifdef PC_WATER
+ _fWaterZOffset = CWeather::WindClipped * 0.5f + 0.25f;
+#endif
RwRGBA color = { 0, 0, 0, 255 };
-
- color.red = uint32((CTimeCycle::GetDirectionalRed() * 0.5f + CTimeCycle::GetAmbientRed() ) * 255.0f);
- color.green = uint32((CTimeCycle::GetDirectionalGreen() * 0.5f + CTimeCycle::GetAmbientGreen()) * 255.0f);
- color.blue = uint32((CTimeCycle::GetDirectionalBlue() * 0.5f + CTimeCycle::GetAmbientBlue() ) * 255.0f);
+
+ color.red = CTimeCycle::GetWaterRed();
+ color.green = CTimeCycle::GetWaterGreen();
+ color.blue = CTimeCycle::GetWaterBlue();
+
+#ifndef PC_WATER
+ RwRGBA colorUnderwater = { 0, 0, 0, 255 };
+ colorUnderwater.red = (uint32)(0.8f * (float)colorUnderwater.red);
+ colorUnderwater.green = (uint32)(0.8f * (float)colorUnderwater.green);
+ colorUnderwater.blue = (uint32)(0.8f * (float)colorUnderwater.blue);
+#endif
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
+
+#ifndef PC_WATER
+ WavesCalculatedThisFrame = false;
+#endif
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
- CVector2D camPos
- (
- TheCamera.GetPosition().x,
- TheCamera.GetPosition().y
- );
+ CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);
- int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist);
- int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist) + 1;
+ int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET);
+ int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1;
int32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist);
int32 nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist) + 1;
-
+
if ( bUseCamStartX )
- nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x);
+ nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
if ( bUseCamEndX )
- nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x);
+ nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
if ( bUseCamStartY )
nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y);
if ( bUseCamEndY )
@@ -417,12 +697,279 @@ CWaterLevel::RenderWater()
{
for ( int32 y = nStartY; y <= nEndY; y++ )
{
- if ( !(aWaterBlockList[2*x+0][2*y+0] & 128)
- || !(aWaterBlockList[2*x+1][2*y+0] & 128)
- || !(aWaterBlockList[2*x+0][2*y+1] & 128)
- || !(aWaterBlockList[2*x+1][2*y+1] & 128) )
+ if ( !(aWaterBlockList[2*x+0][2*y+0] & 0x80)
+ || !(aWaterBlockList[2*x+1][2*y+0] & 0x80)
+ || !(aWaterBlockList[2*x+0][2*y+1] & 0x80)
+ || !(aWaterBlockList[2*x+1][2*y+1] & 0x80) )
+ {
+ float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET;
+ float fY = WATER_FROM_HUGE_SECTOR_Y(y);
+
+ CVector2D vecHugeSectorCentre(fX + HUGE_SECTOR_SIZE/2,fY + HUGE_SECTOR_SIZE/2);
+
+ float fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr();
+
+ if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
+ {
+#ifndef PC_WATER
+ WavesCalculatedThisFrame = true;
+#endif
+
+
+ float fZ;
+
+ if ( !(aWaterBlockList[2*x+0][2*y+0] & 0x80) )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ];
+
+ if ( !(aWaterBlockList[2*x+1][2*y+0] & 0x80) )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ];
+
+ if ( !(aWaterBlockList[2*x+0][2*y+1] & 0x80) )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ];
+
+ if ( !(aWaterBlockList[2*x+1][2*y+1] & 0x80) )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ];
+
+ if ( fHugeSectorDistToCamSqr >= SQR(500.0f) )
+ {
+ RenderOneFlatHugeWaterPoly(fX, fY, fZ, color);
+ }
+ else
+ {
+#ifndef PC_WATER
+ if (m_bRenderSeaBed)
+ RenderOneSlopedUnderWaterPoly(fX, fY, fZ, colorUnderwater);
+#endif
+ // see RenderTransparentWater()
+ ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ ----------- ---------------------- ----------------------
+ | [N] | | [ EndY ] | | [ top ] |
+ | | | | | |
+ |[W] [0] [E]| |[StartX] [] [ EndX ]| |[ left ] [] [ right]|
+ | | | | | |
+ | [S] | | [StartY] | | [bottom] |
+ ----------- ---------------------- ----------------------
+
+
+ [S] [StartY] [bottom]
+ [N] [EndY] [top]
+ [W] [StartX] [left]
+ [E] [EndX] [right]
+
+ [S] -> [N] && [W] -> [E]
+ bottom -> top && left -> right
+ */
+
+ for ( int32 x = 0; x < 26; x++ )
+ {
+ for ( int32 y = 0; y < 5; y++ )
+ {
+ float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - 400.0f;
+ float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
+
+ if ( !bUseCamStartY )
+ {
+ CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2);
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+
+ if ( !bUseCamEndY )
+ {
+ CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, -(fY + EXTRAHUGE_SECTOR_SIZE/2));
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+ }
+ }
+
+ for ( int32 y = 5; y < 21; y++ )
+ {
+ for ( int32 x = 0; x < 5; x++ )
+ {
+ float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - WATER_X_OFFSET;
+ float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f + WATER_X_OFFSET;
+ float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
+
+ if ( !bUseCamStartX )
+ {
+ CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2);
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+
+ if ( !bUseCamEndX )
+ {
+ CVector2D vecExtraHugeSectorCentre(-(fX2 + EXTRAHUGE_SECTOR_SIZE/2), fY + EXTRAHUGE_SECTOR_SIZE/2);
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.x, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+ }
+ }
+
+ RenderAndEmptyRenderBuffer();
+
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ if ( WavesCalculatedThisFrame )
+ {
+ RenderSeaBirds();
+ RenderShipsOnHorizon();
+ CParticle::HandleShipsAtHorizonStuff();
+ HandleBeachToysStuff();
+ }
+
+ if ( _bSeaLife )
+ HandleSeaLifeForms();
+
+ DefinedState();
+}
+
+
+void
+CWaterLevel::RenderTransparentWater(void)
+{
+ bool bUseCamEndX = false;
+ bool bUseCamStartY = false;
+
+ bool bUseCamStartX = false;
+ bool bUseCamEndY = false;
+
+ _bSeaLife = false;
+
+ if ( !CGame::CanSeeWaterFromCurrArea() )
+ return;
+
+ float fWaterDrawDist = _GetWavyDrawDist();
+ float fWaterDrawDistLarge = fWaterDrawDist + 90.0f;
+ float fWavySectorMaxRenderDistSqr = SQR(fWaterDrawDist);
+
+ _GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX);
+
+ float fHugeSectorMaxRenderDist = _GetWaterDrawDist();
+ float fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist);
+
+ RenderBoatWakes();
+
+ RwRGBA color;
+
+ color.red = CTimeCycle::GetWaterRed();
+ color.green = CTimeCycle::GetWaterGreen();
+ color.blue = CTimeCycle::GetWaterBlue();
+ color.alpha = 255;
+
+ RwRGBA colorTrans;
+
+ colorTrans.red = CTimeCycle::GetWaterRed();
+ colorTrans.green = CTimeCycle::GetWaterGreen();
+ colorTrans.blue = CTimeCycle::GetWaterBlue();
+ colorTrans.alpha = CTimeCycle::GetWaterAlpha();
+
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+
+#ifndef PC_WATER
+ WavesCalculatedThisFrame = false;
+#endif
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster);
+#ifndef PC_WATER
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+#endif
+
+ CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);
+
+ int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET);
+ int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1;
+ int32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist );
+ int32 nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist ) + 1;
+
+ if ( bUseCamStartX )
+ nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
+ if ( bUseCamEndX )
+ nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
+ if ( bUseCamStartY )
+ nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y );
+ if ( bUseCamEndY )
+ nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y );
+
+ nStartX = clamp(nStartX, 0, MAX_HUGE_SECTORS - 1);
+ nEndX = clamp(nEndX, 0, MAX_HUGE_SECTORS - 1);
+ nStartY = clamp(nStartY, 0, MAX_HUGE_SECTORS - 1);
+ nEndY = clamp(nEndY, 0, MAX_HUGE_SECTORS - 1);
+
+
+ for ( int32 x = nStartX; x <= nEndX; x++ )
+ {
+ for ( int32 y = nStartY; y <= nEndY; y++ )
+ {
+ if ( !(aWaterBlockList[2*x+0][2*y+0] & 0x80)
+ || !(aWaterBlockList[2*x+1][2*y+0] & 0x80)
+ || !(aWaterBlockList[2*x+0][2*y+1] & 0x80)
+ || !(aWaterBlockList[2*x+1][2*y+1] & 0x80) )
{
- float fX = WATER_FROM_HUGE_SECTOR_X(x);
+ float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET;
float fY = WATER_FROM_HUGE_SECTOR_Y(y);
CVector2D vecHugeSectorCentre
@@ -432,29 +979,15 @@ CWaterLevel::RenderWater()
);
float fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr();
-
+
if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )
{
- if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
+ if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
{
- if ( fHugeSectorDistToCamSqr >= SQR(500.0f) /*fHugeSectorNearDist*/ )
+ if ( fHugeSectorDistToCamSqr >= SQR(500.0f) )
{
- float fZ;
-
- if ( !(aWaterBlockList[2*x+0][2*y+0] & 128) )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ];
-
- if ( !(aWaterBlockList[2*x+1][2*y+0] & 128) )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ];
-
- if ( !(aWaterBlockList[2*x+0][2*y+1] & 128) )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ];
-
- if ( !(aWaterBlockList[2*x+1][2*y+1] & 128) )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ];
-
- RenderOneFlatHugeWaterPoly(fX, fY, fZ, color);
+ // see RenderWater()
+ ;
}
else
{
@@ -462,23 +995,18 @@ CWaterLevel::RenderWater()
{
for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ )
{
- if ( !(aWaterBlockList[x2][y2] & 128) )
+ if ( !(aWaterBlockList[x2][y2] & 0x80) )
{
- float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2);
+ float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2) - WATER_X_OFFSET;
float fLargeY = WATER_FROM_LARGE_SECTOR_Y(y2);
- CVector2D vecLargeSectorCentre
- (
- fLargeX + LARGE_SECTOR_SIZE/2,
- fLargeY + LARGE_SECTOR_SIZE/2
- );
+ CVector2D vecLargeSectorCentre(fLargeX + LARGE_SECTOR_SIZE/2, fLargeY + LARGE_SECTOR_SIZE/2);
float fLargeSectorDistToCamSqr = (camPos - vecLargeSectorCentre).MagnitudeSqr();
if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr )
{
- if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE), //90.879997f,
- &TheCamera.GetCameraMatrix()) )
+ if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
{
// Render four small(32x32) sectors, or one large(64x64).
@@ -491,93 +1019,81 @@ CWaterLevel::RenderWater()
// ---------
// [S]
//
-
- if ( fLargeSectorDistToCamSqr < SQR(176.0f) )
- {
+
+ float fLargeSectorDrawDistSqr = SQR((fWaterDrawDistLarge + 16.0f));
+
+ if ( fLargeSectorDistToCamSqr < fLargeSectorDrawDistSqr )
+ {
+ _bSeaLife = true;
+
float fZ;
// WS
- if ( !(aWaterFineBlockList[2*x2+0][2*y2+0] & 128) )
+ if ( !(aWaterFineBlockList[2*x2+0][2*y2+0] & 0x80) )
{
float fSmallX = fLargeX;
float fSmallY = fLargeY;
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+0] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
// SE
- if ( !(aWaterFineBlockList[2*x2+1][2*y2+0] & 128) )
+ if ( !(aWaterFineBlockList[2*x2+1][2*y2+0] & 0x80) )
{
float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2);
float fSmallY = fLargeY;
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+0] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
// WN
- if ( !(aWaterFineBlockList[2*x2+0][2*y2+1] & 128) )
+ if ( !(aWaterFineBlockList[2*x2+0][2*y2+1] & 0x80) )
{
float fSmallX = fLargeX;
float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2);
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2,fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+1] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
//NE
- if ( !(aWaterFineBlockList[2*x2+1][2*y2+1] & 128) )
+ if ( !(aWaterFineBlockList[2*x2+1][2*y2+1] & 0x80) )
{
float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2);
float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2);
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+1] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
}
else
@@ -588,13 +1104,11 @@ CWaterLevel::RenderWater()
RenderOneFlatLargeWaterPoly(fLargeX, fLargeY, fZ, color);
}
- } // if ( TheCamera.IsSphereVisible
- } // if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr )
- } // if ( !(aWaterBlockList[x2][y2] & 128) )
- } // for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ )
- } // for ( int32 x2 = 2*x; x2 <= 2*x+1; x2++ )
- //
-
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -602,195 +1116,100 @@ CWaterLevel::RenderWater()
}
}
- /*
- ----------- ---------------------- ----------------------
- | [N] | | [ EndY ] | | [ top ] |
- | | | | | |
- |[W] [0] [E]| |[StartX] [] [ EndX ]| |[ left ] [] [ right]|
- | | | | | |
- | [S] | | [StartY] | | [bottom] |
- ----------- ---------------------- ----------------------
-
-
- [S] [StartY] [bottom]
- [N] [EndY] [top]
- [W] [StartX] [left]
- [E] [EndX] [right]
+ RenderAndEmptyRenderBuffer();
- [S] -> [N] && [W] -> [E]
- bottom -> top && left -> right
- */
-
- if ( !bUseCamStartY )
+#ifdef PC_WATER
+ if ( MaskCalculatedThisFrame
+ && (m_nRenderWaterLayers == 0 || m_nRenderWaterLayers == 2 || m_nRenderWaterLayers == 3) )
{
- for ( int32 x = 0; x < 26; x++ )
- {
- for ( int32 y = 0; y < 5; y++ )
- {
- float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
- float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
-
- CVector2D vecExtraHugeSectorCentre
- (
- fX + EXTRAHUGE_SECTOR_SIZE/2,
- fY + EXTRAHUGE_SECTOR_SIZE/2
- );
-
- float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = PreCalculatedMaskPosn.x;
+ pos.y = PreCalculatedMaskPosn.y;
+ pos.z = PreCalculatedMaskPosn.z;
+
+ RpMatFXMaterialSetEnvMapFrame(RpGeometryGetMaterial(RpAtomicGetGeometry(ms_pMaskAtomic), 0),
+ RwCameraGetFrame(RwCameraGetCurrentCamera()));
+
+ RwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE);
- if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
- {
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
- {
- RenderOneFlatExtraHugeWaterPoly(
- vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
- vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
- 0.0f,
- color);
- }
- }
- }
- }
+ RpAtomicRender(ms_pMaskAtomic);
}
-
- for ( int32 y = 5; y < 21; y++ )
+#else
+ if (!CCullZones::WaterFudge())
{
- for ( int32 x = 0; x < 5; x++ )
- {
- float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
- float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
- float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
-
- if ( !bUseCamStartX )
- {
- CVector2D vecExtraHugeSectorCentre
- (
- fX + EXTRAHUGE_SECTOR_SIZE/2,
- fY + EXTRAHUGE_SECTOR_SIZE/2
- );
-
- float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
-
- if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
- {
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
- {
- RenderOneFlatExtraHugeWaterPoly(
- vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
- vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
- 0.0f,
- color);
- }
- }
- }
-
- if ( !bUseCamEndX )
- {
- CVector2D vecExtraHugeSectorCentre
- (
- -(fX2 + EXTRAHUGE_SECTOR_SIZE/2),
- fY + EXTRAHUGE_SECTOR_SIZE/2
- );
-
- float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
-
- if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
- {
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
- {
- RenderOneFlatExtraHugeWaterPoly(
- vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
- vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
- 0.0f,
- color);
- }
- }
- }
- }
- }
+ int32 signX = 0;
+ int32 signY = 0;
- RenderAndEmptyRenderBuffer();
-
- CVector cur_pos = TheCamera.GetPosition();
-
- if ( !CCullZones::CamNoRain()
- && !CCullZones::PlayerNoRain()
- && CWeather::NewWeatherType == WEATHER_SUNNY
- && CClock::GetHours() > 6 && CClock::GetHours() < 20
- && WavesCalculatedThisFrame)
- {
- static CVector prev_pos(0.0f, 0.0f, 0.0f);
- static CVector prev_front(0.0f, 0.0f, 0.0f);
- static int32 timecounter;
+ float fCamX = camPos.x - SMALL_SECTOR_SIZE;
+ float fCamY = camPos.y - SMALL_SECTOR_SIZE;
- 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();
- }
- else if ( CTimer::GetTimeInMilliseconds() - timecounter > 5000 )
+ if (TheCamera.GetForward().x > 0.3f)
+ signX = 1;
+ else if (TheCamera.GetForward().x < -0.3f)
+ signX = -1;
+
+ fCamX += 0.3f * (float)signX * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f
+
+ if (TheCamera.GetForward().y > 0.3f)
+ signY = 1;
+ else if (TheCamera.GetForward().y < -0.3f)
+ signY = -1;
+
+ fCamY += 0.3f * (float)signY * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f
+
+ int32 nBlock;
+
+ int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + 400.0f) + 1;
+ int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY) + 1;
+
+ if (_IsColideWithBlock(BlockX, BlockY, nBlock))
{
- static int32 birdgenTime = 0;
-
- if ( CTimer::GetTimeInMilliseconds() - birdgenTime > 1000 )
+ if (m_nRenderWaterLayers != 1 && m_nRenderWaterLayers != 6)
{
- birdgenTime = CTimer::GetTimeInMilliseconds();
-
- CVector vecPos = cur_pos;
-
- float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f);
-
- int32 nRot = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE-1;
-
- float fCos = CParticle::Cos(nRot);
- float fSin = CParticle::Sin(nRot);
-
- vecPos.x += (fCos - fSin) * fAngle;
- vecPos.y += (fSin + fCos) * fAngle;
- vecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f);
-
- CVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
- CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
- 0.0f);
-
- CParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir);
+ float fMaskX = Floor(fCamX / 2.0f) * 2.0f;
+ float fMaskY = Floor(fCamY / 2.0f) * 2.0f;
+ float fWaterZ = CWaterLevel::ms_aWaterZs[nBlock];
+ float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - 400.0f;
+ float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);
+
+ RenderWavyMask(fMaskX, fMaskY, fWaterZ,
+ fSectorX, fSectorY,
+ signX, signY, colorTrans);
}
}
}
-
+
DefinedState();
+#endif
}
-void
-CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)
+void CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)
{
if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
RenderAndEmptyRenderBuffer();
int32 vidx = TempBufferVerticesStored;
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color);
int32 iidx = TempBufferIndicesStored;
@@ -814,25 +1233,25 @@ CWaterLevel::RenderOneFlatLargeWaterPoly(float fX, float fY, float fZ, RwRGBA co
int32 vidx = TempBufferVerticesStored;
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 2.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 2.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 2.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 2.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color);
int32 iidx = TempBufferIndicesStored;
@@ -855,27 +1274,33 @@ CWaterLevel::RenderOneFlatHugeWaterPoly(float fX, float fY, float fZ, RwRGBA con
RenderAndEmptyRenderBuffer();
int32 vidx = TempBufferVerticesStored;
-
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwRGBA c;
+
+ c.red = color.red;
+ c.green = color.green;
+ c.blue = color.blue;
+ c.alpha = 255;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 4.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 4.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 4.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 4.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c);
int32 iidx = TempBufferIndicesStored;
@@ -898,27 +1323,33 @@ CWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGB
RenderAndEmptyRenderBuffer();
int32 vidx = TempBufferVerticesStored;
-
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwRGBA c;
+
+ c.red = color.red;
+ c.green = color.green;
+ c.blue = color.blue;
+ c.alpha = 255;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 8.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 8.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 8.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 8.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c);
int32 iidx = TempBufferIndicesStored;
@@ -935,172 +1366,1218 @@ CWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGB
}
void
-CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bUnk)
+CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender)
{
- float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
-
- if ( !WavesCalculatedThisFrame )
+ CVector vecSectorPos(fX + (SMALL_SECTOR_SIZE/2), fY + (SMALL_SECTOR_SIZE/2), fZ + 2.0f);
+
+ if ( COcclusion::IsAABoxOccluded(vecSectorPos, SMALL_SECTOR_SIZE, SMALL_SECTOR_SIZE, 4.0f) )
+ return;
+
+#ifdef PC_WATER
+ RequireWavySector = true;
+#else
+ if (!WavesCalculatedThisFrame)
{
- nGeomUsed = 0;
-
WavesCalculatedThisFrame = true;
+
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+ RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+ RwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ RpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);
+
+ RwMatrix *camMat = RwFrameGetLTM(RwCameraGetFrame(RwCameraGetCurrentCamera())); //or curWorld
+
+ float randomDampInv2 = (1.0f - fRandomDamp) * 2.0f;
+
+ float move = 1.0f / 16.0f;
+ float randomMove = 1.0f / (16.0f * fRandomMoveDiv);
+
+ float vertMul = 0.5f;
+
+ float wind = CWeather::WindClipped * 0.4f + 0.2f;
+ float waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f;
+
+ float waveA = (TWOPI / 16.0f)
+ * ((fNormalDirectionScalar1 * Abs(camMat->at.x + camMat->at.y) + fNormMult) * (CWeather::WindClipped * 0.4f + 0.2f));
+
+ float waveB = TWOPI / (16.0f * fWave2NormScale)
+ * ((fNormalDirectionScalar2 * Abs(camMat->at.y - camMat->at.x) + fNormMultB) * (CWeather::WindClipped * 0.2f + 0.1f));
+
+ CVector vA(1.0f, 0.0f, 0.0f);
+ CVector vB(0.0f, 1.0f, 0.0f);
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ for ( int32 j = 0; j < 17; j++ )
+ {
+ wavyTexCoords->u = float(i) * move + TEXTURE_ADDV;
+ wavyTexCoords->v = float(j) * move + TEXTURE_ADDU;
+
+ RwRGBAAssign(wavyPreLight, &color);
+
+ if (i > 0 && i < 16 && j > 0 && j < 16)
+ {
+ wavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->x *= fRandomDamp;
+ wavyMorphVerts->x += float(i) * randomDampInv2;
+
+ wavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->y *= fRandomDamp;
+ wavyMorphVerts->y += float(j) * randomDampInv2;
+ }
+
+ float morphVertXHalf = (i == 16) ? 0.0f : vertMul * wavyMorphVerts->x;
+ float morphVertYHalf = (j == 16) ? 0.0f : vertMul * wavyMorphVerts->y;
+
+ float waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle;
+ float waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle;
+
+ wavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB);
+
+ vA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB));
+ vB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB));
+
+ CVector norm = CrossProduct(vA, vB);
+ norm.Normalise();
+
+ wavyMorphNormals->x = norm.x;
+ wavyMorphNormals->y = norm.y;
+ wavyMorphNormals->z = norm.z;
+
+ ++wavyPreLight;
+ ++wavyTexCoords;
+
+ ++wavyMorphVerts;
+ ++wavyMorphNormals;
+ }
+ }
+
+ RpGeometryUnlock(wavyGeometry);
+ }
+
+ float fCentreX = fX + (SMALL_SECTOR_SIZE / 2);
+ float fCentreY = fY + (SMALL_SECTOR_SIZE / 2);
+#endif
+
+#ifdef PC_WATER
+ if ( WavesCalculatedThisFrame )
+#endif
+ {
+ if (bDontRender == false
+ && m_nRenderWaterLayers != 2
+ && m_nRenderWaterLayers != 4
+ && m_nRenderWaterLayers != 6 )
+ {
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = fX;
+ pos.y = fY;
+ pos.z = fZ;
+
+ RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE);
- CBoat::FillBoatList();
+ RpAtomicRender(ms_pWavyAtomic);
+ }
+ }
+}
- ASSERT( ms_pWavyAtomic != NULL );
+int16
+_RoundValue(int32 v)
+{
+ int16 result = v;
+
+ while ( result < 0 ) result += 16;
+ while ( result > 16 ) result -= 16;
+
+ return result;
+}
- RpGeometry *geometry = RpAtomicGetGeometry(ms_pWavyAtomic);
-
- ASSERT( geometry != NULL );
+void
+CWaterLevel::RenderWavyMask(float fX, float fY, float fZ,
+ float fSectorX, float fSectorY,
+#ifdef PC_WATER
+ float fCamPosX, float fCamPosY,
+ float fCamDirX, float fCamDirY, RwRGBA const&color)
+#else
+ int32 nCamDirX, int32 nCamDirY, RwRGBA const&color)
+#endif
+{
+#ifndef PC_WATER
+ bool bRender = true;
+ if (m_nRenderWaterLayers != 0 && m_nRenderWaterLayers != 2 && m_nRenderWaterLayers != 3)
+ bRender = false;
+#endif
+ CVector vecSectorPos(fX + (LARGE_SECTOR_SIZE/2), fY + (LARGE_SECTOR_SIZE/2), fZ + 2.0f);
- RwRGBA *wavyPreLights = RpGeometryGetPreLightColors(geometry);
- RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(geometry, rwTEXTURECOORDINATEINDEX0);
- RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geometry, 0));
-
- ASSERT( wavyPreLights != NULL );
- ASSERT( wavyTexCoords != NULL );
- ASSERT( wavyVertices != NULL );
+ if ( COcclusion::IsAABoxOccluded(vecSectorPos, LARGE_SECTOR_SIZE, LARGE_SECTOR_SIZE, 4.0f) )
+ return;
- RpGeometryLock(geometry, rpGEOMETRYLOCKVERTICES
- | rpGEOMETRYLOCKPRELIGHT
- | rpGEOMETRYLOCKTEXCOORDS);
-
- for ( int32 i = 0; i < 9; i++ )
+#ifndef PC_WATER
+ float fUOffset = fX - (MAX_LARGE_SECTORS * (int32)Floor(fX / MAX_LARGE_SECTORS));
+ float fVOffset = fY - (MAX_LARGE_SECTORS * (int32)Floor(fY / MAX_LARGE_SECTORS));
+
+ int32 nSecsX = (int32)((fX - fSectorX) / 2.0f);
+ int32 nSecsY = (int32)((fY - fSectorY) / 2.0f);
+#endif
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ RpGeometry *maskGeometry = RpAtomicGetGeometry(ms_pMaskAtomic);
+ RwTexCoords *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0);
+ RwRGBA *maskPreLight = RpGeometryGetPreLightColors(maskGeometry);
+ RpMorphTarget *maskMorph = RpGeometryGetMorphTarget(maskGeometry, 0);
+ RwV3d *maskMorphVerts = RpMorphTargetGetVertices(maskMorph);
+ RwV3d *maskMorphNormals = RpMorphTargetGetVertexNormals(maskMorph);
+
+ RpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES|rpGEOMETRYLOCKNORMALS|rpGEOMETRYLOCKPRELIGHT|rpGEOMETRYLOCKTEXCOORDS);
+
+#ifndef PC_WATER
+ RpMaterial *maskMat = RpGeometryGetMaterial(maskGeometry, 0);
+ RpMatFXMaterialSetEnvMapFrame(maskMat, RwCameraGetFrame(RwCameraGetCurrentCamera()));
+ RpMatFXMaterialSetEnvMapCoefficient(maskMat, fEnvScale);
+ RpMatFXMaterialSetEnvMapFrameBufferAlpha(maskMat, TRUE);
+#endif
+
+#ifndef PC_WATER
+ float fMinSparkZ = (CWeather::WindClipped * fWave2Ampl + 0.05f +
+ CWeather::WindClipped * 0.4f + 0.2) * (1.0f - 0.04f * CWeather::SunGlare);
+
+ int32 randval = CGeneral::GetRandomNumber();
+
+ float fUVStep = 0.125f;
+ float f27 = 2.0f;
+
+ float fMinU = (fUOffset / 16.0f) + _TEXTURE_MASK_ADDU;
+ float fMinV = (fVOffset / 16.0f) + _TEXTURE_MASK_ADDV;
+
+ float fAlphaMul = ((float)color.alpha * 0.4f) / 16.0f;
+
+ float fXOffset = 16.0f;
+ if (nCamDirX > 0)
+ fXOffset = 6.4f;
+ else if (nCamDirX < 0)
+ fXOffset = 25.6f;
+
+ float fYOffset = 16.0f;
+ if (nCamDirY > 0)
+ fYOffset = 6.4f;
+ else if (nCamDirY < 0)
+ fYOffset = 25.6f;
+
+ int16 nX = _RoundValue(nSecsX - 1);
+ int16 nY = _RoundValue(nSecsY - 1);
+#else
+ float fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f +
+ 0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare);
+
+ int32 randval = CGeneral::GetRandomNumber() & 255;
+
+ int16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1);
+ int16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1);
+#endif
+ int16 idxX = nX;
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ int16 idxY = nY;
+
+ if ( ++idxX > 16 )
+ idxX -= 16;
+
+ for ( int32 j = 0; j < 17; j++ )
{
- for ( int32 j = 0; j < 9; j++ )
+ if ( ++idxY > 16 )
+ idxY -= 16;
+
+ const int32 a = (0*16);
+ const int32 b = (1*16);
+ const int32 c = (33*16);
+ const int32 d = (34*16);
+
+ int32 base = (i*33+j);
+
+#ifndef PC_WATER
+ maskTexCoords[base + a].u = fMinU + ((float)i * fUVStep);
+ maskTexCoords[base + a].v = fMinV + ((float)j * fUVStep);
+
+ maskTexCoords[base + b].u = maskTexCoords[base + a].u;
+ maskTexCoords[base + b].v = maskTexCoords[base + a].v + (16.0f * fUVStep);
+
+ maskTexCoords[base + c].u = maskTexCoords[base + a].u + (16.0f * fUVStep);
+ maskTexCoords[base + c].v = maskTexCoords[base + a].v;
+
+ maskTexCoords[base + d].u = maskTexCoords[base + a].u + (16.0f * fUVStep);
+ maskTexCoords[base + d].v = maskTexCoords[base + a].v + (16.0f * fUVStep);
+#else
+ maskTexCoords[base+a].v = float(j) / SMALL_SECTOR_SIZE + ((fCamPosY - fY) / 64);
+ maskTexCoords[base+c].v = maskTexCoords[base+a].v;
+ maskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f;
+ maskTexCoords[base+b].v = maskTexCoords[base+d].v;
+
+ maskTexCoords[base+a].u = float(i) / SMALL_SECTOR_SIZE + ((fCamPosX - fX) / 64);
+ maskTexCoords[base+b].u = maskTexCoords[base+a].u;
+ maskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f;
+ maskTexCoords[base+c].u = maskTexCoords[base+d].u;
+#endif
+
+ maskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f);
+ maskMorphVerts[base+b].x = maskMorphVerts[base+a].x;
+ maskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].x = maskMorphVerts[base+c].x;
+
+ maskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f);
+ maskMorphVerts[base+c].y = maskMorphVerts[base+a].y;
+ maskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].y = maskMorphVerts[base+b].y;
+
+ maskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z;
+ maskMorphVerts[base+d].z = maskMorphVerts[base+a].z;
+ maskMorphVerts[base+c].z = maskMorphVerts[base+d].z;
+ maskMorphVerts[base+b].z = maskMorphVerts[base+c].z;
+
+#ifndef PC_WATER
+ if (maskMorphVerts[base].z >= fMinSparkZ)
+#else
+ if ( maskMorphVerts[base].z > fMinSparkZ )
+#endif
{
- wavyTexCoords[9*i+j].u = float(i) / 8 + TEXTURE_ADDV;
- wavyTexCoords[9*i+j].v = float(j) / 8 + TEXTURE_ADDU;
- RwRGBAAssign(&wavyPreLights[9*i+j], &color);
+ switch ( (i + j + randval) & 3 )
+ {
+ case 0:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+a].x,
+ fY + maskMorphVerts[base+a].y,
+ fZ + maskMorphVerts[base+a].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
- wavyVertices[9*i+j].z = ( CWeather::Wind * 0.7f + 0.3f )
- * ( Sin(float(i + j) * DEGTORAD(45.0f) + fAngle) )
- + ( CWeather::Wind * 0.2f * Sin(float(j - i) * PI + (2.0f * fAngle)) );
+ case 1:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+c].x,
+ fY + maskMorphVerts[base+c].y,
+ fZ + maskMorphVerts[base+c].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+
+ case 2:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+b].x,
+ fY + maskMorphVerts[base+b].y,
+ fZ + maskMorphVerts[base+b].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+
+ case 3:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+d].x,
+ fY + maskMorphVerts[base+d].y,
+ fZ + maskMorphVerts[base+d].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+ }
}
+
+ maskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x;
+ maskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y;
+ maskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z;
+
+ maskMorphNormals[base+d].x = maskMorphNormals[base+a].x;
+ maskMorphNormals[base+d].y = maskMorphNormals[base+a].y;
+ maskMorphNormals[base+d].z = maskMorphNormals[base+a].z;
+
+ maskMorphNormals[base+c].x = maskMorphNormals[base+d].x;
+ maskMorphNormals[base+c].y = maskMorphNormals[base+d].y;
+ maskMorphNormals[base+c].z = maskMorphNormals[base+d].z;
+
+ maskMorphNormals[base+b].x = maskMorphNormals[base+c].x;
+ maskMorphNormals[base+b].y = maskMorphNormals[base+c].y;
+ maskMorphNormals[base+b].z = maskMorphNormals[base+c].z;
+
+ maskPreLight[base+a].red = color.red;
+ maskPreLight[base+a].green = color.green;
+ maskPreLight[base+a].blue = color.blue;
+ maskPreLight[base+a].alpha = color.alpha;
+
+ maskPreLight[base+d].red = maskPreLight[base+a].red;
+ maskPreLight[base+d].green = maskPreLight[base+a].green;
+ maskPreLight[base+d].blue = maskPreLight[base+a].blue;
+ maskPreLight[base+d].alpha = maskPreLight[base+a].alpha;
+
+ maskPreLight[base+c].red = maskPreLight[base+d].red;
+ maskPreLight[base+c].green = maskPreLight[base+d].green;
+ maskPreLight[base+c].blue = maskPreLight[base+d].blue;
+ maskPreLight[base+c].alpha = maskPreLight[base+d].alpha;
+
+ maskPreLight[base+b].red = maskPreLight[base+c].red;
+ maskPreLight[base+b].green = maskPreLight[base+c].green;
+ maskPreLight[base+b].blue = maskPreLight[base+c].blue;
+ maskPreLight[base+b].alpha = maskPreLight[base+c].alpha;
+
+#ifndef PC_WATER
+ maskPreLight[base + a].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs((float)j - fYOffset)))));
+ maskPreLight[base + b].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset)))));
+ maskPreLight[base + c].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs((float)j - fYOffset)))));
+ maskPreLight[base + d].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset)))));
+#endif
}
-
- RpGeometryUnlock(geometry);
}
- static CBoat *apBoatList[4] = { NULL };
+ RpGeometryUnlock(maskGeometry);
+
+#ifndef PC_WATER
+ {
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = fX;
+ pos.y = fY;
+ pos.z = fZ + 0.05f;
+
+ RwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE);
+
+ if (bRender)
+ {
+#ifdef PS2
+ RpSkyTexCacheFlush();
+#endif
+ RpAtomicRender(ms_pMaskAtomic);
+ }
+ }
+#endif
+}
+
+#ifdef PC_WATER
+void
+CWaterLevel::PreCalcWaterGeometry(void)
+{
+ if ( !RequireWavySector )
+ {
+ WavesCalculatedThisFrame = false;
+ MaskCalculatedThisFrame = false;
+ return;
+ }
+
+ RequireWavySector = false;
+ WavesCalculatedThisFrame = true;
- if ( apGeomArray[0]
- && nGeomUsed < MAX_BOAT_WAKES
- && CBoat::IsSectorAffectedByWake(
- CVector2D(fX + (SMALL_SECTOR_SIZE / 2), fY + (SMALL_SECTOR_SIZE / 2)),
- SMALL_SECTOR_SIZE / 2,
- apBoatList) )
+ RwRGBA color;
+
+ color.red = CTimeCycle::GetWaterRed();
+ color.green = CTimeCycle::GetWaterGreen();
+ color.blue = CTimeCycle::GetWaterBlue();
+ color.alpha = CTimeCycle::GetWaterAlpha();
+
+ PreCalcWavySector(color);
+
+ if ( CCullZones::WaterFudge() )
{
- float fWakeColor = fAdd1 - Max(255.0f - float(color.blue + color.red + color.green) / 3, fAdd2);
-
- RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
- RpGeometry *geom = apGeomArray[nGeomUsed++];
-
- ASSERT( wavyGeometry != NULL );
- ASSERT( geom != NULL );
-
- RpAtomic *atomic = RpAtomicCreate();
- ASSERT( atomic != NULL );
-
- RpAtomicSetGeometry(atomic, geom, 0);
-
- RwFrame *frame = RwFrameCreate();
- ASSERT( frame != NULL );
-
- RwMatrixCopy(RwFrameGetMatrix(frame), RwFrameGetMatrix(RpAtomicGetFrame(ms_pWavyAtomic)));
- RpAtomicSetFrame(atomic, frame);
+ MaskCalculatedThisFrame = false;
+ return;
+ }
+
+ CVector CamFwdDir = TheCamera.GetForward();
+ CamFwdDir.z = 0.0f;
+ CamFwdDir.Normalise();
+
+ float fCamX = TheCamera.GetPosition().x - SMALL_SECTOR_SIZE;
+ float fCamY = TheCamera.GetPosition().y - SMALL_SECTOR_SIZE;
+
+ //1.4144272f; 1.4144f;
+ float signX = CamFwdDir.x * 1.4144272f;
+ float signY = CamFwdDir.y * 1.4144272f;
+
+ signX = clamp(signX, -1.0f, 1.0f);
+ fCamX += 0.4f * signX * float(SMALL_SECTOR_SIZE * 2.0f);
+
+ signY = clamp(signY, -1.0f, 1.0f);
+ fCamY += 0.4f * signY * float(SMALL_SECTOR_SIZE * 2.0f);
+
+ int32 nBlock;
+
+ int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1;
+ int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY ) + 1;
+
+ ASSERT( BlockX >= 0 && BlockX < MAX_SMALL_SECTORS );
+ ASSERT( BlockY >= 0 && BlockY < MAX_SMALL_SECTORS );
+
+ if ( _IsColideWithBlock(BlockX, BlockY, nBlock) )
+ {
+ float fMaskX = Floor(fCamX / 2.0f) * 2.0f;
+ float fMaskY = Floor(fCamY / 2.0f) * 2.0f;
+
+ float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET;
+ float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);
- RwTexCoords *geomTexCoords = RpGeometryGetVertexTexCoords(geom, rwTEXTURECOORDINATEINDEX0);
- RwTexCoords *wavyTexCoord = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);
- RwRGBA *geomPreLights = RpGeometryGetPreLightColors(geom);
- RwV3d *geomVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geom, 0));
- RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(wavyGeometry, 0));
+ if ( PreCalcWavyMask( fMaskX, fMaskY, ms_aWaterZs[nBlock],
+ fSectorX, fSectorY, fCamX, fCamY, CamFwdDir.x, CamFwdDir.y, color ) )
+ {
+ PreCalculatedMaskPosn.x = fMaskX;
+ PreCalculatedMaskPosn.y = fMaskY;
+ PreCalculatedMaskPosn.z = ms_aWaterZs[nBlock] + 0.05f;
+
+ MaskCalculatedThisFrame = true;
+ }
+ else
+ MaskCalculatedThisFrame = false;
+ }
+ else
+ MaskCalculatedThisFrame = false;
+}
+
+bool
+CWaterLevel::PreCalcWavySector(RwRGBA const &color)
+{
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+
+ RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+
+ RwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ if ( !m_bRenderSeaBed )
+ RpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES
+ |rpGEOMETRYLOCKNORMALS
+ |rpGEOMETRYLOCKPRELIGHT
+ |rpGEOMETRYLOCKTEXCOORDS);
+
+ CVector camPosUp = TheCamera.GetForward();
- ASSERT( geomTexCoords != NULL );
- ASSERT( wavyTexCoord != NULL );
- ASSERT( geomPreLights != NULL );
- ASSERT( geomVertices != NULL );
- ASSERT( wavyVertices != NULL );
+ float randomDampInv2 = (1.0f - fRandomDamp) * 2.0f;
+
+ float randomMove = 1.0f / (16.0f * fRandomMoveDiv);
+
+ float wind = CWeather::WindClipped * 0.4f + 0.2f;
+ float waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f;
- RpGeometryLock(geom, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);
+ float waveA = (TWOPI / 16.0f)
+ * ((CWeather::WindClipped * 0.4f + 0.2f) * (fNormalDirectionScalar1 * Abs(camPosUp.x + camPosUp.y) + fNormMult));
- for ( int32 i = 0; i < 9; i++ )
+ float waveB = TWOPI / (16.0f * fWave2NormScale)
+ * ((CWeather::WindClipped * 0.2f + 0.1f) * (fNormalDirectionScalar2 * Abs(camPosUp.y - camPosUp.x) + fNormMultB));
+
+
+ CVector vA(1.0f, 0.0f, 0.0f);
+ CVector vB(0.0f, 1.0f, 0.0f);
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ for ( int32 j = 0; j < 17; j++ )
{
- for ( int32 j = 0; j < 9; j++ )
+ wavyTexCoords->u = (float(i) / 16.0f) + TEXTURE_ADDV;
+ wavyTexCoords->v = (float(j) / 16.0f) + TEXTURE_ADDU;
+
+ RwRGBAAssign(wavyPreLight, &color);
+
+ if ( i > 0 && i < 16 && j > 0 && j < 16 )
{
- geomTexCoords[9*i+j] = wavyTexCoord[9*i+j];
+ wavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->x *= fRandomDamp;
+ wavyMorphVerts->x += float(i) * randomDampInv2;
+
+ wavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->y *= fRandomDamp;
+ wavyMorphVerts->y += float(j) * randomDampInv2;
+ }
+
+ float morphVertXHalf = ( i == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->x;
+ float morphVertYHalf = ( j == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->y;
+
+ float waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle;
+ float waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle;
+
+ wavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB);
+
+ vA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB));
+ vB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB));
- float fVertexX = (float)i * 4.0f + fX;
- float fVertexY = (float)j * 4.0f + fY;
+ CVector norm = CrossProduct(vA, vB);
+ norm.Normalise();
- float fDistMult = 0.0f;
-
- for ( int32 k = 0; k < 4; k++ )
- {
- if ( apBoatList[k] != NULL )
- fDistMult += CBoat::IsVertexAffectedByWake(CVector(fVertexX, fVertexY, 0.0f), apBoatList[k]);
- }
-
- if ( fDistMult > 0.0f )
+ wavyMorphNormals->x = norm.x;
+ wavyMorphNormals->y = norm.y;
+ wavyMorphNormals->z = norm.z;
+
+ ++wavyPreLight;
+ ++wavyTexCoords;
+
+ ++wavyMorphVerts;
+ ++wavyMorphNormals;
+ }
+ }
+
+ RpGeometryUnlock(wavyGeometry);
+
+ return true;
+}
+
+bool
+CWaterLevel::PreCalcWavyMask(float fX, float fY, float fZ,
+ float fSectorX, float fSectorY,
+ float fCamPosX, float fCamPosY,
+ float fCamDirX, float fCamDirY,
+ RwRGBA const&color)
+{
+ CVector vecSectorPos(fX + (MAX_LARGE_SECTORS/2), fY + (MAX_LARGE_SECTORS/2), fZ + 2.0f);
+
+ if ( COcclusion::IsAABoxOccluded(vecSectorPos, MAX_LARGE_SECTORS, MAX_LARGE_SECTORS, 4.0f) )
+ return false;
+
+ Floor(fX / MAX_LARGE_SECTORS);
+ Floor(fY / MAX_LARGE_SECTORS);
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ RpGeometry *maskGeometry = RpAtomicGetGeometry(ms_pMaskAtomic);
+ RwTexCoords *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0);
+ RwRGBA *maskPreLight = RpGeometryGetPreLightColors(maskGeometry);
+ RpMorphTarget *maskMorph = RpGeometryGetMorphTarget(maskGeometry, 0);
+ RwV3d *maskMorphVerts = RpMorphTargetGetVertices(maskMorph);
+ RwV3d *maskMorphNormals = RpMorphTargetGetVertexNormals(maskMorph);
+
+ if ( !m_bRenderSeaBed )
+ RpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);
+
+
+ float fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f +
+ 0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare);
+
+ int32 randval = CGeneral::GetRandomNumber() & 255;
+
+ int16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1);
+ int16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1);
+
+ int16 idxX = nX;
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ int16 idxY = nY;
+
+ if ( ++idxX > 16 )
+ idxX -= 16;
+
+ for ( int32 j = 0; j < 17; j++ )
+ {
+ if ( ++idxY > 16 )
+ idxY -= 16;
+
+ const int32 a = (0*16);
+ const int32 b = (1*16);
+ const int32 c = (33*16);
+ const int32 d = (34*16);
+
+ int32 base = (i*33+j);
+
+ maskTexCoords[base+a].v = float(j) / 32 + ((fCamPosY - fY) / 64);
+ maskTexCoords[base+c].v = maskTexCoords[base+a].v;
+ maskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f;
+ maskTexCoords[base+b].v = maskTexCoords[base+d].v;
+
+ maskTexCoords[base+a].u = float(i) / 32 + ((fCamPosX - fX) / 64);
+ maskTexCoords[base+b].u = maskTexCoords[base+a].u;
+ maskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f;
+ maskTexCoords[base+c].u = maskTexCoords[base+d].u;
+
+ maskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f);
+ maskMorphVerts[base+b].x = maskMorphVerts[base+a].x;
+ maskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].x = maskMorphVerts[base+c].x;
+
+ maskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f);
+ maskMorphVerts[base+c].y = maskMorphVerts[base+a].y;
+ maskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].y = maskMorphVerts[base+b].y;
+
+ maskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z;
+ maskMorphVerts[base+d].z = maskMorphVerts[base+a].z;
+ maskMorphVerts[base+c].z = maskMorphVerts[base+d].z;
+ maskMorphVerts[base+b].z = maskMorphVerts[base+c].z;
+
+ if ( maskMorphVerts[base].z > fMinSparkZ )
+ {
+ switch ( (i + j + randval) & 3 )
{
- RwRGBA wakeColor;
-
- RwRGBAAssign(&wakeColor, &color);
+ case 0:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+a].x,
+ fY + maskMorphVerts[base+a].y,
+ fZ + maskMorphVerts[base+a].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
- wakeColor.red = Min(color.red + int32(fWakeColor * fRedMult * fDistMult), 255);
- wakeColor.green = Min(color.green + int32(fWakeColor * fGreenMult * fDistMult), 255);
- wakeColor.blue = Min(color.blue + int32(fWakeColor * fBlueMult * fDistMult), 255);
-
- RwRGBAAssign(&geomPreLights[9*i+j], &wakeColor);
+ case 1:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+c].x,
+ fY + maskMorphVerts[base+c].y,
+ fZ + maskMorphVerts[base+c].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+
+ case 2:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+b].x,
+ fY + maskMorphVerts[base+b].y,
+ fZ + maskMorphVerts[base+b].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+ case 3:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+d].x,
+ fY + maskMorphVerts[base+d].y,
+ fZ + maskMorphVerts[base+d].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
}
- else
- RwRGBAAssign(&geomPreLights[9*i+j], &color);
-
-
- geomVertices[9*i+j].z = wavyVertices[9*i+j].z;
}
+
+ maskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x;
+ maskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y;
+ maskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z;
+
+ maskMorphNormals[base+d].x = maskMorphNormals[base+a].x;
+ maskMorphNormals[base+d].y = maskMorphNormals[base+a].y;
+ maskMorphNormals[base+d].z = maskMorphNormals[base+a].z;
+
+ maskMorphNormals[base+c].x = maskMorphNormals[base+d].x;
+ maskMorphNormals[base+c].y = maskMorphNormals[base+d].y;
+ maskMorphNormals[base+c].z = maskMorphNormals[base+d].z;
+
+ maskMorphNormals[base+b].x = maskMorphNormals[base+c].x;
+ maskMorphNormals[base+b].y = maskMorphNormals[base+c].y;
+ maskMorphNormals[base+b].z = maskMorphNormals[base+c].z;
+
+ maskPreLight[base+a].red = color.red;
+ maskPreLight[base+a].green = color.green;
+ maskPreLight[base+a].blue = color.blue;
+ maskPreLight[base+a].alpha = color.alpha;
+
+ maskPreLight[base+d].red = maskPreLight[base+a].red;
+ maskPreLight[base+d].green = maskPreLight[base+a].green;
+ maskPreLight[base+d].blue = maskPreLight[base+a].blue;
+ maskPreLight[base+d].alpha = maskPreLight[base+a].alpha;
+
+ maskPreLight[base+c].red = maskPreLight[base+d].red;
+ maskPreLight[base+c].green = maskPreLight[base+d].green;
+ maskPreLight[base+c].blue = maskPreLight[base+d].blue;
+ maskPreLight[base+c].alpha = maskPreLight[base+d].alpha;
+
+ maskPreLight[base+b].red = maskPreLight[base+c].red;
+ maskPreLight[base+b].green = maskPreLight[base+c].green;
+ maskPreLight[base+b].blue = maskPreLight[base+c].blue;
+ maskPreLight[base+b].alpha = maskPreLight[base+c].alpha;
}
+ }
+
+ RpGeometryUnlock(maskGeometry);
+ return true;
+}
+#endif
+
+void
+CWaterLevel::RenderBoatWakes(void)
+{
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterWakeRaster);
+#ifndef PC_WATER
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+#endif
+
+#ifdef _XBOX
+ // TODO save and restore rwRENDERSTATESRCBLEND rwRENDERSTATEDESTBLEND
+#endif
+
+ CBoat::FillBoatList();
+
+ float fWakeZ = 5.97f;
+ float fWakeLifeTimeMult = 0.01f / CBoat::WAKE_LIFETIME;
+
+ for ( int32 idx = 0; idx < ARRAY_SIZE(CBoat::apFrameWakeGeneratingBoats); idx++ )
+ {
+ CBoat *pBoat = CBoat::apFrameWakeGeneratingBoats[idx];
+
+ if ( pBoat == nil )
+ break;
+
+ CVector2D vecDistA(pBoat->GetForward().x, pBoat->GetForward().y);
+
+
+ float fSize = pBoat->GetColModel()->boundingBox.max.z
+ * 0.65f;
- RpGeometryUnlock(geom);
+ if ( pBoat->GetModelIndex() == MI_SKIMMER)
+ fSize *= 0.4f;
+ float fAplhaA = 255.0f;
+ float fSizeA = fSize;
+ float fAplhaB;
+ float fSizeB;
- RwV3d pos = {0.0f, 0.0f, 0.0f};
+ for ( int32 wake = 1; wake < pBoat->m_nNumWakePoints; wake++ )
+ {
+ bool bRender = true;
+
+ float fTimeleft = CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake];
- pos.x = fX;
- pos.z = fZ;
- pos.y = fY;
+ float fWakeSizeB = ((float)wake * 0.19f) + fSize - fWakeLifeTimeMult * Max(fTimeleft, 0.0f);
+
+ fSizeB = fWakeSizeB / CBoat::MIN_WAKE_INTERVAL;
+ if ( fSizeB < 0.0f )
+ fSizeB = 1.0f;
+
+ if ( wake == pBoat->m_nNumWakePoints - 1 )
+ {
+ // set alpha to 0 if it's last point
+ fAplhaB = 0.0f;
+ }
+ else
+ {
+ // clip (-100, 500), less lifetime - less val
+ float val = 500.0f - (CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake])
+ * 600.0f / CBoat::WAKE_LIFETIME;
+
+ fAplhaB = clamp(val, 0.0f, 255.0f);
+ }
- RwFrameTranslate(RpAtomicGetFrame(atomic), &pos, rwCOMBINEREPLACE);
+ CVector2D vecDistB = pBoat->m_avec2dWakePoints[wake - 1] - pBoat->m_avec2dWakePoints[wake];
- RpAtomicRender(atomic);
-
- RpAtomicDestroy(atomic);
- RwFrameDestroy(frame);
+ float fScal = vecDistB.MagnitudeSqr();
+
+ // normalize if distance between points is greater than 3
+
+ if ( fScal > SQR(3.0f) )
+ {
+ float fNorm = 1.0f / sqrt(fScal);
+
+ vecDistB.x *= fNorm;
+ vecDistB.y *= fNorm;
+
+ // disable render if distance between points too big
+
+ if ( sqrt(fScal) > 13.0f )
+ bRender = false;
+ }
+
+ CVector2D vecAA
+ (
+ pBoat->m_avec2dWakePoints[wake - 1].x - (fSizeA * vecDistA.y),
+ pBoat->m_avec2dWakePoints[wake - 1].y + (fSizeA * vecDistA.x)
+ );
+ CVector2D vecAB
+ (
+ pBoat->m_avec2dWakePoints[wake - 1].x + (fSizeA * vecDistA.y),
+ pBoat->m_avec2dWakePoints[wake - 1].y - (fSizeA * vecDistA.x)
+ );
+ CVector2D vecBA
+ (
+ pBoat->m_avec2dWakePoints[wake].x + (fSizeB * vecDistB.y),
+ pBoat->m_avec2dWakePoints[wake].y - (fSizeB * vecDistB.x)
+ );
+ CVector2D vecBB
+ (
+ pBoat->m_avec2dWakePoints[wake].x - (fSizeB * vecDistB.y),
+ pBoat->m_avec2dWakePoints[wake].y + (fSizeB * vecDistB.x)
+ );
+
+ if ( bRender )
+ RenderWakeSegment(vecAA, vecAB, vecBA, vecBB, fSizeA, fSizeB, fAplhaA, fAplhaB, fWakeZ);
+
+ vecDistA = vecDistB;
+ fSizeA = fSizeB;
+
+ fAplhaB = fAplhaA;
+ }
}
- else
+
+ RenderAndEmptyRenderBuffer();
+}
+
+inline float
+_GetWindedWave(float fX, float fY)
+{
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+ float x = WATER_HUGE_X(fX + WATER_X_OFFSET);
+ float y = WATER_HUGE_Y(fY);
+
+ float fWindFactor (CWeather::WindClipped * 0.4f + 0.2f);
+ float fWave = Sin(( (x - Floor(x)) + (y - Floor(y)) ) * TWOPI + fAngle);
+
+ return fWindFactor * fWave;
+}
+
+void
+CWaterLevel::RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD,
+ float &fSizeA, float &fSizeB,
+ float &fAlphaA, float &fAlphaB,
+ float &fWakeZ)
+{
+ for ( int32 i = 0; i < 4; i++ )
{
- RwV3d pos = { 0.0f, 0.0f, 0.0f };
+ if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
+ RenderAndEmptyRenderBuffer();
+
+ float fCurStep = (float)i / 4;
+ float fNxtStep = (float)(i + 1) / 4;
+
+ float fLeftCurStep = 1.0f - fCurStep;
+ float fLeftNxtStep = 1.0f - fNxtStep;
- pos.x = fX;
- pos.y = fY;
- pos.z = fZ;
+ uint8 AlphaA = (uint32)(fAlphaA * aAlphaFade[i] );
+ uint8 AlphaB = (uint32)(fAlphaA * aAlphaFade[i + 1]);
+ uint8 AlphaC = (uint32)(fAlphaB * aAlphaFade[i + 1]);
+ uint8 AlphaD = (uint32)(fAlphaB * aAlphaFade[i] );
+
+ CVector2D PosA = vecB*fCurStep + vecA*fLeftCurStep;
+ CVector2D PosB = vecB*fNxtStep + vecA*fLeftNxtStep;
+ CVector2D PosC = vecC*fNxtStep + vecD*fLeftNxtStep;
+ CVector2D PosD = vecC*fCurStep + vecD*fLeftCurStep;
+
+ float fUA = (PosA.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVA = (PosA.y / 4) + _TEXTURE_WAKE_ADDV;
+
+ float fUB = (PosB.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVB = (PosB.y / 4) + _TEXTURE_WAKE_ADDV;
+
+ float fUC = (PosC.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVC = (PosC.y / 4) + _TEXTURE_WAKE_ADDV;
+
+ float fUD = (PosD.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVD = (PosD.y / 4) + _TEXTURE_WAKE_ADDV;
- ASSERT( ms_pWavyAtomic != NULL );
+#define MIN4(a, b, c, d) (Min((a), Min((b), Min((c), (d)))))
+ float fMinU = Floor(MIN4(fUA, fUB, fUC, fUD));
+ float fMinV = Floor(MIN4(fVA, fVB, fVC, fVD));
+#undef MIN4
+
+ float fZA = _GetWindedWave(PosA.x, PosA.y) + fWakeZ;
+ float fZB = _GetWindedWave(PosB.x, PosB.y) + fWakeZ;
+ float fZC = _GetWindedWave(PosC.x, PosC.y) + fWakeZ;
+ float fZD = _GetWindedWave(PosD.x, PosD.y) + fWakeZ;
+
+ int32 vidx = TempBufferVerticesStored;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], PosA.x, PosA.y, fZA);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], fUA - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], fVA - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], 255, 255, 255, AlphaA);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], PosB.x, PosB.y, fZB);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], fUB - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], fVB - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], 255, 255, 255, AlphaB);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], PosC.x, PosC.y, fZC);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], fUC - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], fVC - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], 255, 255, 255, AlphaC);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], PosD.x, PosD.y, fZD);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], fUD - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], fVD - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], 255, 255, 255, AlphaD);
- RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE);
+ int32 iidx = TempBufferIndicesStored;
+
+ TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;
- RpAtomicRender(ms_pWavyAtomic);
+ TempBufferVerticesStored += 4;
+
+ TempBufferIndicesStored += 6;
}
}
+void
+CWaterLevel::RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color)
+{
+ CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);
+
+ float fDistA = (CVector2D(fX, fY) - camPos).Magnitude() + -140.0f;
+ float fDistB = (CVector2D(fX, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f;
+ float fDistC = (CVector2D(fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f;
+ float fDistD = (CVector2D(fX + HUGE_SECTOR_SIZE, fY) - camPos).Magnitude() + -140.0f;
+
+#ifndef PC_WATER
+#define CALCSEABED(v, d) \
+ { \
+ if ( d < 0.0f ) \
+ v = 0.1f + fSeaBedZ; \
+ else if ( d > 240.0f ) \
+ v = 0.1f; \
+ else \
+ v = 0.1f + ((fSeaBedZ * (240.0f - d)) / 240.0f); \
+ }
+#else
+ #define CALCSEABED(v, d) \
+ { \
+ v = 0.1f; \
+ if ( d < 0.0f ) \
+ v += fSeaBedZ; \
+ else if ( d <= 240.0f ) \
+ v += (fSeaBedZ / 240.0f) * (240.0f - d); \
+ }
+#endif
+ float fSeaBedA, fSeaBedB, fSeaBedC, fSeaBedD;
+
+ CALCSEABED(fSeaBedA, fDistA);
+ CALCSEABED(fSeaBedB, fDistB);
+ CALCSEABED(fSeaBedC, fDistC);
+ CALCSEABED(fSeaBedD, fDistD);
+
+ #undef CALCSEABED
+
+ if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
+ RenderAndEmptyRenderBuffer();
+
+ int32 vidx = TempBufferVerticesStored;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset - fSeaBedA);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], 0.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], 0.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedB);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], 0.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], 4.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedC);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], 4.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], 4.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset - fSeaBedD);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], 4.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], 0.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);
+
+ int32 iidx = TempBufferIndicesStored;
+
+ TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;
+
+ TempBufferVerticesStored += 4;
+
+ TempBufferIndicesStored += 6;
+}
+
+void
+CWaterLevel::RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY,
+ RwRGBA const &color, RwRGBA const &colorTrans,
+ float fDrawDist)
+{
+ if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
+ RenderAndEmptyRenderBuffer();
+
+ int32 vidx = TempBufferVerticesStored;
+
+ float fBlendDrawDist = fDrawDist + fStartBlendDistanceAdd;
+
+ float fDistStartX = SQR(fX - fCamX);
+ float fDistStartY = SQR(fY - fCamY);
+ float fDistEndX = SQR((fX + SMALL_SECTOR_SIZE) - fCamX);
+ float fDistEndY = SQR((fY + SMALL_SECTOR_SIZE) - fCamY);
+
+
+ float fAlphaBlendMulA
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+ float fAlphaBlendMulB
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistEndY ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+ float fAlphaBlendMulC
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX + fDistEndY ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+ float fAlphaBlendMulD
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulA));
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulB));
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulC));
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulD));
+
+
+ int32 iidx = TempBufferIndicesStored;
+
+ TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;
+
+ TempBufferVerticesStored += 4;
+
+ TempBufferIndicesStored += 6;
+}
+
float
CWaterLevel::CalcDistanceToWater(float fX, float fY)
{
- const float fSectorMaxRenderDist = 75.0f;
+ const float fSectorMaxRenderDist = 250.0f;
- int32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist) - 1;
- int32 nEndX = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist) + 1;
+ int32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist + WATER_X_OFFSET) - 1;
+ int32 nEndX = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist + WATER_X_OFFSET) + 1;
int32 nStartY = WATER_TO_SMALL_SECTOR_Y(fY - fSectorMaxRenderDist) - 1;
int32 nEndY = WATER_TO_SMALL_SECTOR_Y(fY + fSectorMaxRenderDist) + 1;
@@ -1115,9 +2592,9 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY)
{
for ( int32 y = nStartY; y <= nEndY; y++ )
{
- if ( !(aWaterFineBlockList[x][y] & 128) )
+ if ( !(aWaterFineBlockList[x][y] & 0x80) )
{
- float fSectorX = WATER_FROM_SMALL_SECTOR_X(x);
+ float fSectorX = WATER_FROM_SMALL_SECTOR_X(x) - WATER_X_OFFSET;
float fSectorY = WATER_FROM_SMALL_SECTOR_Y(y);
CVector2D vecDist
@@ -1141,7 +2618,7 @@ CWaterLevel::RenderAndEmptyRenderBuffer()
{
LittleTest();
- if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, NULL, rwIM3D_VERTEXUV) )
+ if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV) )
{
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
RwIm3DEnd();
@@ -1152,97 +2629,339 @@ CWaterLevel::RenderAndEmptyRenderBuffer()
TempBufferVerticesStored = 0;
}
-void
-CWaterLevel::AllocateBoatWakeArray()
+bool
+CWaterLevel::GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance)
+{
+ CColPoint point;
+ CEntity *entity;
+
+ if ( !CWorld::ProcessVerticalLine(vecPosn + CVector(0.0f, 0.0f, fDistance),
+ -fDistance, point, entity, true, false, false, false, true, false, nil) )
+ return false;
+
+ *pfOutLevel = point.point.z;
+
+ if ( pData != nil )
+ {
+ pData->SurfaceType = point.surfaceB;
+ pData->PieceType = point.pieceB;
+ }
+
+ return true;
+}
+
+bool
+CWaterLevel::IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset)
+{
+ int32 x = int32((vecPosn.x / 50.0f) + 48.0f);
+ int32 y = int32((vecPosn.y / 50.0f) + 40.0f);
+
+ return x < nOffset || x >= 80 - nOffset || y < nOffset || y >= 80 - nOffset;
+}
+
+bool
+CWaterLevel::GetGroundLevel_WS(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance)
{
- CStreaming::MakeSpaceFor(14 * CDSTREAM_SECTOR_SIZE);
+ if ( IsLocationOutOfWorldBounds_WS(vecPosn, 0) )
+ return false;
+ else
+ return GetGroundLevel(vecPosn, pfOutLevel, pData, fDistance);
+}
- ASSERT(ms_pWavyAtomic != NULL );
+bool
+CWaterLevel::GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel)
+{
+ float fLevelNoWaves;
+ float fGroundLevel;
- RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
- ASSERT(wavyGeometry != NULL );
- RpMorphTarget *wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0);
- RpMaterial *wavyMaterial = RpGeometryGetMaterial(wavyGeometry, 0);
+ if ( !GetWaterLevelNoWaves(vecPosn.x, vecPosn.y, vecPosn.z, &fLevelNoWaves) )
+ return false;
+
+ if ( !GetGroundLevel(vecPosn, &fGroundLevel, nil, 30.0f) )
+ fGroundLevel = -100.0;
+
+ if ( pfDepth != nil )
+ *pfDepth = fLevelNoWaves - fGroundLevel;
- ASSERT(wavyMorphTarget != NULL );
- ASSERT(wavyMaterial != NULL );
+ if ( pfLevelNoWaves != nil )
+ *pfLevelNoWaves = fLevelNoWaves;
- for ( int32 geom = 0; geom < MAX_BOAT_WAKES; geom++ )
+ if ( pfGroundLevel != nil )
+ *pfGroundLevel = fGroundLevel;
+
+ return true;
+}
+
+void
+CWaterLevel::RenderSeaBirds()
+{
+ CVector cur_pos = TheCamera.GetPosition();
+
+ if ( !CCullZones::CamNoRain()
+ && !CCullZones::PlayerNoRain()
+ && (CWeather::NewWeatherType == WEATHER_SUNNY || CWeather::NewWeatherType == WEATHER_EXTRA_SUNNY)
+ && CClock::ms_nGameClockHours > 6 && CClock::ms_nGameClockHours < 20 )
{
- if ( apGeomArray[geom] == NULL )
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static CVector prev_front(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
{
- apGeomArray[geom] = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP
- | rpGEOMETRYPRELIT
- | rpGEOMETRYMODULATEMATERIALCOLOR
- | rpGEOMETRYTEXTURED);
- ASSERT(apGeomArray[geom] != NULL);
+ prev_pos = cur_pos;
+ timecounter = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+ static int32 birdgenTime = 0;
+
+ if ( (CTimer::GetTimeInMilliseconds() - birdgenTime) > 1000 )
+ {
+ birdgenTime = CTimer::GetTimeInMilliseconds();
+
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
- RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]);
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+ vecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f);
+
+ CVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
+ CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
+ 0.0f);
+
+ CParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+}
+
+void
+CWaterLevel::RenderShipsOnHorizon()
+{
+ CVector cur_pos = FindPlayerPed()->GetPosition();
+
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static CVector prev_front(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ 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();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+ static int32 shipgenTime = 0;
+
+ if ( (CTimer::GetTimeInMilliseconds() - shipgenTime) > 4000 )
+ {
+ shipgenTime = CTimer::GetTimeInMilliseconds();
+
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(450.0f, 750.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
- ASSERT( geomTriangles != NULL );
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
- for ( int32 i = 0; i < 8; i++ )
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ float fLevelNoWaves;
+
+ if ( GetWaterLevelNoWaves(vecPos.x, vecPos.y, vecPos.z, &fLevelNoWaves) )
{
- for ( int32 j = 0; j < 8; j++ )
+ if ( IsLocationOutOfWorldBounds_WS(vecPos, 1) )
{
+ vecPos.z = fLevelNoWaves + 9.5f;
- /*
- [B] [C]
- ***********
- * * *
- * * *
- * * *
- * * *
- ***********
- [A] [D]
- */
-
-
- RpGeometryTriangleSetVertexIndices(apGeomArray[geom],
- &geomTriangles[2 * 8*i + 2*j + 0], /*A*/i*9+j+0, /*B*/i*9+j+1, /*C*/i*9+j+9+1);
+ CVector vecDir
+ (
+ CGeneral::GetRandomNumberInRange(-0.1f, 0.1f),
+ 0.0f,
+ 0.0f
+ );
- RpGeometryTriangleSetVertexIndices(apGeomArray[geom],
- &geomTriangles[2 * 8*i + 2*j + 1], /*A*/i*9+j+0, /*C*/i*9+j+9+1, /*D*/i*9+j+9 );
-
- RpGeometryTriangleSetMaterial(apGeomArray[geom], &geomTriangles[2 * 8*i + 2*j + 0], wavyMaterial);
-
- RpGeometryTriangleSetMaterial(apGeomArray[geom], &geomTriangles[2 * 8*i + 2*j + 1], wavyMaterial);
+ CParticle::AddParticle(PARTICLE_SHIP_SIDE, vecPos, vecDir,
+ nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 7, 0);
}
}
+ }
+ }
+}
- RpMorphTarget *geomMorphTarget = RpGeometryGetMorphTarget(apGeomArray[geom], 0);
- RwV3d *geomVertices = RpMorphTargetGetVertices(geomMorphTarget);
-
- ASSERT( geomMorphTarget != NULL );
- ASSERT( geomVertices != NULL );
+void
+CWaterLevel::HandleSeaLifeForms()
+{
+ if ( CReplay::IsPlayingBack() )
+ return;
+
+ CVector cur_pos = FindPlayerPed()->GetPosition();
- for ( int32 i = 0; i < 9; i++ )
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ 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();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+//TODO(MIAMI)
+// if ( CWaterCreatures::IsSpaceForMoreWaterCreatures() )
+ {
+ for ( int32 i = 0; i < 3; i++ )
{
- for ( int32 j = 0; j < 9; j++ )
- {
- geomVertices[9*i+j].x = (float)i * 4.0f;
- geomVertices[9*i+j].y = (float)j * 4.0f;
- geomVertices[9*i+j].z = 0.0f;
- }
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(15.0f, 30.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ //TODO(MIAMI)
+ //CWaterCreatures::CreateOne(vecPos, 0xFFFFFFFF);
}
-
- RpMorphTargetSetBoundingSphere(geomMorphTarget, RpMorphTargetGetBoundingSphere(wavyMorphTarget));
- RpGeometryUnlock(apGeomArray[geom]);
}
}
+
+ //TODO(MIAMI)
+ //CWaterCreatures::UpdateAll();
}
void
-CWaterLevel::FreeBoatWakeArray()
+CWaterLevel::HandleBeachToysStuff(void)
{
- for ( int32 i = 0; i < MAX_BOAT_WAKES; i++ )
+ CVector cur_pos = FindPlayerPed()->GetPosition();
+
+ static bool bBeachBallInit = true;
+ static CVector FirstBeachBallPos = cur_pos;
+ static bool bLoungeInit = true;
+ static CVector FirstLoungePos = cur_pos;
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
{
- if ( apGeomArray[i] != NULL )
+ prev_pos = cur_pos;
+ timecounter = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+ static int32 toygenTime = CTimer::GetTimeInMilliseconds();
+
+ if ( (CTimer::GetTimeInMilliseconds() - toygenTime) > 20000 )
{
- RpGeometryDestroy(apGeomArray[i]);
- apGeomArray[i] = NULL;
+ toygenTime = CTimer::GetTimeInMilliseconds();
+
+ if ( bBeachBallInit || (cur_pos - FirstBeachBallPos).MagnitudeSqr() > 6400.0f )
+ {
+ for ( int32 i = 0; i < 3; i++ )
+ {
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ if ( TheCamera.IsSphereVisible(vecPos, 1.0f, &TheCamera.GetCameraMatrix()) )
+ {
+ float fWaterLevel;
+
+ if ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) )
+ {
+ float fGroundLevel;
+ ColData coldata;
+
+ if ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) )
+ {
+ if ( coldata.SurfaceType == SURFACE_SAND )
+ {
+ CEntity *toy = CreateBeachToy(vecPos, BEACHTOY_BALL);
+
+ if ( toy )
+ {
+ FirstBeachBallPos = cur_pos;
+ bBeachBallInit = false;
+ i = 10;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( bLoungeInit || (cur_pos - FirstLoungePos).MagnitudeSqr() > 6400.0f )
+ {
+ for ( int32 i = 0; i < 5; i++ )
+ {
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ if ( TheCamera.IsSphereVisible(vecPos, 2.0f, &TheCamera.GetCameraMatrix()) )
+ {
+ float fWaterLevel;
+
+ if ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) )
+ {
+ float fGroundLevel;
+ ColData coldata;
+
+ if ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) )
+ {
+ if ( coldata.SurfaceType == SURFACE_SAND )
+ {
+ CEntity *toy = CreateBeachToy(vecPos, BEACHTOY_LOUNGE);
+ if ( toy )
+ {
+ toy->SetHeading(DEGTORAD(CGeneral::GetRandomNumberInRange(0.0f, 359.0f)));
+ FirstLoungePos = cur_pos;
+ bLoungeInit = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
-
- nGeomUsed = 0;
}
+
+CEntity *
+CWaterLevel::CreateBeachToy(CVector const &vec, eBeachToy beachtoy)
+{
+ //TODO(MIAMI)
+ return nil;
+} \ No newline at end of file
diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h
index 269d6091..5b02d54f 100644
--- a/src/render/WaterLevel.h
+++ b/src/render/WaterLevel.h
@@ -1,8 +1,10 @@
#pragma once
-#define WATER_BLOCK_SIZE LARGE_SECTOR_SIZE
-#define WATER_FINEBLOCK_SIZE HUGE_SECTOR_SIZE
-#define WATER_Z_OFFSET (1.5f)
+#define WATER_X_OFFSET (400.0f)
+
+#define WATER_BLOCK_SECTORS MAX_LARGE_SECTORS
+#define WATER_FINEBLOCK_SECTORS MAX_SMALL_SECTORS
+#define WATER_Z_OFFSET (0.5f)
#define MAX_SMALL_SECTORS 128
#define MAX_LARGE_SECTORS 64
@@ -29,6 +31,14 @@
#define WATER_SIGN_X(x) ( (x) - (WATER_WIDTH /2) )
#define WATER_SIGN_Y(y) ( (y) - (WATER_HEIGHT/2) )
+// 64x64 Large blocks 64x64 each
+#define WATER_TO_BLOCK_X(x) ( WATER_UNSIGN_X(x) / WATER_BLOCK_SECTORS )
+#define WATER_TO_BLOCK_Y(x) ( WATER_UNSIGN_Y(x) / WATER_BLOCK_SECTORS )
+
+// 128x128 Small blocks 32x32 each
+#define WATER_TO_FINEBLOCK_X(x) ( WATER_UNSIGN_X(x) / WATER_FINEBLOCK_SECTORS )
+#define WATER_TO_FINEBLOCK_Y(x) ( WATER_UNSIGN_Y(x) / WATER_FINEBLOCK_SECTORS )
+
// 32
#define WATER_SMALL_X(x) ( WATER_UNSIGN_X(x) / MAX_SMALL_SECTORS )
#define WATER_SMALL_Y(y) ( WATER_UNSIGN_Y(y) / MAX_SMALL_SECTORS )
@@ -61,40 +71,106 @@
#define WATER_TO_EXTRAHUGE_SECTOR_X(x) ( WATER_UNSIGN_X(x) / EXTRAHUGE_SECTOR_SIZE )
#define WATER_TO_EXTRAHUGE_SECTOR_Y(y) ( WATER_UNSIGN_Y(y) / EXTRAHUGE_SECTOR_SIZE )
+struct ColData
+{
+ uint8 SurfaceType;
+ uint8 PieceType;
+};
-#define MAX_BOAT_WAKES 8
+enum eBeachToy
+{
+ BEACHTOY_0 = 0,
+ BEACHTOY_BALL,
+ BEACHTOY_2,
+ BEACHTOY_3,
+ BEACHTOY_4,
+ BEACHTOY_LOUNGE = 5
+};
extern RwRaster* gpWaterRaster;
extern bool gbDontRenderWater;
+class CEntity;
+
class CWaterLevel
{
+public:
static int32 ms_nNoOfWaterLevels;
static float ms_aWaterZs[48];
static CRect ms_aWaterRects[48];
- static uint8 aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE];
- static uint8 aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE];
+ static uint8 aWaterBlockList[WATER_BLOCK_SECTORS][WATER_BLOCK_SECTORS]; // 64x64 Large blocks 64x64 each
+ static uint8 aWaterFineBlockList[WATER_FINEBLOCK_SECTORS][WATER_FINEBLOCK_SECTORS]; // 128x128 Small blocks 32x32 each
static bool WavesCalculatedThisFrame;
- static RpAtomic *ms_pWavyAtomic;
- static RpGeometry *apGeomArray[MAX_BOAT_WAKES];
- static int16 nGeomUsed;
+
+ static bool RequireWavySector;
+ static bool MaskCalculatedThisFrame;
+ static CVector PreCalculatedMaskPosn;
+ static bool m_bRenderSeaBed;
+ static int32 m_nRenderWaterLayers;
+
+ static RpAtomic *ms_pWavyAtomic;
+ static RpAtomic *ms_pMaskAtomic;
-public:
- static void Initialise(Const char *pWaterDat);
static void Shutdown();
+
static void CreateWavyAtomic();
static void DestroyWavyAtomic();
+
+
static bool GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ);
static bool GetWaterLevel(CVector coors, float *pfOutLevel, bool bDontCheckZ) { return GetWaterLevel(coors.x, coors.y, coors.z, pfOutLevel, bDontCheckZ); }
static bool GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel);
+ static float GetWaterWavesOnly(short x, short y); // unused
+ static CVector GetWaterNormal(float fX, float fY);
+
static void RenderWater();
- static void RenderOneFlatSmallWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
- static void RenderOneFlatLargeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
- static void RenderOneFlatHugeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
- static void RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color);
- static void RenderOneWavySector (float fX, float fY, float fZ, RwRGBA const &color, bool bUnk = false);
- static float CalcDistanceToWater(float fX, float fY);
- static void RenderAndEmptyRenderBuffer();
- static void AllocateBoatWakeArray();
- static void FreeBoatWakeArray();
+ static void RenderTransparentWater(void);
+ // unused
+ static void RenderOneFlatSmallWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
+ // inlined
+ static void RenderOneFlatLargeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
+ static void RenderOneFlatHugeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
+ static void RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color);
+ // inlined
+ static void RenderOneWavySector (float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender = false);
+ // unused
+#ifdef PC_WATER
+ static void RenderWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, float fCamPosX, float fCamPosY, float fCamDirX, float fCamDirY, RwRGBA const&color);
+#else
+ static void RenderWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, int32 nCamDirX, int32 nCamDirY, RwRGBA const&color);
+#endif
+
+#ifdef PC_WATER
+ static void PreCalcWaterGeometry(void);
+ static bool PreCalcWavySector(RwRGBA const &color); //fucked up
+ static bool PreCalcWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, float fCamPosX, float fCamPosY, float fCamDirX, float fCamDirY, RwRGBA const&color);
+#endif
+
+
+ static void RenderBoatWakes(void);
+ static void RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD, float &fSizeA, float &fSizeB, float &fAlphaA, float &fAlphaB, float &fWakeZ);
+
+ // unused
+ static void RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color); // UNUSED
+ static void RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY, RwRGBA const &color, RwRGBA const &colorTrans, float fDrawDist);
+ static float CalcDistanceToWater(float fX, float fY);
+ static void RenderAndEmptyRenderBuffer();
+
+ static bool GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance);
+
+ // unused
+ static bool IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset);
+ // unused
+ static bool GetGroundLevel_WS(CVector const & vecPosn, float *pfOutLevel, ColData *pData, float fDistance);
+ static bool GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel);
+
+ static void RenderSeaBirds();
+ static void RenderShipsOnHorizon();
+
+ static void HandleSeaLifeForms();
+
+ static void HandleBeachToysStuff(void);
+ static CEntity *CreateBeachToy(CVector const &vec, eBeachToy beachtoy);
};
+
+extern void WaterLevelInitialise(Const char *datFile); \ No newline at end of file
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index b4031705..945e1f5e 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -8,6 +8,7 @@
#include "DMAudio.h"
#include "General.h"
#include "Pad.h"
+#include "PlayerPed.h"
#include "Particle.h"
#include "RenderBuffer.h"
#include "Stats.h"
@@ -17,6 +18,7 @@
#include "Vehicle.h"
#include "World.h"
#include "ZoneCull.h"
+#include "SpecialFX.h"
int32 CWeather::SoundHandle = -1;
@@ -32,6 +34,7 @@ uint32 CWeather::LightningFlashLastChange;
uint32 CWeather::WhenToPlayLightningSound;
uint32 CWeather::LightningDuration;
+float CWeather::ExtraSunnyness;
float CWeather::Foggyness;
float CWeather::CloudCoverage;
float CWeather::Wind;
@@ -39,41 +42,60 @@ float CWeather::Rain;
float CWeather::InterpolationValue;
float CWeather::WetRoads;
float CWeather::Rainbow;
+float CWeather::SunGlare;
+float CWeather::WindClipped;
+float CWeather::TrafficLightBrightness;
bool CWeather::bScriptsForceRain;
-bool CWeather::Stored_StateStored;
-
-float CWeather::Stored_InterpolationValue;
-int16 CWeather::Stored_OldWeatherType;
-int16 CWeather::Stored_NewWeatherType;
-float CWeather::Stored_Rain;
tRainStreak Streaks[NUM_RAIN_STREAKS];
const int16 WeatherTypesList[] = {
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY,
+ WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY,
WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_CLOUDY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_CLOUDY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, WEATHER_CLOUDY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
- WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY
+};
+
+const int16 WeatherTypesList_WithHurricanes[] = {
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_CLOUDY,
+ WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_CLOUDY, WEATHER_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_RAINY, WEATHER_CLOUDY,
+ WEATHER_CLOUDY, WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_HURRICANE,
+ WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY
};
const float Windiness[] = {
- 0.0f, // WEATHER_SUNNY
+ 0.25f,// WEATHER_SUNNY
0.7f, // WEATHER_CLOUDY
1.0f, // WEATHER_RAINY
- 0.5f // WEATHER_FOGGY
+ 0.0f, // WEATHER_FOGGY
+ 0.0f, // WEATHER_EXTRA_SUNNY
+ 2.0f, // WEATHER_HURRICANE
+ 0.0f
};
#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50)
@@ -104,10 +126,9 @@ const float Windiness[] = {
void CWeather::Init(void)
{
- NewWeatherType = WEATHER_SUNNY;
+ NewWeatherType = WEATHER_EXTRA_SUNNY;
bScriptsForceRain = false;
- OldWeatherType = WEATHER_CLOUDY;
- Stored_StateStored = false;
+ OldWeatherType = WEATHER_EXTRA_SUNNY;
InterpolationValue = 0.0f;
WhenToPlayLightningSound = 0;
WeatherTypeInList = 0;
@@ -127,16 +148,8 @@ void CWeather::Update(void)
NewWeatherType = ForcedWeatherType;
else {
WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList);
- NewWeatherType = WeatherTypesList[WeatherTypeInList];
-#ifdef FIX_BUGS
- }
- if (NewWeatherType == WEATHER_RAINY)
- CStats::mmRain += CGeneral::GetRandomNumber() & 7;
-#else
- if (NewWeatherType == WEATHER_RAINY)
- CStats::mmRain += CGeneral::GetRandomNumber() & 7;
+ NewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList];
}
-#endif
}
InterpolationValue = fNewInterpolation;
if (CPad::GetPad(1)->GetRightShockJustDown()) {
@@ -188,14 +201,14 @@ void CWeather::Update(void)
}
// Wet roads
- if (OldWeatherType == WEATHER_RAINY) {
- if (NewWeatherType == WEATHER_RAINY)
+ if (OldWeatherType == WEATHER_RAINY || OldWeatherType == WEATHER_HURRICANE) {
+ if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)
WetRoads = 1.0f;
else
WetRoads = 1.0f - InterpolationValue;
}
else {
- if (NewWeatherType == WEATHER_RAINY)
+ if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)
WetRoads = InterpolationValue;
else
WetRoads = 0.0f;
@@ -203,10 +216,10 @@ void CWeather::Update(void)
// Rain
float fNewRain;
- if (NewWeatherType == WEATHER_RAINY) {
+ if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {
// if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
- if (OldWeatherType != WEATHER_RAINY) {
+ if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {
if (InterpolationValue < 0.4f)
// if rain has just started (<24 minutes), always 0.5
fNewRain = 0.5f;
@@ -217,19 +230,14 @@ void CWeather::Update(void)
}
else
fNewRain = 0.0f;
- if (Rain != fNewRain) { // ok to use comparasion
- if (Rain < fNewRain)
- Rain = Min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
- else
- Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
- }
+ Rain = fNewRain;
// Clouds
- if (OldWeatherType != WEATHER_SUNNY)
+ if (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
CloudCoverage = 1.0f - InterpolationValue;
else
CloudCoverage = 0.0f;
- if (NewWeatherType != WEATHER_SUNNY)
+ if (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
CloudCoverage += InterpolationValue;
// Fog
@@ -239,12 +247,77 @@ void CWeather::Update(void)
Foggyness = 0.0f;
if (NewWeatherType == WEATHER_FOGGY)
Foggyness += InterpolationValue;
- if (OldWeatherType == WEATHER_RAINY && NewWeatherType == WEATHER_SUNNY && InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21)
+
+ // Extra Sunnyness
+ if (OldWeatherType == WEATHER_EXTRA_SUNNY)
+ ExtraSunnyness = 1.0f - InterpolationValue;
+ else
+ ExtraSunnyness = 0.0f;
+ if (NewWeatherType == WEATHER_EXTRA_SUNNY)
+ ExtraSunnyness += InterpolationValue;
+
+ // Rainbow
+ if (OldWeatherType == WEATHER_RAINY && (NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) &&
+ InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21)
Rainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f;
else
Rainbow = 0.0f;
+
+ // Sun Glare
+ if (OldWeatherType == WEATHER_EXTRA_SUNNY)
+ SunGlare = 1.0f - InterpolationValue;
+ else
+ SunGlare = 0.0f;
+ if (NewWeatherType == WEATHER_EXTRA_SUNNY)
+ SunGlare += InterpolationValue;
+
+ if (SunGlare > 0.0f) {
+ SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunDirection().z);
+ SunGlare = clamp(SunGlare, 0.0f, 1.0f);
+ if (!CSpecialFX::bSnapShotActive)
+ SunGlare *= (1.0f - (CGeneral::GetRandomNumber()&0x1F)*0.007f);
+ }
+
Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType];
+ WindClipped = Min(1.0f, Wind);
+
+ if (CClock::GetHours() == 20)
+ TrafficLightBrightness = CClock::GetMinutes() / 60.0f;
+ else if (CClock::GetHours() > 6 && CClock::GetHours() < 20)
+ TrafficLightBrightness = 0.0f;
+ else if (CClock::GetHours() == 6)
+ TrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f;
+ else
+ TrafficLightBrightness = 1.0f;
+ TrafficLightBrightness = Max(WetRoads, TrafficLightBrightness);
+ TrafficLightBrightness = Max(Rain, TrafficLightBrightness);
+
AddRain();
+
+ if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) &&
+ !CGame::IsInInterior() && !CCutsceneMgr::IsRunning() && (CTimer::GetFrameCounter() & 7) == 0) {
+#ifdef FIX_BUGS
+ if (FindPlayerPed() && (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f &&
+ CClock::GetHours() > 6 && CClock::GetHours() < 18))
+#else
+ if (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f &&
+ CClock::GetHours() > 6 && CClock::GetHours() < 18)
+#endif
+ AddHeatHaze();
+ }
+
+ if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && !CGame::IsInInterior() && !CCutsceneMgr::IsRunning())
+ AddBeastie();
+}
+
+void CWeather::AddHeatHaze()
+{
+ /* TODO(MIAMI) */
+}
+
+void CWeather::AddBeastie()
+{
+ /* TODO(MIAMI) */
}
void CWeather::ForceWeather(int16 weather)
@@ -494,7 +567,7 @@ void CWeather::RenderRainStreaks(void)
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex[3]));
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex));
if (RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 1))
{
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
@@ -510,23 +583,3 @@ void CWeather::RenderRainStreaks(void)
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
}
-
-void CWeather::StoreWeatherState()
-{
- Stored_StateStored = true;
- Stored_InterpolationValue = InterpolationValue;
- Stored_Rain = Rain;
- Stored_NewWeatherType = NewWeatherType;
- Stored_OldWeatherType = OldWeatherType;
-}
-
-void CWeather::RestoreWeatherState()
-{
-#ifdef FIX_BUGS // it's not used anyway though
- Stored_StateStored = false;
-#endif
- InterpolationValue = Stored_InterpolationValue;
- Rain = Stored_Rain;
- NewWeatherType = Stored_NewWeatherType;
- OldWeatherType = Stored_OldWeatherType;
-}
diff --git a/src/render/Weather.h b/src/render/Weather.h
index 9c670317..809bb787 100644
--- a/src/render/Weather.h
+++ b/src/render/Weather.h
@@ -1,21 +1,19 @@
enum {
- WEATHER_SUNNY,
+ WEATHER_RANDOM = -1,
+ WEATHER_SUNNY = 0,
WEATHER_CLOUDY,
WEATHER_RAINY,
- WEATHER_FOGGY
+ WEATHER_FOGGY,
+ WEATHER_EXTRA_SUNNY,
+ WEATHER_HURRICANE,
+ WEATHER_TOTAL,
+
+ WEATHER_EXTRACOLOURS = 6
};
class CWeather
{
public:
- enum {
- WEATHER_RANDOM = -1,
- WEATHER_SUNNY = 0,
- WEATHER_CLOUDY = 1,
- WEATHER_RAINY = 2,
- WEATHER_FOGGY = 3,
- WEATHER_TOTAL = 4
- };
static int32 SoundHandle;
static int32 WeatherTypeInList;
@@ -30,6 +28,7 @@ public:
static uint32 WhenToPlayLightningSound;
static uint32 LightningDuration;
+ static float ExtraSunnyness;
static float Foggyness;
static float CloudCoverage;
static float Wind;
@@ -37,13 +36,11 @@ public:
static float InterpolationValue;
static float WetRoads;
static float Rainbow;
+ static float SunGlare;
+ static float WindClipped;
+ static float TrafficLightBrightness;
static bool bScriptsForceRain;
- static bool Stored_StateStored;
- static float Stored_InterpolationValue;
- static int16 Stored_OldWeatherType;
- static int16 Stored_NewWeatherType;
- static float Stored_Rain;
static void RenderRainStreaks(void);
static void Update(void);
@@ -52,9 +49,9 @@ public:
static void ReleaseWeather();
static void ForceWeather(int16);
static void ForceWeatherNow(int16);
- static void StoreWeatherState();
- static void RestoreWeatherState();
static void AddRain();
+ static void AddHeatHaze();
+ static void AddBeastie();
};
enum {
@@ -68,4 +65,4 @@ struct tRainStreak
uint32 timer;
};
-extern RwTexture* gpRainDropTex[4]; \ No newline at end of file
+extern RwTexture* gpRainDropTex; \ No newline at end of file
diff --git a/src/render/WindModifiers.cpp b/src/render/WindModifiers.cpp
new file mode 100644
index 00000000..2061df6a
--- /dev/null
+++ b/src/render/WindModifiers.cpp
@@ -0,0 +1,51 @@
+#include "common.h"
+#include "WindModifiers.h"
+#include "Camera.h"
+#include "General.h"
+
+#define MAX_HEIGHT_DIST 40.0f
+#define MIN_FADE_DIST 20.0f
+#define MAX_FADE_DIST 50.0f
+
+CWindModifiers Array[16];
+int32 CWindModifiers::Number;
+
+void
+CWindModifiers::RegisterOne(CVector pos, int32 type = 1)
+{
+ if (CWindModifiers::Number < 16 && (pos - TheCamera.GetPosition()).Magnitude() < 100.0f) {
+ Array[Number].m_pos = pos;
+ Array[Number].m_type = type;
+ Number++;
+ }
+}
+
+bool
+CWindModifiers::FindWindModifier(CVector pos, float *x, float *y)
+{
+ bool bWasWindModifierFound = false;
+ CVector2D dir;
+ for (int i = 0; i < Number; i++) {
+ if (Array[i].m_type == 1) {
+ float zDist = Abs(15.0f + pos.z - Array[i].m_pos.z);
+
+ if (zDist < MAX_HEIGHT_DIST) {
+ float dist = (pos - Array[i].m_pos).Magnitude();
+ if (dist < MAX_FADE_DIST) {
+ float distFade = dist < MIN_FADE_DIST ? 1.0f : 1.0f - (dist - MIN_FADE_DIST) / (MAX_FADE_DIST - MIN_FADE_DIST);
+ float heightFade = 1.0f - zDist / MAX_HEIGHT_DIST;
+ dir = (pos - Array[i].m_pos) * heightFade / dist;
+ bWasWindModifierFound = true;
+ }
+ }
+ }
+ }
+
+ if (bWasWindModifierFound) {
+ float directionMult = ((CGeneral::GetRandomNumber() & 0x1F) - 16) * 0.0035f + 1.0f;
+ *x += dir.x * directionMult;
+ *y += dir.y * directionMult;
+ }
+
+ return bWasWindModifierFound;
+}
diff --git a/src/render/WindModifiers.h b/src/render/WindModifiers.h
new file mode 100644
index 00000000..7c2e57bd
--- /dev/null
+++ b/src/render/WindModifiers.h
@@ -0,0 +1,11 @@
+#pragma once
+
+class CWindModifiers
+{
+ CVector m_pos;
+ int32 m_type;
+public:
+ static int32 Number;
+ static void RegisterOne(CVector pos, int32 windSourceType);
+ static bool FindWindModifier(CVector pos, float *x, float *y);
+};