Merge remote-tracking branch 'upstream/lcs' into lcs

This commit is contained in:
Nikolay Korolev
2021-07-24 01:02:23 +03:00
81 changed files with 21 additions and 18 deletions

99
src/renderer/2dEffect.h Normal file
View File

@ -0,0 +1,99 @@
#pragma once
enum {
EFFECT_LIGHT,
EFFECT_PARTICLE,
EFFECT_ATTRACTOR,
EFFECT_PED_ATTRACTOR,
EFFECT_SUNGLARE
};
enum {
LIGHT_ON,
LIGHT_ON_NIGHT,
LIGHT_FLICKER,
LIGHT_FLICKER_NIGHT,
LIGHT_FLASH1,
LIGHT_FLASH1_NIGHT,
LIGHT_FLASH2,
LIGHT_FLASH2_NIGHT,
LIGHT_FLASH3,
LIGHT_FLASH3_NIGHT,
LIGHT_RANDOM_FLICKER,
LIGHT_RANDOM_FLICKER_NIGHT,
LIGHT_SPECIAL,
LIGHT_BRIDGE_FLASH1,
LIGHT_BRIDGE_FLASH2,
};
enum {
ATTRACTORTYPE_ICECREAM,
ATTRACTORTYPE_STARE
};
enum {
LIGHTFLAG_LOSCHECK = 1,
// 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)
};
class C2dEffect
{
public:
struct Light {
float dist;
float range; // of pointlight
float size;
float shadowSize;
uint8 lightType; // LIGHT_
uint8 roadReflection;
uint8 flareType;
uint8 shadowIntensity;
uint8 flags; // LIGHTFLAG_
RwTexture *corona;
RwTexture *shadow;
};
struct Particle {
int particleType;
CVector dir;
float scale;
};
struct Attractor {
CVector dir;
int8 type;
uint8 probability;
};
struct PedAttractor {
CVector queueDir;
CVector useDir;
int8 type;
};
CVector pos;
CRGBA col;
uint8 type;
union {
Light light;
Particle particle;
Attractor attractor;
PedAttractor pedattr;
};
C2dEffect(void) {}
void Shutdown(void){
if(type == EFFECT_LIGHT){
if(light.corona)
RwTextureDestroy(light.corona);
light.corona = nil;
if(light.shadow)
RwTextureDestroy(light.shadow);
light.shadow = nil;
}
}
};
VALIDATE_SIZE(C2dEffect, 0x34);

129
src/renderer/Antennas.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "common.h"
#include "main.h"
#include "Antennas.h"
CAntenna CAntennas::aAntennas[NUMANTENNAS];
void
CAntennas::Init(void)
{
int i;
for(i = 0; i < NUMANTENNAS; i++){
aAntennas[i].active = false;
aAntennas[i].updatedLastFrame = false;
}
}
// Free antennas that aren't used anymore
void
CAntennas::Update(void)
{
int i;
for(i = 0; i < NUMANTENNAS; i++){
if(aAntennas[i].active && !aAntennas[i].updatedLastFrame)
aAntennas[i].active = false;
aAntennas[i].updatedLastFrame = false;
}
}
// Add a new one or update an old one
void
CAntennas::RegisterOne(uint32 id, CVector dir, CVector position, float length)
{
int i, j;
for(i = 0; i < NUMANTENNAS; i++)
if(aAntennas[i].active && aAntennas[i].id == id)
break;
if(i >= NUMANTENNAS){
// not found, register new one
// find empty slot
for(i = 0; i < NUMANTENNAS; i++)
if(!aAntennas[i].active)
break;
// there is space
if(i < NUMANTENNAS){
aAntennas[i].active = true;
aAntennas[i].updatedLastFrame = true;
aAntennas[i].id = id;
aAntennas[i].segmentLength = length/6.0f;
for(j = 0; j < 6; j++){
aAntennas[i].pos[j] = position + dir*j*aAntennas[i].segmentLength;
aAntennas[i].speed[j] = CVector(0.0f, 0.0f, 0.0f);
}
}
}else{
// found, update
aAntennas[i].Update(dir, position);
aAntennas[i].updatedLastFrame = true;
}
}
static RwIm3DVertex vertexbufferA[2];
void
CAntennas::Render(void)
{
int i, j;
PUSH_RENDERGROUP("CAntennas::Render");
for(i = 0; i < NUMANTENNAS; i++){
if(!aAntennas[i].active)
continue;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
for(j = 0; j < 5; j++){
RwIm3DVertexSetRGBA(&vertexbufferA[0], 200, 200, 200, 100);
RwIm3DVertexSetPos(&vertexbufferA[0],
aAntennas[i].pos[j].x,
aAntennas[i].pos[j].y,
aAntennas[i].pos[j].z);
RwIm3DVertexSetRGBA(&vertexbufferA[1], 200, 200, 200, 100);
RwIm3DVertexSetPos(&vertexbufferA[1],
aAntennas[i].pos[j+1].x,
aAntennas[i].pos[j+1].y,
aAntennas[i].pos[j+1].z);
// LittleTest();
if(RwIm3DTransform(vertexbufferA, 2, nil, 0)){
RwIm3DRenderLine(0, 1);
RwIm3DEnd();
}
}
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
POP_RENDERGROUP();
}
void
CAntenna::Update(CVector dir, CVector basepos)
{
int i;
pos[0] = basepos;
pos[1] = basepos + dir*segmentLength;
for(i = 2; i < 6; i++){
CVector basedir = pos[i-1] - pos[i-2];
CVector newdir = pos[i] - pos[i-1] + // drag along
dir*0.1f + // also drag up a bit for stiffness
speed[i]; // and keep moving
newdir.Normalise();
newdir *= segmentLength;
CVector newpos = pos[i-1] + (basedir + newdir)/2.0f;
speed[i] = (newpos - pos[i])*0.9f;
pos[i] = newpos;
}
}

25
src/renderer/Antennas.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
class CAntenna
{
public:
bool active;
bool updatedLastFrame;
uint32 id;
float segmentLength;
CVector pos[6];
CVector speed[6];
void Update(CVector dir, CVector pos);
};
class CAntennas
{
// no need to use game's array
static CAntenna aAntennas[NUMANTENNAS];
public:
static void Init(void);
static void Update(void);
static void RegisterOne(uint32 id, CVector dir, CVector position, float length);
static void Render(void);
};

473
src/renderer/Clouds.cpp Normal file
View File

@ -0,0 +1,473 @@
#include "common.h"
#include "main.h"
#include "Sprite.h"
#include "Sprite2d.h"
#include "General.h"
#include "Game.h"
#include "Coronas.h"
#include "Camera.h"
#include "TxdStore.h"
#include "Weather.h"
#include "Clock.h"
#include "Timer.h"
#include "Timecycle.h"
#include "Renderer.h"
#include "Clouds.h"
#define SMALLSTRIPHEIGHT 4.0f
#define HORIZSTRIPHEIGHT 48.0f
RwTexture *gpCloudTex[5];
float CClouds::CloudRotation;
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)
{
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("particle"));
gpCloudTex[0] = RwTextureRead("cloud1", nil);
gpCloudTex[1] = RwTextureRead("cloud2", nil);
gpCloudTex[2] = RwTextureRead("cloud3", nil);
gpCloudTex[3] = RwTextureRead("cloudhilit", nil);
gpCloudTex[4] = RwTextureRead("cloudmasked", nil);
CTxdStore::PopCurrentTxd();
CloudRotation = 0.0f;
}
void
CClouds::Shutdown(void)
{
RwTextureDestroy(gpCloudTex[0]);
gpCloudTex[0] = nil;
RwTextureDestroy(gpCloudTex[1]);
gpCloudTex[1] = nil;
RwTextureDestroy(gpCloudTex[2]);
gpCloudTex[2] = nil;
RwTextureDestroy(gpCloudTex[3]);
gpCloudTex[3] = nil;
RwTextureDestroy(gpCloudTex[4]);
gpCloudTex[4] = nil;
}
void
CClouds::Update(void)
{
float s = Sin(TheCamera.Orientation - 0.85f);
#ifdef FIX_BUGS
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.001f;
IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f;
#endif
}
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 };
float LowCloudsX[12] = { 1.0f, 0.7f, 0.0f, -0.7f, -1.0f, -0.7f, 0.0f, 0.7f, 0.8f, -0.8f, 0.4f, -0.4f };
float LowCloudsY[12] = { 0.0f, -0.7f, -1.0f, -0.7f, 0.0f, 0.7f, 1.0f, 0.7f, 0.4f, 0.4f, -0.8f, -0.8f };
float LowCloudsZ[12] = { 0.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.3f, 0.9f, 0.4f, 1.3f, 1.4f, 1.2f, 1.7f };
float CoorsOffsetX[37] = {
0.0f, 60.0f, 72.0f, 48.0f, 21.0f, 12.0f,
9.0f, -3.0f, -8.4f, -18.0f, -15.0f, -36.0f,
-40.0f, -48.0f, -60.0f, -24.0f, 100.0f, 100.0f,
100.0f, 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,
100.0f, 100.0f, -30.0f, -20.0f, 10.0f, 30.0f,
0.0f, -100.0f, -100.0f, -100.0f, -100.0f, -100.0f, -100.0f
};
float CoorsOffsetY[37] = {
100.0f, 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,
100.0f, 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,
100.0f, 100.0f, 100.0f, 100.0f, -30.0f, 10.0f,
-25.0f, -5.0f, 28.0f, -10.0f, 10.0f, 0.0f,
15.0f, 40.0f, -100.0f, -100.0f, -100.0f, -100.0f,
-100.0f, -40.0f, -20.0f, 0.0f, 10.0f, 30.0f, 35.0f
};
float CoorsOffsetZ[37] = {
2.0f, 1.0f, 0.0f, 0.3f, 0.7f, 1.4f,
1.7f, 0.24f, 0.7f, 1.3f, 1.6f, 1.0f,
1.2f, 0.3f, 0.7f, 1.4f, 0.0f, 0.1f,
0.5f, 0.4f, 0.55f, 0.75f, 1.0f, 1.4f,
1.7f, 2.0f, 2.0f, 2.3f, 1.9f, 2.4f,
2.0f, 2.0f, 1.5f, 1.2f, 1.7f, 1.5f, 2.1f
};
uint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 };
uint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 };
uint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 };
void
CClouds::Render(void)
{
int i;
float szx, szy;
RwV3d screenpos;
RwV3d worldpos;
if(!CGame::CanSeeOutSideFromCurrArea())
return;
PUSH_RENDERGROUP("CClouds::Render");
CCoronas::SunBlockedByClouds = false;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
CSprite::InitSpriteBuffer();
float minute = CClock::GetHours()*60 + CClock::GetMinutes() + CClock::GetSeconds()/60.0f;
RwV3d campos = TheCamera.GetPosition();
// Moon
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 - (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]));
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);
}
}
// The R* logo
int starintens = 0;
if(CClock::GetHours() < 22 && CClock::GetHours() > 5)
starintens = 0;
else if(CClock::GetHours() > 22 || CClock::GetHours() < 5)
starintens = 255;
else if(CClock::GetHours() == 22)
starintens = 255 * CClock::GetMinutes()/60.0f;
else if(CClock::GetHours() == 5)
starintens = 255 * (60 - CClock::GetMinutes())/60.0f;
if(starintens != 0){
float coverage = Max(CWeather::Foggyness, CWeather::CloudCoverage);
int brightness = (1.0f - coverage) * starintens;
// R
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 11; i++){
RwV3d pos = { 100.0f, 0.0f, 10.0f };
if(i >= 9) pos.x = -pos.x;
RwV3dAdd(&worldpos, &campos, &pos);
worldpos.y -= 90.0f*StarCoorsX[i%9];
worldpos.z += 80.0f*StarCoorsY[i%9];
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
float sz = 0.8f*StarSizes[i%9];
CSprite::RenderBufferedOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,
szx*sz, szy*sz, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255);
}
}
CSprite::FlushSpriteBuffer();
// *
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
RwV3d pos = { 100.0f, 0.0f, 10.0f };
RwV3dAdd(&worldpos, &campos, &pos);
worldpos.y -= 90.0f;
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
brightness *= (CGeneral::GetRandomNumber()&127) / 640.0f + 0.5f;
CSprite::RenderOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,
szx*5.0f, szy*5.0f, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255);
}
}
// Low clouds
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;
for(int cloudtype = 0; cloudtype < 3; cloudtype++){
for(i = cloudtype; i < 12; i += 3){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[cloudtype]));
RwV3d pos = { 800.0f*LowCloudsX[i], 800.0f*LowCloudsY[i], 60.0f*LowCloudsZ[i] };
worldpos.x = campos.x + pos.x;
worldpos.y = campos.y + pos.y;
worldpos.z = 40.0f + pos.z;
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false))
CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(screenpos.x, screenpos.y, screenpos.z,
szx*320.0f, szy*40.0f, r, g, b, 255, 1.0f/screenpos.z, ms_cameraRoll, 255);
}
CSprite::FlushSpriteBuffer();
}
// Fluffy clouds
float rot_sin = Sin(CloudRotation);
float rot_cos = Cos(CloudRotation);
int fluffyalpha = 160 * (1.0f - Max(CWeather::Foggyness, CWeather::ExtraSunnyness));
if(fluffyalpha != 0){
static bool bCloudOnScreen[37];
float sundist, hilight;
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[4]));
for(i = 0; i < 37; i++){
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x;
worldpos.y = pos.x*rot_sin - pos.y*rot_cos + campos.y;
worldpos.z = pos.z;
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
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();
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;
br = br*(1.0f-hilight) + 255*hilight;
bg = bg*(1.0f-hilight) + 190*hilight;
bb = bb*(1.0f-hilight) + 190*hilight;
if(sundist < SCREEN_WIDTH/10)
CCoronas::SunBlockedByClouds = true;
}else
hilight = 0.0f;
CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(screenpos.x, screenpos.y, screenpos.z,
szx*55.0f, szy*55.0f,
tr, tg, tb, br, bg, bb, 0.0f, -1.0f,
1.0f/screenpos.z,
(uint16)IndividualRotation/65336.0f * 6.28f + ms_cameraRoll,
fluffyalpha);
bCloudOnScreen[i] = true;
}else
bCloudOnScreen[i] = false;
}
CSprite::FlushSpriteBuffer();
// Highlights
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[3]));
for(i = 0; i < 37; i++){
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x;
worldpos.y = pos.x*rot_sin + pos.y*rot_cos + campos.y;
worldpos.z = pos.z;
if(bCloudOnScreen[i] && CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
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,
1.7f - CGeneral::GetATanOfXY(screenpos.x-CCoronas::SunScreenX, screenpos.y-CCoronas::SunScreenY) + CClouds::ms_cameraRoll, 255);
}
}
}
CSprite::FlushSpriteBuffer();
}
// Rainbow
if(CWeather::Rainbow != 0.0f){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 6; i++){
RwV3d pos = { i*1.5f, 100.0f, 5.0f };
RwV3dAdd(&worldpos, &campos, &pos);
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false))
CSprite::RenderBufferedOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,
2.0f*szx, 50.0*szy,
BowRed[i]*CWeather::Rainbow, BowGreen[i]*CWeather::Rainbow, BowBlue[i]*CWeather::Rainbow,
255, 1.0f/screenpos.z, 255);
}
CSprite::FlushSpriteBuffer();
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
POP_RENDERGROUP();
}
bool
UseDarkBackground(void)
{
return TheCamera.GetForward().z < -0.9f || gbShowCollisionPolys;
}
void
CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue,
int16 botred, int16 botgreen, int16 botblue, int16 alpha)
{
PUSH_RENDERGROUP("CClouds::RenderBackground");
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(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;
ms_colourTop.b = 50;
ms_colourTop.a = 255;
if(gbShowCollisionPolys){
if(CTimer::GetFrameCounter() & 1){
ms_colourTop.r = 0;
ms_colourTop.g = 0;
ms_colourTop.b = 0;
}else{
ms_colourTop.r = 255;
ms_colourTop.g = 255;
ms_colourTop.b = 255;
}
}
ms_colourBottom = ms_colourTop;
CRect r(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
CSprite2d::DrawRect(r, ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
}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;
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)
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(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;
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 = fogr;
ms_colourTop.g = fogg;
ms_colourTop.b = fogb;
ms_colourBottom.r = fogr;
ms_colourBottom.g = fogg;
ms_colourBottom.b = fogb;
}
POP_RENDERGROUP();
}
void
CClouds::RenderHorizon(void)
{
if(UseDarkBackground())
return;
PUSH_RENDERGROUP("CClouds::RenderHorizon");
ms_colourBottom.a = 230;
ms_colourTop.a = 80;
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);
CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd);
POP_RENDERGROUP();
}

23
src/renderer/Clouds.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
class CClouds
{
public:
static float CloudRotation;
static uint32 IndividualRotation;
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);
static void Update(void);
static void Render(void);
static void RenderBackground(int16 topred, int16 topgreen, int16 topblue,
int16 botred, int16 botgreen, int16 botblue, int16 alpha);
static void RenderHorizon(void);
};

96
src/renderer/Console.cpp Normal file
View File

@ -0,0 +1,96 @@
#include "common.h"
#include <stdarg.h>
#include "Console.h"
#include "Font.h"
#include "Timer.h"
#define CONSOLE_X_POS (30.0f)
#define CONSOLE_Y_POS (10.0f)
#define CONSOLE_LINE_HEIGHT (12.0f)
CConsole TheConsole;
void
CConsole::AddLine(char *s, uint8 r, uint8 g, uint8 b)
{
char tempstr[MAX_STR_LEN+1];
while (strlen(s) > MAX_STR_LEN) {
strncpy(tempstr, s, MAX_STR_LEN);
tempstr[MAX_STR_LEN-1] = '\0';
s += MAX_STR_LEN - 1;
AddOneLine(tempstr, r, g, b);
}
AddOneLine(s, r, g, b);
}
void
CConsole::AddOneLine(char *s, uint8 r, uint8 g, uint8 b)
{
int32 StrIndex = (m_nLineCount + m_nCurrentLine) % MAX_LINES;
for (int32 i = 0; i < MAX_STR_LEN; i++) {
Buffers[StrIndex][i] = s[i];
if (s[i] == '\0') break;
}
uint8 _strNum1 = m_nLineCount;
if (_strNum1 < MAX_LINES)
_strNum1++;
m_aTimer[StrIndex] = CTimer::GetTimeInMilliseconds();
Buffers[StrIndex][MAX_STR_LEN-1] = '\0';
m_aRed[StrIndex] = r;
m_aGreen[StrIndex] = g;
m_aBlue[StrIndex] = b;
if (_strNum1 >= MAX_LINES)
m_nCurrentLine = (m_nCurrentLine + 1) % MAX_LINES;
else
m_nLineCount = _strNum1;
}
void
CConsole::Display()
{
CFont::SetPropOn();
CFont::SetBackgroundOff();
CFont::SetScale(0.6f, 0.6f);
CFont::SetCentreOff();
CFont::SetRightJustifyOff();
CFont::SetJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_STANDARD);
#ifndef FIX_BUGS
CFont::SetPropOff(); // not sure why this is here anyway
#endif
CFont::SetWrapx(RsGlobal.width);
while (m_nLineCount != 0 && CTimer::GetTimeInMilliseconds() - m_aTimer[m_nCurrentLine] > 20000) {
m_nLineCount--;
m_nCurrentLine = (m_nCurrentLine + 1) % MAX_LINES;
}
for (int16 i = 0; i < m_nLineCount; i++) {
int16 line = (i + m_nCurrentLine) % MAX_LINES;
CFont::SetColor(CRGBA(0, 0, 0, 200));
CFont::PrintString(CONSOLE_X_POS + 1.0f, CONSOLE_Y_POS + 1.0f + i * CONSOLE_LINE_HEIGHT, Buffers[line]);
CFont::SetColor(CRGBA(m_aRed[line], m_aGreen[line], m_aBlue[line], 200));
CFont::PrintString(CONSOLE_X_POS, CONSOLE_Y_POS + i * CONSOLE_LINE_HEIGHT, Buffers[line]);
}
}
void
cprintf(char* format, ...)
{
char s[256];
va_list vl1, vl2;
va_start(vl1, format);
va_copy(vl2, vl1);
vsprintf(s, format, vl1);
TheConsole.AddLine(s, 255, 255, 128);
}

27
src/renderer/Console.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
class CConsole
{
enum
{
MAX_LINES = 8, // BUG? only shows 7
MAX_STR_LEN = 40,
};
uint8 m_nLineCount;
uint8 m_nCurrentLine;
wchar Buffers[MAX_LINES][MAX_STR_LEN];
uint32 m_aTimer[MAX_LINES];
uint8 m_aRed[MAX_LINES];
uint8 m_aGreen[MAX_LINES];
uint8 m_aBlue[MAX_LINES];
public:
void AddLine(char *s, uint8 r, uint8 g, uint8 b);
void AddOneLine(char *s, uint8 r, uint8 g, uint8 b);
void Display();
void Init() { m_nCurrentLine = 0; m_nLineCount = 0; }
};
extern CConsole TheConsole;
void cprintf(char*, ...);

959
src/renderer/Coronas.cpp Normal file
View File

@ -0,0 +1,959 @@
#include "common.h"
#include "main.h"
#include "General.h"
#include "Entity.h"
#include "RenderBuffer.h"
#include "TxdStore.h"
#include "Camera.h"
#include "Sprite.h"
#include "Timer.h"
#include "World.h"
#include "Weather.h"
#include "Collision.h"
#include "Timecycle.h"
#include "Coronas.h"
#include "PointLights.h"
#include "Shadows.h"
#include "Clock.h"
#include "Bridge.h"
struct FlareDef
{
float position;
float size;
int16 red;
int16 green;
int16 blue;
int16 alpha;
int16 texture;
};
FlareDef SunFlareDef[] = {
{ -0.5f, 15.0f, 50, 50, 0, 200, 1 },
{ -1.0f, 10.0f, 50, 20, 0, 200, 2 },
{ -1.5f, 15.0f, 50, 0, 0, 200, 3 },
{ -2.5f, 25.0f, 50, 0, 0, 200, 1 },
{ 0.5f, 12.5f, 40, 40, 25, 200, 1 },
{ 0.05f, 20.0f, 30, 22, 9, 200, 2 },
{ 1.3f, 7.5f, 50, 30, 9, 200, 3 },
{ 0.0f, 0.0f, 255, 255, 255, 255, 0 }
};
FlareDef HeadLightsFlareDef[] = {
{ -0.5f, 15.5, 70, 70, 70, 200, 1 },
{ -1.0f, 10.0, 70, 70, 70, 200, 2 },
{ -1.5f, 5.5f, 50, 50, 50, 200, 3 },
{ 0.5f, 12.0f, 50, 50, 50, 200, 1 },
{ 0.05f, 20.0f, 40, 40, 40, 200, 2 },
{ 1.3f, 8.0f, 60, 60, 60, 200, 3 },
{ -2.0f, 12.0f, 50, 50, 50, 200, 1 },
{ -2.3f, 15.0f, 40, 40, 40, 200, 2 },
{ -3.0f, 16.0f, 40, 40, 40, 200, 3 },
{ 0.0f, 0.0f, 255, 255, 255, 255, 0 }
};
RwTexture *gpCoronaTexture[9] = { nil, nil, nil, nil, nil, nil, nil, nil, nil };
float CCoronas::LightsMult = 1.0f;
float CCoronas::SunScreenX;
float CCoronas::SunScreenY;
int CCoronas::MoonSize;
bool CCoronas::SunBlockedByClouds;
int CCoronas::bChangeBrightnessImmediately;
CRegisteredCorona CCoronas::aCoronas[NUMCORONAS];
const char aCoronaSpriteNames[][32] = {
"coronastar",
"corona",
"coronamoon",
"coronareflect",
"coronaheadlightline",
"coronahex",
"coronacircle",
"coronaringa",
"streek"
};
void
CCoronas::Init(void)
{
int i;
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("particle"));
for(i = 0; i < 9; i++)
if(gpCoronaTexture[i] == nil)
gpCoronaTexture[i] = RwTextureRead(aCoronaSpriteNames[i], nil);
CTxdStore::PopCurrentTxd();
for(i = 0; i < NUMCORONAS; i++)
aCoronas[i].id = 0;
}
void
CCoronas::Shutdown(void)
{
int i;
for(i = 0; i < 9; i++)
if(gpCoronaTexture[i]){
RwTextureDestroy(gpCoronaTexture[i]);
gpCoronaTexture[i] = nil;
}
}
void
CCoronas::Update(void)
{
int i;
static int LastCamLook = 0;
LightsMult = Min(LightsMult + 0.03f * CTimer::GetTimeStep(), 1.0f);
int CamLook = 0;
if(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft) CamLook |= 1;
if(TheCamera.Cams[TheCamera.ActiveCam].LookingRight) CamLook |= 2;
if(TheCamera.Cams[TheCamera.ActiveCam].LookingBehind) CamLook |= 4;
// BUG?
if(TheCamera.GetLookDirection() == LOOKING_BEHIND) CamLook |= 8;
if(LastCamLook != CamLook)
bChangeBrightnessImmediately = 3;
else
bChangeBrightnessImmediately = Max(bChangeBrightnessImmediately-1, 0);
LastCamLook = CamLook;
for(i = 0; i < NUMCORONAS; i++)
if(aCoronas[i].id != 0)
aCoronas[i].Update();
}
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,
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;
if(i == NUMCORONAS){
// add a new one
// find empty slot
for(i = 0; i < NUMCORONAS; i++)
if(aCoronas[i].id == 0)
break;
if(i == NUMCORONAS)
return; // no space
aCoronas[i].fadeAlpha = 0;
aCoronas[i].offScreen = true;
aCoronas[i].firstUpdate = true;
aCoronas[i].renderReflection = false;
aCoronas[i].lastLOScheck = 0;
aCoronas[i].sightClear = false;
aCoronas[i].hasValue[0] = false;
aCoronas[i].hasValue[1] = false;
aCoronas[i].hasValue[2] = false;
aCoronas[i].hasValue[3] = false;
aCoronas[i].hasValue[4] = false;
aCoronas[i].hasValue[5] = false;
}else{
// use existing one
if(aCoronas[i].fadeAlpha == 0 && alpha == 0){
// unregister
aCoronas[i].id = 0;
return;
}
}
aCoronas[i].id = id;
aCoronas[i].red = red;
aCoronas[i].green = green;
aCoronas[i].blue = blue;
aCoronas[i].alpha = alpha;
aCoronas[i].coors = coors;
aCoronas[i].size = size;
aCoronas[i].someAngle = someAngle;
aCoronas[i].registeredThisFrame = true;
aCoronas[i].drawDist = drawDist;
aCoronas[i].texture = tex;
aCoronas[i].flareType = flareType;
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,
bool useNearDist, float nearDist)
{
RegisterCorona(id, red, green, blue, alpha, coors, size, drawDist,
gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle,
useNearDist, nearDist);
}
void
CCoronas::UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle)
{
int i;
if(sq(drawDist) < (TheCamera.GetPosition() - coors).MagnitudeSqr2D())
return;
for(i = 0; i < NUMCORONAS; i++)
if(aCoronas[i].id == id)
break;
if(i == NUMCORONAS)
return;
if(aCoronas[i].fadeAlpha == 0)
aCoronas[i].id = 0; // faded out, remove
else{
aCoronas[i].coors = coors;
aCoronas[i].someAngle = someAngle;
}
}
static RwIm2DVertex vertexbufferX[2];
void
CCoronas::Render(void)
{
int i, j;
int screenw, screenh;
PUSH_RENDERGROUP("CCoronas::Render");
screenw = RwRasterGetWidth(RwCameraGetRaster(Scene.camera));
screenh = RwRasterGetHeight(RwCameraGetRaster(Scene.camera));
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
for(i = 0; i < NUMCORONAS; i++){
for(j = 5; j > 0; j--){
aCoronas[i].prevX[j] = aCoronas[i].prevX[j-1];
aCoronas[i].prevY[j] = aCoronas[i].prevY[j-1];
aCoronas[i].prevRed[j] = aCoronas[i].prevRed[j-1];
aCoronas[i].prevGreen[j] = aCoronas[i].prevGreen[j-1];
aCoronas[i].prevBlue[j] = aCoronas[i].prevBlue[j-1];
aCoronas[i].hasValue[j] = aCoronas[i].hasValue[j-1];
}
aCoronas[i].hasValue[0] = false;
if(aCoronas[i].id == 0 ||
aCoronas[i].fadeAlpha == 0 && aCoronas[i].alpha == 0)
continue;
CVector spriteCoors;
float spritew, spriteh;
if(!CSprite::CalcScreenCoors(aCoronas[i].coors, &spriteCoors, &spritew, &spriteh, true)){
aCoronas[i].offScreen = true;
aCoronas[i].sightClear = false;
}else{
aCoronas[i].offScreen = false;
if(spriteCoors.x < 0.0f || spriteCoors.y < 0.0f ||
spriteCoors.x > screenw || spriteCoors.y > screenh){
aCoronas[i].offScreen = true;
aCoronas[i].sightClear = false;
}else{
if(CTimer::GetTimeInMilliseconds() > aCoronas[i].lastLOScheck + 2000){
aCoronas[i].lastLOScheck = CTimer::GetTimeInMilliseconds();
aCoronas[i].sightClear = CWorld::GetIsLineOfSightClear(
aCoronas[i].coors, TheCamera.Cams[TheCamera.ActiveCam].Source,
true, true, false, false, false, true, false);
}
// add new streak point
if(aCoronas[i].sightClear){
aCoronas[i].prevX[0] = spriteCoors.x;
aCoronas[i].prevY[0] = spriteCoors.y;
aCoronas[i].prevRed[0] = aCoronas[i].red;
aCoronas[i].prevGreen[0] = aCoronas[i].green;
aCoronas[i].prevBlue[0] = aCoronas[i].blue;
aCoronas[i].hasValue[0] = true;
}
// if distance too big, break streak
if(aCoronas[i].hasValue[1]){
if(Abs(aCoronas[i].prevX[0] - aCoronas[i].prevX[1]) > 50.0f ||
Abs(aCoronas[i].prevY[0] - aCoronas[i].prevY[1]) > 50.0f)
aCoronas[i].hasValue[0] = false;
}
}
if(aCoronas[i].fadeAlpha && spriteCoors.z < aCoronas[i].drawDist){
float recipz = 1.0f/spriteCoors.z;
float fadeDistance = aCoronas[i].drawDist / 2.0f;
float distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance;
int totalFade = aCoronas[i].fadeAlpha * distanceFade;
if(aCoronas[i].LOScheck)
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
else
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
// render corona itself
if(aCoronas[i].texture){
float fogscale = CWeather::Foggyness*Min(spriteCoors.z, 40.0f)/40.0f + 1.0f;
if(CCoronas::aCoronas[i].id == SUN_CORE)
spriteCoors.z = 0.95f * RwCameraGetFarClipPlane(Scene.camera);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aCoronas[i].texture));
spriteCoors.z -= aCoronas[i].nearDist;
if(aCoronas[i].texture == gpCoronaTexture[8]){
// what's this?
float f = 1.0f - aCoronas[i].someAngle*2.0f/PI;
float wscale = 6.0f*sq(sq(sq(f))) + 0.5f;
float hscale = 0.35f - (wscale - 0.5f) * 0.06f;
hscale = Max(hscale, 0.15f);
CSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * aCoronas[i].size * wscale,
spriteh * aCoronas[i].size * fogscale * hscale,
CCoronas::aCoronas[i].red / fogscale,
CCoronas::aCoronas[i].green / fogscale,
CCoronas::aCoronas[i].blue / fogscale,
totalFade,
recipz,
255);
}else{
CSprite::RenderOneXLUSprite_Rotate_Aspect(
spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * aCoronas[i].size * fogscale,
spriteh * aCoronas[i].size * fogscale,
CCoronas::aCoronas[i].red / fogscale,
CCoronas::aCoronas[i].green / fogscale,
CCoronas::aCoronas[i].blue / fogscale,
totalFade,
recipz,
20.0f * recipz,
255);
}
}
// render flares
if(aCoronas[i].flareType != FLARE_NONE){
FlareDef *flare;
switch(aCoronas[i].flareType){
case FLARE_SUN: flare = SunFlareDef; break;
case FLARE_HEADLIGHTS: flare = HeadLightsFlareDef; break;
default: assert(0);
}
for(; flare->texture; flare++){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[flare->texture + 4]));
CSprite::RenderOneXLUSprite(
(spriteCoors.x - (screenw/2)) * flare->position + (screenw/2),
(spriteCoors.y - (screenh/2)) * flare->position + (screenh/2),
spriteCoors.z,
4.0f*flare->size * spritew/spriteh,
4.0f*flare->size,
(flare->red * aCoronas[i].red)>>8,
(flare->green * aCoronas[i].green)>>8,
(flare->blue * aCoronas[i].blue)>>8,
(totalFade * flare->alpha)>>8,
recipz, 255);
}
}
}
}
}
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
// streaks
for(i = 0; i < NUMCORONAS; i++){
if(aCoronas[i].id == 0 || !aCoronas[i].drawStreak)
continue;
for(j = 0; j < 5; j++){
if(!aCoronas[i].hasValue[j] || !aCoronas[i].hasValue[j+1])
continue;
int alpha1 = (float)(6 - j) / 6 * 128;
int alpha2 = (float)(6 - (j+1)) / 6 * 128;
RwIm2DVertexSetScreenX(&vertexbufferX[0], aCoronas[i].prevX[j]);
RwIm2DVertexSetScreenY(&vertexbufferX[0], aCoronas[i].prevY[j]);
RwIm2DVertexSetIntRGBA(&vertexbufferX[0], aCoronas[i].prevRed[j] * alpha1 / 256, aCoronas[i].prevGreen[j] * alpha1 / 256, aCoronas[i].prevBlue[j] * alpha1 / 256, 255);
RwIm2DVertexSetScreenX(&vertexbufferX[1], aCoronas[i].prevX[j+1]);
RwIm2DVertexSetScreenY(&vertexbufferX[1], aCoronas[i].prevY[j+1]);
RwIm2DVertexSetIntRGBA(&vertexbufferX[1], aCoronas[i].prevRed[j+1] * alpha2 / 256, aCoronas[i].prevGreen[j+1] * alpha2 / 256, aCoronas[i].prevBlue[j+1] * alpha2 / 256, 255);
#ifdef FIX_BUGS
RwIm2DVertexSetScreenZ(&vertexbufferX[0], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&vertexbufferX[0], RwCameraGetNearClipPlane(Scene.camera));
RwIm2DVertexSetRecipCameraZ(&vertexbufferX[0], 1.0f/RwCameraGetNearClipPlane(Scene.camera));
RwIm2DVertexSetScreenZ(&vertexbufferX[1], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&vertexbufferX[1], RwCameraGetNearClipPlane(Scene.camera));
RwIm2DVertexSetRecipCameraZ(&vertexbufferX[1], 1.0f/RwCameraGetNearClipPlane(Scene.camera));
#endif
RwIm2DRenderLine(vertexbufferX, 2, 0, 1);
}
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
POP_RENDERGROUP();
}
void
CCoronas::RenderReflections(void)
{
int i;
CColPoint point;
CEntity *entity;
if(CWeather::WetRoads > 0.0f){
PUSH_RENDERGROUP("CCoronas::RenderReflections");
CSprite::InitSpriteBuffer();
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[3]));
for(i = 0; i < NUMCORONAS; i++){
if(aCoronas[i].id == 0 ||
aCoronas[i].fadeAlpha == 0 && aCoronas[i].alpha == 0 ||
aCoronas[i].reflection == 0)
continue;
// check if we want a reflection on this corona
if(aCoronas[i].renderReflection){
if(((CTimer::GetFrameCounter() + i) & 0xF) == 0 &&
CWorld::ProcessVerticalLine(aCoronas[i].coors, -1000.0f, point, entity, true, false, false, false, true, false, nil))
aCoronas[i].heightAboveRoad = aCoronas[i].coors.z - point.point.z;
}else{
if(CWorld::ProcessVerticalLine(aCoronas[i].coors, -1000.0f, point, entity, true, false, false, false, true, false, nil)){
aCoronas[i].heightAboveRoad = aCoronas[i].coors.z - point.point.z;
aCoronas[i].renderReflection = true;
}
}
// Don't draw if reflection is too high
if(aCoronas[i].renderReflection && aCoronas[i].heightAboveRoad < 20.0f){
// don't draw if camera is below road
if(CCoronas::aCoronas[i].coors.z - aCoronas[i].heightAboveRoad > TheCamera.GetPosition().z)
continue;
CVector coors = aCoronas[i].coors;
coors.z -= 2.0f*aCoronas[i].heightAboveRoad;
CVector spriteCoors;
float spritew, spriteh;
if(CSprite::CalcScreenCoors(coors, &spriteCoors, &spritew, &spriteh, true)) {
float drawDist = 0.75f * aCoronas[i].drawDist;
drawDist = Min(drawDist, 55.0f);
if(spriteCoors.z < drawDist){
float fadeDistance = drawDist / 2.0f;
float distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance;
distanceFade = Clamp(distanceFade, 0.0f, 1.0f);
float recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera);
float heightFade = (20.0f - aCoronas[i].heightAboveRoad)/20.0f;
int intensity = distanceFade*heightFade * 230.0 * CWeather::WetRoads;
CSprite::RenderBufferedOneXLUSprite(
#ifdef FIX_BUGS
spriteCoors.x, spriteCoors.y, spriteCoors.z,
#else
spriteCoors.x, spriteCoors.y, RwIm2DGetNearScreenZ(),
#endif
spritew * aCoronas[i].size * 0.75f,
spriteh * aCoronas[i].size * 2.0f,
(intensity * CCoronas::aCoronas[i].red)>>8,
(intensity * CCoronas::aCoronas[i].green)>>8,
(intensity * CCoronas::aCoronas[i].blue)>>8,
255,
recipz,
255);
}
}
}
}
CSprite::FlushSpriteBuffer();
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
POP_RENDERGROUP();
}else{
for(i = 0; i < NUMCORONAS; i++)
aCoronas[i].renderReflection = false;
}
}
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)
{
// yeah, moon is done somewhere else....
CVector sunCoors = CTimeCycle::GetSunDirection();
sunCoors *= 150.0f;
sunCoors += TheCamera.GetPosition();
if(CTimeCycle::GetSunDirection().z > -0.2f){
float size = ((CGeneral::GetRandomNumber()&0xFF) * 0.005f + 10.0f) * CTimeCycle::GetSunSize();
RegisterCorona(SUN_CORE,
CTimeCycle::GetSunCoreRed(), CTimeCycle::GetSunCoreGreen(), CTimeCycle::GetSunCoreBlue(),
255, sunCoors, size,
999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 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(),
999999.88f, TYPE_STAR, FLARE_SUN, REFLECTION_OFF, LOSCHECK_ON, STREAK_OFF, 0.0f);
}
CVector spriteCoors;
float spritew, spriteh;
if(CSprite::CalcScreenCoors(sunCoors, &spriteCoors, &spritew, &spriteh, true)) {
SunScreenX = spriteCoors.x;
SunScreenY = spriteCoors.y;
}else{
SunScreenX = 1000000.0f;
SunScreenY = 1000000.0f;
}
}
void
CRegisteredCorona::Update(void)
{
if(!registeredThisFrame)
alpha = 0;
if(LOScheck &&
(CCoronas::SunBlockedByClouds && id == CCoronas::SUN_CORONA ||
!CWorld::GetIsLineOfSightClear(coors, TheCamera.GetPosition(), true, false, false, false, false, false))){
// Corona is blocked, fade out
fadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f);
}else if(offScreen){
// Same when off screen
fadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f);
}else{
// Visible
if(alpha > fadeAlpha){
// fade in
fadeAlpha = Min(fadeAlpha + 15.0f*CTimer::GetTimeStep(), alpha);
if(CCoronas::bChangeBrightnessImmediately)
fadeAlpha = alpha;
}else if(alpha < fadeAlpha){
// too visible, decrease alpha but not below alpha
fadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), alpha);
}
// darken scene when the sun is visible
if(id == CCoronas::SUN_CORONA)
CCoronas::LightsMult = Max(CCoronas::LightsMult - CTimer::GetTimeStep()*0.06f, 0.6f);
}
// remove if invisible
if(fadeAlpha == 0 && !firstUpdate)
id = 0;
firstUpdate = false;
registeredThisFrame = false;
}
void
CEntity::ProcessLightsForEntity(void)
{
int i, n;
C2dEffect *effect;
CVector pos;
bool lightOn, lightFlickering;
uint32 flashTimer1, flashTimer2, flashTimer3;
if(bRenderDamaged || !bIsVisible || GetUp().z < 0.96f)
return;
flashTimer1 = 0;
flashTimer2 = 0;
flashTimer3 = 0;
n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();
for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){
effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
switch(effect->type){
case EFFECT_LIGHT:
pos = GetMatrix() * effect->pos;
lightOn = false;
lightFlickering = false;
switch(effect->light.lightType){
case LIGHT_ON:
lightOn = true;
break;
case LIGHT_ON_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
lightOn = true;
break;
case LIGHT_FLICKER:
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)
lightOn = true;
break;
case LIGHT_FLICKER_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)
lightOn = true;
}
break;
case LIGHT_FLASH1:
if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
lightOn = true;
break;
case LIGHT_FLASH1_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
lightOn = true;
break;
case LIGHT_FLASH2:
if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
lightOn = true;
break;
case LIGHT_FLASH2_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
lightOn = true;
break;
case LIGHT_FLASH3:
if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
lightOn = true;
break;
case LIGHT_FLASH3_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
lightOn = true;
break;
case LIGHT_RANDOM_FLICKER:
if(m_randomSeed > 16)
lightOn = true;
else{
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)
lightOn = true;
}
break;
case LIGHT_RANDOM_FLICKER_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7){
if(m_randomSeed > 16)
lightOn = true;
else{
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)
lightOn = true;
}
}
break;
case LIGHT_BRIDGE_FLASH1:
if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200)
lightOn = true;
break;
case LIGHT_BRIDGE_FLASH2:
if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60)
lightOn = true;
break;
}
if(effect->light.flags & LIGHTFLAG_HIDE_OBJECT){
if(lightOn)
bDoNotRender = false;
else
bDoNotRender = true;
return;
}
// Corona
if(lightOn)
CCoronas::RegisterCorona((uintptr)this + i,
effect->col.r, effect->col.g, effect->col.b, 255,
pos, effect->light.size, effect->light.dist,
effect->light.corona, effect->light.flareType, effect->light.roadReflection,
effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,
!!(effect->light.flags&LIGHTFLAG_LONG_DIST));
else if(lightFlickering)
CCoronas::RegisterCorona((uintptr)this + i,
0, 0, 0, 255,
pos, effect->light.size, effect->light.dist,
effect->light.corona, effect->light.flareType, effect->light.roadReflection,
effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,
!!(effect->light.flags&LIGHTFLAG_LONG_DIST));
// Pointlight
bool alreadyProcessedFog;
alreadyProcessedFog = false;
if(effect->light.range != 0.0f && lightOn){
if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
effect->light.range,
0.0f, 0.0f, 0.0f,
CPointLights::FOG_NONE, true);
}else{
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
effect->light.range,
effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f,
effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f,
effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f,
(effect->light.flags & LIGHTFLAG_FOG) >> 1,
true);
alreadyProcessedFog = true;
}
}
if(!alreadyProcessedFog){
if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){
CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS,
pos, CVector(0.0f, 0.0f, 0.0f),
0.0f,
effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
CPointLights::FOG_ALWAYS, true);
}else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){
CPointLights::AddLight(CPointLights::LIGHT_FOGONLY,
pos, CVector(0.0f, 0.0f, 0.0f),
0.0f,
effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
CPointLights::FOG_NORMAL, true);
}
}
// Light shadow
if(effect->light.shadowSize != 0.0f){
if(lightOn){
CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
effect->light.shadow, &pos,
effect->light.shadowSize, 0.0f,
0.0f, -effect->light.shadowSize,
128,
effect->col.r,
effect->col.g,
effect->col.b,
15.0f, 1.0f, 40.0f, false, 0.0f);
}else if(lightFlickering){
CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
effect->light.shadow, &pos,
effect->light.shadowSize, 0.0f,
0.0f, -effect->light.shadowSize,
0, 0.0f, 0.0f, 0.0f,
15.0f, 1.0f, 40.0f, false, 0.0f);
}
}
break;
case EFFECT_SUNGLARE:
if(CWeather::SunGlare >= 0.0f){
CVector pos = GetMatrix() * effect->pos;
CVector glareDir = pos - GetPosition();
glareDir.Normalise();
CVector camDir = TheCamera.GetPosition() - pos;
float dist = camDir.Magnitude();
camDir *= 2.0f/dist;
glareDir += camDir;
glareDir.Normalise();
float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection());
if(camAngle > 0.0f){
float intens = Sqrt(camAngle) * CWeather::SunGlare;
pos += camDir;
CCoronas::RegisterCorona((uintptr)this + 33 + i,
intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f,
intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f,
intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f,
255,
pos, 0.5f*CWeather::SunGlare*Sqrt(dist), 120.0f,
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE,
CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF,
CCoronas::STREAK_OFF, 0.0f);
}
}
break;
}
}
}

