aboutsummaryrefslogtreecommitdiffstats
path: root/src/renderer/WaterLevel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/WaterLevel.cpp')
-rw-r--r--src/renderer/WaterLevel.cpp2951
1 files changed, 2387 insertions, 564 deletions
diff --git a/src/renderer/WaterLevel.cpp b/src/renderer/WaterLevel.cpp
index 7001c0cf..dee60d66 100644
--- a/src/renderer/WaterLevel.cpp
+++ b/src/renderer/WaterLevel.cpp
@@ -7,6 +7,7 @@
#include "Weather.h"
#include "Camera.h"
#include "Vehicle.h"
+#include "PlayerPed.h"
#include "Boat.h"
#include "World.h"
#include "General.h"
@@ -17,48 +18,105 @@
#include "ParticleMgr.h"
#include "RwHelper.h"
#include "Streaming.h"
+#include "ColStore.h"
#include "CdStream.h"
#include "Pad.h"
#include "RenderBuffer.h"
+#include <rwcore.h>
#include <rpworld.h>
+#include <rpmatfx.h>
+#include "Occlusion.h"
+#include "Replay.h"
#include "WaterLevel.h"
-#include "MemoryHeap.h"
+#include "SurfaceTable.h"
+#include "WaterCreatures.h"
+#define RwIm3DVertexSet_RGBA(vert, rgba) RwIm3DVertexSetRGBA(vert, rgba.red, rgba.green, rgba.blue, rgba.alpha) // (RwRGBAAssign(&(_dst)->color, &_src))
float TEXTURE_ADDU;
float TEXTURE_ADDV;
+float _TEXTURE_MASK_ADDU;
+float _TEXTURE_MASK_ADDV;
+
+float _TEXTURE_WAKE_ADDU;
+float _TEXTURE_WAKE_ADDV;
+
int32 CWaterLevel::ms_nNoOfWaterLevels;
float CWaterLevel::ms_aWaterZs[48];
CRect CWaterLevel::ms_aWaterRects[48];
int8 CWaterLevel::aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS];
int8 CWaterLevel::aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS];
bool CWaterLevel::WavesCalculatedThisFrame;
+
+
+bool CWaterLevel::RequireWavySector;
+bool CWaterLevel::MaskCalculatedThisFrame;
+CVector CWaterLevel::PreCalculatedMaskPosn;
+bool CWaterLevel::m_bRenderSeaBed;
+int32 CWaterLevel::m_nRenderWaterLayers;
+
RpAtomic *CWaterLevel::ms_pWavyAtomic;
-RpGeometry *CWaterLevel::apGeomArray[8];
-int16 CWaterLevel::nGeomUsed;
+RpAtomic *CWaterLevel::ms_pMaskAtomic;
//"Custom" Don't Render Water Toggle
bool gbDontRenderWater;
-//RwTexture *gpWaterTex;
-//RwRaster *gpWaterRaster;
RwTexture *gpWaterTex;
+RwTexture *gpWaterEnvTex;
+RwTexture *gpWaterEnvBaseTex;
+RwTexture *gpWaterWakeTex;
+
RwRaster *gpWaterRaster;
+RwRaster *gpWaterEnvRaster;
+RwRaster *gpWaterEnvBaseRaster;
+RwRaster *gpWaterWakeRaster;
+bool _bSeaLife;
+float _fWaterZOffset = WATER_Z_OFFSET;
-const float fAdd1 = 180.0f;
-const float fAdd2 = 80.0f;
-const float fRedMult = 0.6f;
-const float fGreenMult = 1.0f;
-const float fBlueMult = 1.4f;
+#ifdef PC_WATER
+float fEnvScale = 0.25f;
+#else
+float fEnvScale = 0.5f;
+#endif
+float fWave2InvLength = 0.03f;
+float fWave2NormScale = 0.5f;
+float fWave2Ampl = 0.1f;
+uint8 nWaterAlpha = 192;
+uint8 nWakeAlpha = 192;
+float fUnder1 = 4.0;
+float fUnder2 = 2.5;
+float fUnder3 = 1.5;
+int nMaskAlpha = 230;
+float fAdd1 = 180.0f;
+float fAdd2 = 80.0;
+float fRedMult = 0.6f;
+float fGreenMult = 1.0f;
+float fBlueMult = 1.4f;
+float fAlphaMult = 500.0f;
+float fAlphaBase = 30.0f;
+float fRandomMoveDiv = 8.0f;
+float fRandomDamp = 0.99f;
+float fNormMult = 2.0f;
+float fNormMultB = 1.0f;
+float fBumpScale = 1.5;
+float fBumpTexRepeat = 2.0;
+float fNormalDirectionScalar1 = 2.0f;
+float fNormalDirectionScalar2 = 1.0f;
+bool bTestDoNormals = true;
+float fSeaBedZ = 25.0f;
+float aAlphaFade[5] = { 0.4f, 1.0f, 0.2f, 1.0f, 0.4f}; //CWaterLevel::RenderWakeSegment
+float fFlatWaterBlendRange = 0.05f;
+float fStartBlendDistanceAdd = 64.0f;
+float fMinWaterAlphaMult = -30.0f;
void
CWaterLevel::Initialise(Const char *pWaterDat)
{
ms_nNoOfWaterLevels = 0;
-
+
#ifdef MASTER
int32 hFile = -1;
@@ -70,15 +128,14 @@ CWaterLevel::Initialise(Const char *pWaterDat)
#else
int32 hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb");
#endif
-
+
if (hFile > 0)
{
CFileMgr::Read(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels));
- CFileMgr::Read(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs));
+ CFileMgr::Read(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs));
CFileMgr::Read(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects));
CFileMgr::Read(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList));
CFileMgr::Read(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList));
-
CFileMgr::CloseFile(hFile);
}
#ifndef MASTER
@@ -86,6 +143,9 @@ CWaterLevel::Initialise(Const char *pWaterDat)
{
printf("Init waterlevels\n");
+ // collision is streamed in VC
+ CColStore::LoadAllCollision();
+
CFileMgr::SetDir("");
hFile = CFileMgr::OpenFile(pWaterDat, "r");
@@ -93,11 +153,7 @@ CWaterLevel::Initialise(Const char *pWaterDat)
while ((line = CFileLoader::LoadLine(hFile)))
{
-#ifdef FIX_BUGS
if (*line && *line != ';' && !strstr(line, "* ;end of file"))
-#else
- if (*line && *line != ';')
-#endif
{
float z, l, b, r, t;
sscanf(line, "%f %f %f %f %f", &z, &l, &b, &r, &t);
@@ -118,19 +174,15 @@ CWaterLevel::Initialise(Const char *pWaterDat)
// rasterize water rects read from file
for (int32 i = 0; i < ms_nNoOfWaterLevels; i++)
{
- int32 l = WATER_HUGE_X(ms_aWaterRects[i].left);
- int32 r = WATER_HUGE_X(ms_aWaterRects[i].right) + 1.0f;
+ int32 l = WATER_HUGE_X(ms_aWaterRects[i].left + WATER_X_OFFSET);
+ int32 r = WATER_HUGE_X(ms_aWaterRects[i].right + WATER_X_OFFSET) + 1.0f;
int32 t = WATER_HUGE_Y(ms_aWaterRects[i].top);
int32 b = WATER_HUGE_Y(ms_aWaterRects[i].bottom) + 1.0f;
-#ifdef FIX_BUGS
- // water.dat has rects that go out of bounds
- // which causes memory corruption
l = Clamp(l, 0, MAX_SMALL_SECTORS - 1);
r = Clamp(r, 0, MAX_SMALL_SECTORS - 1);
t = Clamp(t, 0, MAX_SMALL_SECTORS - 1);
b = Clamp(b, 0, MAX_SMALL_SECTORS - 1);
-#endif
for (int32 x = l; x <= r; x++)
{
@@ -144,11 +196,11 @@ CWaterLevel::Initialise(Const char *pWaterDat)
// remove tiles that are obscured by land
for (int32 x = 0; x < MAX_SMALL_SECTORS; x++)
{
- float worldX = WATER_START_X + x * SMALL_SECTOR_SIZE;
+ float worldX = WATER_START_X + x * SMALL_SECTOR_SIZE - WATER_X_OFFSET;
for (int32 y = 0; y < MAX_SMALL_SECTORS; y++)
{
- if (aWaterFineBlockList[x][y] >= 0)
+ if (CWaterLevel::aWaterFineBlockList[x][y] >= 0)
{
float worldY = WATER_START_Y + y * SMALL_SECTOR_SIZE;
@@ -160,7 +212,7 @@ CWaterLevel::Initialise(Const char *pWaterDat)
CVector worldPos = CVector(worldX + i * (SMALL_SECTOR_SIZE / 8), worldY + j * (SMALL_SECTOR_SIZE / 8), ms_aWaterZs[aWaterFineBlockList[x][y]]);
if ((worldPos.x > WORLD_MIN_X && worldPos.x < WORLD_MAX_X) && (worldPos.y > WORLD_MIN_Y && worldPos.y < WORLD_MAX_Y) &&
- (!WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) || TestVisibilityForFineWaterBlocks(worldPos)))
+ (!WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) || TestVisibilityForFineWaterBlocks(worldPos)))
continue;
// at least one point in the tile wasn't blocked, so don't remove water
@@ -210,13 +262,16 @@ CWaterLevel::Initialise(Const char *pWaterDat)
if (hFile > 0)
{
CFileMgr::Write(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels));
- CFileMgr::Write(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs));
+ CFileMgr::Write(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs));
CFileMgr::Write(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects));
CFileMgr::Write(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList));
CFileMgr::Write(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList));
CFileMgr::CloseFile(hFile);
}
+
+ // collision is streamed in VC
+ CColStore::RemoveAllCollision();
}
#endif
@@ -226,13 +281,26 @@ CWaterLevel::Initialise(Const char *pWaterDat)
CTxdStore::SetCurrentTxd(slot);
if ( gpWaterTex == nil )
- gpWaterTex = RwTextureRead("water_old", nil);
+ gpWaterTex = RwTextureRead("waterclear256", nil);
gpWaterRaster = RwTextureGetRaster(gpWaterTex);
+ if ( gpWaterEnvTex == nil )
+ gpWaterEnvTex = RwTextureRead("waterreflection2", nil);
+ gpWaterEnvRaster = RwTextureGetRaster(gpWaterEnvTex);
+
+#ifdef PC_WATER
+ if ( gpWaterEnvBaseTex == nil )
+ gpWaterEnvBaseTex = RwTextureRead("sandywater", nil);
+ gpWaterEnvBaseRaster = RwTextureGetRaster(gpWaterEnvBaseTex);
+#endif
+
+ if ( gpWaterWakeTex == nil )
+ gpWaterWakeTex = RwTextureRead("waterwake", nil);
+ gpWaterWakeRaster = RwTextureGetRaster(gpWaterWakeTex);
+
CTxdStore::PopCurrentTxd();
CreateWavyAtomic();
- FreeBoatWakeArray();
printf("Done Initing waterlevels\n");
}
@@ -240,92 +308,154 @@ CWaterLevel::Initialise(Const char *pWaterDat)
void
CWaterLevel::Shutdown()
{
- FreeBoatWakeArray();
DestroyWavyAtomic();
- if ( gpWaterTex != nil )
- {
- RwTextureDestroy(gpWaterTex);
- gpWaterTex = nil;
- }
+#define _DELETE_TEXTURE(t) if ( t ) \
+ { \
+ RwTextureDestroy(t); \
+ t = nil; \
+ }
+
+ _DELETE_TEXTURE(gpWaterTex);
+ _DELETE_TEXTURE(gpWaterEnvTex);
+ _DELETE_TEXTURE(gpWaterWakeTex);
+ _DELETE_TEXTURE(gpWaterEnvBaseTex);
+
+#undef _DELETE_TEXTURE
}
void
CWaterLevel::CreateWavyAtomic()
{
RpGeometry *wavyGeometry;
+ RpGeometry *maskGeometry;
RpMaterial *wavyMaterial;
- RpTriangle *wavyTriangles;
+ RpMaterial *maskMaterial;
+
+ RpTriangle *wavytlist;
+ RpTriangle *masktlist;
+
RpMorphTarget *wavyMorphTarget;
- RwSphere boundingSphere;
+ RpMorphTarget *maskMorphTarget;
+
+ RwSphere boundingSphere;
+
RwV3d *wavyVert;
-
+ RwV3d *wavyNormal;
+
+ RwV3d *maskVert;
+ RwV3d *maskNormal;
+
RwFrame *wavyFrame;
+ RwFrame *maskFrame;
{
- wavyGeometry = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP
+ wavyGeometry = RpGeometryCreate(17*17, 512, rpGEOMETRYTRISTRIP
|rpGEOMETRYTEXTURED
|rpGEOMETRYPRELIT
+ |rpGEOMETRYNORMALS
|rpGEOMETRYMODULATEMATERIALCOLOR);
-
- ASSERT(wavyGeometry != nil);
-
+#ifdef PC_WATER
+ RpGeometryAddMorphTarget(wavyGeometry);
+#endif
+ }
+
+ {
+ maskGeometry = RpGeometryCreate(33*33, 2048, rpGEOMETRYTRISTRIP
+ |rpGEOMETRYTEXTURED
+ |rpGEOMETRYPRELIT
+ |rpGEOMETRYNORMALS
+ |rpGEOMETRYMODULATEMATERIALCOLOR);
+#ifdef PC_WATER
+ RpGeometryAddMorphTarget(maskGeometry);
+#endif
}
{
wavyMaterial = RpMaterialCreate();
-
- ASSERT(wavyMaterial != nil);
- ASSERT(gpWaterTex != nil);
-
RpMaterialSetTexture(wavyMaterial, gpWaterTex);
+ RwRGBA watercolor = { 255, 255, 255, 192 };
+ RpMaterialSetColor(wavyMaterial, &watercolor);
}
{
- wavyTriangles = RpGeometryGetTriangles(wavyGeometry);
-
- ASSERT(wavyTriangles != nil);
- /*
- [B] [C]
- ***********
- * * *
- * * *
- * * *
- * * *
- ***********
- [A] [D]
- */
+ maskMaterial = RpMaterialCreate();
+#ifdef PC_WATER
+ RpMaterialSetTexture(maskMaterial, gpWaterEnvBaseTex);
+#else
+ RpMaterialSetTexture(maskMaterial, gpWaterTex);
+#endif
+ RwRGBA watercolor = { 255, 255, 255, 192 };
+ RpMaterialSetColor(maskMaterial, &watercolor);
+ }
+
+ {
+ wavytlist = RpGeometryGetTriangles(wavyGeometry);
- for ( int32 i = 0; i < 8; i++ )
+ for ( int32 i = 0; i < 16; i++ )
{
- for ( int32 j = 0; j < 8; j++ )
- {
+ for ( int32 j = 0; j < 16; j++ )
+ {
+ const RwUInt16 base = (RwUInt16)((16 + 1)*i+j);
+
RpGeometryTriangleSetVertexIndices(wavyGeometry,
- &wavyTriangles[2 * 8*i + 2*j + 0], /*A*/9*i+j+0, /*B*/9*i+j+1, /*C*/9*i+j+9+1);
-
- RpGeometryTriangleSetVertexIndices(wavyGeometry,
- &wavyTriangles[2 * 8*i + 2*j + 1], /*A*/9*i+j+0, /*C*/9*i+j+9+1, /*D*/9*i+j+9 );
+ wavytlist, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+16+2));
+
+ RpGeometryTriangleSetVertexIndices(wavyGeometry,
+ (wavytlist+1), (RwInt16)base, (RwInt16)(base+16+2), (RwInt16)(base+16+1));
- RpGeometryTriangleSetMaterial(wavyGeometry, &wavyTriangles[2 * 8*i + 2*j + 0], wavyMaterial);
- RpGeometryTriangleSetMaterial(wavyGeometry, &wavyTriangles[2 * 8*i + 2*j + 1], wavyMaterial);
+ RpGeometryTriangleSetMaterial(wavyGeometry, wavytlist, wavyMaterial);
+
+ RpGeometryTriangleSetMaterial(wavyGeometry, (wavytlist+1), wavyMaterial);
+
+ wavytlist+=2;
}
}
}
+ {
+ masktlist = RpGeometryGetTriangles(maskGeometry);
+
+ for ( int32 i = 0; i < 32; i++ )
+ {
+ for ( int32 j = 0; j < 32; j++ )
+ {
+ const RwUInt16 base = (RwUInt16)((32 + 1)*i+j);
+
+ RpGeometryTriangleSetVertexIndices(maskGeometry,
+ masktlist, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+32+2));
+
+ RpGeometryTriangleSetVertexIndices(maskGeometry,
+ (masktlist+1), (RwInt16)base, (RwInt16)(base+32+2), (RwInt16)(base+32+1));
+
+ RpGeometryTriangleSetMaterial(maskGeometry, masktlist, maskMaterial);
+
+ RpGeometryTriangleSetMaterial(maskGeometry, (masktlist+1), maskMaterial);
+
+ masktlist+=2;
+ }
+ }
+ }
{
wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0);
- ASSERT(wavyMorphTarget != nil);
- wavyVert = RpMorphTargetGetVertices(wavyMorphTarget);
- ASSERT(wavyVert != nil);
+ wavyVert = RpMorphTargetGetVertices(wavyMorphTarget);
+ wavyNormal = RpMorphTargetGetVertexNormals(wavyMorphTarget);
- for ( int32 i = 0; i < 9; i++ )
+ for ( int32 i = 0; i < 17; i++ )
{
- for ( int32 j = 0; j < 9; j++ )
+ for ( int32 j = 0; j < 17; j++ )
{
- wavyVert[9*i+j].x = (float)i * 4.0f;
- wavyVert[9*i+j].y = (float)j * 4.0f;
- wavyVert[9*i+j].z = 0.0f;
+ (*wavyVert).x = (float)i * 2.0f;
+ (*wavyVert).y = (float)j * 2.0f;
+ (*wavyVert).z = 0.0f;
+
+ (*wavyNormal).x = 0.0f;
+ (*wavyNormal).y = 0.0f;
+ (*wavyNormal).z = 1.0f;
+
+ wavyVert++;
+ wavyNormal++;
}
}
@@ -334,31 +464,80 @@ CWaterLevel::CreateWavyAtomic()
RpGeometryUnlock(wavyGeometry);
}
-
{
- wavyFrame = RwFrameCreate();
- ASSERT( wavyFrame != nil );
+ maskMorphTarget = RpGeometryGetMorphTarget(maskGeometry, 0);
+ maskVert = RpMorphTargetGetVertices(maskMorphTarget);
+ maskNormal = RpMorphTargetGetVertexNormals(maskMorphTarget);
- ms_pWavyAtomic = RpAtomicCreate();
- ASSERT( ms_pWavyAtomic != nil );
+ for ( int32 i = 0; i < 33; i++ )
+ {
+ for ( int32 j = 0; j < 33; j++ )
+ {
+ (*maskVert).x = (float)i * 2.0f;
+ (*maskVert).y = (float)j * 2.0f;
+ (*maskVert).z = 0.0f;
+
+ (*maskNormal).x = 0.0f;
+ (*maskNormal).y = 0.0f;
+ (*maskNormal).z = 1.0f;
+
+ maskVert++;
+ maskNormal++;
+ }
+ }
+ RpMorphTargetCalcBoundingSphere(maskMorphTarget, &boundingSphere);
+ RpMorphTargetSetBoundingSphere(maskMorphTarget, &boundingSphere);
+ RpGeometryUnlock(maskGeometry);
+ }
+
+ {
+ wavyFrame = RwFrameCreate();
+ ms_pWavyAtomic = RpAtomicCreate();
RpAtomicSetGeometry(ms_pWavyAtomic, wavyGeometry, 0);
RpAtomicSetFrame(ms_pWavyAtomic, wavyFrame);
RpMaterialDestroy(wavyMaterial);
RpGeometryDestroy(wavyGeometry);
}
+
+ {
+ maskFrame = RwFrameCreate();
+ ms_pMaskAtomic = RpAtomicCreate();
+ RpAtomicSetGeometry(ms_pMaskAtomic, maskGeometry, 0);
+ RpAtomicSetFrame(ms_pMaskAtomic, maskFrame);
+ RpMaterialDestroy(maskMaterial);
+ RpGeometryDestroy(maskGeometry);
+ }
+
+ static RwFrame *wakeEnvFrame;
+
+ if ( wakeEnvFrame == nil )
+ {
+ wakeEnvFrame = RwFrameCreate();
+ RwMatrixSetIdentity(RwFrameGetMatrix(wakeEnvFrame));
+ RwFrameUpdateObjects(wakeEnvFrame);
+ }
+
+ RpMatFXMaterialSetEffects(maskMaterial, rpMATFXEFFECTENVMAP);
+ RpMatFXMaterialSetupEnvMap(maskMaterial, gpWaterEnvTex, wakeEnvFrame, TRUE, fEnvScale);
+ RpMatFXAtomicEnableEffects(ms_pMaskAtomic);
}
void
CWaterLevel::DestroyWavyAtomic()
{
- RwFrame *frame;
-
- frame = RpAtomicGetFrame(ms_pWavyAtomic);
-
- RpAtomicDestroy(ms_pWavyAtomic);
+#define _DELETE_ATOMIC(a) \
+ { \
+ RwFrame *frame; \
+ frame = RpAtomicGetFrame(a); \
+ RpAtomicDestroy(a); \
+ RwFrameDestroy(frame); \
+ }
+
+ _DELETE_ATOMIC(ms_pWavyAtomic);
+ _DELETE_ATOMIC(ms_pMaskAtomic);
- RwFrameDestroy(frame);
+#undef _DELETE_ATOMIC
}
#ifndef MASTER
@@ -511,7 +690,7 @@ CWaterLevel::RemoveIsolatedWater()
{
for (int32 y = 0; y < MAX_SMALL_SECTORS; y++)
{
- if (aWaterFineBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] == 0.0f)
+ if (aWaterFineBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] == 6.0f)
{
numRemoved++;
aWaterFineBlockList[x][y] = NO_WATER;
@@ -528,11 +707,13 @@ CWaterLevel::RemoveIsolatedWater()
bool
CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ)
{
- int32 x = WATER_HUGE_X(fX);
- int32 y = WATER_HUGE_Y(fY);
-
- ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE );
- ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE );
+ int32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET);
+ int32 y = WATER_TO_SMALL_SECTOR_Y(fY);
+
+#ifdef FIX_BUGS
+ if ( x < 0 || x >= MAX_SMALL_SECTORS ) return false;
+ if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;
+#endif
int8 nBlock = aWaterFineBlockList[x][y];
@@ -546,12 +727,13 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool
float fWave = Sin
(
- /*( WATER_UNSIGN_Y(fY) - float(y) * MAX_HUGE_SECTORS + WATER_UNSIGN_X(fX) - float(x) * MAX_HUGE_SECTORS )*/ // VC
- (float)( ((int32)fX & (MAX_HUGE_SECTORS-1)) + ((int32)fY & (MAX_HUGE_SECTORS-1)) )
- * (TWOPI / MAX_HUGE_SECTORS ) + fAngle
+ ( WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE
+ + WATER_UNSIGN_X(fX + WATER_X_OFFSET) - x*SMALL_SECTOR_SIZE )
+
+ * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle
);
- float fWindFactor = CWeather::Wind * 0.7f + 0.3f;
+ float fWindFactor = CWeather::WindClipped * 0.4f + 0.2f;
*pfOutLevel += fWave * fWindFactor;
@@ -567,11 +749,13 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool
bool
CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel)
{
- int32 x = WATER_HUGE_X(fX);
- int32 y = WATER_HUGE_Y(fY);
-
- ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE );
- ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE );
+ int32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET);
+ int32 y = WATER_TO_SMALL_SECTOR_Y(fY);
+
+#ifdef FIX_BUGS
+ if ( x < 0 || x >= MAX_SMALL_SECTORS ) return false;
+ if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;
+#endif
int8 nBlock = aWaterFineBlockList[x][y];
@@ -584,18 +768,49 @@ CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLeve
return true;
}
-inline float
-_GetWaterDrawDist()
+float
+CWaterLevel::GetWaterWavesOnly(short x, short y)
{
- // if z less then 15.0f return 1200.0f
- if ( TheCamera.GetPosition().z < 15.0f )
- return 1200.0f;
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+
+ float fWindFactor = CWeather::WindClipped * 0.7f + 0.3f;
+
+ float fWave = Sin( float(float(4 * y + 4 * x) * (TWOPI / SMALL_SECTOR_SIZE )) + fAngle );
+
+ return fWave * fWindFactor;
+}
+
+CVector
+CWaterLevel::GetWaterNormal(float fX, float fY)
+{
+ //TODO: BUG ? no x offset
+
+ int32 x = WATER_TO_SMALL_SECTOR_X(fX);
+ int32 y = WATER_TO_SMALL_SECTOR_Y(fY);
+
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+ float fWindFactor = CWeather::WindClipped * 0.4f + 0.2f;
+
+ float _fWave = (WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE + WATER_UNSIGN_X(fX) - x*SMALL_SECTOR_SIZE)
+ * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle;
- // if z greater then 60.0f return 2000.0f;
- if ( TheCamera.GetPosition().z > 60.0f )
- return 2000.0f;
+ CVector vA(1.0f, 0.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave));
+ CVector vB(0.0f, 1.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave));
+
+ CVector norm = CrossProduct(vA, vB);
+
+ norm.Normalise();
+
+ return norm;
+}
- return (TheCamera.GetPosition().z + -15.0f) * 800.0f / 45.0f + 1200.0f;
+
+inline float
+_GetWaterDrawDist()
+{
+ if ( TheCamera.GetPosition().z < 15.0f ) return 1200.0f;
+ if ( TheCamera.GetPosition().z > 60.0f ) return 2000.0f;
+ return ( TheCamera.GetPosition().z + -15.0f ) * 800.0f / 45.0f + 1200.0f;
}
inline float
@@ -629,6 +844,49 @@ _GetCamBounds(bool *bUseCamStartY, bool *bUseCamEndY, bool *bUseCamStartX, bool
}
}
+
+inline bool
+_IsColideWithBlock(int32 x, int32 y, int32 &block)
+{
+ block = CWaterLevel::aWaterFineBlockList[x + 0][y + 0];
+ if (block >= 0)
+ return true;
+
+ block = CWaterLevel::aWaterFineBlockList[x + 0][y + 1];
+ if (block >= 0)
+ {
+ block = CWaterLevel::aWaterFineBlockList[x + 0][y + 2];
+ if (block >= 0)
+ return true;
+ }
+
+ block = CWaterLevel::aWaterFineBlockList[x + 1][y + 0];
+ if (block >= 0)
+ return true;
+
+ block = CWaterLevel::aWaterFineBlockList[x + 1][y + 1];
+ if (block >= 0)
+ {
+ block = CWaterLevel::aWaterFineBlockList[x + 1][y + 2];
+ if (block >= 0)
+ return true;
+ }
+
+ block = CWaterLevel::aWaterFineBlockList[x + 2][y + 0];
+ if (block >= 0)
+ return true;
+
+ block = CWaterLevel::aWaterFineBlockList[x + 2][y + 1];
+ if (block >= 0)
+ {
+ block = CWaterLevel::aWaterFineBlockList[x + 2][y + 2];
+ if (block >= 0)
+ return true;
+ }
+
+ return false;
+}
+
inline float
SectorRadius(float fSize)
{
@@ -643,71 +901,91 @@ CWaterLevel::RenderWater()
if (gbDontRenderWater)
return;
#endif
- PUSH_RENDERGROUP("CWaterLevel::RenderWater");
bool bUseCamEndX = false;
bool bUseCamStartY = false;
bool bUseCamStartX = false;
bool bUseCamEndY = false;
- float fWavySectorMaxRenderDist = _GetWavyDrawDist();
- float fWavySectorMaxRenderDistSqr = SQR(fWavySectorMaxRenderDist);
+ if ( !CGame::CanSeeWaterFromCurrArea() )
+ return;
_GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX);
float fHugeSectorMaxRenderDist = _GetWaterDrawDist();
float fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist);
- float windAddUV = CWeather::Wind * 0.0015f + 0.0005f;
+ float windAddUV = CWeather::WindClipped * 0.0005f + 0.0006f;
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
if ( !CTimer::GetIsPaused() )
{
-#ifdef FIX_BUGS
- TEXTURE_ADDU += (CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV) * CTimer::GetTimeStepFix();
- TEXTURE_ADDV += (CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV) * CTimer::GetTimeStepFix();
-#else
- TEXTURE_ADDU += CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV;
- TEXTURE_ADDV += CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV;
-#endif
+ TEXTURE_ADDU += windAddUV;
+ TEXTURE_ADDV += windAddUV;
+
+ _TEXTURE_MASK_ADDU += Sin(fAngle) * 0.0005f + 1.1f * windAddUV;
+ _TEXTURE_MASK_ADDV -= Cos(fAngle * 1.3f) * 0.0005f + 1.2f * windAddUV;
+
+ _TEXTURE_WAKE_ADDU -= Sin(fAngle) * 0.0003f + windAddUV;
+ _TEXTURE_WAKE_ADDV += Cos(fAngle * 0.7f) * 0.0003f + windAddUV;
}
+ if ( _TEXTURE_MASK_ADDU >= 1.0f )
+ _TEXTURE_MASK_ADDU = 0.0f;
+ if ( _TEXTURE_MASK_ADDV >= 1.0f )
+ _TEXTURE_MASK_ADDV = 0.0f;
+
+ if ( _TEXTURE_WAKE_ADDU >= 1.0f )
+ _TEXTURE_WAKE_ADDU = 0.0f;
+ if ( _TEXTURE_WAKE_ADDV >= 1.0f )
+ _TEXTURE_WAKE_ADDV = 0.0f;
+
if ( TEXTURE_ADDU >= 1.0f )
TEXTURE_ADDU = 0.0f;
if ( TEXTURE_ADDV >= 1.0f )
TEXTURE_ADDV = 0.0f;
- WavesCalculatedThisFrame = false;
+#ifdef PC_WATER
+ _fWaterZOffset = CWeather::WindClipped * 0.5f + 0.25f;
+#endif
RwRGBA color = { 0, 0, 0, 255 };
-
- color.red = uint32((CTimeCycle::GetDirectionalRed() * 0.5f + CTimeCycle::GetAmbientRed() ) * 255.0f);
- color.green = uint32((CTimeCycle::GetDirectionalGreen() * 0.5f + CTimeCycle::GetAmbientGreen()) * 255.0f);
- color.blue = uint32((CTimeCycle::GetDirectionalBlue() * 0.5f + CTimeCycle::GetAmbientBlue() ) * 255.0f);
+
+ color.red = CTimeCycle::GetWaterRed();
+ color.green = CTimeCycle::GetWaterGreen();
+ color.blue = CTimeCycle::GetWaterBlue();
+
+#ifndef PC_WATER
+ RwRGBA colorUnderwater = { 0, 0, 0, 255 };
+ colorUnderwater.red = (uint32)(0.8f * (float)colorUnderwater.red);
+ colorUnderwater.green = (uint32)(0.8f * (float)colorUnderwater.green);
+ colorUnderwater.blue = (uint32)(0.8f * (float)colorUnderwater.blue);
+#endif
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
+
+#ifndef PC_WATER
+ WavesCalculatedThisFrame = false;
+#endif
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
- CVector2D camPos
- (
- TheCamera.GetPosition().x,
- TheCamera.GetPosition().y
- );
+ CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);
- int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist);
- int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist) + 1;
+ int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET);
+ int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1;
int32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist);
int32 nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist) + 1;
-
+
if ( bUseCamStartX )
- nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x);
+ nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
if ( bUseCamEndX )
- nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x);
+ nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
if ( bUseCamStartY )
nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y);
if ( bUseCamEndY )
@@ -727,7 +1005,276 @@ CWaterLevel::RenderWater()
|| aWaterBlockList[2*x+0][2*y+1] >= 0
|| aWaterBlockList[2*x+1][2*y+1] >= 0 )
{
- float fX = WATER_FROM_HUGE_SECTOR_X(x);
+ float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET;
+ float fY = WATER_FROM_HUGE_SECTOR_Y(y);
+
+ CVector2D vecHugeSectorCentre(fX + HUGE_SECTOR_SIZE/2,fY + HUGE_SECTOR_SIZE/2);
+
+ float fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr();
+
+ if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE)) )
+ {
+#ifndef PC_WATER
+ WavesCalculatedThisFrame = true;
+#endif
+
+
+ float fZ;
+
+ if ( aWaterBlockList[2*x+0][2*y+0] >= 0 )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ];
+
+ if ( aWaterBlockList[2*x+1][2*y+0] >= 0 )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ];
+
+ if ( aWaterBlockList[2*x+0][2*y+1] >= 0 )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ];
+
+ if ( aWaterBlockList[2*x+1][2*y+1] >= 0 )
+ fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ];
+
+ if ( fHugeSectorDistToCamSqr >= SQR(500.0f) )
+ {
+ RenderOneFlatHugeWaterPoly(fX, fY, fZ, color);
+ }
+ else
+ {
+#ifndef PC_WATER
+ if (m_bRenderSeaBed)
+ RenderOneSlopedUnderWaterPoly(fX, fY, fZ, colorUnderwater);
+#endif
+ // see RenderTransparentWater()
+ ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ ----------- ---------------------- ----------------------
+ | [N] | | [ EndY ] | | [ top ] |
+ | | | | | |
+ |[W] [0] [E]| |[StartX] [] [ EndX ]| |[ left ] [] [ right]|
+ | | | | | |
+ | [S] | | [StartY] | | [bottom] |
+ ----------- ---------------------- ----------------------
+
+
+ [S] [StartY] [bottom]
+ [N] [EndY] [top]
+ [W] [StartX] [left]
+ [E] [EndX] [right]
+
+ [S] -> [N] && [W] -> [E]
+ bottom -> top && left -> right
+ */
+
+ for ( int32 x = 0; x < 26; x++ )
+ {
+ for ( int32 y = 0; y < 5; y++ )
+ {
+ float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - WATER_X_OFFSET;
+ float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
+
+ if ( !bUseCamStartY )
+ {
+ CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2);
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+
+ if ( !bUseCamEndY )
+ {
+ CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, -(fY + EXTRAHUGE_SECTOR_SIZE/2));
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+ }
+ }
+
+ for ( int32 y = 5; y < 21; y++ )
+ {
+ for ( int32 x = 0; x < 5; x++ )
+ {
+ float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - WATER_X_OFFSET;
+ float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f + WATER_X_OFFSET;
+ float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
+
+ if ( !bUseCamStartX )
+ {
+ CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2);
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+
+ if ( !bUseCamEndX )
+ {
+ CVector2D vecExtraHugeSectorCentre(-(fX2 + EXTRAHUGE_SECTOR_SIZE/2), fY + EXTRAHUGE_SECTOR_SIZE/2);
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.x, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+ }
+ }
+
+ RenderAndEmptyRenderBuffer();
+
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ if ( WavesCalculatedThisFrame )
+ {
+ RenderSeaBirds();
+ RenderShipsOnHorizon();
+ CParticle::HandleShipsAtHorizonStuff();
+ HandleBeachToysStuff();
+ }
+
+ if ( _bSeaLife )
+ HandleSeaLifeForms();
+
+ DefinedState();
+}
+
+
+void
+CWaterLevel::RenderTransparentWater(void)
+{
+ bool bUseCamEndX = false;
+ bool bUseCamStartY = false;
+
+ bool bUseCamStartX = false;
+ bool bUseCamEndY = false;
+
+ _bSeaLife = false;
+
+ if ( !CGame::CanSeeWaterFromCurrArea() )
+ return;
+
+ PUSH_RENDERGROUP("CWaterLevel::RenderTransparentWater");
+
+ float fWaterDrawDist = _GetWavyDrawDist();
+ float fWaterDrawDistLarge = fWaterDrawDist + 90.0f;
+ float fWavySectorMaxRenderDistSqr = SQR(fWaterDrawDist);
+
+ _GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX);
+
+ float fHugeSectorMaxRenderDist = _GetWaterDrawDist();
+ float fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist);
+
+ RenderBoatWakes();
+
+ RwRGBA color;
+
+ color.red = CTimeCycle::GetWaterRed();
+ color.green = CTimeCycle::GetWaterGreen();
+ color.blue = CTimeCycle::GetWaterBlue();
+ color.alpha = 255;
+
+ RwRGBA colorTrans;
+
+ colorTrans.red = CTimeCycle::GetWaterRed();
+ colorTrans.green = CTimeCycle::GetWaterGreen();
+ colorTrans.blue = CTimeCycle::GetWaterBlue();
+ colorTrans.alpha = CTimeCycle::GetWaterAlpha();
+
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+
+#ifndef PC_WATER
+ WavesCalculatedThisFrame = false;
+#endif
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster);
+#ifndef PC_WATER
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+#endif
+
+ CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);
+
+ int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET);
+ int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1;
+ int32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist );
+ int32 nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist ) + 1;
+
+ if ( bUseCamStartX )
+ nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
+ if ( bUseCamEndX )
+ nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);
+ if ( bUseCamStartY )
+ nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y );
+ if ( bUseCamEndY )
+ nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y );
+
+ nStartX = Clamp(nStartX, 0, MAX_HUGE_SECTORS - 1);
+ nEndX = Clamp(nEndX, 0, MAX_HUGE_SECTORS - 1);
+ nStartY = Clamp(nStartY, 0, MAX_HUGE_SECTORS - 1);
+ nEndY = Clamp(nEndY, 0, MAX_HUGE_SECTORS - 1);
+
+
+ for ( int32 x = nStartX; x <= nEndX; x++ )
+ {
+ for ( int32 y = nStartY; y <= nEndY; y++ )
+ {
+ if ( aWaterBlockList[2*x+0][2*y+0] >= 0
+ || aWaterBlockList[2*x+1][2*y+0] >= 0
+ || aWaterBlockList[2*x+0][2*y+1] >= 0
+ || aWaterBlockList[2*x+1][2*y+1] >= 0 )
+ {
+ float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET;
float fY = WATER_FROM_HUGE_SECTOR_Y(y);
CVector2D vecHugeSectorCentre
@@ -737,28 +1284,15 @@ CWaterLevel::RenderWater()
);
float fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr();
-
+
if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )
{
if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE)) )
{
- if ( fHugeSectorDistToCamSqr >= SQR(500.0f) /*fHugeSectorNearDist*/ )
+ if ( fHugeSectorDistToCamSqr >= SQR(500.0f) )
{
- float fZ;
-
- if ( aWaterBlockList[2*x+0][2*y+0] >= 0 )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ];
-
- if ( aWaterBlockList[2*x+1][2*y+0] >= 0 )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ];
-
- if ( aWaterBlockList[2*x+0][2*y+1] >= 0 )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ];
-
- if ( aWaterBlockList[2*x+1][2*y+1] >= 0 )
- fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ];
-
- RenderOneFlatHugeWaterPoly(fX, fY, fZ, color);
+ // see RenderWater()
+ ;
}
else
{
@@ -768,20 +1302,16 @@ CWaterLevel::RenderWater()
{
if ( aWaterBlockList[x2][y2] >= 0 )
{
- float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2);
+ float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2) - WATER_X_OFFSET;
float fLargeY = WATER_FROM_LARGE_SECTOR_Y(y2);
- CVector2D vecLargeSectorCentre
- (
- fLargeX + LARGE_SECTOR_SIZE/2,
- fLargeY + LARGE_SECTOR_SIZE/2
- );
+ CVector2D vecLargeSectorCentre(fLargeX + LARGE_SECTOR_SIZE/2, fLargeY + LARGE_SECTOR_SIZE/2);
float fLargeSectorDistToCamSqr = (camPos - vecLargeSectorCentre).MagnitudeSqr();
if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr )
{
- if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE)) ) //90.879997f,
+ if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE)) )
{
// Render four small(32x32) sectors, or one large(64x64).
@@ -794,9 +1324,13 @@ CWaterLevel::RenderWater()
// ---------
// [S]
//
-
- if ( fLargeSectorDistToCamSqr < SQR(176.0f) )
- {
+
+ float fLargeSectorDrawDistSqr = SQR((fWaterDrawDistLarge + 16.0f));
+
+ if ( fLargeSectorDistToCamSqr < fLargeSectorDrawDistSqr )
+ {
+ _bSeaLife = true;
+
float fZ;
// WS
@@ -805,19 +1339,15 @@ CWaterLevel::RenderWater()
float fSmallX = fLargeX;
float fSmallY = fLargeY;
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+0] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
// SE
@@ -826,19 +1356,15 @@ CWaterLevel::RenderWater()
float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2);
float fSmallY = fLargeY;
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+0] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
// WN
@@ -847,19 +1373,15 @@ CWaterLevel::RenderWater()
float fSmallX = fLargeX;
float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2);
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2,fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+1] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
//NE
@@ -868,19 +1390,15 @@ CWaterLevel::RenderWater()
float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2);
float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2);
- CVector2D vecSmallSectorCentre
- (
- fSmallX + SMALL_SECTOR_SIZE/2,
- fSmallY + SMALL_SECTOR_SIZE/2
- );
+ CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);
float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();
fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+1] ];
if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )
- RenderOneWavySector(fSmallX, fSmallY, fZ, color);
+ RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);
else
- RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color);
+ RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);
}
}
else
@@ -891,13 +1409,11 @@ CWaterLevel::RenderWater()
RenderOneFlatLargeWaterPoly(fLargeX, fLargeY, fZ, color);
}
- } // if ( TheCamera.IsSphereVisible
- } // if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr )
- } // if ( aWaterBlockList[x2][y2] >= 0 )
- } // for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ )
- } // for ( int32 x2 = 2*x; x2 <= 2*x+1; x2++ )
- //
-
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -905,194 +1421,102 @@ CWaterLevel::RenderWater()
}
}
- /*
- ----------- ---------------------- ----------------------
- | [N] | | [ EndY ] | | [ top ] |
- | | | | | |
- |[W] [0] [E]| |[StartX] [] [ EndX ]| |[ left ] [] [ right]|
- | | | | | |
- | [S] | | [StartY] | | [bottom] |
- ----------- ---------------------- ----------------------
-
-
- [S] [StartY] [bottom]
- [N] [EndY] [top]
- [W] [StartX] [left]
- [E] [EndX] [right]
+ RenderAndEmptyRenderBuffer();
- [S] -> [N] && [W] -> [E]
- bottom -> top && left -> right
- */
-
- if ( !bUseCamStartY )
+#ifdef PC_WATER
+ if ( MaskCalculatedThisFrame
+ && (m_nRenderWaterLayers == 0 || m_nRenderWaterLayers == 2 || m_nRenderWaterLayers == 3) )
{
- for ( int32 x = 0; x < 26; x++ )
- {
- for ( int32 y = 0; y < 5; y++ )
- {
- float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
- float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
-
- CVector2D vecExtraHugeSectorCentre
- (
- fX + EXTRAHUGE_SECTOR_SIZE/2,
- fY + EXTRAHUGE_SECTOR_SIZE/2
- );
-
- float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = PreCalculatedMaskPosn.x;
+ pos.y = PreCalculatedMaskPosn.y;
+ pos.z = PreCalculatedMaskPosn.z;
+
+ RpMatFXMaterialSetEnvMapFrame(RpGeometryGetMaterial(RpAtomicGetGeometry(ms_pMaskAtomic), 0),
+ RwCameraGetFrame(RwCameraGetCurrentCamera()));
+
+ RwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE);
- if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
- {
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
- {
- RenderOneFlatExtraHugeWaterPoly(
- vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
- vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
- 0.0f,
- color);
- }
- }
- }
- }
+ RpAtomicRender(ms_pMaskAtomic);
}
-
- for ( int32 y = 5; y < 21; y++ )
+#else
+ if (!CCullZones::WaterFudge())
{
- for ( int32 x = 0; x < 5; x++ )
- {
- float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
- float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
- float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
-
- if ( !bUseCamStartX )
- {
- CVector2D vecExtraHugeSectorCentre
- (
- fX + EXTRAHUGE_SECTOR_SIZE/2,
- fY + EXTRAHUGE_SECTOR_SIZE/2
- );
-
- float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
-
- if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
- {
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
- {
- RenderOneFlatExtraHugeWaterPoly(
- vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
- vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
- 0.0f,
- color);
- }
- }
- }
-
- if ( !bUseCamEndX )
- {
- CVector2D vecExtraHugeSectorCentre
- (
- -(fX2 + EXTRAHUGE_SECTOR_SIZE/2),
- fY + EXTRAHUGE_SECTOR_SIZE/2
- );
-
- float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
-
- if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
- {
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE)) )
- {
- RenderOneFlatExtraHugeWaterPoly(
- vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
- vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
- 0.0f,
- color);
- }
- }
- }
- }
- }
+ int32 signX = 0;
+ int32 signY = 0;
- RenderAndEmptyRenderBuffer();
-
- CVector cur_pos = TheCamera.GetPosition();
-
- if ( !CCullZones::CamNoRain()
- && !CCullZones::PlayerNoRain()
- && CWeather::NewWeatherType == WEATHER_SUNNY
- && CClock::GetHours() > 6 && CClock::GetHours() < 20
- && WavesCalculatedThisFrame)
- {
- static CVector prev_pos(0.0f, 0.0f, 0.0f);
- static CVector prev_front(0.0f, 0.0f, 0.0f);
- static int32 timecounter;
+ float fCamX = camPos.x - SMALL_SECTOR_SIZE;
+ float fCamY = camPos.y - SMALL_SECTOR_SIZE;
- if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
- {
- prev_pos = cur_pos;
- timecounter = CTimer::GetTimeInMilliseconds();
- }
- else if ( CTimer::GetTimeInMilliseconds() - timecounter > 5000 )
+ if (TheCamera.GetForward().x > 0.3f)
+ signX = 1;
+ else if (TheCamera.GetForward().x < -0.3f)
+ signX = -1;
+
+ fCamX += 0.3f * (float)signX * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f
+
+ if (TheCamera.GetForward().y > 0.3f)
+ signY = 1;
+ else if (TheCamera.GetForward().y < -0.3f)
+ signY = -1;
+
+ fCamY += 0.3f * (float)signY * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f
+
+ int32 nBlock;
+
+ int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1;
+ int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY) + 1;
+
+ if (_IsColideWithBlock(BlockX, BlockY, nBlock))
{
- static int32 birdgenTime = 0;
-
- if ( CTimer::GetTimeInMilliseconds() - birdgenTime > 1000 )
+ if (m_nRenderWaterLayers != 1 && m_nRenderWaterLayers != 6)
{
- birdgenTime = CTimer::GetTimeInMilliseconds();
-
- CVector vecPos = cur_pos;
-
- float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f);
-
- int32 nRot = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE-1;
-
- float fCos = CParticle::Cos(nRot);
- float fSin = CParticle::Sin(nRot);
-
- vecPos.x += (fCos - fSin) * fAngle;
- vecPos.y += (fSin + fCos) * fAngle;
- vecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f);
-
- CVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
- CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
- 0.0f);
-
- CParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir);
+ float fMaskX = Floor(fCamX / 2.0f) * 2.0f;
+ float fMaskY = Floor(fCamY / 2.0f) * 2.0f;
+ float fWaterZ = CWaterLevel::ms_aWaterZs[nBlock];
+ float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET;
+ float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);
+
+ RenderWavyMask(fMaskX, fMaskY, fWaterZ,
+ fSectorX, fSectorY,
+ signX, signY, colorTrans);
}
}
}
-
+
DefinedState();
+#endif
POP_RENDERGROUP();
}
-void
-CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)
+void CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)
{
if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
RenderAndEmptyRenderBuffer();
int32 vidx = TempBufferVerticesStored;
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color);
int32 iidx = TempBufferIndicesStored;
@@ -1116,25 +1540,25 @@ CWaterLevel::RenderOneFlatLargeWaterPoly(float fX, float fY, float fZ, RwRGBA co
int32 vidx = TempBufferVerticesStored;
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 2.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 2.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 2.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 2.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, color.alpha);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color);
int32 iidx = TempBufferIndicesStored;
@@ -1157,27 +1581,33 @@ CWaterLevel::RenderOneFlatHugeWaterPoly(float fX, float fY, float fZ, RwRGBA con
RenderAndEmptyRenderBuffer();
int32 vidx = TempBufferVerticesStored;
-
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwRGBA c;
+
+ c.red = color.red;
+ c.green = color.green;
+ c.blue = color.blue;
+ c.alpha = 255;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 4.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 4.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 4.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 4.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c);
int32 iidx = TempBufferIndicesStored;
@@ -1200,27 +1630,33 @@ CWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGB
RenderAndEmptyRenderBuffer();
int32 vidx = TempBufferVerticesStored;
-
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET);
+ RwRGBA c;
+
+ c.red = color.red;
+ c.green = color.green;
+ c.blue = color.blue;
+ c.alpha = 255;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 8.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 8.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 8.0f);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c);
- RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 8.0f);
RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
- RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);
+ RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c);
int32 iidx = TempBufferIndicesStored;
@@ -1237,172 +1673,1218 @@ CWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGB
}
void
-CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bUnk)
+CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender)
{
- float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
-
- if ( !WavesCalculatedThisFrame )
+ CVector vecSectorPos(fX + (SMALL_SECTOR_SIZE/2), fY + (SMALL_SECTOR_SIZE/2), fZ + 2.0f);
+
+ if ( COcclusion::IsAABoxOccluded(vecSectorPos, SMALL_SECTOR_SIZE, SMALL_SECTOR_SIZE, 4.0f) )
+ return;
+
+#ifdef PC_WATER
+ RequireWavySector = true;
+#else
+ if (!WavesCalculatedThisFrame)
{
- nGeomUsed = 0;
-
WavesCalculatedThisFrame = true;
+
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+ RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+ RwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ RpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);
+
+ RwMatrix *camMat = RwFrameGetLTM(RwCameraGetFrame(RwCameraGetCurrentCamera())); //or curWorld
+
+ float randomDampInv2 = (1.0f - fRandomDamp) * 2.0f;
+
+ float move = 1.0f / 16.0f;
+ float randomMove = 1.0f / (16.0f * fRandomMoveDiv);
+
+ float vertMul = 0.5f;
+
+ float wind = CWeather::WindClipped * 0.4f + 0.2f;
+ float waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f;
+
+ float waveA = (TWOPI / 16.0f)
+ * ((fNormalDirectionScalar1 * Abs(camMat->at.x + camMat->at.y) + fNormMult) * (CWeather::WindClipped * 0.4f + 0.2f));
+
+ float waveB = TWOPI / (16.0f * fWave2NormScale)
+ * ((fNormalDirectionScalar2 * Abs(camMat->at.y - camMat->at.x) + fNormMultB) * (CWeather::WindClipped * 0.2f + 0.1f));
+
+ CVector vA(1.0f, 0.0f, 0.0f);
+ CVector vB(0.0f, 1.0f, 0.0f);
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ for ( int32 j = 0; j < 17; j++ )
+ {
+ wavyTexCoords->u = float(i) * move + TEXTURE_ADDV;
+ wavyTexCoords->v = float(j) * move + TEXTURE_ADDU;
+
+ RwRGBAAssign(wavyPreLight, &color);
+
+ if (i > 0 && i < 16 && j > 0 && j < 16)
+ {
+ wavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->x *= fRandomDamp;
+ wavyMorphVerts->x += float(i) * randomDampInv2;
+
+ wavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->y *= fRandomDamp;
+ wavyMorphVerts->y += float(j) * randomDampInv2;
+ }
+
+ float morphVertXHalf = (i == 16) ? 0.0f : vertMul * wavyMorphVerts->x;
+ float morphVertYHalf = (j == 16) ? 0.0f : vertMul * wavyMorphVerts->y;
+
+ float waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle;
+ float waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle;
+
+ wavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB);
+
+ vA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB));
+ vB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB));
+
+ CVector norm = CrossProduct(vA, vB);
+ norm.Normalise();
+
+ wavyMorphNormals->x = norm.x;
+ wavyMorphNormals->y = norm.y;
+ wavyMorphNormals->z = norm.z;
+
+ ++wavyPreLight;
+ ++wavyTexCoords;
+
+ ++wavyMorphVerts;
+ ++wavyMorphNormals;
+ }
+ }
+
+ RpGeometryUnlock(wavyGeometry);
+ }
+
+ float fCentreX = fX + (SMALL_SECTOR_SIZE / 2);
+ float fCentreY = fY + (SMALL_SECTOR_SIZE / 2);
+#endif
+
+#ifdef PC_WATER
+ if ( WavesCalculatedThisFrame )
+#endif
+ {
+ if (bDontRender == false
+ && m_nRenderWaterLayers != 2
+ && m_nRenderWaterLayers != 4
+ && m_nRenderWaterLayers != 6 )
+ {
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = fX;
+ pos.y = fY;
+ pos.z = fZ;
+
+ RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE);
- CBoat::FillBoatList();
+ RpAtomicRender(ms_pWavyAtomic);
+ }
+ }
+}
- ASSERT( ms_pWavyAtomic != nil );
+int16
+_RoundValue(int32 v)
+{
+ int16 result = v;
+
+ while ( result < 0 ) result += 16;
+ while ( result > 16 ) result -= 16;
+
+ return result;
+}
- RpGeometry *geometry = RpAtomicGetGeometry(ms_pWavyAtomic);
-
- ASSERT( geometry != nil );
+void
+CWaterLevel::RenderWavyMask(float fX, float fY, float fZ,
+ float fSectorX, float fSectorY,
+#ifdef PC_WATER
+ float fCamPosX, float fCamPosY,
+ float fCamDirX, float fCamDirY, RwRGBA const&color)
+#else
+ int32 nCamDirX, int32 nCamDirY, RwRGBA const&color)
+#endif
+{
+#ifndef PC_WATER
+ bool bRender = true;
+ if (m_nRenderWaterLayers != 0 && m_nRenderWaterLayers != 2 && m_nRenderWaterLayers != 3)
+ bRender = false;
+#endif
+ CVector vecSectorPos(fX + (LARGE_SECTOR_SIZE/2), fY + (LARGE_SECTOR_SIZE/2), fZ + 2.0f);
- RwRGBA *wavyPreLights = RpGeometryGetPreLightColors(geometry);
- RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(geometry, rwTEXTURECOORDINATEINDEX0);
- RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geometry, 0));
-
- ASSERT( wavyPreLights != nil );
- ASSERT( wavyTexCoords != nil );
- ASSERT( wavyVertices != nil );
+ if ( COcclusion::IsAABoxOccluded(vecSectorPos, LARGE_SECTOR_SIZE, LARGE_SECTOR_SIZE, 4.0f) )
+ return;
- RpGeometryLock(geometry, rpGEOMETRYLOCKVERTICES
- | rpGEOMETRYLOCKPRELIGHT
- | rpGEOMETRYLOCKTEXCOORDS);
-
- for ( int32 i = 0; i < 9; i++ )
+#ifndef PC_WATER
+ float fUOffset = fX - (MAX_LARGE_SECTORS * (int32)Floor(fX / MAX_LARGE_SECTORS));
+ float fVOffset = fY - (MAX_LARGE_SECTORS * (int32)Floor(fY / MAX_LARGE_SECTORS));
+
+ int32 nSecsX = (int32)((fX - fSectorX) / 2.0f);
+ int32 nSecsY = (int32)((fY - fSectorY) / 2.0f);
+#endif
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ RpGeometry *maskGeometry = RpAtomicGetGeometry(ms_pMaskAtomic);
+ RwTexCoords *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0);
+ RwRGBA *maskPreLight = RpGeometryGetPreLightColors(maskGeometry);
+ RpMorphTarget *maskMorph = RpGeometryGetMorphTarget(maskGeometry, 0);
+ RwV3d *maskMorphVerts = RpMorphTargetGetVertices(maskMorph);
+ RwV3d *maskMorphNormals = RpMorphTargetGetVertexNormals(maskMorph);
+
+ RpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES|rpGEOMETRYLOCKNORMALS|rpGEOMETRYLOCKPRELIGHT|rpGEOMETRYLOCKTEXCOORDS);
+
+#ifndef PC_WATER
+ RpMaterial *maskMat = RpGeometryGetMaterial(maskGeometry, 0);
+ RpMatFXMaterialSetEnvMapFrame(maskMat, RwCameraGetFrame(RwCameraGetCurrentCamera()));
+ RpMatFXMaterialSetEnvMapCoefficient(maskMat, fEnvScale);
+ RpMatFXMaterialSetEnvMapFrameBufferAlpha(maskMat, TRUE);
+#endif
+
+#ifndef PC_WATER
+ float fMinSparkZ = (CWeather::WindClipped * fWave2Ampl + 0.05f +
+ CWeather::WindClipped * 0.4f + 0.2) * (1.0f - 0.04f * CWeather::SunGlare);
+
+ int32 randval = CGeneral::GetRandomNumber();
+
+ float fUVStep = 0.125f;
+ float f27 = 2.0f;
+
+ float fMinU = (fUOffset / 16.0f) + _TEXTURE_MASK_ADDU;
+ float fMinV = (fVOffset / 16.0f) + _TEXTURE_MASK_ADDV;
+
+ float fAlphaMul = ((float)color.alpha * 0.4f) / 16.0f;
+
+ float fXOffset = 16.0f;
+ if (nCamDirX > 0)
+ fXOffset = 6.4f;
+ else if (nCamDirX < 0)
+ fXOffset = 25.6f;
+
+ float fYOffset = 16.0f;
+ if (nCamDirY > 0)
+ fYOffset = 6.4f;
+ else if (nCamDirY < 0)
+ fYOffset = 25.6f;
+
+ int16 nX = _RoundValue(nSecsX - 1);
+ int16 nY = _RoundValue(nSecsY - 1);
+#else
+ float fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f +
+ 0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare);
+
+ int32 randval = CGeneral::GetRandomNumber() & 255;
+
+ int16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1);
+ int16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1);
+#endif
+ int16 idxX = nX;
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ int16 idxY = nY;
+
+ if ( ++idxX > 16 )
+ idxX -= 16;
+
+ for ( int32 j = 0; j < 17; j++ )
{
- for ( int32 j = 0; j < 9; j++ )
+ if ( ++idxY > 16 )
+ idxY -= 16;
+
+ const int32 a = (0*16);
+ const int32 b = (1*16);
+ const int32 c = (33*16);
+ const int32 d = (34*16);
+
+ int32 base = (i*33+j);
+
+#ifndef PC_WATER
+ maskTexCoords[base + a].u = fMinU + ((float)i * fUVStep);
+ maskTexCoords[base + a].v = fMinV + ((float)j * fUVStep);
+
+ maskTexCoords[base + b].u = maskTexCoords[base + a].u;
+ maskTexCoords[base + b].v = maskTexCoords[base + a].v + (16.0f * fUVStep);
+
+ maskTexCoords[base + c].u = maskTexCoords[base + a].u + (16.0f * fUVStep);
+ maskTexCoords[base + c].v = maskTexCoords[base + a].v;
+
+ maskTexCoords[base + d].u = maskTexCoords[base + a].u + (16.0f * fUVStep);
+ maskTexCoords[base + d].v = maskTexCoords[base + a].v + (16.0f * fUVStep);
+#else
+ maskTexCoords[base+a].v = float(j) / SMALL_SECTOR_SIZE + ((fCamPosY - fY) / 64);
+ maskTexCoords[base+c].v = maskTexCoords[base+a].v;
+ maskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f;
+ maskTexCoords[base+b].v = maskTexCoords[base+d].v;
+
+ maskTexCoords[base+a].u = float(i) / SMALL_SECTOR_SIZE + ((fCamPosX - fX) / 64);
+ maskTexCoords[base+b].u = maskTexCoords[base+a].u;
+ maskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f;
+ maskTexCoords[base+c].u = maskTexCoords[base+d].u;
+#endif
+
+ maskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f);
+ maskMorphVerts[base+b].x = maskMorphVerts[base+a].x;
+ maskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].x = maskMorphVerts[base+c].x;
+
+ maskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f);
+ maskMorphVerts[base+c].y = maskMorphVerts[base+a].y;
+ maskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].y = maskMorphVerts[base+b].y;
+
+ maskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z;
+ maskMorphVerts[base+d].z = maskMorphVerts[base+a].z;
+ maskMorphVerts[base+c].z = maskMorphVerts[base+d].z;
+ maskMorphVerts[base+b].z = maskMorphVerts[base+c].z;
+
+#ifndef PC_WATER
+ if (maskMorphVerts[base].z >= fMinSparkZ)
+#else
+ if ( maskMorphVerts[base].z > fMinSparkZ )
+#endif
{
- wavyTexCoords[9*i+j].u = float(i) / 8 + TEXTURE_ADDV;
- wavyTexCoords[9*i+j].v = float(j) / 8 + TEXTURE_ADDU;
- RwRGBAAssign(&wavyPreLights[9*i+j], &color);
+ switch ( (i + j + randval) & 3 )
+ {
+ case 0:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+a].x,
+ fY + maskMorphVerts[base+a].y,
+ fZ + maskMorphVerts[base+a].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
- wavyVertices[9*i+j].z = ( CWeather::Wind * 0.7f + 0.3f )
- * ( Sin(float(i + j) * DEGTORAD(45.0f) + fAngle) )
- + ( CWeather::Wind * 0.2f * Sin(float(j - i) * PI + (2.0f * fAngle)) );
+ case 1:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+c].x,
+ fY + maskMorphVerts[base+c].y,
+ fZ + maskMorphVerts[base+c].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+
+ case 2:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+b].x,
+ fY + maskMorphVerts[base+b].y,
+ fZ + maskMorphVerts[base+b].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+
+ case 3:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+d].x,
+ fY + maskMorphVerts[base+d].y,
+ fZ + maskMorphVerts[base+d].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+ }
}
+
+ maskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x;
+ maskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y;
+ maskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z;
+
+ maskMorphNormals[base+d].x = maskMorphNormals[base+a].x;
+ maskMorphNormals[base+d].y = maskMorphNormals[base+a].y;
+ maskMorphNormals[base+d].z = maskMorphNormals[base+a].z;
+
+ maskMorphNormals[base+c].x = maskMorphNormals[base+d].x;
+ maskMorphNormals[base+c].y = maskMorphNormals[base+d].y;
+ maskMorphNormals[base+c].z = maskMorphNormals[base+d].z;
+
+ maskMorphNormals[base+b].x = maskMorphNormals[base+c].x;
+ maskMorphNormals[base+b].y = maskMorphNormals[base+c].y;
+ maskMorphNormals[base+b].z = maskMorphNormals[base+c].z;
+
+ maskPreLight[base+a].red = color.red;
+ maskPreLight[base+a].green = color.green;
+ maskPreLight[base+a].blue = color.blue;
+ maskPreLight[base+a].alpha = color.alpha;
+
+ maskPreLight[base+d].red = maskPreLight[base+a].red;
+ maskPreLight[base+d].green = maskPreLight[base+a].green;
+ maskPreLight[base+d].blue = maskPreLight[base+a].blue;
+ maskPreLight[base+d].alpha = maskPreLight[base+a].alpha;
+
+ maskPreLight[base+c].red = maskPreLight[base+d].red;
+ maskPreLight[base+c].green = maskPreLight[base+d].green;
+ maskPreLight[base+c].blue = maskPreLight[base+d].blue;
+ maskPreLight[base+c].alpha = maskPreLight[base+d].alpha;
+
+ maskPreLight[base+b].red = maskPreLight[base+c].red;
+ maskPreLight[base+b].green = maskPreLight[base+c].green;
+ maskPreLight[base+b].blue = maskPreLight[base+c].blue;
+ maskPreLight[base+b].alpha = maskPreLight[base+c].alpha;
+
+#ifndef PC_WATER
+ maskPreLight[base + a].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs((float)j - fYOffset)))));
+ maskPreLight[base + b].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset)))));
+ maskPreLight[base + c].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs((float)j - fYOffset)))));
+ maskPreLight[base + d].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset)))));
+#endif
+ }
+ }
+
+ RpGeometryUnlock(maskGeometry);
+
+#ifndef PC_WATER
+ {
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = fX;
+ pos.y = fY;
+ pos.z = fZ + 0.05f;
+
+ RwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE);
+
+ if (bRender)
+ {
+#ifdef PS2
+ RpSkyTexCacheFlush();
+#endif
+ RpAtomicRender(ms_pMaskAtomic);
}
-
- RpGeometryUnlock(geometry);
}
+#endif
+}
+
+#ifdef PC_WATER
+void
+CWaterLevel::PreCalcWaterGeometry(void)
+{
+ if ( !RequireWavySector )
+ {
+ WavesCalculatedThisFrame = false;
+ MaskCalculatedThisFrame = false;
+ return;
+ }
+
+ RequireWavySector = false;
+ WavesCalculatedThisFrame = true;
- static CBoat *apBoatList[4] = { nil };
+ RwRGBA color;
- if ( apGeomArray[0]
- && nGeomUsed < MAX_BOAT_WAKES
- && CBoat::IsSectorAffectedByWake(
- CVector2D(fX + (SMALL_SECTOR_SIZE / 2), fY + (SMALL_SECTOR_SIZE / 2)),
- SMALL_SECTOR_SIZE / 2,
- apBoatList) )
+ color.red = CTimeCycle::GetWaterRed();
+ color.green = CTimeCycle::GetWaterGreen();
+ color.blue = CTimeCycle::GetWaterBlue();
+ color.alpha = CTimeCycle::GetWaterAlpha();
+
+ PreCalcWavySector(color);
+
+ if ( CCullZones::WaterFudge() )
{
- float fWakeColor = fAdd1 - Max(255.0f - float(color.blue + color.red + color.green) / 3, fAdd2);
-
- RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
- RpGeometry *geom = apGeomArray[nGeomUsed++];
-
- ASSERT( wavyGeometry != nil );
- ASSERT( geom != nil );
-
- RpAtomic *atomic = RpAtomicCreate();
- ASSERT( atomic != nil );
-
- RpAtomicSetGeometry(atomic, geom, 0);
-
- RwFrame *frame = RwFrameCreate();
- ASSERT( frame != nil );
-
- RwMatrixCopy(RwFrameGetMatrix(frame), RwFrameGetMatrix(RpAtomicGetFrame(ms_pWavyAtomic)));
- RpAtomicSetFrame(atomic, frame);
+ MaskCalculatedThisFrame = false;
+ return;
+ }
+
+ CVector CamFwdDir = TheCamera.GetForward();
+ CamFwdDir.z = 0.0f;
+ CamFwdDir.Normalise();
+
+ float fCamX = TheCamera.GetPosition().x - SMALL_SECTOR_SIZE;
+ float fCamY = TheCamera.GetPosition().y - SMALL_SECTOR_SIZE;
+
+ //1.4144272f; 1.4144f;
+ float signX = CamFwdDir.x * 1.4144272f;
+ float signY = CamFwdDir.y * 1.4144272f;
+
+ signX = Clamp(signX, -1.0f, 1.0f);
+ fCamX += 0.4f * signX * float(SMALL_SECTOR_SIZE * 2.0f);
+
+ signY = Clamp(signY, -1.0f, 1.0f);
+ fCamY += 0.4f * signY * float(SMALL_SECTOR_SIZE * 2.0f);
+
+ int32 nBlock;
+
+ int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1;
+ int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY ) + 1;
+
+ ASSERT( BlockX >= 0 && BlockX < MAX_SMALL_SECTORS );
+ ASSERT( BlockY >= 0 && BlockY < MAX_SMALL_SECTORS );
+
+ if ( _IsColideWithBlock(BlockX, BlockY, nBlock) )
+ {
+ float fMaskX = Floor(fCamX / 2.0f) * 2.0f;
+ float fMaskY = Floor(fCamY / 2.0f) * 2.0f;
+
+ float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET;
+ float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);
- RwTexCoords *geomTexCoords = RpGeometryGetVertexTexCoords(geom, rwTEXTURECOORDINATEINDEX0);
- RwTexCoords *wavyTexCoord = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);
- RwRGBA *geomPreLights = RpGeometryGetPreLightColors(geom);
- RwV3d *geomVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geom, 0));
- RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(wavyGeometry, 0));
+ if ( PreCalcWavyMask( fMaskX, fMaskY, ms_aWaterZs[nBlock],
+ fSectorX, fSectorY, fCamX, fCamY, CamFwdDir.x, CamFwdDir.y, color ) )
+ {
+ PreCalculatedMaskPosn.x = fMaskX;
+ PreCalculatedMaskPosn.y = fMaskY;
+ PreCalculatedMaskPosn.z = ms_aWaterZs[nBlock] + 0.05f;
+
+ MaskCalculatedThisFrame = true;
+ }
+ else
+ MaskCalculatedThisFrame = false;
+ }
+ else
+ MaskCalculatedThisFrame = false;
+}
+
+bool
+CWaterLevel::PreCalcWavySector(RwRGBA const &color)
+{
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+
+ RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+
+ RwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ if ( !m_bRenderSeaBed )
+ RpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES
+ |rpGEOMETRYLOCKNORMALS
+ |rpGEOMETRYLOCKPRELIGHT
+ |rpGEOMETRYLOCKTEXCOORDS);
+
+ CVector camPosUp = TheCamera.GetForward();
- ASSERT( geomTexCoords != nil );
- ASSERT( wavyTexCoord != nil );
- ASSERT( geomPreLights != nil );
- ASSERT( geomVertices != nil );
- ASSERT( wavyVertices != nil );
+ float randomDampInv2 = (1.0f - fRandomDamp) * 2.0f;
+
+ float randomMove = 1.0f / (16.0f * fRandomMoveDiv);
+
+ float wind = CWeather::WindClipped * 0.4f + 0.2f;
+ float waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f;
- RpGeometryLock(geom, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);
+ float waveA = (TWOPI / 16.0f)
+ * ((CWeather::WindClipped * 0.4f + 0.2f) * (fNormalDirectionScalar1 * Abs(camPosUp.x + camPosUp.y) + fNormMult));
- for ( int32 i = 0; i < 9; i++ )
+ float waveB = TWOPI / (16.0f * fWave2NormScale)
+ * ((CWeather::WindClipped * 0.2f + 0.1f) * (fNormalDirectionScalar2 * Abs(camPosUp.y - camPosUp.x) + fNormMultB));
+
+
+ CVector vA(1.0f, 0.0f, 0.0f);
+ CVector vB(0.0f, 1.0f, 0.0f);
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ for ( int32 j = 0; j < 17; j++ )
{
- for ( int32 j = 0; j < 9; j++ )
+ wavyTexCoords->u = (float(i) / 16.0f) + TEXTURE_ADDV;
+ wavyTexCoords->v = (float(j) / 16.0f) + TEXTURE_ADDU;
+
+ RwRGBAAssign(wavyPreLight, &color);
+
+ if ( i > 0 && i < 16 && j > 0 && j < 16 )
{
- geomTexCoords[9*i+j] = wavyTexCoord[9*i+j];
+ wavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->x *= fRandomDamp;
+ wavyMorphVerts->x += float(i) * randomDampInv2;
+
+ wavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;
+ wavyMorphVerts->y *= fRandomDamp;
+ wavyMorphVerts->y += float(j) * randomDampInv2;
+ }
+
+ float morphVertXHalf = ( i == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->x;
+ float morphVertYHalf = ( j == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->y;
+
+ float waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle;
+ float waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle;
+
+ wavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB);
+
+ vA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB));
+ vB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB));
- float fVertexX = (float)i * 4.0f + fX;
- float fVertexY = (float)j * 4.0f + fY;
+ CVector norm = CrossProduct(vA, vB);
+ norm.Normalise();
- float fDistMult = 0.0f;
-
- for ( int32 k = 0; k < 4; k++ )
- {
- if ( apBoatList[k] != nil )
- fDistMult += CBoat::IsVertexAffectedByWake(CVector(fVertexX, fVertexY, 0.0f), apBoatList[k]);
- }
-
- if ( fDistMult > 0.0f )
+ wavyMorphNormals->x = norm.x;
+ wavyMorphNormals->y = norm.y;
+ wavyMorphNormals->z = norm.z;
+
+ ++wavyPreLight;
+ ++wavyTexCoords;
+
+ ++wavyMorphVerts;
+ ++wavyMorphNormals;
+ }
+ }
+
+ RpGeometryUnlock(wavyGeometry);
+
+ return true;
+}
+
+bool
+CWaterLevel::PreCalcWavyMask(float fX, float fY, float fZ,
+ float fSectorX, float fSectorY,
+ float fCamPosX, float fCamPosY,
+ float fCamDirX, float fCamDirY,
+ RwRGBA const&color)
+{
+ CVector vecSectorPos(fX + (MAX_LARGE_SECTORS/2), fY + (MAX_LARGE_SECTORS/2), fZ + 2.0f);
+
+ if ( COcclusion::IsAABoxOccluded(vecSectorPos, MAX_LARGE_SECTORS, MAX_LARGE_SECTORS, 4.0f) )
+ return false;
+
+ Floor(fX / MAX_LARGE_SECTORS);
+ Floor(fY / MAX_LARGE_SECTORS);
+
+ RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
+ RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);
+ RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);
+ RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);
+
+ RpGeometry *maskGeometry = RpAtomicGetGeometry(ms_pMaskAtomic);
+ RwTexCoords *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0);
+ RwRGBA *maskPreLight = RpGeometryGetPreLightColors(maskGeometry);
+ RpMorphTarget *maskMorph = RpGeometryGetMorphTarget(maskGeometry, 0);
+ RwV3d *maskMorphVerts = RpMorphTargetGetVertices(maskMorph);
+ RwV3d *maskMorphNormals = RpMorphTargetGetVertexNormals(maskMorph);
+
+ if ( !m_bRenderSeaBed )
+ RpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);
+
+
+ float fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f +
+ 0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare);
+
+ int32 randval = CGeneral::GetRandomNumber() & 255;
+
+ int16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1);
+ int16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1);
+
+ int16 idxX = nX;
+
+ for ( int32 i = 0; i < 17; i++ )
+ {
+ int16 idxY = nY;
+
+ if ( ++idxX > 16 )
+ idxX -= 16;
+
+ for ( int32 j = 0; j < 17; j++ )
+ {
+ if ( ++idxY > 16 )
+ idxY -= 16;
+
+ const int32 a = (0*16);
+ const int32 b = (1*16);
+ const int32 c = (33*16);
+ const int32 d = (34*16);
+
+ int32 base = (i*33+j);
+
+ maskTexCoords[base+a].v = float(j) / 32 + ((fCamPosY - fY) / 64);
+ maskTexCoords[base+c].v = maskTexCoords[base+a].v;
+ maskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f;
+ maskTexCoords[base+b].v = maskTexCoords[base+d].v;
+
+ maskTexCoords[base+a].u = float(i) / 32 + ((fCamPosX - fX) / 64);
+ maskTexCoords[base+b].u = maskTexCoords[base+a].u;
+ maskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f;
+ maskTexCoords[base+c].u = maskTexCoords[base+d].u;
+
+ maskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f);
+ maskMorphVerts[base+b].x = maskMorphVerts[base+a].x;
+ maskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].x = maskMorphVerts[base+c].x;
+
+ maskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f);
+ maskMorphVerts[base+c].y = maskMorphVerts[base+a].y;
+ maskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE;
+ maskMorphVerts[base+d].y = maskMorphVerts[base+b].y;
+
+ maskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z;
+ maskMorphVerts[base+d].z = maskMorphVerts[base+a].z;
+ maskMorphVerts[base+c].z = maskMorphVerts[base+d].z;
+ maskMorphVerts[base+b].z = maskMorphVerts[base+c].z;
+
+ if ( maskMorphVerts[base].z > fMinSparkZ )
+ {
+ switch ( (i + j + randval) & 3 )
{
- RwRGBA wakeColor;
-
- RwRGBAAssign(&wakeColor, &color);
+ case 0:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+a].x,
+ fY + maskMorphVerts[base+a].y,
+ fZ + maskMorphVerts[base+a].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
- wakeColor.red = Min(color.red + int32(fWakeColor * fRedMult * fDistMult), 255);
- wakeColor.green = Min(color.green + int32(fWakeColor * fGreenMult * fDistMult), 255);
- wakeColor.blue = Min(color.blue + int32(fWakeColor * fBlueMult * fDistMult), 255);
-
- RwRGBAAssign(&geomPreLights[9*i+j], &wakeColor);
+ case 1:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+c].x,
+ fY + maskMorphVerts[base+c].y,
+ fZ + maskMorphVerts[base+c].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+
+ case 2:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+b].x,
+ fY + maskMorphVerts[base+b].y,
+ fZ + maskMorphVerts[base+b].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
+ case 3:
+ {
+ CVector vecPos
+ (
+ fX + maskMorphVerts[base+d].x,
+ fY + maskMorphVerts[base+d].y,
+ fZ + maskMorphVerts[base+d].z + 0.12f
+ );
+
+ vecPos -= 0.05f * TheCamera.GetForward();
+
+ CParticle::AddParticle(PARTICLE_WATER_SPARK,
+ vecPos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil,
+ 0.0f,
+ 15,
+ CGeneral::GetRandomNumberInRange(-90, 90),
+ 0,
+ 0);
+ }
+ break;
}
- else
- RwRGBAAssign(&geomPreLights[9*i+j], &color);
-
-
- geomVertices[9*i+j].z = wavyVertices[9*i+j].z;
}
+
+ maskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x;
+ maskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y;
+ maskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z;
+
+ maskMorphNormals[base+d].x = maskMorphNormals[base+a].x;
+ maskMorphNormals[base+d].y = maskMorphNormals[base+a].y;
+ maskMorphNormals[base+d].z = maskMorphNormals[base+a].z;
+
+ maskMorphNormals[base+c].x = maskMorphNormals[base+d].x;
+ maskMorphNormals[base+c].y = maskMorphNormals[base+d].y;
+ maskMorphNormals[base+c].z = maskMorphNormals[base+d].z;
+
+ maskMorphNormals[base+b].x = maskMorphNormals[base+c].x;
+ maskMorphNormals[base+b].y = maskMorphNormals[base+c].y;
+ maskMorphNormals[base+b].z = maskMorphNormals[base+c].z;
+
+ maskPreLight[base+a].red = color.red;
+ maskPreLight[base+a].green = color.green;
+ maskPreLight[base+a].blue = color.blue;
+ maskPreLight[base+a].alpha = color.alpha;
+
+ maskPreLight[base+d].red = maskPreLight[base+a].red;
+ maskPreLight[base+d].green = maskPreLight[base+a].green;
+ maskPreLight[base+d].blue = maskPreLight[base+a].blue;
+ maskPreLight[base+d].alpha = maskPreLight[base+a].alpha;
+
+ maskPreLight[base+c].red = maskPreLight[base+d].red;
+ maskPreLight[base+c].green = maskPreLight[base+d].green;
+ maskPreLight[base+c].blue = maskPreLight[base+d].blue;
+ maskPreLight[base+c].alpha = maskPreLight[base+d].alpha;
+
+ maskPreLight[base+b].red = maskPreLight[base+c].red;
+ maskPreLight[base+b].green = maskPreLight[base+c].green;
+ maskPreLight[base+b].blue = maskPreLight[base+c].blue;
+ maskPreLight[base+b].alpha = maskPreLight[base+c].alpha;
}
+ }
+
+ RpGeometryUnlock(maskGeometry);
+ return true;
+}
+#endif
+
+void
+CWaterLevel::RenderBoatWakes(void)
+{
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterWakeRaster);
+#ifndef PC_WATER
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+#endif
+
+#ifdef _XBOX
+ // TODO save and restore rwRENDERSTATESRCBLEND rwRENDERSTATEDESTBLEND
+#endif
+
+ CBoat::FillBoatList();
+
+ float fWakeZ = 5.97f;
+ float fWakeLifeTimeMult = 0.01f / CBoat::WAKE_LIFETIME;
+
+ for ( int32 idx = 0; idx < ARRAY_SIZE(CBoat::apFrameWakeGeneratingBoats); idx++ )
+ {
+ CBoat *pBoat = CBoat::apFrameWakeGeneratingBoats[idx];
+
+ if ( pBoat == nil )
+ break;
+
+ CVector2D vecDistA(pBoat->GetForward().x, pBoat->GetForward().y);
+
+
+ float fSize = pBoat->GetColModel()->boundingBox.max.z
+ * 0.65f;
- RpGeometryUnlock(geom);
+ if ( pBoat->GetModelIndex() == MI_SKIMMER)
+ fSize *= 0.4f;
+ float fAplhaA = 255.0f;
+ float fSizeA = fSize;
+ float fAplhaB;
+ float fSizeB;
- RwV3d pos = {0.0f, 0.0f, 0.0f};
+ for ( int32 wake = 1; wake < pBoat->m_nNumWakePoints; wake++ )
+ {
+ bool bRender = true;
+
+ float fTimeleft = CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake];
- pos.x = fX;
- pos.z = fZ;
- pos.y = fY;
+ float fWakeSizeB = ((float)wake * 0.19f) + fSize - fWakeLifeTimeMult * Max(fTimeleft, 0.0f);
+
+ fSizeB = fWakeSizeB / CBoat::MIN_WAKE_INTERVAL;
+ if ( fSizeB < 0.0f )
+ fSizeB = 1.0f;
+
+ if ( wake == pBoat->m_nNumWakePoints - 1 )
+ {
+ // set alpha to 0 if it's last point
+ fAplhaB = 0.0f;
+ }
+ else
+ {
+ // clip (-100, 500), less lifetime - less val
+ float val = 500.0f - (CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake])
+ * 600.0f / CBoat::WAKE_LIFETIME;
+
+ fAplhaB = Clamp(val, 0.0f, 255.0f);
+ }
- RwFrameTranslate(RpAtomicGetFrame(atomic), &pos, rwCOMBINEREPLACE);
+ CVector2D vecDistB = pBoat->m_avec2dWakePoints[wake - 1] - pBoat->m_avec2dWakePoints[wake];
- RpAtomicRender(atomic);
-
- RpAtomicDestroy(atomic);
- RwFrameDestroy(frame);
+ float fScal = vecDistB.MagnitudeSqr();
+
+ // normalize if distance between points is greater than 3
+
+ if ( fScal > SQR(3.0f) )
+ {
+ float fNorm = 1.0f / sqrt(fScal);
+
+ vecDistB.x *= fNorm;
+ vecDistB.y *= fNorm;
+
+ // disable render if distance between points too big
+
+ if ( sqrt(fScal) > 13.0f )
+ bRender = false;
+ }
+
+ CVector2D vecAA
+ (
+ pBoat->m_avec2dWakePoints[wake - 1].x - (fSizeA * vecDistA.y),
+ pBoat->m_avec2dWakePoints[wake - 1].y + (fSizeA * vecDistA.x)
+ );
+ CVector2D vecAB
+ (
+ pBoat->m_avec2dWakePoints[wake - 1].x + (fSizeA * vecDistA.y),
+ pBoat->m_avec2dWakePoints[wake - 1].y - (fSizeA * vecDistA.x)
+ );
+ CVector2D vecBA
+ (
+ pBoat->m_avec2dWakePoints[wake].x + (fSizeB * vecDistB.y),
+ pBoat->m_avec2dWakePoints[wake].y - (fSizeB * vecDistB.x)
+ );
+ CVector2D vecBB
+ (
+ pBoat->m_avec2dWakePoints[wake].x - (fSizeB * vecDistB.y),
+ pBoat->m_avec2dWakePoints[wake].y + (fSizeB * vecDistB.x)
+ );
+
+ if ( bRender )
+ RenderWakeSegment(vecAA, vecAB, vecBA, vecBB, fSizeA, fSizeB, fAplhaA, fAplhaB, fWakeZ);
+
+ vecDistA = vecDistB;
+ fSizeA = fSizeB;
+
+ fAplhaB = fAplhaA;
+ }
}
- else
+
+ RenderAndEmptyRenderBuffer();
+}
+
+inline float
+_GetWindedWave(float fX, float fY)
+{
+ float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);
+ float x = WATER_HUGE_X(fX + WATER_X_OFFSET);
+ float y = WATER_HUGE_Y(fY);
+
+ float fWindFactor (CWeather::WindClipped * 0.4f + 0.2f);
+ float fWave = Sin(( (x - Floor(x)) + (y - Floor(y)) ) * TWOPI + fAngle);
+
+ return fWindFactor * fWave;
+}
+
+void
+CWaterLevel::RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD,
+ float &fSizeA, float &fSizeB,
+ float &fAlphaA, float &fAlphaB,
+ float &fWakeZ)
+{
+ for ( int32 i = 0; i < 4; i++ )
{
- RwV3d pos = { 0.0f, 0.0f, 0.0f };
+ if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
+ RenderAndEmptyRenderBuffer();
+
+ float fCurStep = (float)i / 4;
+ float fNxtStep = (float)(i + 1) / 4;
+
+ float fLeftCurStep = 1.0f - fCurStep;
+ float fLeftNxtStep = 1.0f - fNxtStep;
- pos.x = fX;
- pos.y = fY;
- pos.z = fZ;
+ uint8 AlphaA = (uint32)(fAlphaA * aAlphaFade[i] );
+ uint8 AlphaB = (uint32)(fAlphaA * aAlphaFade[i + 1]);
+ uint8 AlphaC = (uint32)(fAlphaB * aAlphaFade[i + 1]);
+ uint8 AlphaD = (uint32)(fAlphaB * aAlphaFade[i] );
+
+ CVector2D PosA = vecB*fCurStep + vecA*fLeftCurStep;
+ CVector2D PosB = vecB*fNxtStep + vecA*fLeftNxtStep;
+ CVector2D PosC = vecC*fNxtStep + vecD*fLeftNxtStep;
+ CVector2D PosD = vecC*fCurStep + vecD*fLeftCurStep;
+
+ float fUA = (PosA.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVA = (PosA.y / 4) + _TEXTURE_WAKE_ADDV;
+
+ float fUB = (PosB.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVB = (PosB.y / 4) + _TEXTURE_WAKE_ADDV;
+
+ float fUC = (PosC.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVC = (PosC.y / 4) + _TEXTURE_WAKE_ADDV;
+
+ float fUD = (PosD.x / 4) + _TEXTURE_WAKE_ADDU;
+ float fVD = (PosD.y / 4) + _TEXTURE_WAKE_ADDV;
- ASSERT( ms_pWavyAtomic != nil );
+#define MIN4(a, b, c, d) (Min((a), Min((b), Min((c), (d)))))
+ float fMinU = Floor(MIN4(fUA, fUB, fUC, fUD));
+ float fMinV = Floor(MIN4(fVA, fVB, fVC, fVD));
+#undef MIN4
+
+ float fZA = _GetWindedWave(PosA.x, PosA.y) + fWakeZ;
+ float fZB = _GetWindedWave(PosB.x, PosB.y) + fWakeZ;
+ float fZC = _GetWindedWave(PosC.x, PosC.y) + fWakeZ;
+ float fZD = _GetWindedWave(PosD.x, PosD.y) + fWakeZ;
+
+ int32 vidx = TempBufferVerticesStored;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], PosA.x, PosA.y, fZA);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], fUA - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], fVA - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], 255, 255, 255, AlphaA);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], PosB.x, PosB.y, fZB);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], fUB - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], fVB - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], 255, 255, 255, AlphaB);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], PosC.x, PosC.y, fZC);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], fUC - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], fVC - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], 255, 255, 255, AlphaC);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], PosD.x, PosD.y, fZD);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], fUD - fMinU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], fVD - fMinV);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], 255, 255, 255, AlphaD);
- RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE);
+ int32 iidx = TempBufferIndicesStored;
+
+ TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;
- RpAtomicRender(ms_pWavyAtomic);
+ TempBufferVerticesStored += 4;
+
+ TempBufferIndicesStored += 6;
}
}
+void
+CWaterLevel::RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color)
+{
+ CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);
+
+ float fDistA = (CVector2D(fX, fY) - camPos).Magnitude() + -140.0f;
+ float fDistB = (CVector2D(fX, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f;
+ float fDistC = (CVector2D(fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f;
+ float fDistD = (CVector2D(fX + HUGE_SECTOR_SIZE, fY) - camPos).Magnitude() + -140.0f;
+
+#ifndef PC_WATER
+#define CALCSEABED(v, d) \
+ { \
+ if ( d < 0.0f ) \
+ v = 0.1f + fSeaBedZ; \
+ else if ( d > 240.0f ) \
+ v = 0.1f; \
+ else \
+ v = 0.1f + ((fSeaBedZ * (240.0f - d)) / 240.0f); \
+ }
+#else
+ #define CALCSEABED(v, d) \
+ { \
+ v = 0.1f; \
+ if ( d < 0.0f ) \
+ v += fSeaBedZ; \
+ else if ( d <= 240.0f ) \
+ v += (fSeaBedZ / 240.0f) * (240.0f - d); \
+ }
+#endif
+ float fSeaBedA, fSeaBedB, fSeaBedC, fSeaBedD;
+
+ CALCSEABED(fSeaBedA, fDistA);
+ CALCSEABED(fSeaBedB, fDistB);
+ CALCSEABED(fSeaBedC, fDistC);
+ CALCSEABED(fSeaBedD, fDistD);
+
+ #undef CALCSEABED
+
+ if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
+ RenderAndEmptyRenderBuffer();
+
+ int32 vidx = TempBufferVerticesStored;
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset - fSeaBedA);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], 0.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], 0.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedB);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], 0.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], 4.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedC);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], 4.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], 4.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset - fSeaBedD);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], 4.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], 0.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);
+
+ int32 iidx = TempBufferIndicesStored;
+
+ TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;
+
+ TempBufferVerticesStored += 4;
+
+ TempBufferIndicesStored += 6;
+}
+
+void
+CWaterLevel::RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY,
+ RwRGBA const &color, RwRGBA const &colorTrans,
+ float fDrawDist)
+{
+ if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )
+ RenderAndEmptyRenderBuffer();
+
+ int32 vidx = TempBufferVerticesStored;
+
+ float fBlendDrawDist = fDrawDist + fStartBlendDistanceAdd;
+
+ float fDistStartX = SQR(fX - fCamX);
+ float fDistStartY = SQR(fY - fCamY);
+ float fDistEndX = SQR((fX + SMALL_SECTOR_SIZE) - fCamX);
+ float fDistEndY = SQR((fY + SMALL_SECTOR_SIZE) - fCamY);
+
+
+ float fAlphaBlendMulA
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+ float fAlphaBlendMulB
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistEndY ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+ float fAlphaBlendMulC
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX + fDistEndY ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+ float fAlphaBlendMulD
+ = Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);
+
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulA));
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulB));
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulC));
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue,
+ (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulD));
+
+
+ int32 iidx = TempBufferIndicesStored;
+
+ TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;
+
+ TempBufferVerticesStored += 4;
+
+ TempBufferIndicesStored += 6;
+}
+
float
CWaterLevel::CalcDistanceToWater(float fX, float fY)
{
- const float fSectorMaxRenderDist = 75.0f;
+ const float fSectorMaxRenderDist = 250.0f;
- int32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist) - 1;
- int32 nEndX = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist) + 1;
+ int32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist + WATER_X_OFFSET) - 1;
+ int32 nEndX = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist + WATER_X_OFFSET) + 1;
int32 nStartY = WATER_TO_SMALL_SECTOR_Y(fY - fSectorMaxRenderDist) - 1;
int32 nEndY = WATER_TO_SMALL_SECTOR_Y(fY + fSectorMaxRenderDist) + 1;
@@ -1419,7 +2901,7 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY)
{
if ( aWaterFineBlockList[x][y] >= 0 )
{
- float fSectorX = WATER_FROM_SMALL_SECTOR_X(x);
+ float fSectorX = WATER_FROM_SMALL_SECTOR_X(x) - WATER_X_OFFSET;
float fSectorY = WATER_FROM_SMALL_SECTOR_Y(y);
CVector2D vecDist
@@ -1454,101 +2936,442 @@ CWaterLevel::RenderAndEmptyRenderBuffer()
TempBufferVerticesStored = 0;
}
-void
-CWaterLevel::AllocateBoatWakeArray()
+bool
+CWaterLevel::GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance)
{
- CStreaming::MakeSpaceFor(14 * CDSTREAM_SECTOR_SIZE);
+ CColPoint point;
+ CEntity *entity;
+
+ if ( !CWorld::ProcessVerticalLine(vecPosn + CVector(0.0f, 0.0f, fDistance),
+ -fDistance, point, entity, true, false, false, false, true, false, nil) )
+ return false;
+
+ *pfOutLevel = point.point.z;
+
+ if ( pData != nil )
+ {
+ pData->SurfaceType = point.surfaceB;
+ pData->PieceType = point.pieceB;
+ }
+
+ return true;
+}
+
+bool
+CWaterLevel::IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset)
+{
+ int32 x = int32((vecPosn.x / 50.0f) + 48.0f);
+ int32 y = int32((vecPosn.y / 50.0f) + 40.0f);
+
+ return x < nOffset || x >= 80 - nOffset || y < nOffset || y >= 80 - nOffset;
+}
- PUSH_MEMID(MEMID_STREAM);
+bool
+CWaterLevel::GetGroundLevel_WS(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance)
+{
+ if ( IsLocationOutOfWorldBounds_WS(vecPosn, 0) )
+ return false;
+ else
+ return GetGroundLevel(vecPosn, pfOutLevel, pData, fDistance);
+}
- ASSERT(ms_pWavyAtomic != nil );
+bool
+CWaterLevel::GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel)
+{
+ float fLevelNoWaves;
+ float fGroundLevel;
+
+ if ( !GetWaterLevelNoWaves(vecPosn.x, vecPosn.y, vecPosn.z, &fLevelNoWaves) )
+ return false;
+
+ if ( !GetGroundLevel(vecPosn, &fGroundLevel, nil, 30.0f) )
+ fGroundLevel = -100.0;
- RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
- ASSERT(wavyGeometry != nil );
- RpMorphTarget *wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0);
- RpMaterial *wavyMaterial = RpGeometryGetMaterial(wavyGeometry, 0);
+ if ( pfDepth != nil )
+ *pfDepth = fLevelNoWaves - fGroundLevel;
- ASSERT(wavyMorphTarget != nil );
- ASSERT(wavyMaterial != nil );
+ if ( pfLevelNoWaves != nil )
+ *pfLevelNoWaves = fLevelNoWaves;
- for ( int32 geom = 0; geom < MAX_BOAT_WAKES; geom++ )
+ if ( pfGroundLevel != nil )
+ *pfGroundLevel = fGroundLevel;
+
+ return true;
+}
+
+void
+CWaterLevel::RenderSeaBirds()
+{
+ CVector cur_pos = TheCamera.GetPosition();
+
+ if ( !CCullZones::CamNoRain()
+ && !CCullZones::PlayerNoRain()
+ && (CWeather::NewWeatherType == WEATHER_SUNNY || CWeather::NewWeatherType == WEATHER_EXTRA_SUNNY)
+ && CClock::ms_nGameClockHours > 6 && CClock::ms_nGameClockHours < 20 )
{
- if ( apGeomArray[geom] == nil )
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static CVector prev_front(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
{
- apGeomArray[geom] = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP
- | rpGEOMETRYPRELIT
- | rpGEOMETRYMODULATEMATERIALCOLOR
- | rpGEOMETRYTEXTURED);
- ASSERT(apGeomArray[geom] != nil);
+ prev_pos = cur_pos;
+ timecounter = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+ static int32 birdgenTime = 0;
+
+ if ( (CTimer::GetTimeInMilliseconds() - birdgenTime) > 1000 )
+ {
+ birdgenTime = CTimer::GetTimeInMilliseconds();
+
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+ vecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f);
+
+ CVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
+ CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),
+ 0.0f);
+
+ CParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+}
- RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]);
+void
+CWaterLevel::RenderShipsOnHorizon()
+{
+#ifdef FIX_BUGS
+ CVector cur_pos = FindPlayerCoors();
+#else
+ CVector cur_pos = FindPlayerPed()->GetPosition();
+#endif
+
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static CVector prev_front(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
+ {
+ prev_pos = cur_pos;
+ timecounter = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+ static int32 shipgenTime = 0;
+
+ if ( (CTimer::GetTimeInMilliseconds() - shipgenTime) > 4000 )
+ {
+ shipgenTime = CTimer::GetTimeInMilliseconds();
+
+ CVector vecPos = cur_pos;
- ASSERT( geomTriangles != nil );
+ float fAngle = CGeneral::GetRandomNumberInRange(450.0f, 750.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
- for ( int32 i = 0; i < 8; i++ )
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ float fLevelNoWaves;
+
+ if ( GetWaterLevelNoWaves(vecPos.x, vecPos.y, vecPos.z, &fLevelNoWaves) )
{
- for ( int32 j = 0; j < 8; j++ )
+ if ( IsLocationOutOfWorldBounds_WS(vecPos, 1) )
{
+ vecPos.z = fLevelNoWaves + 9.5f;
- /*
- [B] [C]
- ***********
- * * *
- * * *
- * * *
- * * *
- ***********
- [A] [D]
- */
+ CVector vecDir
+ (
+ CGeneral::GetRandomNumberInRange(-0.1f, 0.1f),
+ 0.0f,
+ 0.0f
+ );
-
- RpGeometryTriangleSetVertexIndices(apGeomArray[geom],
- &geomTriangles[2 * 8*i + 2*j + 0], /*A*/i*9+j+0, /*B*/i*9+j+1, /*C*/i*9+j+9+1);
-
- RpGeometryTriangleSetVertexIndices(apGeomArray[geom],
- &geomTriangles[2 * 8*i + 2*j + 1], /*A*/i*9+j+0, /*C*/i*9+j+9+1, /*D*/i*9+j+9 );
-
- RpGeometryTriangleSetMaterial(apGeomArray[geom], &geomTriangles[2 * 8*i + 2*j + 0], wavyMaterial);
-
- RpGeometryTriangleSetMaterial(apGeomArray[geom], &geomTriangles[2 * 8*i + 2*j + 1], wavyMaterial);
+ CParticle::AddParticle(PARTICLE_SHIP_SIDE, vecPos, vecDir,
+ nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 7, 0);
}
}
+ }
+ }
+}
- RpMorphTarget *geomMorphTarget = RpGeometryGetMorphTarget(apGeomArray[geom], 0);
- RwV3d *geomVertices = RpMorphTargetGetVertices(geomMorphTarget);
-
- ASSERT( geomMorphTarget != nil );
- ASSERT( geomVertices != nil );
+void
+CWaterLevel::HandleSeaLifeForms()
+{
+ if ( CReplay::IsPlayingBack() )
+ return;
+
+ CVector cur_pos = FindPlayerPed()->GetPosition();
- for ( int32 i = 0; i < 9; i++ )
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
+ {
+ prev_pos = cur_pos;
+ timecounter = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
+ {
+ if ( CWaterCreatures::IsSpaceForMoreWaterCreatures() )
+ {
+ for ( int32 i = 0; i < 3; i++ )
{
- for ( int32 j = 0; j < 9; j++ )
- {
- geomVertices[9*i+j].x = (float)i * 4.0f;
- geomVertices[9*i+j].y = (float)j * 4.0f;
- geomVertices[9*i+j].z = 0.0f;
- }
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(15.0f, 30.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ CWaterCreatures::CreateOne(vecPos, -1);
}
-
- RpMorphTargetSetBoundingSphere(geomMorphTarget, RpMorphTargetGetBoundingSphere(wavyMorphTarget));
- RpGeometryUnlock(apGeomArray[geom]);
}
}
-
- POP_MEMID();
+
+ CWaterCreatures::UpdateAll();
}
void
-CWaterLevel::FreeBoatWakeArray()
+CWaterLevel::HandleBeachToysStuff(void)
{
- for ( int32 i = 0; i < MAX_BOAT_WAKES; i++ )
+#ifdef FIX_BUGS
+ CVector cur_pos = FindPlayerCoors();
+#else
+ CVector cur_pos = FindPlayerPed()->GetPosition();
+#endif
+
+ static bool bBeachBallInit = true;
+ static CVector FirstBeachBallPos = cur_pos;
+ static bool bLoungeInit = true;
+ static CVector FirstLoungePos = cur_pos;
+ static CVector prev_pos(0.0f, 0.0f, 0.0f);
+ static int32 timecounter;
+
+ if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )
+ {
+ prev_pos = cur_pos;
+ timecounter = CTimer::GetTimeInMilliseconds();
+ }
+ else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
{
- if ( apGeomArray[i] != nil )
+ static int32 toygenTime = CTimer::GetTimeInMilliseconds();
+
+ if ( (CTimer::GetTimeInMilliseconds() - toygenTime) > 20000 )
{
- RpGeometryDestroy(apGeomArray[i]);
- apGeomArray[i] = nil;
+ toygenTime = CTimer::GetTimeInMilliseconds();
+
+ if ( bBeachBallInit || (cur_pos - FirstBeachBallPos).MagnitudeSqr() > 6400.0f )
+ {
+ for ( int32 i = 0; i < 3; i++ )
+ {
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ if ( TheCamera.IsSphereVisible(vecPos, 1.0f) )
+ {
+ float fWaterLevel;
+
+ if ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) )
+ {
+ float fGroundLevel;
+ ColData coldata;
+
+ if ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) )
+ {
+ if ( coldata.SurfaceType == SURFACE_SAND )
+ {
+ CEntity *toy = CreateBeachToy(vecPos, BEACHTOY_BALL);
+
+ if ( toy )
+ {
+ FirstBeachBallPos = cur_pos;
+ bBeachBallInit = false;
+ i = 10;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( bLoungeInit || (cur_pos - FirstLoungePos).MagnitudeSqr() > 6400.0f )
+ {
+ for ( int32 i = 0; i < 5; i++ )
+ {
+ CVector vecPos = cur_pos;
+
+ float fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f);
+
+ uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);
+
+ float fCos = CParticle::Cos(nSinCosIdx);
+ float fSin = CParticle::Sin(nSinCosIdx);
+
+ vecPos.x += (fCos - fSin) * fAngle;
+ vecPos.y += (fSin + fCos) * fAngle;
+
+ if ( TheCamera.IsSphereVisible(vecPos, 2.0f) )
+ {
+ float fWaterLevel;
+
+ if ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) )
+ {
+ float fGroundLevel;
+ ColData coldata;
+
+ if ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) )
+ {
+ if ( coldata.SurfaceType == SURFACE_SAND )
+ {
+ CEntity *toy = CreateBeachToy(vecPos, BEACHTOY_ANY_LOUNGE);
+ if ( toy )
+ {
+ toy->SetHeading(DEGTORAD(CGeneral::GetRandomNumberInRange(0.0f, 359.0f)));
+ FirstLoungePos = cur_pos;
+ bLoungeInit = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
-
- nGeomUsed = 0;
}
+
+CEntity *
+CWaterLevel::CreateBeachToy(CVector const &vec, eBeachToy beachtoy)
+{
+ if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
+ return nil;
+
+ int finalToy = beachtoy;
+ bool isStatic = false;
+ int model = MI_BEACHBALL;
+ switch (beachtoy) {
+ case BEACHTOY_ANY_LOUNGE:
+ switch ( CGeneral::GetRandomNumber() & 7 ) {
+ case 1:
+ case 7:
+ finalToy = BEACHTOY_LOUNGE_WOOD_UP;
+ break;
+ case 3:
+ case 5:
+ finalToy = BEACHTOY_LOUNGE_TOWEL_UP;
+ break;
+ default:
+ finalToy = BEACHTOY_LOUNGE_WOOD_ON;
+ break;
+ }
+ break;
+ case BEACHTOY_ANY_TOWEL:
+ switch ( CGeneral::GetRandomNumber() & 7 ) {
+ case 1:
+ case 7:
+ finalToy = BEACHTOY_TOWEL2;
+ break;
+ case 2:
+ case 6:
+ finalToy = BEACHTOY_TOWEL3;
+ break;
+ case 3:
+ case 5:
+ finalToy = BEACHTOY_TOWEL4;
+ break;
+ default:
+ finalToy = BEACHTOY_TOWEL1;
+ break;
+ }
+ if (CObject::nNoTempObjects >= 35) {
+ return nil;
+ }
+ default:
+ break;
+ }
+ switch (finalToy) {
+ case BEACHTOY_BALL:
+ isStatic = false;
+ model = MI_BEACHBALL;
+ break;
+ case BEACHTOY_LOUNGE_WOOD_UP:
+ isStatic = false;
+ model = MI_LOUNGE_WOOD_UP;
+ break;
+ case BEACHTOY_LOUNGE_TOWEL_UP:
+ isStatic = false;
+ model = MI_LOUNGE_TOWEL_UP;
+ break;
+ case BEACHTOY_LOUNGE_WOOD_ON:
+ isStatic = false;
+ model = MI_LOUNGE_WOOD_DN;
+ break;
+ case BEACHTOY_LOTION:
+ model = MI_LOTION;
+ isStatic = true;
+ break;
+ case BEACHTOY_TOWEL1:
+ model = MI_BEACHTOWEL01;
+ isStatic = true;
+ break;
+ case BEACHTOY_TOWEL2:
+ model = MI_BEACHTOWEL02;
+ isStatic = true;
+ break;
+ case BEACHTOY_TOWEL3:
+ model = MI_BEACHTOWEL03;
+ isStatic = true;
+ break;
+ case BEACHTOY_TOWEL4:
+ model = MI_BEACHTOWEL04;
+ isStatic = true;
+ break;
+ default:
+ break;
+ }
+ CObject *toy = new CObject(model, true);
+ if (toy) {
+ toy->SetPosition(vec);
+ toy->GetMatrix().UpdateRW();
+ toy->m_vecMoveSpeed = CVector(0.f, 0.f, 0.f);
+ toy->m_vecTurnSpeed = CVector(0.f, 0.f, 0.f);
+ toy->ObjectCreatedBy = TEMP_OBJECT;
+ toy->bIsStatic = isStatic;
+ CObject::nNoTempObjects++;
+ toy->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 43200000;
+ CWorld::Add(toy);
+ return toy;
+ } else
+ return nil;
+} \ No newline at end of file