mirror of
https://github.com/halpz/re3.git
synced 2025-07-08 00:58:58 +00:00
first commit
This commit is contained in:
README.mdpremake5.cmdpremake5.exepremake5.lua
src
Camera.cppCamera.hClock.cppClock.hCollision.cppCollision.hCullZones.cppCullZones.hGame.cppGame.hGeneral.hGlass.cppGlass.hLists.cppLists.hMenuManager.cppMenuManager.hNodeName.cppNodeName.hPad.cppPad.hParticleObject.cppParticleObject.hPathFind.cppPathFind.hPlaceable.cppPlaceable.hPools.cppPools.hReferences.cppReferences.hRwHelper.cppRwHelper.hStreaming.cppStreaming.hSurfaceTable.cppSurfaceTable.hTimecycle.cppTimecycle.hTimer.cppTimer.hTxdStore.cppTxdStore.hWeather.cppWeather.hWorld.cppWorld.hZones.cppZones.hcommon.hconfig.hdebugmenu_public.h
entities
Building.cppBuilding.hCutsceneHead.cppCutsceneHead.hCutsceneObject.cppCutsceneObject.hEntity.cppEntity.hObject.cppObject.hPed.hPhysical.cppPhysical.hTreadable.cppTreadable.hVehicle.h
main.cppmath
modelinfo
BaseModelInfo.cppBaseModelInfo.hClumpModelInfo.cppClumpModelInfo.hModelIndices.cppModelIndices.hModelInfo.cppModelInfo.hPedModelInfo.cppPedModelInfo.hSimpleModelInfo.cppSimpleModelInfo.hTimeModelInfo.cppTimeModelInfo.hVehicleModelInfo.cppVehicleModelInfo.h
patcher.cpppatcher.hrender
2dEffect.hClouds.cppClouds.hCoronas.cppCoronas.hDraw.cppDraw.hLights.cppLights.hParticle.cppParticle.hRenderBuffer.cppRenderBuffer.hRenderer.cppRenderer.hSprite.cppSprite.hVisibilityPlugins.cppVisibilityPlugins.h
rw.cpptemplates.h
39
src/render/2dEffect.h
Normal file
39
src/render/2dEffect.h
Normal file
@ -0,0 +1,39 @@
|
||||
class C2dEffect
|
||||
{
|
||||
public:
|
||||
struct Light {
|
||||
float dist;
|
||||
float outerRange;
|
||||
float size;
|
||||
float innerRange;
|
||||
uint8 flash;
|
||||
uint8 wet;
|
||||
uint8 flare;
|
||||
uint8 shadowIntens;
|
||||
uint8 flag;
|
||||
RwTexture *corona;
|
||||
RwTexture *shadow;
|
||||
};
|
||||
struct Particle {
|
||||
int particleType;
|
||||
float dir[3];
|
||||
float scale;
|
||||
};
|
||||
struct Attractor {
|
||||
CVector dir;
|
||||
uint8 flag;
|
||||
uint8 probability;
|
||||
};
|
||||
|
||||
CVector pos;
|
||||
RwRGBA col;
|
||||
uint8 type;
|
||||
union {
|
||||
Light light;
|
||||
Particle particle;
|
||||
Attractor attractor;
|
||||
};
|
||||
|
||||
C2dEffect(void) {}
|
||||
};
|
||||
static_assert(sizeof(C2dEffect) == 0x34, "C2dEffect: error");
|
430
src/render/Clouds.cpp
Normal file
430
src/render/Clouds.cpp
Normal file
@ -0,0 +1,430 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Sprite.h"
|
||||
#include "General.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 = (RwTexture**)0x9411C0; //[5];
|
||||
|
||||
float &CClouds::CloudRotation = *(float*)0x8F5F40;
|
||||
uint32 &CClouds::IndividualRotation = *(uint32*)0x943078;
|
||||
|
||||
float &CClouds::ms_cameraRoll = *(float*)0x8F29CC;
|
||||
float &CClouds::ms_horizonZ = *(float*)0x8F31C0;
|
||||
CRGBA &CClouds::ms_colourTop = *(CRGBA*)0x94143C;
|
||||
CRGBA &CClouds::ms_colourBottom = *(CRGBA*)0x8F2C38;
|
||||
|
||||
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::Update(void)
|
||||
{
|
||||
float s = sin(TheCamera.Orientation - 0.85f);
|
||||
CloudRotation += CWeather::Wind*s*0.0025f;
|
||||
IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f) * 60.0f;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CClouds::Render(void)
|
||||
{
|
||||
int i;
|
||||
float szx, szy;
|
||||
RwV3d screenpos;
|
||||
RwV3d worldpos;
|
||||
|
||||
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();
|
||||
|
||||
int minute = CClock::GetHours()*60 + CClock::GetMinutes();
|
||||
RwV3d campos = *(RwV3d*)&TheCamera.GetPosition();
|
||||
|
||||
float coverage = CWeather::CloudCoverage <= CWeather::Foggyness ? CWeather::Foggyness : CWeather::CloudCoverage;
|
||||
|
||||
// Moon
|
||||
int moonfadeout = abs(minute - 180); // fully visible at 3AM
|
||||
if(moonfadeout < 180){ // fade in/out 3 hours
|
||||
int brightness = (1.0f - coverage) * (180 - moonfadeout);
|
||||
RwV3d pos = { 0.0f, -100.0f, 15.0f };
|
||||
RwV3dAdd(&worldpos, &campos, &pos);
|
||||
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[2]->raster);
|
||||
if(CCoronas::bSmallMoon){
|
||||
szx *= 4.0f;
|
||||
szy *= 4.0f;
|
||||
}else{
|
||||
szx *= 10.0f;
|
||||
szy *= 10.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){
|
||||
// R
|
||||
static float StarCoorsX[9] = { 0.0f, 0.05f, 0.12f, 0.5f, 0.8f, 0.6f, 0.27f, 0.55f, 0.75f };
|
||||
static float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f };
|
||||
static float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f };
|
||||
int brightness = (1.0f - coverage) * starintens;
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
|
||||
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, gpCoronaTexture[0]->raster);
|
||||
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
|
||||
static 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 };
|
||||
static 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 };
|
||||
static 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 lowcloudintensity = 1.0f - coverage;
|
||||
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, gpCloudTex[cloudtype]->raster);
|
||||
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 - CWeather::Foggyness);
|
||||
if(fluffyalpha != 0){
|
||||
static 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
|
||||
};
|
||||
static 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
|
||||
};
|
||||
static 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
|
||||
};
|
||||
static bool bCloudOnScreen[37];
|
||||
float hilight;
|
||||
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[4]->raster);
|
||||
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)){
|
||||
float sundist = sqrt(sq(screenpos.x-CCoronas::SunScreenX) + sq(screenpos.y-CCoronas::SunScreenY));
|
||||
int tr = CTimeCycle::GetFluffyCloudsTopRed();
|
||||
int tg = CTimeCycle::GetFluffyCloudsTopGreen();
|
||||
int tb = CTimeCycle::GetFluffyCloudsTopBlue();
|
||||
int br = CTimeCycle::GetFluffyCloudsBottomRed();
|
||||
int bg = CTimeCycle::GetFluffyCloudsBottomGreen();
|
||||
int bb = CTimeCycle::GetFluffyCloudsBottomBlue();
|
||||
if(sundist < SCREENW/2){
|
||||
hilight = (1.0f - coverage) * (1.0f - sundist/(SCREENW/2));
|
||||
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 < SCREENW/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,
|
||||
IndividualRotation/65336.0f * 2*3.14f + ms_cameraRoll,
|
||||
fluffyalpha);
|
||||
bCloudOnScreen[i] = true;
|
||||
}else
|
||||
bCloudOnScreen[i] = false;
|
||||
}
|
||||
CSprite::FlushSpriteBuffer();
|
||||
|
||||
// Highlights
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[3]->raster);
|
||||
|
||||
for(i = 0; i < 37; i++){
|
||||
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
|
||||
worldpos.x = campos.x*rot_cos + campos.y*rot_sin + pos.x;
|
||||
worldpos.y = campos.x*rot_sin + campos.y*rot_cos + pos.y;
|
||||
worldpos.z = pos.z;
|
||||
if(bCloudOnScreen[i] && CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
|
||||
// BUG: this is stupid....would have to do this for each cloud individually
|
||||
if(hilight > 0.0f){
|
||||
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){
|
||||
static uint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 };
|
||||
static uint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 };
|
||||
static uint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 };
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
|
||||
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);
|
||||
}
|
||||
|
||||
bool
|
||||
UseDarkBackground(void)
|
||||
{
|
||||
return RwFrameGetLTM(RwCameraGetFrame(TheCamera.m_pRwCamera))->up.z < -0.9f ||
|
||||
gbShowCollisionPolys;
|
||||
}
|
||||
|
||||
void
|
||||
CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue,
|
||||
int16 botred, int16 botgreen, int16 botblue, int16 alpha)
|
||||
{
|
||||
RwMatrix *mat = RwFrameGetLTM(RwCameraGetFrame(TheCamera.m_pRwCamera));
|
||||
float c = sqrt(mat->right.x * mat->right.x + mat->right.y * mat->right.y);
|
||||
if(c > 1.0f)
|
||||
c = 1.0f;
|
||||
ms_cameraRoll = acos(c);
|
||||
if(mat->right.z < 0.0f)
|
||||
ms_cameraRoll = -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, SCREENW, SCREENH);
|
||||
CSprite2d::DrawRect(r, ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
|
||||
}else{
|
||||
ms_horizonZ = CSprite::CalcHorizonCoors();
|
||||
|
||||
// Draw top/bottom gradient
|
||||
float gradheight = SCREENH/2.0f;
|
||||
float topedge = ms_horizonZ - gradheight;
|
||||
float botpos, toppos;
|
||||
if(ms_horizonZ > 0.0f && topedge < SCREENH){
|
||||
ms_colourTop.r = topred;
|
||||
ms_colourTop.g = topgreen;
|
||||
ms_colourTop.b = topblue;
|
||||
ms_colourTop.a = alpha;
|
||||
ms_colourBottom.r = botred;
|
||||
ms_colourBottom.g = botgreen;
|
||||
ms_colourBottom.b = botblue;
|
||||
ms_colourBottom.a = alpha;
|
||||
|
||||
if(ms_horizonZ < SCREENH)
|
||||
botpos = ms_horizonZ;
|
||||
else{
|
||||
float f = (ms_horizonZ - SCREENH)/gradheight;
|
||||
ms_colourBottom.r = topred*f + (1.0f-f)*botred;
|
||||
ms_colourBottom.g = topgreen*f + (1.0f-f)*botgreen;
|
||||
ms_colourBottom.b = topblue*f + (1.0f-f)*botblue;
|
||||
botpos = SCREENH;
|
||||
}
|
||||
if(topedge >= 0.0f)
|
||||
toppos = topedge;
|
||||
else{
|
||||
float f = (0.0f - topedge)/gradheight;
|
||||
ms_colourTop.r = botred*f + (1.0f-f)*topred;
|
||||
ms_colourTop.g = botgreen*f + (1.0f-f)*topgreen;
|
||||
ms_colourTop.b = botblue*f + (1.0f-f)*topblue;
|
||||
toppos = 0.0f;
|
||||
}
|
||||
CSprite2d::DrawRect(CRect(0, toppos, SCREENW, botpos),
|
||||
ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
|
||||
}
|
||||
|
||||
// draw the small stripe (whatever it's supposed to be)
|
||||
if(ms_horizonZ > -SMALLSTRIPHEIGHT && ms_horizonZ < SCREENH){
|
||||
// Same colour as fog
|
||||
ms_colourTop.r = (topred + 2 * botred) / 3;
|
||||
ms_colourTop.g = (topgreen + 2 * botgreen) / 3;
|
||||
ms_colourTop.b = (topblue + 2 * botblue) / 3;
|
||||
CSprite2d::DrawRect(CRect(0, ms_horizonZ, SCREENW, ms_horizonZ+SMALLSTRIPHEIGHT),
|
||||
ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop);
|
||||
}
|
||||
|
||||
// Only top
|
||||
if(topedge > 0.0f){
|
||||
ms_colourTop.r = topred;
|
||||
ms_colourTop.g = topgreen;
|
||||
ms_colourTop.b = topblue;
|
||||
ms_colourTop.a = alpha;
|
||||
ms_colourBottom.r = topred;
|
||||
ms_colourBottom.g = topgreen;
|
||||
ms_colourBottom.b = topblue;
|
||||
ms_colourBottom.a = alpha;
|
||||
|
||||
botpos = min(SCREENH, topedge);
|
||||
CSprite2d::DrawRect(CRect(0, 0, SCREENW, botpos),
|
||||
ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
|
||||
}
|
||||
|
||||
// Set both to fog colour for RenderHorizon
|
||||
ms_colourTop.r = (topred + 2 * botred) / 3;
|
||||
ms_colourTop.g = (topgreen + 2 * botgreen) / 3;
|
||||
ms_colourTop.b = (topblue + 2 * botblue) / 3;
|
||||
ms_colourBottom.r = (topred + 2 * botred) / 3;
|
||||
ms_colourBottom.g = (topgreen + 2 * botgreen) / 3;
|
||||
ms_colourBottom.b = (topblue + 2 * botblue) / 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClouds::RenderHorizon(void)
|
||||
{
|
||||
if(UseDarkBackground())
|
||||
return;
|
||||
|
||||
ms_colourBottom.a = 230;
|
||||
ms_colourTop.a = 80;
|
||||
|
||||
if(ms_horizonZ > SCREENH)
|
||||
return;
|
||||
|
||||
float z1 = min(ms_horizonZ + SMALLSTRIPHEIGHT, SCREENH);
|
||||
CSprite2d::DrawRectXLU(CRect(0, ms_horizonZ, SCREENW, z1),
|
||||
ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
|
||||
|
||||
// This is just weird
|
||||
float a = SCREENH/400.0f * HORIZSTRIPHEIGHT +
|
||||
SCREENH/300.0f * max(TheCamera.GetPosition().z, 0.0f);
|
||||
float b = TheCamera.GetUp().z < 0.0f ?
|
||||
SCREENH :
|
||||
SCREENH * fabs(TheCamera.GetRight().z);
|
||||
float z2 = z1 + (a + b)*TheCamera.LODDistMultiplier;
|
||||
z2 = min(z2, SCREENH);
|
||||
CSprite2d::DrawRect(CRect(0, z1, SCREENW, z2),
|
||||
ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4F6C10, CClouds::Init, PATCH_JUMP);
|
||||
InjectHook(0x4F6CE0, CClouds::Update, PATCH_JUMP);
|
||||
InjectHook(0x4F6D90, CClouds::Render, PATCH_JUMP);
|
||||
InjectHook(0x4F7F00, CClouds::RenderBackground, PATCH_JUMP);
|
||||
InjectHook(0x4F85F0, CClouds::RenderHorizon, PATCH_JUMP);
|
||||
ENDPATCHES
|
20
src/render/Clouds.h
Normal file
20
src/render/Clouds.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
class CClouds
|
||||
{
|
||||
public:
|
||||
static float &CloudRotation;
|
||||
static uint32 &IndividualRotation;
|
||||
|
||||
static float &ms_cameraRoll;
|
||||
static float &ms_horizonZ;
|
||||
static CRGBA &ms_colourTop;
|
||||
static CRGBA &ms_colourBottom;
|
||||
|
||||
static void Init(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);
|
||||
};
|
10
src/render/Coronas.cpp
Normal file
10
src/render/Coronas.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "common.h"
|
||||
#include "Coronas.h"
|
||||
|
||||
RwTexture **gpCoronaTexture = (RwTexture**)0x5FAF44; //[9]
|
||||
|
||||
float &CCoronas::LightsMult = *(float*)0x5FB088; // 1.0
|
||||
float &CCoronas::SunScreenX = *(float*)0x8F4358;
|
||||
float &CCoronas::SunScreenY = *(float*)0x8F4354;
|
||||
bool &CCoronas::bSmallMoon = *(bool*)0x95CD49;
|
||||
bool &CCoronas::SunBlockedByClouds = *(bool*)0x95CD73;
|
13
src/render/Coronas.h
Normal file
13
src/render/Coronas.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
extern RwTexture **gpCoronaTexture; //[9]
|
||||
|
||||
class CCoronas
|
||||
{
|
||||
public:
|
||||
static float &LightsMult;
|
||||
static float &SunScreenY;
|
||||
static float &SunScreenX;
|
||||
static bool &bSmallMoon;
|
||||
static bool &SunBlockedByClouds;
|
||||
};
|
6
src/render/Draw.cpp
Normal file
6
src/render/Draw.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "Draw.h"
|
||||
|
||||
float &CDraw::ms_fNearClipZ = *(float*)0x8E2DC4;
|
||||
float &CDraw::ms_fFarClipZ = *(float*)0x9434F0;
|
||||
float &CDraw::ms_fFOV = *(float*)0x5FBC6C;
|
16
src/render/Draw.h
Normal file
16
src/render/Draw.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
class CDraw
|
||||
{
|
||||
private:
|
||||
static float &ms_fNearClipZ;
|
||||
static float &ms_fFarClipZ;
|
||||
static float &ms_fFOV;
|
||||
public:
|
||||
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) { ms_fFOV = fov; }
|
||||
static float GetFOV(void) { return ms_fFOV; }
|
||||
};
|
171
src/render/Lights.cpp
Normal file
171
src/render/Lights.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
#include "common.h"
|
||||
#include <rwcore.h>
|
||||
#include <rpworld.h>
|
||||
#include "patcher.h"
|
||||
#include "Lights.h"
|
||||
#include "Timecycle.h"
|
||||
#include "Coronas.h"
|
||||
#include "Weather.h"
|
||||
#include "CullZones.h"
|
||||
#include "MenuManager.h"
|
||||
|
||||
RpLight *&pAmbient = *(RpLight**)0x885B6C;
|
||||
RpLight *&pDirect = *(RpLight**)0x880F7C;
|
||||
|
||||
RwRGBAReal &AmbientLightColourForFrame = *(RwRGBAReal*)0x6F46F8;
|
||||
RwRGBAReal &AmbientLightColourForFrame_PedsCarsAndObjects = *(RwRGBAReal*)0x6F1D10;
|
||||
RwRGBAReal &DirectionalLightColourForFrame = *(RwRGBAReal*)0x87C6B8;
|
||||
|
||||
RwRGBAReal &AmbientLightColour = *(RwRGBAReal*)0x86B0F8;
|
||||
RwRGBAReal &DirectionalLightColour = *(RwRGBAReal*)0x72E308;
|
||||
|
||||
void
|
||||
SetLightsWithTimeOfDayColour(RpWorld *)
|
||||
{
|
||||
CVector vec1, vec2, vecsun;
|
||||
RwMatrix mat;
|
||||
|
||||
if(pAmbient){
|
||||
AmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed() * CCoronas::LightsMult;
|
||||
AmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen() * CCoronas::LightsMult;
|
||||
AmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue() * CCoronas::LightsMult;
|
||||
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
|
||||
AmbientLightColourForFrame.red = 1.0f;
|
||||
AmbientLightColourForFrame.green = 1.0f;
|
||||
AmbientLightColourForFrame.blue = 1.0f;
|
||||
}
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.red = min(1.0f, AmbientLightColourForFrame.red*1.3f);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.green = min(1.0f, AmbientLightColourForFrame.green*1.3f);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.blue = min(1.0f, AmbientLightColourForFrame.blue*1.3f);
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
}
|
||||
|
||||
if(pDirect){
|
||||
DirectionalLightColourForFrame.red = CTimeCycle::GetDirectionalRed() * CCoronas::LightsMult;
|
||||
DirectionalLightColourForFrame.green = CTimeCycle::GetDirectionalGreen() * CCoronas::LightsMult;
|
||||
DirectionalLightColourForFrame.blue = CTimeCycle::GetDirectionalBlue() * CCoronas::LightsMult;
|
||||
RpLightSetColor(pDirect, &DirectionalLightColourForFrame);
|
||||
|
||||
vecsun = CTimeCycle::m_VectorToSun[CTimeCycle::m_CurrentStoredValue];
|
||||
vec1 = CVector(0.0f, 0.0f, 1.0f);
|
||||
vec2 = CrossProduct(vec1, vecsun);
|
||||
vec2.Normalise();
|
||||
vec1 = CrossProduct(vec2, vecsun);
|
||||
mat.at.x = -vecsun.x;
|
||||
mat.at.y = -vecsun.y;
|
||||
mat.at.z = -vecsun.z;
|
||||
mat.right.x = vec1.x;
|
||||
mat.right.y = vec1.y;
|
||||
mat.right.z = vec1.z;
|
||||
mat.up.x = vec2.x;
|
||||
mat.up.y = vec2.y;
|
||||
mat.up.z = vec2.z;
|
||||
RwFrameTransform(RpLightGetFrame(pDirect), &mat, rwCOMBINEREPLACE);
|
||||
}
|
||||
|
||||
if(CMenuManager::m_PrefsBrightness > 256){
|
||||
float f1 = 2.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f;
|
||||
float f2 = 3.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f;
|
||||
|
||||
AmbientLightColourForFrame.red = min(1.0f, AmbientLightColourForFrame.red * f2);
|
||||
AmbientLightColourForFrame.green = min(1.0f, AmbientLightColourForFrame.green * f2);
|
||||
AmbientLightColourForFrame.blue = min(1.0f, AmbientLightColourForFrame.blue * f2);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.red = min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.red * f1);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.green = min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.green * f1);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.blue = min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.blue * f1);
|
||||
#ifdef FIX_BUGS
|
||||
DirectionalLightColourForFrame.red = min(1.0f, DirectionalLightColourForFrame.red * f1);
|
||||
DirectionalLightColourForFrame.green = min(1.0f, DirectionalLightColourForFrame.green * f1);
|
||||
DirectionalLightColourForFrame.blue = min(1.0f, DirectionalLightColourForFrame.blue * f1);
|
||||
#else
|
||||
DirectionalLightColourForFrame.red = min(1.0f, AmbientLightColourForFrame.red * f1);
|
||||
DirectionalLightColourForFrame.green = min(1.0f, AmbientLightColourForFrame.green * f1);
|
||||
DirectionalLightColourForFrame.blue = min(1.0f, AmbientLightColourForFrame.blue * f1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientAndDirectionalColours(float f)
|
||||
{
|
||||
AmbientLightColour.red = AmbientLightColourForFrame.red * f;
|
||||
AmbientLightColour.green = AmbientLightColourForFrame.green * f;
|
||||
AmbientLightColour.blue = AmbientLightColourForFrame.blue * f;
|
||||
|
||||
DirectionalLightColour.red = DirectionalLightColourForFrame.red * f;
|
||||
DirectionalLightColour.green = DirectionalLightColourForFrame.green * f;
|
||||
DirectionalLightColour.blue = DirectionalLightColourForFrame.blue * f;
|
||||
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColour);
|
||||
}
|
||||
|
||||
void
|
||||
SetBrightMarkerColours(float f)
|
||||
{
|
||||
AmbientLightColour.red = 0.6f;
|
||||
AmbientLightColour.green = 0.6f;
|
||||
AmbientLightColour.blue = 0.6f;
|
||||
|
||||
DirectionalLightColour.red = (1.0f - DirectionalLightColourForFrame.red) * 0.4f + DirectionalLightColourForFrame.red;
|
||||
DirectionalLightColour.green = (1.0f - DirectionalLightColourForFrame.green) * 0.4f + DirectionalLightColourForFrame.green;
|
||||
DirectionalLightColour.blue = (1.0f - DirectionalLightColourForFrame.blue) * 0.4f + DirectionalLightColourForFrame.blue;
|
||||
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColour);
|
||||
}
|
||||
|
||||
void
|
||||
ReSetAmbientAndDirectionalColours(void)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColourForFrame);
|
||||
}
|
||||
|
||||
void
|
||||
DeActivateDirectional(void)
|
||||
{
|
||||
RpLightSetFlags(pDirect, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ActivateDirectional(void)
|
||||
{
|
||||
RpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientColours(void)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientColoursForPedsCarsAndObjects(void)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame_PedsCarsAndObjects);
|
||||
}
|
||||
|
||||
uint8 IndicateR[] = { 0, 255, 0, 0, 255, 255, 0 };
|
||||
uint8 IndicateG[] = { 0, 0, 255, 0, 255, 0, 255 };
|
||||
uint8 IndicateB[] = { 0, 0, 0, 255, 0, 255, 255 };
|
||||
|
||||
void
|
||||
SetAmbientColoursToIndicateRoadGroup(int i)
|
||||
{
|
||||
AmbientLightColour.red = IndicateR[i%7]/255.0f;
|
||||
AmbientLightColour.green = IndicateG[i%7]/255.0f;
|
||||
AmbientLightColour.blue = IndicateB[i%7]/255.0f;
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x526510, SetLightsWithTimeOfDayColour, PATCH_JUMP);
|
||||
InjectHook(0x526DE0, SetAmbientAndDirectionalColours, PATCH_JUMP);
|
||||
InjectHook(0x526E60, SetBrightMarkerColours, PATCH_JUMP);
|
||||
InjectHook(0x526F10, ReSetAmbientAndDirectionalColours, PATCH_JUMP);
|
||||
InjectHook(0x526F40, DeActivateDirectional, PATCH_JUMP);
|
||||
InjectHook(0x526F50, ActivateDirectional, PATCH_JUMP);
|
||||
InjectHook(0x526F60, SetAmbientColours, PATCH_JUMP);
|
||||
InjectHook(0x526F80, SetAmbientColoursForPedsCarsAndObjects, PATCH_JUMP);
|
||||
ENDPATCHES
|
9
src/render/Lights.h
Normal file
9
src/render/Lights.h
Normal file
@ -0,0 +1,9 @@
|
||||
void SetLightsWithTimeOfDayColour(RpWorld *);
|
||||
void SetAmbientAndDirectionalColours(float f);
|
||||
void SetBrightMarkerColours(float f);
|
||||
void ReSetAmbientAndDirectionalColours(void);
|
||||
void DeActivateDirectional(void);
|
||||
void ActivateDirectional(void);
|
||||
void SetAmbientColours(void);
|
||||
void SetAmbientColoursForPedsCarsAndObjects(void);
|
||||
void SetAmbientColoursToIndicateRoadGroup(int i);
|
10
src/render/Particle.cpp
Normal file
10
src/render/Particle.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Particle.h"
|
||||
|
||||
WRAPPER void
|
||||
CParticle::AddParticle(tParticleType, const CVector &pos, const CVector &velocity, CEntity *ent,
|
||||
float size, int32 rotationStep, int32 rotation, int startFrame, int lifeSpan)
|
||||
{
|
||||
EAXJMP(0x50D140);
|
||||
}
|
82
src/render/Particle.h
Normal file
82
src/render/Particle.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
enum tParticleType
|
||||
{
|
||||
PARTICLE_SPARK,
|
||||
PARTICLE_SPARK_SMALL,
|
||||
PARTICLE_WHEEL_DIRT,
|
||||
PARTICLE_WHEEL_WATER,
|
||||
PARTICLE_BLOOD,
|
||||
PARTICLE_BLOOD_SMALL,
|
||||
PARTICLE_BLOOD_SPURT,
|
||||
PARTICLE_DEBRIS,
|
||||
PARTICLE_DEBRIS2,
|
||||
PARTICLE_WATER,
|
||||
PARTICLE_FLAME,
|
||||
PARTICLE_FIREBALL,
|
||||
PARTICLE_GUNFLASH,
|
||||
PARTICLE_GUNFLASH_NOANIM,
|
||||
PARTICLE_GUNSMOKE,
|
||||
PARTICLE_GUNSMOKE2,
|
||||
PARTICLE_SMOKE,
|
||||
PARTICLE_SMOKE_SLOWMOTION,
|
||||
PARTICLE_GARAGEPAINT_SPRAY,
|
||||
PARTICLE_SHARD,
|
||||
PARTICLE_SPLASH,
|
||||
PARTICLE_CARFLAME,
|
||||
PARTICLE_STEAM,
|
||||
PARTICLE_STEAM2,
|
||||
PARTICLE_STEAM_NY,
|
||||
PARTICLE_STEAM_NY_SLOWMOTION,
|
||||
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_BOAT_WAKE,
|
||||
PARTICLE_WATER_HYDRANT,
|
||||
PARTICLE_WATER_CANNON,
|
||||
PARTICLE_EXTINGUISH_STEAM,
|
||||
PARTICLE_PED_SPLASH,
|
||||
PARTICLE_PEDFOOT_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_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_TEST,
|
||||
PARTICLE_BIRD_FRONT,
|
||||
PARTICLE_RAINDROP_2D,
|
||||
};
|
||||
|
||||
class CEntity;
|
||||
|
||||
class CParticle
|
||||
{
|
||||
public:
|
||||
static void AddParticle(tParticleType, const CVector &pos, const CVector &velocity, CEntity *ent = nil,
|
||||
float size = 0.0, int32 rotationStep = 0, int32 rotation = 0, int startFrame = 0, int lifeSpan = 0);
|
||||
};
|
59
src/render/RenderBuffer.cpp
Normal file
59
src/render/RenderBuffer.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "RenderBuffer.h"
|
||||
|
||||
int32 &TempBufferVerticesStored = *(int32*)0x8F5F78;
|
||||
int32 &TempBufferIndicesStored = *(int32*)0x8F1A4C;
|
||||
|
||||
RwIm3DVertex *TempVertexBuffer = (RwIm3DVertex*)0x862330;
|
||||
RwImVertexIndex *TempBufferRenderIndexList = (RwImVertexIndex*)0x846288;
|
||||
|
||||
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 >= 1024)
|
||||
RenderStuffInBuffer();
|
||||
if(TempBufferVerticesStored + numVertices >= 256)
|
||||
RenderStuffInBuffer();
|
||||
*indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored];
|
||||
*vertexStart = &TempVertexBuffer[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(TempVertexBuffer, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
|
||||
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
|
||||
RwIm3DEnd();
|
||||
}
|
||||
ClearRenderBuffer();
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x517620, RenderBuffer::ClearRenderBuffer, PATCH_JUMP);
|
||||
InjectHook(0x517640, RenderBuffer::StartStoring, PATCH_JUMP);
|
||||
InjectHook(0x5176B0, RenderBuffer::StopStoring, PATCH_JUMP);
|
||||
InjectHook(0x5177C0, RenderBuffer::RenderStuffInBuffer, PATCH_JUMP);
|
||||
ENDPATCHES
|
10
src/render/RenderBuffer.h
Normal file
10
src/render/RenderBuffer.h
Normal file
@ -0,0 +1,10 @@
|
||||
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);
|
||||
};
|
1165
src/render/Renderer.cpp
Normal file
1165
src/render/Renderer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
59
src/render/Renderer.h
Normal file
59
src/render/Renderer.h
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
class CEntity;
|
||||
|
||||
extern bool gbShowPedRoadGroups;
|
||||
extern bool gbShowCarRoadGroups;
|
||||
extern bool gbShowCollisionPolys;
|
||||
|
||||
extern bool gbDontRenderBuildings;
|
||||
extern bool gbDontRenderBigBuildings;
|
||||
extern bool gbDontRenderPeds;
|
||||
extern bool gbDontRenderObjects;
|
||||
|
||||
class CVehicle;
|
||||
class CPtrList;
|
||||
|
||||
class CRenderer
|
||||
{
|
||||
static int32 &ms_nNoOfVisibleEntities;
|
||||
static CEntity **ms_aVisibleEntityPtrs; // [2000];
|
||||
static int32 &ms_nNoOfInVisibleEntities;
|
||||
static CEntity **ms_aInVisibleEntityPtrs; // [150];
|
||||
|
||||
static CVector &ms_vecCameraPosition;
|
||||
static CVehicle *&m_pFirstPersonVehicle;
|
||||
static bool &m_loadingPriority;
|
||||
public:
|
||||
static void Init(void);
|
||||
// TODO: PreRender, needs CHeli and CShadows
|
||||
|
||||
static void RenderRoads(void);
|
||||
static void RenderFadingInEntities(void);
|
||||
static void RenderEverythingBarRoads(void);
|
||||
static void RenderVehiclesButNotBoats(void);
|
||||
static void RenderBoats(void);
|
||||
static void RenderOneRoad(CEntity *);
|
||||
static void RenderOneNonRoad(CEntity *);
|
||||
static void RenderFirstPersonVehicle(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);
|
||||
static bool IsEntityCullZoneVisible(CEntity *ent);
|
||||
static bool IsVehicleCullZoneVisible(CEntity *ent);
|
||||
};
|
553
src/render/Sprite.cpp
Normal file
553
src/render/Sprite.cpp
Normal file
@ -0,0 +1,553 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Draw.h"
|
||||
#include "Camera.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
// Get rid of bullshit windows definitions, we're not running on an 8086
|
||||
#ifdef far
|
||||
#undef far
|
||||
#undef near
|
||||
#endif
|
||||
|
||||
RwIm2DVertex *CSprite2d::maVertices = (RwIm2DVertex*)0x6E9168;
|
||||
float &CSprite2d::RecipNearClip = *(float*)0x880DB4;
|
||||
|
||||
// Arguments:
|
||||
// 2---3
|
||||
// | |
|
||||
// 0---1
|
||||
void
|
||||
CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far)
|
||||
{
|
||||
float screenz, z, recipz;
|
||||
|
||||
if(far){
|
||||
screenz = RwIm2DGetFarScreenZ();
|
||||
z = RwCameraGetFarClipPlane(Scene.camera);
|
||||
}else{
|
||||
screenz = RwIm2DGetNearScreenZ();
|
||||
z = 1.0f/RecipNearClip;
|
||||
}
|
||||
recipz = 1.0f/z;
|
||||
|
||||
// This is what we draw:
|
||||
// 0---1
|
||||
// | / |
|
||||
// 3---2
|
||||
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
|
||||
RwIm2DVertexSetScreenY(&maVertices[0], r.bottom);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[0], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
|
||||
RwIm2DVertexSetU(&maVertices[0], 0.0f, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[0], 0.0f, recipz);
|
||||
|
||||
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
|
||||
RwIm2DVertexSetScreenY(&maVertices[1], r.bottom);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[1], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
|
||||
RwIm2DVertexSetU(&maVertices[1], 1.0f, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[1], 0.0f, recipz);
|
||||
|
||||
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
|
||||
RwIm2DVertexSetScreenY(&maVertices[2], r.top);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[2], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
|
||||
RwIm2DVertexSetU(&maVertices[2], 1.0f, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[2], 1.0f, recipz);
|
||||
|
||||
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
|
||||
RwIm2DVertexSetScreenY(&maVertices[3], r.top);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[3], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
|
||||
RwIm2DVertexSetU(&maVertices[3], 0.0f, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[3], 1.0f, recipz);
|
||||
}
|
||||
|
||||
void
|
||||
CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
|
||||
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
|
||||
{
|
||||
float screenz, z, recipz;
|
||||
|
||||
screenz = RwIm2DGetNearScreenZ();
|
||||
z = 1.0f/RecipNearClip;
|
||||
recipz = 1.0f/z;
|
||||
|
||||
// This is what we draw:
|
||||
// 0---1
|
||||
// | / |
|
||||
// 3---2
|
||||
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
|
||||
RwIm2DVertexSetScreenY(&maVertices[0], r.bottom);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[0], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
|
||||
RwIm2DVertexSetU(&maVertices[0], u0, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[0], v0, recipz);
|
||||
|
||||
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
|
||||
RwIm2DVertexSetScreenY(&maVertices[1], r.bottom);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[1], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
|
||||
RwIm2DVertexSetU(&maVertices[1], u1, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[1], v1, recipz);
|
||||
|
||||
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
|
||||
RwIm2DVertexSetScreenY(&maVertices[2], r.top);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[2], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
|
||||
RwIm2DVertexSetU(&maVertices[2], u2, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[2], v2, recipz);
|
||||
|
||||
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
|
||||
RwIm2DVertexSetScreenY(&maVertices[3], r.top);
|
||||
RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
|
||||
RwIm2DVertexSetCameraZ(&maVertices[3], z);
|
||||
RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
|
||||
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
|
||||
RwIm2DVertexSetU(&maVertices[3], u3, recipz);
|
||||
RwIm2DVertexSetV(&maVertices[3], v3, recipz);
|
||||
}
|
||||
|
||||
void
|
||||
CSprite2d::SetRenderState(void)
|
||||
{
|
||||
if(m_pTexture)
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(m_pTexture));
|
||||
else
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
|
||||
}
|
||||
|
||||
void
|
||||
CSprite2d::DrawRect(const CRect &r, const CRGBA &col)
|
||||
{
|
||||
SetVertices(r, col, col, col, col, false);
|
||||
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, false);
|
||||
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, false);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float &CSprite::m_f2DNearScreenZ = *(float*)0x8F1ABC;
|
||||
float &CSprite::m_f2DFarScreenZ = *(float*)0x8F2C94;
|
||||
int32 &CSprite::m_bFlushSpriteBufferSwitchZTest = *(int32*)0x8F5FB0;
|
||||
|
||||
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 * RsGlobal.maximumHeight / p.z;
|
||||
}
|
||||
|
||||
bool
|
||||
CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip)
|
||||
{
|
||||
CVector viewvec = TheCamera.m_viewMatrix * *(CVector*)∈
|
||||
*out = *(RwV3d*)&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 *= RsGlobal.maximumWidth * recip;
|
||||
out->y *= RsGlobal.maximumHeight * recip;
|
||||
// What is this? size?
|
||||
*outw = 70.0f/CDraw::GetFOV();
|
||||
*outh = 70.0f/CDraw::GetFOV();
|
||||
*outw *= RsGlobal.maximumWidth * recip;
|
||||
*outh *= RsGlobal.maximumHeight * recip;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define SPRITEBUFFERSIZE 64
|
||||
static int32 &nSpriteBufferIndex = *(int32*)0x649A80;
|
||||
static RwIm2DVertex *SpriteBufferVerts = (RwIm2DVertex*)0x649A84; //[SPRITEBUFFERSIZE*6];
|
||||
static RwIm2DVertex *verts = (RwIm2DVertex*)0x64C484; //[4];
|
||||
|
||||
void
|
||||
CSprite::InitSpriteBuffer(void)
|
||||
{
|
||||
m_f2DNearScreenZ = RwIm2DGetNearScreenZ();
|
||||
m_f2DFarScreenZ = RwIm2DGetFarScreenZ();
|
||||
}
|
||||
|
||||
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] > RsGlobal.maximumWidth){
|
||||
us[i] = 1.0f - (xs[i]-RsGlobal.maximumWidth) / (2.0f*w);
|
||||
xs[i] = RsGlobal.maximumWidth;
|
||||
}
|
||||
if(ys[i] < 0.0f){
|
||||
vs[i] = -ys[i] / (2.0f*h);
|
||||
ys[i] = 0.0f;
|
||||
}
|
||||
if(ys[i] > RsGlobal.maximumHeight){
|
||||
vs[i] = 1.0f - (ys[i]-RsGlobal.maximumHeight) / (2.0f*h);
|
||||
ys[i] = RsGlobal.maximumHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// (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::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] > RsGlobal.maximumWidth){
|
||||
us[i] = 1.0f - (xs[i]-RsGlobal.maximumWidth) / (2.0f*w);
|
||||
xs[i] = RsGlobal.maximumWidth;
|
||||
}
|
||||
if(ys[i] < 0.0f){
|
||||
vs[i] = -ys[i] / (2.0f*h);
|
||||
ys[i] = 0.0f;
|
||||
}
|
||||
if(ys[i] > RsGlobal.maximumHeight){
|
||||
vs[i] = 1.0f - (ys[i]-RsGlobal.maximumHeight) / (2.0f*h);
|
||||
ys[i] = RsGlobal.maximumHeight;
|
||||
}
|
||||
}
|
||||
|
||||
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(DEGTORAD(rotation));
|
||||
float s = sin(DEGTORAD(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] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
|
||||
xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
|
||||
if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
|
||||
ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) 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(DEGTORAD(rotation));
|
||||
float s = sin(DEGTORAD(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] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
|
||||
xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
|
||||
if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
|
||||
ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) 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(DEGTORAD(rotation));
|
||||
float s = sin(DEGTORAD(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] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
|
||||
xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
|
||||
if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
|
||||
ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) 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();
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x51EE90, (void (*)(const CRect&, const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA&, uint32))CSprite2d::SetVertices, PATCH_JUMP);
|
||||
InjectHook(0x51F220, (void (*)(const CRect&, const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA&,
|
||||
float, float, float, float, float, float, float, float))CSprite2d::SetVertices, PATCH_JUMP);
|
||||
InjectHook(0x51F970, (void (*)(const CRect&, const CRGBA&))CSprite2d::DrawRect, PATCH_JUMP);
|
||||
InjectHook(0x51FA00, (void (*)(const CRect&, const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA&))CSprite2d::DrawRect, PATCH_JUMP);
|
||||
InjectHook(0x51FA80, CSprite2d::DrawRectXLU, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x51C4A0, CSprite::CalcHorizonCoors, PATCH_JUMP);
|
||||
InjectHook(0x51C3A0, CSprite::CalcScreenCoors, PATCH_JUMP);
|
||||
InjectHook(0x51C590, CSprite::InitSpriteBuffer, PATCH_JUMP);
|
||||
InjectHook(0x51C520, CSprite::FlushSpriteBuffer, PATCH_JUMP);
|
||||
InjectHook(0x51C960, CSprite::RenderOneXLUSprite, PATCH_JUMP);
|
||||
InjectHook(0x51C5D0, CSprite::RenderBufferedOneXLUSprite, PATCH_JUMP);
|
||||
InjectHook(0x51D5B0, CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension, PATCH_JUMP);
|
||||
InjectHook(0x51CCD0, CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect, PATCH_JUMP);
|
||||
InjectHook(0x51D9E0, CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours, PATCH_JUMP);
|
||||
ENDPATCHES
|
37
src/render/Sprite.h
Normal file
37
src/render/Sprite.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
class CSprite2d
|
||||
{
|
||||
RwTexture *m_pTexture;
|
||||
|
||||
static RwIm2DVertex *maVertices; //[4];
|
||||
public:
|
||||
static float &RecipNearClip;
|
||||
|
||||
void SetRenderState(void);
|
||||
|
||||
static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far);
|
||||
static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
|
||||
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);
|
||||
};
|
||||
|
||||
class CSprite
|
||||
{
|
||||
static float &m_f2DNearScreenZ;
|
||||
static float &m_f2DFarScreenZ;
|
||||
static int32 &m_bFlushSpriteBufferSwitchZTest;
|
||||
public:
|
||||
static float CalcHorizonCoors(void);
|
||||
static bool CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip);
|
||||
static void InitSpriteBuffer(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 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);
|
||||
};
|
849
src/render/VisibilityPlugins.cpp
Normal file
849
src/render/VisibilityPlugins.cpp
Normal file
@ -0,0 +1,849 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "templates.h"
|
||||
#include "Entity.h"
|
||||
#include "ModelInfo.h"
|
||||
#include "Lights.h"
|
||||
#include "Renderer.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
|
||||
#define FADE_DISTANCE 20.0f
|
||||
|
||||
/*
|
||||
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList;
|
||||
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList;
|
||||
|
||||
int32 CVisibilityPlugins::ms_atomicPluginOffset = -1;
|
||||
int32 CVisibilityPlugins::ms_framePluginOffset = -1;
|
||||
int32 CVisibilityPlugins::ms_clumpPluginOffset = -1;
|
||||
*/
|
||||
CLinkList<CVisibilityPlugins::AlphaObjectInfo> &CVisibilityPlugins::m_alphaList = *(CLinkList<CVisibilityPlugins::AlphaObjectInfo>*)0x8F42E4;
|
||||
CLinkList<CVisibilityPlugins::AlphaObjectInfo> &CVisibilityPlugins::m_alphaEntityList = *(CLinkList<CVisibilityPlugins::AlphaObjectInfo>*)0x943084;
|
||||
|
||||
int32 &CVisibilityPlugins::ms_atomicPluginOffset = *(int32*)0x600124;
|
||||
int32 &CVisibilityPlugins::ms_framePluginOffset = *(int32*)0x600128;
|
||||
int32 &CVisibilityPlugins::ms_clumpPluginOffset = *(int32*)0x60012C;
|
||||
|
||||
RwV3d *&CVisibilityPlugins::ms_pCameraPosn = *(RwV3d**)0x8F6270;
|
||||
float &CVisibilityPlugins::ms_cullCompsDist = *(float*)0x8F2BC4;
|
||||
float &CVisibilityPlugins::ms_vehicleLod0Dist = *(float*)0x885B28;
|
||||
float &CVisibilityPlugins::ms_vehicleLod1Dist = *(float*)0x885B30;
|
||||
float &CVisibilityPlugins::ms_vehicleFadeDist = *(float*)0x8E28B4;
|
||||
float &CVisibilityPlugins::ms_bigVehicleLod0Dist = *(float*)0x8E2A84;
|
||||
float &CVisibilityPlugins::ms_bigVehicleLod1Dist = *(float*)0x8E2A8C;
|
||||
float &CVisibilityPlugins::ms_pedLod0Dist = *(float*)0x8F2BD4;
|
||||
float &CVisibilityPlugins::ms_pedLod1Dist = *(float*)0x8F2BD8;
|
||||
float &CVisibilityPlugins::ms_pedFadeDist = *(float*)0x8E2C34;
|
||||
|
||||
void
|
||||
CVisibilityPlugins::Initialise(void)
|
||||
{
|
||||
m_alphaList.Init(20);
|
||||
m_alphaList.head.item.sort = 0.0f;
|
||||
m_alphaList.tail.item.sort = 100000000.0f;
|
||||
m_alphaEntityList.Init(350); // TODO: set back to 150 when things are fixed
|
||||
m_alphaEntityList.head.item.sort = 0.0f;
|
||||
m_alphaEntityList.tail.item.sort = 100000000.0f;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::InitAlphaEntityList(void)
|
||||
{
|
||||
m_alphaEntityList.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::InsertEntityIntoSortedList(CEntity *e, float dist)
|
||||
{
|
||||
AlphaObjectInfo item;
|
||||
item.entity = e;
|
||||
item.sort = dist;
|
||||
bool ret = !!m_alphaEntityList.InsertSorted(item);
|
||||
// if(!ret)
|
||||
// printf("list full %d\n", m_alphaEntityList.Count());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::InitAlphaAtomicList(void)
|
||||
{
|
||||
m_alphaList.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::InsertAtomicIntoSortedList(RpAtomic *a, float dist)
|
||||
{
|
||||
AlphaObjectInfo item;
|
||||
item.atomic = a;
|
||||
item.sort = dist;
|
||||
bool ret = !!m_alphaList.InsertSorted(item);
|
||||
// if(!ret)
|
||||
// printf("list full %d\n", m_alphaList.Count());
|
||||
return ret;
|
||||
}
|
||||
|
||||
RpMaterial*
|
||||
SetAlphaCB(RpMaterial *material, void *data)
|
||||
{
|
||||
material->color.alpha = (uint8)(uint32)data;
|
||||
return material;
|
||||
}
|
||||
|
||||
RpMaterial*
|
||||
SetTextureCB(RpMaterial *material, void *data)
|
||||
{
|
||||
RpMaterialSetTexture(material, (RwTexture*)data);
|
||||
return material;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::RenderAlphaAtomics(void)
|
||||
{
|
||||
CLink<AlphaObjectInfo> *node;
|
||||
for(node = m_alphaList.tail.prev;
|
||||
node != &m_alphaList.head;
|
||||
node = node->prev)
|
||||
AtomicDefaultRenderCallBack(node->item.atomic);
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::RenderFadingEntities(void)
|
||||
{
|
||||
CLink<AlphaObjectInfo> *node;
|
||||
CSimpleModelInfo *mi;
|
||||
for(node = m_alphaEntityList.tail.prev;
|
||||
node != &m_alphaEntityList.head;
|
||||
node = node->prev){
|
||||
CEntity *e = node->item.entity;
|
||||
if(e->m_rwObject == nil)
|
||||
continue;
|
||||
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(e->m_modelIndex);
|
||||
if(mi->m_noZwrite)
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
|
||||
|
||||
if(e->bDistanceFade){
|
||||
DeActivateDirectional();
|
||||
SetAmbientColours();
|
||||
e->bImBeingRendered = true;
|
||||
RenderFadingAtomic((RpAtomic*)e->m_rwObject, node->item.sort);
|
||||
e->bImBeingRendered = false;
|
||||
}else
|
||||
CRenderer::RenderOneNonRoad(e);
|
||||
|
||||
if(mi->m_noZwrite)
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic)
|
||||
{
|
||||
RpAtomic *lodatm;
|
||||
RwMatrix *m;
|
||||
RwV3d view;
|
||||
float len;
|
||||
CSimpleModelInfo *mi;
|
||||
|
||||
mi = GetAtomicModelInfo(atomic);
|
||||
m = RwFrameGetLTM(RpAtomicGetFrame(atomic));
|
||||
RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);
|
||||
len = RwV3dLength(&view);
|
||||
lodatm = mi->GetAtomicFromDistance(len);
|
||||
if(lodatm){
|
||||
if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic))
|
||||
RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic)
|
||||
{
|
||||
RwMatrix *m;
|
||||
RwV3d view;
|
||||
float len;
|
||||
|
||||
m = RwFrameGetLTM(RpAtomicGetFrame(atomic));
|
||||
RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);
|
||||
len = RwV3dLength(&view);
|
||||
if(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f)
|
||||
return atomic;
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha)
|
||||
{
|
||||
RpGeometry *geo;
|
||||
uint32 flags;
|
||||
|
||||
geo = RpAtomicGetGeometry(atomic);
|
||||
flags = RpGeometryGetFlags(geo);
|
||||
RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
|
||||
RpGeometrySetFlags(geo, flags);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
|
||||
{
|
||||
RpAtomic *lodatm;
|
||||
float fadefactor;
|
||||
uint8 alpha;
|
||||
CSimpleModelInfo *mi;
|
||||
|
||||
mi = GetAtomicModelInfo(atomic);
|
||||
lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);
|
||||
if(mi->m_additive){
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
||||
}else{
|
||||
fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
|
||||
if(fadefactor > 1.0f)
|
||||
fadefactor = 1.0f;
|
||||
alpha = mi->m_alpha * fadefactor;
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
else{
|
||||
RpGeometry *geo = RpAtomicGetGeometry(lodatm);
|
||||
uint32 flags = RpGeometryGetFlags(geo);
|
||||
RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
|
||||
if(geo != RpAtomicGetGeometry(atomic))
|
||||
RpAtomicSetGeometry(atomic, geo, 0);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
|
||||
RpGeometrySetFlags(geo, flags);
|
||||
}
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_vehicleLod0Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_vehicleLod0Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
|
||||
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
|
||||
return atomic;
|
||||
|
||||
if(flags & ATOMIC_FLAG_DRAWLAST){
|
||||
// sort before clump
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}else{
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_bigVehicleLod0Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(dot > 0.0f)
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_bigVehicleLod0Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(dot > 0.0f)
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
|
||||
return atomic;
|
||||
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_bigVehicleLod1Dist)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq >= ms_bigVehicleLod0Dist &&
|
||||
distsq < ms_bigVehicleLod1Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(dot > 0.0f)
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq >= ms_bigVehicleLod0Dist &&
|
||||
distsq < ms_bigVehicleLod1Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(dot > 0.0f)
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
|
||||
return atomic;
|
||||
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)
|
||||
{
|
||||
RpClump *clump;
|
||||
float dist;
|
||||
int32 alpha;
|
||||
|
||||
clump = RpAtomicGetClump(atomic);
|
||||
dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump));
|
||||
if(dist >= ms_vehicleLod0Dist){
|
||||
alpha = GetClumpAlpha(clump);
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
return atomic;
|
||||
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq >= ms_bigVehicleLod1Dist)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_bigVehicleLod1Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)
|
||||
{
|
||||
RwFrame *clumpframe;
|
||||
float distsq, dot;
|
||||
uint32 flags;
|
||||
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_bigVehicleLod1Dist){
|
||||
flags = GetAtomicId(atomic);
|
||||
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
|
||||
RwFrameGetLTM(clumpframe), flags);
|
||||
if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
|
||||
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
|
||||
return atomic;
|
||||
|
||||
if(flags & ATOMIC_FLAG_DRAWLAST){
|
||||
// sort before clump
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}else{
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
}
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
// TODO: this is part of a struct
|
||||
static RwTexture *&playerskin = *(RwTexture**)0x941428;
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)
|
||||
{
|
||||
if(playerskin)
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, playerskin);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic)
|
||||
{
|
||||
RpClump *clump;
|
||||
float dist;
|
||||
int32 alpha;
|
||||
|
||||
clump = RpAtomicGetClump(atomic);
|
||||
dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump));
|
||||
if(dist >= ms_pedLod0Dist){
|
||||
alpha = GetClumpAlpha(clump);
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic)
|
||||
{
|
||||
RpClump *clump;
|
||||
float dist;
|
||||
int32 alpha;
|
||||
|
||||
clump = RpAtomicGetClump(atomic);
|
||||
dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump));
|
||||
if(dist < ms_pedLod0Dist){
|
||||
alpha = GetClumpAlpha(clump);
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
float
|
||||
CVisibilityPlugins::GetDistanceSquaredFromCamera(RwFrame *frame)
|
||||
{
|
||||
RwMatrix *m;
|
||||
RwV3d dist;
|
||||
m = RwFrameGetLTM(frame);
|
||||
RwV3dSub(&dist, RwMatrixGetPos(m), ms_pCameraPosn);
|
||||
return RwV3dDotProduct(&dist, &dist);
|
||||
}
|
||||
|
||||
float
|
||||
CVisibilityPlugins::GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags)
|
||||
{
|
||||
RwV3d dist;
|
||||
float dot, dotdoor;
|
||||
|
||||
// Vehicle forward is the y axis (RwMatrix.up)
|
||||
// Vehicle right is the x axis (RwMatrix.right)
|
||||
|
||||
RwV3dSub(&dist, RwMatrixGetPos(atomicMat), ms_pCameraPosn);
|
||||
// forward/backward facing
|
||||
if(flags & (ATOMIC_FLAG_FRONT | ATOMIC_FLAG_REAR))
|
||||
dot = RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat));
|
||||
// left/right facing
|
||||
else if(flags & (ATOMIC_FLAG_LEFT & ATOMIC_FLAG_RIGHT))
|
||||
dot = RwV3dDotProduct(&dist, RwMatrixGetRight(clumpMat));
|
||||
else
|
||||
dot = 0.0f;
|
||||
if(flags & (ATOMIC_FLAG_LEFT | ATOMIC_FLAG_REAR))
|
||||
dot = -dot;
|
||||
|
||||
if(flags & (ATOMIC_FLAG_REARDOOR | ATOMIC_FLAG_FRONTDOOR)){
|
||||
if(flags & ATOMIC_FLAG_REARDOOR)
|
||||
dotdoor = -RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat));
|
||||
else if(flags & ATOMIC_FLAG_FRONTDOOR)
|
||||
dotdoor = RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat));
|
||||
else
|
||||
dotdoor = 0.0f;
|
||||
|
||||
if(dot < 0.0f && dotdoor < 0.0f)
|
||||
dot += dotdoor;
|
||||
if(dot > 0.0f && dotdoor > 0.0f)
|
||||
dot += dotdoor;
|
||||
}
|
||||
|
||||
return dot;
|
||||
}
|
||||
|
||||
/* These are all unused */
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::DefaultVisibilityCB(RpClump *clump)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::FrustumSphereCB(RpClump *clump)
|
||||
{
|
||||
// TODO, but unused
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::VehicleVisibilityCB(RpClump *clump)
|
||||
{
|
||||
// TODO, but unused
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::VehicleVisibilityCB_BigVehicle(RpClump *clump)
|
||||
{
|
||||
// TODO, but unused
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// RW Plugins
|
||||
//
|
||||
|
||||
enum
|
||||
{
|
||||
ID_VISIBILITYATOMIC = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x00),
|
||||
ID_VISIBILITYCLUMP = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x01),
|
||||
ID_VISIBILITYFRAME = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x02),
|
||||
};
|
||||
|
||||
bool
|
||||
CVisibilityPlugins::PluginAttach(void)
|
||||
{
|
||||
ms_atomicPluginOffset = RpAtomicRegisterPlugin(sizeof(AtomicExt),
|
||||
ID_VISIBILITYATOMIC,
|
||||
AtomicConstructor, AtomicDestructor, AtomicCopyConstructor);
|
||||
|
||||
ms_framePluginOffset = RwFrameRegisterPlugin(sizeof(FrameExt),
|
||||
ID_VISIBILITYFRAME,
|
||||
FrameConstructor, FrameDestructor, FrameCopyConstructor);
|
||||
|
||||
ms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt),
|
||||
ID_VISIBILITYCLUMP,
|
||||
ClumpConstructor, ClumpDestructor, ClumpCopyConstructor);
|
||||
return ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1;
|
||||
}
|
||||
|
||||
#define ATOMICEXT(o) (RWPLUGINOFFSET(AtomicExt, o, ms_atomicPluginOffset))
|
||||
#define FRAMEEXT(o) (RWPLUGINOFFSET(FrameExt, o, ms_framePluginOffset))
|
||||
#define CLUMPEXT(o) (RWPLUGINOFFSET(ClumpExt, o, ms_clumpPluginOffset))
|
||||
|
||||
//
|
||||
// Atomic
|
||||
//
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::AtomicConstructor(void *object, int32, int32)
|
||||
{
|
||||
ATOMICEXT(object)->modelInfo = nil;
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::AtomicDestructor(void *object, int32, int32)
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::AtomicCopyConstructor(void *dst, const void *src, int32, int32)
|
||||
{
|
||||
*ATOMICEXT(dst) = *ATOMICEXT(src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::SetAtomicModelInfo(RpAtomic *atomic,
|
||||
CSimpleModelInfo *modelInfo)
|
||||
{
|
||||
AtomicExt *ext = ATOMICEXT(atomic);
|
||||
ext->modelInfo = modelInfo;
|
||||
switch(modelInfo->m_type)
|
||||
case MITYPE_SIMPLE:
|
||||
case MITYPE_TIME:
|
||||
if(modelInfo->m_normalCull)
|
||||
SetAtomicRenderCallback(atomic, RenderObjNormalAtomic);
|
||||
}
|
||||
|
||||
CSimpleModelInfo*
|
||||
CVisibilityPlugins::GetAtomicModelInfo(RpAtomic *atomic)
|
||||
{
|
||||
return ATOMICEXT(atomic)->modelInfo;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::SetAtomicFlag(RpAtomic *atomic, int f)
|
||||
{
|
||||
ATOMICEXT(atomic)->flags |= f;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::ClearAtomicFlag(RpAtomic *atomic, int f)
|
||||
{
|
||||
ATOMICEXT(atomic)->flags &= ~f;
|
||||
}
|
||||
|
||||
int
|
||||
CVisibilityPlugins::GetAtomicId(RpAtomic *atomic)
|
||||
{
|
||||
return ATOMICEXT(atomic)->flags;
|
||||
}
|
||||
|
||||
// This is rather useless, but whatever
|
||||
void
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(RpAtomic *atomic, RpAtomicCallBackRender cb)
|
||||
{
|
||||
if(cb == nil)
|
||||
cb = AtomicDefaultRenderCallBack; // not necessary
|
||||
RpAtomicSetRenderCallBack(atomic, cb);
|
||||
}
|
||||
|
||||
//
|
||||
// Frame
|
||||
//
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::FrameConstructor(void *object, int32, int32)
|
||||
{
|
||||
FRAMEEXT(object)->id = 0;
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::FrameDestructor(void *object, int32, int32)
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::FrameCopyConstructor(void *dst, const void *src, int32, int32)
|
||||
{
|
||||
*FRAMEEXT(dst) = *FRAMEEXT(src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::SetFrameHierarchyId(RwFrame *frame, int32 id)
|
||||
{
|
||||
FRAMEEXT(frame)->id = id;
|
||||
}
|
||||
|
||||
int32
|
||||
CVisibilityPlugins::GetFrameHierarchyId(RwFrame *frame)
|
||||
{
|
||||
return FRAMEEXT(frame)->id;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Clump
|
||||
//
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::ClumpConstructor(void *object, int32, int32)
|
||||
{
|
||||
ClumpExt *ext = CLUMPEXT(object);
|
||||
ext->visibilityCB = DefaultVisibilityCB;
|
||||
ext->alpha = 0xFF;
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::ClumpDestructor(void *object, int32, int32)
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CVisibilityPlugins::ClumpCopyConstructor(void *dst, const void *src, int32, int32)
|
||||
{
|
||||
CLUMPEXT(dst)->visibilityCB = CLUMPEXT(src)->visibilityCB;
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::SetClumpModelInfo(RpClump *clump, CClumpModelInfo *modelInfo)
|
||||
{
|
||||
CVehicleModelInfo *vmi;
|
||||
SetFrameHierarchyId(RpClumpGetFrame(clump), (int32)modelInfo);
|
||||
|
||||
// Unused
|
||||
switch(modelInfo->m_type){
|
||||
// ignore MLO
|
||||
case MITYPE_VEHICLE:
|
||||
vmi = (CVehicleModelInfo*)modelInfo;
|
||||
if(vmi->m_vehicleType == VEHICLE_TYPE_TRAIN ||
|
||||
vmi->m_vehicleType == VEHICLE_TYPE_HELI ||
|
||||
vmi->m_vehicleType == VEHICLE_TYPE_PLANE)
|
||||
CLUMPEXT(clump)->visibilityCB = VehicleVisibilityCB_BigVehicle;
|
||||
else
|
||||
CLUMPEXT(clump)->visibilityCB = VehicleVisibilityCB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CVisibilityPlugins::SetClumpAlpha(RpClump *clump, int alpha)
|
||||
{
|
||||
CLUMPEXT(clump)->alpha = alpha;
|
||||
}
|
||||
|
||||
int
|
||||
CVisibilityPlugins::GetClumpAlpha(RpClump *clump)
|
||||
{
|
||||
return CLUMPEXT(clump)->alpha;
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x527E50, CVisibilityPlugins::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x528F90, CVisibilityPlugins::InitAlphaEntityList, PATCH_JUMP);
|
||||
InjectHook(0x528FF0, CVisibilityPlugins::InsertEntityIntoSortedList, PATCH_JUMP);
|
||||
InjectHook(0x528F80, CVisibilityPlugins::InitAlphaAtomicList, PATCH_JUMP);
|
||||
InjectHook(0x528FA0, CVisibilityPlugins::InsertAtomicIntoSortedList, PATCH_JUMP);
|
||||
InjectHook(0x527F60, SetAlphaCB, PATCH_JUMP);
|
||||
InjectHook(0x529040, CVisibilityPlugins::RenderAlphaAtomics, PATCH_JUMP);
|
||||
InjectHook(0x529070, CVisibilityPlugins::RenderFadingEntities, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x527F70, CVisibilityPlugins::RenderWheelAtomicCB, PATCH_JUMP);
|
||||
InjectHook(0x528000, CVisibilityPlugins::RenderObjNormalAtomic, PATCH_JUMP);
|
||||
InjectHook(0x5280B0, CVisibilityPlugins::RenderAlphaAtomic, PATCH_JUMP);
|
||||
InjectHook(0x528100, CVisibilityPlugins::RenderFadingAtomic, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x5283E0, CVisibilityPlugins::RenderVehicleHiDetailCB, PATCH_JUMP);
|
||||
InjectHook(0x5284B0, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB, PATCH_JUMP);
|
||||
InjectHook(0x5288A0, CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle, PATCH_JUMP);
|
||||
InjectHook(0x528A10, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle, PATCH_JUMP);
|
||||
InjectHook(0x528AD0, CVisibilityPlugins::RenderVehicleHiDetailCB_Boat, PATCH_JUMP);
|
||||
InjectHook(0x5287F0, CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle, PATCH_JUMP);
|
||||
InjectHook(0x528940, CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle, PATCH_JUMP);
|
||||
InjectHook(0x528240, CVisibilityPlugins::RenderVehicleReallyLowDetailCB, PATCH_JUMP);
|
||||
InjectHook(0x5287B0, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle, PATCH_JUMP);
|
||||
InjectHook(0x5285D0, CVisibilityPlugins::RenderTrainHiDetailCB, PATCH_JUMP);
|
||||
InjectHook(0x5286A0, CVisibilityPlugins::RenderTrainHiDetailAlphaCB, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x528BC0, CVisibilityPlugins::RenderPedHiDetailCB, PATCH_JUMP);
|
||||
InjectHook(0x528B60, CVisibilityPlugins::RenderPedLowDetailCB, PATCH_JUMP);
|
||||
|
||||
|
||||
InjectHook(0x527DC0, CVisibilityPlugins::PluginAttach, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x527EC0, CVisibilityPlugins::SetAtomicModelInfo, PATCH_JUMP);
|
||||
InjectHook(0x527F00, CVisibilityPlugins::GetAtomicModelInfo, PATCH_JUMP);
|
||||
InjectHook(0x527F10, CVisibilityPlugins::SetAtomicFlag, PATCH_JUMP);
|
||||
InjectHook(0x527F30, CVisibilityPlugins::ClearAtomicFlag, PATCH_JUMP);
|
||||
InjectHook(0x527F50, CVisibilityPlugins::GetAtomicId, PATCH_JUMP);
|
||||
InjectHook(0x528C20, CVisibilityPlugins::SetAtomicRenderCallback, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x528D60, CVisibilityPlugins::SetFrameHierarchyId, PATCH_JUMP);
|
||||
InjectHook(0x528D80, CVisibilityPlugins::GetFrameHierarchyId, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x528ED0, CVisibilityPlugins::SetClumpModelInfo, PATCH_JUMP);
|
||||
InjectHook(0x528F50, CVisibilityPlugins::SetClumpAlpha, PATCH_JUMP);
|
||||
InjectHook(0x528F70, CVisibilityPlugins::GetClumpAlpha, PATCH_JUMP);
|
||||
|
||||
|
||||
InjectHook(0x529120, CVisibilityPlugins::GetDistanceSquaredFromCamera, PATCH_JUMP);
|
||||
InjectHook(0x5282A0, CVisibilityPlugins::GetDotProductWithCameraVector, PATCH_JUMP);
|
||||
ENDPATCHES
|
129
src/render/VisibilityPlugins.h
Normal file
129
src/render/VisibilityPlugins.h
Normal file
@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
|
||||
#include "templates.h"
|
||||
|
||||
class CEntity;
|
||||
class CSimpleModelInfo;
|
||||
class CClumpModelInfo;
|
||||
|
||||
typedef bool (*ClumpVisibilityCB)(RpClump*);
|
||||
|
||||
class CVisibilityPlugins
|
||||
{
|
||||
public:
|
||||
struct AlphaObjectInfo
|
||||
{
|
||||
union {
|
||||
CEntity *entity;
|
||||
RpAtomic *atomic;
|
||||
};
|
||||
float sort;
|
||||
};
|
||||
|
||||
static CLinkList<AlphaObjectInfo> &m_alphaList;
|
||||
static CLinkList<AlphaObjectInfo> &m_alphaEntityList;
|
||||
static RwV3d *&ms_pCameraPosn;
|
||||
static float &ms_cullCompsDist;
|
||||
static float &ms_vehicleLod0Dist;
|
||||
static float &ms_vehicleLod1Dist;
|
||||
static float &ms_vehicleFadeDist;
|
||||
static float &ms_bigVehicleLod0Dist;
|
||||
static float &ms_bigVehicleLod1Dist;
|
||||
static float &ms_pedLod0Dist;
|
||||
static float &ms_pedLod1Dist;
|
||||
static float &ms_pedFadeDist;
|
||||
|
||||
static void Initialise(void);
|
||||
static void InitAlphaEntityList(void);
|
||||
static bool InsertEntityIntoSortedList(CEntity *e, float dist);
|
||||
static void InitAlphaAtomicList(void);
|
||||
static bool InsertAtomicIntoSortedList(RpAtomic *a, float dist);
|
||||
|
||||
static RpAtomic *RenderWheelAtomicCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderObjNormalAtomic(RpAtomic *atomic);
|
||||
static RpAtomic *RenderAlphaAtomic(RpAtomic *atomic, int alpha);
|
||||
static RpAtomic *RenderFadingAtomic(RpAtomic *atm, float dist);
|
||||
|
||||
static RpAtomic *RenderVehicleHiDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailAlphaCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailCB_Boat(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleReallyLowDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderTrainHiDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderTrainHiDetailAlphaCB(RpAtomic *atomic);
|
||||
|
||||
static RpAtomic *RenderPlayerCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderPedLowDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderPedHiDetailCB(RpAtomic *atomic);
|
||||
|
||||
static void RenderAlphaAtomics(void);
|
||||
static void RenderFadingEntities(void);
|
||||
|
||||
// All actually unused
|
||||
static bool DefaultVisibilityCB(RpClump *clump);
|
||||
static bool FrustumSphereCB(RpClump *clump);
|
||||
// static bool MloVisibilityCB(RpClump *clump);
|
||||
static bool VehicleVisibilityCB(RpClump *clump);
|
||||
static bool VehicleVisibilityCB_BigVehicle(RpClump *clump);
|
||||
|
||||
static float GetDistanceSquaredFromCamera(RwFrame *frame);
|
||||
static float GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags);
|
||||
|
||||
//
|
||||
// RW Plugins
|
||||
//
|
||||
|
||||
union AtomicExt
|
||||
{
|
||||
CSimpleModelInfo *modelInfo; // used by SimpleModelInfo
|
||||
int flags; // used by ClumpModelInfo
|
||||
};
|
||||
static void SetAtomicModelInfo(RpAtomic*, CSimpleModelInfo*);
|
||||
static CSimpleModelInfo *GetAtomicModelInfo(RpAtomic *atomic);
|
||||
static void SetAtomicFlag(RpAtomic*, int);
|
||||
static void ClearAtomicFlag(RpAtomic*, int);
|
||||
static int GetAtomicId(RpAtomic *atomic);
|
||||
static void SetAtomicRenderCallback(RpAtomic*, RpAtomicCallBackRender);
|
||||
|
||||
static void *AtomicConstructor(void *object, int32 offset, int32 len);
|
||||
static void *AtomicDestructor(void *object, int32 offset, int32 len);
|
||||
static void *AtomicCopyConstructor(void *dst, const void *src,
|
||||
int32 offset, int32 len);
|
||||
static int32 &ms_atomicPluginOffset;
|
||||
|
||||
struct FrameExt
|
||||
{
|
||||
// BUG: this is abused to hold a pointer by SetClumpModelInfo
|
||||
int32 id;
|
||||
};
|
||||
static void SetFrameHierarchyId(RwFrame *frame, int32 id);
|
||||
static int32 GetFrameHierarchyId(RwFrame *frame);
|
||||
|
||||
static void *FrameConstructor(void *object, int32 offset, int32 len);
|
||||
static void *FrameDestructor(void *object, int32 offset, int32 len);
|
||||
static void *FrameCopyConstructor(void *dst, const void *src,
|
||||
int32 offset, int32 len);
|
||||
static int32 &ms_framePluginOffset;
|
||||
|
||||
// Not actually used
|
||||
struct ClumpExt
|
||||
{
|
||||
ClumpVisibilityCB visibilityCB;
|
||||
int alpha;
|
||||
};
|
||||
static void SetClumpModelInfo(RpClump*, CClumpModelInfo*);
|
||||
static void SetClumpAlpha(RpClump*, int);
|
||||
static int GetClumpAlpha(RpClump*);
|
||||
|
||||
static void *ClumpConstructor(void *object, int32 offset, int32 len);
|
||||
static void *ClumpDestructor(void *object, int32 offset, int32 len);
|
||||
static void *ClumpCopyConstructor(void *dst, const void *src,
|
||||
int32 offset, int32 len);
|
||||
static int32 &ms_clumpPluginOffset;
|
||||
|
||||
static bool PluginAttach(void);
|
||||
};
|
Reference in New Issue
Block a user