105
src/renderer/Coronas.h Normal file
View File

@ -0,0 +1,105 @@
#pragma once
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
bool registeredThisFrame;
int8 flareType;
int8 reflection;
uint8 LOScheck : 1;
uint8 offScreen : 1;
uint8 firstUpdate : 1;
uint8 drawStreak : 1;
uint8 sightClear : 1;
uint8 useNearDist : 1;
uint8 renderReflection : 1;
int16 prevX[6];
int16 prevY[6];
uint8 prevRed[6];
uint8 prevGreen[6];
uint8 prevBlue[6];
bool hasValue[6];
void Update(void);
};
VALIDATE_SIZE(CRegisteredCorona, 0x68);
class CCoronas
{
static CRegisteredCorona aCoronas[NUMCORONAS];
public:
enum {
SUN_CORE = 1,
SUN_CORONA
};
enum {
TYPE_STAR,
TYPE_NORMAL,
TYPE_MOON,
TYPE_REFLECT,
TYPE_HEADLIGHT,
TYPE_HEX,
TYPE_CIRCLE,
TYPE_RING,
TYPE_STREAK,
};
enum {
FLARE_NONE,
FLARE_SUN,
FLARE_HEADLIGHTS
};
enum {
REFLECTION_OFF,
REFLECTION_ON,
};
enum {
LOSCHECK_OFF,
LOSCHECK_ON,
};
enum {
STREAK_OFF,
STREAK_ON,
};
static float LightsMult;
static float SunScreenY;
static float SunScreenX;
static int MoonSize;
static bool SunBlockedByClouds;
static int bChangeBrightnessImmediately;
static void Init(void);
static void Shutdown(void);
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,
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,
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);
};

820
src/renderer/Credits.cpp Normal file
View File

@ -0,0 +1,820 @@
#include "common.h"
#include "Timer.h"
#include "Font.h"
#include "Frontend.h"
#include "RwHelper.h"
#include "Camera.h"
#include "Text.h"
#include "Credits.h"
#include "Pad.h"
bool CCredits::bCreditsGoing;
uint32 CCredits::CreditsStartTime;
void
CCredits::Init(void)
{
Stop();
}
void
CCredits::Start(void)
{
bCreditsGoing = true;
CreditsStartTime = CTimer::GetTimeInMilliseconds();
}
void
CCredits::Stop(void)
{
bCreditsGoing = false;
}
void
CCredits::PrintCreditSpace(float space, uint32 &line)
{
line += space * 25.0f;
}
void
CCredits::PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset)
{
CPad::UpdatePads();
if (CPad::GetPad(0)->GetCrossJustDown())
bCreditsGoing = false;
else {
float start = DEFAULT_SCREEN_HEIGHT + 20.0f;
float y = lineoffset + start - scrolloffset;
if (y > 20.0f && DEFAULT_SCREEN_HEIGHT - 20.0f > y) {
CFont::SetScale(SCREEN_SCALE_X(scaleX), SCREEN_SCALE_Y(scaleY));
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_WIDTH / 2.0f, SCREEN_SCALE_Y(y), (uint16*)text);
CFont::SetColor(CRGBA(220, 220, 220, 220));
CFont::PrintString(SCREEN_WIDTH / 2.0f - SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(y - 1.0f), (uint16*)text);
}
lineoffset += scaleY*25.0f;
}
}
void
CCredits::Render(void)
{
uint32 lineoffset;
float scrolloffset;
if(!bCreditsGoing || FrontEndMenuManager.m_bMenuActive)
return;
DefinedState();
lineoffset = 0;
scrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f;
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.75f));
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetFontStyle(FONT_STANDARD);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED001"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED002"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED003"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED004"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED005"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED006"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED007"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED008"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED025"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED026"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED027"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED028"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED029"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED030"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED031"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031C"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD031D"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031E"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD024A"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED024"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED023"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD023A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD023B"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED018"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED019"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD018A"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD019A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD019B"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED020"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED021"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD022A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED022"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD022B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD022C"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED032"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED033"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD032A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED034"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED035"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED036"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED037"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD037A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD037B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD037C"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD041B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED042"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED039"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED044"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED040"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD042A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED142"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD142A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED009"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED010"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED011"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED012"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED013"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD013A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD013B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD013C"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED089"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED090"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED347"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED047"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED048"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED049"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED348"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED050"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED051"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED052"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED053"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED054"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED055"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED056"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056C"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056D"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED349"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED350"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED351"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED352"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED353"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED354"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED355"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED356"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED357"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED359"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED360"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED361"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED362"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED363"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED364"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED365"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED366"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED367"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED368"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED369"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED370"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED371"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED372"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED373"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED256"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED257"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED258"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED057"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED058"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD057A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED059"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD060A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD060B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD060C"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD002A"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED003"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD001A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD001B"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED060"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED061"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED062"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED063"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED064"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED069"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED070"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED065"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED066"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED067"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED068"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD071A"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD072A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED091"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED094"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED095"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED097"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED098"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD098A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD098B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD098C"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED099"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED096"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED273"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD092A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED092"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD092B"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED073"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED074"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED076"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED075"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED077"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED078"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED081"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED082"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED079"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED080"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED083"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED084"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084C"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD084D"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084E"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED085"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED086"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD086A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED087"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED088"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088A"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088B"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088C"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088D"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088E"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088F"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088G"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED107"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED108"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED109"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED110"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD110A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED111"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED112"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED113"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED114"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED115"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED116"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED117"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED118"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED119"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED120"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED121"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED122"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED123"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED124"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED125"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED126"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED127"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED128"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED129"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.8f));
PrintCreditText(1.1f, 0.8f, TheText.Get("CRD111A"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED130"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED131"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED132"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED133"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED134"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134A"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134B"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134C"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134D"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134E"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134F"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134G"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134H"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134I"), lineoffset, scrolloffset);
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.7f));
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED135"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD136A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD137A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED138"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED066"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD138B"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED139"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(1.1f, 0.8f, TheText.Get("CRED140"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140A"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140B"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140C"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140D"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140E"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140F"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140G"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140H"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140I"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140J"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140K"), lineoffset, scrolloffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140L"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.85f));
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED259"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED260"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED261"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED262"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED263"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED264"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED265"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED266"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED141"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD141A"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD141B"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED143"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED144"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED145"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED146"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED147"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED148"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED149"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED150"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED151"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED152"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED153"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED154"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED155"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED156"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED157"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED158"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED159"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED160"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED161"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED162"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED163"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED164"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED165"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED166"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED167"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED168"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED169"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED170"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED171"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED172"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.75f));
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED217"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED218"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRD218A"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED219"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED220"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED221"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED222"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED223"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(1.1f, 1.1f, TheText.Get("CRED224"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED227"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED228"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED229"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD229A"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD229B"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED274"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED275"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED276"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED277"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED278"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED279"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED280"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED281"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED282"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED283"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED284"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED285"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED286"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED287"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED288"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED289"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED290"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED291"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED292"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED293"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED294"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED295"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED296"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED297"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED298"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED299"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED300"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED301"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED302"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED303"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED304"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED305"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED306"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED307"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED308"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED309"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED310"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED314"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED315"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED316"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED317"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED318"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED319"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED320"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED321"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED322"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED323"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED324"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED325"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED326"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED327"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED328"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED329"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED330"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED331"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED332"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.8f));
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED333"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED334"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED335"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED336"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED337"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED338"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED339"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED340"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED341"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED342"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD344A"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED344"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED345"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRD345A"), lineoffset, scrolloffset);
PrintCreditSpace(1.0f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED346"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(1.0f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.75f));
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED267"), lineoffset, scrolloffset);
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED268"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED269"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED270"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED271"), lineoffset, scrolloffset);
PrintCreditText(0.65f, 0.65f, TheText.Get("CRED272"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditText(0.95f, 0.7f, TheText.Get("CRED230"), lineoffset, scrolloffset);
if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)
PrintCreditSpace(0.5f, lineoffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED231"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED232"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED233"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED234"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED235"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED236"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED237"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED238"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED239"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED240"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED241"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED242"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED243"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED244"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED245"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED246"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED247"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED248"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED249"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED358"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED250"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED251"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED252"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRD251A"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRD252A"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED253"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED254"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED374"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED375"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED376"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED377"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED378"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED379"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED380"), lineoffset, scrolloffset);
PrintCreditText(0.95f, 0.95f, TheText.Get("CRED381"), lineoffset, scrolloffset);
PrintCreditSpace(1.5f, lineoffset);
PrintCreditSpace(1.5f, lineoffset);
CFont::DrawFonts();
#ifdef CUTSCENE_BORDERS_SWITCH
if (CMenuManager::m_PrefsCutsceneBorders)
#endif
if(TheCamera.m_WideScreenOn)
TheCamera.DrawBordersForWideScreen();
#ifdef FIX_BUGS
if(lineoffset + DEFAULT_SCREEN_HEIGHT - scrolloffset < -10.0f)
#else
if(lineoffset + SCREEN_HEIGHT - scrolloffset < -10.0f)
#endif
{
bCreditsGoing = false;
}
}
bool CCredits::AreCreditsDone(void)
{
return !bCreditsGoing;
}

15
src/renderer/Credits.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
class CCredits
{
static bool bCreditsGoing;
static uint32 CreditsStartTime;
public:
static void Init(void);
static void Start(void);
static void Stop(void);
static bool AreCreditsDone(void);
static void Render(void);
static void PrintCreditSpace(float space, uint32 &line);
static void PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset);
};

View File

@ -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);
}

View File

@ -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);
};

113
src/renderer/Draw.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "common.h"
#include "Draw.h"
#include "Frontend.h"
#include "Camera.h"
#include "CutsceneMgr.h"
float CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO;
#ifdef ASPECT_RATIO_SCALE
float CDraw::ms_fScaledFOV = 45.0f;
#endif
float CDraw::ms_fNearClipZ;
float CDraw::ms_fFarClipZ;
float CDraw::ms_fFOV = 45.0f;
float CDraw::ms_fLODDistance;
uint8 CDraw::FadeValue;
uint8 CDraw::FadeRed;
uint8 CDraw::FadeGreen;
uint8 CDraw::FadeBlue;
#ifdef PROPER_SCALING
bool CDraw::ms_bProperScaling = true;
#endif
#ifdef FIX_RADAR
bool CDraw::ms_bFixRadar = true;
#endif
#ifdef FIX_SPRITES
bool CDraw::ms_bFixSprites = true;
#endif
#ifdef ASPECT_RATIO_SCALE
float
FindAspectRatio(void)
{
switch (FrontEndMenuManager.m_PrefsUseWideScreen) {
case AR_AUTO:
return SCREEN_WIDTH / SCREEN_HEIGHT;
default:
case AR_4_3:
return 4.0f / 3.0f;
case AR_5_4:
return 5.0f / 4.0f;
case AR_16_10:
return 16.0f / 10.0f;
case AR_16_9:
return 16.0f / 9.0f;
case AR_21_9:
return 21.0f / 9.0f;
};
}
#endif
float
CDraw::CalculateAspectRatio(void)
{
#ifdef ASPECT_RATIO_SCALE
if (TheCamera.m_WideScreenOn)
CDraw::ms_fAspectRatio = (5.f / 3.f) * FindAspectRatio() / (16.f / 9.f); // It's used on theatrical showings according to Wiki
else
CDraw::ms_fAspectRatio = FindAspectRatio();
#else
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
CDraw::ms_fAspectRatio = 16.f / 9.f;
} else if (TheCamera.m_WideScreenOn) {
CDraw::ms_fAspectRatio = 5.f/4.f;
} else {
CDraw::ms_fAspectRatio = 4.f/3.f;
}
#endif
return CDraw::ms_fAspectRatio;
}
#ifdef ASPECT_RATIO_SCALE
// convert a 4:3 hFOV to vFOV,
// then convert that vFOV to hFOV for our aspect ratio,
// i.e. HOR+
float
CDraw::ConvertFOV(float hfov)
{
// => tan(hFOV/2) = tan(vFOV/2)*aspectRatio
// => tan(vFOV/2) = tan(hFOV/2)/aspectRatio
float ar1 = DEFAULT_ASPECT_RATIO;
float ar2 = GetAspectRatio();
hfov = DEGTORAD(hfov);
float vfov = Atan(tan(hfov/2) / ar1) *2;
hfov = Atan(tan(vfov/2) * ar2) *2;
return RADTODEG(hfov);
}
#endif
void
CDraw::SetFOV(float fov)
{
#ifdef ASPECT_RATIO_SCALE
if (!CCutsceneMgr::IsRunning())
ms_fScaledFOV = ConvertFOV(fov);
else
ms_fScaledFOV = fov;
#endif
ms_fFOV = fov;
}
#ifdef PROPER_SCALING
float CDraw::ScaleY(float y)
{
return ms_bProperScaling ? y : y * ((float)DEFAULT_SCREEN_HEIGHT/SCREEN_HEIGHT_NTSC);
}
#endif

70
src/renderer/Draw.h Normal file
View File

@ -0,0 +1,70 @@
#pragma once
enum eAspectRatio
{
// Make sure these work the same as FrontEndMenuManager.m_PrefsUseWideScreen
// without widescreen support
AR_AUTO,
AR_4_3,
AR_5_4,
AR_16_10,
AR_16_9,
AR_21_9,
AR_MAX,
};
class CDraw
{
private:
static float ms_fNearClipZ;
static float ms_fFarClipZ;
static float ms_fFOV;
// we use this variable to scale a lot of 2D elements
// so better cache it
static float ms_fAspectRatio;
#ifdef ASPECT_RATIO_SCALE
// similar thing for 3D rendering
static float ms_fScaledFOV;
#endif
public:
static float ms_fLODDistance; // set but unused?
static uint8 FadeValue;
static uint8 FadeRed;
static uint8 FadeGreen;
static uint8 FadeBlue;
#ifdef PROPER_SCALING
static bool ms_bProperScaling;
#endif
#ifdef FIX_RADAR
static bool ms_bFixRadar;
#endif
#ifdef FIX_SPRITES
static bool ms_bFixSprites;
#endif
static void SetNearClipZ(float nearclip) { ms_fNearClipZ = nearclip; }
static float GetNearClipZ(void) { return ms_fNearClipZ; }
static void SetFarClipZ(float farclip) { ms_fFarClipZ = farclip; }
static float GetFarClipZ(void) { return ms_fFarClipZ; }
static void SetFOV(float fov);
static float GetFOV(void) { return ms_fFOV; }
#ifdef ASPECT_RATIO_SCALE
static float GetScaledFOV(void) { return ms_fScaledFOV; }
#else
static float GetScaledFOV(void) { return ms_fFOV; }
#endif
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; }
#ifdef PROPER_SCALING
static float ScaleY(float y);
#endif
};

1365
src/renderer/Fluff.cpp Normal file

File diff suppressed because it is too large Load Diff

205
src/renderer/Fluff.h Normal file
View File

@ -0,0 +1,205 @@
#pragma once
#include "common.h"
#include "Vector.h"
#include "Object.h"
#include "Plane.h"
enum {
SCRIPT_PATH_DISABLED = 0,
SCRIPT_PATH_INITIALIZED,
SCRIPT_PATH_ACTIVE
};
class CScriptPath
{
public:
int32 m_numNodes;
CPlaneNode *m_pNode;
float m_fTotalLength;
float m_fSpeed;
float m_fPosition;
float m_fObjectLength;
int32 m_state;
CObject *m_pObjects[6];
void Clear(void);
void Update(void);
void InitialiseOne(int32 numNodes, float length);
void FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ);
void SetObjectToControl(CObject *pObj);
};
class CScriptPaths
{
public:
static CScriptPath aArray[3];
static void Init(void);
static void Shutdown(void);
static void Update(void);
static bool IsOneActive(void);
static void Save(uint8 *buf, uint32 *size);
static void Load(uint8 *buf, uint32 size);
static void Save_ForReplay();
static void Load_ForReplay();
};
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);
bool IsActive() const { return m_bIsActive; };
const CVector& GetPosition() const { return m_midPoint; };
};
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);
static const CEscalator& GetEscalator(int ind) { return aEscalators[ind]; };
};
class CMovingThing
{
public:
CMovingThing *m_pNext;
CMovingThing *m_pPrev;
int16 m_nType;
int16 m_farAway;
CVector m_vecPosn;
CEntity* m_pEntity;
void Update();
void AddToList(CMovingThing *pThing);
void RemoveFromList();
int16 SizeList();
};
#define NUMMOVINGTHINGS 48
class CMovingThings
{
public:
static CMovingThing StartCloseList;
static CMovingThing EndCloseList;
static int16 Num;
static CMovingThing aMovingThings[NUMMOVINGTHINGS];
static void Init();
static void Shutdown();
static void Update();
static void Render();
static void PossiblyAddThisEntity(CEntity *pEnt);
static void RegisterOne(CEntity *pEnt, uint16 nType);
};
class CScrollBar
{
private:
uint8 m_Counter;
const char* m_pMessage;
CVector m_Position;
uint32 m_MessageCurrentChar;
uint32 m_MessageLength;
CVector m_Size;
float m_fIntensity;
uint8 m_MessageBar[40];
uint8 m_Type;
bool m_bVisible;
uint8 m_uRed;
uint8 m_uGreen;
uint8 m_uBlue;
float m_fScale;
public:
static int TonightsEvent;
public:
void SetVisibility(bool visible) { m_bVisible = visible; }
bool IsVisible() { return m_bVisible; }
void Init(CVector pos1, CVector pos2, uint8 type, uint8 red, uint8 green, uint8 blue, float scale);
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);
};

1612
src/renderer/Font.cpp Normal file

File diff suppressed because it is too large Load Diff

226
src/renderer/Font.h Normal file
View File

@ -0,0 +1,226 @@
#pragma once
#include "Sprite2d.h"
void AsciiToUnicode(const char *src, wchar *dst);
void UnicodeStrcpy(wchar *dst, const wchar *src);
void UnicodeStrcat(wchar *dst, wchar *append);
int UnicodeStrlen(const wchar *str);
void UnicodeMakeUpperCase(wchar *dst, const wchar *src);
struct CFontDetails
{
CRGBA color;
float scaleX;
float scaleY;
float slant;
float slantRefX;
float slantRefY;
bool8 justify;
bool8 centre;
bool8 rightJustify;
bool8 background;
bool8 backgroundOnlyText;
bool8 proportional;
bool8 bIsShadow;
bool8 bFlash;
bool8 bBold;
float alphaFade;
CRGBA backgroundColor;
float wrapX;
float centreSize;
float rightJustifyWrap;
int16 style;
bool8 bFontHalfTexture;
uint32 bank;
int16 dropShadowPosition;
CRGBA dropColor;
bool8 bFlashState;
int nFlashTimer;
bool8 anonymous_23;
uint32 anonymous_25;
CRGBA outlineColor;
int bOutlineOn;
int line;
};
struct CFontRenderState
{
uint32 anonymous_0;
float fTextPosX;
float fTextPosY;
float scaleX;
float scaleY;
CRGBA color;
float fExtraSpace;
float slant;
float slantRefX;
float slantRefY;
bool8 bIsShadow;
bool8 bFontHalfTexture;
bool8 proportional;
bool8 anonymous_14;
int16 style;
int bOutlineOn;
int line;
bool8 rightJustify;
};
class CSprite2d;
enum {
FONT_BANK,
FONT_STANDARD,
FONT_HEADING,
MAX_FONTS
};
enum {
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT,
};
#ifdef MORE_LANGUAGES
enum
{
FONT_LANGSET_EFIGS,
FONT_LANGSET_RUSSIAN,
FONT_LANGSET_POLISH,
FONT_LANGSET_JAPANESE,
LANGSET_MAX
};
#define FONT_LOCALE(style) (CFont::IsJapanese() ? FONT_JAPANESE : style)
#else
#define FONT_LOCALE(style) (style)
#endif
#ifdef BUTTON_ICONS
enum
{
BUTTON_NONE = -1,
BUTTON_UP,
BUTTON_DOWN,
BUTTON_LEFT,
BUTTON_RIGHT,
BUTTON_CROSS,
BUTTON_CIRCLE,
BUTTON_SQUARE,
BUTTON_TRIANGLE,
BUTTON_L1,
BUTTON_L2,
BUTTON_L3,
BUTTON_R1,
BUTTON_R2,
BUTTON_R3,
BUTTON_RSTICK_UP,
BUTTON_RSTICK_DOWN,
BUTTON_RSTICK_LEFT,
BUTTON_RSTICK_RIGHT,
MAX_BUTTON_ICONS
};
#endif // BUTTON_ICONS
class CFont
{
#ifdef MORE_LANGUAGES
static int16 Size[LANGSET_MAX][MAX_FONTS][210];
static uint8 LanguageSet;
static int32 Slot;
#else
static int16 Size[MAX_FONTS][419];
#endif
static bool16 NewLine;
public:
static CSprite2d Sprite[MAX_FONTS];
static CFontDetails Details;
static CFontRenderState RenderState;
#ifdef BUTTON_ICONS
static int32 ButtonsSlot;
static CSprite2d ButtonSprite[MAX_BUTTON_ICONS];
static int PS2Symbol;
static void LoadButtons(const char *txdPath);
static void DrawButton(float x, float y);
#endif // BUTTON_ICONS
static void Initialise(void);
static void Shutdown(void);
static void InitPerFrame(void);
static void PrintChar(float x, float y, wchar c);
static void PrintString(float x, float y, wchar *s);
#ifdef XBOX_SUBTITLES
static void PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor);
#endif
static int GetNumberLines(float xstart, float ystart, wchar *s);
static void GetTextRect(CRect *rect, float xstart, float ystart, wchar *s);
//#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, uint32, wchar *start, wchar *end, float spwidth);
//#endif
static void PrintStringFromBottom(float x, float y, wchar *str);
static float GetCharacterWidth(wchar c, bool forceProportional = false);
static float GetCharacterSize(wchar c);
static float GetStringWidth(wchar *s, bool spaces = false);
#ifdef MORE_LANGUAGES
static float GetStringWidth_Jap(wchar* s);
#endif
static uint16 *GetNextSpace(wchar *s);
//#ifdef MORE_LANGUAGES
// static uint16 *ParseToken(wchar *s, bool japShit = false);
//#else
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 void SetScale(float x, float y);
static void SetSlantRefPoint(float x, float y);
static void SetSlant(float s);
static void SetJustifyOn(void);
static void SetJustifyOff(void);
static void SetRightJustifyOn(void);
static void SetRightJustifyOff(void);
static void SetCentreOn(void);
static void SetCentreOff(void);
static void SetWrapx(float x);
static void SetCentreSize(float s);
static void SetBackgroundOn(void);
static void SetBackgroundOff(void);
static void SetBackGroundOnlyTextOn(void);
static void SetBackGroundOnlyTextOff(void);
static void SetFlashOff(void);
static void SetPropOn(void);
static void SetPropOff(void);
static void SetFontStyle(int16 style);
static void SetRightJustifyWrap(float wrap);
static void SetAlphaFade(float fade);
static void SetDropShadowPosition(int16 pos);
static void SetBackgroundColor(CRGBA col);
static void SetColor(CRGBA col);
static void SetDropColor(CRGBA col);
static void SetOutlineColor(CRGBA col);
static void SetOutlineOn(int on);
static void SetNewLineAdd(int line);
static int16 FindNewCharacter(int16 c);
static void FilterOutTokensFromString(wchar*);
static bool16 CheckNewLine(wchar *s);
#ifdef MORE_LANGUAGES
static void ReloadFonts(uint8 set);
// japanese stuff
static bool IsAnsiCharacter(wchar* s);
static bool IsJapanesePunctuation(wchar* str);
static bool IsJapanese() { return LanguageSet == FONT_LANGSET_JAPANESE; }
static bool IsJapaneseFont() { return IsJapanese() && (Details.style == FONT_JAPANESE); }
#endif
};

1027
src/renderer/Glass.cpp Normal file

File diff suppressed because it is too large Load Diff

59
src/renderer/Glass.h Normal file
View File

@ -0,0 +1,59 @@
#pragma once
class CEntity;
class CVehicle;
class CPtrList;
class CFallingGlassPane : public CMatrix
{
public:
CVector m_vecMoveSpeed;
CVector m_vecTurn;
uint32 m_nTimer;
float m_fGroundZ;
float m_fStep;
uint8 m_nTriIndex;
bool m_bActive;
bool m_bShattered;
bool m_bCarGlass;
CFallingGlassPane() { }
~CFallingGlassPane() { }
void Update(void);
void Render(void);
};
VALIDATE_SIZE(CFallingGlassPane, 0x70);
enum
{
NUM_GLASSTRIANGLES = 5,
};
class CGlass
{
static uint32 NumGlassEntities;
static CEntity *apEntitiesToBeRendered[NUM_GLASSENTITIES];
static CFallingGlassPane aGlassPanes[NUM_GLASSPANES];
public:
static void Init(void);
static void Update(void);
static void Render(void);
static CFallingGlassPane *FindFreePane(void);
static void GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center, float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass);
static void AskForObjectToBeRenderedInGlass(CEntity *entity);
static void RenderEntityInGlass(CEntity *entity);
static int32 CalcAlphaWithNormal(CVector *normal);
static void RenderHiLightPolys(void);
static void RenderShatteredPolys(void);
static void RenderReflectionPolys(void);
static void WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion);
static void WindowRespondsToSoftCollision(CEntity *entity, float amount);
static void WasGlassHitByBullet(CEntity *entity, CVector point);
static void WindowRespondsToExplosion(CEntity *entity, CVector point);
static void CarWindscreenShatters(CVehicle *vehicle, bool unk);
static bool HasGlassBeenShatteredAtCoors(float x, float y, float z);
static void FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z);
static void BreakGlassPhysically(CVector pos, float radius);
};

