implemented cBuoyancy
This commit is contained in:
parent
e9cafe340a
commit
ae69aaf5ce
@ -73,7 +73,7 @@ public:
|
|||||||
uint32 bRemoveFromWorld : 1;
|
uint32 bRemoveFromWorld : 1;
|
||||||
uint32 bHasHitWall : 1;
|
uint32 bHasHitWall : 1;
|
||||||
uint32 bImBeingRendered : 1;
|
uint32 bImBeingRendered : 1;
|
||||||
uint32 m_flagD8 : 1;
|
uint32 m_flagD8 : 1; // used by cBuoyancy::ProcessBuoyancy
|
||||||
uint32 bIsSubway : 1; // set when subway, but maybe different meaning?
|
uint32 bIsSubway : 1; // set when subway, but maybe different meaning?
|
||||||
uint32 bDrawLast : 1;
|
uint32 bDrawLast : 1;
|
||||||
uint32 m_flagD40 : 1;
|
uint32 m_flagD40 : 1;
|
||||||
|
@ -1240,7 +1240,7 @@ STARTPATCHES
|
|||||||
InjectHook(0x554FE0, &CWaterLevel::Shutdown, PATCH_JUMP);
|
InjectHook(0x554FE0, &CWaterLevel::Shutdown, PATCH_JUMP);
|
||||||
InjectHook(0x555010, &CWaterLevel::CreateWavyAtomic, PATCH_JUMP);
|
InjectHook(0x555010, &CWaterLevel::CreateWavyAtomic, PATCH_JUMP);
|
||||||
InjectHook(0x5552A0, &CWaterLevel::DestroyWavyAtomic, PATCH_JUMP);
|
InjectHook(0x5552A0, &CWaterLevel::DestroyWavyAtomic, PATCH_JUMP);
|
||||||
InjectHook(0x5552C0, &CWaterLevel::GetWaterLevel, PATCH_JUMP);
|
InjectHook(0x5552C0, (bool (*)(float,float,float,float*,bool))&CWaterLevel::GetWaterLevel, PATCH_JUMP);
|
||||||
InjectHook(0x555440, &CWaterLevel::GetWaterLevelNoWaves, PATCH_JUMP);
|
InjectHook(0x555440, &CWaterLevel::GetWaterLevelNoWaves, PATCH_JUMP);
|
||||||
InjectHook(0x5554E0, &CWaterLevel::RenderWater, PATCH_JUMP);
|
InjectHook(0x5554E0, &CWaterLevel::RenderWater, PATCH_JUMP);
|
||||||
InjectHook(0x556C30, &CWaterLevel::RenderOneFlatSmallWaterPoly, PATCH_JUMP);
|
InjectHook(0x556C30, &CWaterLevel::RenderOneFlatSmallWaterPoly, PATCH_JUMP);
|
||||||
|
@ -82,6 +82,7 @@ public:
|
|||||||
static void CreateWavyAtomic();
|
static void CreateWavyAtomic();
|
||||||
static void DestroyWavyAtomic();
|
static void DestroyWavyAtomic();
|
||||||
static bool GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ);
|
static bool GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ);
|
||||||
|
static bool GetWaterLevel(CVector coors, float *pfOutLevel, bool bDontCheckZ) { return GetWaterLevel(coors.x, coors.y, coors.z, pfOutLevel, bDontCheckZ); }
|
||||||
static bool GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel);
|
static bool GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel);
|
||||||
static void RenderWater();
|
static void RenderWater();
|
||||||
static void RenderOneFlatSmallWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
|
static void RenderOneFlatSmallWaterPoly (float fX, float fY, float fZ, RwRGBA const &color);
|
||||||
|
195
src/vehicles/Floater.cpp
Normal file
195
src/vehicles/Floater.cpp
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "patcher.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
#include "WaterLevel.h"
|
||||||
|
#include "ModelIndices.h"
|
||||||
|
#include "Physical.h"
|
||||||
|
#include "Vehicle.h"
|
||||||
|
#include "Floater.h"
|
||||||
|
|
||||||
|
cBuoyancy &mod_Buoyancy = *(cBuoyancy*)0x8F2674;
|
||||||
|
|
||||||
|
//static float fVolMultiplier = 1.0f;
|
||||||
|
static float &fVolMultiplier = *(float*)0x601394;
|
||||||
|
// amount of boat volume in bounding box
|
||||||
|
// 1.0-volume is the empty space in the bbox
|
||||||
|
static float fBoatVolumeDistribution[9] = {
|
||||||
|
// rear
|
||||||
|
0.75f, 0.9f, 0.75f,
|
||||||
|
0.95f, 1.0f, 0.95f,
|
||||||
|
0.3f, 0.7f, 0.3f
|
||||||
|
// bow
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
cBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *impulse, CVector *point)
|
||||||
|
{
|
||||||
|
m_numSteps = 2.0f;
|
||||||
|
|
||||||
|
if(!CWaterLevel::GetWaterLevel(phys->GetPosition(), &m_waterlevel, phys->m_flagD8))
|
||||||
|
return false;
|
||||||
|
m_matrix = phys->GetMatrix();
|
||||||
|
|
||||||
|
PreCalcSetup(phys, buoyancy);
|
||||||
|
SimpleCalcBuoyancy();
|
||||||
|
float f = CalcBuoyancyForce(phys, impulse, point);
|
||||||
|
if(m_isBoat)
|
||||||
|
return true;
|
||||||
|
return f != 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cBuoyancy::PreCalcSetup(CPhysical *phys, float buoyancy)
|
||||||
|
{
|
||||||
|
CColModel *colModel;
|
||||||
|
|
||||||
|
m_isBoat = phys->IsVehicle() && ((CVehicle*)phys)->IsBoat();
|
||||||
|
colModel = phys->GetColModel();
|
||||||
|
m_dimMin = colModel->boundingBox.min;
|
||||||
|
m_dimMax = colModel->boundingBox.max;
|
||||||
|
|
||||||
|
if(m_isBoat){
|
||||||
|
if(phys->GetModelIndex() == MI_PREDATOR){
|
||||||
|
m_dimMax.y *= 0.9f;
|
||||||
|
m_dimMin.y *= 0.9f;
|
||||||
|
}else if(phys->GetModelIndex() == MI_SPEEDER){
|
||||||
|
m_dimMax.y *= 1.1f;
|
||||||
|
m_dimMin.y *= 0.9f;
|
||||||
|
}else if(phys->GetModelIndex() == MI_REEFER){
|
||||||
|
m_dimMin.y *= 0.9f;
|
||||||
|
}else{
|
||||||
|
m_dimMax.y *= 0.9f;
|
||||||
|
m_dimMin.y *= 0.9f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_step = (m_dimMax - m_dimMin)/m_numSteps;
|
||||||
|
|
||||||
|
if(m_step.z > m_step.x && m_step.z > m_step.y){
|
||||||
|
m_stepRatio.x = m_step.x/m_step.z;
|
||||||
|
m_stepRatio.y = m_step.y/m_step.z;
|
||||||
|
m_stepRatio.z = 1.0f;
|
||||||
|
}else if(m_step.y > m_step.x && m_step.y > m_step.z){
|
||||||
|
m_stepRatio.x = m_step.x/m_step.y;
|
||||||
|
m_stepRatio.y = 1.0f;
|
||||||
|
m_stepRatio.z = m_step.z/m_step.y;
|
||||||
|
}else{
|
||||||
|
m_stepRatio.x = 1.0f;
|
||||||
|
m_stepRatio.y = m_step.y/m_step.x;
|
||||||
|
m_stepRatio.z = m_step.z/m_step.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_haveVolume = false;
|
||||||
|
m_numPartialVolumes = 1.0f;
|
||||||
|
m_volumeUnderWater = 0.0f;
|
||||||
|
m_impulse = CVector(0.0f, 0.0f, 0.0f);
|
||||||
|
m_position = phys->GetPosition();
|
||||||
|
m_positionZ = CVector(0.0f, 0.0f, m_position.z);
|
||||||
|
m_buoyancy = buoyancy;
|
||||||
|
m_waterlevel += m_waterLevelInc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cBuoyancy::SimpleCalcBuoyancy(void)
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
int ix, i;
|
||||||
|
tWaterLevel waterPosition;
|
||||||
|
|
||||||
|
// Floater is divided into 3x3 parts. Process and sum each of them
|
||||||
|
ix = 0;
|
||||||
|
for(x = m_dimMin.x; x <= m_dimMax.x; x += m_step.x){
|
||||||
|
i = ix;
|
||||||
|
for(y = m_dimMin.y; y <= m_dimMax.y; y += m_step.y){
|
||||||
|
CVector waterLevel(x, y, 0.0f);
|
||||||
|
FindWaterLevel(m_positionZ, &waterLevel, &waterPosition);
|
||||||
|
fVolMultiplier = m_isBoat ? fBoatVolumeDistribution[i] : 1.0f;
|
||||||
|
if(waterPosition != FLOATER_ABOVE_WATER)
|
||||||
|
SimpleSumBuoyancyData(waterLevel, waterPosition);
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
ix++;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_volumeUnderWater /= (m_dimMax.z - m_dimMin.z)*sq(m_numSteps+1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
cBuoyancy::SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition)
|
||||||
|
{
|
||||||
|
static float fThisVolume;
|
||||||
|
static CVector AverageOfWaterLevel;
|
||||||
|
static float fFraction;
|
||||||
|
static float fRemainingSlice;
|
||||||
|
|
||||||
|
float submerged = Abs(waterLevel.z - m_dimMin.z);
|
||||||
|
// subtract empty space from submerged volume
|
||||||
|
fThisVolume = submerged - (1.0f - fVolMultiplier);
|
||||||
|
if(fThisVolume < 0.0f)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
if(m_isBoat){
|
||||||
|
fThisVolume *= fVolMultiplier;
|
||||||
|
if(fThisVolume < 0.5f)
|
||||||
|
fThisVolume = 2.0f*sq(fThisVolume);
|
||||||
|
if(fThisVolume < 1.0f)
|
||||||
|
fThisVolume = sq(fThisVolume);
|
||||||
|
fThisVolume = sq(fThisVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_volumeUnderWater += fThisVolume;
|
||||||
|
|
||||||
|
AverageOfWaterLevel.x = waterLevel.x * m_stepRatio.x;
|
||||||
|
AverageOfWaterLevel.y = waterLevel.y * m_stepRatio.y;
|
||||||
|
AverageOfWaterLevel.z = (waterLevel.z+m_dimMin.z)/2.0f * m_stepRatio.z;
|
||||||
|
|
||||||
|
if(m_flipAverage)
|
||||||
|
AverageOfWaterLevel = -AverageOfWaterLevel;
|
||||||
|
|
||||||
|
fFraction = 1.0f/m_numPartialVolumes;
|
||||||
|
fRemainingSlice = 1.0f - fFraction;
|
||||||
|
m_impulse = m_impulse*fRemainingSlice + AverageOfWaterLevel*fThisVolume*fFraction;
|
||||||
|
m_numPartialVolumes += 1.0f;
|
||||||
|
m_haveVolume = true;
|
||||||
|
return fThisVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cBuoyancy::FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition)
|
||||||
|
{
|
||||||
|
*waterPosition = FLOATER_IN_WATER;
|
||||||
|
// waterLevel is a local x,y point
|
||||||
|
// m_position is the global position of our floater
|
||||||
|
// zpos is the global z coordinate of our floater
|
||||||
|
CVector xWaterLevel = Multiply3x3(m_matrix, *waterLevel);
|
||||||
|
CWaterLevel::GetWaterLevel(xWaterLevel.x + m_position.x, xWaterLevel.y + m_position.y, m_position.z,
|
||||||
|
&waterLevel->z, true);
|
||||||
|
waterLevel->z -= xWaterLevel.z + zpos.z; // make local
|
||||||
|
if(waterLevel->z > m_dimMax.z){
|
||||||
|
waterLevel->z = m_dimMax.z;
|
||||||
|
*waterPosition = FLOATER_UNDER_WATER;
|
||||||
|
}else if(waterLevel->z < m_dimMin.z){
|
||||||
|
waterLevel->z = m_dimMin.z;
|
||||||
|
*waterPosition = FLOATER_ABOVE_WATER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
cBuoyancy::CalcBuoyancyForce(CPhysical *phys, CVector *impulse, CVector *point)
|
||||||
|
{
|
||||||
|
if(!m_haveVolume)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*impulse = Multiply3x3(m_matrix, m_impulse);
|
||||||
|
*point = CVector(0.0f, 0.0f, m_volumeUnderWater*m_buoyancy*CTimer::GetTimeStep());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x546270, &cBuoyancy::ProcessBuoyancy, PATCH_JUMP);
|
||||||
|
InjectHook(0x546360, &cBuoyancy::PreCalcSetup, PATCH_JUMP);
|
||||||
|
InjectHook(0x5466F0, &cBuoyancy::SimpleCalcBuoyancy, PATCH_JUMP);
|
||||||
|
InjectHook(0x546820, &cBuoyancy::SimpleSumBuoyancyData, PATCH_JUMP);
|
||||||
|
InjectHook(0x546620, &cBuoyancy::FindWaterLevel, PATCH_JUMP);
|
||||||
|
InjectHook(0x5465A0, &cBuoyancy::CalcBuoyancyForce, PATCH_JUMP);
|
||||||
|
ENDPATCHES
|
45
src/vehicles/Floater.h
Normal file
45
src/vehicles/Floater.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Physical;
|
||||||
|
|
||||||
|
enum tWaterLevel
|
||||||
|
{
|
||||||
|
FLOATER_ABOVE_WATER,
|
||||||
|
FLOATER_IN_WATER,
|
||||||
|
FLOATER_UNDER_WATER,
|
||||||
|
};
|
||||||
|
|
||||||
|
class cBuoyancy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CVector m_position;
|
||||||
|
CMatrix m_matrix;
|
||||||
|
int m_field_54;
|
||||||
|
CVector m_positionZ;
|
||||||
|
float m_waterlevel;
|
||||||
|
float m_waterLevelInc;
|
||||||
|
float m_buoyancy;
|
||||||
|
CVector m_dimMax;
|
||||||
|
CVector m_dimMin;
|
||||||
|
float m_numPartialVolumes;
|
||||||
|
int m_field_8C;
|
||||||
|
int m_field_90;
|
||||||
|
int m_field_94;
|
||||||
|
bool m_haveVolume;
|
||||||
|
CVector m_step;
|
||||||
|
CVector m_stepRatio;
|
||||||
|
float m_numSteps;
|
||||||
|
bool m_flipAverage;
|
||||||
|
char m_field_B9;
|
||||||
|
bool m_isBoat;
|
||||||
|
float m_volumeUnderWater;
|
||||||
|
CVector m_impulse;
|
||||||
|
|
||||||
|
bool ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *impulse, CVector *point);
|
||||||
|
void PreCalcSetup(CPhysical *phys, float buoyancy);
|
||||||
|
void SimpleCalcBuoyancy(void);
|
||||||
|
float SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition);
|
||||||
|
void FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition);
|
||||||
|
bool CalcBuoyancyForce(CPhysical *phys, CVector *impulse, CVector *point);
|
||||||
|
};
|
||||||
|
extern cBuoyancy &mod_Buoyancy;
|
Loading…
Reference in New Issue
Block a user