summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio/oal/stream.cpp7
-rw-r--r--src/control/RoadBlocks.cpp4
-rw-r--r--src/control/Script.cpp4
-rw-r--r--src/core/Accident.cpp4
-rw-r--r--src/core/Accident.h1
-rw-r--r--src/core/Cam.cpp4
-rw-r--r--src/core/Collision.cpp1118
-rw-r--r--src/core/Collision.h70
-rw-r--r--src/core/EventList.cpp8
-rw-r--r--src/core/Game.cpp2
-rw-r--r--src/core/Stats.cpp1
-rw-r--r--src/core/Stats.h1
-rw-r--r--src/core/World.cpp5
-rw-r--r--src/core/Zones.cpp5
-rw-r--r--src/core/common.h10
-rw-r--r--src/core/config.h20
-rw-r--r--src/core/main.cpp2
-rw-r--r--src/core/re3.cpp26
-rw-r--r--src/core/vu0Collision.dsm21
-rw-r--r--src/core/vu0Collision_1.s610
-rw-r--r--src/core/vu0Collision_2.s191
-rw-r--r--src/entities/Entity.cpp4
-rw-r--r--src/math/Matrix.h19
-rw-r--r--src/math/VuVector.h41
-rw-r--r--src/math/math.cpp128
-rw-r--r--src/objects/CutsceneObject.cpp109
-rw-r--r--src/objects/CutsceneObject.h8
-rw-r--r--src/objects/ParticleObject.cpp2
-rw-r--r--src/peds/Ped.cpp25
-rw-r--r--src/peds/Ped.h3
-rw-r--r--src/peds/Population.cpp4
-rw-r--r--src/render/Antennas.cpp2
-rw-r--r--src/render/Coronas.cpp188
-rw-r--r--src/render/Coronas.h26
-rw-r--r--src/render/CutsceneShadow.cpp269
-rw-r--r--src/render/CutsceneShadow.h52
-rw-r--r--src/render/Fluff.cpp5
-rw-r--r--src/render/MBlur.cpp36
-rw-r--r--src/render/PointLights.cpp68
-rw-r--r--src/render/PointLights.h5
-rw-r--r--src/render/Renderer.cpp6
-rw-r--r--src/render/Rubbish.cpp67
-rw-r--r--src/render/Rubbish.h4
-rw-r--r--src/render/ShadowCamera.cpp549
-rw-r--r--src/render/ShadowCamera.h54
-rw-r--r--src/render/Shadows.cpp1307
-rw-r--r--src/render/Shadows.h121
-rw-r--r--src/render/Skidmarks.cpp13
-rw-r--r--src/render/Timecycle.cpp325
-rw-r--r--src/render/Timecycle.h238
-rw-r--r--src/render/Weather.h4
-rw-r--r--src/rw/RwHelper.cpp119
-rw-r--r--src/rw/RwHelper.h3
-rw-r--r--src/vehicles/Automobile.cpp8
-rw-r--r--src/vehicles/Bike.cpp2
-rw-r--r--src/vehicles/Heli.cpp3
-rw-r--r--src/weapons/BulletInfo.cpp39
-rw-r--r--src/weapons/ProjectileInfo.cpp46
-rw-r--r--src/weapons/ShotInfo.cpp20
59 files changed, 5311 insertions, 725 deletions
diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp
index f2a9eb22..23a0a0c9 100644
--- a/src/audio/oal/stream.cpp
+++ b/src/audio/oal/stream.cpp
@@ -8,13 +8,8 @@
#include <opusfile.h>
#else
#ifdef _WIN32
-
-// TODO: This is due to version difference of 32-bit libmpg123 and 64-bit libmpg123, fix it
-#ifndef _WIN64
-typedef long ssize_t;
-#endif
#pragma comment( lib, "libsndfile-1.lib" )
-#pragma comment( lib, "libmpg123.lib" )
+#pragma comment( lib, "libmpg123-0.lib" )
#else
#include "crossplatform.h"
#endif
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index 010dec3f..e8630bde 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -111,6 +111,10 @@ CRoadBlocks::GenerateRoadBlocks(void)
{
CMatrix tmp1, tmp2;
static int16 unk;
+#ifdef SQUEEZE_PERFORMANCE
+ if (FindPlayerPed()->m_pWanted->m_RoadblockDensity == 0)
+ return;
+#endif
uint32 frame = CTimer::GetFrameCounter() & 0xF;
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index eb950464..9508677b 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -12709,13 +12709,13 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
case COMMAND_SET_EXTRA_COLOURS:
{
CollectParameters(&m_nIp, 2);
- debug("SET_EXTRA_COLOURS not implemented, skipping\n");
+ CTimeCycle::StartExtraColour(ScriptParams[0]-1, ScriptParams[1] != 0);
return 0;
}
case COMMAND_CLEAR_EXTRA_COLOURS:
{
CollectParameters(&m_nIp, 1);
- debug("CLEAR_EXTRA_COLOURS not implemented, skipping\n");
+ CTimeCycle::StopExtraColour(ScriptParams[0]);
return 0;
}
//case COMMAND_CLOSE_CAR_BOOT:
diff --git a/src/core/Accident.cpp b/src/core/Accident.cpp
index 1fd6c123..c8611323 100644
--- a/src/core/Accident.cpp
+++ b/src/core/Accident.cpp
@@ -53,6 +53,10 @@ CAccidentManager::ReportAccident(CPed *ped)
void
CAccidentManager::Update()
{
+#ifdef SQUEEZE_PERFORMANCE
+ // Handled after injury registered.
+ return;
+#endif
int32 e;
if (CEventList::GetEvent(EVENT_INJURED_PED, &e)) {
CPed *ped = CPools::GetPed(gaEvent[e].entityRef);
diff --git a/src/core/Accident.h b/src/core/Accident.h
index 949d5fb9..568e1149 100644
--- a/src/core/Accident.h
+++ b/src/core/Accident.h
@@ -1,5 +1,4 @@
#pragma once
-#include "common.h"
#include "config.h"
class CPed;
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index 3b11e16f..375e9d5b 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -3958,7 +3958,7 @@ CCam::Process_Debug(const CVector&, float, float, float)
if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
12.0f, 0.0f, 0.0f, -12.0f,
- 128, 128, 128, 128, 1000.0f, false, 1.0f);
+ 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false);
if(CHud::m_Wants_To_Draw_Hud){
char str[256];
@@ -4103,7 +4103,7 @@ CCam::Process_Editor(const CVector&, float, float, float)
if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
12.0f, 0.0f, 0.0f, -12.0f,
- 128, 128, 128, 128, 1000.0f, false, 1.0f);
+ 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false);
if(CHud::m_Wants_To_Draw_Hud){
char str[256];
diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp
index 268e3c5e..c2037dc5 100644
--- a/src/core/Collision.cpp
+++ b/src/core/Collision.cpp
@@ -1,5 +1,6 @@
#include "common.h"
+#include "VuVector.h"
#include "main.h"
#include "Lists.h"
#include "Game.h"
@@ -25,6 +26,346 @@
//--MIAMI: file done
+
+// TODO: where do these go?
+
+#ifdef VU_COLLISION
+
+struct VuTriangle
+{
+ // Compressed int16 but unpacked
+#ifdef GTA_PS2
+ uint128 v0;
+ uint128 v1;
+ uint128 v2;
+ uint128 plane;
+#else
+ int32 v0[4];
+ int32 v1[4];
+ int32 v2[4];
+ int32 plane[4];
+#endif
+};
+
+#ifndef GTA_PS2
+static int16 vi01;
+static CVuVector vf01;
+static CVuVector vf02;
+static CVuVector vf03;
+
+CVuVector
+DistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)
+{
+ // center VF12
+ // p0 VF14
+ // line VF15
+ CVuVector ret; // VF16
+ CVuVector p1 = p0+line;
+ CVuVector dist0 = center - p0; // VF20
+ CVuVector dist1 = center - p1; // VF25
+ float lenSq = line.MagnitudeSqr(); // VF21
+ float distSq0 = dist0.MagnitudeSqr(); // VF22
+ float distSq1 = dist1.MagnitudeSqr();
+ float dot = DotProduct(dist0, line); // VF23
+ if(dot < 0.0f){
+ // not above line, closest to p0
+ ret = p0;
+ ret.w = distSq0;
+ return ret;
+ }
+ float t = dot/lenSq; // param of nearest point on infinite line
+ if(t > 1.0f){
+ // not above line, closest to p1
+ ret = p1;
+ ret.w = distSq1;
+ return ret;
+ }
+ // closest to line
+ ret = p0 + line*t;
+ ret.w = (ret - center).MagnitudeSqr();
+ return ret;
+}
+inline int SignFlags(const CVector &v)
+{
+ int f = 0;
+ if(v.x < 0.0f) f |= 1;
+ if(v.y < 0.0f) f |= 2;
+ if(v.z < 0.0f) f |= 4;
+ return f;
+}
+#endif
+
+extern "C" void
+LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
+ const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
+ const CVuVector &plane)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf13, 0x0(%1)\n"
+ "lqc2 vf14, 0x0(%2)\n"
+ "lqc2 vf15, 0x0(%3)\n"
+ "lqc2 vf16, 0x0(%4)\n"
+ "lqc2 vf17, 0x0(%5)\n"
+ "vcallms Vu0LineToTriangleCollisionStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
+ );
+#else
+ float dot0 = DotProduct(plane, p0);
+ float dot1 = DotProduct(plane, p1);
+ float dist0 = plane.w - dot0;
+ float dist1 = plane.w - dot1;
+
+ // if points are on the same side, no collision
+ if(dist0 * dist1 > 0.0f){
+ vi01 = 0;
+ return;
+ }
+
+ CVuVector diff = p1 - p0;
+ float t = dist0/(dot1 - dot0);
+ CVuVector p = p0 + diff*t;
+ p.w = 0.0f;
+ vf01 = p;
+ vf03.x = t;
+
+ // Check if point is inside
+ CVector cross1 = CrossProduct(p-v0, v1-v0);
+ CVector cross2 = CrossProduct(p-v1, v2-v1);
+ CVector cross3 = CrossProduct(p-v2, v0-v2);
+ // Only check relevant directions
+ int flagmask = 0;
+ if(Abs(plane.x) > 0.5f) flagmask |= 1;
+ if(Abs(plane.y) > 0.5f) flagmask |= 2;
+ if(Abs(plane.z) > 0.5f) flagmask |= 4;
+ int flags1 = SignFlags(cross1) & flagmask;
+ int flags2 = SignFlags(cross2) & flagmask;
+ int flags3 = SignFlags(cross3) & flagmask;
+ // inside if on the same side of all edges
+ if(flags1 != flags2 || flags1 != flags3){
+ vi01 = 0;
+ return;
+ }
+ vi01 = 1;
+ vf02 = plane;
+ return;
+#endif
+}
+
+extern "C" void
+LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf13, 0x0(%1)\n"
+ "lqc2 vf14, 0x0(%2)\n"
+ "lqc2 vf15, 0x10(%2)\n"
+ "lqc2 vf16, 0x20(%2)\n"
+ "lqc2 vf17, 0x30(%2)\n"
+ "vcallms Vu0LineToTriangleCollisionCompressedStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&p0), "r" (&p1), "r" (&tri)
+ );
+#else
+ CVuVector v0, v1, v2, plane;
+ v0.x = tri.v0[0]/128.0f;
+ v0.y = tri.v0[1]/128.0f;
+ v0.z = tri.v0[2]/128.0f;
+ v0.w = tri.v0[3]/128.0f;
+ v1.x = tri.v1[0]/128.0f;
+ v1.y = tri.v1[1]/128.0f;
+ v1.z = tri.v1[2]/128.0f;
+ v1.w = tri.v1[3]/128.0f;
+ v2.x = tri.v2[0]/128.0f;
+ v2.y = tri.v2[1]/128.0f;
+ v2.z = tri.v2[2]/128.0f;
+ v2.w = tri.v2[3]/128.0f;
+ plane.x = tri.plane[0]/4096.0f;
+ plane.y = tri.plane[1]/4096.0f;
+ plane.z = tri.plane[2]/4096.0f;
+ plane.w = tri.plane[3]/128.0f;
+ LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
+#endif
+}
+
+extern "C" void
+SphereToTriangleCollision(const CVuVector &sph,
+ const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
+ const CVuVector &plane)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf14, 0x0(%1)\n"
+ "lqc2 vf15, 0x0(%2)\n"
+ "lqc2 vf16, 0x0(%3)\n"
+ "lqc2 vf17, 0x0(%4)\n"
+ "vcallms Vu0SphereToTriangleCollisionStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
+ );
+#else
+ float planedist = DotProduct(plane, sph) - plane.w; // VF02
+ if(Abs(planedist) > sph.w){
+ vi01 = 0;
+ return;
+ }
+ // point on plane
+ CVuVector p = sph - planedist*plane;
+ p.w = 0.0f;
+ vf01 = p;
+ planedist = Abs(planedist);
+ // edges
+ CVuVector v01 = v1 - v0;
+ CVuVector v12 = v2 - v1;
+ CVuVector v20 = v0 - v2;
+ // VU code calculates normal again for some weird reason...
+ // Check sides of point
+ CVector cross1 = CrossProduct(p-v0, v01);
+ CVector cross2 = CrossProduct(p-v1, v12);
+ CVector cross3 = CrossProduct(p-v2, v20);
+ // Only check relevant directions
+ int flagmask = 0;
+ if(Abs(plane.x) > 0.1f) flagmask |= 1;
+ if(Abs(plane.y) > 0.1f) flagmask |= 2;
+ if(Abs(plane.z) > 0.1f) flagmask |= 4;
+ int nflags = SignFlags(plane) & flagmask;
+ int flags1 = SignFlags(cross1) & flagmask;
+ int flags2 = SignFlags(cross2) & flagmask;
+ int flags3 = SignFlags(cross3) & flagmask;
+ int testcase = 0;
+ CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
+ if(flags1 == nflags){
+ closest += v2;
+ testcase++;
+ }
+ if(flags2 == nflags){
+ closest += v0;
+ testcase++;
+ }
+ if(flags3 == nflags){
+ closest += v1;
+ testcase++;
+ }
+ if(testcase == 3){
+ // inside triangle - dist to plane already checked
+ vf02 = plane;
+ vf02.w = vf03.x = planedist;
+ vi01 = 1;
+ }else if(testcase == 1){
+ // outside two sides - closest to point opposide inside edge
+ vf01 = closest;
+ vf02 = sph - closest;
+ float distSq = vf02.MagnitudeSqr();
+ vi01 = sph.w*sph.w > distSq;
+ vf03.x = Sqrt(distSq);
+ vf02 *= 1.0f/vf03.x;
+ }else{
+ // inside two sides - closest to third edge
+ if(flags1 != nflags)
+ closest = DistanceBetweenSphereAndLine(sph, v0, v01);
+ else if(flags2 != nflags)
+ closest = DistanceBetweenSphereAndLine(sph, v1, v12);
+ else
+ closest = DistanceBetweenSphereAndLine(sph, v2, v20);
+ vi01 = sph.w*sph.w > closest.w;
+ vf01 = closest;
+ vf02 = sph - closest;
+ vf03.x = Sqrt(closest.w);
+ vf02 *= 1.0f/vf03.x;
+ }
+#endif
+}
+
+extern "C" void
+SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf14, 0x0(%1)\n"
+ "lqc2 vf15, 0x10(%1)\n"
+ "lqc2 vf16, 0x20(%1)\n"
+ "lqc2 vf17, 0x30(%1)\n"
+ "vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&sph), "r" (&tri)
+ );
+#else
+ CVuVector v0, v1, v2, plane;
+ v0.x = tri.v0[0]/128.0f;
+ v0.y = tri.v0[1]/128.0f;
+ v0.z = tri.v0[2]/128.0f;
+ v0.w = tri.v0[3]/128.0f;
+ v1.x = tri.v1[0]/128.0f;
+ v1.y = tri.v1[1]/128.0f;
+ v1.z = tri.v1[2]/128.0f;
+ v1.w = tri.v1[3]/128.0f;
+ v2.x = tri.v2[0]/128.0f;
+ v2.y = tri.v2[1]/128.0f;
+ v2.z = tri.v2[2]/128.0f;
+ v2.w = tri.v2[3]/128.0f;
+ plane.x = tri.plane[0]/4096.0f;
+ plane.y = tri.plane[1]/4096.0f;
+ plane.z = tri.plane[2]/4096.0f;
+ plane.w = tri.plane[3]/128.0f;
+ SphereToTriangleCollision(sph, v0, v1, v2, plane);
+#endif
+}
+
+inline int
+GetVUresult(void)
+{
+#ifdef GTA_PS2
+ int ret;
+ __asm__ volatile (
+ "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish
+ : "=r" (ret)
+ );
+ return ret;
+#else
+ return vi01;
+#endif
+}
+
+inline int
+GetVUresult(CVuVector &point, CVuVector &normal, float &dist)
+{
+#ifdef GTA_PS2
+ int ret;
+ __asm__ volatile (
+ "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish
+ "sqc2 vf01,(%1)\n"
+ "sqc2 vf02,(%2)\n"
+ "qmfc2 $12,vf03\n"
+ "sw $12,(%3)\n"
+ : "=r" (ret)
+ : "r" (&point), "r" (&normal), "r" (&dist)
+ : "$12"
+ );
+ return ret;
+#else
+ point = vf01;
+ normal = vf02;
+ dist = vf03.x;
+ return vi01;
+#endif
+}
+
+#endif
+
+
enum Direction
{
DIR_X_POS,
@@ -252,6 +593,20 @@ CCollision::TestVerticalLineBox(const CColLine &line, const CBox &box)
bool
CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
{
+#ifdef VU_COLLISION
+ // not used in favour of optimized loops
+ VuTriangle vutri;
+ verts[tri.a].Unpack(vutri.v0);
+ verts[tri.b].Unpack(vutri.v1);
+ verts[tri.c].Unpack(vutri.v2);
+ plane.Unpack(vutri.plane);
+
+ LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri);
+
+ if(GetVUresult())
+ return true;
+ return false;
+#else
float t;
CVector normal;
plane.GetNormal(normal);
@@ -325,6 +680,7 @@ CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts
if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;
if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;
return true;
+#endif
}
// Test if line segment intersects with sphere.
@@ -362,6 +718,20 @@ bool
CCollision::TestSphereTriangle(const CColSphere &sphere,
const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
{
+#ifdef VU_COLLISION
+ // not used in favour of optimized loops
+ VuTriangle vutri;
+ verts[tri.a].Unpack(vutri.v0);
+ verts[tri.b].Unpack(vutri.v1);
+ verts[tri.c].Unpack(vutri.v2);
+ plane.Unpack(vutri.plane);
+
+ SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri);
+
+ if(GetVUresult())
+ return true;
+ return false;
+#else
// If sphere and plane don't intersect, no collision
float planedist = plane.CalcPoint(sphere.center);
if(Abs(planedist) > sphere.radius)
@@ -375,7 +745,9 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
CVector vec2 = vb - va;
float len = vec2.Magnitude();
vec2 = vec2 * (1.0f/len);
- CVector vec1 = CrossProduct(vec2, plane.normal);
+ CVector normal;
+ plane.GetNormal(normal);
+ CVector vec1 = CrossProduct(vec2, normal);
// We know A has local coordinate [0,0] and B has [0,len].
// Now calculate coordinates on triangle for these two vectors:
@@ -420,11 +792,78 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
}
return dist < sphere.radius;
+#endif
}
bool
CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough)
{
+#ifdef VU_COLLISION
+ CMatrix matTransform;
+ int i;
+
+ // transform line to model space
+ Invert(matrix, matTransform);
+ CVuVector newline[2];
+ TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2);
+
+ // If we don't intersect with the bounding box, no chance on the rest
+ if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
+ return false;
+
+ for(i = 0; i < model.numSpheres; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(TestLineSphere(*(CColLine*)newline, model.spheres[i]))
+ return true;
+ }
+
+ for(i = 0; i < model.numBoxes; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(TestLineBox(*(CColLine*)newline, model.boxes[i]))
+ return true;
+ }
+
+ CalculateTrianglePlanes(&model);
+ int lastTest = -1;
+ VuTriangle vutri;
+ for(i = 0; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+
+ CColTriangle *tri = &model.triangles[i];
+ model.vertices[tri->a].Unpack(vutri.v0);
+ model.vertices[tri->b].Unpack(vutri.v1);
+ model.vertices[tri->c].Unpack(vutri.v2);
+ model.trianglePlanes[i].Unpack(vutri.plane);
+
+ LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
+ lastTest = i;
+ break;
+ }
+#ifdef FIX_BUGS
+ // no need to check first again
+ i++;
+#endif
+ for(; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+
+ CColTriangle *tri = &model.triangles[i];
+ model.vertices[tri->a].Unpack(vutri.v0);
+ model.vertices[tri->b].Unpack(vutri.v1);
+ model.vertices[tri->c].Unpack(vutri.v2);
+ model.trianglePlanes[i].Unpack(vutri.plane);
+
+ if(GetVUresult())
+ return true;
+
+ LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
+ lastTest = i;
+
+ }
+ if(lastTest != -1 && GetVUresult())
+ return true;
+
+ return false;
+#else
static CMatrix matTransform;
int i;
@@ -459,6 +898,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
}
return false;
+#endif
}
// TODO: TestPillWithSpheresInColModel, but only called from overloaded CWeapon::FireMelee which isn't used
@@ -475,20 +915,24 @@ CCollision::ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CCol
{
CVector dist = s1.center - s2.center;
float d = dist.Magnitude() - s2.radius; // distance from s1's center to s2
- float dc = d < 0.0f ? 0.0f : d; // clamp to zero, i.e. if s1's center is inside s2
+ float depth = s1.radius - d; // sphere overlap
+ if(d < 0.0f) d = 0.0f; // clamp to zero, i.e. if s1's center is inside s2
// no collision if sphere is not close enough
- if(mindistsq <= dc*dc || s1.radius <= dc)
- return false;
- dist.Normalise();
- point.point = s1.center - dist*dc;
- point.normal = dist;
- point.surfaceA = s1.surface;
- point.pieceA = s1.piece;
- point.surfaceB = s2.surface;
- point.pieceB = s2.piece;
- point.depth = s1.radius - d; // sphere overlap
- mindistsq = dc*dc; // collision radius
- return true;
+ if(d*d < mindistsq && d < s1.radius){
+ dist.Normalise();
+ point.point = s1.center - dist*d;
+ point.normal = dist;
+#ifndef VU_COLLISION
+ point.surfaceA = s1.surface;
+ point.pieceA = s1.piece;
+ point.surfaceB = s2.surface;
+ point.pieceB = s2.piece;
+#endif
+ point.depth = depth;
+ mindistsq = d*d; // collision radius
+ return true;
+ }
+ return false;
}
bool
@@ -528,10 +972,12 @@ CCollision::ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoin
if(lensq < mindistsq){
point.normal = dist * (1.0f/Sqrt(lensq));
point.point = sph.center - point.normal;
+#ifndef VU_COLLISION
point.surfaceA = sph.surface;
point.pieceA = sph.piece;
point.surfaceB = box.surface;
point.pieceB = box.piece;
+#endif
// find absolute distance to the closer side in each dimension
float dx = dist.x > 0.0f ?
@@ -571,10 +1017,12 @@ CCollision::ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoin
float len = Sqrt(lensq);
point.point = p;
point.normal = dist * (1.0f/len);
+#ifndef VU_COLLISION
point.surfaceA = sph.surface;
point.pieceA = sph.piece;
point.surfaceB = box.surface;
point.pieceB = box.piece;
+#endif
point.depth = sph.radius - len;
mindistsq = lensq;
return true;
@@ -689,10 +1137,12 @@ CCollision::ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &
point.point = p;
point.normal = normal;
+#ifndef VU_COLLISION
point.surfaceA = 0;
point.pieceA = 0;
point.surfaceB = box.surface;
point.pieceB = box.piece;
+#endif
mindist = mint;
return true;
@@ -722,10 +1172,12 @@ CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CC
point.point = line.p0 + v01*t;
point.normal = point.point - sphere.center;
point.normal.Normalise();
+#ifndef VU_COLLISION
point.surfaceA = 0;
point.pieceA = 0;
point.surfaceB = sphere.surface;
point.pieceB = sphere.piece;
+#endif
mindist = t;
return true;
}
@@ -736,6 +1188,17 @@ CCollision::ProcessVerticalLineTriangle(const CColLine &line,
const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
CColPoint &point, float &mindist, CStoredCollPoly *poly)
{
+#ifdef VU_COLLISION
+ // not used in favour of optimized loops
+ bool res = ProcessLineTriangle(line, verts, tri, plane, point, mindist);
+ if(res && poly){
+ poly->verts[0] = verts[tri.a].Get();
+ poly->verts[1] = verts[tri.b].Get();
+ poly->verts[2] = verts[tri.c].Get();
+ poly->valid = true;
+ }
+ return res;
+#else
float t;
CVector normal;
@@ -822,11 +1285,40 @@ CCollision::ProcessVerticalLineTriangle(const CColLine &line,
}
mindist = t;
return true;
+#endif
}
bool
CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly)
{
+#ifdef VU_COLLISION
+ if(!poly->valid)
+ return false;
+
+ CVuVector p0 = pos;
+ CVuVector p1 = pos;
+ p1.z = z;
+
+ CVector v01 = poly->verts[1] - poly->verts[0];
+ CVector v02 = poly->verts[2] - poly->verts[0];
+ CVuVector plane = CrossProduct(v02, v01);
+ plane.Normalise();
+ plane.w = DotProduct(plane, poly->verts[0]);
+
+ LineToTriangleCollision(p0, p1, poly->verts[0], poly->verts[1], poly->verts[2], plane);
+
+ CVuVector pnt;
+ float dist;
+ if(!GetVUresult(pnt, plane, dist))
+#ifdef FIX_BUGS
+ // perhaps not needed but be safe
+ return poly->valid = false;
+#else
+ return false;
+#endif
+ point.point = pnt;
+ return true;
+#else
float t;
if(!poly->valid)
@@ -849,7 +1341,9 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol
return poly->valid = false;
// intersection parameter on line
- t = -plane.CalcPoint(p0) / DotProduct(p1 - p0, plane.normal);
+ CVector normal;
+ plane.GetNormal(normal);
+ t = -plane.CalcPoint(p0) / DotProduct(p1 - p0, normal);
// find point of intersection
CVector p = p0 + (p1-p0)*t;
@@ -899,13 +1393,36 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol
if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return poly->valid = false;
point.point = p;
return poly->valid = true;
+#endif
}
bool
-CCollision::ProcessLineTriangle(const CColLine &line ,
+CCollision::ProcessLineTriangle(const CColLine &line,
const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
CColPoint &point, float &mindist, CStoredCollPoly *poly)
{
+#ifdef VU_COLLISION
+ // not used in favour of optimized loops
+ VuTriangle vutri;
+ verts[tri.a].Unpack(vutri.v0);
+ verts[tri.b].Unpack(vutri.v1);
+ verts[tri.c].Unpack(vutri.v2);
+ plane.Unpack(vutri.plane);
+
+ LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri);
+
+ CVuVector pnt, normal;
+ float dist;
+ if(GetVUresult(pnt, normal, dist)){
+ if(dist < mindist){
+ point.point = pnt;
+ point.normal = normal;
+ mindist = dist;
+ return true;
+ }
+ }
+ return false;
+#else
float t;
CVector normal;
plane.GetNormal(normal);
@@ -985,6 +1502,7 @@ CCollision::ProcessLineTriangle(const CColLine &line ,
}
mindist = t;
return true;
+#endif
}
bool
@@ -992,6 +1510,30 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
CColPoint &point, float &mindistsq)
{
+#ifdef VU_COLLISION
+ // not used in favour of optimized loops
+ VuTriangle vutri;
+ verts[tri.a].Unpack(vutri.v0);
+ verts[tri.b].Unpack(vutri.v1);
+ verts[tri.c].Unpack(vutri.v2);
+ plane.Unpack(vutri.plane);
+
+ SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri);
+
+ CVuVector pnt, normal;
+ float dist;
+ if(GetVUresult(pnt, normal, dist) && dist*dist < mindistsq){
+ float depth = sphere.radius - dist;
+ if(depth > point.depth){
+ point.point = pnt;
+ point.normal = normal;
+ point.depth = depth;
+ mindistsq = dist*dist;
+ return true;
+ }
+ }
+ return false;
+#else
// If sphere and plane don't intersect, no collision
float planedist = plane.CalcPoint(sphere.center);
float distsq = planedist*planedist;
@@ -1061,13 +1603,16 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
point.point = p;
point.normal = sphere.center - p;
point.normal.Normalise();
+#ifndef VU_COLLISION
point.surfaceA = sphere.surface;
point.pieceA = sphere.piece;
point.surfaceB = tri.surface;
point.pieceB = 0;
+#endif
point.depth = sphere.radius - dist;
mindistsq = dist*dist;
return true;
+#endif
}
bool
@@ -1075,6 +1620,94 @@ CCollision::ProcessLineOfSight(const CColLine &line,
const CMatrix &matrix, CColModel &model,
CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough)
{
+#ifdef VU_COLLISION
+ CMatrix matTransform;
+ int i;
+
+ // transform line to model space
+ Invert(matrix, matTransform);
+ CVuVector newline[2];
+ TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2);
+
+ if(mindist < 1.0f)
+ newline[1] = newline[0] + (newline[1] - newline[0])*mindist;
+
+ // If we don't intersect with the bounding box, no chance on the rest
+ if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
+ return false;
+
+ float coldist = 1.0f;
+ for(i = 0; i < model.numSpheres; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist))
+ point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece);
+ }
+
+ for(i = 0; i < model.numBoxes; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist))
+ point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece);
+ }
+
+ CalculateTrianglePlanes(&model);
+ VuTriangle vutri;
+ CColTriangle *lasttri = nil;
+ for(i = 0; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+
+ CColTriangle *tri = &model.triangles[i];
+ model.vertices[tri->a].Unpack(vutri.v0);
+ model.vertices[tri->b].Unpack(vutri.v1);
+ model.vertices[tri->c].Unpack(vutri.v2);
+ model.trianglePlanes[i].Unpack(vutri.plane);
+
+ LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
+ lasttri = tri;
+ break;
+ }
+#ifdef FIX_BUGS
+ // no need to check first again
+ i++;
+#endif
+ CVuVector pnt, normal;
+ float dist;
+ for(; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+
+ CColTriangle *tri = &model.triangles[i];
+ model.vertices[tri->a].Unpack(vutri.v0);
+ model.vertices[tri->b].Unpack(vutri.v1);
+ model.vertices[tri->c].Unpack(vutri.v2);
+ model.trianglePlanes[i].Unpack(vutri.plane);
+
+ if(GetVUresult(pnt, normal, dist))
+ if(dist < coldist){
+ point.point = pnt;
+ point.normal = normal;
+ point.Set(0, 0, lasttri->surface, 0);
+ coldist = dist;
+ }
+
+ LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
+ lasttri = tri;
+ }
+ if(lasttri && GetVUresult(pnt, normal, dist))
+ if(dist < coldist){
+ point.point = pnt;
+ point.normal = normal;
+ point.Set(0, 0, lasttri->surface, 0);
+ coldist = dist;
+ }
+
+
+ if(coldist < 1.0f){
+ point.point = matrix * point.point;
+ point.normal = Multiply3x3(matrix, point.normal);
+ mindist *= coldist;
+ return true;
+ }
+ return false;
+#else
static CMatrix matTransform;
int i;
@@ -1113,6 +1746,7 @@ CCollision::ProcessLineOfSight(const CColLine &line,
return true;
}
return false;
+#endif
}
bool
@@ -1120,6 +1754,125 @@ CCollision::ProcessVerticalLine(const CColLine &line,
const CMatrix &matrix, CColModel &model,
CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly)
{
+#ifdef VU_COLLISION
+ static CStoredCollPoly TempStoredPoly;
+ CMatrix matTransform;
+ int i;
+
+ // transform line to model space
+ Invert(matrix, matTransform);
+ CVuVector newline[2];
+ TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2);
+
+ if(mindist < 1.0f)
+ newline[1] = newline[0] + (newline[1] - newline[0])*mindist;
+
+ if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
+ return false;
+
+ float coldist = 1.0f;
+ for(i = 0; i < model.numSpheres; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist))
+ point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece);
+ }
+
+ for(i = 0; i < model.numBoxes; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist))
+ point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece);
+ }
+
+ CalculateTrianglePlanes(&model);
+ TempStoredPoly.valid = false;
+ if(model.numTriangles){
+ bool registeredCol;
+ CColTriangle *lasttri = nil;
+ VuTriangle vutri;
+ for(i = 0; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+
+ CColTriangle *tri = &model.triangles[i];
+ model.vertices[tri->a].Unpack(vutri.v0);
+ model.vertices[tri->b].Unpack(vutri.v1);
+ model.vertices[tri->c].Unpack(vutri.v2);
+ model.trianglePlanes[i].Unpack(vutri.plane);
+
+ LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
+ lasttri = tri;
+ break;
+ }
+#ifdef FIX_BUGS
+ // no need to check first again
+ i++;
+#endif
+ CVuVector pnt, normal;
+ float dist;
+ for(; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+
+ CColTriangle *tri = &model.triangles[i];
+ model.vertices[tri->a].Unpack(vutri.v0);
+ model.vertices[tri->b].Unpack(vutri.v1);
+ model.vertices[tri->c].Unpack(vutri.v2);
+ model.trianglePlanes[i].Unpack(vutri.plane);
+
+ if(GetVUresult(pnt, normal, dist)){
+ if(dist < coldist){
+ point.point = pnt;
+ point.normal = normal;
+ point.Set(0, 0, lasttri->surface, 0);
+ coldist = dist;
+ registeredCol = true;
+ }else
+ registeredCol = false;
+ }else
+ registeredCol = false;
+
+ if(registeredCol){
+ TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get();
+ TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get();
+ TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get();
+ TempStoredPoly.valid = true;
+ }
+
+ LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
+ lasttri = tri;
+ }
+ if(lasttri && GetVUresult(pnt, normal, dist)){
+ if(dist < coldist){
+ point.point = pnt;
+ point.normal = normal;
+ point.Set(0, 0, lasttri->surface, 0);
+ coldist = dist;
+ registeredCol = true;
+ }else
+ registeredCol = false;
+ }else
+ registeredCol = false;
+
+ if(registeredCol){
+ TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get();
+ TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get();
+ TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get();
+ TempStoredPoly.valid = true;
+ }
+ }
+
+ if(coldist < 1.0f){
+ point.point = matrix * point.point;
+ point.normal = Multiply3x3(matrix, point.normal);
+ if(TempStoredPoly.valid && poly){
+ *poly = TempStoredPoly;
+ poly->verts[0] = matrix * CVector(poly->verts[0]);
+ poly->verts[1] = matrix * CVector(poly->verts[1]);
+ poly->verts[2] = matrix * CVector(poly->verts[2]);
+ }
+ mindist *= coldist;
+ return true;
+ }
+ return false;
+#else
static CStoredCollPoly TempStoredPoly;
int i;
@@ -1162,6 +1915,7 @@ CCollision::ProcessVerticalLine(const CColLine &line,
return true;
}
return false;
+#endif
}
enum {
@@ -1171,6 +1925,15 @@ enum {
MAXNUMTRIS = 600
};
+#ifdef VU_COLLISION
+#ifdef GTA_PS2
+#define SPR(off) ((uint8*)(0x70000000 + (off)))
+#else
+static uint8 fakeSPR[16*1024];
+#define SPR(off) ((uint8*)(fakeSPR + (off)))
+#endif
+#endif
+
// This checks model A's spheres and lines against model B's spheres, boxes and triangles.
// Returns the number of A's spheres that collide.
// Returned ColPoints are in world space.
@@ -1180,6 +1943,308 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
const CMatrix &matrixB, CColModel &modelB,
CColPoint *spherepoints, CColPoint *linepoints, float *linedists)
{
+#ifdef VU_COLLISION
+ CVuVector *aSpheresA = (CVuVector*)SPR(0x0000);
+ CVuVector *aSpheresB = (CVuVector*)SPR(0x0800);
+ CVuVector *aLinesA = (CVuVector*)SPR(0x1000);
+ int32 *aSphereIndicesA = (int32*)SPR(0x1200);
+ int32 *aSphereIndicesB = (int32*)SPR(0x1400);
+ int32 *aBoxIndicesB = (int32*)SPR(0x1600);
+ int32 *aTriangleIndicesB = (int32*)SPR(0x1680);
+ bool *aCollided = (bool*)SPR(0x1FE0);
+ CMatrix &matAB = *(CMatrix*)SPR(0x1FF0);
+ CMatrix &matBA = *(CMatrix*)SPR(0x2040);
+ int i, j, k;
+
+ // From model A space to model B space
+ Invert(matrixB, matAB);
+ matAB *= matrixA;
+
+ CVuVector bsphereAB; // bounding sphere of A in B space
+ TransformPoint(bsphereAB, matAB, *(RwV3d*)modelA.boundingSphere.center); // inlined
+ bsphereAB.w = modelA.boundingSphere.radius;
+ if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox))
+ return 0;
+
+ // transform modelA's spheres and lines to B space
+ TransformPoints(aSpheresA, modelA.numSpheres, matAB, (RwV3d*)&modelA.spheres->center, sizeof(CColSphere));
+ for(i = 0; i < modelA.numSpheres; i++)
+ aSpheresA[i].w = modelA.spheres[i].radius;
+ TransformPoints(aLinesA, modelA.numLines*2, matAB, (RwV3d*)&modelA.lines->p0, sizeof(CColLine)/2);
+
+ // Test them against model B's bounding volumes
+ int numSpheresA = 0;
+ for(i = 0; i < modelA.numSpheres; i++)
+ if(TestSphereBox(*(CColSphere*)&aSpheresA[i], modelB.boundingBox))
+ aSphereIndicesA[numSpheresA++] = i;
+ // No collision
+ if(numSpheresA == 0 && modelA.numLines == 0)
+ return 0;
+
+
+ // B to A space
+ Invert(matrixA, matBA);
+ matBA *= matrixB;
+
+ // transform modelB's spheres to A space
+ TransformPoints(aSpheresB, modelB.numSpheres, matBA, (RwV3d*)&modelB.spheres->center, sizeof(CColSphere));
+ for(i = 0; i < modelB.numSpheres; i++)
+ aSpheresB[i].w = modelB.spheres[i].radius;
+
+ // Check model B against A's bounding volumes
+ int numSpheresB = 0;
+ int numBoxesB = 0;
+ int numTrianglesB = 0;
+ for(i = 0; i < modelB.numSpheres; i++)
+ if(TestSphereBox(*(CColSphere*)&aSpheresB[i], modelA.boundingBox))
+ aSphereIndicesB[numSpheresB++] = i;
+ for(i = 0; i < modelB.numBoxes; i++)
+ if(TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boxes[i]))
+ aBoxIndicesB[numBoxesB++] = i;
+ CalculateTrianglePlanes(&modelB);
+ if(modelB.numTriangles){
+ VuTriangle vutri;
+ // process the first triangle
+ CColTriangle *tri = &modelB.triangles[0];
+ modelB.vertices[tri->a].Unpack(vutri.v0);
+ modelB.vertices[tri->b].Unpack(vutri.v1);
+ modelB.vertices[tri->c].Unpack(vutri.v2);
+ modelB.trianglePlanes[0].Unpack(vutri.plane);
+
+ SphereToTriangleCollisionCompressed(bsphereAB, vutri);
+
+ for(i = 1; i < modelB.numTriangles; i++){
+ // set up the next triangle while VU0 is running
+ tri = &modelB.triangles[i];
+ modelB.vertices[tri->a].Unpack(vutri.v0);
+ modelB.vertices[tri->b].Unpack(vutri.v1);
+ modelB.vertices[tri->c].Unpack(vutri.v2);
+ modelB.trianglePlanes[i].Unpack(vutri.plane);
+
+ // check previous result
+ if(GetVUresult())
+ aTriangleIndicesB[numTrianglesB++] = i-1;
+
+ // kick off this one
+ SphereToTriangleCollisionCompressed(bsphereAB, vutri);
+ }
+
+ // check last result
+ if(GetVUresult())
+ aTriangleIndicesB[numTrianglesB++] = i-1;
+ }
+ // No collision
+ if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0)
+ return 0;
+
+ // We now have the collision volumes in A and B that are worth processing.
+
+ // Process A's spheres against B's collision volumes
+ int numCollisions = 0;
+ spherepoints[numCollisions].depth = -1.0f;
+ for(i = 0; i < numSpheresA; i++){
+ float coldist = 1.0e24f;
+ bool hasCollided = false;
+ CColSphere *sphA = &modelA.spheres[aSphereIndicesA[i]];
+ CVuVector *vusphA = &aSpheresA[aSphereIndicesA[i]];
+
+ for(j = 0; j < numSpheresB; j++)
+ // This actually looks like something was inlined here
+ if(ProcessSphereSphere(*(CColSphere*)vusphA, modelB.spheres[aSphereIndicesB[j]],
+ spherepoints[numCollisions], coldist)){
+ spherepoints[numCollisions].Set(
+ sphA->surface, sphA->piece,
+ modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece);
+ hasCollided = true;
+ }
+ for(j = 0; j < numBoxesB; j++)
+ if(ProcessSphereBox(*(CColSphere*)vusphA, modelB.boxes[aBoxIndicesB[j]],
+ spherepoints[numCollisions], coldist)){
+ spherepoints[numCollisions].Set(
+ sphA->surface, sphA->piece,
+ modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece);
+ hasCollided = true;
+ }
+ if(numTrianglesB){
+ CVuVector point, normal;
+ float depth;
+ bool registeredCol;
+ CColTriangle *lasttri;
+
+ VuTriangle vutri;
+ // process the first triangle
+ k = aTriangleIndicesB[0];
+ CColTriangle *tri = &modelB.triangles[k];
+ modelB.vertices[tri->a].Unpack(vutri.v0);
+ modelB.vertices[tri->b].Unpack(vutri.v1);
+ modelB.vertices[tri->c].Unpack(vutri.v2);
+ modelB.trianglePlanes[k].Unpack(vutri.plane);
+
+ SphereToTriangleCollisionCompressed(*vusphA, vutri);
+ lasttri = tri;
+
+ for(j = 1; j < numTrianglesB; j++){
+ k = aTriangleIndicesB[j];
+ // set up the next triangle while VU0 is running
+ tri = &modelB.triangles[k];
+ modelB.vertices[tri->a].Unpack(vutri.v0);
+ modelB.vertices[tri->b].Unpack(vutri.v1);
+ modelB.vertices[tri->c].Unpack(vutri.v2);
+ modelB.trianglePlanes[k].Unpack(vutri.plane);
+
+ // check previous result
+ // TODO: this looks inlined but spherepoints[numCollisions] does not...
+ if(GetVUresult(point, normal, depth)){
+ depth = sphA->radius - depth;
+ if(depth > spherepoints[numCollisions].depth){
+ spherepoints[numCollisions].point = point;
+ spherepoints[numCollisions].normal = normal;
+ spherepoints[numCollisions].Set(depth,
+ sphA->surface, sphA->piece, lasttri->surface, 0);
+ registeredCol = true;
+ }else
+ registeredCol = false;
+ }else
+ registeredCol = false;
+
+ if(registeredCol)
+ hasCollided = true;
+
+ // kick off this one
+ SphereToTriangleCollisionCompressed(*vusphA, vutri);
+ lasttri = tri;
+ }
+
+ // check last result
+ // TODO: this looks inlined but spherepoints[numCollisions] does not...
+ if(GetVUresult(point, normal, depth)){
+ depth = sphA->radius - depth;
+ if(depth > spherepoints[numCollisions].depth){
+ spherepoints[numCollisions].point = point;
+ spherepoints[numCollisions].normal = normal;
+ spherepoints[numCollisions].Set(depth,
+ sphA->surface, sphA->piece, lasttri->surface, 0);
+ registeredCol = true;
+ }else
+ registeredCol = false;
+ }else
+ registeredCol = false;
+
+ if(registeredCol)
+ hasCollided = true;
+ }
+
+ if(hasCollided){
+ numCollisions++;
+ if(numCollisions == MAX_COLLISION_POINTS)
+ break;
+ spherepoints[numCollisions].depth = -1.0f;
+ }
+ }
+ for(i = 0; i < numCollisions; i++){
+ // TODO: both VU0 macros
+ spherepoints[i].point = matrixB * spherepoints[i].point;
+ spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);
+ }
+
+ // And the same thing for the lines in A
+ for(i = 0; i < modelA.numLines; i++){
+ aCollided[i] = false;
+ CVuVector *lineA = &aLinesA[i*2];
+
+ for(j = 0; j < numSpheresB; j++)
+ if(ProcessLineSphere(*(CColLine*)lineA, modelB.spheres[aSphereIndicesB[j]],
+ linepoints[i], linedists[i])){
+ linepoints[i].Set(0, 0,
+#ifdef FIX_BUGS
+ modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece);
+#else
+ modelB.spheres[j].surface, modelB.spheres[j].piece);
+#endif
+ aCollided[i] = true;
+ }
+ for(j = 0; j < numBoxesB; j++)
+ if(ProcessLineBox(*(CColLine*)lineA, modelB.boxes[aBoxIndicesB[j]],
+ linepoints[i], linedists[i])){
+ linepoints[i].Set(0, 0,
+ modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece);
+ aCollided[i] = true;
+ }
+ if(numTrianglesB){
+ CVuVector point, normal;
+ float dist;
+ bool registeredCol;
+ CColTriangle *lasttri;
+
+ VuTriangle vutri;
+ // process the first triangle
+ k = aTriangleIndicesB[0];
+ CColTriangle *tri = &modelB.triangles[k];
+ modelB.vertices[tri->a].Unpack(vutri.v0);
+ modelB.vertices[tri->b].Unpack(vutri.v1);
+ modelB.vertices[tri->c].Unpack(vutri.v2);
+ modelB.trianglePlanes[k].Unpack(vutri.plane);
+
+ LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri);
+ lasttri = tri;
+
+ for(j = 1; j < numTrianglesB; j++){
+ k = aTriangleIndicesB[j];
+ // set up the next triangle while VU0 is running
+ CColTriangle *tri = &modelB.triangles[k];
+ modelB.vertices[tri->a].Unpack(vutri.v0);
+ modelB.vertices[tri->b].Unpack(vutri.v1);
+ modelB.vertices[tri->c].Unpack(vutri.v2);
+ modelB.trianglePlanes[k].Unpack(vutri.plane);
+
+ // check previous result
+ // TODO: this again somewhat looks inlined
+ if(GetVUresult(point, normal, dist)){
+ if(dist < linedists[i]){
+ linepoints[i].point = point;
+ linepoints[i].normal = normal;
+ linedists[i] = dist;
+ linepoints[i].Set(0, 0, lasttri->surface, 0);
+ registeredCol = true;
+ }else
+ registeredCol = false;
+ }else
+ registeredCol = false;
+
+ if(registeredCol)
+ aCollided[i] = true;
+
+ // kick of this one
+ LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri);
+ lasttri = tri;
+ }
+
+ // check last result
+ if(GetVUresult(point, normal, dist)){
+ if(dist < linedists[i]){
+ linepoints[i].point = point;
+ linepoints[i].normal = normal;
+ linedists[i] = dist;
+ linepoints[i].Set(0, 0, lasttri->surface, 0);
+ registeredCol = true;
+ }else
+ registeredCol = false;
+ }else
+ registeredCol = false;
+
+ if(registeredCol)
+ aCollided[i] = true;
+ }
+
+ if(aCollided[i]){
+ // TODO: both VU0 macros
+ linepoints[i].point = matrixB * linepoints[i].point;
+ linepoints[i].normal = Multiply3x3(matrixB, linepoints[i].normal);
+ }
+ }
+
+ return numCollisions; // sphere collisions
+#else
static int aSphereIndicesA[MAXNUMSPHERES];
static int aLineIndicesA[MAXNUMLINES];
static int aSphereIndicesB[MAXNUMSPHERES];
@@ -1196,14 +2261,16 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space
- matAB = Invert(matrixB, matAB) * matrixA;
+ Invert(matrixB, matAB);
+ matAB *= matrixA;
CColSphere bsphereAB; // bounding sphere of A in B space
bsphereAB.Set(modelA.boundingSphere.radius, matAB * modelA.boundingSphere.center);
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
return 0;
// B to A space
- matBA = Invert(matrixA, matBA) * matrixB;
+ matBA = Invert(matrixA, matBA);
+ matBA *= matrixB;
// transform modelA's spheres and lines to B space
for(i = 0; i < modelA.numSpheres; i++){
@@ -1316,6 +2383,7 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
}
return numCollisions; // sphere collisions
+#endif
}
@@ -1858,6 +2926,19 @@ CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uin
this->surface = surf;
}
+#ifdef VU_COLLISION
+void
+CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
+{
+ CVector norm = CrossProduct(vc-va, vb-va);
+ norm.Normalise();
+ float d = DotProduct(norm, va);
+ normal.x = norm.x*4096.0f;
+ normal.y = norm.y*4096.0f;
+ normal.z = norm.z*4096.0f;
+ dist = d*128.0f;
+}
+#else
void
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
{
@@ -1873,6 +2954,7 @@ CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
else
dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
}
+#endif
CColPoint&
CColPoint::operator=(const CColPoint& other)
diff --git a/src/core/Collision.h b/src/core/Collision.h
index eb11d8c4..fd079028 100644
--- a/src/core/Collision.h
+++ b/src/core/Collision.h
@@ -2,9 +2,12 @@
#include "templates.h"
#include "Game.h" // for eLevelName
+#ifdef VU_COLLISION
+#include "VuVector.h"
+#endif
// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
-#ifdef FIX_BUGS
+#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
#define MAX_COLLISION_POINTS 64
#else
#define MAX_COLLISION_POINTS 32
@@ -16,6 +19,28 @@ struct CompressedVector
int16 x, y, z;
CVector Get(void) const { return CVector(x, y, z)/128.0f; };
void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };
+#ifdef GTA_PS2
+ void Unpack(uint128 &qword) const {
+ __asm__ volatile (
+ "lh $8, 0(%1)\n"
+ "lh $9, 2(%1)\n"
+ "lh $10, 4(%1)\n"
+ "pextlw $10, $8\n"
+ "pextlw $2, $9, $10\n"
+ "sq $2, %0\n"
+ : "=m" (qword)
+ : "r" (this)
+ : "$8", "$9", "$10", "$2"
+ );
+ }
+#else
+ void Unpack(int32 *qword) const {
+ qword[0] = x;
+ qword[1] = y;
+ qword[2] = z;
+ qword[3] = 0; // junk
+ }
+#endif
#else
float x, y, z;
CVector Get(void) const { return CVector(x, y, z); };
@@ -25,6 +50,7 @@ struct CompressedVector
struct CSphere
{
+ // NB: this has to be compatible with a CVuVector
CVector center;
float radius;
void Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }
@@ -59,6 +85,7 @@ struct CColBox : public CBox
struct CColLine
{
+ // NB: this has to be compatible with two CVuVectors
CVector p0;
int pad0;
CVector p1;
@@ -81,6 +108,39 @@ struct CColTriangle
struct CColTrianglePlane
{
+#ifdef VU_COLLISION
+ CompressedVector normal;
+ int16 dist;
+
+ void Set(const CVector &va, const CVector &vb, const CVector &vc);
+ void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
+ void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }
+ float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };
+#ifdef GTA_PS2
+ void Unpack(uint128 &qword) const {
+ __asm__ volatile (
+ "lh $8, 0(%1)\n"
+ "lh $9, 2(%1)\n"
+ "lh $10, 4(%1)\n"
+ "lh $11, 6(%1)\n"
+ "pextlw $10, $8\n"
+ "pextlw $11, $9\n"
+ "pextlw $2, $11, $10\n"
+ "sq $2, %0\n"
+ : "=m" (qword)
+ : "r" (this)
+ : "$8", "$9", "$10", "$11", "$2"
+ );
+ }
+#else
+ void Unpack(int32 *qword) const {
+ qword[0] = normal.x;
+ qword[1] = normal.y;
+ qword[2] = normal.z;
+ qword[3] = dist;
+ }
+#endif
+#else
CVector normal;
float dist;
uint8 dir;
@@ -88,7 +148,11 @@ struct CColTrianglePlane
void Set(const CVector &va, const CVector &vb, const CVector &vc);
void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
void GetNormal(CVector &n) const { n = normal; }
+ float GetNormalX() const { return normal.x; }
+ float GetNormalY() const { return normal.y; }
+ float GetNormalZ() const { return normal.z; }
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
+#endif
};
struct CColPoint
@@ -109,7 +173,11 @@ struct CColPoint
struct CStoredCollPoly
{
+#ifdef VU_COLLISION
+ CVuVector verts[3];
+#else
CVector verts[3];
+#endif
bool valid;
};
diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp
index e5f264c7..da0a5967 100644
--- a/src/core/EventList.cpp
+++ b/src/core/EventList.cpp
@@ -8,6 +8,7 @@
#include "Messages.h"
#include "Text.h"
#include "main.h"
+#include "Accident.h"
int32 CEventList::ms_nFirstFreeSlotIndex;
CEvent gaEvent[NUMEVENTS];
@@ -63,6 +64,13 @@ CEventList::RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent
int ref;
bool copsDontCare;
+#ifdef SQUEEZE_PERFORMANCE
+ if (type == EVENT_INJURED_PED) {
+ gAccidentManager.ReportAccident((CPed*)ent);
+ return;
+ }
+#endif
+
copsDontCare = false;
switch(entityType){
case EVENT_ENTITY_PED:
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 6573ac22..7b113d89 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -110,6 +110,7 @@ int gameTxdSlot;
bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
void DoRWStuffEndOfFrame(void);
+#ifdef PS2_MENU
void MessageScreen(char *msg)
{
//TODO: stretch_screen
@@ -143,6 +144,7 @@ void MessageScreen(char *msg)
DoRWStuffEndOfFrame();
}
+#endif
bool
CGame::InitialiseOnceBeforeRW(void)
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 2e3a27b2..29087b34 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -61,6 +61,7 @@ int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES];
int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES];
int32 CStats::BestPositions[CStats::TOTAL_BEST_POSITIONS];
int32 CStats::PropertyDestroyed;
+int32 CStats::PamphletMissionPassed;
int32 CStats::Sprayings;
float CStats::AutoPaintingBudget;
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 7dd527ea..e6b8df6a 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -65,6 +65,7 @@ public:
static int32 HighestScores[TOTAL_HIGHEST_SCORES];
static int32 BestPositions[TOTAL_BEST_POSITIONS];
static int32 PropertyDestroyed;
+ static int32 PamphletMissionPassed;
static int32 Sprayings;
static float AutoPaintingBudget;
static int32 NoMoreHurricanes;
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 7126b26f..fb2dbad3 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -1933,6 +1933,11 @@ CWorld::Process(void)
} else {
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
+#ifdef SQUEEZE_PERFORMANCE
+ if (movingEnt->bRemoveFromWorld) {
+ RemoveEntityInsteadOfProcessingIt(movingEnt);
+ } else
+#endif
if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP &&
RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) {
// TODO(MIAMI): doRender argument
diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp
index 3095b36d..96f5dc62 100644
--- a/src/core/Zones.cpp
+++ b/src/core/Zones.cpp
@@ -7,6 +7,7 @@
#include "Clock.h"
#include "Text.h"
#include "World.h"
+#include "Timer.h"
eLevelName CTheZones::m_CurrLevel;
int16 CTheZones::FindIndex;
@@ -127,6 +128,10 @@ CTheZones::Init(void)
void
CTheZones::Update(void)
{
+#ifdef SQUEEZE_PERFORMANCE
+ if (CTimer::GetFrameCounter() % 5 != 0)
+ return;
+#endif
CVector pos;
pos = FindPlayerCoors();
m_CurrLevel = GetLevelFromPosition(&pos);
diff --git a/src/core/common.h b/src/core/common.h
index d22c1715..ba1d24ef 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -89,6 +89,16 @@ typedef uint16_t wchar;
#include <rpskin.h>
#endif
+#ifdef __GNUC__
+#define TYPEALIGN(n) __attribute__ ((aligned (n)))
+#else
+#ifdef _MSC_VER
+#define TYPEALIGN(n) __declspec(align(n))
+#else
+#define TYPEALIGN(n) // unknown compiler...ignore
+#endif
+#endif
+
#define ALIGNPTR(p) (void*)((((uintptr)(void*)p) + sizeof(void*)-1) & ~(sizeof(void*)-1))
// PDP-10 like byte functions
diff --git a/src/core/config.h b/src/core/config.h
index 4cd4cbe1..469f9017 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -167,7 +167,7 @@ enum Config {
#if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH
-# define COMPRESSED_COL_VECTORS
+# define VU_COLLISION
#elif defined GTA_PC
# define GTA3_1_1_PATCH
//# define GTA3_STEAM_PATCH
@@ -180,6 +180,10 @@ enum Config {
#elif defined GTA_XBOX
#endif
+#ifdef VU_COLLISION
+#define COMPRESSED_COL_VECTORS // current need compressed vectors in this code
+#endif
+
#ifdef MASTER
// only in master builds
#else
@@ -228,6 +232,9 @@ enum Config {
// #define PC_WATER
#define WATER_CHEATS
+//#define USE_CUTSCENE_SHADOW_FOR_PED
+#define DISABLE_CUTSCENE_SHADOWS
+
// Pad
#if !defined(RW_GL3) && defined(_WIN32)
#define XINPUT
@@ -297,4 +304,13 @@ enum Config {
#ifndef AUDIO_OAL // is not working yet for openal
#define AUDIO_CACHE // cache sound lengths to speed up the cold boot
#endif
-//#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS \ No newline at end of file
+//#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS
+
+
+//#define SQUEEZE_PERFORMANCE
+#ifdef SQUEEZE_PERFORMANCE
+ #undef PS2_ALPHA_TEST
+ #undef NO_ISLAND_LOADING
+ #define PC_PARTICLE
+ #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial
+#endif \ No newline at end of file
diff --git a/src/core/main.cpp b/src/core/main.cpp
index d4ef8c4b..83d4b66e 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -852,7 +852,7 @@ RenderScene(void)
CRenderer::RenderFadingInEntities();
RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
CWeather::RenderRainStreaks();
- // CCoronas::RenderSunReflection
+ CCoronas::RenderSunReflection();
}
void
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 81b2bfc0..e9c643ac 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -7,6 +7,7 @@
#include "Credits.h"
#include "Camera.h"
#include "Weather.h"
+#include "Timecycle.h"
#include "Clock.h"
#include "World.h"
#include "Vehicle.h"
@@ -406,6 +407,26 @@ DebugMenuPopulate(void)
static const char *weathers[] = {
"Sunny", "Cloudy", "Rainy", "Foggy", "Extrasunny", "Stormy"
};
+ static const char *extracols[] = {
+ "1 - Malibu club",
+ "2 - Strib club",
+ "3 - Hotel",
+ "4 - Bank",
+ "5 - Police HQ",
+ "6 - Mall",
+ "7 - Rifle Range",
+ "8 - Mansion",
+ "9 - Dirt ring",
+ "10 - Blood ring",
+ "11 - Hot ring",
+ "12 - Concert hall",
+ "13 - Auntie Poulets",
+ "14 - Intro at docks",
+ "15 - Biker bar",
+ "16 - Intro cafe",
+ "17 - Studio",
+ "18", "19", "20", "21", "22", "23", "24"
+ };
DebugMenuEntry *e;
e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil);
DebugMenuEntrySetWrap(e, true);
@@ -416,7 +437,8 @@ DebugMenuPopulate(void)
DebugMenuEntrySetWrap(e, true);
e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 5, weathers);
DebugMenuEntrySetWrap(e, true);
- DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f);
+ DebugMenuAddVarBool8("Time & Weather", "Extracolours On", &CTimeCycle::m_bExtraColourOn, nil);
+ DebugMenuAddVar("Time & Weather", "Extracolour", &CTimeCycle::m_ExtraColour, nil, 1, 0, 23, extracols);
DebugMenuAddVar("Time & Weather", "Time scale", (float*)&CTimer::GetTimeScale(), nil, 0.1f, 0.0f, 10.0f);
DebugMenuAddCmd("Cheats", "Weapon set 1", WeaponCheat1);
@@ -489,9 +511,7 @@ DebugMenuPopulate(void)
DebugMenuAddVarBool8("Render", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil);
DebugMenuAddVarBool8("Render", "Backface Culling", &gBackfaceCulling, nil);
-#ifdef LIBRW
DebugMenuAddVarBool8("Render", "PS2 Alpha test Emu", &gPS2alphaTest, nil);
-#endif
DebugMenuAddVarBool8("Render", "Frame limiter", &FrontEndMenuManager.m_PrefsFrameLimiter, nil);
DebugMenuAddVarBool8("Render", "VSynch", &FrontEndMenuManager.m_PrefsVsync, nil);
DebugMenuAddVar("Render", "Max FPS", &RsGlobal.maxFPS, nil, 1, 1, 1000, nil);
diff --git a/src/core/vu0Collision.dsm b/src/core/vu0Collision.dsm
new file mode 100644
index 00000000..657c8b81
--- /dev/null
+++ b/src/core/vu0Collision.dsm
@@ -0,0 +1,21 @@
+.align 4
+.global Vu0CollisionDmaTag
+Vu0CollisionDmaTag:
+DMAcnt *
+MPG 0, *
+.vu
+.include "vu0Collision_1.s"
+.EndMPG
+.EndDmaData
+DMAend
+
+.global Vu0Collision2DmaTag
+Vu0Collision2DmaTag:
+DMAcnt *
+MPG 0, *
+.vu
+.include "vu0Collision_2.s"
+.EndMPG
+.EndDmaData
+DMAend
+.end
diff --git a/src/core/vu0Collision_1.s b/src/core/vu0Collision_1.s
new file mode 100644
index 00000000..055c8640
--- /dev/null
+++ b/src/core/vu0Collision_1.s
@@ -0,0 +1,610 @@
+QuitAndFail:
+ NOP[E] IADDIU VI01, VI00, 0
+ NOP NOP
+
+
+QuitAndSucceed:
+ NOP[E] IADDIU VI01, VI00, 1
+ NOP NOP
+
+
+; 20 -- unused
+; VF12, VF13 xyz: sphere centers
+; VF14, VF15 x: sphere radii
+; out:
+; VI01: set when collision
+; VF01: supposed to be intersection point?
+; VF02: normal (pointing towards s1, not normalized)
+.globl Vu0SphereToSphereCollision
+Vu0SphereToSphereCollision:
+ SUB.xyz VF02, VF13, VF12 NOP ; dist of centers
+ ADD.x VF04, VF14, VF15 NOP ; s = sum of radii
+ MUL.xyzw VF03, VF02, VF02 NOP ;
+ MUL.x VF04, VF04, VF04 DIV Q, VF14x, VF04x ; square s
+ NOP NOP ;
+ NOP NOP ;
+ MULAx.w ACC, VF00, VF03 NOP ;
+ MADDAy.w ACC, VF00, VF03 NOP ;
+ MADDz.w VF03, VF00, VF03 NOP ; d = DistSq of centers
+ NOP NOP ;
+ MULAw.xyz ACC, VF12, VF00 NOP ;
+ MADDq.xyz VF01, VF02, Q NOP ; intersection, but wrong
+ CLIPw.xyz VF04, VF03 NOP ; compare s and d
+ SUB.xyz VF02, VF00, VF02 NOP ; compute normal
+ NOP NOP ;
+ NOP NOP ;
+ NOP FCAND VI01, 0x3 ; 0x2 cannot be set here
+ NOP[E] NOP ;
+ NOP NOP ;
+
+
+; B8 -- unused
+; VF12:
+; VF13: radius
+; VF14:
+; VF15: box dimensions (?)
+.globl Vu0SphereToAABBCollision
+Vu0SphereToAABBCollision:
+ SUB.xyz VF03, VF12, VF14 LOI 0.5
+ MULi.xyz VF15, VF15, I NOP
+ MUL.x VF13, VF13, VF13 NOP
+ SUB.xyz VF04, VF03, VF15 NOP
+ ADD.xyz VF05, VF03, VF15 MR32.xyzw VF16, VF15
+ CLIPw.xyz VF03, VF16 MR32.xyzw VF17, VF16
+ MUL.xyz VF04, VF04, VF04 NOP
+ MUL.xyz VF05, VF05, VF05 NOP
+ CLIPw.xyz VF03, VF17 MR32.xyzw VF16, VF17
+ NOP FCAND VI01, 0x1
+ MINI.xyz VF04, VF04, VF05 MFIR.x VF09, VI01
+ NOP NOP
+ CLIPw.xyz VF03, VF16 FCAND VI01, 0x4
+ NOP MFIR.y VF09, VI01
+ NOP NOP
+ MULAx.w ACC, VF00, VF00 NOP
+ ADD.xyz VF01, VF00, VF03 FCAND VI01, 0x10
+ NOP MFIR.z VF09, VI01
+ NOP LOI 2
+ NOP FCAND VI01, 0x30
+ SUBAw.xyz ACC, VF00, VF00 IADD VI04, VI00, VI01
+ ITOF0.xyz VF09, VF09 FCAND VI01, 0x300
+ NOP IADD VI03, VI00, VI01
+ NOP FCAND VI01, 0x3000
+ NOP IADD VI02, VI00, VI01
+ MADDi.xyzw VF09, VF09, I NOP
+ NOP IBEQ VI04, VI00, IgnoreZValue
+ NOP NOP
+ MADDAz.w ACC, VF00, VF04 NOP
+ MUL.z VF01, VF09, VF15 NOP
+IgnoreZValue:
+ NOP IBEQ VI03, VI00, IgnoreYValue
+ NOP NOP
+ MADDAy.w ACC, VF00, VF04 NOP
+ MUL.y VF01, VF09, VF15 NOP
+IgnoreYValue:
+ NOP IBEQ VI02, VI00, IgnoreXValue
+ NOP NOP
+ MADDAx.w ACC, VF00, VF04 NOP
+ MUL.x VF01, VF09, VF15 NOP
+IgnoreXValue:
+ MADDx.w VF06, VF00, VF00 NOP
+ SUB.xyz VF02, VF03, VF01 NOP
+ ADD.xyz VF01, VF01, VF14 NOP
+ MULx.w VF01, VF00, VF00 NOP
+ CLIPw.xyz VF13, VF06 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x1
+QuitMicrocode:
+ NOP[E] NOP
+ NOP NOP
+
+
+; 240
+.globl Vu0LineToSphereCollision
+Vu0LineToSphereCollision:
+ SUB.xyzw VF01, VF13, VF12 NOP
+ SUB.xyzw VF02, VF14, VF12 NOP
+ MUL.xyz VF03, VF01, VF02 NOP
+ MUL.xyz VF04, VF01, VF01 NOP
+ MUL.x VF15, VF15, VF15 NOP
+ MUL.xyz VF02, VF02, VF02 NOP
+ MULAx.w ACC, VF00, VF03 NOP
+ MADDAy.w ACC, VF00, VF03 NOP
+ MADDz.w VF03, VF00, VF03 NOP
+ MULAx.w ACC, VF00, VF04 NOP
+ MADDAy.w ACC, VF00, VF04 NOP
+ MADDz.w VF01, VF00, VF04 NOP
+ MULAx.w ACC, VF00, VF02 NOP
+ MADDAy.w ACC, VF00, VF02 NOP
+ MADDz.w VF02, VF00, VF02 NOP
+ MULA.w ACC, VF03, VF03 NOP
+ MADDAx.w ACC, VF01, VF15 NOP
+ MSUB.w VF05, VF01, VF02 NOP
+ NOP NOP
+ NOP NOP
+ NOP IADDIU VI02, VI00, 0x10
+ NOP FMAND VI01, VI02
+ NOP IBNE VI01, VI00, QuitAndFail
+ NOP NOP
+ CLIPw.xyz VF15, VF02 SQRT Q, VF05w
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x1
+ NOP IBNE VI00, VI01, LineStartInsideSphere
+ NOP NOP
+ SUBq.w VF05, VF03, Q NOP
+ SUB.w VF05, VF05, VF01 DIV Q, VF05w, VF01w
+ NOP FMAND VI01, VI02
+ NOP IBNE VI01, VI00, QuitAndFail
+ NOP NOP
+ NOP FMAND VI01, VI02
+ NOP IBEQ VI01, VI00, QuitAndFail
+ NOP NOP
+ ADDA.xyz ACC, VF12, VF00 NOP
+ MADDq.xyz VF01, VF01, Q NOP
+ MULx.w VF01, VF00, VF00 NOP
+ SUB.xyz VF02, VF01, VF14 NOP
+ NOP[E] NOP
+ NOP NOP
+LineStartInsideSphere:
+ NOP MOVE.xyzw VF01, VF12
+ NOP[E] IADDIU VI01, VI00, 0x1
+ NOP NOP
+
+
+; 3C0
+.globl Vu0LineToAABBCollision
+Vu0LineToAABBCollision:
+ SUB.xyzw VF08, VF13, VF12 LOI 0.5
+ MULi.xyz VF15, VF15, I IADDIU VI08, VI00, 0x0
+ SUB.xyzw VF12, VF12, VF14 NOP
+ SUB.xyzw VF13, VF13, VF14 NOP
+ NOP DIV Q, VF00w, VF08x
+ NOP MR32.xyzw VF03, VF15
+ SUB.xyz VF06, VF15, VF12 NOP
+ ADD.xyz VF07, VF15, VF12 NOP
+ NOP NOP
+ CLIPw.xyz VF12, VF03 MR32.xyzw VF04, VF03
+ NOP NOP
+ ADDq.x VF09, VF00, Q DIV Q, VF00w, VF08y
+ NOP NOP
+ CLIPw.xyz VF12, VF04 MR32.xyzw VF05, VF04
+ SUB.xyz VF07, VF00, VF07 IADDIU VI06, VI00, 0xCC
+ NOP IADDIU VI07, VI00, 0x30
+ NOP NOP
+ CLIPw.xyz VF12, VF05 FCGET VI02
+ NOP IAND VI02, VI02, VI06
+ ADDq.y VF09, VF00, Q DIV Q, VF00w, VF08z
+ SUB.xyz VF10, VF00, VF10 NOP
+ CLIPw.xyz VF13, VF03 FCGET VI03
+ CLIPw.xyz VF13, VF04 IAND VI03, VI03, VI07
+ CLIPw.xyz VF13, VF05 FCAND VI01, 0x3330
+ NOP IBEQ VI01, VI00, StartPointInsideAABB
+ NOP NOP
+ ADDq.z VF09, VF00, Q FCGET VI04
+ NOP FCGET VI05
+ NOP IAND VI04, VI04, VI06
+ NOP IAND VI05, VI05, VI07
+ MULx.xyz VF17, VF08, VF09 NOP
+ MULy.xyz VF18, VF08, VF09 IADDIU VI07, VI00, 0x80
+ MULz.xyz VF19, VF08, VF09 IAND VI06, VI02, VI07
+ MUL.w VF10, VF00, VF00 IAND VI07, VI04, VI07
+ NOP NOP
+ NOP IBEQ VI06, VI07, CheckMaxXSide
+ NOP NOP
+ MULAx.xyz ACC, VF17, VF07 NOP
+ MADDw.xyz VF16, VF12, VF00 NOP
+ MUL.x VF10, VF07, VF09 NOP
+ CLIPw.xyz VF16, VF04 NOP
+ CLIPw.xyz VF16, VF05 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x330
+ NOP IBNE VI01, VI00, CheckMaxXSide
+ NOP NOP
+ MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
+ ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
+ SUBw.x VF02, VF00, VF00 NOP
+CheckMaxXSide:
+ MULAx.xyz ACC, VF17, VF06 IADDIU VI07, VI00, 0x40
+ MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07
+ MUL.x VF10, VF06, VF09 IAND VI07, VI04, VI07
+ NOP NOP
+ NOP IBEQ VI06, VI07, CheckMinYSide
+ NOP NOP
+ CLIPw.xyz VF16, VF04 NOP
+ CLIPw.xyz VF16, VF05 NOP
+ CLIPw.xyz VF10, VF10 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0xCC03
+ NOP IBNE VI01, VI00, CheckMinYSide
+ NOP NOP
+ MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
+ ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
+ ADDw.x VF02, VF00, VF00 NOP
+CheckMinYSide:
+ MULAy.xyz ACC, VF18, VF07 IADDIU VI07, VI00, 0x8
+ MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07
+ MUL.y VF10, VF07, VF09 IAND VI07, VI04, VI07
+ NOP NOP
+ NOP IBEQ VI06, VI07, CheckMaxYSide
+ NOP NOP
+ CLIPw.xyz VF16, VF03 NOP
+ CLIPw.xyz VF16, VF05 NOP
+ CLIPw.xyz VF10, VF10 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x3C0C
+ NOP IBNE VI01, VI00, CheckMaxYSide
+ NOP NOP
+ MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
+ ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
+ SUBw.y VF02, VF00, VF00 NOP
+CheckMaxYSide:
+ MULAy.xyz ACC, VF18, VF06 IADDIU VI07, VI00, 0x4
+ MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07
+ MUL.y VF10, VF06, VF09 IAND VI07, VI04, VI07
+ NOP NOP
+ NOP IBEQ VI06, VI07, CheckMinZSide
+ NOP NOP
+ CLIPw.xyz VF16, VF03 NOP
+ CLIPw.xyz VF16, VF05 NOP
+ CLIPw.xyz VF10, VF10 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x3C0C
+ NOP IBNE VI01, VI00, CheckMinZSide
+ NOP NOP
+ MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
+ ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
+ ADDw.y VF02, VF00, VF00 NOP
+CheckMinZSide:
+ MULAz.xyz ACC, VF19, VF07 IADDIU VI07, VI00, 0x20
+ MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07
+ MUL.z VF10, VF07, VF09 IAND VI07, VI05, VI07
+ NOP NOP
+ NOP IBEQ VI06, VI07, CheckMaxZSide
+ NOP NOP
+ CLIPw.xyz VF16, VF03 NOP
+ CLIPw.xyz VF16, VF04 NOP
+ CLIPw.xyz VF10, VF10 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x3330
+ NOP IBNE VI01, VI00, CheckMaxZSide
+ NOP NOP
+ MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
+ ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16
+ SUBw.z VF02, VF00, VF00 NOP
+CheckMaxZSide:
+ MULAz.xyz ACC, VF19, VF06 IADDIU VI07, VI00, 0x10
+ MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07
+ MUL.z VF10, VF06, VF09 IAND VI07, VI05, VI07
+ NOP NOP
+ NOP IBEQ VI06, VI07, DoneAllChecks
+ NOP NOP
+ CLIPw.xyz VF16, VF03 NOP
+ CLIPw.xyz VF16, VF04 NOP
+ CLIPw.xyz VF10, VF10 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x3330
+ NOP IBNE VI01, VI00, DoneAllChecks
+ NOP NOP
+ MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
+ ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16
+ ADDw.z VF02, VF00, VF00 NOP
+DoneAllChecks:
+ ADD.xyz VF01, VF01, VF14 IADD VI01, VI00, VI08
+ NOP[E] NOP
+ NOP NOP
+StartPointInsideAABB:
+ ADD.xyz VF01, VF12, VF14 WAITQ
+ NOP IADDIU VI01, VI00, 0x1
+ NOP[E] NOP
+ NOP NOP
+
+
+; 860
+.globl Vu0LineToTriangleCollisionCompressedStart
+Vu0LineToTriangleCollisionCompressedStart:
+ ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0
+ ITOF0.xyzw VF14, VF14 NOP
+ ITOF0.xyzw VF15, VF15 NOP
+ ITOF0.xyzw VF16, VF16 NOP
+ MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0
+ MULi.w VF17, VF17, I NOP
+ MULi.xyzw VF14, VF14, I NOP
+ MULi.xyzw VF15, VF15, I NOP
+ MULi.xyzw VF16, VF16, I NOP
+; fall through
+
+; 8A8
+; VF12: point0
+; VF13: point1
+; VF14-16: verts
+; VF17: plane
+; out:
+; VF01: intersection point
+; VF02: triangle normal
+; VF03 x: intersection parameter
+.globl Vu0LineToTriangleCollisionStart
+Vu0LineToTriangleCollisionStart:
+ MUL.xyz VF10, VF17, VF12 LOI 0.5
+ MUL.xyz VF11, VF17, VF13 NOP
+ SUB.xyz VF02, VF13, VF12 NOP ; line dist
+ ADD.xyz VF17, VF17, VF00 NOP
+ MULi.w VF03, VF00, I NOP
+ MULAx.w ACC, VF00, VF10 NOP
+ MADDAy.w ACC, VF00, VF10 IADDIU VI06, VI00, 0xE0
+ MADDz.w VF10, VF00, VF10 FMAND VI05, VI06 ; -- normal sign flags, unused
+ MULAx.w ACC, VF00, VF11 NOP
+ MADDAy.w ACC, VF00, VF11 NOP
+ MADDz.w VF11, VF00, VF11 NOP
+ SUB.w VF09, VF17, VF10 NOP ; plane-pos 0
+ CLIPw.xyz VF17, VF03 NOP ; compare normal against 0.5 to figure out which in which dimension to compare
+ NOP IADDIU VI02, VI00, 0x10 ; Sw flag
+ SUBA.w ACC, VF17, VF11 NOP ; plane-pos 1
+ SUB.w VF08, VF11, VF10 FMAND VI01, VI02
+ NOP NOP
+ NOP NOP
+ NOP FMAND VI02, VI02
+ NOP IBEQ VI01, VI02, QuitAndFail ; if on same side, no collision
+ NOP NOP
+ NOP DIV Q, VF09w, VF08w ; parameter of intersection
+ NOP FCAND VI01, 0x3 ; check x direction
+ NOP IADDIU VI02, VI01, 0x7F
+ NOP IADDIU VI06, VI00, 0x80
+ NOP IAND VI02, VI02, VI06 ; Sx flag
+ NOP FCAND VI01, 0xC ; check y direction
+ NOP IADDIU VI03, VI01, 0x3F
+ MULAw.xyz ACC, VF12, VF00 IADDIU VI06, VI00, 0x40
+ MADDq.xyz VF01, VF02, Q IAND VI03, VI03, VI06 ; point of intersection -- Sy flag
+ MULx.w VF01, VF00, VF00 FCAND VI01, 0x30 ; -- check z direction
+ ADDq.x VF03, VF00, Q IADDIU VI04, VI01, 0x1F ; output parameter
+ SUB.xyz VF05, VF15, VF14 IADDIU VI06, VI00, 0x20 ; edge vectors
+ SUB.xyz VF08, VF01, VF14 IAND VI04, VI04, VI06 ; edge vectors -- Sz flag
+ SUB.xyz VF06, VF16, VF15 IADD VI06, VI02, VI03 ; edge vectors
+ SUB.xyz VF09, VF01, VF15 IADD VI06, VI06, VI04 ; edge vectors -- combine flags
+ SUB.xyz VF07, VF14, VF16 NOP ; edge vectors
+ SUB.xyz VF10, VF01, VF16 NOP ; edge vectors
+ OPMULA.xyz ACC, VF08, VF05 NOP
+ OPMSUB.xyz VF18, VF05, VF08 NOP ; cross1
+ OPMULA.xyz ACC, VF09, VF06 NOP
+ OPMSUB.xyz VF19, VF06, VF09 NOP ; cross2
+ OPMULA.xyz ACC, VF10, VF07 NOP
+ OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; cross3
+ NOP NOP
+ NOP FMAND VI03, VI06
+ NOP NOP
+ NOP FMAND VI04, VI06
+ NOP NOP
+ NOP IBNE VI03, VI02, QuitAndFail ; point has to lie on the same side of all edges (i.e. inside)
+ NOP NOP
+ NOP IBNE VI04, VI02, QuitAndFail
+ NOP NOP
+ MULw.xyz VF02, VF17, VF00 IADDIU VI01, VI00, 0x1 ; success
+ NOP[E] NOP
+ NOP NOP
+
+
+; A68
+; VF12: center
+; VF14: line origin
+; VF15: line vector to other point
+; out: VF16 xyz: nearest point on line; w: distance to that point
+DistanceBetweenSphereAndLine:
+ SUB.xyz VF20, VF12, VF14 NOP
+ MUL.xyz VF21, VF15, VF15 NOP
+ ADDA.xyz ACC, VF14, VF15 NOP
+ MSUBw.xyz VF25, VF12, VF00 NOP ; VF25 = VF12 - (VF14+VF15)
+ MUL.xyz VF22, VF20, VF20 NOP
+ MUL.xyz VF23, VF20, VF15 NOP
+ MULAx.w ACC, VF00, VF21 NOP
+ MADDAy.w ACC, VF00, VF21 NOP
+ MADDz.w VF21, VF00, VF21 NOP ; MagSq VF15 (line length)
+ MULAx.w ACC, VF00, VF23 NOP
+ MADDAy.w ACC, VF00, VF23 NOP
+ MADDz.w VF23, VF00, VF23 NOP ; dot(VF12-VF14, VF15)
+ MULAx.w ACC, VF00, VF22 NOP
+ MADDAy.w ACC, VF00, VF22 NOP
+ MADDz.w VF22, VF00, VF22 IADDIU VI08, VI00, 0x10 ; MagSq VF12-VF14 -- Sw bit
+ MUL.xyz VF25, VF25, VF25 FMAND VI08, VI08
+ NOP DIV Q, VF23w, VF21w
+ NOP IBNE VI00, VI08, NegativeRatio
+ NOP NOP
+ ADDA.xyz ACC, VF00, VF14 NOP
+ MADDq.xyz VF16, VF15, Q WAITQ ; nearest point on infinte line
+ ADDq.x VF24, VF00, Q NOP ; ratio
+ NOP NOP
+ NOP NOP
+ SUB.xyz VF26, VF16, VF12 NOP
+ CLIPw.xyz VF24, VF00 NOP ; compare ratio to 1.0
+ NOP NOP
+ NOP NOP
+ MUL.xyz VF26, VF26, VF26 NOP
+ NOP FCAND VI01, 0x1
+ NOP IBNE VI00, VI01, RatioGreaterThanOne
+ NOP NOP
+ MULAx.w ACC, VF00, VF26 NOP
+ MADDAy.w ACC, VF00, VF26 NOP
+ MADDz.w VF16, VF00, VF26 NOP ; distance
+ NOP JR VI15
+ NOP NOP
+NegativeRatio:
+ ADD.xyz VF16, VF00, VF14 NOP ; return line origin
+ MUL.w VF16, VF00, VF22 NOP ; and DistSq to it
+ NOP JR VI15
+ NOP NOP
+RatioGreaterThanOne:
+ MULAx.w ACC, VF00, VF25 NOP
+ MADDAy.w ACC, VF00, VF25 NOP
+ MADDz.w VF16, VF00, VF25 NOP
+ ADD.xyz VF16, VF14, VF15 NOP ; return toerh line point
+ NOP JR VI15
+ NOP NOP
+
+
+; BE0
+.globl Vu0SphereToTriangleCollisionCompressedStart
+Vu0SphereToTriangleCollisionCompressedStart:
+ ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0
+ ITOF0.xyzw VF14, VF14 NOP
+ ITOF0.xyzw VF15, VF15 NOP
+ ITOF0.xyzw VF16, VF16 NOP
+ MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0
+ MULi.w VF17, VF17, I NOP
+ MULi.xyzw VF14, VF14, I NOP
+ MULi.xyzw VF15, VF15, I NOP
+ MULi.xyzw VF16, VF16, I NOP
+; fall through
+
+; C28
+; VF12: sphere
+; VF14-16: verts
+; VF17: plane
+; out:
+; VF01: intersection point
+; VF02: triangle normal
+; VF03 x: intersection parameter
+.globl Vu0SphereToTriangleCollisionStart
+Vu0SphereToTriangleCollisionStart:
+ MUL.xyz VF02, VF12, VF17 LOI 0.1
+ ADD.xyz VF17, VF17, VF00 NOP
+ ADDw.x VF13, VF00, VF12 NOP
+ NOP NOP
+ MULAx.w ACC, VF00, VF02 IADDIU VI06, VI00, 0xE0
+ MADDAy.w ACC, VF00, VF02 FMAND VI05, VI06 ; normal sign flags
+ MADDAz.w ACC, VF00, VF02 NOP
+ MSUB.w VF02, VF00, VF17 NOP ; center plane pos
+ MULi.w VF03, VF00, I MOVE.xyzw VF04, VF03
+ NOP NOP
+ NOP NOP
+ CLIPw.xyz VF13, VF02 NOP ; compare dist and radius
+ CLIPw.xyz VF17, VF03 NOP
+ MULAw.xyz ACC, VF12, VF00 IADDIU VI07, VI00, 0x0 ; -- clear test case
+ MSUBw.xyz VF01, VF17, VF02 NOP
+ MULx.w VF01, VF00, VF00 FCAND VI01, 0x3 ; projected center on plane
+ ABS.w VF02, VF02 IBEQ VI00, VI01, QuitAndFail ; no intersection
+ NOP NOP
+ NOP FCAND VI01, 0x3 ; -- check x direction
+ SUB.xyz VF02, VF12, VF01 IADDIU VI02, VI01, 0x7F
+ NOP IADDIU VI06, VI00, 0x80
+ SUB.xyz VF05, VF15, VF14 IAND VI02, VI02, VI06
+ SUB.xyz VF08, VF01, VF14 FCAND VI01, 0xC ; -- check y direction
+ SUB.xyz VF06, VF16, VF15 IADDIU VI03, VI01, 0x3F
+ SUB.xyz VF09, VF01, VF15 IADDIU VI06, VI00, 0x40
+ SUB.xyz VF07, VF14, VF16 IAND VI03, VI03, VI06
+ SUB.xyz VF10, VF01, VF16 FCAND VI01, 0x30 ; -- check z direction
+ MUL.xyz VF03, VF02, VF02 IADDIU VI04, VI01, 0x1F
+ OPMULA.xyz ACC, VF08, VF05 IADDIU VI06, VI00, 0x20
+ OPMSUB.xyz VF18, VF05, VF08 IAND VI04, VI04, VI06
+ OPMULA.xyz ACC, VF09, VF06 NOP
+ OPMSUB.xyz VF19, VF06, VF09 IADD VI06, VI02, VI03
+ OPMULA.xyz ACC, VF10, VF07 IADD VI06, VI06, VI04 ; -- combine flags
+ OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; -- cross 1 flags
+ MULAx.w ACC, VF00, VF03 IAND VI05, VI05, VI06
+ MADDAy.w ACC, VF00, VF03 FMAND VI03, VI06 ; -- cross 2 flags
+ MADDz.w VF03, VF00, VF03 IADDIU VI08, VI00, 0x3
+ NOP FMAND VI04, VI06 ; -- cross 3 flags
+ NOP NOP
+ NOP IBNE VI02, VI05, CheckSide2
+ NOP RSQRT Q, VF00w, VF03w
+ ADD.xyz VF04, VF00, VF16 IADDIU VI07, VI07, 0x1 ; inside side 1
+CheckSide2:
+ NOP IBNE VI03, VI05, CheckSide3
+ NOP NOP
+ ADD.xyz VF04, VF00, VF14 IADDIU VI07, VI07, 0x1 ; inside side 2
+CheckSide3:
+ NOP IBNE VI04, VI05, FinishCheckingSides
+ NOP NOP
+ ADD.xyz VF04, VF00, VF15 IADDIU VI07, VI07, 0x1 ; inside side 3
+ NOP NOP
+ NOP IBEQ VI07, VI08, TotallyInsideTriangle
+ NOP NOP
+FinishCheckingSides:
+ MUL.x VF13, VF13, VF13 IADDIU VI08, VI00, 0x2
+ MULq.xyz VF02, VF02, Q WAITQ
+ NOP IBNE VI07, VI08, IntersectionOutsideTwoSides
+ NOP NOP
+ NOP IBEQ VI02, VI05, CheckDistanceSide2
+ NOP NOP
+ NOP MOVE.xyzw VF15, VF05
+ NOP BAL VI15, DistanceBetweenSphereAndLine
+ NOP NOP
+ NOP B ProcessLineResult
+ NOP NOP
+CheckDistanceSide2:
+ NOP IBEQ VI03, VI05, CheckDistanceSide3
+ NOP NOP
+ NOP MOVE.xyzw VF14, VF15
+ NOP MOVE.xyzw VF15, VF06
+ NOP BAL VI15, DistanceBetweenSphereAndLine
+ NOP NOP
+ NOP B ProcessLineResult
+ NOP NOP
+CheckDistanceSide3:
+ NOP MOVE.xyzw VF14, VF16
+ NOP MOVE.xyzw VF15, VF07
+ NOP BAL VI15, DistanceBetweenSphereAndLine
+ NOP NOP
+ NOP B ProcessLineResult
+ NOP NOP
+IntersectionOutsideTwoSides:
+ SUB.xyz VF05, VF04, VF12 NOP
+ ADD.xyz VF01, VF00, VF04 NOP ; col point
+ SUB.xyz VF02, VF12, VF04 NOP
+ NOP NOP
+ MUL.xyz VF05, VF05, VF05 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ MULAx.w ACC, VF00, VF05 NOP
+ MADDAy.w ACC, VF00, VF05 NOP
+ MADDz.w VF05, VF00, VF05 NOP ; distSq to vertex
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ CLIPw.xyz VF13, VF05 SQRT Q, VF05w ; compare radiusSq and distSq
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x1
+ ADDq.x VF03, VF00, Q WAITQ ; dist to vertex
+ NOP IBEQ VI00, VI01, QuitAndFail ; too far
+ NOP NOP
+ NOP NOP
+ NOP DIV Q, VF00w, VF03x
+ MULq.xyz VF02, VF02, Q WAITQ ; col normal
+ NOP[E] NOP
+ NOP NOP
+TotallyInsideTriangle:
+ ADDw.x VF03, VF00, VF02 WAITQ
+ MULq.xyz VF02, VF02, Q NOP
+ NOP[E] IADDIU VI01, VI00, 0x1
+ NOP NOP
+ProcessLineResult:
+ CLIPw.xyz VF13, VF16 SQRT Q, VF16w
+ ADD.xyz VF01, VF00, VF16 NOP
+ SUB.xyz VF02, VF12, VF16 NOP
+ NOP NOP
+ NOP FCAND VI01, 0x1
+ ADDq.x VF03, VF00, Q WAITQ
+ NOP IBEQ VI00, VI01, QuitAndFail
+ NOP NOP
+ NOP NOP
+ NOP DIV Q, VF00w, VF03x
+ MULq.xyz VF02, VF02, Q WAITQ
+ NOP[E] NOP
+ NOP NOP
+
+EndOfMicrocode:
diff --git a/src/core/vu0Collision_2.s b/src/core/vu0Collision_2.s
new file mode 100644
index 00000000..716c29ac
--- /dev/null
+++ b/src/core/vu0Collision_2.s
@@ -0,0 +1,191 @@
+QuitAndFail2:
+ NOP[E] IADDIU VI01, VI00, 0x0
+ NOP NOP
+
+
+QuitAndSucceed2:
+ NOP[E] IADDIU VI01, VI00, 0x1
+ NOP NOP
+
+
+; 20
+GetBBVertices:
+ MULw.xy VF02, VF01, VF00 NOP
+ MUL.z VF02, VF01, VF11 NOP
+ MULw.xz VF03, VF01, VF00 NOP
+ MUL.y VF03, VF01, VF11 NOP
+ MULw.x VF04, VF01, VF00 NOP
+ MUL.yz VF04, VF01, VF11 NOP
+ NOP JR VI15
+ NOP NOP
+
+
+; 60
+Vu0OBBToOBBCollision:
+ SUBw.xyz VF11, VF00, VF00 LOI 0.5
+ MULi.xyz VF12, VF12, I NOP
+ MULi.xyz VF13, VF13, I NOP
+ NOP NOP
+ NOP NOP
+ NOP MOVE.xyz VF01, VF12
+ NOP BAL VI15, GetBBVertices
+ NOP NOP
+ MULAx.xyz ACC, VF14, VF01 NOP
+ MADDAy.xyz ACC, VF15, VF01 NOP
+ MADDz.xyz VF01, VF16, VF01 NOP
+ MULAx.xyz ACC, VF14, VF02 NOP
+ MADDAy.xyz ACC, VF15, VF02 NOP
+ MADDz.xyz VF02, VF16, VF02 NOP
+ MULAx.xyz ACC, VF14, VF03 NOP
+ MADDAy.xyz ACC, VF15, VF03 NOP
+ MADDz.xyz VF03, VF16, VF03 NOP
+ MULAx.xyz ACC, VF14, VF04 NOP
+ MADDAy.xyz ACC, VF15, VF04 NOP
+ MADDz.xyz VF04, VF16, VF04 NOP
+ ABS.xyz VF05, VF01 NOP
+ ABS.xyz VF06, VF02 NOP
+ ABS.xyz VF07, VF03 NOP
+ ABS.xyz VF08, VF04 NOP
+ NOP NOP
+ MAX.xyz VF05, VF05, VF06 NOP
+ NOP NOP
+ MAX.xyz VF07, VF07, VF08 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ MAX.xyz VF05, VF05, VF07 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ ADD.xyz VF09, VF05, VF13 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ MULx.w VF05, VF00, VF09 NOP
+ MULy.w VF06, VF00, VF09 NOP
+ MULz.w VF07, VF00, VF09 NOP
+ CLIPw.xyz VF17, VF05 NOP
+ CLIPw.xyz VF17, VF06 NOP
+ CLIPw.xyz VF17, VF07 MOVE.xyz VF01, VF13
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x3330
+ NOP IBNE VI01, VI00, QuitAndFail2
+ NOP NOP
+ NOP BAL VI15, GetBBVertices
+ NOP NOP
+ MULAx.xyz ACC, VF18, VF01 NOP
+ MADDAy.xyz ACC, VF19, VF01 NOP
+ MADDz.xyz VF01, VF20, VF01 NOP
+ MULAx.xyz ACC, VF18, VF02 NOP
+ MADDAy.xyz ACC, VF19, VF02 NOP
+ MADDz.xyz VF02, VF20, VF02 NOP
+ MULAx.xyz ACC, VF18, VF03 NOP
+ MADDAy.xyz ACC, VF19, VF03 NOP
+ MADDz.xyz VF03, VF20, VF03 NOP
+ MULAx.xyz ACC, VF18, VF04 NOP
+ MADDAy.xyz ACC, VF19, VF04 NOP
+ MADDz.xyz VF04, VF20, VF04 NOP
+ ABS.xyz VF05, VF01 NOP
+ ABS.xyz VF06, VF02 NOP
+ ABS.xyz VF07, VF03 NOP
+ ABS.xyz VF08, VF04 NOP
+ NOP NOP
+ MAX.xyz VF05, VF05, VF06 NOP
+ NOP NOP
+ MAX.xyz VF07, VF07, VF08 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ MAX.xyz VF05, VF05, VF07 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ ADD.xyz VF09, VF05, VF12 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ MULx.w VF05, VF00, VF09 NOP
+ MULy.w VF06, VF00, VF09 NOP
+ MULz.w VF07, VF00, VF09 NOP
+ CLIPw.xyz VF21, VF05 NOP
+ CLIPw.xyz VF21, VF06 NOP
+ CLIPw.xyz VF21, VF07 NOP
+ NOP NOP
+ NOP NOP
+ NOP NOP
+ NOP FCAND VI01, 0x3330
+ NOP IBNE VI01, VI00, QuitAndFail2
+ NOP NOP
+ SUB.xyz VF06, VF02, VF01 NOP
+ SUB.xyz VF07, VF03, VF01 NOP
+ ADD.xyz VF08, VF04, VF01 NOP
+ ADD.x VF09, VF00, VF12 NOP
+ ADD.yz VF09, VF00, VF00 NOP
+ ADD.y VF10, VF00, VF12 NOP
+ ADD.xz VF10, VF00, VF00 NOP
+ ADD.z VF11, VF00, VF12 IADDI VI04, VI00, 0x0
+ ADD.xy VF11, VF00, VF00 IADD VI02, VI00, VI00
+ OPMULA.xyz ACC, VF06, VF09 NOP
+ OPMSUB.xyz VF01, VF09, VF06 NOP
+ OPMULA.xyz ACC, VF06, VF10 NOP
+ OPMSUB.xyz VF02, VF10, VF06 NOP
+ OPMULA.xyz ACC, VF06, VF11 NOP
+ OPMSUB.xyz VF03, VF11, VF06 SQI.xyzw VF01, (VI02++)
+ OPMULA.xyz ACC, VF07, VF09 NOP
+ OPMSUB.xyz VF01, VF09, VF07 SQI.xyzw VF02, (VI02++)
+ OPMULA.xyz ACC, VF07, VF10 NOP
+ OPMSUB.xyz VF02, VF10, VF07 SQI.xyzw VF03, (VI02++)
+ OPMULA.xyz ACC, VF07, VF11 NOP
+ OPMSUB.xyz VF03, VF11, VF07 SQI.xyzw VF01, (VI02++)
+ OPMULA.xyz ACC, VF08, VF09 NOP
+ OPMSUB.xyz VF01, VF09, VF08 SQI.xyzw VF02, (VI02++)
+ OPMULA.xyz ACC, VF08, VF10 NOP
+ OPMSUB.xyz VF02, VF10, VF08 SQI.xyzw VF03, (VI02++)
+ OPMULA.xyz ACC, VF08, VF11 LOI 0.5
+ OPMSUB.xyz VF01, VF11, VF08 SQI.xyzw VF01, (VI02++)
+ MULi.xyz VF06, VF06, I NOP
+ MULi.xyz VF07, VF07, I SQI.xyzw VF02, (VI02++)
+ MULi.xyz VF08, VF08, I NOP
+ MUL.xyz VF02, VF21, VF01 NOP
+ MUL.xyz VF03, VF12, VF01 NOP
+ MUL.xyz VF09, VF06, VF01 NOP
+ MUL.xyz VF10, VF07, VF01 NOP
+ MUL.xyz VF11, VF08, VF01 NOP
+ ABS.xyz VF03, VF03 NOP
+ ADDy.x VF05, VF09, VF09 NOP
+ ADDx.y VF05, VF10, VF10 NOP
+ ADDx.z VF05, VF11, VF11 NOP
+ NOP NOP
+EdgePairLoop:
+ ADDz.x VF05, VF05, VF09 NOP
+ ADDz.y VF05, VF05, VF10 NOP
+ ADDy.z VF05, VF05, VF11 NOP
+ MULAx.w ACC, VF00, VF02 IADD VI03, VI02, VI00
+ MADDAy.w ACC, VF00, VF02 LQD.xyzw VF01, (--VI02)
+ MADDz.w VF02, VF00, VF02 NOP
+ ABS.xyz VF05, VF05 NOP
+ MULAx.w ACC, VF00, VF03 NOP
+ MADDAy.w ACC, VF00, VF03 NOP
+ MADDAz.w ACC, VF00, VF03 NOP
+ MADDAx.w ACC, VF00, VF05 NOP
+ MADDAy.w ACC, VF00, VF05 NOP
+ MADDz.w VF03, VF00, VF05 NOP
+ ADDw.x VF04, VF00, VF02 NOP
+ MUL.xyz VF02, VF21, VF01 NOP
+ MUL.xyz VF03, VF12, VF01 NOP
+ MUL.xyz VF09, VF06, VF01 NOP
+ CLIPw.xyz VF04, VF03 NOP
+ MUL.xyz VF10, VF07, VF01 NOP
+ MUL.xyz VF11, VF08, VF01 NOP
+ ABS.xyz VF03, VF03 NOP
+ ADDy.x VF05, VF09, VF09 FCAND VI01, 0x3
+ ADDx.y VF05, VF10, VF10 IBNE VI01, VI00, QuitAndFail2
+ ADDx.z VF05, VF11, VF11 NOP
+ NOP IBNE VI03, VI00, EdgePairLoop
+ NOP NOP
+ NOP[E] IADDIU VI01, VI00, 0x1
+ NOP NOP
+
+EndOfMicrocode2:
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index e9332e8a..b27284bc 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -445,7 +445,7 @@ CEntity::PreRender(void)
gpShadowExplosionTex, &pos,
8.0f, 0.0f, 0.0f, -8.0f,
255, 200.0f*flicker, 160.0f*flicker, 120.0f*flicker,
- 20.0f, false, 1.0f);
+ 20.0f, false, 1.0f, nil, false);
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
8.0f,
@@ -483,7 +483,7 @@ CEntity::PreRender(void)
CTimeCycle::GetShadowStrength(),
CTimeCycle::GetShadowStrength(),
CTimeCycle::GetShadowStrength(),
- 20.0f, false, 1.0f);
+ 20.0f, false, 1.0f, nil, false);
}
// fall through
case ENTITY_TYPE_DUMMY:
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index 2d721e93..73870fe5 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -29,6 +29,15 @@ public:
if(m_hasRwMatrix && m_attachment)
RwMatrixDestroy(m_attachment);
}
+#ifdef RWCORE_H
+ operator RwMatrix (void) const {
+ return m_matrix;
+ }
+
+ operator RwMatrix *(void) {
+ return &m_matrix;
+ }
+#endif
void Attach(RwMatrix *matrix, bool owner = false){
#ifdef FIX_BUGS
if(m_attachment && m_hasRwMatrix)
@@ -81,6 +90,7 @@ public:
m_matrix.pos.z += rhs.m_matrix.pos.z;
return *this;
}
+ CMatrix& operator*=(CMatrix const &rhs);
const CVector &GetPosition(void) const { return *(CVector*)&m_matrix.pos; }
CVector& GetPosition(void) { return *(CVector*)&m_matrix.pos; }
@@ -240,6 +250,15 @@ public:
void CopyOnlyMatrix(CMatrix *other){
m_matrix = other->m_matrix;
}
+ void CopyRwMatrix(RwMatrix *matrix){
+ m_matrix = *matrix;
+ }
+
+ void CopyToRwMatrix(RwMatrix *matrix){
+ *matrix = m_matrix;
+ RwMatrixUpdate(matrix);
+ }
+
void SetUnity(void) {
m_matrix.right.x = 1.0f;
m_matrix.right.y = 0.0f;
diff --git a/src/math/VuVector.h b/src/math/VuVector.h
new file mode 100644
index 00000000..f90818e0
--- /dev/null
+++ b/src/math/VuVector.h
@@ -0,0 +1,41 @@
+#pragma once
+
+class TYPEALIGN(16) CVuVector : public CVector
+{
+public:
+ float w;
+ CVuVector(void) {}
+ CVuVector(float x, float y, float z) : CVector(x, y, z) {}
+ CVuVector(float x, float y, float z, float w) : CVector(x, y, z), w(w) {}
+ CVuVector(const CVector &v) : CVector(v.x, v.y, v.z) {}
+#ifdef RWCORE_H
+ CVuVector(const RwV3d &v) : CVector(v.x, v.y, v.z) {}
+
+ operator RwV3d (void) const {
+ RwV3d vecRw = { this->x, this->y, this->z };
+ return vecRw;
+ }
+
+ operator RwV3d *(void) {
+ return (RwV3d*)this;
+ }
+#endif
+/*
+ void Normalise(void) {
+ float sq = MagnitudeSqr();
+ // TODO: VU0 code
+ if(sq > 0.0f){
+ float invsqrt = RecipSqrt(sq);
+ x *= invsqrt;
+ y *= invsqrt;
+ z *= invsqrt;
+ }else
+ x = 1.0f;
+ }
+*/
+};
+
+void TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in);
+void TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in);
+void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride);
+void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in);
diff --git a/src/math/math.cpp b/src/math/math.cpp
index 0661dcac..d231b147 100644
--- a/src/math/math.cpp
+++ b/src/math/math.cpp
@@ -1,9 +1,124 @@
#include "common.h"
#include "Quaternion.h"
+#include "VuVector.h"
// TODO: move more stuff into here
+
+void TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in)
+{
+#ifdef GTA_PS2
+ __asm__ __volatile__("\n\
+ lqc2 vf01,0x0(%2)\n\
+ lqc2 vf02,0x0(%1)\n\
+ lqc2 vf03,0x10(%1)\n\
+ lqc2 vf04,0x20(%1)\n\
+ lqc2 vf05,0x30(%1)\n\
+ vmulax.xyz ACC, vf02,vf01\n\
+ vmadday.xyz ACC, vf03,vf01\n\
+ vmaddaz.xyz ACC, vf04,vf01\n\
+ vmaddw.xyz vf06,vf05,vf00\n\
+ sqc2 vf06,0x0(%0)\n\
+ ": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
+#else
+ out = mat * in;
+#endif
+}
+
+void TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in)
+{
+#ifdef GTA_PS2
+ __asm__ __volatile__("\n\
+ ldr $8,0x0(%2)\n\
+ ldl $8,0x7(%2)\n\
+ lw $9,0x8(%2)\n\
+ pcpyld $10,$9,$8\n\
+ qmtc2 $10,vf01\n\
+ lqc2 vf02,0x0(%1)\n\
+ lqc2 vf03,0x10(%1)\n\
+ lqc2 vf04,0x20(%1)\n\
+ lqc2 vf05,0x30(%1)\n\
+ vmulax.xyz ACC, vf02,vf01\n\
+ vmadday.xyz ACC, vf03,vf01\n\
+ vmaddaz.xyz ACC, vf04,vf01\n\
+ vmaddw.xyz vf06,vf05,vf00\n\
+ sqc2 vf06,0x0(%0)\n\
+ ": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
+#else
+ out = mat * in;
+#endif
+}
+
+void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride)
+{
+#ifdef GTA_PS3
+ __asm__ __volatile__("\n\
+ paddub $3,%4,$0\n\
+ lqc2 vf02,0x0(%2)\n\
+ lqc2 vf03,0x10(%2)\n\
+ lqc2 vf04,0x20(%2)\n\
+ lqc2 vf05,0x30(%2)\n\
+ ldr $8,0x0(%3)\n\
+ ldl $8,0x7(%3)\n\
+ lw $9,0x8(%3)\n\
+ pcpyld $10,$9,$8\n\
+ qmtc2 $10,vf01\n\
+ 1: vmulax.xyz ACC, vf02,vf01\n\
+ vmadday.xyz ACC, vf03,vf01\n\
+ vmaddaz.xyz ACC, vf04,vf01\n\
+ vmaddw.xyz vf06,vf05,vf00\n\
+ add %3,%3,$3\n\
+ ldr $8,0x0(%3)\n\
+ ldl $8,0x7(%3)\n\
+ lw $9,0x8(%3)\n\
+ pcpyld $10,$9,$8\n\
+ qmtc2 $10,vf01\n\
+ addi %1,%1,-1\n\
+ addiu %0,%0,0x10\n\
+ sqc2 vf06,-0x10(%0)\n\
+ bnez %1,1b\n\
+ ": : "r" (out) , "r" (n), "r" (&mat), "r" (in), "r" (stride): "memory");
+#else
+ while(n--){
+ *out = mat * *in;
+ in = (RwV3d*)((uint8*)in + stride);
+ out++;
+ }
+#endif
+}
+
+void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in)
+{
+#ifdef GTA_PS2
+ __asm__ __volatile__("\n\
+ lqc2 vf02,0x0(%2)\n\
+ lqc2 vf03,0x10(%2)\n\
+ lqc2 vf04,0x20(%2)\n\
+ lqc2 vf05,0x30(%2)\n\
+ lqc2 vf01,0x0(%3)\n\
+ nop\n\
+ 1: vmulax.xyz ACC, vf02,vf01\n\
+ vmadday.xyz ACC, vf03,vf01\n\
+ vmaddaz.xyz ACC, vf04,vf01\n\
+ vmaddw.xyz vf06,vf05,vf00\n\
+ lqc2 vf01,0x10(%3)\n\
+ addiu %3,%3,0x10\n\
+ addi %1,%1,-1\n\
+ addiu %0,%0,0x10\n\
+ sqc2 vf06,-0x10(%0)\n\
+ bnez %1,1b\n\
+ ": : "r" (out) , "r" (n), "r" (&mat) ,"r" (in): "memory");
+#else
+ while(n--){
+ *out = mat * *in;
+ in++;
+ out++;
+ }
+#endif
+}
+
+
void
CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
{
@@ -74,6 +189,7 @@ CMatrix::Reorthogonalise(void)
CMatrix&
Invert(const CMatrix &src, CMatrix &dst)
{
+ // TODO: VU0 code
// GTA handles this as a raw 4x4 orthonormal matrix
// and trashes the RW flags, let's not do that
// actual copy of librw code:
@@ -104,6 +220,7 @@ Invert(const CMatrix &src, CMatrix &dst)
CVector
operator*(const CMatrix &mat, const CVector &vec)
{
+ // TODO: VU0 code
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z + mat.m_matrix.pos.x,
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z + mat.m_matrix.pos.y,
@@ -113,6 +230,7 @@ operator*(const CMatrix &mat, const CVector &vec)
CMatrix
operator*(const CMatrix &m1, const CMatrix &m2)
{
+ // TODO: VU0 code
CMatrix out;
RwMatrix *dst = &out.m_matrix;
const RwMatrix *src1 = &m1.m_matrix;
@@ -132,9 +250,18 @@ operator*(const CMatrix &m1, const CMatrix &m2)
return out;
}
+CMatrix&
+CMatrix::operator*=(CMatrix const &rhs)
+{
+ // TODO: VU0 code
+ *this = *this * rhs;
+ return *this;
+}
+
const CVector
Multiply3x3(const CMatrix &mat, const CVector &vec)
{
+ // TODO: VU0 code
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z,
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z,
@@ -166,6 +293,7 @@ CQuaternion::Slerp(const CQuaternion &q1, const CQuaternion &q2, float theta, fl
w1 = Sin((1.0f - t) * theta) * invSin;
w2 = Sin(t * theta) * invSin;
}
+ // TODO: VU0 code
*this = w1*q1 + w2*q2;
}
}
diff --git a/src/objects/CutsceneObject.cpp b/src/objects/CutsceneObject.cpp
index adfec37c..8d1be357 100644
--- a/src/objects/CutsceneObject.cpp
+++ b/src/objects/CutsceneObject.cpp
@@ -11,7 +11,11 @@
#include "ModelIndices.h"
#include "Shadows.h"
#include "Timecycle.h"
+#include "CutsceneShadow.h"
#include "CutsceneObject.h"
+#include "ModelIndices.h"
+#include "RpAnimBlend.h"
+
CCutsceneObject::CCutsceneObject(void)
{
@@ -21,6 +25,19 @@ CCutsceneObject::CCutsceneObject(void)
ObjectCreatedBy = CUTSCENE_OBJECT;
m_fMass = 1.0f;
m_fTurnMass = 1.0f;
+
+ m_pAttachTo = nil;
+ m_pAttachmentObject = nil;
+ m_pShadow = nil;
+}
+
+CCutsceneObject::~CCutsceneObject(void)
+{
+ if ( m_pShadow )
+ {
+ delete m_pShadow;
+ m_pShadow = nil;
+ }
}
void
@@ -34,21 +51,37 @@ CCutsceneObject::SetModelIndex(uint32 id)
}
void
+CCutsceneObject::CreateShadow(void)
+{
+ if ( IsPedModel(GetModelIndex()) )
+ {
+ m_pShadow = new CCutsceneShadow();
+ if (!m_pShadow->IsInitialized())
+ m_pShadow->Create(m_rwObject, 6, true, 4, true);
+ }
+}
+
+void
CCutsceneObject::ProcessControl(void)
{
CPhysical::ProcessControl();
- if(CTimer::GetTimeStep() < 1/100.0f)
- m_vecMoveSpeed *= 100.0f;
+ if ( m_pAttachTo )
+ {
+ if ( m_pAttachmentObject )
+ GetMatrix() = CMatrix((RwMatrix*)m_pAttachTo);
+ else
+ GetMatrix() = CMatrix(RwFrameGetLTM((RwFrame*)m_pAttachTo));
+ }
else
- m_vecMoveSpeed *= 1.0f/CTimer::GetTimeStep();
-
- ApplyMoveSpeed();
-
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump()))
- UpdateRpHAnim();
-#endif
+ {
+ if(CTimer::GetTimeStep() < 1/100.0f)
+ m_vecMoveSpeed *= 100.0f;
+ else
+ m_vecMoveSpeed *= 1.0f/CTimer::GetTimeStep();
+
+ ApplyMoveSpeed();
+ }
}
static RpMaterial*
@@ -61,14 +94,52 @@ MaterialSetAlpha(RpMaterial *material, void *data)
void
CCutsceneObject::PreRender(void)
{
- if(IsPedModel(GetModelIndex())){
- CShadows::StoreShadowForPedObject(this,
- CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue],
- CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue],
- CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue],
- CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue],
- CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue],
- CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]);
+ if ( m_pAttachTo )
+ {
+ if ( m_pAttachmentObject )
+ {
+ m_pAttachmentObject->UpdateRpHAnim();
+ GetMatrix() = CMatrix((RwMatrix*)m_pAttachTo);
+ }
+ else
+ GetMatrix() = CMatrix(RwFrameGetLTM((RwFrame*)m_pAttachTo));
+
+ if ( RwObjectGetType(m_rwObject) == rpCLUMP && IsClumpSkinned(GetClump()) )
+ {
+ RpAtomic *atomic = GetFirstAtomic(GetClump());
+ atomic->boundingSphere.center = (*RPANIMBLENDCLUMPDATA(GetClump()))->frames[0].hanimFrame->t;
+ }
+ }
+
+ if ( RwObjectGetType(m_rwObject) == rpCLUMP )
+ UpdateRpHAnim();
+
+ if(IsPedModel(GetModelIndex()))
+ {
+ if ( m_pShadow == nil )
+ {
+ CShadows::StoreShadowForPedObject(this,
+ CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]);
+ }
+ else
+ {
+ if ( m_pShadow->IsInitialized() )
+ m_pShadow->UpdateForCutscene();
+
+ CShadows::StoreShadowForCutscenePedObject(this,
+ CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue],
+ CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]);
+ }
+
// For some reason xbox/android limbs are transparent here...
RpGeometry *geometry = RpAtomicGetGeometry(GetFirstAtomic(GetClump()));
RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
@@ -79,7 +150,9 @@ CCutsceneObject::PreRender(void)
void
CCutsceneObject::Render(void)
{
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void *)rwCULLMODECULLNONE);
CObject::Render();
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void *)rwCULLMODECULLBACK);
}
bool
diff --git a/src/objects/CutsceneObject.h b/src/objects/CutsceneObject.h
index bb642f3e..af24c0a6 100644
--- a/src/objects/CutsceneObject.h
+++ b/src/objects/CutsceneObject.h
@@ -2,12 +2,20 @@
#include "Object.h"
+class CCutsceneShadow;
+
class CCutsceneObject : public CObject
{
public:
+ CCutsceneShadow *m_pShadow;
+ void *m_pAttachTo;
+ CObject *m_pAttachmentObject;
+
CCutsceneObject(void);
+ ~CCutsceneObject(void);
void SetModelIndex(uint32 id);
+ void CreateShadow(void);
void ProcessControl(void);
void PreRender(void);
void Render(void);
diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp
index b2a77bc5..6ed74214 100644
--- a/src/objects/ParticleObject.cpp
+++ b/src/objects/ParticleObject.cpp
@@ -124,8 +124,6 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe
{
CParticleObject *pobj = pUnusedListHead;
- ASSERT(pobj != nil);
-
if ( pobj == nil )
{
printf("Error: No particle objects available!\n");
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index f6624c1f..a1c03024 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -64,6 +64,7 @@
#include "GameLogic.h"
#include "Bike.h"
#include "WindModifiers.h"
+#include "CutsceneShadow.h"
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
@@ -147,6 +148,9 @@ void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((
// --MIAMI: Done
CPed::~CPed(void)
{
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+ if ( m_pRTShadow ) delete m_pRTShadow;
+#endif
CWorld::Remove(this);
if (m_attractor)
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
@@ -204,6 +208,9 @@ CPed::FlagToDestroyWhenNextProcessed(void)
CPed::CPed(uint32 pedType) : m_pedIK(this)
{
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+ m_pRTShadow = nil;
+#endif
m_type = ENTITY_TYPE_PED;
bPedPhysics = true;
bUseCollisionRecords = true;
@@ -2782,12 +2789,16 @@ CPed::SetModelIndex(uint32 mi)
// This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
(*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
-#ifdef PED_SKIN
if(modelInfo->GetHitColModel() == nil)
modelInfo->CreateHitColModelSkinned(GetClump());
- if (IsClumpSkinned(GetClump())) // condition isn't there in VC
- UpdateRpHAnim();
+ UpdateRpHAnim();
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+ if (!m_pRTShadow)
+ {
+ m_pRTShadow = new CCutsceneShadow;
+ m_pRTShadow->Create(m_rwObject, 10, 1, 1, 1);
+ }
#endif
}
@@ -16421,16 +16432,16 @@ CPed::PreRender(void)
&& !CCullZones::PlayerNoRain() && GetPedState() != PED_DRIVING)
bIsWindModifierTurnedOn = true;
- bool bIsPlayerDrivingBikeOrOpenTopCar = false;
+ bool bIsPedDrivingBikeOrOpenTopCar = false;
if (GetPedState() == PED_DRIVING && m_pMyVehicle) {
if (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE
|| (m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR && m_pMyVehicle->IsOpenTopCar()))
- bIsPlayerDrivingBikeOrOpenTopCar = true;
+ bIsPedDrivingBikeOrOpenTopCar = true;
}
- if (bIsWindModifierTurnedOn || bIsPlayerDrivingBikeOrOpenTopCar) {
+ if (bIsWindModifierTurnedOn || bIsPedDrivingBikeOrOpenTopCar) {
float fWindMult = 0.0f;
- if (bIsPlayerDrivingBikeOrOpenTopCar) {
+ if (bIsPedDrivingBikeOrOpenTopCar) {
fWindMult = DotProduct(m_pMyVehicle->m_vecMoveSpeed, GetForward());
if (fWindMult > 0.4f) {
float volume = (fWindMult - 0.4f) / 0.6f;
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index b3d2f71c..6b0cc5fb 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -363,6 +363,9 @@ class CVehicle;
class CPed : public CPhysical
{
public:
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+ class CCutsceneShadow *m_pRTShadow;
+#endif
// 0x128
CStoredCollPoly m_collPoly;
float m_fCollisionSpeed;
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index 70caf1f2..f7e0973f 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -1004,7 +1004,11 @@ CPopulation::ManagePopulation(void)
}
int pedPoolSize = CPools::GetPedPool()->GetSize();
+#ifndef SQUEEZE_PERFORMANCE
for (int poolIndex = pedPoolSize-1; poolIndex >= 0; poolIndex--) {
+#else
+ for (int poolIndex = (pedPoolSize * (frameMod32 + 1) / 32) - 1; poolIndex >= pedPoolSize * frameMod32 / 32; poolIndex--) {
+#endif
CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);
if (ped && !ped->IsPlayer() && ped->CanBeDeleted() && !ped->bInVehicle) {
diff --git a/src/render/Antennas.cpp b/src/render/Antennas.cpp
index 452069a0..b9da95cb 100644
--- a/src/render/Antennas.cpp
+++ b/src/render/Antennas.cpp
@@ -2,6 +2,8 @@
#include "Antennas.h"
+//--MIAMI: file done
+
CAntenna CAntennas::aAntennas[NUMANTENNAS];
void
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index efe486fe..df5dfadb 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -2,6 +2,7 @@
#include "main.h"
#include "General.h"
+#include "RenderBuffer.h"
#include "TxdStore.h"
#include "Camera.h"
#include "Sprite.h"
@@ -12,6 +13,8 @@
#include "Timecycle.h"
#include "Coronas.h"
+//--MIAMI: file done
+
struct FlareDef
{
float position;
@@ -130,13 +133,21 @@ void
CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, RwTexture *tex,
int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
- bool longDist, float nearDist)
+ bool useNearDist, float nearDist)
{
int i;
if(sq(drawDist) < (TheCamera.GetPosition() - coors).MagnitudeSqr2D())
return;
+ if(useNearDist){
+ float dist = (TheCamera.GetPosition() - coors).Magnitude();
+ if(dist < 35.0f)
+ return;
+ if(dist < 50.0f)
+ alpha *= (dist - 35.0f)/(50.0f - 35.0f);
+ }
+
for(i = 0; i < NUMCORONAS; i++)
if(aCoronas[i].id == id)
break;
@@ -189,17 +200,19 @@ CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 al
aCoronas[i].reflection = reflection;
aCoronas[i].LOScheck = LOScheck;
aCoronas[i].drawStreak = drawStreak;
+ aCoronas[i].useNearDist = useNearDist;
+ aCoronas[i].nearDist = nearDist;
}
void
CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, uint8 type,
int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
- bool longDist, float nearDist)
+ bool useNearDist, float nearDist)
{
RegisterCorona(id, red, green, blue, alpha, coors, size, drawDist,
gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle,
- longDist, nearDist);
+ useNearDist, nearDist);
}
void
@@ -258,7 +271,10 @@ CCoronas::Render(void)
CVector spriteCoors;
float spritew, spriteh;
- if(CSprite::CalcScreenCoors(aCoronas[i].coors, spriteCoors, &spritew, &spriteh, true)){
+ if(!CSprite::CalcScreenCoors(aCoronas[i].coors, spriteCoors, &spritew, &spriteh, true)){
+ aCoronas[i].offScreen = true;
+ aCoronas[i].sightClear = false;
+ }else{
aCoronas[i].offScreen = false;
if(spriteCoors.x < 0.0f || spriteCoors.y < 0.0f ||
@@ -292,10 +308,7 @@ CCoronas::Render(void)
}
- if(aCoronas[i].fadeAlpha == 0)
- continue;
-
- if(spriteCoors.z < aCoronas[i].drawDist){
+ if(aCoronas[i].fadeAlpha && spriteCoors.z < aCoronas[i].drawDist){
float recipz = 1.0f/spriteCoors.z;
float fadeDistance = aCoronas[i].drawDist / 2.0f;
float distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance;
@@ -312,7 +325,7 @@ CCoronas::Render(void)
if(CCoronas::aCoronas[i].id == SUN_CORE)
spriteCoors.z = 0.95f * RwCameraGetFarClipPlane(Scene.camera);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aCoronas[i].texture));
- spriteCoors.z -= 1.5f;
+ spriteCoors.z -= aCoronas[i].nearDist;
if(aCoronas[i].texture == gpCoronaTexture[8]){
// what's this?
@@ -370,14 +383,11 @@ CCoronas::Render(void)
recipz, 255);
}
}
- }else{
- aCoronas[i].offScreen = true;
- aCoronas[i].sightClear = false;
}
}
}
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
@@ -393,23 +403,24 @@ CCoronas::Render(void)
if(!aCoronas[i].hasValue[j] || !aCoronas[i].hasValue[j+1])
continue;
- int mod1 = (float)(6 - j) / 6 * 128;
- int mod2 = (float)(6 - (j+1)) / 6 * 128;
+ int alpha1 = (float)(6 - j) / 6 * 128;
+ int alpha2 = (float)(6 - (j+1)) / 6 * 128;
RwIm2DVertexSetScreenX(&vertexbufferX[0], aCoronas[i].prevX[j]);
RwIm2DVertexSetScreenY(&vertexbufferX[0], aCoronas[i].prevY[j]);
- RwIm2DVertexSetIntRGBA(&vertexbufferX[0], aCoronas[i].prevRed[j] * mod1 / 256, aCoronas[i].prevGreen[j] * mod1 / 256, aCoronas[i].prevBlue[j] * mod1 / 256, 255);
+ RwIm2DVertexSetIntRGBA(&vertexbufferX[0], aCoronas[i].prevRed[j] * alpha1 / 256, aCoronas[i].prevGreen[j] * alpha1 / 256, aCoronas[i].prevBlue[j] * alpha1 / 256, 255);
RwIm2DVertexSetScreenX(&vertexbufferX[1], aCoronas[i].prevX[j+1]);
RwIm2DVertexSetScreenY(&vertexbufferX[1], aCoronas[i].prevY[j+1]);
- RwIm2DVertexSetIntRGBA(&vertexbufferX[1], aCoronas[i].prevRed[j+1] * mod2 / 256, aCoronas[i].prevGreen[j+1] * mod2 / 256, aCoronas[i].prevBlue[j+1] * mod2 / 256, 255);
+ RwIm2DVertexSetIntRGBA(&vertexbufferX[1], aCoronas[i].prevRed[j+1] * alpha2 / 256, aCoronas[i].prevGreen[j+1] * alpha2 / 256, aCoronas[i].prevBlue[j+1] * alpha2 / 256, 255);
- // BUG: game doesn't do this
+#ifdef FIX_BUGS
RwIm2DVertexSetScreenZ(&vertexbufferX[0], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&vertexbufferX[0], RwCameraGetNearClipPlane(Scene.camera));
RwIm2DVertexSetRecipCameraZ(&vertexbufferX[0], 1.0f/RwCameraGetNearClipPlane(Scene.camera));
RwIm2DVertexSetScreenZ(&vertexbufferX[1], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&vertexbufferX[1], RwCameraGetNearClipPlane(Scene.camera));
RwIm2DVertexSetRecipCameraZ(&vertexbufferX[1], 1.0f/RwCameraGetNearClipPlane(Scene.camera));
+#endif
RwIm2DRenderLine(vertexbufferX, 2, 0, 1);
}
@@ -428,6 +439,8 @@ CCoronas::RenderReflections(void)
CEntity *entity;
if(CWeather::WetRoads > 0.0f){
+ CSprite::InitSpriteBuffer();
+
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
@@ -438,7 +451,8 @@ CCoronas::RenderReflections(void)
for(i = 0; i < NUMCORONAS; i++){
if(aCoronas[i].id == 0 ||
- aCoronas[i].fadeAlpha == 0 && aCoronas[i].alpha == 0)
+ aCoronas[i].fadeAlpha == 0 && aCoronas[i].alpha == 0 ||
+ aCoronas[i].reflection == 0)
continue;
// check if we want a reflection on this corona
@@ -453,11 +467,8 @@ CCoronas::RenderReflections(void)
}
}
- if(!aCoronas[i].renderReflection)
- continue;
-
// Don't draw if reflection is too high
- if(aCoronas[i].heightAboveRoad < 20.0f){
+ if(aCoronas[i].renderReflection && aCoronas[i].heightAboveRoad < 20.0f){
// don't draw if camera is below road
if(CCoronas::aCoronas[i].coors.z - aCoronas[i].heightAboveRoad > TheCamera.GetPosition().z)
continue;
@@ -469,13 +480,14 @@ CCoronas::RenderReflections(void)
float spritew, spriteh;
if(CSprite::CalcScreenCoors(coors, spriteCoors, &spritew, &spriteh, true)){
float drawDist = 0.75f * aCoronas[i].drawDist;
- drawDist = Min(drawDist, 50.0f);
+ drawDist = Min(drawDist, 55.0f);
if(spriteCoors.z < drawDist){
float fadeDistance = drawDist / 2.0f;
float distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance;
distanceFade = clamp(distanceFade, 0.0f, 1.0f);
float recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera);
- int intensity = (20.0f - aCoronas[i].heightAboveRoad) * 230.0 * distanceFade*CWeather::WetRoads * 0.05f;
+ float heightFade = (20.0f - aCoronas[i].heightAboveRoad)/20.0f;
+ int intensity = distanceFade*heightFade * 230.0 * CWeather::WetRoads;
CSprite::RenderBufferedOneXLUSprite(
spriteCoors.x, spriteCoors.y, RwIm2DGetNearScreenZ(),
@@ -504,6 +516,130 @@ CCoronas::RenderReflections(void)
}
}
+void
+CCoronas::RenderSunReflection(void)
+{
+ float sunZDir = CTimeCycle::GetSunDirection().z;
+ if(sunZDir > -0.05f){
+ float intensity = (0.3f - Abs(sunZDir - 0.25f))/0.3f *
+ (1.0f - CWeather::CloudCoverage) *
+ (1.0f - CWeather::Foggyness) *
+ (1.0f - CWeather::Wind);
+ if(intensity > 0.0f){
+ int r = (CTimeCycle::GetSunCoreRed() + CTimeCycle::GetSunCoronaRed())*intensity*0.25f;
+ int g = (CTimeCycle::GetSunCoreGreen() + CTimeCycle::GetSunCoronaGreen())*intensity*0.25f;
+ int b = (CTimeCycle::GetSunCoreBlue() + CTimeCycle::GetSunCoronaBlue())*intensity*0.25f;
+
+ CVector sunPos = 40.0f*CTimeCycle::GetSunDirection() + TheCamera.GetPosition();
+ sunPos.z = 0.5f*CWeather::Wind + 6.1f;
+ CVector sunDir = CTimeCycle::GetSunDirection();
+ sunDir.z = 0.0;
+ sunDir.Normalise();
+
+ TempBufferIndicesStored = 6;
+ TempBufferRenderIndexList[0] = 2;
+ TempBufferRenderIndexList[1] = 1;
+ TempBufferRenderIndexList[2] = 0;
+ TempBufferRenderIndexList[3] = 2;
+ TempBufferRenderIndexList[4] = 3;
+ TempBufferRenderIndexList[5] = 1;
+
+ // 60 unit square in sun direction
+ TempBufferVerticesStored = 4;
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[0],
+ sunPos.x + 30.0f*sunDir.y,
+ sunPos.y - 30.0f*sunDir.x,
+ sunPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[1],
+ sunPos.x - 30.0f*sunDir.y,
+ sunPos.y + 30.0f*sunDir.x,
+ sunPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[2], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[2],
+ sunPos.x + 60.0f*sunDir.x + 30.0f*sunDir.y,
+ sunPos.y + 60.0f*sunDir.y - 30.0f*sunDir.x,
+ sunPos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[3], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[3],
+ sunPos.x + 60.0f*sunDir.x - 30.0f*sunDir.y,
+ sunPos.y + 60.0f*sunDir.y + 30.0f*sunDir.x,
+ sunPos.z);
+
+ RwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[0], 1.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[1], 1.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[2], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[2], 0.5f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[3], 1.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[3], 0.5f);
+
+ int timeInc = 0;
+ int sideInc = 0;
+ int fwdInc = 0;
+ for(int i = 0; i < 20; i++){
+ TempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored-1;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored-2;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored+1;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored-1;
+ TempBufferIndicesStored += 6;
+
+ // What a weird way to do it...
+ float fwdLen = fwdInc/20 + 60;
+ float sideLen = sideInc/20 + 30;
+ sideLen += 10.0f*Sin((float)(CTimer::GetTimeInMilliseconds()+timeInc & 0x7FF)/0x800*TWOPI);
+ timeInc += 900;
+ sideInc += 970;
+ fwdInc += 1440;
+
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0],
+ sunPos.x + fwdLen*sunDir.x + sideLen*sunDir.y,
+ sunPos.y + fwdLen*sunDir.y - sideLen*sunDir.x,
+ sunPos.z);
+
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], r, g, b, 255);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1],
+ sunPos.x + fwdLen*sunDir.x - sideLen*sunDir.x,
+ sunPos.y + fwdLen*sunDir.y + sideLen*sunDir.y,
+ sunPos.z);
+
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.5f);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 0.5f);
+ TempBufferVerticesStored += 2;
+ }
+
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[4]));
+ if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
+ RwIm3DEnd();
+ }
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+ }
+ }
+}
+
void
CCoronas::DoSunAndMoon(void)
{
@@ -520,7 +656,7 @@ CCoronas::DoSunAndMoon(void)
255, sunCoors, size,
999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f);
- if(CTimeCycle::GetSunDirection().z > 0.0f)
+ if(CTimeCycle::GetSunDirection().z > 0.0f && !CGame::IsInInterior())
RegisterCorona(SUN_CORONA,
CTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(),
255, sunCoors, 25.0f * CTimeCycle::GetSunSize(),
diff --git a/src/render/Coronas.h b/src/render/Coronas.h
index cb4e8583..45f027d8 100644
--- a/src/render/Coronas.h
+++ b/src/render/Coronas.h
@@ -4,19 +4,21 @@ extern RwTexture *gpCoronaTexture[9];
struct CRegisteredCorona
{
+ CVector coors;
uint32 id;
uint32 lastLOScheck;
RwTexture *texture;
+ float size;
+ float someAngle;
+ float drawDist;
+ float nearDist;
+ float heightAboveRoad;
uint8 red;
uint8 green;
uint8 blue;
uint8 alpha; // alpha when fully visible
uint8 fadeAlpha; // actual value used for rendering, faded
- CVector coors;
- float size;
- float someAngle;
bool registeredThisFrame;
- float drawDist;
int8 flareType;
int8 reflection;
@@ -25,12 +27,11 @@ struct CRegisteredCorona
uint8 firstUpdate : 1;
uint8 drawStreak : 1;
uint8 sightClear : 1;
+ uint8 useNearDist : 1;
+ uint8 renderReflection : 1;
- bool renderReflection;
- float heightAboveRoad;
-
- float prevX[6];
- float prevY[6];
+ int16 prevX[6];
+ int16 prevY[6];
uint8 prevRed[6];
uint8 prevGreen[6];
uint8 prevBlue[6];
@@ -39,7 +40,7 @@ struct CRegisteredCorona
void Update(void);
};
-VALIDATE_SIZE(CRegisteredCorona, 0x80);
+VALIDATE_SIZE(CRegisteredCorona, 0x68);
class CCoronas
{
@@ -91,13 +92,14 @@ public:
static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, RwTexture *tex,
int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
- bool longDist = false, float nearClip = 1.5f);
+ bool useNearDist = false, float nearDist = 1.5f);
static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, uint8 type,
int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,
- bool longDist = false, float nearClip = 1.5f);
+ bool useNearDist = false, float nearDist = 1.5f);
static void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle);
static void Render(void);
static void RenderReflections(void);
+ static void RenderSunReflection(void);
static void DoSunAndMoon(void);
};
diff --git a/src/render/CutsceneShadow.cpp b/src/render/CutsceneShadow.cpp
new file mode 100644
index 00000000..8cb33896
--- /dev/null
+++ b/src/render/CutsceneShadow.cpp
@@ -0,0 +1,269 @@
+#include "common.h"
+#include "main.h"
+#include "rwcore.h"
+#include "rwplcore.h"
+#include "CutsceneShadow.h"
+#include "RwHelper.h"
+
+#define DLIGHT_VALUE 0.8f /* Directional light intensity */
+
+
+CCutsceneShadow::CCutsceneShadow()
+{
+ m_pAtomic = nil;
+ m_nRwObjectType = -1;
+ m_pLight = nil;
+ m_nBlurPasses = 0;
+ m_bResample = false;
+ m_bGradient = false;
+}
+
+CCutsceneShadow::~CCutsceneShadow()
+{
+ Destroy();
+}
+
+bool
+CCutsceneShadow::Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient)
+{
+ ASSERT(object != nil);
+
+ RwRGBAReal color;
+ RwFrame *frame;
+
+ if (!object)
+ return false;
+
+ m_pLight = RpLightCreate(rpLIGHTDIRECTIONAL);
+ ASSERT(m_pLight != nil);
+
+ if (!m_pLight)
+ return false;
+
+ color.red = color.green = color.blue = DLIGHT_VALUE;
+ color.alpha = 0.0f;
+
+ RpLightSetColor(m_pLight, &color);
+
+ frame = RwFrameCreate();
+ ASSERT(frame != nil);
+
+ RpLightSetFrame(m_pLight, frame);
+
+ SetLightProperties(180.0f, 90.0f, false);
+
+ m_pObject = object;
+ m_nRwObjectType = RwObjectGetType(m_pObject);
+
+ switch ( m_nRwObjectType )
+ {
+ case rpCLUMP:
+ {
+ RpClumpGetBoundingSphere(m_pClump, &m_BoundingSphere, 1);
+ m_BaseSphere.radius = m_BoundingSphere.radius;
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump)));
+ break;
+ }
+
+ case rpATOMIC:
+ {
+ m_BoundingSphere = *RpAtomicGetBoundingSphere(m_pAtomic);
+ m_BaseSphere.radius = m_BoundingSphere.radius;
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));
+ break;
+ }
+
+ default:
+ {
+ Destroy();
+ return false;
+ break;
+ }
+ }
+
+ if ( !m_Camera.Create(rasterSize) )
+ {
+ Destroy();
+ return false;
+ }
+
+ m_nBlurPasses = blurPasses;
+ m_bResample = resample;
+ m_bGradient = gradient;
+
+ if ( m_bResample && !m_ResampleCamera.Create(rasterSize - 1) )
+ {
+ Destroy();
+ return false;
+ }
+
+ if ( m_nBlurPasses != 0 )
+ {
+ if ( !m_BlurCamera.Create(resample ? rasterSize - 1 : rasterSize) )
+ {
+ Destroy();
+ return false;
+ }
+ }
+
+ if ( m_bGradient )
+ {
+ if ( !m_GradientCamera.Create(resample ? rasterSize - 1 : rasterSize) )
+ {
+ Destroy();
+ return false;
+ }
+
+ m_GradientCamera.MakeGradientRaster();
+ }
+
+ m_Camera.SetLight(m_pLight);
+
+ switch ( m_nRwObjectType )
+ {
+ case rpATOMIC:
+ m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius);
+ break;
+
+ case rpCLUMP:
+ m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius);
+ break;
+ }
+
+ m_Camera.SetCenter(&m_BaseSphere.center);
+ return true;
+}
+
+RwFrame *
+CCutsceneShadow::SetLightProperties(float angleY, float angleX, bool setLight)
+{
+ ASSERT(m_pLight != nil);
+
+ RwFrame *frame;
+ static RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+ static RwV3d Yaxis = { 0.0f, 1.0f, 0.0f };
+
+ frame = RpLightGetFrame(m_pLight);
+ ASSERT(frame != nil);
+
+ if ( !frame )
+ return nil;
+
+ RwFrameRotate(frame, &Yaxis, angleY, rwCOMBINEREPLACE);
+ RwFrameRotate(frame, &Xaxis, angleX, rwCOMBINEPOSTCONCAT);
+
+ if ( setLight )
+ m_Camera.SetLight(m_pLight);
+
+ return frame;
+}
+
+bool
+CCutsceneShadow::IsInitialized()
+{
+ return m_pObject != nil;
+}
+
+void
+CCutsceneShadow::Destroy()
+{
+ m_Camera.Destroy();
+ m_ResampleCamera.Destroy();
+ m_BlurCamera.Destroy();
+ m_GradientCamera.Destroy();
+
+ m_pAtomic = nil;
+
+ m_nRwObjectType = -1;
+
+ if (m_pLight)
+ {
+ RwFrame *frame = RpLightGetFrame(m_pLight);
+ RpLightSetFrame(m_pLight, nil);
+ RwFrameDestroy(frame);
+ RpLightDestroy(m_pLight);
+ m_pLight = nil;
+ }
+}
+
+RwRaster *
+CCutsceneShadow::Update()
+{
+ switch ( m_nRwObjectType )
+ {
+ case rpCLUMP:
+ ASSERT(m_pClump != nil);
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump)));
+ break;
+
+ case rpATOMIC:
+ ASSERT(m_pAtomic != nil);
+ RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));
+ break;
+ }
+
+ m_Camera.SetCenter(&m_BaseSphere.center);
+
+ switch ( m_nRwObjectType )
+ {
+ case rpCLUMP:
+ m_Camera.Update(m_pClump);
+ break;
+
+ case rpATOMIC:
+ m_Camera.Update(m_pAtomic);
+ break;
+ }
+
+ RwRaster *raster = m_Camera.GetRwRenderRaster();
+ ASSERT(raster != nil);
+
+ if ( m_bResample )
+ return m_ResampleCamera.RasterResample(raster);
+
+ if ( m_nBlurPasses )
+ return m_BlurCamera.RasterBlur(raster, m_nBlurPasses);
+
+ if ( m_bGradient )
+ return m_GradientCamera.RasterGradient(raster);
+
+ return raster;
+}
+
+RwTexture *
+CCutsceneShadow::UpdateForCutscene()
+{
+ Update();
+ return GetShadowRwTexture();
+}
+
+CShadowCamera *
+CCutsceneShadow::GetShadowCamera(int32 camType)
+{
+ switch ( camType )
+ {
+ case RESAMPLE: return &m_ResampleCamera;
+ case BLUR: return &m_BlurCamera;
+ case GRADIENT: return &m_GradientCamera;
+ }
+
+ return &m_Camera;
+}
+
+RwTexture *
+CCutsceneShadow::GetShadowRwTexture()
+{
+ if ( m_bResample )
+ return m_ResampleCamera.GetRwRenderTexture();
+ else
+ return m_Camera.GetRwRenderTexture();
+}
+
+void
+CCutsceneShadow::DrawBorderAroundTexture(RwRGBA const& color)
+{
+ if ( m_bResample )
+ m_ResampleCamera.DrawOutlineBorder(color);
+ else
+ m_Camera.DrawOutlineBorder(color);
+} \ No newline at end of file
diff --git a/src/render/CutsceneShadow.h b/src/render/CutsceneShadow.h
new file mode 100644
index 00000000..a59fe78f
--- /dev/null
+++ b/src/render/CutsceneShadow.h
@@ -0,0 +1,52 @@
+#pragma once
+#include "ShadowCamera.h"
+
+class CCutsceneShadow
+{
+public:
+ enum
+ {
+ RASTER = 0,
+ RESAMPLE,
+ BLUR,
+ GRADIENT,
+ };
+
+ CShadowCamera m_Camera;
+ bool m_bResample;
+ CShadowCamera m_ResampleCamera;
+ int32 m_nBlurPasses;
+ CShadowCamera m_BlurCamera;
+ bool m_bGradient;
+ CShadowCamera m_GradientCamera;
+
+ union
+ {
+ RwObject *m_pObject;
+ RpAtomic *m_pAtomic;
+ RpClump *m_pClump;
+ };
+
+ int32 m_nRwObjectType;
+ RpLight *m_pLight;
+ RwSphere m_BoundingSphere;
+ RwSphere m_BaseSphere;
+
+ CCutsceneShadow();
+ ~CCutsceneShadow();
+
+ RwSphere GetBaseSphere()
+ {
+ return m_BaseSphere;
+ }
+
+ bool Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient);
+ RwFrame *SetLightProperties(float angleY, float angleX, bool setLight);
+ bool IsInitialized();
+ void Destroy();
+ RwRaster *Update();
+ RwTexture *UpdateForCutscene();
+ CShadowCamera *GetShadowCamera(int32 camType = RASTER);
+ RwTexture *GetShadowRwTexture();
+ void DrawBorderAroundTexture(RwRGBA const& color);
+};
diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp
index 5d8ccf47..14c80a63 100644
--- a/src/render/Fluff.cpp
+++ b/src/render/Fluff.cpp
@@ -7,6 +7,7 @@
#include "Camera.h"
#include "Sprite.h"
#include "Coronas.h"
+#include "PointLights.h"
#include "Rubbish.h"
#include "Timecycle.h"
#include "General.h"
@@ -391,7 +392,7 @@ void CMovingThings::Init()
CPlaneTrails::Init();
CSmokeTrails::Init();
CPlaneBanners::Init();
- CEscalators::Init();
+ CPointLights::Init();
StartCloseList.m_pNext = &CMovingThings::EndCloseList;
StartCloseList.m_pPrev = nil;
@@ -399,6 +400,8 @@ void CMovingThings::Init()
EndCloseList.m_pPrev = &CMovingThings::StartCloseList;
Num = 0;
+ CEscalators::Init();
+
#ifndef MIAMI // something is still used here actually
// Initialize scroll bars
aScrollBars[0].Init(CVector( 228.3f, -669.0f, 39.0f ), SCROLL_BUSINESS, 0.0f, 0.5f, 0.5f, 255, 128, 0, 0.3f);
diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp
index 568a0bc1..4c805d25 100644
--- a/src/render/MBlur.cpp
+++ b/src/render/MBlur.cpp
@@ -255,6 +255,11 @@ CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, u
#endif
}
+static uint8 DrunkBlurRed = 128;
+static uint8 DrunkBlurGreen = 128;
+static uint8 DrunkBlurBlue = 128;
+static int32 DrunkBlurIncrement = 1;
+
void
CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha)
{
@@ -367,7 +372,36 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type,
}
}
- // TODO(MIAMI): drunkness
+ int DrunkBlurAlpha = 175.0f * Drunkness;
+ if(DrunkBlurAlpha != 0){
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ if(BlurOn){
+ RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, DrunkBlurAlpha);
+ }else{
+ RwIm2DVertexSetIntRGBA(&Vertex[0], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);
+ if(DrunkBlurIncrement){
+ if(DrunkBlurRed < 255) DrunkBlurRed++;
+ if(DrunkBlurGreen < 255) DrunkBlurGreen++;
+ if(DrunkBlurBlue < 255) DrunkBlurBlue++;
+ if(DrunkBlurRed == 255)
+ DrunkBlurIncrement = 0;
+ }else{
+ if(DrunkBlurRed > 128) DrunkBlurRed--;
+ if(DrunkBlurGreen > 128) DrunkBlurGreen--;
+ if(DrunkBlurBlue > 128) DrunkBlurBlue--;
+ if(DrunkBlurRed == 128)
+ DrunkBlurIncrement = 1;
+ }
+ }
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+ }
// TODO(MIAMI): OverlayRenderFx
diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp
index 88b9aaea..b09b07bd 100644
--- a/src/render/PointLights.cpp
+++ b/src/render/PointLights.cpp
@@ -1,6 +1,7 @@
#include "common.h"
#include "main.h"
+#include "CutsceneMgr.h"
#include "Lights.h"
#include "Camera.h"
#include "Weather.h"
@@ -10,8 +11,23 @@
#include "Timer.h"
#include "PointLights.h"
+//--MIAMI: file done
+
int16 CPointLights::NumLights;
CRegisteredPointLight CPointLights::aLights[NUMPOINTLIGHTS];
+CVector CPointLights::aCachedMapReads[32];
+float CPointLights::aCachedMapReadResults[32];
+int32 CPointLights::NextCachedValue;
+
+void
+CPointLights::Init(void)
+{
+ for(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++){
+ aCachedMapReads[i] = CVector(0.0f, 0.0f, 0.0f);
+ aCachedMapReadResults[i] = 0.0f;
+ }
+ NextCachedValue = 0;
+}
void
CPointLights::InitPerFrame(void)
@@ -86,12 +102,11 @@ CPointLights::GenerateLightsAffectingObject(Const CVector *objCoors)
ret *= distNorm;
}else{
float intensity;
+ // distance fade
if(distNorm < 0.5f)
- // near enough
intensity = 1.0f;
else
- // attenuate
- intensity = 1.0f - (distNorm - 0.5f)*2.0f;
+ intensity = 1.0f - (distNorm - 0.5f)/(1.0f - 0.5f);
if(distance != 0.0f){
CVector dir = dist / distance;
@@ -143,17 +158,22 @@ CPointLights::RenderFogEffect(void)
CVector spriteCoors;
float spritew, spriteh;
+ if(CCutsceneMgr::IsRunning())
+ return;
+
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpPointlightRaster);
+ CSprite::InitSpriteBuffer();
+
for(i = 0; i < NumLights; i++){
if(aLights[i].fogType != FOG_NORMAL && aLights[i].fogType != FOG_ALWAYS)
continue;
- fogginess = aLights[i].fogType == FOG_ALWAYS ? 1.0f : CWeather::Foggyness;
+ fogginess = aLights[i].fogType == FOG_NORMAL ? CWeather::Foggyness : 1.0f;
if(fogginess == 0.0f)
continue;
@@ -198,7 +218,7 @@ CPointLights::RenderFogEffect(void)
float distsq = sq(dx) + sq(dy);
float linedistsq = distsq - sq(dot);
if(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){
- CVector fogcoors(xi, yi, aLights[i].coors.z + 1.0f);
+ CVector fogcoors(xi, yi, aLights[i].coors.z + 10.0f);
if(CWorld::ProcessVerticalLine(fogcoors, fogcoors.z - 20.0f,
point, entity, true, false, false, false, true, false, nil)){
// Now same check again in xyz
@@ -220,9 +240,9 @@ CPointLights::RenderFogEffect(void)
intensity *= 1.0f - sq(Sqrt(linedistsq) / FOG_AREA_WIDTH);
if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){
- float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x1FFF;
+ float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x2000;
float size = FogSizes[r>>1];
- CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * size, spriteh * size,
aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,
intensity, 1/spriteCoors.z, rotation, 255);
@@ -234,9 +254,8 @@ CPointLights::RenderFogEffect(void)
}
}else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS){
- if(CWorld::ProcessVerticalLine(aLights[i].coors, aLights[i].coors.z - 20.0f,
- point, entity, true, false, false, false, true, false, nil)){
-
+ float groundZ;
+ if(ProcessVerticalLineUsingCache(aLights[i].coors, &groundZ)){
xmin = aLights[i].coors.x - FOG_AREA_RADIUS;
ymin = aLights[i].coors.y - FOG_AREA_RADIUS;
xmax = aLights[i].coors.x + FOG_AREA_RADIUS;
@@ -267,11 +286,11 @@ CPointLights::RenderFogEffect(void)
// more intensity the closer to light source
intensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS);
- CVector fogcoors(xi, yi, point.point.z + 1.6f);
+ CVector fogcoors(xi, yi, groundZ + 1.6f);
if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){
- float rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x3FFF;
+ float rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x4000;
float size = FogSizes[r>>1];
- CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
+ CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * size, spriteh * size,
aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,
intensity, 1/spriteCoors.z, rotation, 255);
@@ -283,4 +302,27 @@ CPointLights::RenderFogEffect(void)
}
}
}
+
+ CSprite::FlushSpriteBuffer();
+}
+
+bool
+CPointLights::ProcessVerticalLineUsingCache(CVector coors, float *groundZ)
+{
+ for(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++)
+ if(aCachedMapReads[i] == coors){
+ *groundZ = aCachedMapReadResults[i];
+ return true;
+ }
+
+ CColPoint point;
+ CEntity *entity;
+ if(CWorld::ProcessVerticalLine(coors, coors.z - 20.0f, point, entity, true, false, false, false, true, false, nil)){
+ aCachedMapReads[NextCachedValue] = coors;
+ aCachedMapReadResults[NextCachedValue] = point.point.z;
+ NextCachedValue = (NextCachedValue+1) % ARRAY_SIZE(aCachedMapReads);
+ *groundZ = point.point.z;
+ return true;
+ }
+ return false;
}
diff --git a/src/render/PointLights.h b/src/render/PointLights.h
index 9e94328f..827200b9 100644
--- a/src/render/PointLights.h
+++ b/src/render/PointLights.h
@@ -20,6 +20,9 @@ class CPointLights
public:
static int16 NumLights;
static CRegisteredPointLight aLights[NUMPOINTLIGHTS];
+ static CVector aCachedMapReads[32];
+ static float aCachedMapReadResults[32];
+ static int32 NextCachedValue;
enum {
LIGHT_POINT,
@@ -37,9 +40,11 @@ public:
FOG_ALWAYS
};
+ static void Init(void);
static void InitPerFrame(void);
static void AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows);
static float GenerateLightsAffectingObject(Const CVector *objCoors);
static void RemoveLightsAffectingObject(void);
static void RenderFogEffect(void);
+ static bool ProcessVerticalLineUsingCache(CVector coors, float *groundZ);
};
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 0640f25e..03ef1064 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -74,8 +74,12 @@ CRenderer::PreRender(void)
for(i = 0; i < ms_nNoOfVisibleEntities; i++)
ms_aVisibleEntityPtrs[i]->PreRender();
- for(i = 0; i < ms_nNoOfInVisibleEntities; i++)
+ for (i = 0; i < ms_nNoOfInVisibleEntities; i++) {
+#ifdef SQUEEZE_PERFORMANCE
+ if (ms_aInVisibleEntityPtrs[i]->IsVehicle() && ((CVehicle*)ms_aInVisibleEntityPtrs[i])->IsHeli())
+#endif
ms_aInVisibleEntityPtrs[i]->PreRender();
+ }
for(node = CVisibilityPlugins::m_alphaEntityList.head.next;
node != &CVisibilityPlugins::m_alphaEntityList.tail;
diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp
index bfd50c07..dada2439 100644
--- a/src/render/Rubbish.cpp
+++ b/src/render/Rubbish.cpp
@@ -8,17 +8,18 @@
#include "World.h"
#include "Vehicle.h"
#include "ZoneCull.h"
+#include "Stats.h"
#include "TxdStore.h"
#include "RenderBuffer.h"
#include "Rubbish.h"
-#define RUBBISH_MAX_DIST (18.0f)
-#define RUBBISH_FADE_DIST (16.5f)
+//--MIAMI: file done
+
+#define RUBBISH_MAX_DIST (23.0f)
+#define RUBBISH_FADE_DIST (20.0f)
RwTexture *gpRubbishTexture[4];
RwImVertexIndex RubbishIndexList[6];
-RwImVertexIndex RubbishIndexList2[6]; // unused
-RwIm3DVertex RubbishVertices[4];
bool CRubbish::bRubbishInvisible;
int CRubbish::RubbishVisibility;
COneSheet CRubbish::aSheets[NUM_RUBBISH_SHEETS];
@@ -52,12 +53,16 @@ CRubbish::Render(void)
{
int type;
+ if(RubbishVisibility == 0)
+ return;
+
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
for(type = 0; type < 4; type++){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type]));
+ if(type < 3 || CStats::PamphletMissionPassed)
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type]));
TempBufferIndicesStored = 0;
TempBufferVerticesStored = 0;
@@ -69,7 +74,7 @@ CRubbish::Render(void)
if(sheet->m_state == 0)
continue;
- uint32 alpha = 128;
+ uint32 alpha = 100;
CVector pos;
if(sheet->m_state == 1){
pos = sheet->m_basePos;
@@ -82,7 +87,7 @@ CRubbish::Render(void)
float t = (float)(CTimer::GetTimeInMilliseconds() - sheet->m_moveStart)/sheet->m_moveDuration;
float f1 = sheet->m_isVisible ? 1.0f-t : 0.0f;
float f2 = sheet->m_targetIsVisible ? t : 0.0f;
- alpha = 128 * (f1+f2);
+ alpha = 100 * (f1+f2);
}
}
@@ -92,17 +97,27 @@ CRubbish::Render(void)
alpha -= alpha*(camDist-RUBBISH_FADE_DIST)/(RUBBISH_MAX_DIST-RUBBISH_FADE_DIST);
alpha = (RubbishVisibility*alpha)/256;
- float vx = Sin(sheet->m_angle) * 0.4f;
- float vy = Cos(sheet->m_angle) * 0.4f;
+ float vx1, vy1, vx2, vy2;
+ if(type == 0 || type == 1){
+ vx1 = 0.9f*Sin(sheet->m_angle);
+ vy1 = 0.9f*Cos(sheet->m_angle);
+ vx2 = 0.3f*Cos(sheet->m_angle);
+ vy2 = -0.3f*Sin(sheet->m_angle);
+ }else{
+ vx1 = 0.3f*Sin(sheet->m_angle);
+ vy1 = 0.3f*Cos(sheet->m_angle);
+ vx2 = 0.3f*Cos(sheet->m_angle);
+ vy2 = -0.3f*Sin(sheet->m_angle);
+ }
int v = TempBufferVerticesStored;
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx, pos.y + vy, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx1 + vx2, pos.y + vy1 + vy2, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x + vx1 - vx2, pos.y + vy1 - vy2, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x - vx1 + vx2, pos.y - vy1 + vy2, pos.z);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx1 - vx2, pos.y - vy1 - vy2, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], 255, 255, 255, alpha);
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x - vy, pos.y + vx, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], 255, 255, 255, alpha);
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x + vy, pos.y - vx, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], 255, 255, 255, alpha);
- RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx, pos.y - vy, pos.z);
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], 255, 255, 255, alpha);
RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], 0.0f);
RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], 0.0f);
@@ -373,24 +388,6 @@ CRubbish::Init(void)
EndMoversList.m_next = nil;
EndMoversList.m_prev = &StartMoversList;
- // unused
- RwIm3DVertexSetU(&RubbishVertices[0], 0.0f);
- RwIm3DVertexSetV(&RubbishVertices[0], 0.0f);
- RwIm3DVertexSetU(&RubbishVertices[1], 1.0f);
- RwIm3DVertexSetV(&RubbishVertices[1], 0.0f);
- RwIm3DVertexSetU(&RubbishVertices[2], 0.0f);
- RwIm3DVertexSetV(&RubbishVertices[2], 1.0f);
- RwIm3DVertexSetU(&RubbishVertices[3], 1.0f);
- RwIm3DVertexSetV(&RubbishVertices[3], 1.0f);
-
- // unused
- RubbishIndexList2[0] = 0;
- RubbishIndexList2[1] = 2;
- RubbishIndexList2[2] = 1;
- RubbishIndexList2[3] = 1;
- RubbishIndexList2[4] = 2;
- RubbishIndexList2[5] = 3;
-
RubbishIndexList[0] = 0;
RubbishIndexList[1] = 1;
RubbishIndexList[2] = 2;
@@ -414,19 +411,11 @@ void
CRubbish::Shutdown(void)
{
RwTextureDestroy(gpRubbishTexture[0]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[0] = nil;
-#endif
RwTextureDestroy(gpRubbishTexture[1]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[1] = nil;
-#endif
RwTextureDestroy(gpRubbishTexture[2]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[2] = nil;
-#endif
RwTextureDestroy(gpRubbishTexture[3]);
-#ifdef GTA3_1_1_PATCH
gpRubbishTexture[3] = nil;
-#endif
}
diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h
index 52050e20..5a4e479b 100644
--- a/src/render/Rubbish.h
+++ b/src/render/Rubbish.h
@@ -4,7 +4,11 @@ class CVehicle;
enum {
// NB: not all values are allowed, check the code
+#ifdef SQUEEZE_PERFORMANCE
+ NUM_RUBBISH_SHEETS = 32
+#else
NUM_RUBBISH_SHEETS = 64
+#endif
};
class COneSheet
diff --git a/src/render/ShadowCamera.cpp b/src/render/ShadowCamera.cpp
new file mode 100644
index 00000000..ae94f8ac
--- /dev/null
+++ b/src/render/ShadowCamera.cpp
@@ -0,0 +1,549 @@
+#include "common.h"
+#include "rwcore.h"
+#include "ShadowCamera.h"
+#include "RwHelper.h"
+
+#define TEXELOFFSET 0.5f
+
+RpAtomic *ShadowRenderCallBack(RpAtomic *atomic, void *data)
+{
+ RpAtomicCallBackRender savedCB = RpAtomicGetRenderCallBack(atomic);
+ RpAtomicSetRenderCallBack(atomic, AtomicDefaultRenderCallBack);
+ RpAtomicRender(atomic);
+ RpAtomicSetRenderCallBack(atomic, savedCB);
+ return atomic;
+}
+
+CShadowCamera::CShadowCamera()
+{
+ m_pCamera = nil;
+ m_pTexture = nil;
+}
+
+CShadowCamera::~CShadowCamera()
+{
+ Destroy();
+}
+
+void
+CShadowCamera::Destroy()
+{
+ if ( m_pCamera )
+ {
+ RwRaster *raster;
+ RwFrame *frame;
+
+ frame = RwCameraGetFrame(m_pCamera);
+
+ if ( frame )
+ {
+ RwCameraSetFrame(m_pCamera, nil);
+ RwFrameDestroy(frame);
+ }
+
+ raster = RwCameraGetZRaster(m_pCamera);
+ if ( raster )
+ {
+ RwCameraSetZRaster(m_pCamera, nil);
+ RwRasterDestroy(raster);
+ }
+
+ raster = RwCameraGetRaster(m_pCamera);
+ if ( raster )
+ {
+ RwCameraSetRaster(m_pCamera, nil);
+ RwRasterDestroy(raster);
+ }
+
+ if ( m_pTexture )
+ {
+ RwTextureSetRaster(m_pTexture, nil);
+ RwTextureDestroy(m_pTexture);
+ m_pTexture = nil;
+ }
+
+ RwCameraDestroy(m_pCamera);
+ m_pCamera = nil;
+ }
+ return;
+}
+
+RwCamera *
+CShadowCamera::Create(int32 rasterSize)
+{
+ int32 size = 1 << rasterSize;
+
+ m_pCamera = RwCameraCreate();
+ ASSERT(m_pCamera != nil);
+
+ if ( m_pCamera )
+ {
+ RwCameraSetFrame(m_pCamera, RwFrameCreate());
+
+ if( RwCameraGetFrame(m_pCamera) )
+ {
+ RwRaster *zRaster = RwRasterCreate(size, size, 0, rwRASTERTYPEZBUFFER);
+ ASSERT(zRaster != nil);
+
+ if ( zRaster )
+ {
+ RwCameraSetZRaster(m_pCamera, zRaster);
+
+ RwRaster *raster = RwRasterCreate(size, size, 0, rwRASTERTYPECAMERATEXTURE);
+ ASSERT(raster != nil);
+
+ if ( raster )
+ {
+ RwCameraSetRaster(m_pCamera, raster);
+ m_pTexture = RwTextureCreate(raster);
+ ASSERT(m_pTexture != nil);
+
+ if ( m_pTexture )
+ {
+ RwTextureSetAddressing(m_pTexture, rwTEXTUREADDRESSCLAMP);
+ RwTextureSetFilterMode(m_pTexture, rwFILTERLINEAR);
+ RwCameraSetProjection(m_pCamera, rwPARALLEL);
+ return (m_pCamera);
+ }
+ }
+ }
+ }
+ }
+
+ Destroy();
+
+ return (nil);
+}
+
+RwCamera *
+CShadowCamera::SetFrustum(float objectRadius)
+{
+ ASSERT(m_pCamera != nil);
+
+ RwV2d vw;
+
+ RwCameraSetFarClipPlane (m_pCamera, 2.0f * objectRadius);
+ RwCameraSetNearClipPlane(m_pCamera, 0.001f * objectRadius);
+
+ vw.x = objectRadius;
+ vw.y = objectRadius;
+ RwCameraSetViewWindow(m_pCamera, &vw);
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::SetLight(RpLight *light)
+{
+ ASSERT(light != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwFrame *camFrame = RwCameraGetFrame(m_pCamera);
+ RwMatrix *camMatrix = RwFrameGetMatrix(camFrame);
+ RwFrame *lightFrame = RpLightGetFrame(light);
+ RwMatrix *lightMatrix = RwFrameGetMatrix(lightFrame);
+
+ *RwMatrixGetRight(camMatrix) = *RwMatrixGetRight(lightMatrix);
+ *RwMatrixGetUp(camMatrix) = *RwMatrixGetUp(lightMatrix);
+ *RwMatrixGetAt(camMatrix) = *RwMatrixGetAt(lightMatrix);
+
+ RwMatrixUpdate(camMatrix);
+ RwFrameUpdateObjects(camFrame);
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::SetCenter(RwV3d *center)
+{
+ ASSERT(center != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwFrame *camFrame = RwCameraGetFrame(m_pCamera);
+ RwMatrix *camMatrix = RwFrameGetMatrix(camFrame);
+
+ *RwMatrixGetPos(camMatrix) = *center;
+
+ RwV3dIncrementScaled(RwMatrixGetPos(camMatrix), RwMatrixGetAt(camMatrix), -0.5f * RwCameraGetFarClipPlane(m_pCamera));
+
+ RwMatrixUpdate(camMatrix);
+ RwFrameUpdateObjects(camFrame);
+ RwFrameOrthoNormalize(camFrame);
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::Update(RpClump *clump)
+{
+ ASSERT(clump != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwUInt32 flags;
+ RpGeometry *geometry;
+
+ RwRGBA bgColor = { 255, 255, 255, 0 };
+
+ RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ geometry = GetFirstAtomic(clump)->geometry;
+ ASSERT(geometry != nil);
+
+ flags = RpGeometryGetFlags(geometry);
+
+ RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT
+ |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR));
+
+ RpClumpForAllAtomics(clump, ShadowRenderCallBack, nil);
+
+ RpGeometrySetFlags(geometry, flags);
+
+ InvertRaster();
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return m_pCamera;
+}
+
+RwCamera *
+CShadowCamera::Update(RpAtomic *atomic)
+{
+ ASSERT(atomic != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwUInt32 flags;
+ RpGeometry *geometry;
+
+ RwRGBA bgColor = { 255, 255, 255, 0 };
+
+ RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ geometry = RpAtomicGetGeometry(atomic);
+ ASSERT(geometry != nil);
+ flags = RpGeometryGetFlags(geometry);
+
+ RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT
+ |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYNORMALS));
+
+ ShadowRenderCallBack(atomic, nil);
+
+ RpGeometrySetFlags(geometry, flags);
+
+ InvertRaster();
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return m_pCamera;
+}
+
+void
+CShadowCamera::InvertRaster()
+{
+ ASSERT(m_pCamera != nil);
+
+ RwIm2DVertex vx[4];
+ float crw, crh;
+ RwRaster *raster;
+ float recipZ;
+
+ raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ crw = (float)RwRasterGetWidth(raster);
+ crh = (float)RwRasterGetHeight(raster);
+
+ recipZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwIm2DVertexSetScreenX (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[0], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX (&vx[1], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[1], crh);
+ RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX (&vx[2], crw);
+ RwIm2DVertexSetScreenY (&vx[2], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX (&vx[3], crw);
+ RwIm2DVertexSetScreenY (&vx[3], crh);
+ RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ);
+ RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255);
+
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+
+ RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+}
+
+RwRaster *
+CShadowCamera::MakeGradientRaster()
+{
+ ASSERT(m_pCamera != nil);
+
+ RwIm2DVertex vx[2];
+
+ if ( !m_pCamera )
+ return nil;
+
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float width = (float)RwRasterGetWidth(raster);
+ float height = (float)RwRasterGetHeight(raster);
+
+ if ( height < 1 )
+ return nil;
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)rwFILTERNAFILTERMODE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT);
+
+ float color = 255.0f;
+ float step = (-191.0f / height);
+
+ for ( int32 i = 0; i < height; i++ )
+ {
+ RwIm2DVertexSetScreenX (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[0], i);
+ RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);
+ RwIm2DVertexSetIntRGBA (&vx[0], (uint32)color, (uint32)color, (uint32)color, (uint32)color);
+
+ RwIm2DVertexSetScreenX (&vx[1], width - 1);
+ RwIm2DVertexSetScreenY (&vx[1], i);
+ RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);
+ RwIm2DVertexSetIntRGBA (&vx[1], (uint32)color, (uint32)color, (uint32)color, (uint32)color);
+
+ RwIm2DRenderLine(vx, 2, 0, 1);
+
+ color += step;
+ }
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEGOURAUD);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return raster;
+}
+
+RwRaster *
+CShadowCamera::RasterResample(RwRaster *dstRaster)
+{
+ ASSERT(dstRaster != nil);
+ ASSERT(m_pCamera != nil);
+
+ if ( !m_pCamera )
+ return nil;
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float) RwRasterGetWidth(raster);
+ float uvOffset = TEXELOFFSET / size;
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster);
+
+ Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, uvOffset);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return raster;
+}
+
+RwRaster *
+CShadowCamera::RasterBlur(RwRaster *dstRaster, int32 numPasses)
+{
+ ASSERT(dstRaster != nil);
+ ASSERT(m_pCamera != nil);
+
+ if ( !m_pCamera )
+ return nil;
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float) RwRasterGetWidth(dstRaster);
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ for (int i = 0; i < numPasses; i++ )
+ {
+ RwCameraSetRaster(m_pCamera, raster);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ if ( i == 0 )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ }
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster);
+ Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 1.0f / size);
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ RwCameraSetRaster(m_pCamera, dstRaster);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster);
+ Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0);
+
+ if ( i == numPasses - 1 )
+ {
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ }
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+ }
+
+ RwCameraSetRaster(m_pCamera, raster);
+
+ return dstRaster;
+}
+
+RwRaster *
+CShadowCamera::RasterGradient(RwRaster *dstRaster)
+{
+ ASSERT(dstRaster != nil);
+ ASSERT(m_pCamera != nil);
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float)RwRasterGetWidth(dstRaster);
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwCameraSetRaster(m_pCamera, dstRaster);
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDSRCCOLOR);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster);
+
+ Im2DRenderQuad(0, 0, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ RwCameraSetRaster(m_pCamera, raster);
+
+ return dstRaster;
+}
+
+RwRaster *CShadowCamera::DrawOutlineBorder(RwRGBA const& color)
+{
+ ASSERT(m_pCamera != nil);
+
+ RwIm2DVertex vx[4];
+ RwImVertexIndex ix[5];
+
+ RwRaster *raster = RwCameraGetRaster(m_pCamera);
+ ASSERT(raster != nil);
+
+ float size = (float)RwRasterGetWidth(raster) - 1.0f;
+ float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);
+
+ RwIm2DVertexSetScreenX (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[0], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[0], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);
+
+ RwIm2DVertexSetScreenX (&vx[1], size);
+ RwIm2DVertexSetScreenY (&vx[1], 0.0f);
+ RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[1], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);
+
+ RwIm2DVertexSetScreenX (&vx[2], size);
+ RwIm2DVertexSetScreenY (&vx[2], size);
+ RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[2], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);
+
+ RwIm2DVertexSetScreenX (&vx[3], 0.0f);
+ RwIm2DVertexSetScreenY (&vx[3], size);
+ RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetIntRGBA (&vx[3], color.red, color.green, color.blue, color.alpha);
+ RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);
+
+ ix[0] = 0;
+ ix[4] = 0;
+ ix[1] = 1;
+ ix[2] = 2;
+ ix[3] = 3;
+
+ if ( RwCameraBeginUpdate(m_pCamera) )
+ {
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, vx, 4, ix, 5);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+
+ RwCameraEndUpdate(m_pCamera);
+ }
+
+ return raster;
+} \ No newline at end of file
diff --git a/src/render/ShadowCamera.h b/src/render/ShadowCamera.h
new file mode 100644
index 00000000..a2149db7
--- /dev/null
+++ b/src/render/ShadowCamera.h
@@ -0,0 +1,54 @@
+#pragma once
+
+
+class CShadowCamera
+{
+public:
+ RwCamera *m_pCamera;
+ RwTexture *m_pTexture;
+
+ CShadowCamera();
+ ~CShadowCamera();
+
+ RwCamera *Create(int32 rasterSize);
+ void Destroy();
+
+ RwCamera *SetFrustum(float objectRadius);
+ RwCamera *SetLight(RpLight *light);
+ RwCamera *SetCenter(RwV3d *center);
+
+ RwCamera *Update(RpClump *clump);
+ RwCamera *Update(RpAtomic *atomic);
+
+ void InvertRaster();
+
+ RwRaster* GetRwRenderRaster()
+ {
+ return RwCameraGetRaster(m_pCamera);
+ }
+
+ // ShadowRasterRender(RwV2d *)
+ // ApplyAlphaMapToRaster(void)
+
+ RwRaster *MakeGradientRaster();
+
+ RwTexture *GetRwRenderTexture()
+ {
+ return m_pTexture;
+ }
+
+ RwRaster* GetRwZRaster()
+ {
+ return RwCameraGetZRaster(m_pCamera);
+ }
+
+ RwRaster *RasterResample(RwRaster *dstRaster);
+ RwRaster *RasterBlur(RwRaster *dstRaster, int32 numPasses);
+ RwRaster *RasterGradient(RwRaster *dstRaster);
+ RwRaster *DrawOutlineBorder(RwRGBA const& color);
+
+ RwCamera *GetRwCamera()
+ {
+ return m_pCamera;
+ }
+}; \ No newline at end of file
diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp
index c4d14fdc..5bb6a734 100644
--- a/src/render/Shadows.cpp
+++ b/src/render/Shadows.cpp
@@ -7,6 +7,7 @@
#include "Timecycle.h"
#include "CutsceneMgr.h"
#include "Automobile.h"
+#include "Bike.h"
#include "Ped.h"
#include "PlayerPed.h"
#include "World.h"
@@ -19,7 +20,11 @@
#include "PointLights.h"
#include "SpecialFX.h"
#include "Script.h"
+#include "TimeStep.h"
#include "Shadows.h"
+#include "CutsceneObject.h"
+#include "CutsceneShadow.h"
+#include "Clock.h"
#ifdef DEBUGMENU
SETTWEAKPATH("Shadows");
@@ -31,6 +36,8 @@ RwImVertexIndex ShadowIndexList[24];
RwTexture *gpShadowCarTex;
RwTexture *gpShadowPedTex;
RwTexture *gpShadowHeliTex;
+RwTexture *gpShadowBikeTex;
+RwTexture *gpShadowBaronTex;
RwTexture *gpShadowExplosionTex;
RwTexture *gpShadowHeadLightsTex;
RwTexture *gpOutline1Tex;
@@ -38,7 +45,6 @@ RwTexture *gpOutline2Tex;
RwTexture *gpOutline3Tex;
RwTexture *gpBloodPoolTex;
RwTexture *gpReflectionTex;
-RwTexture *gpGoalMarkerTex;
RwTexture *gpWalkDontTex;
RwTexture *gpCrackedGlassTex;
RwTexture *gpPostShadowTex;
@@ -60,37 +66,39 @@ CShadows::Init(void)
int32 slut = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slut);
- gpShadowCarTex = RwTextureRead("shad_car", NULL);
- gpShadowPedTex = RwTextureRead("shad_ped", NULL);
- gpShadowHeliTex = RwTextureRead("shad_heli", NULL);
- gpShadowExplosionTex = RwTextureRead("shad_exp", NULL);
- gpShadowHeadLightsTex = RwTextureRead("headlight", NULL);
- gpOutline1Tex = RwTextureRead("outline_64", NULL);
- gpOutline2Tex = RwTextureRead("outline2_64", NULL);
- gpOutline3Tex = RwTextureRead("outline3_64", NULL);
- gpBloodPoolTex = RwTextureRead("bloodpool_64", NULL);
- gpReflectionTex = RwTextureRead("reflection01", NULL);
- gpGoalMarkerTex = RwTextureRead("goal", NULL);
- gpWalkDontTex = RwTextureRead("walk_dont", NULL);
- gpCrackedGlassTex = RwTextureRead("wincrack_32", NULL);
- gpPostShadowTex = RwTextureRead("lamp_shad_64", NULL);
+ gpShadowCarTex = RwTextureRead("shad_car", nil);
+ gpShadowPedTex = RwTextureRead("shad_ped", nil);
+ gpShadowHeliTex = RwTextureRead("shad_heli", nil);
+ gpShadowBikeTex = RwTextureRead("shad_bike", nil);
+ gpShadowBaronTex = RwTextureRead("shad_rcbaron", nil);
+ gpShadowExplosionTex = RwTextureRead("shad_exp", nil);
+ gpShadowHeadLightsTex = RwTextureRead("headlight", nil);
+ gpOutline1Tex = RwTextureRead("outline_64", nil);
+ gpOutline2Tex = RwTextureRead("outline2_64", nil);
+ gpOutline3Tex = RwTextureRead("outline3_64", nil);
+ gpBloodPoolTex = RwTextureRead("bloodpool_64", nil);
+ gpReflectionTex = RwTextureRead("reflection01", nil);
+ gpWalkDontTex = RwTextureRead("walk_dont", nil);
+ gpCrackedGlassTex = RwTextureRead("wincrack_32", nil);
+ gpPostShadowTex = RwTextureRead("lamp_shad_64", nil);
CTxdStore::PopCurrentTxd();
- ASSERT(gpShadowCarTex != NULL);
- ASSERT(gpShadowPedTex != NULL);
- ASSERT(gpShadowHeliTex != NULL);
- ASSERT(gpShadowExplosionTex != NULL);
- ASSERT(gpShadowHeadLightsTex != NULL);
- ASSERT(gpOutline1Tex != NULL);
- ASSERT(gpOutline2Tex != NULL);
- ASSERT(gpOutline3Tex != NULL);
- ASSERT(gpBloodPoolTex != NULL);
- ASSERT(gpReflectionTex != NULL);
- ASSERT(gpGoalMarkerTex != NULL);
- ASSERT(gpWalkDontTex != NULL);
- ASSERT(gpCrackedGlassTex != NULL);
- ASSERT(gpPostShadowTex != NULL);
+ ASSERT(gpShadowCarTex != nil);
+ ASSERT(gpShadowPedTex != nil);
+ ASSERT(gpShadowHeliTex != nil);
+ ASSERT(gpShadowBikeTex != nil);
+ ASSERT(gpShadowBaronTex != nil);
+ ASSERT(gpShadowExplosionTex != nil);
+ ASSERT(gpShadowHeadLightsTex != nil);
+ ASSERT(gpOutline1Tex != nil);
+ ASSERT(gpOutline2Tex != nil);
+ ASSERT(gpOutline3Tex != nil);
+ ASSERT(gpBloodPoolTex != nil);
+ ASSERT(gpReflectionTex != nil);
+ ASSERT(gpWalkDontTex != nil);
+ ASSERT(gpCrackedGlassTex != nil);
+ ASSERT(gpPostShadowTex != nil);
ShadowIndexList[0] = 0;
@@ -129,7 +137,7 @@ CShadows::Init(void)
for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
{
aStaticShadows[i].m_nId = 0;
- aStaticShadows[i].m_pPolyBunch = NULL;
+ aStaticShadows[i].m_pPolyBunch = nil;
}
pEmptyBunchList = &aPolyBunches[0];
@@ -137,7 +145,7 @@ CShadows::Init(void)
for ( int32 i = 0; i < MAX_POLYBUNCHES; i++ )
{
if ( i == MAX_POLYBUNCHES - 1 )
- aPolyBunches[i].m_pNext = NULL;
+ aPolyBunches[i].m_pNext = nil;
else
aPolyBunches[i].m_pNext = &aPolyBunches[i + 1];
}
@@ -151,24 +159,27 @@ CShadows::Init(void)
void
CShadows::Shutdown(void)
{
- ASSERT(gpShadowCarTex != NULL);
- ASSERT(gpShadowPedTex != NULL);
- ASSERT(gpShadowHeliTex != NULL);
- ASSERT(gpShadowExplosionTex != NULL);
- ASSERT(gpShadowHeadLightsTex != NULL);
- ASSERT(gpOutline1Tex != NULL);
- ASSERT(gpOutline2Tex != NULL);
- ASSERT(gpOutline3Tex != NULL);
- ASSERT(gpBloodPoolTex != NULL);
- ASSERT(gpReflectionTex != NULL);
- ASSERT(gpGoalMarkerTex != NULL);
- ASSERT(gpWalkDontTex != NULL);
- ASSERT(gpCrackedGlassTex != NULL);
- ASSERT(gpPostShadowTex != NULL);
+ ASSERT(gpShadowCarTex != nil);
+ ASSERT(gpShadowPedTex != nil);
+ ASSERT(gpShadowHeliTex != nil);
+ ASSERT(gpShadowBikeTex != nil);
+ ASSERT(gpShadowBaronTex != nil);
+ ASSERT(gpShadowExplosionTex != nil);
+ ASSERT(gpShadowHeadLightsTex != nil);
+ ASSERT(gpOutline1Tex != nil);
+ ASSERT(gpOutline2Tex != nil);
+ ASSERT(gpOutline3Tex != nil);
+ ASSERT(gpBloodPoolTex != nil);
+ ASSERT(gpReflectionTex != nil);
+ ASSERT(gpWalkDontTex != nil);
+ ASSERT(gpCrackedGlassTex != nil);
+ ASSERT(gpPostShadowTex != nil);
RwTextureDestroy(gpShadowCarTex);
RwTextureDestroy(gpShadowPedTex);
RwTextureDestroy(gpShadowHeliTex);
+ RwTextureDestroy(gpShadowBikeTex);
+ RwTextureDestroy(gpShadowBaronTex);
RwTextureDestroy(gpShadowExplosionTex);
RwTextureDestroy(gpShadowHeadLightsTex);
RwTextureDestroy(gpOutline1Tex);
@@ -176,7 +187,6 @@ CShadows::Shutdown(void)
RwTextureDestroy(gpOutline3Tex);
RwTextureDestroy(gpBloodPoolTex);
RwTextureDestroy(gpReflectionTex);
- RwTextureDestroy(gpGoalMarkerTex);
RwTextureDestroy(gpWalkDontTex);
RwTextureDestroy(gpCrackedGlassTex);
RwTextureDestroy(gpPostShadowTex);
@@ -188,8 +198,8 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, uint32 nTime, float fScale)
{
- ASSERT(pTexture != NULL);
- ASSERT(pPosn != NULL);
+ ASSERT(pTexture != nil);
+ ASSERT(pPosn != nil);
// find free slot
@@ -216,36 +226,39 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo
}
}
-void
+bool
CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();
- if ( SQR(fDrawDistance) > fDistToCamSqr)
+ if ( SQR(fDrawDistance) > fDistToCamSqr || fDrawDistance == 0.0f )
{
- float fDistToCam = Sqrt(fDistToCamSqr);
-
- if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
+ if ( fDrawDistance != 0.0f )
{
- //fDistToCam == 0 -> 4
- //fDistToCam == fDrawDistance -> 0
- float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))));
+ float fDistToCam = Sqrt(fDistToCamSqr);
- nIntensity = (int32)(nIntensity * fMult);
- nRed = (int32)(nRed * fMult);
- nGreen = (int32)(nGreen * fMult);
- nBlue = (int32)(nBlue * fMult);
+ if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
+ {
+ //fDistToCam == 0 -> 4
+ //fDistToCam == fDrawDistance -> 0
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))));
+
+ nIntensity = (int32)(nIntensity * fMult);
+ nRed = (int32)(nRed * fMult);
+ nGreen = (int32)(nGreen * fMult);
+ nBlue = (int32)(nBlue * fMult);
+ }
}
int32 nSlot;
nSlot = 0;
- while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != NULL) )
+ while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != nil) )
nSlot++;
if ( nSlot < MAX_STATICSHADOWS )
@@ -264,8 +277,10 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_fScale = fScale;
aStaticShadows[nSlot].m_bTemp = bTempShadow;
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+
+ return true;
}
- else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f
+ else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f
&& Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < 0.05f
&& Abs(pPosn->z - aStaticShadows[nSlot].m_vecPosn.z) < 2.0f
@@ -285,6 +300,8 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_fScale = fScale;
aStaticShadows[nSlot].m_bTemp = bTempShadow;
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
+
+ return true;
}
else
{
@@ -309,12 +326,14 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
GeneratePolysForStaticShadow(nSlot);
+
+ return aStaticShadows[nSlot].m_pPolyBunch != nil;
}
}
else
{
nSlot = 0;
- while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != NULL )
+ while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != nil )
nSlot++;
if ( nSlot != MAX_STATICSHADOWS )
@@ -338,9 +357,13 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C
aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();
GeneratePolysForStaticShadow(nSlot);
+
+ return aStaticShadows[nSlot].m_pPolyBunch != nil;
}
}
}
+
+ return true;
}
void
@@ -348,7 +371,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
switch ( ShadowTexture )
{
@@ -362,7 +385,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -372,7 +395,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -382,7 +405,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -392,7 +415,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowHeliTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -402,7 +425,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowHeadLightsTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -411,8 +434,8 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,
{
StoreShadowToBeRendered(SHADOWTYPE_DARK, gpBloodPoolTex, pPosn,
fFrontX, fFrontY, fSideX, fSideY,
- nIntensity, nRed, nGreen, nBlue,
- 15.0f, false, 1.0f);
+ nIntensity, nRed, 150, 0,
+ 15.0f, false, 1.0f, nil, false);
break;
}
@@ -425,46 +448,64 @@ void
CShadows::StoreShadowToBeRendered(uint8 ShadowType, RwTexture *pTexture, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
- float fZDistance, bool bDrawOnWater, float fScale)
+ float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings)
{
- ASSERT(pTexture != NULL);
- ASSERT(pPosn != NULL);
+ ASSERT(pTexture != nil);
+ ASSERT(pPosn != nil);
if ( ShadowsStoredToBeRendered < MAX_STOREDSHADOWS )
{
- asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType;
- asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX;
- asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY;
- asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity;
- asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed;
- asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen;
- asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue;
- asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance;
- asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater;
- asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale;
+ asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType;
+ asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX;
+ asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue;
+ asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater;
+ asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnBuildings = bDrawOnBuildings;
+ asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale;
+ asShadowsStored[ShadowsStoredToBeRendered].m_pCutsceneShadow = pShadow;
ShadowsStoredToBeRendered++;
}
}
+
void
-CShadows::StoreShadowForCar(CAutomobile *pCar)
+CShadows::StoreShadowForVehicle(CVehicle *pCar, VEH_SHD_TYPE type)
{
- ASSERT(pCar != NULL);
+ ASSERT(pCar != nil);
if ( CTimeCycle::GetShadowStrength() != 0 )
{
CVector CarPos = pCar->GetPosition();
- float fDistToCamSqr = (CarPos - TheCamera.GetPosition()).MagnitudeSqr();
+ float fDistToCamSqr = (CarPos - TheCamera.GetPosition()).MagnitudeSqr2D();
if ( CCutsceneMgr::IsRunning() )
fDistToCamSqr /= SQR(TheCamera.LODDistMultiplier) * 4.0f;
- float fDrawDistance = 18.0f;
+ float fDrawDistance;
+ switch ( type )
+ {
+ case VEH_SHD_TYPE_SEAPLANE:
+ case VEH_SHD_TYPE_RCPLANE:
+ fDrawDistance = 144.0f;
+ break;
+
+ case VEH_SHD_TYPE_HELI:
+ fDrawDistance = 144.0f;
+ break;
+
+ default:
+ fDrawDistance = 18.0f;
+ break;
+ }
if ( fDistToCamSqr < SQR(fDrawDistance) )
{
@@ -472,46 +513,202 @@ CShadows::StoreShadowForCar(CAutomobile *pCar)
//fDistToCam == 0 -> 4
//fDistToCam == fDrawDistance -> 0
- float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))) );
+ float fMult = 1.0f - (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))) / (fDrawDistance*(1.0f/4.0f));
int32 nColorStrength;
if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )
- nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ nColorStrength = (int32)(fMult * CTimeCycle::GetShadowStrength());
else
nColorStrength = CTimeCycle::GetShadowStrength();
-
+
+
float fVehicleHeight = pCar->GetColModel()->boundingBox.GetSize().y;
float fVehicleWidth = pCar->GetColModel()->boundingBox.GetSize().x;
-
- if ( pCar->GetModelIndex() == MI_DODO )
+
+ float size = 1.0f;
+
+ if ( pCar->GetModelIndex() == MI_HUNTER )
+ {
+ fVehicleWidth *= 3.0f;
+ fVehicleHeight *= 1.4f;
+ size *= 0.5f;
+ }
+ else if ( pCar->GetModelIndex() == MI_ANGEL )
+ {
+ fVehicleHeight = fVehicleHeight * 1.5f;
+ size = 0.03f;
+ }
+ else if ( pCar->GetModelIndex() == MI_SEASPAR )
+ {
+ fVehicleWidth *= 3.0f;
+ fVehicleHeight *= 1.4f;
+ size *= 0.5f;
+ }
+ else if ( pCar->GetModelIndex() == MI_PIZZABOY || pCar->GetModelIndex() == MI_PCJ600 || pCar->GetModelIndex() == MI_FAGGIO )
+ {
+ fVehicleHeight *= 1.2f;
+ size = 0.05f;
+ }
+ else if ( pCar->GetModelIndex() == MI_FREEWAY )
+ {
+ fVehicleHeight *= 1.5f;
+ size = 0.03f;
+ }
+ else if ( pCar->GetModelIndex() == MI_RCRAIDER )
+ {
+ fVehicleHeight *= 1.5f;
+ fVehicleWidth *= 2.0f;
+ size = 0.2f;
+ }
+ else if ( pCar->GetModelIndex() == MI_SANCHEZ )
+ {
+ fVehicleHeight *= 1.5f;
+ size = 0.03f;
+ }
+ else if ( pCar->GetModelIndex() == MI_SPARROW || pCar->GetModelIndex() == MI_MAVERICK || pCar->GetModelIndex() == MI_VCNMAV || pCar->GetModelIndex() == MI_POLMAV )
+ {
+ fVehicleWidth *= 3.0f;
+ fVehicleHeight *= 1.4f;
+ size *= 0.5f;
+ }
+ else if ( pCar->GetModelIndex() == MI_RCGOBLIN )
+ {
+ fVehicleHeight *= 1.5f;
+ fVehicleWidth *= 2.0f;
+ size = 0.2f;
+ }
+ else if ( pCar->GetModelIndex() == MI_DODO )
{
fVehicleHeight *= 0.9f;
fVehicleWidth *= 0.4f;
}
+
+ CarPos.x -= pCar->GetForward().x * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size);
+ CarPos.y -= pCar->GetForward().y * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size);
+
+ RwTexture *tex = gpShadowCarTex;
+ switch ( type )
+ {
+ case VEH_SHD_TYPE_BIKE:
+ {
+ float wheelZ = Abs(((CBike*)pCar)->m_fLeanLRAngle);
+ float mul = 5.092958f * wheelZ + 1.0f;
+ if (pCar->GetStatus() == STATUS_PHYSICS)
+ {
+ float z = pCar->GetRight().z;
+ if (z > 0.6f)
+ mul += 4.0f * z;
+ }
+ fVehicleWidth *= mul;
+ tex = gpShadowBikeTex;
+ break;
+ }
+
+ case VEH_SHD_TYPE_HELI:
+ tex = gpShadowHeliTex;
+ break;
+
+ case VEH_SHD_TYPE_SEAPLANE:
+ nColorStrength = CTimeCycle::GetShadowStrength();
+ tex = gpShadowBaronTex;
+ break;
+
+ case VEH_SHD_TYPE_RCPLANE:
+ tex = gpShadowBaronTex;
+ fVehicleHeight *= 1.5f;
+ fVehicleWidth *= 2.2f;
+ break;
+
+ case VEH_SHD_TYPE_CAR:
+ tex = gpShadowCarTex;
+ break;
+ }
+
+ float frontx = pCar->GetForward().x;
+ float fronty = pCar->GetForward().y;
+ float sidex = pCar->GetRight().x;
+ float sidey = pCar->GetRight().y;
+
+ switch ( type )
+ {
+ case VEH_SHD_TYPE_BIKE:
+ if ( Abs(pCar->GetRight().z) > 0.6f )
+ {
+ sidex = pCar->GetUp().x;
+ sidey = pCar->GetUp().y;
+ }
+ break;
+
+ case VEH_SHD_TYPE_HELI:
+ if ( Abs(pCar->GetRight().z) > 0.57f )
+ {
+ sidex = pCar->GetUp().x;
+ sidey = pCar->GetUp().y;
+ }
+ if ( Abs(pCar->GetForward().z) > 0.57f )
+ {
+ frontx = pCar->GetUp().x;
+ fronty = pCar->GetUp().y;
+ }
+ break;
+ }
- CarPos.x -= pCar->GetForward().x * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y);
- CarPos.y -= pCar->GetForward().y * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y);
-
- if ( pCar->GetUp().z > 0.0f )
+ bool bDrawOnBuildings = false;
+ if ( pCar->GetModelIndex() == MI_RCBANDIT
+ || pCar->GetModelIndex() == MI_RCBARON
+ || pCar->GetModelIndex() == MI_RCRAIDER
+ || pCar->GetModelIndex() == MI_RCGOBLIN
+ || pCar == FindPlayerVehicle() )
{
- StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos,
- pCar->GetForward().x * (fVehicleHeight / 2),
- pCar->GetForward().y * (fVehicleHeight / 2),
- pCar->GetRight().x * (fVehicleWidth / 2),
- pCar->GetRight().y * (fVehicleWidth / 2),
- nColorStrength, nColorStrength, nColorStrength, nColorStrength,
- 4.5f, false, 1.0f);
+ bDrawOnBuildings = true;
+ }
+
+ if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.1f || bDrawOnBuildings )
+ {
+ if ( pCar->GetUp().z > 0.0f )
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ sidex * (fVehicleWidth / 2),
+ sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, false, 1.0f, nil, bDrawOnBuildings);
+ }
+ else
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ -sidex * (fVehicleWidth / 2),
+ -sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, false, 1.0f, nil, bDrawOnBuildings);
+ }
}
else
{
- StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos,
- pCar->GetForward().x * (fVehicleHeight / 2),
- pCar->GetForward().y * (fVehicleHeight / 2),
- -pCar->GetRight().x * (fVehicleWidth / 2),
- -pCar->GetRight().y * (fVehicleWidth / 2),
- nColorStrength, nColorStrength, nColorStrength, nColorStrength,
- 4.5f, false, 1.0f);
+ if ( pCar->GetUp().z > 0.0f )
+ {
+ StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ sidex * (fVehicleWidth / 2),
+ sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, 1.0f, 0.0f, false, 0.1f);
+ }
+ else
+ {
+ StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos,
+ frontx * (fVehicleHeight / 2),
+ fronty * (fVehicleHeight / 2),
+ -sidex * (fVehicleWidth / 2),
+ -sidey * (fVehicleWidth / 2),
+ nColorStrength, nColorStrength, nColorStrength, nColorStrength,
+ 4.5f, 1.0f, 0.0f, false, 0.1f);
+ }
}
}
}
@@ -522,8 +719,8 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture,
float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fMaxViewAngle)
{
- ASSERT(pCar != NULL);
- ASSERT(pPosn != NULL);
+ ASSERT(pCar != nil);
+ ASSERT(pPosn != nil);
float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();
@@ -551,31 +748,131 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture,
nBlue = (int32)(nBlue * fMult);
}
- StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn,
- fFrontX, fFrontY,
- fSideX, fSideY,
- 128, nRed, nGreen, nBlue,
- 6.0f, false, 1.0f);
+ if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.4f || pCar == FindPlayerVehicle() )
+ {
+ StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ 128, nRed, nGreen, nBlue,
+ 6.0f, false, 1.0f,
+ nil, pCar == FindPlayerVehicle());
+ }
+ else
+ {
+ StoreStaticShadow((uintptr)pCar + nID, SHADOWTYPE_ADDITIVE, pTexture, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ 128, nRed, nGreen, nBlue,
+ 6.0f, 1.0f, 27.0f,
+ false, 0.4f);
+ }
+ }
+ }
+}
+
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+void
+StoreShadowForCutscenePedObject(CPed *pObject, float fDisplacementX, float fDisplacementY,
+ float fFrontX, float fFrontY, float fSideX, float fSideY)
+{
+ ASSERT(pObject != nil);
+
+ CCutsceneShadow *shadow = pObject->m_pRTShadow;
+
+ if ( shadow == nil )
+ return;
+
+ if ( !shadow->IsInitialized() )
+ return;
+
+ CVector pos = pObject->GetPosition();
+
+ float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ float fDrawDistance = 100.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )
+ {
+ if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f)));
+ int32 nColorStrength;
+
+ if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) )
+ nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ else
+ nColorStrength = CTimeCycle::GetShadowStrength();
+
+ int32 color = int32(nColorStrength * 0.8f);
+
+ pos.x += fDisplacementX;
+ pos.y += fDisplacementY;
+
+ RwTexture *texture = shadow->GetShadowRwTexture();
+ ASSERT(texture);
+ RwRGBA bordercolor = {0, 0, 0, 0};
+ shadow->DrawBorderAroundTexture(bordercolor);
+
+ pos.x -= fDisplacementX;
+ pos.y -= fDisplacementY;
+
+ float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes
+ +60*CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f));
+
+ RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true);
+ ASSERT(frame);
+ CVector at(RwFrameGetMatrix(frame)->at);
+ at.Normalise();
+
+ CShadows::CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY);
+
+ pos.x -= 2.5f * fDisplacementX;
+ pos.y -= 2.5f * fDisplacementY;
+
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos,
+ fFrontX * 1.5f, fFrontY * 1.5f,
+ fSideX * 1.5f, fSideY * 1.5f,
+ color, color, color, color,
+ 4.0f, false, 1.0f, shadow, false);
}
}
}
+#endif
+
void
CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacementY,
float fFrontX, float fFrontY, float fSideX, float fSideY)
{
- ASSERT(pPed != NULL);
+ ASSERT(pPed != nil);
if ( pPed->bIsVisible )
{
if ( !(pPed->bInVehicle && pPed->m_nPedState != PED_DRAG_FROM_CAR && pPed->m_nPedState != PED_EXIT_CAR) )
{
if ( CTimeCycle::GetShadowStrength() != 0 )
+ {
+#ifdef USE_CUTSCENE_SHADOW_FOR_PED
+ CCutsceneShadow *pShadow = pPed->m_pRTShadow;
+
+ if (pShadow)
+ {
+ if (pShadow->IsInitialized())
+ pShadow->UpdateForCutscene();
+ ::StoreShadowForCutscenePedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY);
+ }
+
+ return;
+#endif
+
StoreShadowForPedObject(pPed,
fDisplacementX, fDisplacementY,
fFrontX, fFrontY,
fSideX, fSideY);
+ }
}
}
}
@@ -583,8 +880,8 @@ CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacemen
void
CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, float fDisplacementY,
float fFrontX, float fFrontY, float fSideX, float fSideY)
-{
- ASSERT(pPedObject != NULL);
+{
+ ASSERT(pPedObject != nil);
CVector PedPos = pPedObject->GetPosition();
@@ -592,7 +889,7 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo
float fDrawDistance = 26.0f;
- if ( fDistToCamSqr < SQR(fDrawDistance*0.5f)/*?*/ )
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )
{
if ( pPedObject == FindPlayerPed() || TheCamera.IsSphereVisible(PedPos, 2.0f) != false )
{
@@ -615,7 +912,80 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo
fFrontX, fFrontY,
fSideX, fSideY,
nColorStrength, nColorStrength, nColorStrength, nColorStrength,
- 4.0f, false, 1.0f);
+ 4.0f, false, 1.0f, nil, pPedObject == FindPlayerPed());
+ }
+ }
+}
+
+
+void
+CShadows::StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY,
+ float fFrontX, float fFrontY, float fSideX, float fSideY)
+{
+#ifdef DISABLE_CUTSCENE_SHADOWS
+ return;
+#endif
+ ASSERT(pObject != nil);
+
+ CCutsceneShadow *shadow = pObject->m_pShadow;
+
+ if ( shadow == nil )
+ return;
+
+ if ( !shadow->IsInitialized() )
+ return;
+
+ CVector pos = pObject->GetPosition();
+
+ float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D();
+
+ float fDrawDistance = 100.0f;
+
+ if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )
+ {
+ if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) )
+ {
+ float fDistToCam = Sqrt(fDistToCamSqr);
+
+ float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f)));
+ int32 nColorStrength;
+
+ if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) )
+ nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);
+ else
+ nColorStrength = CTimeCycle::GetShadowStrength();
+
+ int32 color = int32(nColorStrength * 0.8f);
+
+ pos.x += fDisplacementX;
+ pos.y += fDisplacementY;
+
+ RwTexture *texture = shadow->GetShadowRwTexture();
+ ASSERT(texture);
+ RwRGBA bordercolor = {0, 0, 0, 0};
+ shadow->DrawBorderAroundTexture(bordercolor);
+
+ pos.x -= fDisplacementX;
+ pos.y -= fDisplacementY;
+
+ float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes+60*
+ CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f));
+
+ RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true);
+ ASSERT(frame);
+ CVector at(RwFrameGetMatrix(frame)->at);
+ at.Normalise();
+
+ CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY);
+
+ pos.x -= 2.5f * fDisplacementX;
+ pos.y -= 2.5f * fDisplacementY;
+
+ StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos,
+ fFrontX * 1.5f, fFrontY * 1.5f,
+ fSideX * 1.5f, fSideY * 1.5f,
+ color, color, color, color,
+ 4.0f, false, 1.0f, shadow, false);
}
}
}
@@ -623,14 +993,15 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo
void
CShadows::StoreShadowForTree(CEntity *pTree)
{
- ASSERT(pTree != NULL);
+ ASSERT(pTree != nil);
}
+
void
CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ,
float fPoleHeight, float fPoleWidth, uint32 nID)
{
- ASSERT(pPole != NULL);
+ ASSERT(pPole != nil);
if ( CTimeCycle::GetShadowStrength() != 0 )
{
@@ -685,6 +1056,7 @@ CShadows::SetRenderModeForShadowType(uint8 ShadowType)
}
}
+
void
CShadows::RenderStoredShadows(void)
{
@@ -693,17 +1065,20 @@ CShadows::RenderStoredShadows(void)
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSCLAMP);
+
for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ )
asShadowsStored[i].m_nFlags.bRendered = false;
+
for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ )
{
if ( !asShadowsStored[i].m_nFlags.bRendered )
{
SetRenderModeForShadowType(asShadowsStored[i].m_ShadowType);
- ASSERT(asShadowsStored[i].m_pTexture != NULL);
+ ASSERT(asShadowsStored[i].m_pTexture != nil);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(asShadowsStored[i].m_pTexture));
@@ -735,39 +1110,112 @@ CShadows::RenderStoredShadows(void)
{
CSector *pCurSector = CWorld::GetSector(x, y);
- ASSERT(pCurSector != NULL);
-
- CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
- fStartX, fStartY,
- fEndX, fEndY,
- &shadowPos,
- asShadowsStored[j].m_vecFront.x,
- asShadowsStored[j].m_vecFront.y,
- asShadowsStored[j].m_vecSide.x,
- asShadowsStored[j].m_vecSide.y,
- asShadowsStored[j].m_nIntensity,
- asShadowsStored[j].m_nRed,
- asShadowsStored[j].m_nGreen,
- asShadowsStored[j].m_nBlue,
- asShadowsStored[j].m_fZDistance,
- asShadowsStored[j].m_fScale,
- NULL);
-
- CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
- fStartX, fStartY,
- fEndX, fEndY,
- &shadowPos,
- asShadowsStored[j].m_vecFront.x,
- asShadowsStored[j].m_vecFront.y,
- asShadowsStored[j].m_vecSide.x,
- asShadowsStored[j].m_vecSide.y,
- asShadowsStored[j].m_nIntensity,
- asShadowsStored[j].m_nRed,
- asShadowsStored[j].m_nGreen,
- asShadowsStored[j].m_nBlue,
- asShadowsStored[j].m_fZDistance,
- asShadowsStored[j].m_fScale,
- NULL);
+ ASSERT(pCurSector != nil);
+
+ if ( asShadowsStored[j].m_pCutsceneShadow )
+ {
+ CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil,
+ asShadowsStored[j].m_pCutsceneShadow);
+
+ CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil,
+ asShadowsStored[j].m_pCutsceneShadow);
+ }
+ else if ( asShadowsStored[j].m_nFlags.bDrawOnBuildings )
+ {
+ CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+
+ CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+ }
+ else
+ {
+ CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+
+ CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
+ fStartX, fStartY,
+ fEndX, fEndY,
+ &shadowPos,
+ asShadowsStored[j].m_vecFront.x,
+ asShadowsStored[j].m_vecFront.y,
+ asShadowsStored[j].m_vecSide.x,
+ asShadowsStored[j].m_vecSide.y,
+ asShadowsStored[j].m_nIntensity,
+ asShadowsStored[j].m_nRed,
+ asShadowsStored[j].m_nGreen,
+ asShadowsStored[j].m_nBlue,
+ asShadowsStored[j].m_fZDistance,
+ asShadowsStored[j].m_fScale,
+ nil);
+ }
}
}
@@ -777,16 +1225,17 @@ CShadows::RenderStoredShadows(void)
RenderBuffer::RenderStuffInBuffer();
}
-
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSWRAP);
ShadowsStoredToBeRendered = 0;
}
+
void
CShadows::RenderStaticShadows(void)
{
@@ -812,19 +1261,19 @@ CShadows::RenderStaticShadows(void)
// optimization trick, render all shadows with same renderstate and texture
for ( int32 j = i; j < MAX_STATICSHADOWS; j++ )
{
- if ( aStaticShadows[j].m_pPolyBunch != NULL
+ if ( aStaticShadows[j].m_pPolyBunch != nil
&& aStaticShadows[i].m_nType == aStaticShadows[j].m_nType
&& aStaticShadows[i].m_pTexture == aStaticShadows[j].m_pTexture )
{
- for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != NULL; bunch = bunch->m_pNext )
+ for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != nil; bunch = bunch->m_pNext )
{
RwImVertexIndex *pIndexes;
RwIm3DVertex *pVerts;
RenderBuffer::StartStoring(3 * (bunch->m_nNumVerts - 2), bunch->m_nNumVerts, &pIndexes, &pVerts);
- ASSERT(pIndexes != NULL);
- ASSERT(pVerts != NULL);
+ ASSERT(pIndexes != nil);
+ ASSERT(pVerts != nil);
for ( int32 k = 0; k < bunch->m_nNumVerts; k++ )
{
@@ -858,6 +1307,7 @@ CShadows::RenderStaticShadows(void)
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
}
+
void
CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
{
@@ -884,7 +1334,7 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
{
CSector *pCurSector = CWorld::GetSector(x, y);
- ASSERT(pCurSector != NULL);
+ ASSERT(pCurSector != nil);
CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],
fStartX, fStartY,
@@ -915,50 +1365,162 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)
}
}
+
void
CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, float fScale, CPolyBunch **ppPolyBunch)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
+
+ CPtrNode *pNode = PtrList.first;
+
+ CRect Bound;
+
+ while ( pNode != nil )
+ {
+ CEntity *pEntity = (CEntity *)pNode->item;
+ uint16 nScanCode = pEntity->m_scanCode;
+ pNode = pNode->next;
+
+ ASSERT( pEntity != nil );
+
+ if ( nScanCode != CWorld::GetCurrentScanCode() )
+ {
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if ( pEntity->bUsesCollision && !pEntity->m_flagE2 )
+ {
+ if ( IsAreaVisible(pEntity->m_area) )
+ {
+ Bound = pEntity->GetBoundRect();
+
+ if ( fStartX < Bound.right
+ && fEndX > Bound.left
+ && fStartY < Bound.bottom
+ && fEndY > Bound.top )
+ {
+ if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
+ && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ {
+ CastShadowEntityXY(pEntity,
+ fStartX, fStartY,
+ fEndX, fEndY,
+ pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void
+CShadows::CastPlayerShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch)
+{
+ ASSERT(pPosn != nil);
CPtrNode *pNode = PtrList.first;
CRect Bound;
- while ( pNode != NULL )
+ while ( pNode != nil )
{
CEntity *pEntity = (CEntity *)pNode->item;
uint16 nScanCode = pEntity->m_scanCode;
pNode = pNode->next;
- ASSERT( pEntity != NULL );
+ ASSERT( pEntity != nil );
if ( nScanCode != CWorld::GetCurrentScanCode() )
{
- if ( pEntity->bUsesCollision && pEntity->IsBuilding() )
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if ( pEntity->bUsesCollision )
{
- pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+ if ( IsAreaVisible(pEntity->m_area) )
+ {
+ Bound = pEntity->GetBoundRect();
+
+ if ( fStartX < Bound.right
+ && fEndX > Bound.left
+ && fStartY < Bound.bottom
+ && fEndY > Bound.top )
+ {
+ if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
+ && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ {
+ CastShadowEntityXY(pEntity,
+ fStartX, fStartY,
+ fEndX, fEndY,
+ pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void
+CShadows::CastCutsceneShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)
+{
+ ASSERT(pPosn != nil);
+ ASSERT(pShadow != nil);
+
+ CPtrNode *pNode = PtrList.first;
- Bound = pEntity->GetBoundRect();
+ CRect Bound;
+
+ while ( pNode != nil )
+ {
+ CEntity *pEntity = (CEntity *)pNode->item;
+ uint16 nScanCode = pEntity->m_scanCode;
+ pNode = pNode->next;
- if ( fStartX < Bound.right
- && fEndX > Bound.left
- && fStartY < Bound.bottom
- && fEndY > Bound.top )
+ ASSERT( pEntity != nil );
+
+ if ( nScanCode != CWorld::GetCurrentScanCode() )
+ {
+ pEntity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if ( pEntity->bUsesCollision )
+ {
+ if ( IsAreaVisible(pEntity->m_area) )
{
- if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
- && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ Bound = pEntity->GetBoundRect();
+
+ if ( fStartX < Bound.right
+ && fEndX > Bound.left
+ && fStartY < Bound.bottom
+ && fEndY > Bound.top )
{
- CastShadowEntity(pEntity,
- fStartX, fStartY,
- fEndX, fEndY,
- pPosn,
- fFrontX, fFrontY,
- fSideX, fSideY,
- nIntensity, nRed, nGreen, nBlue,
- fZDistance, fScale, ppPolyBunch);
+ if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z
+ && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )
+ {
+ CastShadowEntityXYZ(pEntity, pPosn,
+ fFrontX, fFrontY,
+ fSideX, fSideY,
+ nIntensity, nRed, nGreen, nBlue,
+ fZDistance, fScale, ppPolyBunch, pShadow);
+ }
}
}
}
@@ -967,20 +1529,20 @@ CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY,
}
void
-CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
+CShadows::CastShadowEntityXY(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
float fZDistance, float fScale, CPolyBunch **ppPolyBunch)
-{
- ASSERT(pEntity != NULL);
- ASSERT(pPosn != NULL);
+{
+ ASSERT(pEntity != nil);
+ ASSERT(pPosn != nil);
static CVector List [20];
static CVector Texture[20];
static CVector Points [4];
CColModel *pCol = pEntity->GetColModel();
- ASSERT(pCol != NULL);
+ ASSERT(pCol != nil);
#ifndef MASTER
if ( gbPrintShite )
@@ -1026,12 +1588,14 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
for ( int32 i = 0; i < pCol->numTriangles; i++ )
{
CColTrianglePlane *pColTriPlanes = pCol->trianglePlanes;
- ASSERT(pColTriPlanes != NULL);
+ ASSERT(pColTriPlanes != nil);
- if ( Abs(pColTriPlanes[i].normal.z) > 0.1f )
+ CVector normal;
+ pColTriPlanes[i].GetNormal(normal);
+ if ( Abs(normal.z) > 0.1f )
{
CColTriangle *pColTri = pCol->triangles;
- ASSERT(pColTri != NULL);
+ ASSERT(pColTri != nil);
CVector PointA, PointB, PointC;
@@ -1431,12 +1995,12 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
}
- if ( ppPolyBunch != NULL )
+ if ( ppPolyBunch != nil )
{
- if ( pEmptyBunchList != NULL )
+ if ( pEmptyBunchList != nil )
{
CPolyBunch *pBunch = pEmptyBunchList;
- ASSERT(pBunch != NULL);
+ ASSERT(pBunch != nil);
pEmptyBunchList = pEmptyBunchList->m_pNext;
pBunch->m_pNext = *ppPolyBunch;
*ppPolyBunch = pBunch;
@@ -1461,8 +2025,8 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
RenderBuffer::StartStoring(3 * (numVerts3 - 2), numVerts3, &pIndexes, &pVerts);
- ASSERT(pIndexes != NULL);
- ASSERT(pVerts != NULL);
+ ASSERT(pIndexes != nil);
+ ASSERT(pVerts != nil);
for ( int32 j = 0; j < numVerts3; j++ )
@@ -1486,12 +2050,222 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa
}
}
+
+typedef struct _ProjectionParam
+{
+ RwV3d at; /* Camera at vector */
+ RwMatrix invMatrix; /* Transforms to shadow camera space */
+ RwUInt8 shadowValue; /* Shadow opacity value */
+ RwBool fade; /* Shadow fades with distance */
+ RwUInt32 numIm3DBatch; /* Number of buffer flushes */
+ RwMatrix entityMatrix;
+}
+ProjectionParam;
+
+RwV3d *ShadowRenderTriangleCB(RwV3d *points, RwV3d *normal, ProjectionParam *param)
+{
+ RwV3d vIn[3];
+ RwV3d vShad[3];
+
+ RwV3dTransformPoints(&vIn[0], points, 3, &param->entityMatrix);
+
+ /*
+ * Reject backfacing triangles
+ * This reject the triangles parallel to the light as well
+ */
+ if (RwV3dDotProduct(normal, &param->at) > 0.0f)
+ {
+ return points;
+ }
+
+ RwV3dTransformPoints(&vShad[0], &vIn[0], 3, &param->invMatrix);
+
+ /*
+ * Reject triangles behind the camera (z test). Note that any world
+ * triangles lying in front of the camera but before the object may
+ * have a shadow applied. To minimize such artefacts, this test could
+ * be modified to use a specific value rather than 0.0f, perhaps
+ * to reject triangles behind the center plane of the object.
+ *
+ * Reject triangles that lie entirely outside the shadow texture range
+ * (x,y test).
+ */
+ if (((vShad[0].z < 0.0f) && (vShad[1].z < 0.0f)
+ && (vShad[2].z < 0.0f)) || ((vShad[0].x < 0.0f)
+ && (vShad[1].x < 0.0f)
+ && (vShad[2].x < 0.0f))
+ || ((vShad[0].x > 1.0f) && (vShad[1].x > 1.0f)
+ && (vShad[2].x > 1.0f)) || ((vShad[0].y < 0.0f)
+ && (vShad[1].y < 0.0f)
+ && (vShad[2].y < 0.0f))
+ || ((vShad[0].y > 1.0f) && (vShad[1].y > 1.0f)
+ && (vShad[2].y > 1.0f)))
+ {
+ return points;
+ }
+
+ RwIm3DVertex *imv = nil;
+ RwImVertexIndex *imi = nil;
+
+ RenderBuffer::StartStoring(3, 3, &imi, &imv);
+
+ /*
+ * Set the immediate mode vertices for this triangle
+ */
+
+ RwIm3DVertexSetPos(imv, vIn[0].x, vIn[0].y, vIn[0].z);
+ RwIm3DVertexSetPos(imv + 1, vIn[1].x, vIn[1].y, vIn[1].z);
+ RwIm3DVertexSetPos(imv + 2, vIn[2].x, vIn[2].y, vIn[2].z);
+
+ RwIm3DVertexSetU(imv, vShad[0].x);
+ RwIm3DVertexSetU(imv + 1, vShad[1].x);
+ RwIm3DVertexSetU(imv + 2, vShad[2].x);
+
+ RwIm3DVertexSetV(imv, vShad[0].y);
+ RwIm3DVertexSetV(imv + 1, vShad[1].y);
+ RwIm3DVertexSetV(imv + 2, vShad[2].y);
+
+ /*
+ * Do we fade out the shadow with distance?
+ */
+ if (param->fade)
+ {
+ RwReal fadeVal;
+ RwUInt8 val;
+
+ fadeVal = 1.0f - vShad[0].z * vShad[0].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv, val, val, val, val);
+
+ fadeVal = 1.0f - vShad[1].z * vShad[1].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv + 1, val, val, val, val);
+
+ fadeVal = 1.0f - vShad[2].z * vShad[2].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv + 2, val, val, val, val);
+ }
+ else
+ {
+ RwUInt8 val = param->shadowValue;
+
+ RwIm3DVertexSetRGBA(imv, val, val, val, val);
+ RwIm3DVertexSetRGBA(imv + 1, val, val, val, val);
+ RwIm3DVertexSetRGBA(imv + 2, val, val, val, val);
+ }
+
+ /*
+ * Update buffer position
+ */
+ imi[0] = 0;
+ imi[1] = 1;
+ imi[2] = 2;
+
+ RenderBuffer::StopStoring();
+
+ return points;
+}
+
+void
+CShadows::CastShadowEntityXYZ(CEntity *pEntity, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)
+{
+ ASSERT(pEntity != nil);
+ ASSERT(pPosn != nil);
+
+ if ( pShadow )
+ {
+ ProjectionParam proj;
+ RwV3d scl;
+ RwV3d tr;
+
+ CShadowCamera *shadow = pShadow->GetShadowCamera();
+ CColModel *collision = pEntity->GetColModel();
+
+ CCollision::CalculateTrianglePlanes(collision);
+
+ RwMatrix mat;
+ mat = *RwFrameGetMatrix(RwCameraGetFrame(shadow->GetRwCamera()));
+
+ RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+
+ RwMatrixRotate(&mat, &Xaxis, -45.0f, rwCOMBINEPRECONCAT);
+
+ proj.at = mat.at;
+ pEntity->GetMatrix().CopyToRwMatrix(&proj.entityMatrix);
+
+ RwMatrixInvert(&proj.invMatrix, &mat);
+ RwReal radius = RwCameraGetViewWindow(shadow->GetRwCamera())->x;
+
+ scl.x = scl.y = -0.5f / (radius*0.9f);
+ scl.z = 1.0f / (radius*0.8f);
+ RwMatrixScale(&proj.invMatrix, &scl, rwCOMBINEPOSTCONCAT);
+
+ tr.x = 0.5f;
+ tr.y = tr.z = 0.0f;
+ RwMatrixTranslate(&proj.invMatrix, &tr, rwCOMBINEPOSTCONCAT);
+
+ proj.shadowValue = nIntensity;
+ proj.fade = 0;
+
+ RwMatrix matrix;
+ pEntity->GetMatrix().CopyToRwMatrix(&matrix);
+ RwMatrix invMatrix;
+ RwMatrixInvert(&invMatrix, &matrix);
+
+
+ CVector center(pShadow->GetBaseSphere().center);
+ center += CVector(-fFrontX * 1.1f, -fFrontY * 1.1f, -0.5f);
+
+ CSphere sphere;
+ sphere.Set(2.0f, center);
+
+ RwV3d point;
+ RwV3dTransformPoints(&point, center, 1, &invMatrix);
+
+ CColSphere colSphere;
+ colSphere.Set(2.0f, CVector(point), 0, 0);
+
+ int i = 0;
+ while ( i < collision->numTriangles )
+ {
+ CVector p[3];
+
+ collision->GetTrianglePoint(p[0], collision->triangles[i].a);
+ collision->GetTrianglePoint(p[1], collision->triangles[i].b);
+ collision->GetTrianglePoint(p[2], collision->triangles[i].c);
+
+ if ( CCollision::TestSphereTriangle(colSphere, collision->vertices, collision->triangles[i], collision->trianglePlanes[i]) )
+ {
+ CVector n(collision->trianglePlanes[i].GetNormalX(), collision->trianglePlanes[i].GetNormalY(), collision->trianglePlanes[i].GetNormalZ());
+ CVector offset = n * 0.028f;
+
+ p[0] += offset;
+ p[1] += offset;
+ p[2] += offset;
+
+ if ( !ShadowRenderTriangleCB((RwV3d *)p, n, &proj) )
+ break;
+ }
+ i++;
+ }
+ }
+}
+
void
CShadows::UpdateStaticShadows(void)
{
for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )
{
- if ( aStaticShadows[i].m_pPolyBunch != NULL && !aStaticShadows[i].m_bJustCreated
+ if ( aStaticShadows[i].m_pPolyBunch != nil && !aStaticShadows[i].m_bJustCreated
&& (!aStaticShadows[i].m_bTemp || CTimer::GetTimeInMilliseconds() > aStaticShadows[i].m_nTimeCreated + 5000) )
{
aStaticShadows[i].Free();
@@ -1514,13 +2288,14 @@ CShadows::UpdatePermanentShadows(void)
aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
else
{
+ bool bOk;
if ( timePassed >= (aPermanentShadows[i].m_nLifeTime * 3 / 4) )
{
// timePassed == 0 -> 4
// timePassed == aPermanentShadows[i].m_nLifeTime -> 0
float fMult = 1.0f - float(timePassed - (aPermanentShadows[i].m_nLifeTime * 3 / 4)) / (aPermanentShadows[i].m_nLifeTime / 4);
- StoreStaticShadow((uintptr)&aPermanentShadows[i],
+ bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i],
aPermanentShadows[i].m_nType,
aPermanentShadows[i].m_pTexture,
&aPermanentShadows[i].m_vecPos,
@@ -1537,7 +2312,7 @@ CShadows::UpdatePermanentShadows(void)
}
else
{
- StoreStaticShadow((uintptr)&aPermanentShadows[i],
+ bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i],
aPermanentShadows[i].m_nType,
aPermanentShadows[i].m_pTexture,
&aPermanentShadows[i].m_vecPos,
@@ -1552,6 +2327,9 @@ CShadows::UpdatePermanentShadows(void)
aPermanentShadows[i].m_fZDistance,
1.0f, 40.0f, false, 0.0f);
}
+
+ if ( !bOk )
+ aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
}
}
}
@@ -1560,61 +2338,63 @@ CShadows::UpdatePermanentShadows(void)
void
CStaticShadow::Free(void)
{
- if ( m_pPolyBunch != NULL )
+ if ( m_pPolyBunch != nil )
{
CPolyBunch *pFree = CShadows::pEmptyBunchList;
CShadows::pEmptyBunchList = m_pPolyBunch;
CPolyBunch *pUsed = m_pPolyBunch;
- while (pUsed->m_pNext != NULL)
+ while (pUsed->m_pNext != nil)
pUsed = pUsed->m_pNext;
pUsed->m_pNext = pFree;
}
- m_pPolyBunch = NULL;
+ m_pPolyBunch = nil;
m_nId = 0;
}
void
CShadows::CalcPedShadowValues(CVector vecLightDir,
- float *pfDisplacementX, float *pfDisplacementY,
float *pfFrontX, float *pfFrontY,
- float *pfSideX, float *pfSideY)
+ float *pfSideX, float *pfSideY,
+ float *pfDisplacementX, float *pfDisplacementY)
{
- ASSERT(pfDisplacementX != NULL);
- ASSERT(pfDisplacementY != NULL);
- ASSERT(pfFrontX != NULL);
- ASSERT(pfFrontY != NULL);
- ASSERT(pfSideX != NULL);
- ASSERT(pfSideY != NULL);
+ ASSERT(pfFrontX != nil);
+ ASSERT(pfFrontY != nil);
+ ASSERT(pfSideX != nil);
+ ASSERT(pfSideY != nil);
+ ASSERT(pfDisplacementX != nil);
+ ASSERT(pfDisplacementY != nil);
- *pfDisplacementX = -vecLightDir.x;
- *pfDisplacementY = -vecLightDir.y;
+ *pfFrontX = -vecLightDir.x;
+ *pfFrontY = -vecLightDir.y;
- float fDist = Sqrt(*pfDisplacementY * *pfDisplacementY + *pfDisplacementX * *pfDisplacementX);
+ float fDist = Sqrt(*pfFrontY * *pfFrontY + *pfFrontX * *pfFrontX);
float fMult = (fDist + 1.0f) / fDist;
- *pfDisplacementX *= fMult;
- *pfDisplacementY *= fMult;
-
- *pfFrontX = -vecLightDir.y / fDist;
- *pfFrontY = vecLightDir.x / fDist;
+ *pfFrontX *= fMult;
+ *pfFrontY *= fMult;
- *pfSideX = -vecLightDir.x;
- *pfSideY = -vecLightDir.y;
+ *pfSideX = -vecLightDir.y / fDist;
+ *pfSideY = vecLightDir.x / fDist;
- *pfDisplacementX /= 2;
- *pfDisplacementY /= 2;
+ *pfDisplacementX = -vecLightDir.x;
+ *pfDisplacementY = -vecLightDir.y;
*pfFrontX /= 2;
*pfFrontY /= 2;
*pfSideX /= 2;
*pfSideY /= 2;
+
+ *pfDisplacementX /= 2;
+ *pfDisplacementY /= 2;
+
}
+
void
CShadows::RenderExtraPlayerShadows(void)
{
@@ -1625,64 +2405,13 @@ CShadows::RenderExtraPlayerShadows(void)
if ( CTimeCycle::GetLightShadowStrength() != 0 )
{
CVehicle *pCar = FindPlayerVehicle();
-
- if ( pCar == NULL )
- {
- for ( int32 i = 0; i < CPointLights::NumLights; i++ )
- {
- if ( 0.0f != CPointLights::aLights[i].red
- || 0.0f != CPointLights::aLights[i].green
- || 0.0f != CPointLights::aLights[i].blue )
- {
- if ( CPointLights::aLights[i].castExtraShadows )
- {
- CVector vecLight = CPointLights::aLights[i].coors - FindPlayerCoors();
- float fLightDist = vecLight.Magnitude();
- float fRadius = CPointLights::aLights[i].radius;
-
- if ( fLightDist < fRadius )
- {
- // fLightDist == fRadius -> 2.0f
- // fLightDist == 0 -> 0.0f
- float fMult = (1.0f - (2.0f * fLightDist - fRadius) / fRadius);
-
- int32 nColorStrength;
- if ( fLightDist < fRadius*0.5f )
- nColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8);
- else
- nColorStrength = int32((5*CTimeCycle::GetLightShadowStrength()/8) * fMult);
-
- float fInv = 1.0f / fLightDist;
- vecLight.x *= fInv;
- vecLight.y *= fInv;
- vecLight.z *= fInv;
-
- float fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY;
-
- CalcPedShadowValues(vecLight,
- &fDisplacementX, &fDisplacementY,
- &fFrontX, &fFrontY,
- &fSideX, &fSideY);
-
- CVector shadowPos = FindPlayerCoors();
-
- shadowPos.x += fSideX;
- shadowPos.y += fSideY;
-
-
- StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &shadowPos,
- fDisplacementX, fDisplacementY,
- fFrontX, fFrontY,
- nColorStrength, 0, 0, 0,
- 4.0f, false, 1.0f);
- }
- }
- }
- }
- }
+ if ( pCar == nil )
+ ; // R* cut it out for playerped
else
{
- if ( pCar->GetModelIndex() != MI_RCBANDIT )
+ if ( pCar->GetModelIndex() != MI_RCBANDIT
+ && pCar->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE
+ && !pCar->IsBike() && !pCar->IsPlane() && !pCar->IsBoat() )
{
for ( int32 i = 0; i < CPointLights::NumLights; i++ )
{
@@ -1735,7 +2464,7 @@ CShadows::RenderExtraPlayerShadows(void)
pCar->GetRight().x * (fVehicleWidth/3),
pCar->GetRight().y * (fVehicleWidth/3),
nColorStrength, 0, 0, 0,
- 4.5f, false, 1.0f);
+ 4.5f, false, 1.0f, nil, false);
}
else
{
@@ -1745,7 +2474,7 @@ CShadows::RenderExtraPlayerShadows(void)
-pCar->GetRight().x * (fVehicleWidth/2),
-pCar->GetRight().y * (fVehicleWidth/2),
nColorStrength, 0, 0, 0,
- 4.5f, false, 1.0f);
+ 4.5f, false, 1.0f, nil, false);
}
}
}
@@ -1767,9 +2496,9 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur
float fFrontX, float fFrontY, float fSideX, float fSideY,
int16 nIntensity)
{
- ASSERT(pPosn != NULL);
+ ASSERT(pPosn != nil);
- C3dMarkers::PlaceMarkerSet(nID, _TODOCONST(4), *pPosn, Max(fFrontX, -fSideY),
+ C3dMarkers::PlaceMarkerSet(nID, MARKERTYPE_CYLINDER, *pPosn, Max(fFrontX, -fSideY),
SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B,
SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0);
}
diff --git a/src/render/Shadows.h b/src/render/Shadows.h
index 63aaaaf2..94b2981f 100644
--- a/src/render/Shadows.h
+++ b/src/render/Shadows.h
@@ -1,12 +1,19 @@
#pragma once
#define MAX_STOREDSHADOWS 48
-#define MAX_POLYBUNCHES 300
-#define MAX_STATICSHADOWS 64
+#define MAX_POLYBUNCHES 380
+#define MAX_STATICSHADOWS 48
#define MAX_PERMAMENTSHADOWS 48
+
class CEntity;
+class CPtrList;
+class CAutomobile;
+class CVehicle;
+class CPed;
+class CCutsceneShadow;
+class CCutsceneObject;
enum eShadowType
{
@@ -27,6 +34,16 @@ enum eShadowTextureType
SHADOWTEX_BLOOD
};
+enum VEH_SHD_TYPE
+{
+ VEH_SHD_TYPE_CAR = 0,
+ VEH_SHD_TYPE_BIKE,
+ VEH_SHD_TYPE_HELI,
+ VEH_SHD_TYPE_SEAPLANE,
+ VEH_SHD_TYPE_RCPLANE,
+};
+
+
class CStoredShadow
{
public:
@@ -35,6 +52,8 @@ public:
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
+ RwTexture *m_pTexture;
+ CCutsceneShadow *m_pCutsceneShadow;
int16 m_nIntensity;
uint8 m_ShadowType;
uint8 m_nRed;
@@ -44,9 +63,9 @@ public:
{
uint8 bDrawOnWater : 1;
uint8 bRendered : 1;
- //uint8 bDrawOnBuildings : 1;
+ uint8 bDrawOnBuildings : 1;
} m_nFlags;
- RwTexture *m_pTexture;
+
CStoredShadow()
{ }
@@ -57,11 +76,11 @@ VALIDATE_SIZE(CStoredShadow, 0x30);
class CPolyBunch
{
public:
- int16 m_nNumVerts;
CVector m_aVerts[7];
+ CPolyBunch *m_pNext;
+ int16 m_nNumVerts;
uint8 m_aU[7];
uint8 m_aV[7];
- CPolyBunch *m_pNext;
CPolyBunch()
{ }
@@ -80,15 +99,16 @@ public:
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
- uint8 m_nType;
+ RwTexture *m_pTexture;
int16 m_nIntensity; // unsigned ?
+ uint8 m_nType;
uint8 m_nRed;
uint8 m_nGreen;
uint8 m_nBlue;
bool m_bJustCreated;
bool m_bRendered;
bool m_bTemp;
- RwTexture *m_pTexture;
+
CStaticShadow()
{ }
@@ -106,14 +126,14 @@ public:
CVector2D m_vecSide;
float m_fZDistance;
float m_fScale;
+ uint32 m_nTimeCreated;
+ uint32 m_nLifeTime;
+ RwTexture *m_pTexture;
int16 m_nIntensity;
uint8 m_nType; // eShadowType
uint8 m_nRed;
uint8 m_nGreen;
uint8 m_nBlue;
- uint32 m_nTimeCreated;
- uint32 m_nLifeTime;
- RwTexture *m_pTexture;
CPermanentShadow()
{ }
@@ -121,60 +141,62 @@ public:
VALIDATE_SIZE(CPermanentShadow, 0x38);
-class CPtrList;
-class CAutomobile;
-class CPed;
-
class CShadows
{
public:
-#if 1
static int16 ShadowsStoredToBeRendered;
static CStoredShadow asShadowsStored [MAX_STOREDSHADOWS];
static CPolyBunch aPolyBunches [MAX_POLYBUNCHES];
static CStaticShadow aStaticShadows [MAX_STATICSHADOWS];
static CPolyBunch *pEmptyBunchList;
static CPermanentShadow aPermanentShadows[MAX_PERMAMENTSHADOWS];
-#else
- static int16 &ShadowsStoredToBeRendered;
- static CStoredShadow (&asShadowsStored) [MAX_STOREDSHADOWS];
- static CPolyBunch (&aPolyBunches) [MAX_POLYBUNCHES];
- static CStaticShadow (&aStaticShadows) [MAX_STATICSHADOWS];
- static CPolyBunch *&pEmptyBunchList;
- static CPermanentShadow (&aPermanentShadows)[MAX_PERMAMENTSHADOWS];
-#endif
-
- static void Init (void);
- static void Shutdown (void);
- static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale);
- static void StoreStaticShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance);
- static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue);
- static void StoreShadowToBeRendered ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale);
- static void StoreShadowForCar (CAutomobile *pCar);
- static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle);
- static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
- static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
- static void StoreShadowForTree (CEntity *pTree);
- static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID);
- static void SetRenderModeForShadowType (uint8 ShadowType);
- static void RenderStoredShadows (void);
- static void RenderStaticShadows (void);
- static void GeneratePolysForStaticShadow (int16 nStaticShadowID);
- static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
+
+ static void Init (void);
+ static void Shutdown (void);
+ static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale);
+
+ static bool StoreStaticShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance);
+ static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue);
+ static void StoreShadowToBeRendered ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings);
+ static void StoreShadowForVehicle (CVehicle *pCar, VEH_SHD_TYPE type);
+ static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle);
+ static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
+ static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
+ static void StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);
+ static void StoreShadowForTree (CEntity *pTree);
+ static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID);
+ static void SetRenderModeForShadowType (uint8 ShadowType);
+ static void RenderStoredShadows (void);
+ static void RenderStaticShadows (void);
+
+ static void GeneratePolysForStaticShadow (int16 nStaticShadowID);
+ static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch);
- static void CastShadowEntity (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY,
+
+ static void CastPlayerShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
+ CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch);
+
+ static void CastCutsceneShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,
+ CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);
+
+ static void CastShadowEntityXY (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY,
CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch);
- static void UpdateStaticShadows (void);
- static void UpdatePermanentShadows (void);
- static void CalcPedShadowValues (CVector vecLightDir, float *pfDisplacementX, float *pfDisplacementY, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY);
- static void RenderExtraPlayerShadows (void);
- static void TidyUpShadows (void);
- static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);
+
+ static void CastShadowEntityXYZ (CEntity *pEntity, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);
+
+ static void UpdateStaticShadows (void);
+ static void UpdatePermanentShadows (void);
+ static void CalcPedShadowValues (CVector vecLightDir, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY, float *pfDisplacementX, float *pfDisplacementY);
+ static void RenderExtraPlayerShadows (void);
+ static void TidyUpShadows (void);
+ static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);
};
extern RwTexture *gpShadowCarTex;
extern RwTexture *gpShadowPedTex;
extern RwTexture *gpShadowHeliTex;
+extern RwTexture *gpShadowBikeTex;
+extern RwTexture *gpShadowBaronTex;
extern RwTexture *gpShadowExplosionTex;
extern RwTexture *gpShadowHeadLightsTex;
extern RwTexture *gpOutline1Tex;
@@ -182,7 +204,6 @@ extern RwTexture *gpOutline2Tex;
extern RwTexture *gpOutline3Tex;
extern RwTexture *gpBloodPoolTex;
extern RwTexture *gpReflectionTex;
-extern RwTexture *gpGoalMarkerTex;
extern RwTexture *gpWalkDontTex;
extern RwTexture *gpCrackedGlassTex;
extern RwTexture *gpPostShadowTex;
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index efd88387..f2a66db1 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -6,6 +6,8 @@
#include "Replay.h"
#include "Skidmarks.h"
+//--MIAMI: file done
+
CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];
RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];
@@ -37,13 +39,6 @@ CSkidmarks::Init(void)
SkidmarkIndexList[i*6+5] = ix+3;
ix += 2;
}
-
- for(i = 0; i < SKIDMARK_LENGTH; i++){
- RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 0], 0.0f);
- RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 0], i*5.01f);
- RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 1], 1.0f);
- RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 1], i*5.01f);
- }
}
void
@@ -141,8 +136,12 @@ CSkidmarks::Render(void)
p2.y -= aSkidmarks[i].m_sideY[j];
RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], color.red, color.green, color.blue, alpha);
RwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f);
+ RwIm3DVertexSetU(&SkidmarkVertices[j*2+0], 0.0f);
+ RwIm3DVertexSetV(&SkidmarkVertices[j*2+0], j*5.01f);
RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], color.red, color.green, color.blue, alpha);
RwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f);
+ RwIm3DVertexSetU(&SkidmarkVertices[j*2+1], 1.0f);
+ RwIm3DVertexSetV(&SkidmarkVertices[j*2+1], j*5.01f);
}
LittleTest();
diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp
index fe898412..7e8ad5e5 100644
--- a/src/render/Timecycle.cpp
+++ b/src/render/Timecycle.cpp
@@ -10,60 +10,60 @@
#include "FileMgr.h"
#include "Timecycle.h"
-// TODO(MIAMI): change some of the types here
-
-int CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
-short CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS];
-short CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
-short CTimeCycle::m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
-int CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fWaterRed[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fWaterGreen[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fWaterBlue[NUMHOURS][NUMWEATHERS];
-float CTimeCycle::m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
+//--MIAMI: done
+
+uint8 CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
+int8 CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS];
+int8 CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS];
+int8 CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
+int16 CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS];
+int16 CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterRed[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterGreen[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterBlue[NUMHOURS][NUMWEATHERS];
+uint8 CTimeCycle::m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
float CTimeCycle::m_fCurrentAmbientRed;
@@ -81,36 +81,36 @@ float CTimeCycle::m_fCurrentAmbientBlue_Obj_Bl;
float CTimeCycle::m_fCurrentDirectionalRed;
float CTimeCycle::m_fCurrentDirectionalGreen;
float CTimeCycle::m_fCurrentDirectionalBlue;
-int CTimeCycle::m_nCurrentSkyTopRed;
-int CTimeCycle::m_nCurrentSkyTopGreen;
-int CTimeCycle::m_nCurrentSkyTopBlue;
-int CTimeCycle::m_nCurrentSkyBottomRed;
-int CTimeCycle::m_nCurrentSkyBottomGreen;
-int CTimeCycle::m_nCurrentSkyBottomBlue;
-int CTimeCycle::m_nCurrentSunCoreRed;
-int CTimeCycle::m_nCurrentSunCoreGreen;
-int CTimeCycle::m_nCurrentSunCoreBlue;
-int CTimeCycle::m_nCurrentSunCoronaRed;
-int CTimeCycle::m_nCurrentSunCoronaGreen;
-int CTimeCycle::m_nCurrentSunCoronaBlue;
+int32 CTimeCycle::m_nCurrentSkyTopRed;
+int32 CTimeCycle::m_nCurrentSkyTopGreen;
+int32 CTimeCycle::m_nCurrentSkyTopBlue;
+int32 CTimeCycle::m_nCurrentSkyBottomRed;
+int32 CTimeCycle::m_nCurrentSkyBottomGreen;
+int32 CTimeCycle::m_nCurrentSkyBottomBlue;
+int32 CTimeCycle::m_nCurrentSunCoreRed;
+int32 CTimeCycle::m_nCurrentSunCoreGreen;
+int32 CTimeCycle::m_nCurrentSunCoreBlue;
+int32 CTimeCycle::m_nCurrentSunCoronaRed;
+int32 CTimeCycle::m_nCurrentSunCoronaGreen;
+int32 CTimeCycle::m_nCurrentSunCoronaBlue;
float CTimeCycle::m_fCurrentSunSize;
float CTimeCycle::m_fCurrentSpriteSize;
float CTimeCycle::m_fCurrentSpriteBrightness;
-int CTimeCycle::m_nCurrentShadowStrength;
-int CTimeCycle::m_nCurrentLightShadowStrength;
-int CTimeCycle::m_nCurrentPoleShadowStrength;
+int32 CTimeCycle::m_nCurrentShadowStrength;
+int32 CTimeCycle::m_nCurrentLightShadowStrength;
+int32 CTimeCycle::m_nCurrentPoleShadowStrength;
float CTimeCycle::m_fCurrentFogStart;
float CTimeCycle::m_fCurrentFarClip;
float CTimeCycle::m_fCurrentLightsOnGroundBrightness;
-int CTimeCycle::m_nCurrentLowCloudsRed;
-int CTimeCycle::m_nCurrentLowCloudsGreen;
-int CTimeCycle::m_nCurrentLowCloudsBlue;
-int CTimeCycle::m_nCurrentFluffyCloudsTopRed;
-int CTimeCycle::m_nCurrentFluffyCloudsTopGreen;
-int CTimeCycle::m_nCurrentFluffyCloudsTopBlue;
-int CTimeCycle::m_nCurrentFluffyCloudsBottomRed;
-int CTimeCycle::m_nCurrentFluffyCloudsBottomGreen;
-int CTimeCycle::m_nCurrentFluffyCloudsBottomBlue;
+int32 CTimeCycle::m_nCurrentLowCloudsRed;
+int32 CTimeCycle::m_nCurrentLowCloudsGreen;
+int32 CTimeCycle::m_nCurrentLowCloudsBlue;
+int32 CTimeCycle::m_nCurrentFluffyCloudsTopRed;
+int32 CTimeCycle::m_nCurrentFluffyCloudsTopGreen;
+int32 CTimeCycle::m_nCurrentFluffyCloudsTopBlue;
+int32 CTimeCycle::m_nCurrentFluffyCloudsBottomRed;
+int32 CTimeCycle::m_nCurrentFluffyCloudsBottomGreen;
+int32 CTimeCycle::m_nCurrentFluffyCloudsBottomBlue;
float CTimeCycle::m_fCurrentBlurRed;
float CTimeCycle::m_fCurrentBlurGreen;
float CTimeCycle::m_fCurrentBlurBlue;
@@ -118,13 +118,16 @@ float CTimeCycle::m_fCurrentWaterRed;
float CTimeCycle::m_fCurrentWaterGreen;
float CTimeCycle::m_fCurrentWaterBlue;
float CTimeCycle::m_fCurrentWaterAlpha;
-int CTimeCycle::m_nCurrentFogColourRed;
-int CTimeCycle::m_nCurrentFogColourGreen;
-int CTimeCycle::m_nCurrentFogColourBlue;
+int32 CTimeCycle::m_nCurrentFogColourRed;
+int32 CTimeCycle::m_nCurrentFogColourGreen;
+int32 CTimeCycle::m_nCurrentFogColourBlue;
-int CTimeCycle::m_FogReduction;
+int32 CTimeCycle::m_FogReduction;
+bool CTimeCycle::m_bExtraColourOn;
+int32 CTimeCycle::m_ExtraColour;
+float CTimeCycle::m_ExtraColourInter;
-int CTimeCycle::m_CurrentStoredValue;
+int32 CTimeCycle::m_CurrentStoredValue;
CVector CTimeCycle::m_VectorToSun[16];
float CTimeCycle::m_fShadowFrontX[16];
float CTimeCycle::m_fShadowFrontY[16];
@@ -133,7 +136,6 @@ float CTimeCycle::m_fShadowSideY[16];
float CTimeCycle::m_fShadowDisplacementX[16];
float CTimeCycle::m_fShadowDisplacementY[16];
-
void
CTimeCycle::Initialise(void)
{
@@ -233,15 +235,15 @@ CTimeCycle::Initialise(void)
m_nSunCoronaRed[h][w] = sunCoronaR;
m_nSunCoronaGreen[h][w] = sunCoronaG;
m_nSunCoronaBlue[h][w] = sunCoronaB;
- m_fSunSize[h][w] = sunSz;
- m_fSpriteSize[h][w] = sprSz;
- m_fSpriteBrightness[h][w] = sprBght;
+ m_fSunSize[h][w] = sunSz * 10.0f;
+ m_fSpriteSize[h][w] = sprSz * 10.0f;
+ m_fSpriteBrightness[h][w] = sprBght * 10.0f;
m_nShadowStrength[h][w] = shad;
m_nLightShadowStrength[h][w] = lightShad;
m_nPoleShadowStrength[h][w] = poleShad;
m_fFarClip[h][w] = farClp;
m_fFogStart[h][w] = fogSt;
- m_fLightsOnGroundBrightness[h][w] = lightGnd;
+ m_fLightsOnGroundBrightness[h][w] = lightGnd * 10.0f;
m_nLowCloudsRed[h][w] = cloudR;
m_nLowCloudsGreen[h][w] = cloudG;
m_nLowCloudsBlue[h][w] = cloudB;
@@ -265,6 +267,51 @@ CTimeCycle::Initialise(void)
debug("CTimeCycle ready\n");
}
+static float interp_c0, interp_c1, interp_c2, interp_c3;
+
+float CTimeCycle::Interpolate(int8 *a, int8 *b)
+{
+ return a[CWeather::OldWeatherType] * interp_c0 +
+ b[CWeather::OldWeatherType] * interp_c1 +
+ a[CWeather::NewWeatherType] * interp_c2 +
+ b[CWeather::NewWeatherType] * interp_c3;
+}
+
+float CTimeCycle::Interpolate(uint8 *a, uint8 *b)
+{
+ return a[CWeather::OldWeatherType] * interp_c0 +
+ b[CWeather::OldWeatherType] * interp_c1 +
+ a[CWeather::NewWeatherType] * interp_c2 +
+ b[CWeather::NewWeatherType] * interp_c3;
+}
+
+float CTimeCycle::Interpolate(int16 *a, int16 *b)
+{
+ return a[CWeather::OldWeatherType] * interp_c0 +
+ b[CWeather::OldWeatherType] * interp_c1 +
+ a[CWeather::NewWeatherType] * interp_c2 +
+ b[CWeather::NewWeatherType] * interp_c3;
+}
+
+void
+CTimeCycle::StartExtraColour(int32 c, bool fade)
+{
+ m_bExtraColourOn = true;
+ m_ExtraColour = c;
+ if(fade)
+ m_ExtraColourInter = 0.0f;
+ else
+ m_ExtraColourInter = 1.0f;
+}
+
+void
+CTimeCycle::StopExtraColour(bool fade)
+{
+ m_bExtraColourOn = false;
+ if(!fade)
+ m_ExtraColourInter = 0.0f;
+}
+
void
CTimeCycle::Update(void)
{
@@ -274,12 +321,12 @@ CTimeCycle::Update(void)
int w2 = CWeather::NewWeatherType;
float timeInterp = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f;
// coefficients for a bilinear interpolation
- float c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue);
- float c1 = timeInterp * (1.0f-CWeather::InterpolationValue);
- float c2 = (1.0f-timeInterp) * CWeather::InterpolationValue;
- float c3 = timeInterp * CWeather::InterpolationValue;
+ interp_c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue);
+ interp_c1 = timeInterp * (1.0f-CWeather::InterpolationValue);
+ interp_c2 = (1.0f-timeInterp) * CWeather::InterpolationValue;
+ interp_c3 = timeInterp * CWeather::InterpolationValue;
-#define INTERP(v) v[h1][w1]*c0 + v[h2][w1]*c1 + v[h1][w2]*c2 + v[h2][w2]*c3;
+#define INTERP(v) Interpolate(v[h1], v[h2])
m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed);
m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen);
@@ -317,15 +364,15 @@ CTimeCycle::Update(void)
m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen);
m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue);
- m_fCurrentSunSize = INTERP(m_fSunSize);
- m_fCurrentSpriteSize = INTERP(m_fSpriteSize);
- m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness);
+ m_fCurrentSunSize = INTERP(m_fSunSize)/10.0f;
+ m_fCurrentSpriteSize = INTERP(m_fSpriteSize)/10.0f;
+ m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness)/10.0f;
m_nCurrentShadowStrength = INTERP(m_nShadowStrength);
m_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength);
m_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength);
m_fCurrentFarClip = INTERP(m_fFarClip);
m_fCurrentFogStart = INTERP(m_fFogStart);
- m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness);
+ m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness)/10.0f;
m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed);
m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen);
@@ -347,6 +394,7 @@ CTimeCycle::Update(void)
m_fCurrentWaterGreen = INTERP(m_fWaterGreen);
m_fCurrentWaterBlue = INTERP(m_fWaterBlue);
m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha);
+#undef INTERP
if(m_FogReduction != 0)
m_fCurrentFarClip = Max(m_fCurrentFarClip, m_FogReduction/64.0f * 650.0f);
@@ -360,7 +408,88 @@ CTimeCycle::Update(void)
sunPos.z = 0.2f - Cos(sunAngle);
sunPos.Normalise();
- // TODO(MIAMI): extra colours
+ if(m_bExtraColourOn)
+ m_ExtraColourInter = Min(1.0f, m_ExtraColourInter + CTimer::GetTimeStep()/120.0f);
+ else
+ m_ExtraColourInter = Max(-.0f, m_ExtraColourInter - CTimer::GetTimeStep()/120.0f);
+ if(m_ExtraColourInter > 0.0f){
+#define INTERP(extra,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS] + (1.0f-m_ExtraColourInter)*cur)
+#define INTERPscl(extra,scl,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS]/scl + (1.0f-m_ExtraColourInter)*cur)
+ if(m_nSkyTopRed[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 ||
+ m_nSkyTopGreen[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 ||
+ m_nSkyTopBlue[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0){
+ m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed,m_nCurrentSkyTopRed);
+ m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen,m_nCurrentSkyTopGreen);
+ m_nCurrentSkyTopBlue = INTERP(m_nSkyTopBlue,m_nCurrentSkyTopBlue);
+
+ m_nCurrentSkyBottomRed = INTERP(m_nSkyBottomRed,m_nCurrentSkyBottomRed);
+ m_nCurrentSkyBottomGreen = INTERP(m_nSkyBottomGreen,m_nCurrentSkyBottomGreen);
+ m_nCurrentSkyBottomBlue = INTERP(m_nSkyBottomBlue,m_nCurrentSkyBottomBlue);
+
+ m_nCurrentSunCoreRed = INTERP(m_nSunCoreRed,m_nCurrentSunCoreRed);
+ m_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen,m_nCurrentSunCoreGreen);
+ m_nCurrentSunCoreBlue = INTERP(m_nSunCoreBlue,m_nCurrentSunCoreBlue);
+
+ m_nCurrentSunCoronaRed = INTERP(m_nSunCoronaRed,m_nCurrentSunCoronaRed);
+ m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen,m_nCurrentSunCoronaGreen);
+ m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue,m_nCurrentSunCoronaBlue);
+
+ m_fCurrentSunSize = INTERPscl(m_fSunSize,10.0f,m_fCurrentSunSize);
+
+ m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed,m_nCurrentLowCloudsRed);
+ m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen,m_nCurrentLowCloudsGreen);
+ m_nCurrentLowCloudsBlue = INTERP(m_nLowCloudsBlue,m_nCurrentLowCloudsBlue);
+
+ m_nCurrentFluffyCloudsTopRed = INTERP(m_nFluffyCloudsTopRed,m_nCurrentFluffyCloudsTopRed);
+ m_nCurrentFluffyCloudsTopGreen = INTERP(m_nFluffyCloudsTopGreen,m_nCurrentFluffyCloudsTopGreen);
+ m_nCurrentFluffyCloudsTopBlue = INTERP(m_nFluffyCloudsTopBlue,m_nCurrentFluffyCloudsTopBlue);
+
+ m_nCurrentFluffyCloudsBottomRed = INTERP(m_nFluffyCloudsBottomRed,m_nCurrentFluffyCloudsBottomRed);
+ m_nCurrentFluffyCloudsBottomGreen = INTERP(m_nFluffyCloudsBottomGreen,m_nCurrentFluffyCloudsBottomGreen);
+ m_nCurrentFluffyCloudsBottomBlue = INTERP(m_nFluffyCloudsBottomBlue,m_nCurrentFluffyCloudsBottomBlue);
+
+ m_fCurrentWaterRed = INTERP(m_fWaterRed,m_fCurrentWaterRed);
+ m_fCurrentWaterGreen = INTERP(m_fWaterGreen,m_fCurrentWaterGreen);
+ m_fCurrentWaterBlue = INTERP(m_fWaterBlue,m_fCurrentWaterBlue);
+ m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha,m_fCurrentWaterAlpha);
+ }
+
+ m_fCurrentAmbientRed = INTERP(m_nAmbientRed,m_fCurrentAmbientRed);
+ m_fCurrentAmbientGreen = INTERP(m_nAmbientGreen,m_fCurrentAmbientGreen);
+ m_fCurrentAmbientBlue = INTERP(m_nAmbientBlue,m_fCurrentAmbientBlue);
+
+ m_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj,m_fCurrentAmbientRed_Obj);
+ m_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj,m_fCurrentAmbientGreen_Obj);
+ m_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj,m_fCurrentAmbientBlue_Obj);
+
+ m_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl,m_fCurrentAmbientRed_Bl);
+ m_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl,m_fCurrentAmbientGreen_Bl);
+ m_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl,m_fCurrentAmbientBlue_Bl);
+
+ m_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl,m_fCurrentAmbientRed_Obj_Bl);
+ m_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl,m_fCurrentAmbientGreen_Obj_Bl);
+ m_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl,m_fCurrentAmbientBlue_Obj_Bl);
+
+ m_fCurrentDirectionalRed = INTERP(m_nDirectionalRed,m_fCurrentDirectionalRed);
+ m_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen,m_fCurrentDirectionalGreen);
+ m_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue,m_fCurrentDirectionalBlue);
+
+ m_fCurrentSpriteSize = INTERPscl(m_fSpriteSize,10.0f,m_fCurrentSpriteSize);
+ m_fCurrentSpriteBrightness = INTERPscl(m_fSpriteBrightness,10.0f,m_fCurrentSpriteBrightness);
+ m_nCurrentShadowStrength = INTERP(m_nShadowStrength,m_nCurrentShadowStrength);
+ m_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength,m_nCurrentLightShadowStrength);
+ m_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength,m_nCurrentPoleShadowStrength);
+ m_fCurrentFarClip = INTERP(m_fFarClip,m_fCurrentFarClip);
+ m_fCurrentFogStart = INTERP(m_fFogStart,m_fCurrentFogStart);
+ m_fCurrentLightsOnGroundBrightness = INTERPscl(m_fLightsOnGroundBrightness,10.0f,m_fCurrentLightsOnGroundBrightness);
+
+ m_fCurrentBlurRed = INTERP(m_fBlurRed,m_fCurrentBlurRed);
+ m_fCurrentBlurGreen = INTERP(m_fBlurGreen,m_fCurrentBlurGreen);
+ m_fCurrentBlurBlue = INTERP(m_fBlurBlue,m_fCurrentBlurBlue);
+
+#undef INTERP
+#undef INTERPscl
+ }
if(TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE)
TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, 5, MOTION_BLUR_LIGHT_SCENE);
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index 832b36e2..ad079a95 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -2,58 +2,58 @@
class CTimeCycle
{
- static int m_nAmbientRed[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
- static int m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
- static int m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
- static int m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
- static int m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
- static int m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
- static int m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
- static int m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
- static int m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
- static int m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
- static int m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
- static int m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
- static int m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
- static int m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
- static int m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
- static int m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
- static int m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
- static float m_fSunSize[NUMHOURS][NUMWEATHERS];
- static float m_fSpriteSize[NUMHOURS][NUMWEATHERS];
- static float m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
- static short m_nShadowStrength[NUMHOURS][NUMWEATHERS];
- static short m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
- static short m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
- static float m_fFogStart[NUMHOURS][NUMWEATHERS];
- static float m_fFarClip[NUMHOURS][NUMWEATHERS];
- static float m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
- static int m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
- static int m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
- static int m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
- static int m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
- static int m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
- static int m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
- static int m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
- static int m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
- static int m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
- static float m_fBlurRed[NUMHOURS][NUMWEATHERS];
- static float m_fBlurGreen[NUMHOURS][NUMWEATHERS];
- static float m_fBlurBlue[NUMHOURS][NUMWEATHERS];
- static float m_fWaterRed[NUMHOURS][NUMWEATHERS];
- static float m_fWaterGreen[NUMHOURS][NUMWEATHERS];
- static float m_fWaterBlue[NUMHOURS][NUMWEATHERS];
- static float m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyTopRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoreRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];
+ static int8 m_fSunSize[NUMHOURS][NUMWEATHERS];
+ static int8 m_fSpriteSize[NUMHOURS][NUMWEATHERS];
+ static int8 m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nShadowStrength[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
+ static int16 m_fFogStart[NUMHOURS][NUMWEATHERS];
+ static int16 m_fFarClip[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fBlurRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fBlurGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fBlurBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterRed[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterGreen[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterBlue[NUMHOURS][NUMWEATHERS];
+ static uint8 m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
static float m_fCurrentAmbientRed;
static float m_fCurrentAmbientGreen;
@@ -70,36 +70,36 @@ class CTimeCycle
static float m_fCurrentDirectionalRed;
static float m_fCurrentDirectionalGreen;
static float m_fCurrentDirectionalBlue;
- static int m_nCurrentSkyTopRed;
- static int m_nCurrentSkyTopGreen;
- static int m_nCurrentSkyTopBlue;
- static int m_nCurrentSkyBottomRed;
- static int m_nCurrentSkyBottomGreen;
- static int m_nCurrentSkyBottomBlue;
- static int m_nCurrentSunCoreRed;
- static int m_nCurrentSunCoreGreen;
- static int m_nCurrentSunCoreBlue;
- static int m_nCurrentSunCoronaRed;
- static int m_nCurrentSunCoronaGreen;
- static int m_nCurrentSunCoronaBlue;
+ static int32 m_nCurrentSkyTopRed;
+ static int32 m_nCurrentSkyTopGreen;
+ static int32 m_nCurrentSkyTopBlue;
+ static int32 m_nCurrentSkyBottomRed;
+ static int32 m_nCurrentSkyBottomGreen;
+ static int32 m_nCurrentSkyBottomBlue;
+ static int32 m_nCurrentSunCoreRed;
+ static int32 m_nCurrentSunCoreGreen;
+ static int32 m_nCurrentSunCoreBlue;
+ static int32 m_nCurrentSunCoronaRed;
+ static int32 m_nCurrentSunCoronaGreen;
+ static int32 m_nCurrentSunCoronaBlue;
static float m_fCurrentSunSize;
static float m_fCurrentSpriteSize;
static float m_fCurrentSpriteBrightness;
- static int m_nCurrentShadowStrength;
- static int m_nCurrentLightShadowStrength;
- static int m_nCurrentPoleShadowStrength;
+ static int32 m_nCurrentShadowStrength;
+ static int32 m_nCurrentLightShadowStrength;
+ static int32 m_nCurrentPoleShadowStrength;
static float m_fCurrentFogStart;
static float m_fCurrentFarClip;
static float m_fCurrentLightsOnGroundBrightness;
- static int m_nCurrentLowCloudsRed;
- static int m_nCurrentLowCloudsGreen;
- static int m_nCurrentLowCloudsBlue;
- static int m_nCurrentFluffyCloudsTopRed;
- static int m_nCurrentFluffyCloudsTopGreen;
- static int m_nCurrentFluffyCloudsTopBlue;
- static int m_nCurrentFluffyCloudsBottomRed;
- static int m_nCurrentFluffyCloudsBottomGreen;
- static int m_nCurrentFluffyCloudsBottomBlue;
+ static int32 m_nCurrentLowCloudsRed;
+ static int32 m_nCurrentLowCloudsGreen;
+ static int32 m_nCurrentLowCloudsBlue;
+ static int32 m_nCurrentFluffyCloudsTopRed;
+ static int32 m_nCurrentFluffyCloudsTopGreen;
+ static int32 m_nCurrentFluffyCloudsTopBlue;
+ static int32 m_nCurrentFluffyCloudsBottomRed;
+ static int32 m_nCurrentFluffyCloudsBottomGreen;
+ static int32 m_nCurrentFluffyCloudsBottomBlue;
static float m_fCurrentBlurRed;
static float m_fCurrentBlurGreen;
static float m_fCurrentBlurBlue;
@@ -107,14 +107,17 @@ class CTimeCycle
static float m_fCurrentWaterGreen;
static float m_fCurrentWaterBlue;
static float m_fCurrentWaterAlpha;
- static int m_nCurrentFogColourRed;
- static int m_nCurrentFogColourGreen;
- static int m_nCurrentFogColourBlue;
+ static int32 m_nCurrentFogColourRed;
+ static int32 m_nCurrentFogColourGreen;
+ static int32 m_nCurrentFogColourBlue;
- static int m_FogReduction;
+ static int32 m_FogReduction;
public:
- static int m_CurrentStoredValue;
+ static bool m_bExtraColourOn;
+ static int32 m_ExtraColour;
+ static float m_ExtraColourInter;
+ static int32 m_CurrentStoredValue;
static CVector m_VectorToSun[16];
static float m_fShadowFrontX[16];
static float m_fShadowFrontY[16];
@@ -138,51 +141,56 @@ public:
static float GetDirectionalRed(void) { return m_fCurrentDirectionalRed; }
static float GetDirectionalGreen(void) { return m_fCurrentDirectionalGreen; }
static float GetDirectionalBlue(void) { return m_fCurrentDirectionalBlue; }
- static int GetSkyTopRed(void) { return m_nCurrentSkyTopRed; }
- static int GetSkyTopGreen(void) { return m_nCurrentSkyTopGreen; }
- static int GetSkyTopBlue(void) { return m_nCurrentSkyTopBlue; }
- static int GetSkyBottomRed(void) { return m_nCurrentSkyBottomRed; }
- static int GetSkyBottomGreen(void) { return m_nCurrentSkyBottomGreen; }
- static int GetSkyBottomBlue(void) { return m_nCurrentSkyBottomBlue; }
- static int GetSunCoreRed(void) { return m_nCurrentSunCoreRed; }
- static int GetSunCoreGreen(void) { return m_nCurrentSunCoreGreen; }
- static int GetSunCoreBlue(void) { return m_nCurrentSunCoreBlue; }
- static int GetSunCoronaRed(void) { return m_nCurrentSunCoronaRed; }
- static int GetSunCoronaGreen(void) { return m_nCurrentSunCoronaGreen; }
- static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }
+ static int32 GetSkyTopRed(void) { return m_nCurrentSkyTopRed; }
+ static int32 GetSkyTopGreen(void) { return m_nCurrentSkyTopGreen; }
+ static int32 GetSkyTopBlue(void) { return m_nCurrentSkyTopBlue; }
+ static int32 GetSkyBottomRed(void) { return m_nCurrentSkyBottomRed; }
+ static int32 GetSkyBottomGreen(void) { return m_nCurrentSkyBottomGreen; }
+ static int32 GetSkyBottomBlue(void) { return m_nCurrentSkyBottomBlue; }
+ static int32 GetSunCoreRed(void) { return m_nCurrentSunCoreRed; }
+ static int32 GetSunCoreGreen(void) { return m_nCurrentSunCoreGreen; }
+ static int32 GetSunCoreBlue(void) { return m_nCurrentSunCoreBlue; }
+ static int32 GetSunCoronaRed(void) { return m_nCurrentSunCoronaRed; }
+ static int32 GetSunCoronaGreen(void) { return m_nCurrentSunCoronaGreen; }
+ static int32 GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }
static float GetSunSize(void) { return m_fCurrentSunSize; }
static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; }
static float GetSpriteSize(void) { return m_fCurrentSpriteSize; }
- static int GetShadowStrength(void) { return m_nCurrentShadowStrength; }
- static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }
+ static int32 GetShadowStrength(void) { return m_nCurrentShadowStrength; }
+ static int32 GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }
static float GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; }
static float GetFarClip(void) { return m_fCurrentFarClip; }
static float GetFogStart(void) { return m_fCurrentFogStart; }
- static int GetLowCloudsRed(void) { return m_nCurrentLowCloudsRed; }
- static int GetLowCloudsGreen(void) { return m_nCurrentLowCloudsGreen; }
- static int GetLowCloudsBlue(void) { return m_nCurrentLowCloudsBlue; }
- static int GetFluffyCloudsTopRed(void) { return m_nCurrentFluffyCloudsTopRed; }
- static int GetFluffyCloudsTopGreen(void) { return m_nCurrentFluffyCloudsTopGreen; }
- static int GetFluffyCloudsTopBlue(void) { return m_nCurrentFluffyCloudsTopBlue; }
- static int GetFluffyCloudsBottomRed(void) { return m_nCurrentFluffyCloudsBottomRed; }
- static int GetFluffyCloudsBottomGreen(void) { return m_nCurrentFluffyCloudsBottomGreen; }
- static int GetFluffyCloudsBottomBlue(void) { return m_nCurrentFluffyCloudsBottomBlue; }
- static int GetFogRed(void) { return m_nCurrentFogColourRed; }
- static int GetFogGreen(void) { return m_nCurrentFogColourGreen; }
- static int GetFogBlue(void) { return m_nCurrentFogColourBlue; }
- static int GetFogReduction(void) { return m_FogReduction; }
+ static int32 GetLowCloudsRed(void) { return m_nCurrentLowCloudsRed; }
+ static int32 GetLowCloudsGreen(void) { return m_nCurrentLowCloudsGreen; }
+ static int32 GetLowCloudsBlue(void) { return m_nCurrentLowCloudsBlue; }
+ static int32 GetFluffyCloudsTopRed(void) { return m_nCurrentFluffyCloudsTopRed; }
+ static int32 GetFluffyCloudsTopGreen(void) { return m_nCurrentFluffyCloudsTopGreen; }
+ static int32 GetFluffyCloudsTopBlue(void) { return m_nCurrentFluffyCloudsTopBlue; }
+ static int32 GetFluffyCloudsBottomRed(void) { return m_nCurrentFluffyCloudsBottomRed; }
+ static int32 GetFluffyCloudsBottomGreen(void) { return m_nCurrentFluffyCloudsBottomGreen; }
+ static int32 GetFluffyCloudsBottomBlue(void) { return m_nCurrentFluffyCloudsBottomBlue; }
+ static int32 GetFogRed(void) { return m_nCurrentFogColourRed; }
+ static int32 GetFogGreen(void) { return m_nCurrentFogColourGreen; }
+ static int32 GetFogBlue(void) { return m_nCurrentFogColourBlue; }
+ static int32 GetFogReduction(void) { return m_FogReduction; }
- static int GetBlurRed(void) { return m_fCurrentBlurRed; }
- static int GetBlurGreen(void) { return m_fCurrentBlurGreen; }
- static int GetBlurBlue(void) { return m_fCurrentBlurBlue; }
- static int GetWaterRed(void) { return m_fCurrentWaterRed; }
- static int GetWaterGreen(void) { return m_fCurrentWaterGreen; }
- static int GetWaterBlue(void) { return m_fCurrentWaterBlue; }
- static int GetWaterAlpha(void) { return m_fCurrentWaterAlpha; }
+ static int32 GetBlurRed(void) { return m_fCurrentBlurRed; }
+ static int32 GetBlurGreen(void) { return m_fCurrentBlurGreen; }
+ static int32 GetBlurBlue(void) { return m_fCurrentBlurBlue; }
+ static int32 GetWaterRed(void) { return m_fCurrentWaterRed; }
+ static int32 GetWaterGreen(void) { return m_fCurrentWaterGreen; }
+ static int32 GetWaterBlue(void) { return m_fCurrentWaterBlue; }
+ static int32 GetWaterAlpha(void) { return m_fCurrentWaterAlpha; }
static void Initialise(void);
static void Update(void);
+ static float Interpolate(int8 *a, int8 *b);
+ static float Interpolate(uint8 *a, uint8 *b);
+ static float Interpolate(int16 *a, int16 *b);
+ static void StartExtraColour(int32 c, bool fade);
+ static void StopExtraColour(bool fade);
static CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; }
static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; }
static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; }
diff --git a/src/render/Weather.h b/src/render/Weather.h
index ae09e5d1..809bb787 100644
--- a/src/render/Weather.h
+++ b/src/render/Weather.h
@@ -6,7 +6,9 @@ enum {
WEATHER_FOGGY,
WEATHER_EXTRA_SUNNY,
WEATHER_HURRICANE,
- WEATHER_TOTAL
+ WEATHER_TOTAL,
+
+ WEATHER_EXTRACOLOURS = 6
};
class CWeather
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 7ce1d4f5..58791ce2 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -399,6 +399,125 @@ RenderSkeleton(RpHAnimHierarchy *hier)
}
#endif
+
+RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset)
+{
+ RwIm2DVertex vx[4];
+
+ /*
+ * Render an opaque white 2D quad at the given coordinates and
+ * spanning a whole texture.
+ */
+
+ RwIm2DVertexSetScreenX(&vx[0], x1);
+ RwIm2DVertexSetScreenY(&vx[0], y1);
+ RwIm2DVertexSetScreenZ(&vx[0], z);
+ RwIm2DVertexSetIntRGBA(&vx[0], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);
+ RwIm2DVertexSetU(&vx[0], uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[0], uvOffset, recipCamZ);
+
+ RwIm2DVertexSetScreenX(&vx[1], x1);
+ RwIm2DVertexSetScreenY(&vx[1], y2);
+ RwIm2DVertexSetScreenZ(&vx[1], z);
+ RwIm2DVertexSetIntRGBA(&vx[1], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);
+ RwIm2DVertexSetU(&vx[1], uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[1], 1.0f + uvOffset, recipCamZ);
+
+ RwIm2DVertexSetScreenX(&vx[2], x2);
+ RwIm2DVertexSetScreenY(&vx[2], y1);
+ RwIm2DVertexSetScreenZ(&vx[2], z);
+ RwIm2DVertexSetIntRGBA(&vx[2], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);
+ RwIm2DVertexSetU(&vx[2], 1.0f + uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[2], uvOffset, recipCamZ);
+
+ RwIm2DVertexSetScreenX(&vx[3], x2);
+ RwIm2DVertexSetScreenY(&vx[3], y2);
+ RwIm2DVertexSetScreenZ(&vx[3], z);
+ RwIm2DVertexSetIntRGBA(&vx[3], 255, 255, 255, 255);
+ RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);
+ RwIm2DVertexSetU(&vx[3], 1.0f + uvOffset, recipCamZ);
+ RwIm2DVertexSetV(&vx[3], 1.0f + uvOffset, recipCamZ);
+
+ RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
+
+ return TRUE;
+}
+
+bool b_cbsUseLTM = true;
+
+RpAtomic *cbsCalcMeanBSphereRadiusCB(RpAtomic *atomic, void *data)
+{
+ RwV3d atomicPos;
+
+ if ( b_cbsUseLTM )
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump)));
+ else
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump)));
+
+ RwV3d temp;
+ RwV3dSub(&temp, &atomicPos, &((RwSphere *)data)->center);
+ RwReal radius = RwV3dLength(&temp) + RpAtomicGetBoundingSphere(atomic)->radius;
+
+ if ( ((RwSphere *)data)->radius < radius )
+ ((RwSphere *)data)->radius = radius;
+
+ return atomic;
+}
+
+RpAtomic *cbsCalcMeanBSphereCenterCB(RpAtomic *atomic, void *data)
+{
+ RwV3d atomicPos;
+
+ if ( b_cbsUseLTM )
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump)));
+ else
+ RwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump)));
+
+ RwV3dAdd(&((RwSphere *)data)->center, &((RwSphere *)data)->center, &atomicPos);
+
+ return atomic;
+}
+
+RpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM)
+{
+ RwMatrix matrix;
+ RwSphere result = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ b_cbsUseLTM = useLTM;
+
+ if ( clump == nil || sphere == nil )
+ return nil;
+
+ sphere->radius = 0.0f;
+ sphere->center.x = 0.0f;
+ sphere->center.y = 0.0f;
+ sphere->center.z = 0.0f;
+
+ RwInt32 numAtomics = RpClumpGetNumAtomics(clump);
+ if ( numAtomics < 1.0f )
+ return nil;
+
+ RpClumpForAllAtomics(clump, cbsCalcMeanBSphereCenterCB, &result);
+
+ RwV3dScale(&result.center, &result.center, 1.0f/numAtomics);
+
+ RpClumpForAllAtomics(clump, cbsCalcMeanBSphereRadiusCB, &result);
+
+ if ( b_cbsUseLTM )
+ RwMatrixInvert(&matrix, RwFrameGetLTM(RpClumpGetFrame(clump)));
+ else
+ RwMatrixInvert(&matrix, RwFrameGetMatrix(RpClumpGetFrame(clump)));
+
+ RwV3dTransformPoints(&result.center, &result.center, 1, &matrix);
+
+ *sphere = result;
+
+ return clump;
+}
+
void
CameraSize(RwCamera * camera, RwRect * rect,
RwReal viewWindow, RwReal aspectRatio)
diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h
index 1862c7f1..3f1a3d19 100644
--- a/src/rw/RwHelper.h
+++ b/src/rw/RwHelper.h
@@ -29,6 +29,9 @@ RpAtomic *AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data);
void RenderSkeleton(RpHAnimHierarchy *hier);
#endif
+RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset);
+RpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM);
+
RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream);
RwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream);
RwTexDictionary *RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict);
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 3f329251..e06ce03b 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -2505,8 +2505,12 @@ CAutomobile::PreRender(void)
// end of lights
}
-//TODO(MIAMI): StoreShadowForVehicle once we have it
- CShadows::StoreShadowForCar(this);
+ if (IsRealHeli())
+ CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_HELI);
+ else if ( GetModelIndex() == MI_RCBARON)
+ CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_RCPLANE);
+ else
+ CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_CAR);
DoSunGlare();
diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp
index e52027f9..c32e72bc 100644
--- a/src/vehicles/Bike.cpp
+++ b/src/vehicles/Bike.cpp
@@ -1546,7 +1546,7 @@ CBike::PreRender(void)
}
AddDamagedVehicleParticles();
-//TODO(MIAMI): StoreShadowForVehicle once we have it
+ CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_BIKE);
CMatrix mat;
CVector pos;
diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp
index 00bb0023..a770f83d 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -557,6 +557,7 @@ CHeli::PreRender(void)
{
float radius = (GetPosition().z - FindPlayerCoors().z - 10.0f - 1.0f) * 0.3f + 10.0f;
HeliDustGenerate(this, radius, FindPlayerCoors().z, Max(16.0f - 4.0f*CTimer::GetTimeStep(), 2.0f));
+ CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_HELI);
}
void
@@ -592,7 +593,7 @@ CHeli::PreRenderAlways(void)
CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &shadowPos,
6.0f, 0.0f, 0.0f, -6.0f,
80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity,
- 50.0f, true, 1.0f);
+ 50.0f, true, 1.0f, nil, false);
CVector front = GetMatrix() * CVector(0.0f, 7.0f, 0.0f);
CVector toPlayer = FindPlayerCoors() - front;
diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp
index 129e4b2b..41d9c730 100644
--- a/src/weapons/BulletInfo.cpp
+++ b/src/weapons/BulletInfo.cpp
@@ -24,6 +24,10 @@
#include "World.h"
#include "SurfaceTable.h"
+#ifdef SQUEEZE_PERFORMANCE
+uint32 bulletInfoInUse;
+#endif
+
#define BULLET_LIFETIME (1000)
#define NUM_PED_BLOOD_PARTICLES (8)
#define BLOOD_PARTICLE_OFFSET (CVector(0.0f, 0.0f, 0.0f))
@@ -47,6 +51,9 @@ void CBulletInfo::Initialise(void)
gaBulletInfo[i].m_pSource = nil;
}
debug("CBulletInfo ready\n");
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse = 0;
+#endif
}
void CBulletInfo::Shutdown(void)
@@ -71,11 +78,19 @@ bool CBulletInfo::AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosit
gaBulletInfo[i].m_vecSpeed = vecSpeed;
gaBulletInfo[i].m_fTimer = CTimer::GetTimeInMilliseconds() + BULLET_LIFETIME;
gaBulletInfo[i].m_bInUse = true;
+
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse++;
+#endif
return true;
}
void CBulletInfo::Update(void)
{
+#ifdef SQUEEZE_PERFORMANCE
+ if (bulletInfoInUse == 0)
+ return;
+#endif
bPlayerSniperBullet = false;
for (int i = 0; i < NUM_BULLETS; i++) {
CBulletInfo* pBullet = &gaBulletInfo[i];
@@ -83,8 +98,12 @@ void CBulletInfo::Update(void)
pBullet->m_pSource = nil;
if (!pBullet->m_bInUse)
continue;
- if (CTimer::GetTimeInMilliseconds() > pBullet->m_fTimer)
+ if (CTimer::GetTimeInMilliseconds() > pBullet->m_fTimer) {
pBullet->m_bInUse = false;
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse--;
+#endif
+ }
CVector vecOldPos = pBullet->m_vecPosition;
CVector vecNewPos = pBullet->m_vecPosition + pBullet->m_vecSpeed * CTimer::GetTimeStep() * 0.5f;
CWorld::bIncludeCarTyres = true;
@@ -108,6 +127,9 @@ void CBulletInfo::Update(void)
pPed->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage, (ePedPieceTypes)point.pieceB, pPed->GetLocalDirection(pPed->GetPosition() - point.point));
CEventList::RegisterEvent(pPed->m_nPedType == PEDTYPE_COP ? EVENT_SHOOT_COP : EVENT_SHOOT_PED, EVENT_ENTITY_PED, pPed, (CPed*)pBullet->m_pSource, 1000);
pBullet->m_bInUse = false;
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse--;
+#endif
vecNewPos = point.point;
}
if (CGame::nastyGame) {
@@ -130,6 +152,9 @@ void CBulletInfo::Update(void)
}
}
pBullet->m_bInUse = false;
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse--;
+#endif
vecNewPos = point.point;
}
}
@@ -144,6 +169,9 @@ void CBulletInfo::Update(void)
}
#ifdef FIX_BUGS
pBullet->m_bInUse = false;
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse--;
+#endif
vecNewPos = point.point;
#endif
}
@@ -163,6 +191,9 @@ void CBulletInfo::Update(void)
}
#ifdef FIX_BUGS
pBullet->m_bInUse = false;
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse--;
+#endif
vecNewPos = point.point;
#endif
}
@@ -213,8 +244,12 @@ void CBulletInfo::Update(void)
}
pBullet->m_vecPosition = vecNewPos;
if (pBullet->m_vecPosition.x < -MAP_BORDER || pBullet->m_vecPosition.x > MAP_BORDER ||
- pBullet->m_vecPosition.y < -MAP_BORDER || pBullet->m_vecPosition.y > MAP_BORDER)
+ pBullet->m_vecPosition.y < -MAP_BORDER || pBullet->m_vecPosition.y > MAP_BORDER) {
pBullet->m_bInUse = false;
+#ifdef SQUEEZE_PERFORMANCE
+ bulletInfoInUse--;
+#endif
+ }
}
}
diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp
index 35e55b36..4150852a 100644
--- a/src/weapons/ProjectileInfo.cpp
+++ b/src/weapons/ProjectileInfo.cpp
@@ -13,6 +13,10 @@
#include "Weapon.h"
#include "World.h"
+#ifdef SQUEEZE_PERFORMANCE
+uint32 projectileInUse;
+#endif
+
CProjectileInfo gaProjectileInfo[NUM_PROJECTILES];
CProjectile *CProjectileInfo::ms_apProjectile[NUM_PROJECTILES];
@@ -30,6 +34,10 @@ CProjectileInfo::Initialise()
}
debug("CProjectileInfo ready\n");
+
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse = 0;
+#endif
}
void
@@ -163,6 +171,10 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
ms_apProjectile[i]->m_fElasticity = elasticity;
ms_apProjectile[i]->m_nSpecialCollisionResponseCases = SpecialCollisionResponseCase;
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse++;
+#endif
+
gaProjectileInfo[i].m_bInUse = true;
CWorld::Add(ms_apProjectile[i]);
@@ -178,6 +190,9 @@ void
CProjectileInfo::RemoveProjectile(CProjectileInfo *info, CProjectile *projectile)
{
RemoveNotAdd(info->m_pSource, info->m_eWeaponType, projectile->GetPosition());
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse--;
+#endif
info->m_bInUse = false;
CWorld::Remove(projectile);
@@ -205,6 +220,11 @@ CProjectileInfo::RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector p
void
CProjectileInfo::Update()
{
+#ifdef SQUEEZE_PERFORMANCE
+ if (projectileInUse == 0)
+ return;
+#endif
+
for (int i = 0; i < ARRAY_SIZE(gaProjectileInfo); i++) {
if (!gaProjectileInfo[i].m_bInUse) continue;
@@ -213,6 +233,10 @@ CProjectileInfo::Update()
gaProjectileInfo[i].m_pSource = nil;
if (ms_apProjectile[i] == nil) {
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse--;
+#endif
+
gaProjectileInfo[i].m_bInUse = false;
continue;
}
@@ -276,6 +300,10 @@ CProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, flo
if (pos.x >= x1 && pos.x <= x2 && pos.y >= y1 && pos.y <= y2 && pos.z >= z1 && pos.z <= z2) {
result = true;
if (remove) {
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse--;
+#endif
+
gaProjectileInfo[i].m_bInUse = false;
CWorld::Remove(ms_apProjectile[i]);
delete ms_apProjectile[i];
@@ -304,8 +332,17 @@ CProjectileInfo::RemoveDetonatorProjectiles()
void
CProjectileInfo::RemoveAllProjectiles()
{
+#ifdef SQUEEZE_PERFORMANCE
+ if (projectileInUse == 0)
+ return;
+#endif
+
for (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {
if (gaProjectileInfo[i].m_bInUse) {
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse--;
+#endif
+
gaProjectileInfo[i].m_bInUse = false;
CWorld::Remove(ms_apProjectile[i]);
delete ms_apProjectile[i];
@@ -316,12 +353,21 @@ CProjectileInfo::RemoveAllProjectiles()
bool
CProjectileInfo::RemoveIfThisIsAProjectile(CObject *object)
{
+#ifdef SQUEEZE_PERFORMANCE
+ if (projectileInUse == 0)
+ return false;
+#endif
+
int i = 0;
while (ms_apProjectile[i++] != object) {
if (i >= ARRAY_SIZE(ms_apProjectile))
return false;
}
+#ifdef SQUEEZE_PERFORMANCE
+ projectileInUse--;
+#endif
+
gaProjectileInfo[i].m_bInUse = false;
CWorld::Remove(ms_apProjectile[i]);
delete ms_apProjectile[i];
diff --git a/src/weapons/ShotInfo.cpp b/src/weapons/ShotInfo.cpp
index 6fc6341d..a70f3f7b 100644
--- a/src/weapons/ShotInfo.cpp
+++ b/src/weapons/ShotInfo.cpp
@@ -13,6 +13,9 @@
CShotInfo gaShotInfo[NUMSHOTINFOS];
float CShotInfo::ms_afRandTable[20];
+#ifdef SQUEEZE_PERFORMANCE
+uint32 shotInfoInUse;
+#endif
/*
Used for flamethrower. I don't know why it's name is CShotInfo.
@@ -41,6 +44,9 @@ CShotInfo::Initialise()
nextVal += 0.005f;
}
debug("CShotInfo ready\n");
+#ifdef SQUEEZE_PERFORMANCE
+ shotInfoInUse = 0;
+#endif
}
bool
@@ -54,6 +60,10 @@ CShotInfo::AddShot(CEntity *sourceEntity, eWeaponType weapon, CVector startPos,
if (slot == ARRAY_SIZE(gaShotInfo))
return false;
+#ifdef SQUEEZE_PERFORMANCE
+ shotInfoInUse++;
+#endif
+
gaShotInfo[slot].m_inUse = true;
gaShotInfo[slot].m_weapon = weapon;
gaShotInfo[slot].m_startPos = startPos;
@@ -87,6 +97,10 @@ CShotInfo::Shutdown()
void
CShotInfo::Update()
{
+#ifdef SQUEEZE_PERFORMANCE
+ if (shotInfoInUse == 0)
+ return;
+#endif
for (int slot = 0; slot < ARRAY_SIZE(gaShotInfo); slot++) {
CShotInfo &shot = gaShotInfo[slot];
if (shot.m_sourceEntity && shot.m_sourceEntity->IsPed() && !((CPed*)shot.m_sourceEntity)->IsPointerValid())
@@ -96,8 +110,12 @@ CShotInfo::Update()
continue;
CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(shot.m_weapon);
- if (CTimer::GetTimeInMilliseconds() > shot.m_timeout)
+ if (CTimer::GetTimeInMilliseconds() > shot.m_timeout) {
+#ifdef SQUEEZE_PERFORMANCE
+ shotInfoInUse--;
+#endif
shot.m_inUse = false;
+ }
if (weaponInfo->m_bSlowsDown)
shot.m_areaAffected *= pow(0.96, CTimer::GetTimeStep()); // FRAMERATE