2265
src/renderer/Hud.cpp Normal file

File diff suppressed because it is too large Load Diff

154
src/renderer/Hud.h Normal file
View File

@ -0,0 +1,154 @@
#pragma once
#include "Sprite2d.h"
#define HELP_MSG_LENGTH 256
#define HUD_TEXT_SCALE_X 0.7f
#define HUD_TEXT_SCALE_Y 1.25f
enum eItems
{
ITEM_NONE = -1,
ITEM_ARMOUR = 3,
ITEM_HEALTH = 4,
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,
HUD_SITEROCKET = 41,
HUD_RADARDISC = 50,
HUD_BAR_INSIDE1DARK = 57,
HUD_BAR_INSIDE2DARK,
HUD_HUDNUMBERS,
HUD_BAR_INSIDE1,
HUD_BAR_INSIDE2,
HUD_BAR_OUTLINE,
HUD_SITESNIPER,
HUD_SITEM16,
HUD_SITELASER,
HUD_LASERDOT,
HUD_VIEWFINDER,
HUD_BLEEDER,
NUM_HUD_SPRITES = 70,
};
extern float BigMessageInUse[6];
class CHud
{
public:
static CSprite2d Sprites[NUM_HUD_SPRITES];
static wchar m_HelpMessage[HELP_MSG_LENGTH];
static wchar m_LastHelpMessage[HELP_MSG_LENGTH];
static uint32 m_HelpMessageState;
static uint32 m_HelpMessageTimer;
static int32 m_HelpMessageFadeTimer;
static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH];
static float m_HelpMessageDisplayTime;
static bool m_HelpMessageDisplayForever;
static bool m_HelpMessageQuick;
static uint32 m_ZoneState;
static int32 m_ZoneFadeTimer;
static uint32 m_ZoneNameTimer;
static wchar *m_pZoneName;
static wchar *m_pLastZoneName;
static wchar *m_ZoneToPrint;
static wchar *m_VehicleName;
static wchar *m_pLastVehicleName;
static wchar *m_pVehicleNameToPrint;
static uint32 m_VehicleState;
static int32 m_VehicleFadeTimer;
static uint32 m_VehicleNameTimer;
static wchar m_Message[256];
static wchar m_PagerMessage[256];
static bool m_Wants_To_Draw_Hud;
static bool m_Wants_To_Draw_3dMarkers;
static wchar m_BigMessage[6][128];
static int16 m_ItemToFlash;
static bool m_HideRadar;
static int32 m_ClockState;
// These aren't really in CHud
static float BigMessageAlpha[6];
static float BigMessageX[6];
static float OddJob2OffTimer;
static bool CounterOnLastFrame[NUMONSCREENCOUNTERS];
static float OddJob2XOffset;
static uint16 CounterFlashTimer[NUMONSCREENCOUNTERS];
static uint16 OddJob2Timer;
static bool TimerOnLastFrame;
static int16 OddJob2On;
static uint16 TimerFlashTimer;
static int16 PagerSoundPlayed;
static int32 SpriteBrightness;
static float PagerXOffset;
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;
static uint32 m_LastWeapon;
static uint32 m_LastTimeEnergyLost;
static wchar* gLastPrintForeverString;
static uint8 m_HudAlpha;
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, uint16 style);
static void SetHelpMessage(wchar *message, bool quick, bool displayForever = false);
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);
static void ResetWastedText(void);
static void DrawHealthBar(int16 value);
static void DrawArmourBar(int16 value);
static void DrawTimeAndCashNumbers(char *str, float x, float y, bool secondSet);
static void DrawCash();
static void DrawTime();
};

View File

@ -0,0 +1,9 @@
#include "common.h"
#include "Instance.h"
void
CInstance::Shutdown()
{
GetMatrix().Detach();
}

14
src/renderer/Instance.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include "Placeable.h"
// unused
class CInstance : public CPlaceable
{
public:
int m_modelIndex;
public:
~CInstance() { }
void Shutdown();
};

74
src/renderer/Lines.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "common.h"
#include "main.h"
#include "Lines.h"
// This is super inefficient, why split the line into segments at all?
void
CLines::RenderLineWithClipping(float x1, float y1, float z1, float x2, float y2, float z2, uint32 c1, uint32 c2)
{
static RwIm3DVertex v[2];
#ifdef THIS_IS_STUPID
int i;
float f1, f2;
float len = sqrt(sq(x1-x2) + sq(y1-y2) + sq(z1-z2));
int numsegs = len/1.5f + 1.0f;
RwRGBA col1;
col1.red = c1>>24;
col1.green = c1>>16;
col1.blue = c1>>8;
col1.alpha = c1;
RwRGBA col2;
col2.red = c2>>24;
col2.green = c2>>16;
col2.blue = c2>>8;
col2.alpha = c2;
float dx = x2 - x1;
float dy = y2 - y1;
float dz = z2 - z1;
for(i = 0; i < numsegs; i++){
f1 = (float)i/numsegs;
f2 = (float)(i+1)/numsegs;
RwIm3DVertexSetRGBA(&v[0], (int)(col1.red + (col2.red-col1.red)*f1),
(int)(col1.green + (col2.green-col1.green)*f1),
(int)(col1.blue + (col2.blue-col1.blue)*f1),
(int)(col1.alpha + (col2.alpha-col1.alpha)*f1));
RwIm3DVertexSetRGBA(&v[1], (int)(col1.red + (col2.red-col1.red)*f2),
(int)(col1.green + (col2.green-col1.green)*f2),
(int)(col1.blue + (col2.blue-col1.blue)*f2),
(int)(col1.alpha + (col2.alpha-col1.alpha)*f2));
RwIm3DVertexSetPos(&v[0], x1 + dx*f1, y1 + dy*f1, z1 + dz*f1);
RwIm3DVertexSetPos(&v[1], x1 + dx*f2, y1 + dy*f2, z1 + dz*f2);
LittleTest();
if(RwIm3DTransform(v, 2, nil, 0)){
RwIm3DRenderLine(0, 1);
RwIm3DEnd();
}
}
#else
RwRGBA col1;
col1.red = c1>>24;
col1.green = c1>>16;
col1.blue = c1>>8;
col1.alpha = c1;
RwRGBA col2;
col2.red = c2>>24;
col2.green = c2>>16;
col2.blue = c2>>8;
col2.alpha = c2;
RwIm3DVertexSetRGBA(&v[0], col1.red, col1.green, col1.blue, col1.alpha);
RwIm3DVertexSetRGBA(&v[1], col2.red, col2.green, col2.blue, col2.alpha);
RwIm3DVertexSetPos(&v[0], x1, y1, z1);
RwIm3DVertexSetPos(&v[1], x2, y2, z2);
LittleTest();
if(RwIm3DTransform(v, 2, nil, 0)){
RwIm3DRenderLine(0, 1);
RwIm3DEnd();
}
#endif
}

7
src/renderer/Lines.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
class CLines
{
public:
static void RenderLineWithClipping(float x1, float y1, float z1, float x2, float y2, float z2, uint32 c1, uint32 c2);
};

804
src/renderer/MBlur.cpp Normal file
View File

@ -0,0 +1,804 @@
#ifndef LIBRW
#define WITHD3D
#endif
#include "common.h"
#ifndef LIBRW
#include <d3d8caps.h>
#endif
#include "main.h"
#include "General.h"
#include "RwHelper.h"
#include "Camera.h"
#include "Timecycle.h"
#include "Particle.h"
#include "Timer.h"
#include "Hud.h"
#include "Frontend.h"
#include "MBlur.h"
#include "postfx.h"
// Originally taken from RW example 'mblur'
RwRaster *CMBlur::pFrontBuffer;
bool CMBlur::ms_bJustInitialised;
bool CMBlur::ms_bScaledBlur;
bool CMBlur::BlurOn;
float CMBlur::Drunkness;
int32 CMBlur::pBufVertCount;
static RwIm2DVertex Vertex[4];
static RwIm2DVertex Vertex2[4];
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
#ifndef LIBRW
extern "C" D3DCAPS8 _RwD3D8DeviceCaps;
#endif
RwBool
CMBlur::MotionBlurOpen(RwCamera *cam)
{
#ifdef EXTENDED_COLOURFILTER
CPostFX::Open(cam);
return TRUE;
#else
#ifdef GTA_PS2
RwRect rect = {0, 0, 0, 0};
if (pFrontBuffer)
return TRUE;
BlurOn = true;
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
pFrontBuffer = RwRasterCreate(0, 0, 0, rwRASTERDONTALLOCATE|rwRASTERTYPECAMERATEXTURE);
if (!pFrontBuffer)
{
printf("Error creating raster\n");
return FALSE;
}
RwRaster *raster = RwRasterSubRaster(pFrontBuffer, RwCameraGetRaster(cam), &rect);
if (!raster)
{
RwRasterDestroy(pFrontBuffer);
pFrontBuffer = NULL;
printf("Error subrastering\n");
return FALSE;
}
CreateImmediateModeData(cam, &rect);
#else
RwRect rect = { 0, 0, 0, 0 };
if(pFrontBuffer)
MotionBlurClose();
#ifndef LIBRW
extern void _GetVideoMemInfo(LPDWORD total, LPDWORD avaible);
DWORD total, avaible;
_GetVideoMemInfo(&total, &avaible);
debug("Available video memory %d\n", avaible);
#endif
if(BlurOn)
{
uint32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);
uint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);
uint32 depth = RwRasterGetDepth(RwCameraGetRaster(cam));
#ifndef LIBRW
extern DWORD _dwMemTotalVideo;
if ( _RwD3D8DeviceCaps.MaxTextureWidth >= width && _RwD3D8DeviceCaps.MaxTextureHeight >= height )
{
total = _dwMemTotalVideo - 3 *
( RwRasterGetDepth(RwCameraGetRaster(cam))
* RwRasterGetHeight(RwCameraGetRaster(cam))
* RwRasterGetWidth(RwCameraGetRaster(cam)) / 8 );
BlurOn = total >= height*width*(depth/8) + (12*1024*1024) /*12 MB*/;
}
else
BlurOn = false;
#endif
if ( BlurOn )
{
ms_bScaledBlur = false;
rect.w = width;
rect.h = height;
pFrontBuffer = RwRasterCreate(rect.w, rect.h, depth, rwRASTERTYPECAMERATEXTURE);
if ( !pFrontBuffer )
{
debug("MBlurOpen can't create raster.");
BlurOn = false;
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
}
else
ms_bJustInitialised = true;
}
else
{
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
}
#ifndef LIBRW
_GetVideoMemInfo(&total, &avaible);
debug("Available video memory %d\n", avaible);
#endif
CreateImmediateModeData(cam, &rect);
}
else
{
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
CreateImmediateModeData(cam, &rect);
}
return TRUE;
#endif
#endif
}
RwBool
CMBlur::MotionBlurClose(void)
{
#ifdef EXTENDED_COLOURFILTER
CPostFX::Close();
#else
if(pFrontBuffer){
RwRasterDestroy(pFrontBuffer);
pFrontBuffer = nil;
return TRUE;
}
#endif
return FALSE;
}
void
CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect)
{
float zero, xmax, ymax;
if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){
zero = HALFPX;
xmax = rect->w + HALFPX;
ymax = rect->h + HALFPX;
}else{
zero = -HALFPX;
xmax = rect->w - HALFPX;
ymax = rect->h - HALFPX;
}
RwIm2DVertexSetScreenX(&Vertex[0], zero);
RwIm2DVertexSetScreenY(&Vertex[0], zero);
RwIm2DVertexSetScreenZ(&Vertex[0], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[0], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[0], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, 255);
RwIm2DVertexSetScreenX(&Vertex[1], zero);
RwIm2DVertexSetScreenY(&Vertex[1], ymax);
RwIm2DVertexSetScreenZ(&Vertex[1], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[1], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[1], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, 255);
RwIm2DVertexSetScreenX(&Vertex[2], xmax);
RwIm2DVertexSetScreenY(&Vertex[2], ymax);
RwIm2DVertexSetScreenZ(&Vertex[2], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[2], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[2], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, 255);
RwIm2DVertexSetScreenX(&Vertex[3], xmax);
RwIm2DVertexSetScreenY(&Vertex[3], zero);
RwIm2DVertexSetScreenZ(&Vertex[3], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[3], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[3], 1.0f/RwCameraGetNearClipPlane(cam));
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
CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect, RwIm2DVertex *verts, RwRGBA color, float u1Off, float v1Off, float u2Off, float v2Off, float z, int fullTexture)
{
float x1 = rect->x;
float y1 = rect->y;
float x2 = rect->w;
float y2 = rect->h;
float u1, v1, u2, v2;
if(fullTexture){
u1 = 0.0f;
v1 = 0.0f;
u2 = 1.0f;
v2 = 1.0f;
}else{
if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){
x1 += HALFPX;
y1 += HALFPX;
x2 += HALFPX;
y2 += HALFPX;
}else{
x1 -= HALFPX;
y1 -= HALFPX;
x2 -= HALFPX;
y2 -= HALFPX;
}
int32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);
int32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);
u1 = x1/width + u1Off;
v1 = y1/height + v1Off;
u2 = x2/width + u2Off;
v2 = y2/height + v2Off;
u1 = Clamp(u1, 0.0f, 1.0f);
v1 = Clamp(v1, 0.0f, 1.0f);
u2 = Clamp(u2, 0.0f, 1.0f);
v2 = Clamp(v2, 0.0f, 1.0f);
}
float recipz = 1.0f/z;
// TODO: CameraZ is wrong, what should we do?
RwIm2DVertexSetScreenX(&verts[0], x1);
RwIm2DVertexSetScreenY(&verts[0], y1);
RwIm2DVertexSetScreenZ(&verts[0], z);
RwIm2DVertexSetCameraZ(&verts[0], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&verts[0], recipz);
RwIm2DVertexSetU(&verts[0], u1, recipz);
RwIm2DVertexSetV(&verts[0], v1, recipz);
RwIm2DVertexSetIntRGBA(&verts[0], color.red, color.green, color.blue, color.alpha);
RwIm2DVertexSetScreenX(&verts[1], x1);
RwIm2DVertexSetScreenY(&verts[1], y2);
RwIm2DVertexSetScreenZ(&verts[1], z);
RwIm2DVertexSetCameraZ(&verts[1], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&verts[1], recipz);
RwIm2DVertexSetU(&verts[1], u1, recipz);
RwIm2DVertexSetV(&verts[1], v2, recipz);
RwIm2DVertexSetIntRGBA(&verts[1], color.red, color.green, color.blue, color.alpha);
RwIm2DVertexSetScreenX(&verts[2], x2);
RwIm2DVertexSetScreenY(&verts[2], y2);
RwIm2DVertexSetScreenZ(&verts[2], z);
RwIm2DVertexSetCameraZ(&verts[2], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&verts[2], recipz);
RwIm2DVertexSetU(&verts[2], u2, recipz);
RwIm2DVertexSetV(&verts[2], v2, recipz);
RwIm2DVertexSetIntRGBA(&verts[2], color.red, color.green, color.blue, color.alpha);
RwIm2DVertexSetScreenX(&verts[3], x2);
RwIm2DVertexSetScreenY(&verts[3], y1);
RwIm2DVertexSetScreenZ(&verts[3], z);
RwIm2DVertexSetCameraZ(&verts[3], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&verts[3], recipz);
RwIm2DVertexSetU(&verts[3], u2, recipz);
RwIm2DVertexSetV(&verts[3], v1, recipz);
RwIm2DVertexSetIntRGBA(&verts[3], color.red, color.green, color.blue, color.alpha);
}
void
CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)
{
#ifdef EXTENDED_COLOURFILTER
CPostFX::Render(cam, red, green, blue, blur, type, bluralpha);
#else
PUSH_RENDERGROUP("CMBlur::MotionBlurRender");
RwRGBA color = { (RwUInt8)red, (RwUInt8)green, (RwUInt8)blue, (RwUInt8)blur };
#ifdef GTA_PS2
if( pFrontBuffer )
OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
#else
if(ms_bJustInitialised)
ms_bJustInitialised = false;
else
OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
if(BlurOn){
RwRasterPushContext(pFrontBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext();
}
#endif
POP_RENDERGROUP();
#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)
{
int r, g, b, a;
r = color.red;
g = color.green;
b = color.blue;
a = color.alpha;
DefinedState();
switch(type)
{
case MOTION_BLUR_SECURITY_CAM:
r = 0;
g = 255;
b = 0;
a = 128;
break;
case MOTION_BLUR_INTRO:
r = 100;
g = 220;
b = 230;
a = 158;
break;
case MOTION_BLUR_INTRO2:
r = 80;
g = 255;
b = 230;
a = 138;
break;
case MOTION_BLUR_INTRO3:
r = 255;
g = 60;
b = 60;
a = 200;
break;
case MOTION_BLUR_INTRO4:
r = 255;
g = 180;
b = 180;
a = 128;
break;
}
if(!BlurOn){
// 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);
}
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
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);
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);
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);
}
}
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);
}
if(type != MOTION_BLUR_SNIPER)
OverlayRenderFx(cam, pFrontBuffer);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
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);
}
#define NUM_RENDER_FX 64
static RwRect fxRect[NUM_RENDER_FX];
static FxType fxType[NUM_RENDER_FX];
static float fxZ[NUM_RENDER_FX];
bool
CMBlur::PosInside(RwRect *rect, float x1, float y1, float x2, float y2)
{
if((rect->x < x1 - 10.0f || rect->x > x2 + 10.0f || rect->y < y1 - 10.0f || rect->y > y2 + 10.0f) &&
(rect->w < x1 - 10.0f || rect->w > x2 + 10.0f || rect->h < y1 - 10.0f || rect->h > y2 + 10.0f) &&
(rect->x < x1 - 10.0f || rect->x > x2 + 10.0f || rect->h < y1 - 10.0f || rect->h > y2 + 10.0f) &&
(rect->w < x1 - 10.0f || rect->w > x2 + 10.0f || rect->y < y1 - 10.0f || rect->y > y2 + 10.0f))
return false;
return true;
}
bool
CMBlur::AddRenderFx(RwCamera *cam, RwRect *rect, float z, FxType type)
{
if(pBufVertCount >= NUM_RENDER_FX)
return false;
rect->x = Max(rect->x, 0);
rect->y = Max(rect->y, 0);
rect->w = Min(rect->w, SCREEN_WIDTH);
rect->h = Min(rect->h, SCREEN_HEIGHT);
if(rect->x >= rect->w || rect->y >= rect->h)
return false;
switch(type){
case FXTYPE_WATER1:
case FXTYPE_WATER2:
case FXTYPE_BLOOD1:
case FXTYPE_BLOOD2:
case FXTYPE_HEATHAZE: // code seems to be duplicated for this case
for(int i = 0; i < pBufVertCount; i++)
if(fxType[i] == type && PosInside(rect, fxRect[i].x-10.0f, fxRect[i].y-10.0f, fxRect[i].w+10.0f, fxRect[i].h+10.0f))
return false;
// TODO: fix aspect ratio scaling
// radar
if(PosInside(rect, 40.0f, SCREEN_SCALE_FROM_BOTTOM(116.0f), 40.0f + SCREEN_SCALE_X(94.0f), SCREEN_SCALE_FROM_BOTTOM(116.0f - 76.0f)))
return false;
// HUD
if(PosInside(rect, 400.0f, 0.0f, SCREEN_WIDTH, 90.0f))
return false;
// vehicle name
if(CHud::m_VehicleState != 0 && PosInside(rect, SCREEN_WIDTH/2, 350.0f, SCREEN_WIDTH, SCREEN_HEIGHT))
return false;
// zone name
if(CHud::m_ZoneState != 0 && PosInside(rect, SCREEN_WIDTH/2, 350.0f, SCREEN_WIDTH, SCREEN_HEIGHT))
return false;
break;
}
fxRect[pBufVertCount] = *rect;
fxZ[pBufVertCount] = z;
fxType[pBufVertCount] = type;
pBufVertCount++;
return true;
}
void
CMBlur::OverlayRenderFx(RwCamera *cam, RwRaster *frontBuf)
{
//TODO(LCS)
#if 0
bool drawWaterDrops = false;
RwIm2DVertex verts[4];
int red = (0.75f*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed())*0.55f * 255;
int green = (0.75f*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen())*0.55f * 255;
int blue = (0.75f*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue())*0.55f * 255;
red = Clamp(red, 0, 255);
green = Clamp(green, 0, 255);
blue = Clamp(blue, 0, 255);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
#ifdef LIBRW
rw::SetRenderState(rw::STENCILENABLE, TRUE);
#else
RwD3D8SetRenderState(D3DRS_STENCILENABLE, TRUE);
#endif
for(int i = 0; i < pBufVertCount; i++)
switch(fxType[i]){
case FXTYPE_WATER1:
case FXTYPE_WATER2:
case FXTYPE_BLOOD1:
case FXTYPE_BLOOD2: {
drawWaterDrops = true;
int32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);
int32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);
float u1Off = (fxRect[i].w - fxRect[i].x)/width;
float u2Off = u1Off - (fxRect[i].w - fxRect[i].x + 0.5f)*0.66f/width;
float halfHeight = (fxRect[i].h - fxRect[i].y + 0.5f)*0.25f/height;
if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){
if(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2)
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 128), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
else
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(32, 32, 32, 225), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
}else{
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(32, 32, 32, 225), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
}
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpDotRaster);
#ifdef LIBRW
rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS);
rw::SetRenderState(rw::STENCILFUNCTIONREF, 1);
rw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFFFFFFFF);
rw::SetRenderState(rw::STENCILFUNCTIONWRITEMASK, 0xFFFFFFFF);
rw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP);
rw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP);
rw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE);
#else
RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
RwD3D8SetRenderState(D3DRS_STENCILREF, 1);
RwD3D8SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
RwD3D8SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
RwD3D8SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
RwD3D8SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
#endif
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
if(RwRasterGetDepth(RwCameraGetRaster(cam)) != 16){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, frontBuf);
#ifdef LIBRW
rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILEQUAL);
rw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP);
#else
RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
#endif
if(BlurOn){
if(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2)
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 255), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);
else
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(225, 225, 225, 160), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDDESTALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA);
}else{
if(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2)
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 128), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);
else
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(128, 128, 128, 32), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
break;
}
case FXTYPE_SPLASH1:
case FXTYPE_SPLASH2:
case FXTYPE_SPLASH3:
drawWaterDrops = true;
break;
case FXTYPE_HEATHAZE:
if(TheCamera.GetScreenFadeStatus() == FADE_0 && frontBuf){
int alpha = FrontEndMenuManager.m_PrefsBrightness > 255 ?
FrontEndMenuManager.m_PrefsBrightness - 90 :
FrontEndMenuManager.m_PrefsBrightness - 130;
alpha = Clamp(alpha, 16, 200)/2;
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(0, 0, 0, alpha), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpHeatHazeRaster);
#ifdef LIBRW
rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS);
rw::SetRenderState(rw::STENCILFUNCTIONREF, 1);
rw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFFFFFFFF);
rw::SetRenderState(rw::STENCILFUNCTIONWRITEMASK, 0xFFFFFFFF);
rw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP);
rw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP);
rw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE);
#else
RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
RwD3D8SetRenderState(D3DRS_STENCILREF, 1);
RwD3D8SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
RwD3D8SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
RwD3D8SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
RwD3D8SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
#endif
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 255, 255, alpha),
CGeneral::GetRandomNumberInRange(-0.002f, 0.002f),
CGeneral::GetRandomNumberInRange(-0.002f, 0.002f),
CGeneral::GetRandomNumberInRange(-0.002f, 0.002f),
CGeneral::GetRandomNumberInRange(-0.002f, 0.002f),
fxZ[i], false);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, frontBuf);
#ifdef LIBRW
rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILEQUAL);
rw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP);
#else
RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
#endif
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
break;
}
#ifdef LIBRW
rw::SetRenderState(rw::STENCILENABLE, FALSE);
#else
RwD3D8SetRenderState(D3DRS_STENCILENABLE, FALSE);
#endif
if(drawWaterDrops){
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
// Draw drops
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripRaster[0]);
for(int i = 0; i < pBufVertCount; i++)
if(fxType[i] == FXTYPE_WATER1 || fxType[i] == FXTYPE_BLOOD1){
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, fxType[i] == FXTYPE_BLOOD1 ? 255 : 192),
0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripRaster[1]);
for(int i = 0; i < pBufVertCount; i++)
if(fxType[i] == FXTYPE_WATER2 || fxType[i] == FXTYPE_BLOOD2){
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, fxType[i] == FXTYPE_BLOOD2 ? 255 : 192),
0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCarSplashRaster[0]);
for(int i = 0; i < pBufVertCount; i++)
if(fxType[i] == FXTYPE_SPLASH1 || fxType[i] == FXTYPE_SPLASH2 || fxType[i] == FXTYPE_SPLASH3){
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(200, 200, 200, 255),
0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
// Darken the water drops
int alpha = 192*0.5f;
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripDarkRaster[0]);
for(int i = 0; i < pBufVertCount; i++)
if(fxType[i] == FXTYPE_WATER1){
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, alpha),
0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripDarkRaster[1]);
for(int i = 0; i < pBufVertCount; i++)
if(fxType[i] == FXTYPE_WATER2){
CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, alpha),
0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);
}
}
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
pBufVertCount = 0;
#endif
}

39
src/renderer/MBlur.h Normal file
View File

@ -0,0 +1,39 @@
#pragma once
enum FxType
{
FXTYPE_WATER1,
FXTYPE_WATER2,
FXTYPE_BLOOD1,
FXTYPE_BLOOD2,
FXTYPE_HEATHAZE,
FXTYPE_SPLASH1,
FXTYPE_SPLASH2,
FXTYPE_SPLASH3
};
class CMBlur
{
public:
static RwRaster *pFrontBuffer;
static bool ms_bJustInitialised;
static bool ms_bScaledBlur;
static bool BlurOn;
static float Drunkness;
static int32 pBufVertCount;
public:
static RwBool MotionBlurOpen(RwCamera *cam);
static RwBool MotionBlurClose(void);
static void CreateImmediateModeData(RwCamera *cam, RwRect *rect);
static void CreateImmediateModeData(RwCamera *cam, RwRect *rect, RwIm2DVertex *verts, RwRGBA color, float u1Off, float v1Off, float u2Off, float v2Off, float z, int fullTexture);
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();
static bool PosInside(RwRect *rect, float x1, float y1, float x2, float y2);
static bool AddRenderFx(RwCamera *cam, RwRect *rect, float z, FxType type);
static void OverlayRenderFx(RwCamera *cam, RwRaster *frontBuf);
};

530
src/renderer/Occlusion.cpp Normal file
View File

@ -0,0 +1,530 @@
#include "common.h"
#include "main.h"
#include "Entity.h"
#include "Occlusion.h"
#include "Game.h"
#include "Camera.h"
#include "Vector.h"
#include "Draw.h"
#include "Timer.h"
#include "RwHelper.h"
#include "VarConsole.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];
#ifndef MASTER
bool bDispayOccDebugStuff; // disPAY, yeah
#endif
void
COcclusion::Init(void)
{
NumOccludersOnMap = 0;
#ifndef MASTER
VarConsole.Add("Occlusion debug", &bDispayOccDebugStuff, true);
#endif
FarAwayList = -1;
NearbyList = -1;
ListWalkThroughFA = -1;
PreviousListWalkThroughFA = -1;
}
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;
#ifndef MASTER
if (gbModelViewer)
return;
#endif
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--;
// Taken from Mobile!
#ifdef FIX_BUGS
if (i == -1) {
i = 0;
}
#endif
}
}
}
}
}
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;
}
#ifndef MASTER
#include "Lines.h"
RwIm2DVertex vertexbufferT[2];
void COcclusion::Render() {
if (!bDispayOccDebugStuff || !(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();
}
#endif
bool CEntity::IsEntityOccluded(void) {
CVector coors;
float width, height;
if (COcclusion::NumActiveOccluders == 0 || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height))
return false;
float area = Max(width, height) * GetBoundRadius() * 0.9f;
for (int i = 0; i < COcclusion::NumActiveOccluders; i++) {
if (coors.z - (GetBoundRadius() * 0.85f) > COcclusion::aActiveOccluders[i].radius) {
if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) {
return true;
}
if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) {
CVector min = m_matrix * CModelInfo::GetColModel(m_modelIndex)->boundingBox.min;
CVector max = m_matrix * CModelInfo::GetColModel(m_modelIndex)->boundingBox.max;
if (CalcScreenCoors(min, &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
if (CalcScreenCoors(CVector(max.x, max.y, min.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
if (CalcScreenCoors(CVector(max.x, min.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
if (CalcScreenCoors(CVector(min.x, max.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
return true;
}
}
}
return false;
}

62
src/renderer/Occlusion.h Normal file
View File

@ -0,0 +1,62 @@
#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);
#ifndef MASTER
static void Render();
#endif
};
bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh);
bool CalcScreenCoors(CVector const &in, CVector *out);
#ifndef MASTER
extern bool bDispayOccDebugStuff;
#endif

2328
src/renderer/Particle.cpp Normal file

File diff suppressed because it is too large Load Diff

101
src/renderer/Particle.h Normal file
View File

@ -0,0 +1,101 @@
#pragma once
#include "ParticleMgr.h"
class CEntity;
class CParticle
{
public:
enum
{
RAND_TABLE_SIZE = 20,
SIN_COS_TABLE_SIZE = 1024
};
CVector m_vecPosition;
CVector m_vecVelocity;
uint32 m_nTimeWhenWillBeDestroyed;
uint32 m_nTimeWhenColorWillBeChanged;
float m_fZGround;
uint8 m_nColorIntensity;
uint8 m_nAlpha;
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;
int32 field_4C;
CParticle()
{
;
}
~CParticle()
{
;
}
static float ms_afRandTable[RAND_TABLE_SIZE];
static CParticle *m_pUnusedListHead;
static float m_SinTable[SIN_COS_TABLE_SIZE];
static float m_CosTable[SIN_COS_TABLE_SIZE];
static float Sin(int32 value) { return m_SinTable[value]; }
static float Cos(int32 value) { return m_CosTable[value]; }
static void ReloadConfig();
static void Initialise();
static void Shutdown();
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();
static void RemovePSystem(tParticleType type);
static void RemoveParticle(CParticle *pParticle, CParticle *pPrevParticle, tParticleSystemData *pPSystemData);
static void _Next(CParticle *&pParticle, CParticle *&pPrevParticle, tParticleSystemData *pPSystemData, bool bRemoveParticle)
{
if ( bRemoveParticle )
{
RemoveParticle(pParticle, pPrevParticle, pPSystemData);
if ( pPrevParticle )
pParticle = pPrevParticle->m_pNext;
else
pParticle = pPSystemData->m_pParticles;
}
else
{
pPrevParticle = pParticle;
pParticle = pParticle->m_pNext;
}
}
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);
};
extern RwRaster *gpCarSplashRaster[];
extern RwRaster *gpHeatHazeRaster;
extern RwRaster *gpRainDripRaster[];
extern RwRaster *gpRainDripDarkRaster[];
VALIDATE_SIZE(CParticle, 0x50);

View File

@ -0,0 +1,277 @@
#include "common.h"
#include "main.h"
#include "FileMgr.h"
#include "ParticleMgr.h"
// --LCS: File done
cParticleSystemMgr mod_ParticleSystemManager;
const char *ParticleFilename = "PARTICLE.CFG";
cParticleSystemMgr::cParticleSystemMgr()
{
#ifdef FIX_BUGS
m_aParticles = nil;
#endif
}
#ifdef FIX_BUGS
cParticleSystemMgr::~cParticleSystemMgr()
{
delete [] m_aParticles;
}
#endif
void cParticleSystemMgr::Initialise()
{
if ( gMakeResources )
LoadParticleData();
for ( int32 i = 0; i < MAX_PARTICLES; i++ )
m_aParticles[i].m_pParticles = nil;
}
void cParticleSystemMgr::LoadParticleData()
{
#ifdef FIX_BUGS
delete [] m_aParticles;
#endif
m_aParticles = new tParticleSystemData[MAX_PARTICLES];
memset(m_aParticles, 0, sizeof(tParticleSystemData)*MAX_PARTICLES);
CFileMgr::SetDir("Data");
ssize_t len = CFileMgr::LoadFile(ParticleFilename, work_buff, ARRAY_SIZE(work_buff), "r");
CFileMgr::SetDir("");
ASSERT(!(len <= 0));
tParticleSystemData *entry = nil;
int32 type = PARTICLE_FIRST;
char *buffEnd = (char *)&work_buff[len];
char *lineStart = (char *)work_buff;
char *lineEnd = lineStart + 1;
char line[500];
char delims[4];
while ( lineStart < buffEnd )
{
ASSERT(lineStart != nil);
ASSERT(lineEnd != nil);
while ( *lineEnd != '\n' )
++lineEnd;
int32 lineLength = lineEnd - lineStart;
ASSERT(lineLength < 500);
strncpy(line, lineStart, lineLength);
line[lineLength] = '\0';
if ( !strcmp(line, ";the end") )
break;
if ( *line != ';' )
{
int32 param = CFG_PARAM_FIRST;
strcpy(delims, " \t");
char *value = strtok(line, delims);
ASSERT(value != nil);
do
{
switch ( param )
{
case CFG_PARAM_PARTICLE_TYPE_NAME:
ASSERT(type < MAX_PARTICLES);
entry = &m_aParticles[type];
ASSERT(entry != nil);
entry->m_Type = (tParticleType)type++;
strcpy(entry->m_aName, value);
break;
case CFG_PARAM_RENDER_COLOURING_R:
entry->m_RenderColouring.red = atoi(value);
break;
case CFG_PARAM_RENDER_COLOURING_G:
entry->m_RenderColouring.green = atoi(value);
break;
case CFG_PARAM_RENDER_COLOURING_B:
entry->m_RenderColouring.blue = atoi(value);
break;
case CFG_PARAM_INITIAL_COLOR_VARIATION:
entry->m_InitialColorVariation = Min(atoi(value), 100);
break;
case CFG_PARAM_FADE_DESTINATION_COLOR_R:
entry->m_FadeDestinationColor.red = atoi(value);
break;
case CFG_PARAM_FADE_DESTINATION_COLOR_G:
entry->m_FadeDestinationColor.green = atoi(value);
break;
case CFG_PARAM_FADE_DESTINATION_COLOR_B:
entry->m_FadeDestinationColor.blue = atoi(value);
break;
case CFG_PARAM_COLOR_FADE_TIME:
entry->m_ColorFadeTime = atoi(value);
break;
case CFG_PARAM_DEFAULT_INITIAL_RADIUS:
entry->m_fDefaultInitialRadius = atof(value);
break;
case CFG_PARAM_EXPANSION_RATE:
entry->m_fExpansionRate = atof(value);
break;
case CFG_PARAM_INITIAL_INTENSITY:
entry->m_nFadeToBlackInitialIntensity = atoi(value);
break;
case CFG_PARAM_FADE_TIME:
entry->m_nFadeToBlackTime = atoi(value);
break;
case CFG_PARAM_FADE_AMOUNT:
entry->m_nFadeToBlackAmount = atoi(value);
break;
case CFG_PARAM_INITIAL_ALPHA_INTENSITY:
entry->m_nFadeAlphaInitialIntensity = atoi(value);
break;
case CFG_PARAM_FADE_ALPHA_TIME:
entry->m_nFadeAlphaTime = atoi(value);
break;
case CFG_PARAM_FADE_ALPHA_AMOUNT:
entry->m_nFadeAlphaAmount = atoi(value);
break;
case CFG_PARAM_INITIAL_ANGLE:
entry->m_nZRotationInitialAngle = atoi(value);
break;
case CFG_PARAM_CHANGE_TIME:
entry->m_nZRotationChangeTime = atoi(value);
break;
case CFG_PARAM_ANGLE_CHANGE_AMOUNT:
entry->m_nZRotationAngleChangeAmount = atoi(value);
break;
case CFG_PARAM_INITIAL_Z_RADIUS:
entry->m_fInitialZRadius = atof(value);
break;
case CFG_PARAM_Z_RADIUS_CHANGE_TIME:
entry->m_nZRadiusChangeTime = atoi(value);
break;
case CFG_PARAM_Z_RADIUS_CHANGE_AMOUNT:
entry->m_fZRadiusChangeAmount = atof(value);
break;
case CFG_PARAM_ANIMATION_SPEED:
entry->m_nAnimationSpeed = atoi(value);
break;
case CFG_PARAM_START_ANIMATION_FRAME:
entry->m_nStartAnimationFrame = atoi(value);
break;
case CFG_PARAM_FINAL_ANIMATION_FRAME:
entry->m_nFinalAnimationFrame = atoi(value);
break;
case CFG_PARAM_ROTATION_SPEED:
entry->m_nRotationSpeed = atoi(value);
break;
case CFG_PARAM_GRAVITATIONAL_ACCELERATION:
entry->m_fGravitationalAcceleration = atof(value);
break;
case CFG_PARAM_FRICTION_DECCELERATION:
entry->m_nFrictionDecceleration = atoi(value);
break;
case CFG_PARAM_LIFE_SPAN:
entry->m_nLifeSpan = atoi(value);
break;
case CFG_PARAM_POSITION_RANDOM_ERROR:
entry->m_fPositionRandomError = atof(value);
break;
case CFG_PARAM_VELOCITY_RANDOM_ERROR:
entry->m_fVelocityRandomError = atof(value);
break;
case CFG_PARAM_EXPANSION_RATE_ERROR:
entry->m_fExpansionRateError = atof(value);
break;
case CFG_PARAM_ROTATION_RATE_ERROR:
entry->m_nRotationRateError = atoi(value);
break;
case CFG_PARAM_LIFE_SPAN_ERROR_SHAPE:
entry->m_nLifeSpanErrorShape = atoi(value);
break;
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));
break;
case CFG_PARAM_FLAGS:
entry->Flags = atoi(value);
break;
}
value = strtok(nil, delims);
param++;
if ( param > CFG_PARAM_LAST )
param = CFG_PARAM_FIRST;
} while ( value != nil );
}
lineEnd++;
lineStart = lineEnd;
lineEnd++;
}
}

141
src/renderer/ParticleMgr.h Normal file
View File

@ -0,0 +1,141 @@
#pragma once
#include "ParticleType.h"
class CParticle;
enum
{
ZCHECK_FIRST = BIT(0),
ZCHECK_STEP = BIT(1),
DRAW_OPAQUE = BIT(2),
SCREEN_TRAIL = BIT(3),
SPEED_TRAIL = BIT(4),
RAND_VERT_V = BIT(5),
CYCLE_ANIM = BIT(6),
DRAW_DARK = BIT(7),
VERT_TRAIL = BIT(8),
_FLAG9 = BIT(9), // unused
DRAWTOP2D = BIT(10),
CLIPOUT2D = BIT(11),
ZCHECK_BUMP = BIT(12),
ZCHECK_BUMP_FIRST = BIT(13)
};
struct tParticleSystemData
{
tParticleType m_Type;
char m_aName[20];
float m_fCreateRange;
float m_fDefaultInitialRadius;
float m_fExpansionRate;
uint16 m_nZRotationInitialAngle;
int16 m_nZRotationAngleChangeAmount;
uint16 m_nZRotationChangeTime;
uint16 m_nZRadiusChangeTime;
float m_fInitialZRadius;
float m_fZRadiusChangeAmount;
int16 m_nFadeToBlackTime;
uint8 m_nFadeToBlackInitialIntensity;
int16 m_nFadeToBlackAmount;
uint8 m_nFadeAlphaInitialIntensity;
int16 m_nFadeAlphaTime;
int16 m_nFadeAlphaAmount;
uint8 m_nStartAnimationFrame;
uint8 m_nFinalAnimationFrame;
uint16 m_nAnimationSpeed;
uint16 m_nRotationSpeed;
float m_fGravitationalAcceleration;
int32 m_nFrictionDecceleration;
int32 m_nLifeSpan;
float m_fPositionRandomError;
float m_fVelocityRandomError;
float m_fExpansionRateError;
int32 m_nRotationRateError;
uint32 m_nLifeSpanErrorShape;
float m_fTrailLengthMultiplier;
uint32 Flags;
CRGBA m_RenderColouring;
uint8 m_InitialColorVariation;
CRGBA m_FadeDestinationColor;
uint32 m_ColorFadeTime;
CVector2D m_vecTextureStretch;
float m_fWindFactor;
RwRaster **m_ppRaster;
CParticle *m_pParticles;
};
VALIDATE_SIZE(tParticleSystemData, 0x94);
class cParticleSystemMgr
{
enum
{
CFG_PARAM_PARTICLE_TYPE_NAME = 0,
CFG_PARAM_RENDER_COLOURING_R,
CFG_PARAM_RENDER_COLOURING_G,
CFG_PARAM_RENDER_COLOURING_B,
CFG_PARAM_INITIAL_COLOR_VARIATION,
CFG_PARAM_FADE_DESTINATION_COLOR_R,
CFG_PARAM_FADE_DESTINATION_COLOR_G,
CFG_PARAM_FADE_DESTINATION_COLOR_B,
CFG_PARAM_COLOR_FADE_TIME,
CFG_PARAM_DEFAULT_INITIAL_RADIUS,
CFG_PARAM_EXPANSION_RATE,
CFG_PARAM_INITIAL_INTENSITY,
CFG_PARAM_FADE_TIME,
CFG_PARAM_FADE_AMOUNT,
CFG_PARAM_INITIAL_ALPHA_INTENSITY,
CFG_PARAM_FADE_ALPHA_TIME,
CFG_PARAM_FADE_ALPHA_AMOUNT,
CFG_PARAM_INITIAL_ANGLE,
CFG_PARAM_CHANGE_TIME,
CFG_PARAM_ANGLE_CHANGE_AMOUNT,
CFG_PARAM_INITIAL_Z_RADIUS,
CFG_PARAM_Z_RADIUS_CHANGE_TIME,
CFG_PARAM_Z_RADIUS_CHANGE_AMOUNT,
CFG_PARAM_ANIMATION_SPEED,
CFG_PARAM_START_ANIMATION_FRAME,
CFG_PARAM_FINAL_ANIMATION_FRAME,
CFG_PARAM_ROTATION_SPEED,
CFG_PARAM_GRAVITATIONAL_ACCELERATION,
CFG_PARAM_FRICTION_DECCELERATION,
CFG_PARAM_LIFE_SPAN,
CFG_PARAM_POSITION_RANDOM_ERROR,
CFG_PARAM_VELOCITY_RANDOM_ERROR,
CFG_PARAM_EXPANSION_RATE_ERROR,
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,
MAX_CFG_PARAMS,
CFG_PARAM_FIRST = CFG_PARAM_PARTICLE_TYPE_NAME,
CFG_PARAM_LAST = CFG_PARAM_FLAGS
};
public:
tParticleSystemData *m_aParticles;//[MAX_PARTICLES];
cParticleSystemMgr();
#ifdef FIX_BUGS
~cParticleSystemMgr();
#endif
void Initialise();
void LoadParticleData();
void RangeCheck(tParticleSystemData *pData) { }
};
VALIDATE_SIZE(cParticleSystemMgr, 0x4);
extern cParticleSystemMgr mod_ParticleSystemManager;

View File

@ -0,0 +1,91 @@
#pragma once
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,
PARTICLE_GUNFLASH,
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,
PARTICLE_CARFLAME,
PARTICLE_STEAM,
PARTICLE_STEAM2,
PARTICLE_STEAM_NY,
PARTICLE_STEAM_NY_SLOWMOTION,
PARTICLE_GROUND_STEAM,
PARTICLE_ENGINE_STEAM,
PARTICLE_RAINDROP,
PARTICLE_RAINDROP_SMALL,
PARTICLE_RAIN_SPLASH,
PARTICLE_RAIN_SPLASH_BIGGROW,
PARTICLE_RAIN_SPLASHUP,
PARTICLE_WATERSPRAY,
PARTICLE_EXPLOSION_MEDIUM,
PARTICLE_EXPLOSION_LARGE,
PARTICLE_EXPLOSION_MFAST,
PARTICLE_EXPLOSION_LFAST,
PARTICLE_CAR_SPLASH,
PARTICLE_BOAT_SPLASH,
PARTICLE_BOAT_THRUSTJET,
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,
PARTICLE_ENGINE_SMOKE2,
PARTICLE_CARFLAME_SMOKE,
PARTICLE_FIREBALL_SMOKE,
PARTICLE_PAINT_SMOKE,
PARTICLE_TREE_LEAVES,
PARTICLE_CARCOLLISION_DUST,
PARTICLE_CAR_DEBRIS,
PARTICLE_BIRD_DEBRIS,
PARTICLE_HELI_DEBRIS,
PARTICLE_EXHAUST_FUMES,
PARTICLE_RUBBER_SMOKE,
PARTICLE_BURNINGRUBBER_SMOKE,
PARTICLE_BULLETHIT_SMOKE,
PARTICLE_GUNSHELL_FIRST,
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_FERRY_CHIM_SMOKE,
PARTICLE_MULTIPLAYER_HIT,
PARTICLE_HYDRANT_STEAM,
MAX_PARTICLES,
PARTICLE_FIRST = PARTICLE_SPARK,
PARTICLE_LAST = PARTICLE_HYDRANT_STEAM
};

164
src/renderer/PlayerSkin.cpp Normal file
View File

@ -0,0 +1,164 @@
#include "common.h"
#include "main.h"
#include "PlayerSkin.h"
#include "TxdStore.h"
#include "rtbmp.h"
#include "ClumpModelInfo.h"
#include "VisibilityPlugins.h"
#include "World.h"
#include "PlayerInfo.h"
#include "CdStream.h"
#include "FileMgr.h"
#include "Directory.h"
#include "RwHelper.h"
#include "Timer.h"
#include "Lights.h"
#include "MemoryMgr.h"
RpClump *gpPlayerClump;
float gOldFov;
int CPlayerSkin::m_txdSlot;
void
FindPlayerDff(uint32 &offset, uint32 &size)
{
int file;
CDirectory::DirectoryInfo info;
file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
do {
if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
return;
} while (strcasecmp("player.dff", info.name) != 0);
offset = info.offset;
size = info.size;
}
void
LoadPlayerDff(void)
{
RwStream *stream;
RwMemory mem;
uint32 offset, size;
uint8 *buffer;
bool streamWasAdded = false;
if (CdStreamGetNumImages() == 0) {
CdStreamAddImage("models\\gta3.img");
streamWasAdded = true;
}
FindPlayerDff(offset, size);
buffer = (uint8*)RwMallocAlign(size << 11, 2048);
CdStreamRead(0, buffer, offset, size);
CdStreamSync(0);
mem.start = buffer;
mem.length = size << 11;
stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
gpPlayerClump = RpClumpStreamRead(stream);
RwStreamClose(stream, &mem);
RwFreeAlign(buffer);
if (streamWasAdded)
CdStreamRemoveImages();
}
void
CPlayerSkin::Initialise(void)
{
// empty on PS2
m_txdSlot = CTxdStore::AddTxdSlot("skin");
CTxdStore::Create(m_txdSlot);
CTxdStore::AddRef(m_txdSlot);
}
void
CPlayerSkin::Shutdown(void)
{
// empty on PS2
CTxdStore::RemoveTxdSlot(m_txdSlot);
}
RwTexture *
CPlayerSkin::GetSkinTexture(const char *texName)
{
RwTexture *tex;
RwRaster *raster;
int32 width, height, depth, format;
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(m_txdSlot);
tex = RwTextureRead(texName, NULL);
CTxdStore::PopCurrentTxd();
if (tex != nil) return tex;
if (strcmp(DEFAULT_SKIN_NAME, texName) == 0 || texName[0] == '\0')
sprintf(gString, "models\\generic\\player.bmp");
else
sprintf(gString, "skins\\%s.bmp", texName);
if (RwImage *image = RtBMPImageRead(gString)) {
RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
raster = RwRasterCreate(width, height, depth, format);
RwRasterSetFromImage(raster, image);
tex = RwTextureCreate(raster);
RwTextureSetName(tex, texName);
RwTextureSetFilterMode(tex, rwFILTERLINEAR);
RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
RwImageDestroy(image);
}
return tex;
}
void
CPlayerSkin::BeginFrontendSkinEdit(void)
{
LoadPlayerDff();
RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
CWorld::Players[0].LoadPlayerSkin();
gOldFov = CDraw::GetFOV();
CDraw::SetFOV(30.0f);
}
void
CPlayerSkin::EndFrontendSkinEdit(void)
{
RpClumpDestroy(gpPlayerClump);
gpPlayerClump = NULL;
CDraw::SetFOV(gOldFov);
}
void
CPlayerSkin::RenderFrontendSkinEdit(void)
{
static float rotation = 0.0f;
RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
const RwV3d pos = { 1.35f, 0.35f, 7.725f };
const RwV3d axis = { 0.0f, 1.0f, 0.0f };
static uint32 LastFlash = 0;
RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
rotation += 2.0f;
if (rotation > 360.0f)
rotation -= 360.0f;
LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
}
RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
RwFrameRotate(frame, &axis, rotation, rwCOMBINEPRECONCAT);
RwFrameUpdateObjects(frame);
SetAmbientColours(&AmbientColor);
RpClumpRender(gpPlayerClump);
}

15
src/renderer/PlayerSkin.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#define DEFAULT_SKIN_NAME "$$\"\""
class CPlayerSkin
{
static int m_txdSlot;
public:
static void Initialise();
static void Shutdown();
static RwTexture *GetSkinTexture(const char *texName);
static void BeginFrontendSkinEdit();
static void EndFrontendSkinEdit();
static void RenderFrontendSkinEdit();
};

View File

@ -0,0 +1,330 @@
#include "common.h"
#include "main.h"
#include "CutsceneMgr.h"
#include "Lights.h"
#include "Camera.h"
#include "Weather.h"
#include "World.h"
#include "Collision.h"
#include "Sprite.h"
#include "Timer.h"
#include "PointLights.h"
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)
{
NumLights = 0;
}
#define MAX_DIST 22.0f
void
CPointLights::AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows)
{
CVector dist;
float distance;
// The check is done in some weird way in the game
// we're doing it a bit better here
if(NumLights >= NUMPOINTLIGHTS)
return;
dist = coors - TheCamera.GetPosition();
if(Abs(dist.x) < MAX_DIST && Abs(dist.y) < MAX_DIST){
distance = dist.Magnitude();
if(distance < MAX_DIST){
aLights[NumLights].type = type;
aLights[NumLights].fogType = fogType;
aLights[NumLights].coors = coors;
aLights[NumLights].dir = dir;
aLights[NumLights].radius = radius;
aLights[NumLights].castExtraShadows = castExtraShadows;
if(distance < MAX_DIST*0.75f){
aLights[NumLights].red = red;
aLights[NumLights].green = green;
aLights[NumLights].blue = blue;
}else{
float fade = 1.0f - (distance/MAX_DIST - 0.75f)*4.0f;
aLights[NumLights].red = red * fade;
aLights[NumLights].green = green * fade;
aLights[NumLights].blue = blue * fade;
}
NumLights++;
}
}
}
float
CPointLights::GenerateLightsAffectingObject(Const CVector *objCoors)
{
int i;
float ret;
CVector dist;
float radius, distance;
ret = 1.0f;
for(i = 0; i < NumLights; i++){
if(aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS)
continue;
// same weird distance calculation. simplified here
dist = aLights[i].coors - *objCoors;
radius = aLights[i].radius;
if(Abs(dist.x) < radius &&
Abs(dist.y) < radius &&
Abs(dist.z) < radius){
distance = dist.Magnitude();
if(distance < radius){
float distNorm = distance/radius;
if(aLights[i].type == LIGHT_DARKEN){
// darken the object the closer it is
ret *= distNorm;
}else{
float intensity;
// distance fade
if(distNorm < 0.5f)
intensity = 1.0f;
else
intensity = 1.0f - (distNorm - 0.5f)/(1.0f - 0.5f);
if(distance != 0.0f){
CVector dir = dist / distance;
if(aLights[i].type == LIGHT_DIRECTIONAL){
float dot = -DotProduct(dir, aLights[i].dir);
intensity *= Max((dot-0.5f)*2.0f, 0.0f);
}
if(intensity > 0.0f)
AddAnExtraDirectionalLight(Scene.world,
dir.x, dir.y, dir.z,
aLights[i].red*intensity, aLights[i].green*intensity, aLights[i].blue*intensity);
}
}
}
}
}
return ret;
}
extern RwRaster *gpPointlightRaster;
void
CPointLights::RemoveLightsAffectingObject(void)
{
RemoveExtraDirectionalLights(Scene.world);
}
// for directional fog
#define FOG_AREA_LENGTH 12.0f
#define FOG_AREA_WIDTH 5.0f
// for pointlight fog
#define FOG_AREA_RADIUS 9.0f
float FogSizes[8] = { 1.3f, 2.0f, 1.7f, 2.0f, 1.4f, 2.1f, 1.5f, 2.3f };
void
CPointLights::RenderFogEffect(void)
{
int i;
float fogginess;
CColPoint point;
CEntity *entity;
float xmin, ymin;
float xmax, ymax;
int16 xi, yi;
CVector spriteCoors;
float spritew, spriteh;
if(CCutsceneMgr::IsRunning())
return;
PUSH_RENDERGROUP("CPointLights::RenderFogEffect");
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;
fogginess = aLights[i].fogType == FOG_NORMAL ? CWeather::Foggyness : 1.0f;
if(fogginess == 0.0f)
continue;
if(aLights[i].type == LIGHT_DIRECTIONAL){
// TODO: test this. haven't found directional fog so far
float coors2X = aLights[i].coors.x + FOG_AREA_LENGTH*aLights[i].dir.x;
float coors2Y = aLights[i].coors.y + FOG_AREA_LENGTH*aLights[i].dir.y;
if(coors2X < aLights[i].coors.x){
xmin = coors2X;
xmax = aLights[i].coors.x;
}else{
xmax = coors2X;
xmin = aLights[i].coors.x;
}
if(coors2Y < aLights[i].coors.y){
ymin = coors2Y;
ymax = aLights[i].coors.y;
}else{
ymax = coors2Y;
ymin = aLights[i].coors.y;
}
xmin -= 5.0f;
ymin -= 5.0f;
xmax += 5.0f;
ymax += 5.0f;
for(xi = (int16)xmin - (int16)xmin % 4; xi <= (int16)xmax + 4; xi += 4){
for(yi = (int16)ymin - (int16)ymin % 4; yi <= (int16)ymax + 4; yi += 4){
// Some kind of pseudo random number?
int r = (xi ^ yi)>>2 & 0xF;
if((r & 1) == 0)
continue;
// Check if fog effect is close enough to directional line in x and y
float dx = xi - aLights[i].coors.x;
float dy = yi - aLights[i].coors.y;
float dot = dx*aLights[i].dir.x + dy*aLights[i].dir.y;
float distsq = sq(dx) + sq(dy);
float linedistsq = distsq - sq(dot);
if(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){
CVector fogcoors(xi, yi, aLights[i].coors.z + 10.0f);
if(CWorld::ProcessVerticalLine(fogcoors, fogcoors.z - 20.0f,
point, entity, true, false, false, false, true, false, nil)){
// Now same check again in xyz
fogcoors.z = point.point.z + 1.3f;
// actually we don't have to recalculate x and y, but the game does it that way
dx = xi - aLights[i].coors.x;
dy = yi - aLights[i].coors.y;
float dz = fogcoors.z - aLights[i].coors.z;
dot = dx*aLights[i].dir.x + dy*aLights[i].dir.y + dz*aLights[i].dir.z;
distsq = sq(dx) + sq(dy) + sq(dz);
linedistsq = distsq - sq(dot);
if(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){
float intensity = 158.0f * fogginess;
// more intensity the smaller the angle
intensity *= dot/Sqrt(distsq);
// more intensity the closer to light source
intensity *= 1.0f - sq(dot/FOG_AREA_LENGTH);
// more intensity the closer to line
intensity *= 1.0f - sq(Sqrt(linedistsq) / FOG_AREA_WIDTH);
if(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)) {
float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x2000;
float size = FogSizes[r>>1];
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);
}
}
}
}
}
}
}else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS){
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;
ymax = aLights[i].coors.y + FOG_AREA_RADIUS;
for(xi = (int16)xmin - (int16)xmin % 2; xi <= (int16)xmax + 2; xi += 2){
for(yi = (int16)ymin - (int16)ymin % 2; yi <= (int16)ymax + 2; yi += 2){
// Some kind of pseudo random number?
int r = (xi ^ yi)>>1 & 0xF;
if((r & 1) == 0)
continue;
float dx = xi - aLights[i].coors.x;
float dy = yi - aLights[i].coors.y;
float lightdist = Sqrt(sq(dx) + sq(dy));
if(lightdist < FOG_AREA_RADIUS){
dx = xi - TheCamera.GetPosition().x;
dy = yi - TheCamera.GetPosition().y;
float camdist = Sqrt(sq(dx) + sq(dy));
if(camdist < MAX_DIST){
float intensity;
// distance fade
if(camdist < MAX_DIST/2)
intensity = 1.0f;
else
intensity = 1.0f - (camdist - MAX_DIST/2) / (MAX_DIST/2);
intensity *= 132.0f * fogginess;
// more intensity the closer to light source
intensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS);
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::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);
}
}
}
}
}
}
}
}
CSprite::FlushSpriteBuffer();
POP_RENDERGROUP();
}
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;
}

View File

@ -0,0 +1,50 @@
#pragma once
class CRegisteredPointLight
{
public:
CVector coors;
CVector dir;
float radius;
float red;
float green;
float blue;
int8 type;
int8 fogType;
bool castExtraShadows;
};
VALIDATE_SIZE(CRegisteredPointLight, 0x2C);
class CPointLights
{
public:
static int16 NumLights;
static CRegisteredPointLight aLights[NUMPOINTLIGHTS];
static CVector aCachedMapReads[32];
static float aCachedMapReadResults[32];
static int32 NextCachedValue;
enum {
LIGHT_POINT,
LIGHT_DIRECTIONAL,
LIGHT_DARKEN, // no effects at all
// these have only fog, otherwise no difference?
// only used by CEntity::ProcessLightsForEntity it seems
// and there used together with fog type
LIGHT_FOGONLY_ALWAYS,
LIGHT_FOGONLY,
};
enum {
FOG_NONE,
FOG_NORMAL, // taken from Foggyness
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);
};

View File

@ -0,0 +1,52 @@
#include "common.h"
#include "RenderBuffer.h"
int32 TempBufferVerticesStored;
int32 TempBufferIndicesStored;
VertexBufferUnion TempVertexBuffer;
RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE];
int RenderBuffer::VerticesToBeStored;
int RenderBuffer::IndicesToBeStored;
void
RenderBuffer::ClearRenderBuffer(void)
{
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
}
void
RenderBuffer::StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, RwIm3DVertex **vertexStart)
{
if(TempBufferIndicesStored + numIndices >= TEMPBUFFERINDEXSIZE)
RenderStuffInBuffer();
if(TempBufferVerticesStored + numVertices >= TEMPBUFFERVERTSIZE)
RenderStuffInBuffer();
*indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored];
*vertexStart = &TempBufferRenderVertices[TempBufferVerticesStored];
IndicesToBeStored = numIndices;
VerticesToBeStored = numVertices;
}
void
RenderBuffer::StopStoring(void)
{
int i;
for(i = TempBufferIndicesStored; i < TempBufferIndicesStored+IndicesToBeStored; i++)
TempBufferRenderIndexList[i] += TempBufferVerticesStored;
TempBufferIndicesStored += IndicesToBeStored;
TempBufferVerticesStored += VerticesToBeStored;
}
void
RenderBuffer::RenderStuffInBuffer(void)
{
if(TempBufferVerticesStored && RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
RwIm3DEnd();
}
ClearRenderBuffer();
}

View File

@ -0,0 +1,25 @@
class RenderBuffer
{
public:
static int VerticesToBeStored;
static int IndicesToBeStored;
static void ClearRenderBuffer(void);
static void StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, RwIm3DVertex **vertexStart);
static void StopStoring(void);
static void RenderStuffInBuffer(void);
};
#define TEMPBUFFERVERTSIZE 512
#define TEMPBUFFERINDEXSIZE 1024
struct VertexBufferUnion
{
RwIm2DVertex im2d[TEMPBUFFERVERTSIZE];
RwIm3DVertex im3d[TEMPBUFFERVERTSIZE];
};
extern int32 TempBufferVerticesStored;
extern int32 TempBufferIndicesStored;
extern VertexBufferUnion TempVertexBuffer;
#define TempBufferRenderVertices (TempVertexBuffer.im3d)
extern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE];

1865
src/renderer/Renderer.cpp Normal file

File diff suppressed because it is too large Load Diff

107
src/renderer/Renderer.h Normal file
View File

@ -0,0 +1,107 @@
#pragma once
class CEntity;
#ifdef FIX_BUGS
#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier)
#else
#define LOD_DISTANCE 300.0f
#endif
#define FADE_DISTANCE 20.0f
#define STREAM_DISTANCE 30.0f
extern bool gbShowPedRoadGroups;
extern bool gbShowCarRoadGroups;
extern bool gbShowCollisionPolys;
extern bool gbShowCollisionLines;
extern bool gbBigWhiteDebugLightSwitchedOn;
extern bool gbDontRenderBuildings;
extern bool gbDontRenderBigBuildings;
extern bool gbDontRenderPeds;
extern bool gbDontRenderObjects;
extern bool gbDontRenderVehicles;
class CVehicle;
class CPtrList;
// unused
struct BlockedRange
{
float a, b; // unknown
BlockedRange *prev, *next;
};
class CRenderer
{
static int32 ms_nNoOfVisibleEntities;
static CEntity *ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES];
static int32 ms_nNoOfInVisibleEntities;
static CEntity *ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES];
#ifdef NEW_RENDERER
static int32 ms_nNoOfVisibleVehicles;
static CEntity *ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES];
// for cWorldStream emulation
static int32 ms_nNoOfVisibleBuildings;
static CEntity *ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES];
#endif
static CVector ms_vecCameraPosition;
static CVehicle *m_pFirstPersonVehicle;
// unused
static BlockedRange aBlockedRanges[16];
static BlockedRange *pFullBlockedRanges;
static BlockedRange *pEmptyBlockedRanges;
public:
static float ms_lodDistScale;
static bool m_loadingPriority;
static void Init(void);
static void Shutdown(void);
static void PreRender(void);
static void RenderRoads(void);
static void RenderFadingInEntities(void);
static void RenderFadingInUnderwaterEntities(void);
static void RenderEverythingBarRoads(void);
static void RenderBoats(void);
static void RenderOneRoad(CEntity *);
static void RenderOneNonRoad(CEntity *);
static void RenderFirstPersonVehicle(void);
static void RenderCollisionLines(void);
static int32 SetupEntityVisibility(CEntity *ent);
static int32 SetupBigBuildingVisibility(CEntity *ent);
static void ConstructRenderList(void);
static void ScanWorld(void);
static void RequestObjectsInFrustum(void);
static void ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrList *));
static void ScanBigBuildingList(CPtrList &list);
static void ScanSectorList(CPtrList *lists);
static void ScanSectorList_Priority(CPtrList *lists);
static void ScanSectorList_Subway(CPtrList *lists);
static void ScanSectorList_RequestModels(CPtrList *lists);
static void SortBIGBuildings(void);
static void SortBIGBuildingsForSectorList(CPtrList *list);
static bool ShouldModelBeStreamed(CEntity *ent, const CVector &campos);
static void RemoveVehiclePedLights(CEntity *ent, bool reset);
#ifdef NEW_RENDERER
static void ClearForFrame(void);
static void RenderPeds(void);
static void RenderVehicles(void); // also renders peds in LCS
static void RenderOneBuilding(CEntity *ent, float camdist = 0.0f);
static void RenderWorld(int pass); // like cWorldStream::Render(int)
static void RenderTransparentWater(void); // keep-out polys and transparent water
#endif
static void InsertEntityIntoList(CEntity *ent);
static void GenerateEnvironmentMap(void);
};

423
src/renderer/Rubbish.cpp Normal file
View File

@ -0,0 +1,423 @@
#include "common.h"
#include "main.h"
#include "General.h"
#include "Timer.h"
#include "Weather.h"
#include "Camera.h"
#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 (23.0f)
#define RUBBISH_FADE_DIST (20.0f)
RwTexture *gpRubbishTexture[4];
RwImVertexIndex RubbishIndexList[6];
bool CRubbish::bRubbishInvisible;
int CRubbish::RubbishVisibility;
COneSheet CRubbish::aSheets[NUM_RUBBISH_SHEETS];
COneSheet CRubbish::StartEmptyList;
COneSheet CRubbish::EndEmptyList;
COneSheet CRubbish::StartStaticsList;
COneSheet CRubbish::EndStaticsList;
COneSheet CRubbish::StartMoversList;
COneSheet CRubbish::EndMoversList;
void
COneSheet::AddToList(COneSheet *list)
{
this->m_next = list->m_next;
this->m_prev = list;
list->m_next = this;
this->m_next->m_prev = this;
}
void
COneSheet::RemoveFromList(void)
{
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
void
CRubbish::Render(void)
{
int type;
if(RubbishVisibility == 0)
return;
PUSH_RENDERGROUP("CRubbish::Render");
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
for(type = 0; type < 4; type++){
if(type < 3 || CStats::PamphletMissionPassed)
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type]));
TempBufferIndicesStored = 0;
TempBufferVerticesStored = 0;
COneSheet *sheet;
for(sheet = &aSheets[type*NUM_RUBBISH_SHEETS / 4];
sheet < &aSheets[(type+1)*NUM_RUBBISH_SHEETS / 4];
sheet++){
if(sheet->m_state == 0)
continue;
uint32 alpha = 100;
CVector pos;
if(sheet->m_state == 1){
pos = sheet->m_basePos;
if(!sheet->m_isVisible)
alpha = 0;
}else{
pos = sheet->m_animatedPos;
// Not fully visible during animation, calculate current alpha
if(!sheet->m_isVisible || !sheet->m_targetIsVisible){
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 = 100 * (f1+f2);
}
}
float camDist = (pos - TheCamera.GetPosition()).Magnitude2D();
if(camDist < RUBBISH_MAX_DIST){
if(camDist >= RUBBISH_FADE_DIST)
alpha -= alpha*(camDist-RUBBISH_FADE_DIST)/(RUBBISH_MAX_DIST-RUBBISH_FADE_DIST);
alpha = (RubbishVisibility*alpha)/256;
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 + 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);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], 255, 255, 255, alpha);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], 255, 255, 255, alpha);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], 255, 255, 255, alpha);
RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], 0.0f);
RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], 0.0f);
RwIm3DVertexSetU(&TempBufferRenderVertices[v+1], 1.0f);
RwIm3DVertexSetV(&TempBufferRenderVertices[v+1], 0.0f);
RwIm3DVertexSetU(&TempBufferRenderVertices[v+2], 0.0f);
RwIm3DVertexSetV(&TempBufferRenderVertices[v+2], 1.0f);
RwIm3DVertexSetU(&TempBufferRenderVertices[v+3], 1.0f);
RwIm3DVertexSetV(&TempBufferRenderVertices[v+3], 1.0f);
int i = TempBufferIndicesStored;
TempBufferRenderIndexList[i+0] = RubbishIndexList[0] + TempBufferVerticesStored;
TempBufferRenderIndexList[i+1] = RubbishIndexList[1] + TempBufferVerticesStored;
TempBufferRenderIndexList[i+2] = RubbishIndexList[2] + TempBufferVerticesStored;
TempBufferRenderIndexList[i+3] = RubbishIndexList[3] + TempBufferVerticesStored;
TempBufferRenderIndexList[i+4] = RubbishIndexList[4] + TempBufferVerticesStored;
TempBufferRenderIndexList[i+5] = RubbishIndexList[5] + TempBufferVerticesStored;
TempBufferVerticesStored += 4;
TempBufferIndicesStored += 6;
}
}
if(TempBufferIndicesStored != 0){
LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
RwIm3DEnd();
}
}
}
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
POP_RENDERGROUP();
}
void
CRubbish::StirUp(CVehicle *veh)
{
if((CTimer::GetFrameCounter() ^ (veh->m_randomSeed&3)) == 0)
return;
if(Abs(veh->GetPosition().x - TheCamera.GetPosition().x) < 20.0f &&
Abs(veh->GetPosition().y - TheCamera.GetPosition().y) < 20.0f)
if(Abs(veh->GetMoveSpeed().x) > 0.05f || Abs(veh->GetMoveSpeed().y) > 0.05f){
float speed = veh->GetMoveSpeed().Magnitude2D();
if(speed > 0.05f){
bool movingForward = DotProduct2D(veh->GetMoveSpeed(), veh->GetForward()) > 0.0f;
COneSheet *sheet = StartStaticsList.m_next;
CVector2D size = veh->GetColModel()->boundingBox.max;
// Check all static sheets
while(sheet != &EndStaticsList){
COneSheet *next = sheet->m_next;
CVector2D carToSheet = sheet->m_basePos - veh->GetPosition();
float distFwd = DotProduct2D(carToSheet, veh->GetForward());
// sheet has to be a bit behind car
if(movingForward && distFwd < -0.5f*size.y && distFwd > -1.5f*size.y ||
!movingForward && distFwd > 0.5f*size.y && distFwd < 1.5f*size.y){
float distSide = Abs(DotProduct2D(carToSheet, veh->GetRight()));
if(distSide < 1.5*size.x){
// Check with higher speed for sheet directly behind car
float speedToCheck = distSide < size.x ? speed : speed*0.5f;
if(speedToCheck > 0.05f){
sheet->m_state = 2;
if(speedToCheck > 0.15f)
sheet->m_animationType = 2;
else
sheet->m_animationType = 1;
sheet->m_moveDuration = 2000;
sheet->m_xDist = veh->GetMoveSpeed().x;
sheet->m_yDist = veh->GetMoveSpeed().y;
float dist = Sqrt(SQR(sheet->m_xDist)+SQR(sheet->m_yDist));
sheet->m_xDist *= 25.0f*speed/dist;
sheet->m_yDist *= 25.0f*speed/dist;
sheet->m_animHeight = 3.0f*speed;
sheet->m_moveStart = CTimer::GetTimeInMilliseconds();
float tx = sheet->m_basePos.x + sheet->m_xDist;
float ty = sheet->m_basePos.y + sheet->m_yDist;
float tz = sheet->m_basePos.z + 3.0f;
sheet->m_targetZ = CWorld::FindGroundZFor3DCoord(tx, ty, tz, nil) + 0.1f;
sheet->RemoveFromList();
sheet->AddToList(&StartMoversList);
}
}
}
sheet = next;
}
}
}
}
static float aAnimations[3][34] = {
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
// Normal move
{ 0.0f, 0.05f, 0.12f, 0.25f, 0.42f, 0.57f, 0.68f, 0.8f, 0.86f, 0.9f, 0.93f, 0.95f, 0.96f, 0.97f, 0.98f, 0.99f, 1.0f, // XY movemnt
0.15f, 0.35f, 0.6f, 0.9f, 1.2f, 1.25f, 1.3f, 1.2f, 1.1f, 0.95f, 0.8f, 0.6f, 0.45f, 0.3f, 0.2f, 0.1f, 0 }, // Z movement
// Stirred up by fast vehicle
{ 0.0f, 0.05f, 0.12f, 0.25f, 0.42f, 0.57f, 0.68f, 0.8f, 0.95f, 1.1f, 1.15f, 1.18f, 1.15f, 1.1f, 1.05f, 1.03f, 1.0f,
0.15f, 0.35f, 0.6f, 0.9f, 1.2f, 1.25f, 1.3f, 1.2f, 1.1f, 0.95f, 0.8f, 0.6f, 0.45f, 0.3f, 0.2f, 0.1f, 0 }
};
void
CRubbish::Update(void)
{
bool foundGround;
// FRAMETIME
if(bRubbishInvisible)
RubbishVisibility = Max(RubbishVisibility-5, 0);
else
RubbishVisibility = Min(RubbishVisibility+5, 255);
// Spawn a new sheet
COneSheet *sheet = StartEmptyList.m_next;
if(sheet != &EndEmptyList){
float spawnDist;
float spawnAngle;
spawnDist = (CGeneral::GetRandomNumber()&0xFF)/256.0f + RUBBISH_MAX_DIST;
uint8 r = CGeneral::GetRandomNumber();
if(r&1)
spawnAngle = (CGeneral::GetRandomNumber()&0xFF)/256.0f * 6.28f;
else
spawnAngle = (r-128)/160.0f + TheCamera.Orientation;
sheet->m_basePos.x = TheCamera.GetPosition().x + spawnDist*Sin(spawnAngle);
sheet->m_basePos.y = TheCamera.GetPosition().y + spawnDist*Cos(spawnAngle);
sheet->m_basePos.z = CWorld::FindGroundZFor3DCoord(sheet->m_basePos.x, sheet->m_basePos.y, TheCamera.GetPosition().z, &foundGround) + 0.1f;
if(foundGround){
// Found ground, so add to statics list
sheet->m_angle = (CGeneral::GetRandomNumber()&0xFF)/256.0f * 6.28f;
sheet->m_state = 1;
if(CCullZones::FindAttributesForCoors(sheet->m_basePos, nil) & ATTRZONE_NORAIN)
sheet->m_isVisible = false;
else
sheet->m_isVisible = true;
sheet->RemoveFromList();
sheet->AddToList(&StartStaticsList);
}
}
// Process animation
sheet = StartMoversList.m_next;
while(sheet != &EndMoversList){
uint32 currentTime = CTimer::GetTimeInMilliseconds() - sheet->m_moveStart;
if(currentTime < sheet->m_moveDuration){
// Animation
int step = 16 * currentTime / sheet->m_moveDuration; // 16 steps in animation
int stepTime = sheet->m_moveDuration/16; // time in each step
float s = (float)(currentTime - stepTime*step) / stepTime; // position on step
float t = (float)currentTime / sheet->m_moveDuration; // position on total animation
// factors for xy and z-movment
float fxy = aAnimations[sheet->m_animationType][step]*(1.0f-s) + aAnimations[sheet->m_animationType][step+1]*s;
float fz = aAnimations[sheet->m_animationType][step+17]*(1.0f-s) + aAnimations[sheet->m_animationType][step+1+17]*s;
sheet->m_animatedPos.x = sheet->m_basePos.x + fxy*sheet->m_xDist;
sheet->m_animatedPos.y = sheet->m_basePos.y + fxy*sheet->m_yDist;
sheet->m_animatedPos.z = (1.0f-t)*sheet->m_basePos.z + t*sheet->m_targetZ + fz*sheet->m_animHeight;
sheet->m_angle += CTimer::GetTimeStep()*0.04f;
if(sheet->m_angle > 6.28f)
sheet->m_angle -= 6.28f;
sheet = sheet->m_next;
}else{
// End of animation, back into statics list
sheet->m_basePos.x += sheet->m_xDist;
sheet->m_basePos.y += sheet->m_yDist;
sheet->m_basePos.z = sheet->m_targetZ;
sheet->m_state = 1;
sheet->m_isVisible = sheet->m_targetIsVisible;
COneSheet *next = sheet->m_next;
sheet->RemoveFromList();
sheet->AddToList(&StartStaticsList);
sheet = next;
}
}
// Stir up a sheet by wind
// FRAMETIME
int freq;
if(CWeather::Wind < 0.1f)
freq = 31;
else if(CWeather::Wind < 0.4f)
freq = 7;
else if(CWeather::Wind < 0.7f)
freq = 1;
else
freq = 0;
if((CTimer::GetFrameCounter() & freq) == 0){
// Pick a random sheet and set animation state if static
int i = CGeneral::GetRandomNumber() % NUM_RUBBISH_SHEETS;
if(aSheets[i].m_state == 1){
aSheets[i].m_moveStart = CTimer::GetTimeInMilliseconds();
aSheets[i].m_moveDuration = CWeather::Wind*1500.0f + 1000.0f;
aSheets[i].m_animHeight = 0.2f;
aSheets[i].m_xDist = 3.0f*CWeather::Wind;
aSheets[i].m_yDist = 3.0f*CWeather::Wind;
// Check if target position is ok
float tx = aSheets[i].m_basePos.x + aSheets[i].m_xDist;
float ty = aSheets[i].m_basePos.y + aSheets[i].m_yDist;
float tz = aSheets[i].m_basePos.z + 3.0f;
aSheets[i].m_targetZ = CWorld::FindGroundZFor3DCoord(tx, ty, tz, &foundGround) + 0.1f;
if(CCullZones::FindAttributesForCoors(CVector(tx, ty, aSheets[i].m_targetZ), nil) & ATTRZONE_NORAIN)
aSheets[i].m_targetIsVisible = false;
else
aSheets[i].m_targetIsVisible = true;
if(foundGround){
// start animation
aSheets[i].m_state = 2;
aSheets[i].m_animationType = 1;
aSheets[i].RemoveFromList();
aSheets[i].AddToList(&StartMoversList);
}
}
}
// Remove sheets that are too far away
int i = (CTimer::GetFrameCounter()%(NUM_RUBBISH_SHEETS/4))*4;
int last = ((CTimer::GetFrameCounter()%(NUM_RUBBISH_SHEETS/4)) + 1)*4;
for(; i < last; i++){
if(aSheets[i].m_state == 1 &&
(aSheets[i].m_basePos - TheCamera.GetPosition()).MagnitudeSqr2D() > SQR(RUBBISH_MAX_DIST+1.0f)){
aSheets[i].m_state = 0;
aSheets[i].RemoveFromList();
aSheets[i].AddToList(&StartEmptyList);
}
}
}
void
CRubbish::SetVisibility(bool visible)
{
bRubbishInvisible = !visible;
}
void
CRubbish::Init(void)
{
int i;
for(i = 0; i < NUM_RUBBISH_SHEETS; i++){
aSheets[i].m_state = 0;
if(i < NUM_RUBBISH_SHEETS-1)
aSheets[i].m_next = &aSheets[i+1];
else
aSheets[i].m_next = &EndEmptyList;
if(i > 0)
aSheets[i].m_prev = &aSheets[i-1];
else
aSheets[i].m_prev = &StartEmptyList;
}
StartEmptyList.m_next = &aSheets[0];
StartEmptyList.m_prev = nil;
EndEmptyList.m_next = nil;
EndEmptyList.m_prev = &aSheets[NUM_RUBBISH_SHEETS-1];
StartStaticsList.m_next = &EndStaticsList;
StartStaticsList.m_prev = nil;
EndStaticsList.m_next = nil;
EndStaticsList.m_prev = &StartStaticsList;
StartMoversList.m_next = &EndMoversList;
StartMoversList.m_prev = nil;
EndMoversList.m_next = nil;
EndMoversList.m_prev = &StartMoversList;
RubbishIndexList[0] = 0;
RubbishIndexList[1] = 1;
RubbishIndexList[2] = 2;
RubbishIndexList[3] = 1;
RubbishIndexList[4] = 3;
RubbishIndexList[5] = 2;
CTxdStore::PushCurrentTxd();
int slot = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slot);
gpRubbishTexture[0] = RwTextureRead("gameleaf01_64", nil);
gpRubbishTexture[1] = RwTextureRead("gameleaf02_64", nil);
gpRubbishTexture[2] = RwTextureRead("newspaper01_64", nil);
gpRubbishTexture[3] = RwTextureRead("newspaper02_64", nil);
CTxdStore::PopCurrentTxd();
RubbishVisibility = 255;
bRubbishInvisible = false;
}
void
CRubbish::Shutdown(void)
{
RwTextureDestroy(gpRubbishTexture[0]);
gpRubbishTexture[0] = nil;
RwTextureDestroy(gpRubbishTexture[1]);
gpRubbishTexture[1] = nil;
RwTextureDestroy(gpRubbishTexture[2]);
gpRubbishTexture[2] = nil;
RwTextureDestroy(gpRubbishTexture[3]);
gpRubbishTexture[3] = nil;
}

57
src/renderer/Rubbish.h Normal file
View File

@ -0,0 +1,57 @@
#pragma once
class CVehicle;
enum {
// NB: not all values are allowed, check the code
#ifdef SQUEEZE_PERFORMANCE
NUM_RUBBISH_SHEETS = 32
#else
NUM_RUBBISH_SHEETS = 64
#endif
};
class COneSheet
{
public:
CVector m_basePos;
CVector m_animatedPos;
float m_targetZ;
int8 m_state;
int8 m_animationType;
uint32 m_moveStart;
uint32 m_moveDuration;
float m_animHeight;
float m_xDist;
float m_yDist;
float m_angle;
bool m_isVisible;
bool m_targetIsVisible;
COneSheet *m_next;
COneSheet *m_prev;
void AddToList(COneSheet *list);
void RemoveFromList(void);
};
class CRubbish
{
static bool bRubbishInvisible;
static int RubbishVisibility;
static COneSheet aSheets[NUM_RUBBISH_SHEETS];
static COneSheet StartEmptyList;
static COneSheet EndEmptyList;
static COneSheet StartStaticsList;
static COneSheet EndStaticsList;
static COneSheet StartMoversList;
static COneSheet EndMoversList;
public:
static void Render(void);
static void StirUp(CVehicle *veh); // CAutomobile on PS2
static void Update(void);
static void SetVisibility(bool visible);
static void Init(void);
static void Shutdown(void);
};
extern RwTexture *gpRubbishTexture[4];

View File

@ -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;
}

View File

@ -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;
}
};

2520
src/renderer/Shadows.cpp Normal file

File diff suppressed because it is too large Load Diff

210
src/renderer/Shadows.h Normal file
View File

@ -0,0 +1,210 @@
#pragma once
#define MAX_STOREDSHADOWS 48
#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
{
SHADOWTYPE_NONE = 0,
SHADOWTYPE_DARK,
SHADOWTYPE_ADDITIVE,
SHADOWTYPE_INVCOLOR
};
enum eShadowTextureType
{
SHADOWTEX_NONE = 0,
SHADOWTEX_CAR,
SHADOWTEX_PED,
SHADOWTEX_EXPLOSION,
SHADOWTEX_HELI,
SHADOWTEX_HEADLIGHTS,
SHADOWTEX_BLOOD
};
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:
CVector m_vecPos;
CVector2D m_vecFront;
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
RwTexture *m_pTexture;
CCutsceneShadow *m_pCutsceneShadow;
int16 m_nIntensity;
uint8 m_ShadowType;
uint8 m_nRed;
uint8 m_nGreen;
uint8 m_nBlue;
struct
{
uint8 bDrawOnWater : 1;
uint8 bRendered : 1;
uint8 bDrawOnBuildings : 1;
} m_nFlags;
CStoredShadow()
{ }
};
VALIDATE_SIZE(CStoredShadow, 0x30);
class CPolyBunch
{
public:
CVector m_aVerts[7];
CPolyBunch *m_pNext;
int16 m_nNumVerts;
uint8 m_aU[7];
uint8 m_aV[7];
CPolyBunch()
{ }
};
VALIDATE_SIZE(CPolyBunch, 0x6C);
class CStaticShadow
{
public:
uint32 m_nId;
CPolyBunch *m_pPolyBunch;
uint32 m_nTimeCreated;
CVector m_vecPosn;
CVector2D m_vecFront;
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
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;
CStaticShadow()
{ }
void Free();
};
VALIDATE_SIZE(CStaticShadow, 0x40);
class CPermanentShadow
{
public:
CVector m_vecPos;
CVector2D m_vecFront;
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
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;
CPermanentShadow()
{ }
};
VALIDATE_SIZE(CPermanentShadow, 0x38);
class CShadows
{
public:
static int16 ShadowsStoredToBeRendered;
static CStoredShadow asShadowsStored [MAX_STOREDSHADOWS];
static CPolyBunch aPolyBunches [MAX_POLYBUNCHES];
static CStaticShadow aStaticShadows [MAX_STATICSHADOWS];
static CPolyBunch *pEmptyBunchList;
static CPermanentShadow aPermanentShadows[MAX_PERMAMENTSHADOWS];
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 (CVehicle *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 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 CastShadowEntityXYZ (CEntity *pEntity, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);
static void UpdateStaticShadows (void);
static void UpdatePermanentShadows (void);
static void CalcPedShadowValues (CVector vecLightDir, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY, float *pfDisplacementX, float *pfDisplacementY);
static void RenderExtraPlayerShadows (void);
static void TidyUpShadows (void);
static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);
};
extern RwTexture *gpShadowCarTex;
extern RwTexture *gpShadowPedTex;
extern RwTexture *gpShadowHeliTex;
extern RwTexture *gpShadowBikeTex;
extern RwTexture *gpShadowBaronTex;
extern RwTexture *gpShadowExplosionTex;
extern RwTexture *gpShadowHeadLightsTex;
extern RwTexture *gpOutline1Tex;
extern RwTexture *gpOutline2Tex;
extern RwTexture *gpOutline3Tex;
extern RwTexture *gpBloodPoolTex;
extern RwTexture *gpReflectionTex;
extern RwTexture *gpWalkDontTex;
extern RwTexture *gpCrackedGlassTex;
extern RwTexture *gpPostShadowTex;
extern RwTexture *gpGoalTex;

259
src/renderer/Skidmarks.cpp Normal file
View File

@ -0,0 +1,259 @@
#include "common.h"
#include "main.h"
#include "TxdStore.h"
#include "Timer.h"
#include "Replay.h"
#include "Skidmarks.h"
CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];
RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];
RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2];
RwTexture *gpSkidTex;
void
CSkidmarks::Init(void)
{
int i, ix, slot;
CTxdStore::PushCurrentTxd();
slot = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slot);
gpSkidTex = RwTextureRead("particleskid", nil);
CTxdStore::PopCurrentTxd();
for(i = 0; i < NUMSKIDMARKS; i++){
aSkidmarks[i].m_state = 0;
aSkidmarks[i].m_wasUpdated = false;
}
ix = 0;
for(i = 0; i < SKIDMARK_LENGTH; i++){
SkidmarkIndexList[i*6+0] = ix+0;
SkidmarkIndexList[i*6+1] = ix+2;
SkidmarkIndexList[i*6+2] = ix+1;
SkidmarkIndexList[i*6+3] = ix+1;
SkidmarkIndexList[i*6+4] = ix+2;
SkidmarkIndexList[i*6+5] = ix+3;
ix += 2;
}
}
void
CSkidmarks::Shutdown(void)
{
RwTextureDestroy(gpSkidTex);
gpSkidTex = nil;
}
void
CSkidmarks::Clear(void)
{
int i;
for(i = 0; i < NUMSKIDMARKS; i++){
aSkidmarks[i].m_state = 0;
aSkidmarks[i].m_wasUpdated = false;
}
}
void
CSkidmarks::Update(void)
{
int i;
uint32 t1 = CTimer::GetTimeInMilliseconds() + 2500;
uint32 t2 = CTimer::GetTimeInMilliseconds() + 5000;
uint32 t3 = CTimer::GetTimeInMilliseconds() + 10000;
uint32 t4 = CTimer::GetTimeInMilliseconds() + 20000;
for(i = 0; i < NUMSKIDMARKS; i++){
switch(aSkidmarks[i].m_state){
case 1:
if(!aSkidmarks[i].m_wasUpdated){
// Didn't continue this one last time, so finish it and set fade times
aSkidmarks[i].m_state = 2;
if(aSkidmarks[i].m_last < 4){
aSkidmarks[i].m_fadeStart = t1;
aSkidmarks[i].m_fadeEnd = t2;
}else if(aSkidmarks[i].m_last < 9){
aSkidmarks[i].m_fadeStart = t2;
aSkidmarks[i].m_fadeEnd = t3;
}else{
aSkidmarks[i].m_fadeStart = t3;
aSkidmarks[i].m_fadeEnd = t4;
}
}
break;
case 2:
if(CTimer::GetTimeInMilliseconds() > aSkidmarks[i].m_fadeEnd)
aSkidmarks[i].m_state = 0;
break;
}
aSkidmarks[i].m_wasUpdated = false;
}
}
void
CSkidmarks::Render(void)
{
int i, j;
PUSH_RENDERGROUP("CSkidmarks::Render");
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;
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;
if(aSkidmarks[i].m_state == 1 || CTimer::GetTimeInMilliseconds() < aSkidmarks[i].m_fadeStart)
fade = 255;
else
fade = 255*(aSkidmarks[i].m_fadeEnd - CTimer::GetTimeInMilliseconds()) / (aSkidmarks[i].m_fadeEnd - aSkidmarks[i].m_fadeStart);
for(j = 0; j <= aSkidmarks[i].m_last; j++){
alpha = 128;
if(j == 0 || j == aSkidmarks[i].m_last && aSkidmarks[i].m_state == 2)
alpha = 0;
alpha = alpha*fade/256;
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);
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();
if(RwIm3DTransform(SkidmarkVertices, 2*(aSkidmarks[i].m_last+1), nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, SkidmarkIndexList, 6*aSkidmarks[i].m_last);
RwIm3DEnd();
}
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
POP_RENDERGROUP();
}
void
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);
if(CReplay::IsPlayingBack())
return;
// Find a skidmark to continue
for(i = 0; i < NUMSKIDMARKS; i++)
if(aSkidmarks[i].m_state == 1 && aSkidmarks[i].m_id == id)
break;
if(i < NUMSKIDMARKS){
// Continue this one
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;
aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;
return;
}
aSkidmarks[i].m_wasUpdated = true;
if(CTimer::GetTimeInMilliseconds() - aSkidmarks[i].m_lastUpdate <= 100){
// Last update was recently, just change last coords
aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
return;
}
aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds();
if(aSkidmarks[i].m_last >= SKIDMARK_LENGTH-1){
// No space to continue, end it
aSkidmarks[i].m_state = 2;
aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;
aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;
*isBloody = false; // stpo blood marks at end
return;
}
aSkidmarks[i].m_last++;
aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
CVector2D right(aSkidmarks[i].m_pos[aSkidmarks[i].m_last].y - aSkidmarks[i].m_pos[aSkidmarks[i].m_last - 1].y,
aSkidmarks[i].m_pos[aSkidmarks[i].m_last - 1].x - aSkidmarks[i].m_pos[aSkidmarks[i].m_last].x);
right.Normalise();
fwd.Normalise();
float turn = DotProduct2D(fwd, right);
turn = Abs(turn) + 1.0f;
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
return;
}
// Start a new one
for(i = 0; i < NUMSKIDMARKS; i++)
if(aSkidmarks[i].m_state == 0)
break;
if(i < NUMSKIDMARKS){
// Found a free slot
aSkidmarks[i].m_state = 1;
aSkidmarks[i].m_id = id;
aSkidmarks[i].m_pos[0] = pos;
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;
if(*isBloody)
aSkidmarks[i].m_type = SKIDMARK_BLOODY;
else
aSkidmarks[i].m_type = type;
}else
*isBloody = false; // stop blood marks if no space
}

41
src/renderer/Skidmarks.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
enum { SKIDMARK_LENGTH = 16 };
enum eSkidmarkType
{
SKIDMARK_NORMAL,
SKIDMARK_MUDDY,
SKIDMARK_SANDY,
SKIDMARK_BLOODY
};
class CSkidmark
{
public:
CVector m_pos[SKIDMARK_LENGTH];
float m_sideX[SKIDMARK_LENGTH];
float m_sideY[SKIDMARK_LENGTH];
uintptr m_id;
uint32 m_lastUpdate;
uint32 m_fadeStart;
uint32 m_fadeEnd;
uint32 m_type;
int16 m_last;
uint8 m_state;
bool m_wasUpdated;
};
class CSkidmarks
{
static CSkidmark aSkidmarks[NUMSKIDMARKS];
public:
static void Init(void);
static void Shutdown(void);
static void Clear(void);
static void Update(void);
static void Render(void);
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);
};

1493
src/renderer/SpecialFX.cpp Normal file

File diff suppressed because it is too large Load Diff

249
src/renderer/SpecialFX.h Normal file
View File

@ -0,0 +1,249 @@
#pragma once
//file done
class CSpecialFX
{
public:
static bool bVideoCam;
static bool bLiftCam;
static bool bSnapShotActive;
static int32 SnapShotFrames;
static void Render(void);
static void Update(void);
static void Init(void);
static void Shutdown(void);
static void AddWeaponStreak(int type);
static void Render2DFXs();
};
class CRegisteredMotionBlurStreak
{
public:
uintptr m_id;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
CVector m_pos1[3];
CVector m_pos2[3];
bool m_isValid[3];
void Update(void);
void Render(void);
};
class CMotionBlurStreaks
{
static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS];
public:
static void Init(void);
static void Update(void);
static void RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2);
static void Render(void);
};
struct CBulletTrace
{
CVector m_vecStartPos;
CVector m_vecEndPos;
bool m_bInUse;
uint32 m_nCreationTime;
uint32 m_nLifeTime;
float m_fThickness;
uint8 m_fVisibility;
void Update(void);
};
class CBulletTraces
{
public:
static CBulletTrace aTraces[NUMBULLETTRACES];
static void Init(void);
static void Render(void);
static void Update(void);
static void AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility);
static void AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter);
};
enum
{
MARKERTYPE_0 = 0,
MARKERTYPE_ARROW,
MARKERTYPE_2,
MARKERTYPE_3,
MARKERTYPE_CYLINDER,
NUMMARKERTYPES,
MARKERTYPE_INVALID = 0x101
};
class C3dMarker
{
public:
CMatrix m_Matrix;
RpAtomic *m_pAtomic;
RpMaterial *m_pMaterial;
uint16 m_nType;
bool m_bIsUsed;
bool m_bFindZOnNextPlacement;
uint32 m_nIdentifier;
RwRGBA m_Color;
uint16 m_nPulsePeriod;
int16 m_nRotateRate;
uint32 m_nStartTime;
float m_fPulseFraction;
float m_fStdSize;
float m_fSize;
float m_fBrightness;
float m_fCameraRange;
bool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
void DeleteMarkerObject();
void Render();
};
class C3dMarkers
{
public:
static void Init();
static void Shutdown();
static C3dMarker *PlaceMarker(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
static void PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
static void Render();
static void Update();
static C3dMarker m_aMarkerArray[NUM3DMARKERS];
static int32 NumActiveMarkers;
static RpClump* m_pRpClumpArray[NUMMARKERTYPES];
};
enum
{
BRIGHTLIGHT_INVALID,
BRIGHTLIGHT_TRAFFIC_GREEN,
BRIGHTLIGHT_TRAFFIC_YELLOW,
BRIGHTLIGHT_TRAFFIC_RED,
// white
BRIGHTLIGHT_FRONT_LONG,
BRIGHTLIGHT_FRONT_SMALL,
BRIGHTLIGHT_FRONT_BIG,
BRIGHTLIGHT_FRONT_TALL,
// red
BRIGHTLIGHT_REAR_LONG,
BRIGHTLIGHT_REAR_SMALL,
BRIGHTLIGHT_REAR_BIG,
BRIGHTLIGHT_REAR_TALL,
BRIGHTLIGHT_SIREN, // unused
BRIGHTLIGHT_FRONT = BRIGHTLIGHT_FRONT_LONG,
BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG,
};
class CBrightLight
{
public:
CVector m_pos;
CVector m_up;
CVector m_side;
CVector m_front;
float m_camDist;
uint8 m_type;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
};
class CBrightLights
{
static int NumBrightLights;
static CBrightLight aBrightLights[NUMBRIGHTLIGHTS];
public:
static void Init(void);
static void RegisterOne(CVector pos, CVector up, CVector side, CVector front,
uint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0);
static void Render(void);
static void RenderOutGeometryBuffer(void);
};
enum
{
SHINYTEXT_WALK = 1,
SHINYTEXT_FLAT
};
class CShinyText
{
public:
CVector m_verts[4];
CVector2D m_texCoords[4];
float m_camDist;
uint8 m_type;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
};
class CShinyTexts
{
static int NumShinyTexts;
static CShinyText aShinyTexts[NUMSHINYTEXTS];
public:
static void Init(void);
static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); //not used
static void Render(void);
static void RenderOutGeometryBuffer(void);
};
class CMoneyMessage
{
friend class CMoneyMessages;
uint32 m_nTimeRegistered;
CVector m_vecPosition;
wchar m_aText[16];
CRGBA m_Colour;
float m_fSize;
float m_fOpacity;
public:
void Render();
};
class CMoneyMessages
{
static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];
public:
static void Init();
static void Render();
static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
};
class CSpecialParticleStuff
{
static uint32 BoatFromStart;
public:
static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); //not used
static void StartBoatFoamAnimation(); //not used
static void UpdateBoatFoamAnimation(CMatrix*); //not used
};

612
src/renderer/Sprite.cpp Normal file
View File

@ -0,0 +1,612 @@
#include "common.h"
#include "main.h"
#include "Draw.h"
#include "Camera.h"
#include "Sprite.h"
float CSprite::m_f2DNearScreenZ;
float CSprite::m_f2DFarScreenZ;
float CSprite::m_fRecipNearClipPlane;
int32 CSprite::m_bFlushSpriteBufferSwitchZTest;
float CalcScreenZ(float z)
{
// LCS TODO: check
if ( z == 0.0f )
return CSprite::GetNearScreenZ();
return (z - CDraw::GetNearClipZ())
* (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ()) * CDraw::GetFarClipZ()
/ ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * z )
+ CSprite::GetNearScreenZ();
}
float
CSprite::CalcHorizonCoors(void)
{
CVector p = TheCamera.GetPosition() + CVector(TheCamera.CamFrontXNorm, TheCamera.CamFrontYNorm, 0.0f)*3000.0f;
p.z = 0.0f;
p = TheCamera.m_viewMatrix * p;
return p.y * SCREEN_HEIGHT / p.z;
}
bool
CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip)
{
CVector viewvec = TheCamera.m_viewMatrix * in;
*out = viewvec;
if(out->z <= CDraw::GetNearClipZ() + 1.0f) return false;
if(out->z >= CDraw::GetFarClipZ() && farclip) return false;
float recip = 1.0f/out->z;
out->x *= SCREEN_WIDTH * recip;
out->y *= SCREEN_HEIGHT * recip;
const float fov = DefaultFOV;
// this is used to scale correctly if you zoom in with sniper rifle
float fovScale = fov / CDraw::GetFOV();
#ifdef FIX_SPRITES
*outw = CDraw::ms_bFixSprites ? (fovScale * recip * SCREEN_HEIGHT) : (fovScale * SCREEN_SCALE_AR(recip) * SCREEN_WIDTH);
#else
*outw = fovScale * SCREEN_SCALE_AR(recip) * SCREEN_WIDTH;
#endif
*outh = fovScale * recip * SCREEN_HEIGHT;
return true;
}
#define SPRITEBUFFERSIZE 64
static int32 nSpriteBufferIndex;
static RwIm2DVertex SpriteBufferVerts[SPRITEBUFFERSIZE*6];
static RwIm2DVertex verts[4];
void
CSprite::InitSpriteBuffer(void)
{
m_f2DNearScreenZ = RwIm2DGetNearScreenZ();
m_f2DFarScreenZ = RwIm2DGetFarScreenZ();
}
void
CSprite::InitSpriteBuffer2D(void)
{
m_fRecipNearClipPlane = 1.0f / RwCameraGetNearClipPlane(Scene.camera);
InitSpriteBuffer();
}
void
CSprite::FlushSpriteBuffer(void)
{
if(nSpriteBufferIndex > 0){
if(m_bFlushSpriteBufferSwitchZTest){
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, SpriteBufferVerts, nSpriteBufferIndex*6);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
}else
RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, SpriteBufferVerts, nSpriteBufferIndex*6);
nSpriteBufferIndex = 0;
}
}
void
CSprite::RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a)
{
static short indices[] = { 0, 1, 2, 3 };
// 0---3
// | |
// 1---2
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x-w; us[0] = 0.0f;
xs[1] = x-w; us[1] = 0.0f;
xs[2] = x+w; us[2] = 1.0f;
xs[3] = x+w; us[3] = 1.0f;
ys[0] = y-h; vs[0] = 0.0f;
ys[1] = y+h; vs[1] = 1.0f;
ys[2] = y+h; vs[2] = 1.0f;
ys[3] = y-h; vs[3] = 0.0f;
// clip
for(i = 0; i < 4; i++){
if(xs[i] < 0.0f){
us[i] = -xs[i] / (2.0f*w);
xs[i] = 0.0f;
}
if(xs[i] > SCREEN_WIDTH){
us[i] = 1.0f - (xs[i]-SCREEN_WIDTH) / (2.0f*w);
xs[i] = SCREEN_WIDTH;
}
if(ys[i] < 0.0f){
vs[i] = -ys[i] / (2.0f*h);
ys[i] = 0.0f;
}
if(ys[i] > SCREEN_HEIGHT){
vs[i] = 1.0f - (ys[i]-SCREEN_HEIGHT) / (2.0f*h);
ys[i] = SCREEN_HEIGHT;
}
}
// (DrawZ - DrawNear)/(DrawFar - DrawNear) = (SpriteZ-SpriteNear)/(SpriteFar-SpriteNear)
// So to calculate SpriteZ:
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
for(i = 0; i < 4; i++){
RwIm2DVertexSetScreenX(&verts[i], xs[i]);
RwIm2DVertexSetScreenY(&verts[i], ys[i]);
RwIm2DVertexSetScreenZ(&verts[i], screenz);
RwIm2DVertexSetCameraZ(&verts[i], z);
RwIm2DVertexSetRecipCameraZ(&verts[i], recipz);
RwIm2DVertexSetIntRGBA(&verts[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&verts[i], us[i], recipz);
RwIm2DVertexSetV(&verts[i], vs[i], recipz);
}
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, verts, 4);
}
void
CSprite::RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)
{
float c = Cos(rotation);
float s = Sin(rotation);
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
// Fade out when too near
// why not in buffered version?
if(z < 2.3f){
if(z < 1.3f)
return;
int f = (z - 1.3f)/(2.3f-1.3f) * 255;
r = f*r >> 8;
g = f*g >> 8;
b = f*b >> 8;
intens = f*intens >> 8;
}
xs[0] = x + w*(-c-s); us[0] = 0.0f;
xs[1] = x + w*(-c+s); us[1] = 0.0f;
xs[2] = x + w*(+c+s); us[2] = 1.0f;
xs[3] = x + w*(+c-s); us[3] = 1.0f;
ys[0] = y + h*(-c+s); vs[0] = 0.0f;
ys[1] = y + h*(+c+s); vs[1] = 1.0f;
ys[2] = y + h*(+c-s); vs[2] = 1.0f;
ys[3] = y + h*(-c-s); vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
for(i = 0; i < 4; i++){
RwIm2DVertexSetScreenX(&verts[i], xs[i]);
RwIm2DVertexSetScreenY(&verts[i], ys[i]);
RwIm2DVertexSetScreenZ(&verts[i], screenz);
RwIm2DVertexSetCameraZ(&verts[i], z);
RwIm2DVertexSetRecipCameraZ(&verts[i], recipz);
RwIm2DVertexSetIntRGBA(&verts[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&verts[i], us[i], recipz);
RwIm2DVertexSetV(&verts[i], vs[i], recipz);
}
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, verts, 4);
}
void
CSprite::RenderBufferedOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
// 0---3
// | |
// 1---2
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x-w; us[0] = 0.0f;
xs[1] = x-w; us[1] = 0.0f;
xs[2] = x+w; us[2] = 1.0f;
xs[3] = x+w; us[3] = 1.0f;
ys[0] = y-h; vs[0] = 0.0f;
ys[1] = y+h; vs[1] = 1.0f;
ys[2] = y+h; vs[2] = 1.0f;
ys[3] = y-h; vs[3] = 0.0f;
// clip
for(i = 0; i < 4; i++){
if(xs[i] < 0.0f){
us[i] = -xs[i] / (2.0f*w);
xs[i] = 0.0f;
}
if(xs[i] > SCREEN_WIDTH){
us[i] = 1.0f - (xs[i]-SCREEN_WIDTH) / (2.0f*w);
xs[i] = SCREEN_WIDTH;
}
if(ys[i] < 0.0f){
vs[i] = -ys[i] / (2.0f*h);
ys[i] = 0.0f;
}
if(ys[i] > SCREEN_HEIGHT){
vs[i] = 1.0f - (ys[i]-SCREEN_HEIGHT) / (2.0f*h);
ys[i] = SCREEN_HEIGHT;
}
}
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
// TODO: replace with lookup
float c = Cos(rotation);
float s = Sin(rotation);
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x - c*w - s*h; us[0] = 0.0f;
xs[1] = x - c*w + s*h; us[1] = 0.0f;
xs[2] = x + c*w + s*h; us[2] = 1.0f;
xs[3] = x + c*w - s*h; us[3] = 1.0f;
ys[0] = y - c*h + s*w; vs[0] = 0.0f;
ys[1] = y + c*h + s*w; vs[1] = 1.0f;
ys[2] = y + c*h - s*w; vs[2] = 1.0f;
ys[3] = y - c*h - s*w; vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
float c = Cos(rotation);
float s = Sin(rotation);
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x + w*(-c-s); us[0] = 0.0f;
xs[1] = x + w*(-c+s); us[1] = 0.0f;
xs[2] = x + w*(+c+s); us[2] = 1.0f;
xs[3] = x + w*(+c-s); us[3] = 1.0f;
ys[0] = y + h*(-c+s); vs[0] = 0.0f;
ys[1] = y + h*(+c+s); vs[1] = 1.0f;
ys[2] = y + h*(+c-s); vs[2] = 1.0f;
ys[3] = y + h*(-c-s); vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
float c = Cos(rotation);
float s = Sin(rotation);
float xs[4];
float ys[4];
float us[4];
float vs[4];
float cf[4];
int i;
xs[0] = x + w*(-c-s); us[0] = 0.0f;
xs[1] = x + w*(-c+s); us[1] = 0.0f;
xs[2] = x + w*(+c+s); us[2] = 1.0f;
xs[3] = x + w*(+c-s); us[3] = 1.0f;
ys[0] = y + h*(-c+s); vs[0] = 0.0f;
ys[1] = y + h*(+c+s); vs[1] = 1.0f;
ys[2] = y + h*(+c-s); vs[2] = 1.0f;
ys[3] = y + h*(-c-s); vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
// Colour factors, cx/y is the direction in which colours change from rgb1 to rgb2
cf[0] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;
cf[0] = Clamp(cf[0], 0.0f, 1.0f);
cf[1] = (cx*(-c+s) + cy*( c+s))*0.5f + 0.5f;
cf[1] = Clamp(cf[1], 0.0f, 1.0f);
cf[2] = (cx*( c+s) + cy*( c-s))*0.5f + 0.5f;
cf[2] = Clamp(cf[2], 0.0f, 1.0f);
cf[3] = (cx*( c-s) + cy*(-c-s))*0.5f + 0.5f;
cf[3] = Clamp(cf[3], 0.0f, 1.0f);
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i],
r1*cf[indices[i]] + r2*(1.0f - cf[indices[i]]),
g1*cf[indices[i]] + g2*(1.0f - cf[indices[i]]),
b1*cf[indices[i]] + b2*(1.0f - cf[indices[i]]),
a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, 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 = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane;
RwIm2DVertexSetScreenX(&verts[0], r.left);
RwIm2DVertexSetScreenY(&verts[0], r.top);
RwIm2DVertexSetScreenZ(&verts[0], screenz);
RwIm2DVertexSetCameraZ(&verts[0], z);
RwIm2DVertexSetRecipCameraZ(&verts[0], recipz);
RwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a);
RwIm2DVertexSetU(&verts[0], 0.0f, recipz);
RwIm2DVertexSetV(&verts[0], 0.0f, recipz);
RwIm2DVertexSetScreenX(&verts[1], r.right);
RwIm2DVertexSetScreenY(&verts[1], r.top);
RwIm2DVertexSetScreenZ(&verts[1], screenz);
RwIm2DVertexSetCameraZ(&verts[1], z);
RwIm2DVertexSetRecipCameraZ(&verts[1], recipz);
RwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a);
RwIm2DVertexSetU(&verts[1], 1.0f, recipz);
RwIm2DVertexSetV(&verts[1], 0.0f, recipz);
RwIm2DVertexSetScreenX(&verts[2], r.right);
RwIm2DVertexSetScreenY(&verts[2], r.bottom);
RwIm2DVertexSetScreenZ(&verts[2], screenz);
RwIm2DVertexSetCameraZ(&verts[2], z);
RwIm2DVertexSetRecipCameraZ(&verts[2], recipz);
RwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&verts[2], 1.0f, recipz);
RwIm2DVertexSetV(&verts[2], 1.0f, recipz);
RwIm2DVertexSetScreenX(&verts[3], r.left);
RwIm2DVertexSetScreenY(&verts[3], r.bottom);
RwIm2DVertexSetScreenZ(&verts[3], screenz);
RwIm2DVertexSetCameraZ(&verts[3], z);
RwIm2DVertexSetRecipCameraZ(&verts[3], recipz);
RwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a);
RwIm2DVertexSetU(&verts[3], 0.0f, recipz);
RwIm2DVertexSetV(&verts[3], 1.0f, recipz);
RwIm2DVertexSetScreenX(&verts[4], r.left);
RwIm2DVertexSetScreenY(&verts[4], r.top);
RwIm2DVertexSetScreenZ(&verts[4], screenz);
RwIm2DVertexSetCameraZ(&verts[4], z);
RwIm2DVertexSetRecipCameraZ(&verts[4], recipz);
RwIm2DVertexSetIntRGBA(&verts[4], c2.r, c2.g, c2.b, c2.a);
RwIm2DVertexSetU(&verts[4], 0.0f, recipz);
RwIm2DVertexSetV(&verts[4], 0.0f, recipz);
RwIm2DVertexSetScreenX(&verts[5], r.right);
RwIm2DVertexSetScreenY(&verts[5], r.bottom);
RwIm2DVertexSetScreenZ(&verts[5], screenz);
RwIm2DVertexSetCameraZ(&verts[5], z);
RwIm2DVertexSetRecipCameraZ(&verts[5], recipz);
RwIm2DVertexSetIntRGBA(&verts[5], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&verts[5], 1.0f, recipz);
RwIm2DVertexSetV(&verts[5], 1.0f, recipz);
}
void
CSprite::Set6Vertices2D(RwIm2DVertex *verts, 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 = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane;
RwIm2DVertexSetScreenX(&verts[0], x3);
RwIm2DVertexSetScreenY(&verts[0], y3);
RwIm2DVertexSetScreenZ(&verts[0], screenz);
RwIm2DVertexSetCameraZ(&verts[0], z);
RwIm2DVertexSetRecipCameraZ(&verts[0], recipz);
RwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a);
RwIm2DVertexSetU(&verts[0], 0.0f, recipz);
RwIm2DVertexSetV(&verts[0], 0.0f, recipz);
RwIm2DVertexSetScreenX(&verts[1], x4);
RwIm2DVertexSetScreenY(&verts[1], y4);
RwIm2DVertexSetScreenZ(&verts[1], screenz);
RwIm2DVertexSetCameraZ(&verts[1], z);
RwIm2DVertexSetRecipCameraZ(&verts[1], recipz);
RwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a);
RwIm2DVertexSetU(&verts[1], 1.0f, recipz);
RwIm2DVertexSetV(&verts[1], 0.0f, recipz);
RwIm2DVertexSetScreenX(&verts[2], x2);
RwIm2DVertexSetScreenY(&verts[2], y2);
RwIm2DVertexSetScreenZ(&verts[2], screenz);
RwIm2DVertexSetCameraZ(&verts[2], z);
RwIm2DVertexSetRecipCameraZ(&verts[2], recipz);
RwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&verts[2], 1.0f, recipz);
RwIm2DVertexSetV(&verts[2], 1.0f, recipz);
RwIm2DVertexSetScreenX(&verts[3], x1);
RwIm2DVertexSetScreenY(&verts[3], y1);
RwIm2DVertexSetScreenZ(&verts[3], screenz);
RwIm2DVertexSetCameraZ(&verts[3], z);
RwIm2DVertexSetRecipCameraZ(&verts[3], recipz);
RwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a);
RwIm2DVertexSetU(&verts[3], 0.0f, recipz);
RwIm2DVertexSetV(&verts[3], 1.0f, recipz);
RwIm2DVertexSetScreenX(&verts[4], x3);
RwIm2DVertexSetScreenY(&verts[4], y3);
RwIm2DVertexSetScreenZ(&verts[4], screenz);
RwIm2DVertexSetCameraZ(&verts[4], z);
RwIm2DVertexSetRecipCameraZ(&verts[4], recipz);
RwIm2DVertexSetIntRGBA(&verts[4], c2.r, c2.g, c2.b, c2.a);
RwIm2DVertexSetU(&verts[4], 0.0f, recipz);
RwIm2DVertexSetV(&verts[4], 0.0f, recipz);
RwIm2DVertexSetScreenX(&verts[5], x2);
RwIm2DVertexSetScreenY(&verts[5], y2);
RwIm2DVertexSetScreenZ(&verts[5], screenz);
RwIm2DVertexSetCameraZ(&verts[5], z);
RwIm2DVertexSetRecipCameraZ(&verts[5], recipz);
RwIm2DVertexSetIntRGBA(&verts[5], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&verts[5], 1.0f, recipz);
RwIm2DVertexSetV(&verts[5], 1.0f, recipz);
}
void
CSprite::RenderBufferedOneXLUSprite2D(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, uint8 alpha)
{
m_bFlushSpriteBufferSwitchZTest = 1;
CRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha);
CRect rect(x - w, y - h, x + h, y + h);
Set6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex], rect, col, col, col, col);
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, float rotation, uint8 alpha)
{
m_bFlushSpriteBufferSwitchZTest = 1;
CRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha);
float c = Cos(rotation);
float s = Sin(rotation);
Set6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex],
x + c*w - s*h,
y - c*h - s*w,
x + c*w + s*h,
y + c*h - s*w,
x - c*w - s*h,
y - c*h + s*w,
x - c*w + s*h,
y + c*h + s*w,
col, col, col, col);
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}

33
src/renderer/Sprite.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
class CSprite
{
static float m_f2DNearScreenZ;
static float m_f2DFarScreenZ;
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);
static void InitSpriteBuffer2D(void);
static void FlushSpriteBuffer(void);
static void RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a);
static void RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float roll, uint8 a);
static void RenderBufferedOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a);
static void RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float roll, uint8 a);
static void RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float roll, uint8 a);
// cx/y is the direction in which the colour changes
static void RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a);
static void Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
static void Set6Vertices2D(RwIm2DVertex *verts, 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 RenderBufferedOneXLUSprite2D(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, uint8 alpha);
static void RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, float rotation, uint8 alpha);
};
extern float CalcScreenZ(float z);

434
src/renderer/Sprite2d.cpp Normal file
View File

@ -0,0 +1,434 @@
#include "common.h"
#include "main.h"
#include "Draw.h"
#include "Camera.h"
#include "Sprite2d.h"
#include "Font.h"
#include "RenderBuffer.h"
float CSprite2d::RecipNearClip;
float CSprite2d::NearScreenZ;
float CSprite2d::NearCamZ;
int CSprite2d::nextBufferVertex;
int CSprite2d::nextBufferIndex;
RwIm2DVertex CSprite2d::maVertices[8];
void
CSprite2d::SetRecipNearClip(void)
{
// Used but empty in VC, instead they set in InitPerFrame. Isn't that great?
}
void
CSprite2d::InitPerFrame(void)
{
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)
{
if(m_pTexture){
RwTextureDestroy(m_pTexture);
m_pTexture = nil;
}
}
void
CSprite2d::SetTexture(const char *name)
{
Delete();
if(name)
m_pTexture = RwTextureRead(name, nil);
}
void
CSprite2d::SetTexture(const char *name, const char *mask)
{
Delete();
if(name)
m_pTexture = RwTextureRead(name, mask);
}
void
CSprite2d::SetAddressing(RwTextureAddressMode addr)
{
if(m_pTexture)
RwTextureSetAddressing(m_pTexture, addr);
}
void
CSprite2d::SetRenderState(void)
{
if(m_pTexture)
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(m_pTexture));
else
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
}
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);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
void
CSprite2d::Draw(const CRect &rect, const CRGBA &col)
{
SetVertices(rect, col, col, col, col);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
void
CSprite2d::Draw(const CRect &rect, const CRGBA &col,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
{
SetVertices(rect, col, col, col, col, u0, v0, u1, v1, u3, v3, u2, v2);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
void
CSprite2d::Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
SetVertices(rect, c0, c1, c2, c3);
SetRenderState();
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
void
CSprite2d::Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &col)
{
SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, col, col, col, col);
SetRenderState();
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)
{
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], 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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[0], 0.0f+offset, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
RwIm2DVertexSetScreenY(&maVertices[1], r.top);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[1], 0.0f+offset, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
RwIm2DVertexSetScreenY(&maVertices[2], r.bottom);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[2], 1.0f+offset, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
RwIm2DVertexSetScreenY(&maVertices[3], r.bottom);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[3], 1.0f+offset, 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)
{
// This is what we draw:
// 0---1
// | / |
// 3---2
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
RwIm2DVertexSetScreenY(&maVertices[0], r.top);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[0], v0, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
RwIm2DVertexSetScreenY(&maVertices[1], r.top);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[1], v1, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
RwIm2DVertexSetScreenY(&maVertices[2], r.bottom);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[2], v2, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
RwIm2DVertexSetScreenY(&maVertices[3], r.bottom);
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, 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)
{
RwIm2DVertexSetScreenX(&maVertices[0], x3);
RwIm2DVertexSetScreenY(&maVertices[0], y3);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[0], 0.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[1], x4);
RwIm2DVertexSetScreenY(&maVertices[1], y4);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[1], 0.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[2], x2);
RwIm2DVertexSetScreenY(&maVertices[2], y2);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[2], 1.0f, RecipNearClip);
RwIm2DVertexSetScreenX(&maVertices[3], x1);
RwIm2DVertexSetScreenY(&maVertices[3], y1);
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, RecipNearClip);
RwIm2DVertexSetV(&maVertices[3], 1.0f, RecipNearClip);
}
void
CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col)
{
int i;
for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
RwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]);
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], RecipNearClip);
RwIm2DVertexSetV(&maVertices[i], uvs[i*2 + 1], RecipNearClip);
}
}
void
CSprite2d::SetMaskVertices(int n, float *positions)
{
int i;
for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
RwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]);
RwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ);
RwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ);
RwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip);
#if !defined(GTA_PS2_STUFF) && defined(RWLIBS)
RwIm2DVertexSetIntRGBA(&maVertices[i], 0, 0, 0, 0);
#else
RwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255);
#endif
}
}
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)
{
RwIm2DVertexSetScreenX(&verts[0], r.left);
RwIm2DVertexSetScreenY(&verts[0], r.top);
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, 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], NearScreenZ);
RwIm2DVertexSetCameraZ(&verts[2], NearCamZ);
RwIm2DVertexSetRecipCameraZ(&verts[2], RecipNearClip);
RwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&verts[2], u2, RecipNearClip);
RwIm2DVertexSetV(&verts[2], v2, RecipNearClip);
RwIm2DVertexSetScreenX(&verts[3], r.left);
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);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(col.a != 255));
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
}
void
CSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
SetVertices(r, c0, c1, c2, c3);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
void
CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
SetVertices(r, c0, c1, c2, c3);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
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);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
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;
}
}

54
src/renderer/Sprite2d.h Normal file
View File

@ -0,0 +1,54 @@
#pragma once
class CSprite2d
{
static float RecipNearClip;
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);
CSprite2d(void) : m_pTexture(nil) {};
~CSprite2d(void) { Delete(); };
void Delete(void);
void SetRenderState(void);
void SetTexture(const char *name);
void SetTexture(const char *name, const char *mask);
void SetAddressing(RwTextureAddressMode addr);
void Draw(float x, float y, float w, float h, const CRGBA &col);
void Draw(const CRect &rect, const CRGBA &col);
void Draw(const CRect &rect, const CRGBA &col,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2);
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);
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,
const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);
static void SetVertices(int n, float *positions, float *uvs, const CRGBA &col);
static void SetMaskVertices(int n, float *positions);
static void 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);
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();
};

41
src/renderer/TexList.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "common.h"
#include "TexList.h"
#include "rtbmp.h"
#include "FileMgr.h"
bool CTexList::ms_nTexUsed[MAX_TEXUSED];
void
CTexList::Initialise()
{}
void
CTexList::Shutdown()
{}
RwTexture *
CTexList::SetTexture(int32 slot, char *name)
{
return nil;
}
int32
CTexList::GetFirstFreeTexture()
{
for (int32 i = 0; i < MAX_TEXUSED; i++)
if (!ms_nTexUsed[i])
return i;
return -1;
}
RwTexture *
CTexList::LoadFileNameTexture(char *name)
{
return SetTexture(GetFirstFreeTexture(), name);
}
void
CTexList::LoadGlobalTextureList()
{
CFileMgr::SetDir("TEXTURES");
}

14
src/renderer/TexList.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
class CTexList
{
enum { MAX_TEXUSED = 400, };
static bool ms_nTexUsed[MAX_TEXUSED];
public:
static void Initialise();
static void Shutdown();
static RwTexture *SetTexture(int32 slot, char *name);
static int32 GetFirstFreeTexture();
static RwTexture *LoadFileNameTexture(char *name);
static void LoadGlobalTextureList();
};

696
src/renderer/Timecycle.cpp Normal file
View File

@ -0,0 +1,696 @@
#include "common.h"
#include "main.h"
#include "Clock.h"
#include "Weather.h"
#include "Camera.h"
#include "Shadows.h"
#include "ZoneCull.h"
#include "CutsceneMgr.h"
#include "FileMgr.h"
#include "Timecycle.h"
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;
int32 CTimeCycle::m_nCurrentSkyTopRed;
int32 CTimeCycle::m_nCurrentSkyTopGreen;
int32 CTimeCycle::m_nCurrentSkyTopBlue;
int32 CTimeCycle::m_nCurrentSkyBottomRed;
int32 CTimeCycle::m_nCurrentSkyBottomGreen;
int32 CTimeCycle::m_nCurrentSkyBottomBlue;
int32 CTimeCycle::m_nCurrentSunCoreRed;
int32 CTimeCycle::m_nCurrentSunCoreGreen;
int32 CTimeCycle::m_nCurrentSunCoreBlue;
int32 CTimeCycle::m_nCurrentSunCoronaRed;
int32 CTimeCycle::m_nCurrentSunCoronaGreen;
int32 CTimeCycle::m_nCurrentSunCoronaBlue;
float CTimeCycle::m_fCurrentSunSize;
float CTimeCycle::m_fCurrentSpriteSize;
float CTimeCycle::m_fCurrentSpriteBrightness;
int32 CTimeCycle::m_nCurrentShadowStrength;
int32 CTimeCycle::m_nCurrentLightShadowStrength;
int32 CTimeCycle::m_nCurrentPoleShadowStrength;
float CTimeCycle::m_fCurrentFogStart;
float CTimeCycle::m_fCurrentFarClip;
float CTimeCycle::m_fCurrentLightsOnGroundBrightness;
int32 CTimeCycle::m_nCurrentLowCloudsRed;
int32 CTimeCycle::m_nCurrentLowCloudsGreen;
int32 CTimeCycle::m_nCurrentLowCloudsBlue;
int32 CTimeCycle::m_nCurrentFluffyCloudsTopRed;
int32 CTimeCycle::m_nCurrentFluffyCloudsTopGreen;
int32 CTimeCycle::m_nCurrentFluffyCloudsTopBlue;
int32 CTimeCycle::m_nCurrentFluffyCloudsBottomRed;
int32 CTimeCycle::m_nCurrentFluffyCloudsBottomGreen;
int32 CTimeCycle::m_nCurrentFluffyCloudsBottomBlue;
float CTimeCycle::m_fCurrentBlurRed;
float CTimeCycle::m_fCurrentBlurGreen;
float CTimeCycle::m_fCurrentBlurBlue;
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];
float CTimeCycle::m_fShadowFrontX[16];
float CTimeCycle::m_fShadowFrontY[16];
float CTimeCycle::m_fShadowSideX[16];
float CTimeCycle::m_fShadowSideY[16];
float CTimeCycle::m_fShadowDisplacementX[16];
float CTimeCycle::m_fShadowDisplacementY[16];
static float tmp_nAmbientRed[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
static float tmp_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
static float tmp_nDirectionalRed[NUMHOURS][NUMWEATHERS];
static float tmp_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nSkyTopRed[NUMHOURS][NUMWEATHERS];
static float tmp_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
static float tmp_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nSunCoreRed[NUMHOURS][NUMWEATHERS];
static float tmp_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
static float tmp_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
static float tmp_fSunSize[NUMHOURS][NUMWEATHERS];
static float tmp_fSpriteSize[NUMHOURS][NUMWEATHERS];
static float tmp_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
static float tmp_nShadowStrength[NUMHOURS][NUMWEATHERS];
static float tmp_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
static float tmp_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
static float tmp_fFogStart[NUMHOURS][NUMWEATHERS];
static float tmp_fFarClip[NUMHOURS][NUMWEATHERS];
static float tmp_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
static float tmp_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
static float tmp_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
static float tmp_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
static float tmp_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
static float tmp_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
static float tmp_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
static float tmp_fBlurRed[NUMHOURS][NUMWEATHERS];
static float tmp_fBlurGreen[NUMHOURS][NUMWEATHERS];
static float tmp_fBlurBlue[NUMHOURS][NUMWEATHERS];
static float tmp_fWaterRed[NUMHOURS][NUMWEATHERS];
static float tmp_fWaterGreen[NUMHOURS][NUMWEATHERS];
static float tmp_fWaterBlue[NUMHOURS][NUMWEATHERS];
static float tmp_fWaterAlpha[NUMHOURS][NUMWEATHERS];
void
CTimeCycle::Initialise(void)
{
int w, h;
int li, bi;
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, poleShad;
float farClp, fogSt, lightGnd;
int cloudR, cloudG, cloudB;
int fluffyTopR, fluffyTopG, fluffyTopB;
int fluffyBotR, fluffyBotG, fluffyBotB;
float blurR, blurG, blurB;
float waterR, waterG, waterB, waterA;
debug("Intialising CTimeCycle...\n");
CFileMgr::SetDir("DATA");
CFileMgr::LoadFile("TIMECYC.DAT", work_buff, sizeof(work_buff), "rb");
CFileMgr::SetDir("");
line[0] = '\0';
bi = 0;
for(w = 0; w < NUMWEATHERS; w++)
for(h = 0; h < NUMHOURS; h++){
li = 0;
while(work_buff[bi] == '/' || work_buff[bi] == '\n' ||
work_buff[bi] == '\0' || work_buff[bi] == '\r'){
while(work_buff[bi] != '\n' && work_buff[bi] != '\0' && work_buff[bi] != '\r')
bi++;
bi++;
}
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 %f %f %f",
&ambR, &ambG, &ambB,
&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, &poleShad,
&farClp, &fogSt, &lightGnd,
&cloudR, &cloudG, &cloudB,
&fluffyTopR, &fluffyTopG, &fluffyTopB,
&fluffyBotR, &fluffyBotG, &fluffyBotB,
&blurR, &blurG, &blurB,
&waterR, &waterG, &waterB, &waterA);
tmp_nAmbientRed[h][w] = ambR;
tmp_nAmbientGreen[h][w] = ambG;
tmp_nAmbientBlue[h][w] = ambB;
tmp_nAmbientRed_Obj[h][w] = ambobjR;
tmp_nAmbientGreen_Obj[h][w] = ambobjG;
tmp_nAmbientBlue_Obj[h][w] = ambobjB;
tmp_nAmbientRed_Bl[h][w] = ambblR;
tmp_nAmbientGreen_Bl[h][w] = ambblG;
tmp_nAmbientBlue_Bl[h][w] = ambblB;
tmp_nAmbientRed_Obj_Bl[h][w] = ambobjblR;
tmp_nAmbientGreen_Obj_Bl[h][w] = ambobjblG;
tmp_nAmbientBlue_Obj_Bl[h][w] = ambobjblB;
tmp_nDirectionalRed[h][w] = dirR;
tmp_nDirectionalGreen[h][w] = dirG;
tmp_nDirectionalBlue[h][w] = dirB;
tmp_nSkyTopRed[h][w] = skyTopR;
tmp_nSkyTopGreen[h][w] = skyTopG;
tmp_nSkyTopBlue[h][w] = skyTopB;
tmp_nSkyBottomRed[h][w] = skyBotR;
tmp_nSkyBottomGreen[h][w] = skyBotG;
tmp_nSkyBottomBlue[h][w] = skyBotB;
tmp_nSunCoreRed[h][w] = sunCoreR;
tmp_nSunCoreGreen[h][w] = sunCoreG;
tmp_nSunCoreBlue[h][w] = sunCoreB;
tmp_nSunCoronaRed[h][w] = sunCoronaR;
tmp_nSunCoronaGreen[h][w] = sunCoronaG;
tmp_nSunCoronaBlue[h][w] = sunCoronaB;
if(sunSz == -1)
tmp_fSunSize[h][w] = -1;
else
tmp_fSunSize[h][w] = sunSz * 10.0f;
if(sprSz == -1)
tmp_fSpriteSize[h][w] = -1;
else
tmp_fSpriteSize[h][w] = sprSz * 10.0f;
if(sprBght == -1)
tmp_fSpriteBrightness[h][w] = -1;
else
tmp_fSpriteBrightness[h][w] = sprBght * 10.0f;
tmp_nShadowStrength[h][w] = shad;
tmp_nLightShadowStrength[h][w] = lightShad;
tmp_nPoleShadowStrength[h][w] = poleShad;
tmp_fFarClip[h][w] = farClp;
tmp_fFogStart[h][w] = fogSt;
if(lightGnd == -1)
tmp_fLightsOnGroundBrightness[h][w] = -1;
else
tmp_fLightsOnGroundBrightness[h][w] = lightGnd * 10.0f;
tmp_nLowCloudsRed[h][w] = cloudR;
tmp_nLowCloudsGreen[h][w] = cloudG;
tmp_nLowCloudsBlue[h][w] = cloudB;
tmp_nFluffyCloudsTopRed[h][w] = fluffyTopR;
tmp_nFluffyCloudsTopGreen[h][w] = fluffyTopG;
tmp_nFluffyCloudsTopBlue[h][w] = fluffyTopB;
tmp_nFluffyCloudsBottomRed[h][w] = fluffyBotR;
tmp_nFluffyCloudsBottomGreen[h][w] = fluffyBotG;
tmp_nFluffyCloudsBottomBlue[h][w] = fluffyBotB;
tmp_fBlurRed[h][w] = blurR;
tmp_fBlurGreen[h][w] = blurG;
tmp_fBlurBlue[h][w] = blurB;
tmp_fWaterRed[h][w] = waterR;
tmp_fWaterGreen[h][w] = waterG;
tmp_fWaterBlue[h][w] = waterB;
tmp_fWaterAlpha[h][w] = waterA;
}
UpdateArrays();
m_FogReduction = 0;
debug("CTimeCycle ready\n");
}
template<typename T> void
FillGaps(T (*out)[NUMWEATHERS], float (*in)[NUMWEATHERS])
{
int w;
for(w = 0; w < NUMWEATHERS; w++){
for(int h = 0; h < NUMHOURS; h++)
out[h][w] = in[h][w];
#define NEXT(h) (((h)+1)%NUMHOURS)
#define PREV(h) (((h)+NUMHOURS-1)%NUMHOURS)
int hend, h1, h2;
for(hend = 0; hend < NUMHOURS; hend++)
if(in[hend][w] != -1.0f)
goto foundstart;
return; // this should never happen
foundstart:
// Found the start of a block of filled in entries
for(h1 = NEXT(hend); h1 != hend; h1 = h2){
// Skip filled in entries
for(; h1 != hend; h1 = NEXT(h1))
if(in[h1][w] == -1.0f)
goto foundfirst;
break; // all filled in already
foundfirst:
// h1 is now the first -1 after n filled in values
for(h2 = NEXT(h1); ; h2 = NEXT(h2))
if(in[h2][w] != -1.0f)
goto foundlast;
break;
foundlast:
// h2 is now the first entry after a row of -1s
h1 = PREV(h1); // make h1 the first before a row of -1s
int n = (h2-h1 + NUMHOURS) % NUMHOURS;
if(n == 0) n = NUMHOURS; // can't happen
float step = (in[h2][w] - in[h1][w])/n;
for(int i = 1; i < n; i++){
float f = (float)i/n;
out[(h1+i)%NUMHOURS][w] = in[h2][w]*f + in[h1][w]*(1.0f-f);
}
}
}
}
void
CTimeCycle::UpdateArrays(void)
{
FillGaps(m_nAmbientRed, tmp_nAmbientRed);
FillGaps(m_nAmbientGreen, tmp_nAmbientGreen);
FillGaps(m_nAmbientBlue, tmp_nAmbientBlue);
FillGaps(m_nAmbientRed_Obj, tmp_nAmbientRed_Obj);
FillGaps(m_nAmbientGreen_Obj, tmp_nAmbientGreen_Obj);
FillGaps(m_nAmbientBlue_Obj, tmp_nAmbientBlue_Obj);
FillGaps(m_nAmbientRed_Bl, tmp_nAmbientRed_Bl);
FillGaps(m_nAmbientGreen_Bl, tmp_nAmbientGreen_Bl);
FillGaps(m_nAmbientBlue_Bl, tmp_nAmbientBlue_Bl);
FillGaps(m_nAmbientRed_Obj_Bl, tmp_nAmbientRed_Obj_Bl);
FillGaps(m_nAmbientGreen_Obj_Bl, tmp_nAmbientGreen_Obj_Bl);
FillGaps(m_nAmbientBlue_Obj_Bl, tmp_nAmbientBlue_Obj_Bl);
FillGaps(m_nDirectionalRed, tmp_nDirectionalRed);
FillGaps(m_nDirectionalGreen, tmp_nDirectionalGreen);
FillGaps(m_nDirectionalBlue, tmp_nDirectionalBlue);
FillGaps(m_nSkyTopRed, tmp_nSkyTopRed);
FillGaps(m_nSkyTopGreen, tmp_nSkyTopGreen);
FillGaps(m_nSkyTopBlue, tmp_nSkyTopBlue);
FillGaps(m_nSkyBottomRed, tmp_nSkyBottomRed);
FillGaps(m_nSkyBottomGreen, tmp_nSkyBottomGreen);
FillGaps(m_nSkyBottomBlue, tmp_nSkyBottomBlue);
FillGaps(m_nSunCoreRed, tmp_nSunCoreRed);
FillGaps(m_nSunCoreGreen, tmp_nSunCoreGreen);
FillGaps(m_nSunCoreBlue, tmp_nSunCoreBlue);
FillGaps(m_nSunCoronaRed, tmp_nSunCoronaRed);
FillGaps(m_nSunCoronaGreen, tmp_nSunCoronaGreen);
FillGaps(m_nSunCoronaBlue, tmp_nSunCoronaBlue);
FillGaps(m_fSunSize, tmp_fSunSize);
FillGaps(m_fSpriteSize, tmp_fSpriteSize);
FillGaps(m_fSpriteBrightness, tmp_fSpriteBrightness);
FillGaps(m_nShadowStrength, tmp_nShadowStrength);
FillGaps(m_nLightShadowStrength, tmp_nLightShadowStrength);
FillGaps(m_nPoleShadowStrength, tmp_nPoleShadowStrength);
FillGaps(m_fFogStart, tmp_fFogStart);
FillGaps(m_fFarClip, tmp_fFarClip);
FillGaps(m_fLightsOnGroundBrightness, tmp_fLightsOnGroundBrightness);
FillGaps(m_nLowCloudsRed, tmp_nLowCloudsRed);
FillGaps(m_nLowCloudsGreen, tmp_nLowCloudsGreen);
FillGaps(m_nLowCloudsBlue, tmp_nLowCloudsBlue);
FillGaps(m_nFluffyCloudsTopRed, tmp_nFluffyCloudsTopRed);
FillGaps(m_nFluffyCloudsTopGreen, tmp_nFluffyCloudsTopGreen);
FillGaps(m_nFluffyCloudsTopBlue, tmp_nFluffyCloudsTopBlue);
FillGaps(m_nFluffyCloudsBottomRed, tmp_nFluffyCloudsBottomRed);
FillGaps(m_nFluffyCloudsBottomGreen, tmp_nFluffyCloudsBottomGreen);
FillGaps(m_nFluffyCloudsBottomBlue, tmp_nFluffyCloudsBottomBlue);
FillGaps(m_fBlurRed, tmp_fBlurRed);
FillGaps(m_fBlurGreen, tmp_fBlurGreen);
FillGaps(m_fBlurBlue, tmp_fBlurBlue);
FillGaps(m_fWaterRed, tmp_fWaterRed);
FillGaps(m_fWaterGreen, tmp_fWaterGreen);
FillGaps(m_fWaterBlue, tmp_fWaterBlue);
FillGaps(m_fWaterAlpha, tmp_fWaterAlpha);
}
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)
{
int h1 = CClock::GetHours();
int h2 = (h1+1)%24;
int w1 = CWeather::OldWeatherType;
int w2 = CWeather::NewWeatherType;
float timeInterp = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f;
// coefficients for a bilinear interpolation
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) Interpolate(v[h1], v[h2])
m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed);
m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen);
m_nCurrentSkyTopBlue = INTERP(m_nSkyTopBlue);
m_nCurrentSkyBottomRed = INTERP(m_nSkyBottomRed);
m_nCurrentSkyBottomGreen = INTERP(m_nSkyBottomGreen);
m_nCurrentSkyBottomBlue = INTERP(m_nSkyBottomBlue);
m_fCurrentAmbientRed = INTERP(m_nAmbientRed);
m_fCurrentAmbientGreen = INTERP(m_nAmbientGreen);
m_fCurrentAmbientBlue = INTERP(m_nAmbientBlue);
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_nCurrentSunCoreRed = INTERP(m_nSunCoreRed);
m_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen);
m_nCurrentSunCoreBlue = INTERP(m_nSunCoreBlue);
m_nCurrentSunCoronaRed = INTERP(m_nSunCoronaRed);
m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen);
m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue);
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_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength);
m_fCurrentFarClip = INTERP(m_fFarClip);
m_fCurrentFogStart = INTERP(m_fFogStart);
m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness)/10.0f;
m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed);
m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen);
m_nCurrentLowCloudsBlue = INTERP(m_nLowCloudsBlue);
m_nCurrentFluffyCloudsTopRed = INTERP(m_nFluffyCloudsTopRed);
m_nCurrentFluffyCloudsTopGreen = INTERP(m_nFluffyCloudsTopGreen);
m_nCurrentFluffyCloudsTopBlue = INTERP(m_nFluffyCloudsTopBlue);
m_nCurrentFluffyCloudsBottomRed = INTERP(m_nFluffyCloudsBottomRed);
m_nCurrentFluffyCloudsBottomGreen = INTERP(m_nFluffyCloudsBottomGreen);
m_nCurrentFluffyCloudsBottomBlue = INTERP(m_nFluffyCloudsBottomBlue);
m_fCurrentBlurRed = INTERP(m_fBlurRed);
m_fCurrentBlurGreen = INTERP(m_fBlurGreen);
m_fCurrentBlurBlue = INTERP(m_fBlurBlue);
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_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF;
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],
&m_fShadowDisplacementX[m_CurrentStoredValue], &m_fShadowDisplacementY[m_CurrentStoredValue]);
if(TheCamera.GetForward().z < -0.9f ||
!CWeather::bScriptsForceRain && (CCullZones::PlayerNoRain() || CCullZones::CamNoRain() || CCutsceneMgr::IsRunning()))
m_FogReduction = Min(m_FogReduction+1, 64);
else
m_FogReduction = Max(m_FogReduction-1, 0);
}

202
src/renderer/Timecycle.h Normal file
View File

@ -0,0 +1,202 @@
#pragma once
class CTimeCycle
{
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;
static int32 m_nCurrentSkyTopRed;
static int32 m_nCurrentSkyTopGreen;
static int32 m_nCurrentSkyTopBlue;
static int32 m_nCurrentSkyBottomRed;
static int32 m_nCurrentSkyBottomGreen;
static int32 m_nCurrentSkyBottomBlue;
static int32 m_nCurrentSunCoreRed;
static int32 m_nCurrentSunCoreGreen;
static int32 m_nCurrentSunCoreBlue;
static int32 m_nCurrentSunCoronaRed;
static int32 m_nCurrentSunCoronaGreen;
static int32 m_nCurrentSunCoronaBlue;
static float m_fCurrentSunSize;
static float m_fCurrentSpriteSize;
static float m_fCurrentSpriteBrightness;
static int32 m_nCurrentShadowStrength;
static int32 m_nCurrentLightShadowStrength;
static int32 m_nCurrentPoleShadowStrength;
static float m_fCurrentFogStart;
static float m_fCurrentFarClip;
static float m_fCurrentLightsOnGroundBrightness;
static int32 m_nCurrentLowCloudsRed;
static int32 m_nCurrentLowCloudsGreen;
static int32 m_nCurrentLowCloudsBlue;
static int32 m_nCurrentFluffyCloudsTopRed;
static int32 m_nCurrentFluffyCloudsTopGreen;
static int32 m_nCurrentFluffyCloudsTopBlue;
static int32 m_nCurrentFluffyCloudsBottomRed;
static int32 m_nCurrentFluffyCloudsBottomGreen;
static int32 m_nCurrentFluffyCloudsBottomBlue;
static float m_fCurrentBlurRed;
static float m_fCurrentBlurGreen;
static float m_fCurrentBlurBlue;
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;
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];
static float m_fShadowFrontY[16];
static float m_fShadowSideX[16];
static float m_fShadowSideY[16];
static float m_fShadowDisplacementX[16];
static float m_fShadowDisplacementY[16];
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; }
static int32 GetSkyTopRed(void) { return m_nCurrentSkyTopRed; }
static int32 GetSkyTopGreen(void) { return m_nCurrentSkyTopGreen; }
static int32 GetSkyTopBlue(void) { return m_nCurrentSkyTopBlue; }
static int32 GetSkyBottomRed(void) { return m_nCurrentSkyBottomRed; }
static int32 GetSkyBottomGreen(void) { return m_nCurrentSkyBottomGreen; }
static int32 GetSkyBottomBlue(void) { return m_nCurrentSkyBottomBlue; }
static int32 GetSunCoreRed(void) { return m_nCurrentSunCoreRed; }
static int32 GetSunCoreGreen(void) { return m_nCurrentSunCoreGreen; }
static int32 GetSunCoreBlue(void) { return m_nCurrentSunCoreBlue; }
static int32 GetSunCoronaRed(void) { return m_nCurrentSunCoronaRed; }
static int32 GetSunCoronaGreen(void) { return m_nCurrentSunCoronaGreen; }
static int32 GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }
static float GetSunSize(void) { return m_fCurrentSunSize; }
static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; }
static float GetSpriteSize(void) { return m_fCurrentSpriteSize; }
static int32 GetShadowStrength(void) { return m_nCurrentShadowStrength; }
static int32 GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }
static float GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; }
static float GetFarClip(void) { return m_fCurrentFarClip; }
static float GetFogStart(void) { return m_fCurrentFogStart; }
static int32 GetLowCloudsRed(void) { return m_nCurrentLowCloudsRed; }
static int32 GetLowCloudsGreen(void) { return m_nCurrentLowCloudsGreen; }
static int32 GetLowCloudsBlue(void) { return m_nCurrentLowCloudsBlue; }
static int32 GetFluffyCloudsTopRed(void) { return m_nCurrentFluffyCloudsTopRed; }
static int32 GetFluffyCloudsTopGreen(void) { return m_nCurrentFluffyCloudsTopGreen; }
static int32 GetFluffyCloudsTopBlue(void) { return m_nCurrentFluffyCloudsTopBlue; }
static int32 GetFluffyCloudsBottomRed(void) { return m_nCurrentFluffyCloudsBottomRed; }
static int32 GetFluffyCloudsBottomGreen(void) { return m_nCurrentFluffyCloudsBottomGreen; }
static int32 GetFluffyCloudsBottomBlue(void) { return m_nCurrentFluffyCloudsBottomBlue; }
static int32 GetFogRed(void) { return m_nCurrentFogColourRed; }
static int32 GetFogGreen(void) { return m_nCurrentFogColourGreen; }
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 UpdateArrays(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]; }
static float GetShadowSideX(void) { return m_fShadowSideX[m_CurrentStoredValue]; }
static float GetShadowSideY(void) { return m_fShadowSideY[m_CurrentStoredValue]; }
static float GetShadowDisplacementX(void) { return m_fShadowDisplacementX[m_CurrentStoredValue]; }
static float GetShadowDisplacementY(void) { return m_fShadowDisplacementY[m_CurrentStoredValue]; }
};

786
src/renderer/VarConsole.cpp Normal file
View File

@ -0,0 +1,786 @@
#include "common.h"
#include "VarConsole.h"
#include "Font.h"
#include "Pad.h"
#define VAR_CONSOLE_PAD 1
CVarConsole VarConsole;
void
CVarConsole::Initialise()
{
m_nCountEntries = 0;
m_nCurPage = 1;
m_bIsOpen = false;
m_nCurEntry = 0;
m_nFirstEntryOnPage = 0;
}
void
CVarConsole::Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt8Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT8;
m_aEntries[i].I8_step = step;
m_aEntries[i].I8_min = min;
m_aEntries[i].I8_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt16Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT16;
m_aEntries[i].I16_step = step;
m_aEntries[i].I16_min = min;
m_aEntries[i].I16_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt32Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT32;
m_aEntries[i].I32_step = step;
m_aEntries[i].I32_min = min;
m_aEntries[i].I32_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt64Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT64;
m_aEntries[i].I64_step = step;
m_aEntries[i].I64_min = min;
m_aEntries[i].I64_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint8Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT8;
m_aEntries[i].I8_step = step;
m_aEntries[i].I8_min = min;
m_aEntries[i].I8_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint16Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT16;
m_aEntries[i].I16_step = step;
m_aEntries[i].I16_min = min;
m_aEntries[i].I16_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint32Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT32;
m_aEntries[i].I32_step = step;
m_aEntries[i].I32_min = min;
m_aEntries[i].I32_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint64Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT64;
m_aEntries[i].I64_step = step;
m_aEntries[i].I64_min = min;
m_aEntries[i].I64_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, float *pVal, float step, float min, float max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pFloatValue = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_FLOAT;
m_aEntries[i].F_step = step;
m_aEntries[i].F_min = min;
m_aEntries[i].F_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pBoolValue = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool8 *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint8Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL8;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool16 *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint16Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL16;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool32 *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint32Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL32;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, void (*pCallback)(void))
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pCallback = pCallback;
m_aEntries[i].VarType = VCE_TYPE_FUNCTION;
m_nCountEntries++;
}
void
CVarConsole::Remove(char *text)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
{
for (int j = i; j < m_nCountEntries-1; j++)
m_aEntries[j] = m_aEntries[j+1];
m_nCountEntries--;
return;
}
}
}
void
CVarConsole::SortPages()
{
m_nNumPages = m_nCountEntries / 30 + 1;
}
void
CVarConsole::Display()
{
char s[256];
wchar ws[256];
CFont::SetColor(CRGBA(200, 200, 200, 255));
CFont::SetFontStyle(FONT_STANDARD);
CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.6f));
CFont::SetDropShadowPosition(2);
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetPropOn();
CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
CFont::SetRightJustifyWrap(0.0f);
sprintf(s, "PAGE %d", m_nCurPage);
AsciiToUnicode(s, ws);
CFont::SetRightJustifyOn();
CFont::PrintString(SCREEN_SCALE_X(310.0f), SCREEN_SCALE_Y(30.0f), ws);
CFont::SetRightJustifyOff();
int y = 45;
for (int i = m_nFirstEntryOnPage; i < m_nCountEntries && i < m_nFirstEntryOnPage + 30; i++)
{
switch (m_aEntries[i].VarType)
{
case VCE_TYPE_INT8:
sprintf(s, "(%d) %s:I8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt8Value);
break;
case VCE_TYPE_INT16:
sprintf(s, "(%d) %s:I16:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt16Value);
break;
case VCE_TYPE_INT32:
sprintf(s, "(%d) %s:I32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt32Value);
break;
case VCE_TYPE_INT64:
#ifdef FIX_BUGS
sprintf(s, "(%d) %s:I64:%lld", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt64Value);
#else
sprintf(s, "(%d) %s:I64:%d", i + 1, m_aEntries[i].text, (int32)*m_aEntries[i].pInt64Value);
#endif
break;
case VCE_TYPE_UINT8:
sprintf(s, "(%d) %s:U8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint8Value);
break;
case VCE_TYPE_UINT16:
sprintf(s, "(%d) %s:U6:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint16Value);
break;
case VCE_TYPE_UINT32:
sprintf(s, "(%d) %s:U32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint32Value);
break;
case VCE_TYPE_UINT64:
#ifdef FIX_BUGS
sprintf(s, "(%d) %s:U64:%llu", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint64Value);
#else
sprintf(s, "(%d) %s:U64:%d", i + 1, m_aEntries[i].text, (uint32)*m_aEntries[i].pUint64Value);
#endif
break;
case VCE_TYPE_FLOAT:
sprintf(s, "(%d) %s:F:%f", i + 1, m_aEntries[i].text, *m_aEntries[i].pFloatValue);
break;
case VCE_TYPE_BOOL:
if (*m_aEntries[i].pBoolValue)
sprintf(s, "(%d) %s:B:TRUE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B : FALSE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_BOOL8:
if (*m_aEntries[i].pUint8Value == FALSE)
sprintf(s, "(%d) %s:B8:FALSE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B8:TRUE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_BOOL16:
if (*m_aEntries[i].pUint16Value == FALSE)
sprintf(s, "(%d) %s:B16:FALSE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B16:TRUE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_BOOL32:
if (*m_aEntries[i].pUint32Value == FALSE)
sprintf(s, "(%d) %s:B32:FALSE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B32:TRUE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_FUNCTION:
sprintf(s, "(%d) %s:FUNCTION:call this function?", i + 1, m_aEntries[i].text);
break;
}
AsciiToUnicode(s, ws);
if (m_nCurEntry == i) {
CFont::SetBackgroundOn();
#ifdef FIX_BUGS
CFont::SetBackgroundColor(CRGBA(128, 128, 128, 128));
#endif
}
#ifdef FIX_BUGS
else
CFont::SetBackgroundColor(CRGBA(128, 128, 128, 0));
#endif
CFont::SetColor(CRGBA(200, 200, 200, 255));
CFont::PrintString(SCREEN_SCALE_X(30.0f), SCREEN_SCALE_Y(y), ws);
if (m_nCurEntry == i)
CFont::SetBackgroundOff();
y += 12;
}
}
void
CVarConsole::ModifyLeft()
{
CVarConsoleEntry &entry = m_aEntries[m_nCurEntry];
switch (entry.VarType)
{
case VCE_TYPE_INT8:
*entry.pInt8Value -= entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt8Value < entry.I8_min)
*entry.pInt8Value = entry.I8_max;
} else {
if (*entry.pInt8Value < entry.I8_min)
*entry.pInt8Value = entry.I8_min;
}
break;
case VCE_TYPE_INT16:
*entry.pInt16Value -= entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt16Value < entry.I16_min)
*entry.pInt16Value = entry.I16_max;
}
else {
if (*entry.pInt16Value < entry.I16_min)
*entry.pInt16Value = entry.I16_min;
}
break;
case VCE_TYPE_INT32:
*entry.pInt32Value -= entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt32Value < entry.I32_min)
*entry.pInt32Value = entry.I32_max;
}
else {
if (*entry.pInt32Value < entry.I32_min)
*entry.pInt32Value = entry.I32_min;
}
break;
case VCE_TYPE_INT64:
*entry.pInt64Value -= entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt64Value < entry.I64_min)
*entry.pInt64Value = entry.I64_max;
}
else {
if (*entry.pInt64Value < entry.I64_min)
*entry.pInt64Value = entry.I64_min;
}
break;
case VCE_TYPE_UINT8:
*entry.pUint8Value -= entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*(int8*)entry.pUint8Value < entry.I8_min)
*entry.pUint8Value = entry.I8_max;
}
else {
if (*(int8*)entry.pUint8Value < entry.I8_min)
*entry.pUint8Value = entry.I8_min;
}
break;
case VCE_TYPE_UINT16:
*entry.pUint16Value -= entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*(int16*)entry.pUint16Value < entry.I16_min)
*entry.pUint16Value = entry.I16_max;
}
else {
if (*(int16*)entry.pUint16Value < entry.I16_min)
*entry.pUint16Value = entry.I16_min;
}
break;
case VCE_TYPE_UINT32:
*entry.pUint32Value -= entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*(int32*)entry.pUint32Value < entry.I32_min)
*entry.pUint32Value = entry.I32_max;
}
else {
if (*(int32*)entry.pUint32Value < entry.I32_min)
*entry.pUint32Value = entry.I32_min;
}
break;
case VCE_TYPE_UINT64:
*entry.pUint64Value -= entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*(int64*)entry.pUint64Value < entry.I64_min)
*entry.pUint64Value = entry.I64_max;
}
else {
if (*(int64*)entry.pUint64Value < entry.I64_min)
*entry.pUint64Value = entry.I64_min;
}
break;
case VCE_TYPE_FLOAT:
*entry.pFloatValue -= entry.F_step;
if (entry.bAllowExceedBounds) {
if (*entry.pFloatValue < entry.F_min)
*entry.pFloatValue = entry.F_max;
}
else {
if (*entry.pFloatValue < entry.F_min)
*entry.pFloatValue = entry.F_min;
}
break;
case VCE_TYPE_BOOL:
if (entry.bAllowExceedBounds)
*entry.pBoolValue ^= true;
else
*entry.pBoolValue = false;
break;
case VCE_TYPE_BOOL8:
if (entry.bAllowExceedBounds)
*entry.pUint8Value = *entry.pUint8Value == false;
else
*entry.pUint8Value = false;
break;
case VCE_TYPE_BOOL16:
if (entry.bAllowExceedBounds)
*entry.pUint16Value = *entry.pUint16Value == false;
else
*entry.pUint16Value = false;
break;
case VCE_TYPE_BOOL32:
if (entry.bAllowExceedBounds)
*entry.pUint32Value = *entry.pUint32Value == false;
else
*entry.pUint32Value = false;
break;
case VCE_TYPE_FUNCTION:
entry.pCallback();
break;
default:
return;
}
}
void
CVarConsole::ModifyRight()
{
CVarConsoleEntry &entry = m_aEntries[m_nCurEntry];
switch (entry.VarType)
{
case VCE_TYPE_INT8:
*entry.pInt8Value += entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt8Value > entry.I8_max)
*entry.pInt8Value = entry.I8_min;
}
else {
if (*entry.pInt8Value > entry.I8_max)
*entry.pInt8Value = entry.I8_max;
}
break;
case VCE_TYPE_INT16:
*entry.pInt16Value += entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt16Value > entry.I16_max)
*entry.pInt16Value = entry.I16_min;
}
else {
if (*entry.pInt16Value > entry.I16_max)
*entry.pInt16Value = entry.I16_max;
}
break;
case VCE_TYPE_INT32:
*entry.pInt32Value += entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt32Value > entry.I32_max)
*entry.pInt32Value = entry.I32_min;
}
else {
if (*entry.pInt32Value > entry.I32_max)
*entry.pInt32Value = entry.I32_max;
}
break;
case VCE_TYPE_INT64:
*entry.pInt64Value += entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt64Value > entry.I64_max)
*entry.pInt64Value = entry.I64_min;
}
else {
if (*entry.pInt64Value > entry.I64_max)
*entry.pInt64Value = entry.I64_max;
}
break;
case VCE_TYPE_UINT8:
*entry.pUint8Value += entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint8Value > (uint8)entry.I8_max)
*entry.pUint8Value = entry.I8_min;
}
else {
if (*entry.pUint8Value > (uint8)entry.I8_max)
*entry.pUint8Value = entry.I8_max;
}
break;
case VCE_TYPE_UINT16:
*entry.pUint16Value += entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint16Value > (uint16)entry.I16_max)
*entry.pUint16Value = entry.I16_min;
}
else {
if (*entry.pUint16Value > (uint16)entry.I16_max)
*entry.pUint16Value = entry.I16_max;
}
break;
case VCE_TYPE_UINT32:
*entry.pUint32Value += entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint32Value > (uint32)entry.I32_max)
*entry.pUint32Value = entry.I32_min;
}
else {
if (*entry.pUint32Value > (uint32)entry.I32_max)
*entry.pUint32Value = entry.I32_max;
}
break;
case VCE_TYPE_UINT64:
*entry.pUint64Value += entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint64Value > (uint64)entry.I64_max)
*entry.pUint64Value = entry.I64_min;
}
else {
if (*entry.pUint64Value > (uint64)entry.I64_max)
*entry.pUint64Value = entry.I64_max;
}
break;
case VCE_TYPE_FLOAT:
*entry.pFloatValue += entry.F_step;
if (entry.bAllowExceedBounds) {
if (*entry.pFloatValue > entry.F_max)
*entry.pFloatValue = entry.F_min;
}
else {
if (*entry.pFloatValue > entry.F_max)
*entry.pFloatValue = entry.F_max;
}
break;
case VCE_TYPE_BOOL:
if (entry.bAllowExceedBounds)
*entry.pBoolValue ^= true;
else
*entry.pBoolValue = true;
break;
case VCE_TYPE_BOOL8:
if (entry.bAllowExceedBounds)
*entry.pUint8Value = *entry.pUint8Value == false;
else
*entry.pUint8Value = true;
break;
case VCE_TYPE_BOOL16:
if (entry.bAllowExceedBounds)
*entry.pUint16Value = *entry.pUint16Value == false;
else
*entry.pUint16Value = true;
break;
case VCE_TYPE_BOOL32:
if (entry.bAllowExceedBounds)
*entry.pUint32Value = *entry.pUint32Value == false;
else
*entry.pUint32Value = true;
break;
case VCE_TYPE_FUNCTION:
entry.pCallback();
break;
default:
return;
}
}
void
CVarConsole::Enter()
{
m_bIsOpen = true;
}
void
CVarConsole::Exit()
{
m_bIsOpen = false;
}
void
CVarConsole::Input()
{
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadDownJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadDown())
{
m_nCurEntry++;
if (m_nCurEntry < m_nCountEntries)
{
if (m_nCurEntry > m_nFirstEntryOnPage + 29)
{
m_nFirstEntryOnPage = m_nCurEntry;
++m_nCurPage;
}
}
else
{
m_nCurEntry = m_nCountEntries - 1;
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadUpJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadUp())
{
m_nCurEntry--;
if (m_nCurEntry < m_nFirstEntryOnPage)
{
m_nFirstEntryOnPage = m_nCurEntry - 29;
--m_nCurPage;
}
if (m_nFirstEntryOnPage < 0)
{
m_nCurEntry = 0;
m_nFirstEntryOnPage = 0;
m_nCurPage = 1;
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetSquare())
ModifyLeft();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetTriangle())
ModifyRight();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadLeftJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadLeft())
ModifyLeft();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadRightJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadRight())
ModifyRight();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder2JustDown())
{
if (m_nCurPage > 1)
{
m_nCurPage--;
m_nFirstEntryOnPage -= 30;
m_nCurEntry = m_nFirstEntryOnPage;
if (m_nFirstEntryOnPage < 0)
{
m_nFirstEntryOnPage = 0;
m_nCurEntry = m_nFirstEntryOnPage;
m_nCurPage = 1;
}
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder2JustDown())
{
if (m_nCurPage < m_nNumPages)
{
m_nCurPage++;
m_nFirstEntryOnPage += 30;
m_nCurEntry = m_nFirstEntryOnPage;
if (m_nFirstEntryOnPage >= m_nCountEntries)
{
m_nFirstEntryOnPage -= 30;
m_nCurEntry = m_nFirstEntryOnPage;
m_nCurPage--;
}
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())
Exit();
}
void
CVarConsole::Process()
{
Input();
SortPages();
Display();
}
bool8
CVarConsole::Open()
{
return m_bIsOpen;
}
void
CVarConsole::Check()
{
if (Open())
Process();
else if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())
Enter();
}

92
src/renderer/VarConsole.h Normal file
View File

@ -0,0 +1,92 @@
#pragma once
enum eVarConsoleEntryType
{
VCE_TYPE_INT8,
VCE_TYPE_INT16,
VCE_TYPE_INT32,
VCE_TYPE_INT64,
VCE_TYPE_UINT8,
VCE_TYPE_UINT16,
VCE_TYPE_UINT32,
VCE_TYPE_UINT64,
VCE_TYPE_FLOAT,
VCE_TYPE_BOOL,
VCE_TYPE_BOOL8,
VCE_TYPE_BOOL16,
VCE_TYPE_BOOL32,
VCE_TYPE_FUNCTION,
};
struct CVarConsoleEntry
{
char *text;
int8 *pInt8Value;
int16 *pInt16Value;
int32 *pInt32Value;
int64 *pInt64Value;
uint8 *pUint8Value;
uint16 *pUint16Value;
uint32 *pUint32Value;
uint64 *pUint64Value;
float *pFloatValue;
bool *pBoolValue;
void (*pCallback)(void);
int8 I8_step, I8_max, I8_min;
int16 I16_step, I16_max, I16_min;
int32 I32_step, I32_max, I32_min;
int64 I64_step, I64_max, I64_min;
float F_step, F_max, F_min;
bool8 bAllowExceedBounds;
uint8 VarType;
};
class CVarConsole
{
int32 m_nCountEntries;
bool8 m_bIsOpen;
int32 m_nCurEntry;
int32 m_nFirstEntryOnPage;
int32 m_nCurPage;
int32 m_nNumPages;
CVarConsoleEntry m_aEntries[91];
public:
#ifdef FIX_BUGS
CVarConsole() { Initialise(); }
#endif
void Initialise();
void Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);
void Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);
void Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);
void Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);
void Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);
void Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);
void Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);
void Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);
void Add(char *text, float *pVal, float step, float min, float max, bool8 isVar);
void Add(char *text, bool *pVal, bool8 isVar);
void Add(char *text, bool8 *pVal, bool8 isVar);
void Add(char *text, bool16 *pVal, bool8 isVar);
void Add(char *text, bool32 *pVal, bool8 isVar);
void Add(char *text, void (*pVar)(void));
void Remove(char *text);
void SortPages();
void Display();
void ModifyLeft();
void ModifyRight();
void Enter();
void Exit();
void Input();
void Process();
bool8 Open();
void Check();
};
extern CVarConsole VarConsole;

View File

@ -0,0 +1,341 @@
#include "common.h"
#include "WaterCannon.h"
#include "Vector.h"
#include "General.h"
#include "main.h"
#include "Timer.h"
#include "Pools.h"
#include "Ped.h"
#include "AnimManager.h"
#include "Fire.h"
#include "WaterLevel.h"
#include "Camera.h"
#include "Particle.h"
// --LCS: file done
#ifdef PSP_WATERCANNON
//PSP:
#define WATER_COLOR 255
#else
//PS2:
#define WATER_COLOR 127
#endif
#define WATERCANNONVERTS 4
#define WATERCANNONINDEXES 12
RwIm3DVertex WaterCannonVertices[WATERCANNONVERTS];
RwImVertexIndex WaterCannonIndexList[WATERCANNONINDEXES];
CWaterCannon CWaterCannons::aCannons[NUM_WATERCANNONS];
void CWaterCannon::Init(void)
{
m_nId = 0;
m_nCur = 0;
m_nTimeCreated = CTimer::GetTimeInMilliseconds();
for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )
m_abUsed[i] = false;
RwIm3DVertexSetU(&WaterCannonVertices[0], 0.0f);
RwIm3DVertexSetV(&WaterCannonVertices[0], 0.0f);
RwIm3DVertexSetU(&WaterCannonVertices[1], 1.0f);
RwIm3DVertexSetV(&WaterCannonVertices[1], 0.0f);
RwIm3DVertexSetU(&WaterCannonVertices[2], 0.0f);
RwIm3DVertexSetV(&WaterCannonVertices[2], 0.0f);
RwIm3DVertexSetU(&WaterCannonVertices[3], 1.0f);
RwIm3DVertexSetV(&WaterCannonVertices[3], 0.0f);
WaterCannonIndexList[0] = 0;
WaterCannonIndexList[1] = 1;
WaterCannonIndexList[2] = 2;
WaterCannonIndexList[3] = 1;
WaterCannonIndexList[4] = 3;
WaterCannonIndexList[5] = 2;
WaterCannonIndexList[6] = 0;
WaterCannonIndexList[7] = 2;
WaterCannonIndexList[8] = 1;
WaterCannonIndexList[9] = 1;
WaterCannonIndexList[10] = 2;
WaterCannonIndexList[11] = 3;
}
void CWaterCannon::Update_OncePerFrame(int16 index)
{
ASSERT(index < NUM_WATERCANNONS);
if (CTimer::GetTimeInMilliseconds() > m_nTimeCreated + WATERCANNON_LIFETIME )
{
m_nCur = (m_nCur + 1) % NUM_SEGMENTPOINTS;
m_abUsed[m_nCur] = false;
}
for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )
{
if ( m_abUsed[i] )
{
m_avecVelocity[i].z += -WATERCANNON_GRAVITY * CTimer::GetTimeStep();
m_avecPos[i] += m_avecVelocity[i] * CTimer::GetTimeStep();
}
}
for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )
{
if ( m_abUsed[i] && gFireManager.ExtinguishPointWithWater(m_avecPos[i], 4.0f) )
{
break;
}
}
if ( ((index + CTimer::GetFrameCounter()) & 3) == 0 )
PushPeds();
// free if unused
int32 i = 0;
while ( 1 )
{
if ( m_abUsed[i] )
break;
if ( ++i >= NUM_SEGMENTPOINTS )
{
m_nId = 0;
return;
}
}
}
void CWaterCannon::Update_NewInput(CVector *pos, CVector *dir)
{
ASSERT(pos != NULL);
ASSERT(dir != NULL);
m_avecPos[m_nCur] = *pos;
m_avecVelocity[m_nCur] = *dir;
m_abUsed[m_nCur] = true;
}
static float fWaterCannonU = 0.0f;
void CWaterCannon::Render(void)
{
extern RwRaster *gpFireHoseRaster;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpFireHoseRaster);
fWaterCannonU += CTimer::GetTimeStepInSeconds() * 6.0f;
while ( fWaterCannonU >= 1.0f )
fWaterCannonU -= 1.0f;
RwIm3DVertexSetU(&WaterCannonVertices[0], -fWaterCannonU);
RwIm3DVertexSetV(&WaterCannonVertices[0], 0.0f);
RwIm3DVertexSetU(&WaterCannonVertices[1], -fWaterCannonU);
RwIm3DVertexSetV(&WaterCannonVertices[1], 1.0f);
RwIm3DVertexSetU(&WaterCannonVertices[2], 1.0f - fWaterCannonU);
RwIm3DVertexSetV(&WaterCannonVertices[2], 0.0f);
RwIm3DVertexSetU(&WaterCannonVertices[3], 1.0f - fWaterCannonU);
RwIm3DVertexSetV(&WaterCannonVertices[3], 1.0f);
int16 pointA = m_nCur % NUM_SEGMENTPOINTS;
int16 pointB = pointA - 1;
int16 pointC = pointA;
if ( pointB < 0 )
pointB += NUM_SEGMENTPOINTS;
bool bInit = false;
CVector norm;
for ( int32 i = 0; i < NUM_SEGMENTPOINTS - 1; i++ )
{
if ( m_abUsed[pointA] && m_abUsed[pointB] )
{
bool bFirst = false;
if ( i == 0 || m_abUsed[pointA] && !m_abUsed[pointC] )
bFirst = true;
if ( !bInit )
{
CVector cp = CrossProduct(m_avecPos[pointB] - m_avecPos[pointA], TheCamera.GetForward());
norm = cp * (0.05f / cp.Magnitude());
bInit = true;
}
float brightness = float(i) / NUM_SEGMENTPOINTS;
int32 color = (int32)((1.0f - brightness*brightness) * 255.0f);
CVector offset = (float(i)+1.0f) * norm;
RwIm3DVertexSetRGBA(&WaterCannonVertices[0], WATER_COLOR, WATER_COLOR, WATER_COLOR, bFirst ? 0 : color);
RwIm3DVertexSetPos (&WaterCannonVertices[0], m_avecPos[pointA].x - offset.x, m_avecPos[pointA].y - offset.y, m_avecPos[pointA].z - offset.z);
RwIm3DVertexSetRGBA(&WaterCannonVertices[1], WATER_COLOR, WATER_COLOR, WATER_COLOR, bFirst ? 0 : color);
RwIm3DVertexSetPos (&WaterCannonVertices[1], m_avecPos[pointA].x + offset.x, m_avecPos[pointA].y + offset.y, m_avecPos[pointA].z + offset.z);
offset = (float(i+1)+1.0f) * norm;
RwIm3DVertexSetRGBA(&WaterCannonVertices[2], WATER_COLOR, WATER_COLOR, WATER_COLOR, color);
RwIm3DVertexSetPos (&WaterCannonVertices[2], m_avecPos[pointB].x - offset.x, m_avecPos[pointB].y - offset.y, m_avecPos[pointB].z - offset.z);
RwIm3DVertexSetRGBA(&WaterCannonVertices[3], WATER_COLOR, WATER_COLOR, WATER_COLOR, color);
RwIm3DVertexSetPos (&WaterCannonVertices[3], m_avecPos[pointB].x + offset.x, m_avecPos[pointB].y + offset.y, m_avecPos[pointB].z + offset.z);
if ( RwIm3DTransform(WaterCannonVertices, WATERCANNONVERTS, NULL, rwIM3D_VERTEXUV) )
{
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, WaterCannonIndexList, WATERCANNONINDEXES);
RwIm3DEnd();
}
}
pointC = pointA;
pointA = pointB--;
if ( pointB < 0 )
pointB += NUM_SEGMENTPOINTS;
}
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
}
void CWaterCannon::PushPeds(void)
{
float minx = 10000.0f;
float maxx = -10000.0f;
float miny = 10000.0f;
float maxy = -10000.0f;
float minz = 10000.0f;
float maxz = -10000.0f;
for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )
{
if ( m_abUsed[i] )
{
minx = Min(minx, m_avecPos[i].x);
maxx = Max(maxx, m_avecPos[i].x);
miny = Min(miny, m_avecPos[i].y);
maxy = Max(maxy, m_avecPos[i].y);
minz = Min(minz, m_avecPos[i].z);
maxz = Max(maxz, m_avecPos[i].z);
}
}
for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--)
{
CPed *ped = CPools::GetPedPool()->GetSlot(i);
if ( ped )
{
if ( ped->GetPosition().x > minx && ped->GetPosition().x < maxx
&& ped->GetPosition().y > miny && ped->GetPosition().y < maxy
&& ped->GetPosition().z > minz && ped->GetPosition().z < maxz )
{
for ( int32 j = 0; j < NUM_SEGMENTPOINTS; j++ )
{
if ( m_abUsed[j] )
{
CVector dist = m_avecPos[j] - ped->GetPosition();
if ( dist.MagnitudeSqr() < 5.0f )
{
int32 localDir = ped->GetLocalDirection(CVector2D(1.0f, 0.0f));
ped->bIsStanding = false;
ped->ApplyMoveForce(0.0f, 0.0f, 2.0f * CTimer::GetTimeStep());
ped->m_vecMoveSpeed.x = (0.6f * m_avecVelocity[j].x + ped->m_vecMoveSpeed.x) * 0.5f;
ped->m_vecMoveSpeed.y = (0.6f * m_avecVelocity[j].y + ped->m_vecMoveSpeed.y) * 0.5f;
float pedSpeed2D = ped->m_vecMoveSpeed.Magnitude2D();
if ( pedSpeed2D > 0.2f ) {
ped->m_vecMoveSpeed.x *= (0.2f / pedSpeed2D);
ped->m_vecMoveSpeed.y *= (0.2f / pedSpeed2D);
}
ped->SetFall(2000, (AnimationId)(localDir + ANIM_STD_HIGHIMPACT_FRONT), 0);
CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, ped->GetPosition(), ped->m_vecMoveSpeed * 0.3f, 0, 0.5f);
CParticle::AddParticle(PARTICLE_CAR_SPLASH, ped->GetPosition(), ped->m_vecMoveSpeed * -0.3f + CVector(0.f, 0.f, 0.5f), 0, 0.5f,
CGeneral::GetRandomNumberInRange(0.f, 10.f), CGeneral::GetRandomNumberInRange(0.f, 90.f), 1);
j = NUM_SEGMENTPOINTS;
}
}
}
}
}
}
}
void CWaterCannons::Init(void)
{
for ( int32 i = 0; i < NUM_WATERCANNONS; i++ )
aCannons[i].Init();
}
void CWaterCannons::UpdateOne(uint32 id, CVector *pos, CVector *dir)
{
ASSERT(pos != NULL);
ASSERT(dir != NULL);
// find the one by id
{
int32 n = 0;
while ( n < NUM_WATERCANNONS && id != aCannons[n].m_nId )
n++;
if ( n < NUM_WATERCANNONS )
{
aCannons[n].Update_NewInput(pos, dir);
return;
}
}
// if no luck then find a free one
{
int32 n = 0;
while ( n < NUM_WATERCANNONS && 0 != aCannons[n].m_nId )
n++;
if ( n < NUM_WATERCANNONS )
{
aCannons[n].Init();
aCannons[n].m_nId = id;
aCannons[n].Update_NewInput(pos, dir);
return;
}
}
}
void CWaterCannons::Update(void)
{
for ( int32 i = 0; i < NUM_WATERCANNONS; i++ )
{
if ( aCannons[i].m_nId != 0 )
aCannons[i].Update_OncePerFrame(i);
}
}
void CWaterCannons::Render(void)
{
PUSH_RENDERGROUP("CWaterCannons::Render");
for ( int32 i = 0; i < NUM_WATERCANNONS; i++ )
{
if ( aCannons[i].m_nId != 0 )
aCannons[i].Render();
}
POP_RENDERGROUP();
}

View File

@ -0,0 +1,40 @@
#pragma once
#define WATERCANNON_GRAVITY (0.009f)
#define WATERCANNON_LIFETIME (150)
class CWaterCannon
{
public:
enum
{
NUM_SEGMENTPOINTS = 16,
};
int32 m_nId;
int16 m_nCur;
uint32 m_nTimeCreated;
int32 field_C;
CVector m_avecPos[NUM_SEGMENTPOINTS];
CVector m_avecVelocity[NUM_SEGMENTPOINTS];
bool m_abUsed[NUM_SEGMENTPOINTS];
void Init(void);
void Update_OncePerFrame(int16 index);
void Update_NewInput(CVector *pos, CVector *dir);
void Render(void);
void PushPeds(void);
};
VALIDATE_SIZE(CWaterCannon, 0x1A0);
class CWaterCannons
{
public:
static CWaterCannon aCannons[NUM_WATERCANNONS];
static void Init(void);
static void UpdateOne(uint32 id, CVector *pos, CVector *dir);
static void Update();
static void Render(void);
};

View File

@ -0,0 +1,277 @@
#include "common.h"
#include "WaterCreatures.h"
#include "ModelIndices.h"
#include "World.h"
#include "WaterLevel.h"
#include "Camera.h"
#include "PlayerPed.h"
#include "General.h"
#include "Object.h"
/*
int CWaterCreatures::nNumActiveSeaLifeForms;
CWaterCreature CWaterCreatures::aWaterCreatures[NUM_WATER_CREATURES];
struct WaterCreatureProperties aProperties[65] = {
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_JELLYFISH, 0.01f, 2.2f, 0.0005f, 3.5f },
{ &MI_JELLYFISH01, 0.01f, 2.2f, 0.0005f, 3.5f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_TURTLE, 0.01f, 2.0f, 0.0005f, 4.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_DOLPHIN, 0.03f, 1.5f, 0.0005f, 4.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_SHARK, 0.03f, 0.4f, 0.0005f, 4.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
};
CWaterCreature::CWaterCreature() {
Free();
}
void CWaterCreature::Initialise(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) {
this->m_pObj = pObj;
this->m_fFwdSpeed = fFwdSpeed;
this->m_fZTurnSpeed = fZTurnSpeed;
this->m_fWaterDepth = fWaterDepth;
this->m_alpha = alpha;
this->m_state = state;
}
void CWaterCreature::Allocate(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) {
CWaterCreature::Initialise(pObj, fFwdSpeed, fZTurnSpeed, fWaterDepth, alpha, state);
}
void CWaterCreature::Free() {
CWaterCreature::Initialise(nil, 0.0f, 0.0f, 0.0f, 0, WATER_CREATURE_DISABLED);
}
CWaterCreature *CWaterCreatures::GetFishStructSlot() {
for (int i = 0; i < NUM_WATER_CREATURES; i++)
if (aWaterCreatures[i].m_state == WATER_CREATURE_DISABLED)
return &aWaterCreatures[i];
return nil;
}
CObject *CWaterCreatures::CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle) {
if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
return nil;
CObject *pObj = new CObject(modelID, true);
if (!pObj) return nil;
pObj->SetPosition(pos);
pObj->GetMatrix().UpdateRW();
pObj->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
pObj->GetMatrix().SetRotateZOnly(DEGTORAD(zRotAngle));
pObj->GetMatrix().UpdateRW();
pObj->ObjectCreatedBy = CONTROLLED_SUB_OBJECT;
pObj->bIsStatic = false;
if (pObj->ObjectCreatedBy == TEMP_OBJECT) {
CObject::nNoTempObjects++;
pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
}
pObj->bTouchingWater = true;
pObj->bUnderwater = true;
CWorld::Add(pObj);
return pObj;
}
bool CWaterCreatures::IsSpaceForMoreWaterCreatures() {
return nNumActiveSeaLifeForms < NUM_WATER_CREATURES;
}
float CWaterCreatures::CalculateFishHeading(CVector const& pos1, CVector const& pos2) {
CVector delta = pos1 - pos2;
delta.Normalise();
return CGeneral::GetRandomNumberInRange(-90, 90) +
RADTODEG(delta.Heading() + HALFPI + PI);
}
void CWaterCreatures::CreateOne(CVector const& pos, int32 modelID) {
if (!IsSpaceForMoreWaterCreatures())
return;
CVector playerPos = FindPlayerPed()->GetPosition();
CVector fishPos = pos;
float fDepth, fLevelNoWaves;
if (!TheCamera.IsSphereVisible(fishPos, 3.0f)
&& CWaterLevel::GetWaterDepth(fishPos, &fDepth, &fLevelNoWaves, nil) && fDepth > 4.5f) {
if (modelID == -1 || modelID < 0 || modelID > 64)
modelID = CGeneral::GetRandomNumberInRange(0, 64);
WaterCreatureProperties *creature = &aProperties[modelID];
fishPos.z = fLevelNoWaves - creature->fLevel;
float fFwdSpeed = CGeneral::GetRandomNumberInRange(0.0f, creature->fFwdSpeed) + 0.01f;
float angle = CWaterCreatures::CalculateFishHeading(playerPos, fishPos);
CObject *fish = CreateSeaLifeForm(fishPos, *creature->modelID, angle);
if (!fish) return;
fish->SetRwObjectAlpha(255);
CWaterCreature *wc = GetFishStructSlot();
wc->Allocate(fish, fFwdSpeed, 0.0f, creature->fWaterDepth, 255, WATER_CREATURE_INIT);
nNumActiveSeaLifeForms++;
}
}
void CWaterCreatures::FreeFishStructSlot(CWaterCreature *wc) {
wc->Free();
}
void CWaterCreatures::UpdateAll() {
if (nNumActiveSeaLifeForms == 0)
return;
CVector playerPos = FindPlayerPed()->GetPosition();
for (int i = 0; i < NUM_WATER_CREATURES; i++) {
switch (aWaterCreatures[i].m_state) {
case WATER_CREATURE_ACTIVE:
// is this even reachable?
aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000;
if (!aWaterCreatures[i].m_pObj->GetIsOnScreen()) {
aWaterCreatures[i].m_pObj->SetRwObjectAlpha(0);
aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;
break;
}
// fall through
case WATER_CREATURE_INIT: {
if ((playerPos - aWaterCreatures[i].m_pObj->GetPosition()).MagnitudeSqr() < SQR(75.0f)) {
if (aWaterCreatures[i].m_alpha < 255)
aWaterCreatures[i].m_alpha = Min(aWaterCreatures[i].m_alpha + 4, 255);
aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha);
CVector fwd = aWaterCreatures[i].m_pObj->GetRight(); // for some reason they used x for forward
fwd.Normalise();
aWaterCreatures[i].m_pObj->m_vecMoveSpeed = fwd * aWaterCreatures[i].m_fFwdSpeed;
aWaterCreatures[i].m_pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, aWaterCreatures[i].m_fZTurnSpeed);
aWaterCreatures[i].m_pObj->bIsStatic = false;
float fDepth = 0.0;
CWaterLevel::GetWaterDepth(aWaterCreatures[i].m_pObj->GetPosition(), &fDepth, nil, nil);
if (aWaterCreatures[i].m_fWaterDepth < fDepth) {
// it looks like this can never be true initially, looks like a BUG
if (aWaterCreatures[i].m_pObj->m_nEndOfLifeTime - 40000 <= CTimer::GetTimeInMilliseconds())
aWaterCreatures[i].m_state = WATER_CREATURE_ACTIVE;
}
else {
// creature is deeper than water
aWaterCreatures[i].m_state = WATER_CREATURE_FADE_OUT;
}
}
else {
aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;
}
break;
}
case WATER_CREATURE_FADE_OUT: {
aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000;
if (aWaterCreatures[i].m_alpha <= 0) {
aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;
}
else {
aWaterCreatures[i].m_alpha = Max(aWaterCreatures[i].m_alpha - 6, 0);
aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha);
CVector speed = aWaterCreatures[i].m_pObj->GetRight();
speed.Normalise();
speed.x *= aWaterCreatures[i].m_fFwdSpeed;
speed.y *= aWaterCreatures[i].m_fFwdSpeed;
speed.z = -0.015f;
aWaterCreatures[i].m_pObj->m_vecMoveSpeed = speed;
if (!aWaterCreatures[i].m_pObj->GetIsOnScreen())
aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;
}
break;
}
case WATER_CREATURE_REMOVE:
if (aWaterCreatures[i].m_pObj){
CWorld::Remove(aWaterCreatures[i].m_pObj);
delete aWaterCreatures[i].m_pObj;
}
FreeFishStructSlot(&aWaterCreatures[i]);
nNumActiveSeaLifeForms--;
aWaterCreatures[i].m_state = WATER_CREATURE_DISABLED;
break;
default:
break;
}
}
}
void CWaterCreatures::RemoveAll() {
for (int i = 0; i < NUM_WATER_CREATURES; i++) {
if (aWaterCreatures[i].m_state != WATER_CREATURE_DISABLED) {
if (aWaterCreatures[i].m_pObj){
CWorld::Remove(aWaterCreatures[i].m_pObj);
delete aWaterCreatures[i].m_pObj;
}
FreeFishStructSlot(&aWaterCreatures[i]);
aWaterCreatures[i].m_state = WATER_CREATURE_DISABLED;
nNumActiveSeaLifeForms--;
}
}
}
*/

View File

@ -0,0 +1,50 @@
#pragma once
class CObject;
/*
enum eFishSlotState {
WATER_CREATURE_INIT = 0,
WATER_CREATURE_ACTIVE,
WATER_CREATURE_FADE_OUT,
WATER_CREATURE_REMOVE,
WATER_CREATURE_DISABLED
};
class CWaterCreature {
public:
CObject *m_pObj;
float m_fFwdSpeed;
float m_fZTurnSpeed;
int32 m_alpha;
float m_fWaterDepth;
int32 m_state;
CWaterCreature();
void Allocate(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state);
void Free();
void Initialise(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state);
};
class CWaterCreatures {
public:
static CWaterCreature aWaterCreatures[NUM_WATER_CREATURES];
static int32 nNumActiveSeaLifeForms;
static CObject *CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle);
static void CreateOne(CVector const& pos, int32 modelID);
static void UpdateAll();
static void FreeFishStructSlot(CWaterCreature *wc);
static bool IsSpaceForMoreWaterCreatures();
static float CalculateFishHeading(CVector const& pos1, CVector const& pos2);
static void RemoveAll();
static CWaterCreature* GetFishStructSlot();
};
struct WaterCreatureProperties {
int16 *modelID;
float fFwdSpeed;
float fLevel;
float fUnknown; //unused
float fWaterDepth;
};*/

3378
src/renderer/WaterLevel.cpp Normal file

File diff suppressed because it is too large Load Diff

184
src/renderer/WaterLevel.h Normal file
View File

@ -0,0 +1,184 @@
#pragma once
#define WATER_X_OFFSET (0.0f)
#define WATER_Z_OFFSET (0.5f)
#define NO_WATER -128
#define MAX_SMALL_SECTORS 128
#define MAX_LARGE_SECTORS 64
#define MAX_HUGE_SECTORS 32
#define MAX_EXTRAHUGE_SECTORS 16
#define SMALL_SECTOR_SIZE 32
#define LARGE_SECTOR_SIZE 64
#define HUGE_SECTOR_SIZE 128
#define EXTRAHUGE_SECTOR_SIZE 256
#define WATER_START_X -2048.0f
#define WATER_END_X 2048.0f
#define WATER_START_Y -2048.0f
#define WATER_END_Y 2048.0f
#define WATER_WIDTH ((WATER_END_X - WATER_START_X))
#define WATER_HEIGHT ((WATER_END_Y - WATER_START_Y))
#define WATER_UNSIGN_X(x) ( (x) + (WATER_WIDTH /2) )
#define WATER_UNSIGN_Y(y) ( (y) + (WATER_HEIGHT/2) )
#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 )
#define WATER_FROM_SMALL_SECTOR_X(x) ( ((x) - (MAX_SMALL_SECTORS/2) ) * SMALL_SECTOR_SIZE )
#define WATER_FROM_SMALL_SECTOR_Y(y) ( ((y) - (MAX_SMALL_SECTORS/2) ) * SMALL_SECTOR_SIZE )
#define WATER_TO_SMALL_SECTOR_X(x) ( WATER_UNSIGN_X(x) / SMALL_SECTOR_SIZE )
#define WATER_TO_SMALL_SECTOR_Y(y) ( WATER_UNSIGN_Y(y) / SMALL_SECTOR_SIZE )
// 64
#define WATER_LARGE_X(x) ( WATER_UNSIGN_X(x) / MAX_LARGE_SECTORS )
#define WATER_LARGE_Y(y) ( WATER_UNSIGN_Y(y) / MAX_LARGE_SECTORS )
#define WATER_FROM_LARGE_SECTOR_X(x) ( ((x) - (MAX_LARGE_SECTORS/2) ) * LARGE_SECTOR_SIZE )
#define WATER_FROM_LARGE_SECTOR_Y(y) ( ((y) - (MAX_LARGE_SECTORS/2) ) * LARGE_SECTOR_SIZE )
#define WATER_TO_LARGE_SECTOR_X(x) ( WATER_UNSIGN_X(x) / LARGE_SECTOR_SIZE )
#define WATER_TO_LARGE_SECTOR_Y(y) ( WATER_UNSIGN_Y(y) / LARGE_SECTOR_SIZE )
// 128
#define WATER_HUGE_X(x) ( WATER_UNSIGN_X(x) / MAX_HUGE_SECTORS )
#define WATER_HUGE_Y(y) ( WATER_UNSIGN_Y(y) / MAX_HUGE_SECTORS )
#define WATER_FROM_HUGE_SECTOR_X(x) ( ((x) - (MAX_HUGE_SECTORS/2) ) * HUGE_SECTOR_SIZE )
#define WATER_FROM_HUGE_SECTOR_Y(y) ( ((y) - (MAX_HUGE_SECTORS/2) ) * HUGE_SECTOR_SIZE )
#define WATER_TO_HUGE_SECTOR_X(x) ( WATER_UNSIGN_X(x) / HUGE_SECTOR_SIZE )
#define WATER_TO_HUGE_SECTOR_Y(y) ( WATER_UNSIGN_Y(y) / HUGE_SECTOR_SIZE )
// 256
#define WATER_EXTRAHUGE_X(x) ( WATER_UNSIGN_X(x) / MAX_EXTRAHUGE_SECTORS )
#define WATER_EXTRAHUGE_Y(y) ( WATER_UNSIGN_Y(y) / MAX_EXTRAHUGE_SECTORS )
#define WATER_FROM_EXTRAHUGE_SECTOR_X(x) ( ((x) - (MAX_EXTRAHUGE_SECTORS/2)) * EXTRAHUGE_SECTOR_SIZE )
#define WATER_FROM_EXTRAHUGE_SECTOR_Y(y) ( ((y) - (MAX_EXTRAHUGE_SECTORS/2)) * EXTRAHUGE_SECTOR_SIZE )
#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;
};
enum eBeachToy
{
BEACHTOY_0 = 0,
BEACHTOY_BALL,
BEACHTOY_LOUNGE_WOOD_UP,
BEACHTOY_LOUNGE_TOWEL_UP,
BEACHTOY_LOUNGE_WOOD_ON,
BEACHTOY_ANY_LOUNGE,
BEACHTOY_LOTION,
BEACHTOY_TOWEL1,
BEACHTOY_TOWEL2,
BEACHTOY_TOWEL3,
BEACHTOY_TOWEL4,
BEACHTOY_ANY_TOWEL,
};
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 int8 aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS]; // 64x64 Large blocks 64x64 each
static int8 aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS]; // 128x128 Small blocks 32x32 each
static bool WavesCalculatedThisFrame;
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;
static void Initialise(Const char *pWaterDat); // out of class in III PC and later because of SecuROM
static void Shutdown();
static void CreateWavyAtomic();
static void DestroyWavyAtomic();
static void AddWaterLevel(float fXLeft, float fYBottom, float fXRight, float fYTop, float fLevel);
static bool WaterLevelAccordingToRectangles(float fX, float fY, float *pfOutLevel = nil);
static bool TestVisibilityForFineWaterBlocks(const CVector &worldPos);
static void RemoveIsolatedWater();
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 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);
};

689
src/renderer/Weather.cpp Normal file
View File

@ -0,0 +1,689 @@
#include "common.h"
#include "Weather.h"
#include "Camera.h"
#include "Clock.h"
#include "CutsceneMgr.h"
#include "DMAudio.h"
#include "General.h"
#include "Pad.h"
#include "PlayerPed.h"
#include "Particle.h"
#include "RenderBuffer.h"
#include "Stats.h"
#include "Shadows.h"
#include "Timecycle.h"
#include "Timer.h"
#include "Vehicle.h"
#include "World.h"
#include "ZoneCull.h"
#include "SpecialFX.h"
#include "Replay.h"
int32 CWeather::SoundHandle = -1;
int32 CWeather::WeatherTypeInList;
int16 CWeather::OldWeatherType;
int16 CWeather::NewWeatherType;
int16 CWeather::ForcedWeatherType;
bool CWeather::LightningFlash;
bool CWeather::LightningBurst;
uint32 CWeather::LightningStart;
uint32 CWeather::LightningFlashLastChange;
uint32 CWeather::WhenToPlayLightningSound;
uint32 CWeather::LightningDuration;
int32 CWeather::StreamAfterRainTimer;
float CWeather::ExtraSunnyness;
float CWeather::Foggyness;
float CWeather::CloudCoverage;
float CWeather::Wind;
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];
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_CLOUDY,
WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY,
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
};
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_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 Windyness[] = {
0.25f,// WEATHER_SUNNY
0.7f, // WEATHER_CLOUDY
1.0f, // WEATHER_RAINY
0.0f, // WEATHER_FOGGY
0.0f, // WEATHER_EXTRA_SUNNY
2.0f, // WEATHER_HURRICANE
0.0f
};
#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50)
#define RAIN_CHANGE_SPEED (0.003f)
#define DROPLETS_LEFT_OFFSET (10.0f)
#define DROPLETS_RIGHT_OFFSET (10.0f)
#define DROPLETS_TOP_OFFSET (10.0f)
#define DROPLETS_BOTTOM_OFFSET (10.0f)
#define STREAK_U (10.0f)
#define STREAK_V (18.0f)
#define LARGE_STREAK_COEFFICIENT (1.23f)
#define STREAK_MIN_DISTANCE (8.0f)
#define STREAK_MAX_DISTANCE (16.0f)
#define SPLASH_CHECK_RADIUS (7.0f)
#define SPLASH_OFFSET_RADIUS (2.0f)
#define STREAK_LIFETIME (4.0f)
#define STREAK_INTEROLATION_TIME (0.3f)
#define RAIN_COLOUR_R (200)
#define RAIN_COLOUR_G (200)
#define RAIN_COLOUR_B (256)
#define RAIN_ALPHA (255)
void CWeather::Init(void)
{
NewWeatherType = WEATHER_EXTRA_SUNNY;
bScriptsForceRain = false;
OldWeatherType = WEATHER_EXTRA_SUNNY;
InterpolationValue = 0.0f;
WhenToPlayLightningSound = 0;
WeatherTypeInList = 0;
ForcedWeatherType = WEATHER_RANDOM;
SoundHandle = DMAudio.CreateEntity(AUDIOTYPE_WEATHER, (void*)1);
if (SoundHandle >= 0)
DMAudio.SetEntityStatus(SoundHandle, TRUE);
}
void CWeather::Update(void)
{
if(!CReplay::IsPlayingBack()){
float fNewInterpolation = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f;
if (fNewInterpolation < InterpolationValue) {
// new hour
OldWeatherType = NewWeatherType;
if (ForcedWeatherType >= 0)
NewWeatherType = ForcedWeatherType;
else {
WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList);
NewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList];
}
}
InterpolationValue = fNewInterpolation;
}
#ifndef FINAL
if (CPad::GetPad(1)->GetRightShockJustDown()) {
NewWeatherType = (NewWeatherType + 1) % WEATHER_TOTAL;
OldWeatherType = NewWeatherType;
}
#endif
// Lightning
if (NewWeatherType != WEATHER_RAINY || OldWeatherType != WEATHER_RAINY) {
LightningFlash = false;
LightningBurst = false;
}
else{
if (LightningBurst) {
if ((CGeneral::GetRandomNumber() & 255) >= 32) {
// 0.875 probability
if (CTimer::GetTimeInMilliseconds() - LightningFlashLastChange > MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES) {
bool bOldLightningFlash = LightningFlash;
LightningFlash = CGeneral::GetRandomTrueFalse();
if (LightningFlash != bOldLightningFlash)
LightningFlashLastChange = CTimer::GetTimeInMilliseconds();
}
}
else {
// 0.125 probability
LightningBurst = false;
LightningDuration = Min(CTimer::GetFrameCounter() - LightningStart, 20);
LightningFlash = false;
WhenToPlayLightningSound = CTimer::GetTimeInMilliseconds() + 150 * (20 - LightningDuration);
}
}
else {
if (CGeneral::GetRandomNumber() >= 200) {
// lower probability on PC due to randomness bug
LightningFlash = false;
}
else {
LightningBurst = true;
LightningStart = CTimer::GetFrameCounter();
LightningFlashLastChange = CTimer::GetTimeInMilliseconds();
LightningFlash = true;
}
}
}
if (WhenToPlayLightningSound && CTimer::GetTimeInMilliseconds() > WhenToPlayLightningSound) {
DMAudio.PlayOneShot(SoundHandle, SOUND_LIGHTNING, LightningDuration);
CPad::GetPad(0)->StartShake(40 * LightningDuration + 100, 2 * LightningDuration + 80);
WhenToPlayLightningSound = 0;
}
// Wet roads
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 || NewWeatherType == WEATHER_HURRICANE)
WetRoads = InterpolationValue;
else
WetRoads = 0.0f;
}
// Rain
float fNewRain;
if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {
// if raining for >1 hour, values: 0, 0.33, switching every ~16.5s
fNewRain = (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.33f;
if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {
if (InterpolationValue < 0.4f)
// if rain has just started (<24 minutes), always 0.5
fNewRain = 0.5f;
else
// if rain is ongoing for >24 minutes, values: 0.25, 0.5, switching every ~16.5s
fNewRain = 0.25f + (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.25f;
}
fNewRain = Max(fNewRain, 0.5f);
}
else
fNewRain = 0.0f;
Rain = fNewRain;
// Clouds
if (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
CloudCoverage = 1.0f - InterpolationValue;
else
CloudCoverage = 0.0f;
if (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
CloudCoverage += InterpolationValue;
// Fog
if (OldWeatherType == WEATHER_FOGGY)
Foggyness = 1.0f - InterpolationValue;
else
Foggyness = 0.0f;
if (NewWeatherType == WEATHER_FOGGY)
Foggyness += InterpolationValue;
// 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_CLOUDY && (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 * Windyness[NewWeatherType] + (1.0f - InterpolationValue) * Windyness[OldWeatherType];
WindClipped = Min(1.0f, Wind);
if (CClock::GetHours() > 20)
TrafficLightBrightness = 1.0f;
else if (CClock::GetHours() > 19)
TrafficLightBrightness = CClock::GetMinutes() / 60.0f;
else if (CClock::GetHours() > 6)
TrafficLightBrightness = 0.0f;
else if (CClock::GetHours() > 5)
TrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f;
else
TrafficLightBrightness = 1.0f;
TrafficLightBrightness = Max(WetRoads, TrafficLightBrightness);
TrafficLightBrightness = Max(Foggyness, 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()
{
/*
if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED)
return;
CVector pos;
pos.x = SCREEN_WIDTH*0.5f;
if(TheCamera.GetLookingForwardFirstPerson())
pos.y = CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT*0.25f, SCREEN_HEIGHT*0.9f);
else
pos.y = CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT*0.4f, SCREEN_HEIGHT*0.9f);
pos.z = 100.0f;
CParticle::AddParticle(PARTICLE_HEATHAZE_IN_DIST, pos, CVector(0.0f, 0.0f, 0.0f));
*/
}
void CWeather::AddBeastie()
{
if(FindPlayerVehicle() || CTimer::GetFrameCounter()%10 || (CGeneral::GetRandomNumber()&5) == 0)
return;
CVector pos = TheCamera.GetPosition();
float dist = CGeneral::GetRandomNumberInRange(90.0f, 60.0f);
int angle = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE;
float c = CParticle::m_CosTable[angle];
float s = CParticle::m_SinTable[angle];
pos.x += dist*(c - s);
pos.y += dist*(c + s);
pos.z += CGeneral::GetRandomNumberInRange(7.5f, 30.0f);
CParticle::AddParticle(PARTICLE_BEASTIE, pos, CVector(0.0f, 0.0f, 0.0f));
}
void CWeather::ForceWeather(int16 weather)
{
ForcedWeatherType = weather;
}
void CWeather::ForceWeatherNow(int16 weather)
{
OldWeatherType = weather;
NewWeatherType = weather;
ForcedWeatherType = weather;
}
void CWeather::ReleaseWeather()
{
ForcedWeatherType = -1;
}
void CWeather::AddSplashesDuringHurricane()
{
RwRGBA colour = { 255, 255, 255, 32 };
CVector pos = TheCamera.pTargetEntity ? TheCamera.pTargetEntity->GetPosition() : TheCamera.GetPosition();
bool foundGround;
float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &foundGround) + 0.1f;
if(!foundGround)
groundZ = pos.z + 0.5f;
for(int i = 0; i < 20; i++){
float dist = (CGeneral::GetRandomNumber()&0xFF)/255.0f +
CGeneral::GetRandomNumberInRange(-10.0f, 30.0f);
float angle;
uint8 rnd = CGeneral::GetRandomNumber();
if(rnd&1)
angle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI;
else
angle = TheCamera.Orientation + (rnd-128)/160.0f;
pos.x = TheCamera.GetPosition().x + dist*Sin(angle);
pos.y = TheCamera.GetPosition().y + dist*Cos(angle);
pos.z = groundZ;
if(foundGround)
CParticle::AddParticle(PARTICLE_GROUND_STEAM, pos, CVector(-0.002f, -0.002f, 0.015f), nil, 0.0f, colour);
}
}
static int startStreamAfterRain;
void CWeather::AddStreamAfterRain()
{
if(CClock::GetHours() > 6 && CClock::GetHours() < 18){
RwRGBA colour = { 255, 255, 255, 24 };
CVector pos = TheCamera.pTargetEntity ? TheCamera.pTargetEntity->GetPosition() : TheCamera.GetPosition();
bool foundGround;
float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &foundGround) + 0.2f;
if(!foundGround)
groundZ = pos.z + 0.75f;
for(int i = 0; i < 20; i++){
float dist = (CGeneral::GetRandomNumber()&0xFF)/255.0f +
CGeneral::GetRandomNumberInRange(-10.0f, 30.0f);
float angle;
uint8 rnd = CGeneral::GetRandomNumber();
if(rnd&1)
angle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI;
else
angle = TheCamera.Orientation + (rnd-128)/160.0f;
pos.x = TheCamera.GetPosition().x + dist*Sin(angle);
pos.y = TheCamera.GetPosition().y + dist*Cos(angle);
pos.z = groundZ;
CParticle::AddParticle(PARTICLE_GROUND_STEAM, pos, CVector(0.0f, 0.0f, 0.015f), nil, 0.0f, colour);
}
}else{
startStreamAfterRain = 0;
StreamAfterRainTimer = 800;
}
}
void CWeather::AddRain()
{
if (CCullZones::CamNoRain() || CCullZones::PlayerNoRain())
return;
if (TheCamera.GetLookingLRBFirstPerson()) {
CVehicle* pVehicle = FindPlayerVehicle();
if (pVehicle && pVehicle->CarHasRoof()) {
CParticle::RemovePSystem(PARTICLE_RAINDROP_2D);
return;
}
}
if(Rain > 0.0){
startStreamAfterRain = 1;
StreamAfterRainTimer = 800;
}else if(startStreamAfterRain){
if(StreamAfterRainTimer > 0){
AddStreamAfterRain();
StreamAfterRainTimer--;
}else{
startStreamAfterRain = 0;
StreamAfterRainTimer = 800;
}
}
if (Wind > 1.1f)
AddSplashesDuringHurricane();
if (Rain <= 0.1f)
return;
static RwRGBA colour;
int numDrops = 5.0f * Rain;
int numSplashes = 2.0f * Rain;
CVector pos, dir;
for(int i = 0; i < numDrops; i++){
pos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH);
pos.y = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_HEIGHT/5);
pos.z = 0.0f;
dir.x = 0.0f;
dir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f);
dir.z = 0.0f;
CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0);
pos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH);
pos.y = CGeneral::GetRandomNumberInRange((int)SCREEN_HEIGHT/5, (int)SCREEN_HEIGHT/2);
pos.z = 0.0f;
dir.x = 0.0f;
dir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f);
dir.z = 0.0f;
CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0);
pos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH);
pos.y = 0.0f;
pos.z = 0.0f;
dir.x = 0.0f;
dir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f);
dir.z = 0.0f;
CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0);
float dist = CGeneral::GetRandomNumberInRange(0.0f, Max(10.0f*Rain, 40.0f)/2.0f);
float angle;
uint8 rnd = CGeneral::GetRandomNumber();
if(rnd&1)
angle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI;
else
angle = TheCamera.Orientation + (rnd-128)/160.0f;
pos.x = TheCamera.GetPosition().x + dist*Sin(angle);
pos.y = TheCamera.GetPosition().y + dist*Cos(angle);
pos.z = 0.0f;
CColPoint point;
CEntity *ent;
if(CWorld::ProcessVerticalLine(pos+CVector(0.0f, 0.0f, 40.0f), -40.0f, point, ent, true, false, false, false, true, false, nil)){
pos.z = point.point.z;
for(int j = 0; j < numSplashes+15; j++){
CVector pos2 = pos;
pos2.x += CGeneral::GetRandomNumberInRange(-15.0f, 15.0f);
pos2.y += CGeneral::GetRandomNumberInRange(-15.0f, 15.0f);
if(CGeneral::GetRandomNumber() & 1)
CParticle::AddParticle(PARTICLE_RAIN_SPLASH, pos2, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour);
else
CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, pos2, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour);
}
}
}
}
void RenderOneRainStreak(CVector pos, CVector unused, int intensity, bool scale, float distance)
{
static float RandomTex;
static float RandomTexX;
static float RandomTexY;
TempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored + 0;
TempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored + 2;
TempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored + 1;
TempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored + 0;
TempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored + 3;
TempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored + 2;
TempBufferRenderIndexList[TempBufferIndicesStored + 6] = TempBufferVerticesStored + 1;
TempBufferRenderIndexList[TempBufferIndicesStored + 7] = TempBufferVerticesStored + 2;
TempBufferRenderIndexList[TempBufferIndicesStored + 8] = TempBufferVerticesStored + 4;
TempBufferRenderIndexList[TempBufferIndicesStored + 9] = TempBufferVerticesStored + 2;
TempBufferRenderIndexList[TempBufferIndicesStored + 10] = TempBufferVerticesStored + 3;
TempBufferRenderIndexList[TempBufferIndicesStored + 11] = TempBufferVerticesStored + 4;
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0, 0, 0, 0);
RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 0], pos.x + 11.0f * TheCamera.GetUp().x, pos.y + 11.0f * TheCamera.GetUp().y, pos.z + 11.0f * TheCamera.GetUp().z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 1], 0, 0, 0, 0);
RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 1], pos.x - 9.0f * TheCamera.GetRight().x, pos.y - 9.0f * TheCamera.GetRight().y, pos.z - 9.0f * TheCamera.GetRight().z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RAIN_COLOUR_R * intensity / 256, RAIN_COLOUR_G * intensity / 256, RAIN_COLOUR_B * intensity / 256, RAIN_ALPHA);
RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 2], pos.x, pos.y, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 3], 0, 0, 0, 0);
RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 3], pos.x + 9.0f * TheCamera.GetRight().x, pos.y + 9.0f * TheCamera.GetRight().y, pos.z + 9.0f * TheCamera.GetRight().z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0, 0, 0, 0);
RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 4], pos.x - 11.0f * TheCamera.GetUp().x, pos.y - 11.0f * TheCamera.GetUp().y, pos.z - 11.0f * TheCamera.GetUp().z);
float u = STREAK_U;
float v = STREAK_V;
if (scale) {
u *= LARGE_STREAK_COEFFICIENT;
v *= LARGE_STREAK_COEFFICIENT;
}
float distance_coefficient;
if (distance < STREAK_MIN_DISTANCE)
distance_coefficient = 1.0f;
else if (distance > STREAK_MAX_DISTANCE)
distance_coefficient = 0.5f;
else
distance_coefficient = 1.0f - 0.5f * (distance - STREAK_MIN_DISTANCE) / (STREAK_MAX_DISTANCE - STREAK_MIN_DISTANCE);
u *= distance_coefficient;
v *= distance_coefficient;
if (!CTimer::GetIsPaused()) {
RandomTex = 0.0f;
RandomTexX = 0.0f;
RandomTexY = 0.0f;
}
RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0.5f * u - RandomTex + RandomTexX);
RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 0], -v * 0.5f + RandomTexY);
RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexX);
RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexY);
RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 2], 0.5f * u + RandomTexX);
RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RandomTexY);
RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 3], u + RandomTexX);
RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 3], RandomTexY);
RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0.5f * u + RandomTex + RandomTexX);
RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 5], 0.5f * v + RandomTexY);
TempBufferIndicesStored += 12;
TempBufferVerticesStored += 5;
}
void CWeather::RenderRainStreaks(void)
{
if (CTimer::GetIsCodePaused())
return;
int base_intensity = (64.0f - CTimeCycle::GetFogReduction()) / 64.0f * int(255 * Rain);
if (base_intensity == 0)
return;
if (TheCamera.m_CameraAverageSpeed > 1.75f)
return;
TempBufferIndicesStored = 0;
TempBufferVerticesStored = 0;
for (int i = 0; i < NUM_RAIN_STREAKS; i++) {
if (Streaks[i].timer) {
float secondsElapsed = (CTimer::GetTimeInMilliseconds() - Streaks[i].timer) / 1024.0f;
if (secondsElapsed > STREAK_LIFETIME)
Streaks[i].timer = 0;
else{
int intensity;
if (secondsElapsed < STREAK_INTEROLATION_TIME)
intensity = base_intensity * 0.25f * secondsElapsed / STREAK_INTEROLATION_TIME;
else if (secondsElapsed > (STREAK_LIFETIME - STREAK_INTEROLATION_TIME))
intensity = (STREAK_LIFETIME - secondsElapsed) * 0.25f * base_intensity / STREAK_INTEROLATION_TIME;
else
intensity = base_intensity * 0.25f;
CVector dir = Streaks[i].direction;
dir.Normalise();
CVector pos = Streaks[i].position + secondsElapsed * Streaks[i].direction;
RenderOneRainStreak(pos, dir, intensity, false, (pos - TheCamera.GetPosition()).Magnitude());
#ifndef FIX_BUGS // remove useless code
if (secondsElapsed > 1.0f && secondsElapsed < STREAK_LIFETIME - 1.0f) {
CGeneral::GetRandomNumber(), CGeneral::GetRandomNumber();
}
#endif
}
}
else if ((CGeneral::GetRandomNumber() & 0xF00) == 0){
// 1/16 probability
Streaks[i].direction = CVector(0.0f, 0.0f, -12.0f);
Streaks[i].position = 6.0f * TheCamera.GetForward() + TheCamera.GetPosition() + CVector(-1.8f * Streaks[i].direction.x, -1.8f * Streaks[i].direction.y, 8.0f);
if (!CCutsceneMgr::IsRunning()) {
Streaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f;
Streaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f;
}
else
Streaks[i].position += (TheCamera.GetPosition() - TheCamera.m_RealPreviousCameraPosition) * 20.0f;
Streaks[i].position.x += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.04f;
Streaks[i].position.y += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.04f;
Streaks[i].timer = CTimer::GetTimeInMilliseconds();
}
}
if (TempBufferIndicesStored){
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(gpRainDropTex));
if (RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 1))
{
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 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;
}
#ifdef SECUROM
void CWeather::ForceHurricaneWeather()
{
for (int i = 0; i < ARRAY_SIZE(WeatherTypesList_WithHurricanes); i++)
{
WeatherTypesList[i] = WEATHER_HURRICANE;
WeatherTypesList_WithHurricanes[i] = WEATHER_HURRICANE;
}
CWeather::OldWeatherType = WEATHER_HURRICANE;
CWeather::NewWeatherType = WEATHER_HURRICANE;
CWeather::ForcedWeatherType = WEATHER_HURRICANE;
}
#endif

80
src/renderer/Weather.h Normal file
View File

@ -0,0 +1,80 @@
enum {
WEATHER_RANDOM = -1,
WEATHER_SUNNY = 0,
WEATHER_CLOUDY,
WEATHER_RAINY,
WEATHER_FOGGY,
WEATHER_EXTRA_SUNNY,
WEATHER_HURRICANE,
WEATHER_TOTAL,
WEATHER_EXTRACOLOURS = 6
};
class CWeather
{
public:
static int32 SoundHandle;
static int32 WeatherTypeInList;
static int16 OldWeatherType;
static int16 NewWeatherType;
static int16 ForcedWeatherType;
static bool LightningFlash;
static bool LightningBurst;
static uint32 LightningStart;
static uint32 LightningFlashLastChange;
static uint32 WhenToPlayLightningSound;
static uint32 LightningDuration;
static int32 StreamAfterRainTimer;
static float ExtraSunnyness;
static float Foggyness;
static float CloudCoverage;
static float Wind;
static float Rain;
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);
static void Init(void);
static void ReleaseWeather();
static void ForceWeather(int16);
static void ForceWeatherNow(int16);
static void AddSplashesDuringHurricane();
static void AddStreamAfterRain();
static void AddRain();
static void AddHeatHaze();
static void AddBeastie();
static void ForceHurricaneWeather();
static void StoreWeatherState();
static void RestoreWeatherState();
};
enum {
NUM_RAIN_STREAKS = 35
};
struct tRainStreak
{
CVector position;
CVector direction;
uint32 timer;
};
extern RwTexture* gpRainDropTex;

View File

@ -0,0 +1,52 @@
#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;
float fade = distFade * heightFade * 0.5f;
dir = (pos - Array[i].m_pos) * fade / 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;
}

View File

@ -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);
};