Merge pull request #247 from Sergeanur/3dMarkers

Full C3dMarkers
This commit is contained in:
erorcun 2019-10-24 00:45:16 +03:00 committed by GitHub
commit d61430fbba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 354 additions and 17 deletions

View file

@ -9,7 +9,7 @@ public:
static char *LoadLine(int fd);
static RwTexDictionary *LoadTexDictionary(const char *filename);
static void LoadCollisionFile(const char *filename);
static void LoadCollisionModel(uint8 *buf, CColModel &model, char *name);
static void LoadCollisionModel(uint8 *buf, struct CColModel &model, char *name);
static void LoadModelFile(const char *filename);
static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data);
static void LoadClumpFile(const char *filename);

View file

@ -67,6 +67,7 @@ enum Config {
NUMANTENNAS = 8,
NUMCORONAS = 56,
NUMPOINTLIGHTS = 32,
NUM3DMARKERS = 32,
NUMMONEYMESSAGES = 16,
NUMPICKUPMESSAGES = 16,

View file

@ -127,20 +127,14 @@ public:
}
void Scale(float scale)
{
// GTA treats this as 4x4 floats
m_matrix.right.x *= scale;
m_matrix.right.y *= scale;
m_matrix.right.z *= scale;
m_matrix.up.x *= scale;
m_matrix.up.y *= scale;
m_matrix.up.z *= scale;
m_matrix.at.x *= scale;
m_matrix.at.y *= scale;
m_matrix.at.z *= scale;
m_matrix.pos.x *= scale;
m_matrix.pos.y *= scale;
m_matrix.pos.z *= scale;
m_matrix.flags = 0;
float *pFloatMatrix = (float*)&m_matrix;
for (int i = 0; i < 3; i++)
#ifdef FIX_BUGS // BUGFIX from VC
for (int j = 0; j < 3; j++)
#else
for (int j = 0; j < 4; j++)
#endif
pFloatMatrix[i * 4 + j] *= scale;
}

View file

@ -5,6 +5,12 @@
#include "Sprite.h"
#include "Font.h"
#include "Text.h"
#include "TxdStore.h"
#include "FileMgr.h"
#include "FileLoader.h"
#include "Lights.h"
#include "VisibilityPlugins.h"
#include "World.h"
WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); }
WRAPPER void CSpecialFX::Update(void) { EAXJMP(0x518D40); }
@ -18,9 +24,290 @@ WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }
WRAPPER void CBrightLights::RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1, uint8 unk2, uint8 unk3) { EAXJMP(0x51A410); }
WRAPPER void C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { EAXJMP(0x51BB80); }
RpAtomic *
MarkerAtomicCB(RpAtomic *atomic, void *data)
{
*(RpAtomic**)data = atomic;
return atomic;
}
bool
C3dMarker::AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
{
m_nIdentifier = identifier;
m_Matrix.SetUnity();
RpAtomic *origAtomic;
origAtomic = nil;
RpClumpForAllAtomics(C3dMarkers::m_pRpClumpArray[type], MarkerAtomicCB, &origAtomic);
RpAtomic *atomic = RpAtomicClone(origAtomic);
RwFrame *frame = RwFrameCreate();
RpAtomicSetFrame(atomic, frame);
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
RpGeometry *geometry = RpAtomicGetGeometry(atomic);
RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
m_pAtomic = atomic;
m_Matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));
m_pMaterial = RpGeometryGetMaterial(geometry, 0);
m_fSize = fSize;
m_fStdSize = m_fSize;
m_Color.red = r;
m_Color.green = g;
m_Color.blue = b;
m_Color.alpha = a;
m_nPulsePeriod = pulsePeriod;
m_fPulseFraction = pulseFraction;
m_nRotateRate = rotateRate;
m_nStartTime = CTimer::GetTimeInMilliseconds();
m_nType = type;
return m_pAtomic != nil;
}
void
C3dMarker::DeleteMarkerObject()
{
RwFrame *frame;
m_nIdentifier = 0;
m_nStartTime = 0;
m_bIsUsed = false;
m_nType = MARKERTYPE_INVALID;
frame = RpAtomicGetFrame(m_pAtomic);
RpAtomicDestroy(m_pAtomic);
RwFrameDestroy(frame);
m_pAtomic = nil;
}
void
C3dMarker::Render()
{
if (m_pAtomic == nil) return;
RwRGBA *color = RpMaterialGetColor(m_pMaterial);
*color = m_Color;
m_Matrix.UpdateRW();
CMatrix matrix;
matrix.Attach(m_Matrix.m_attachment);
matrix.Scale(m_fSize);
matrix.UpdateRW();
RwFrameUpdateObjects(RpAtomicGetFrame(m_pAtomic));
SetBrightMarkerColours(m_fBrightness);
if (m_nType != MARKERTYPE_ARROW)
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RpAtomicRender(m_pAtomic);
if (m_nType != MARKERTYPE_ARROW)
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
ReSetAmbientAndDirectionalColours();
}
C3dMarker(&C3dMarkers::m_aMarkerArray)[NUM3DMARKERS] = *(C3dMarker(*)[NUM3DMARKERS])*(uintptr*)0x72D408;
int32 &C3dMarkers::NumActiveMarkers = *(int32*)0x8F2A08;
RpClump* (&C3dMarkers::m_pRpClumpArray)[NUMMARKERTYPES] = *(RpClump*(*)[NUMMARKERTYPES])*(uintptr*)0x8E2888;
void
C3dMarkers::Init()
{
for (int i = 0; i < NUM3DMARKERS; i++) {
m_aMarkerArray[i].m_pAtomic = nil;
m_aMarkerArray[i].m_nType = MARKERTYPE_INVALID;
m_aMarkerArray[i].m_bIsUsed = false;
m_aMarkerArray[i].m_nIdentifier = 0;
m_aMarkerArray[i].m_Color.red = 255;
m_aMarkerArray[i].m_Color.green = 255;
m_aMarkerArray[i].m_Color.blue = 255;
m_aMarkerArray[i].m_Color.alpha = 255;
m_aMarkerArray[i].m_nPulsePeriod = 1024;
m_aMarkerArray[i].m_nRotateRate = 5;
m_aMarkerArray[i].m_nStartTime = 0;
m_aMarkerArray[i].m_fPulseFraction = 0.25f;
m_aMarkerArray[i].m_fStdSize = 1.0f;
m_aMarkerArray[i].m_fSize = 1.0f;
m_aMarkerArray[i].m_fBrightness = 1.0f;
m_aMarkerArray[i].m_fCameraRange = 0.0f;
}
NumActiveMarkers = 0;
int txdSlot = CTxdStore::FindTxdSlot("particle");
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(txdSlot);
CFileMgr::ChangeDir("\\");
m_pRpClumpArray[MARKERTYPE_ARROW] = CFileLoader::LoadAtomicFile2Return("models/generic/arrow.dff");
m_pRpClumpArray[MARKERTYPE_CYLINDER] = CFileLoader::LoadAtomicFile2Return("models/generic/zonecylb.dff");
CTxdStore::PopCurrentTxd();
}
void
C3dMarkers::Shutdown()
{
for (int i = 0; i < NUM3DMARKERS; i++) {
if (m_aMarkerArray[i].m_pAtomic != nil)
m_aMarkerArray[i].DeleteMarkerObject();
}
for (int i = 0; i < NUMMARKERTYPES; i++) {
if (m_pRpClumpArray[i] != nil)
RpClumpDestroy(m_pRpClumpArray[i]);
}
}
void
C3dMarkers::Render()
{
NumActiveMarkers = 0;
ActivateDirectional();
for (int i = 0; i < NUM3DMARKERS; i++) {
if (m_aMarkerArray[i].m_bIsUsed) {
if (m_aMarkerArray[i].m_fCameraRange < 120.0f)
m_aMarkerArray[i].Render();
NumActiveMarkers++;
m_aMarkerArray[i].m_bIsUsed = false;
} else if (m_aMarkerArray[i].m_pAtomic != nil) {
m_aMarkerArray[i].DeleteMarkerObject();
}
}
}
C3dMarker *
C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
{
C3dMarker *pMarker;
pMarker = nil;
float dist = Sqrt((pos.x - FindPlayerCentreOfWorld(0).x) * (pos.x - FindPlayerCentreOfWorld(0).x) + (pos.y - FindPlayerCentreOfWorld(0).y) * (pos.y - FindPlayerCentreOfWorld(0).y));
if (type != MARKERTYPE_ARROW && type != MARKERTYPE_CYLINDER) return nil;
for (int i = 0; i < NUM3DMARKERS; i++) {
if (!m_aMarkerArray[i].m_bIsUsed && m_aMarkerArray[i].m_nIdentifier == identifier) {
pMarker = &m_aMarkerArray[i];
break;
}
}
if (pMarker == nil) {
for (int i = 0; i < NUM3DMARKERS; i++) {
if (m_aMarkerArray[i].m_nType == MARKERTYPE_INVALID) {
pMarker = &m_aMarkerArray[i];
break;
}
}
}
if (pMarker == nil && type == MARKERTYPE_ARROW) {
for (int i = 0; i < NUM3DMARKERS; i++) {
if (dist < m_aMarkerArray[i].m_fCameraRange && m_aMarkerArray[i].m_nType == MARKERTYPE_ARROW && (pMarker == nil || m_aMarkerArray[i].m_fCameraRange > pMarker->m_fCameraRange)) {
pMarker = &m_aMarkerArray[i];
break;
}
}
if (pMarker != nil)
pMarker->m_nType = MARKERTYPE_INVALID;
}
if (pMarker == nil) return pMarker;
pMarker->m_fCameraRange = dist;
if (pMarker->m_nIdentifier == identifier && pMarker->m_nType == type) {
if (type == MARKERTYPE_ARROW) {
if (dist < 25.0f) {
if (dist > 5.0f)
pMarker->m_fStdSize = size - (25.0f - dist) * (0.3f * size) / 20.0f;
else
pMarker->m_fStdSize = size - 0.3f * size;
} else {
pMarker->m_fStdSize = size;
}
} else if (type == MARKERTYPE_CYLINDER) {
if (dist < size + 12.0f) {
if (dist > size + 1.0f)
pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a;
else
pMarker->m_Color.alpha = (float)a * 0.3f;
} else {
pMarker->m_Color.alpha = a;
}
}
float someSin = Sin(TWOPI * (float)((pMarker->m_nPulsePeriod - 1) & (CTimer::GetTimeInMilliseconds() - pMarker->m_nStartTime)) / (float)pMarker->m_nPulsePeriod);
pMarker->m_fSize = pMarker->m_fStdSize - pulseFraction * pMarker->m_fStdSize * someSin;
if (type == MARKERTYPE_ARROW) {
pos.z += 0.25f * pMarker->m_fStdSize * someSin;
} else if (type == MARKERTYPE_0) {
if (someSin > 0.0f)
pMarker->m_Color.alpha = (float)a * 0.7f * someSin + a;
else
pMarker->m_Color.alpha = (float)a * 0.4f * someSin + a;
}
if (pMarker->m_nRotateRate) {
RwV3d pos = pMarker->m_Matrix.m_matrix.pos;
pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep()));
pMarker->m_Matrix.GetPosition() = pos;
}
if (type == MARKERTYPE_ARROW)
pMarker->m_Matrix.GetPosition() = pos;
pMarker->m_bIsUsed = true;
return pMarker;
}
if (pMarker->m_nIdentifier != 0)
pMarker->DeleteMarkerObject();
pMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate);
if (type == MARKERTYPE_CYLINDER || type == MARKERTYPE_0 || type == MARKERTYPE_2) {
float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);
if (z != 0.0f)
pos.z = z - 0.05f * size;
}
pMarker->m_Matrix.SetTranslate(pos.x, pos.y, pos.z);
if (type == MARKERTYPE_2) {
pMarker->m_Matrix.RotateX(PI);
pMarker->m_Matrix.GetPosition() = pos;
}
pMarker->m_Matrix.UpdateRW();
if (type == MARKERTYPE_ARROW) {
if (dist < 25.0f) {
if (dist > 5.0f)
pMarker->m_fStdSize = size - (25.0f - dist) * (0.3f * size) / 20.0f;
else
pMarker->m_fStdSize = size - 0.3f * size;
} else {
pMarker->m_fStdSize = size;
}
} else if (type == MARKERTYPE_CYLINDER) {
if (dist < size + 12.0f) {
if (dist > size + 1.0f)
pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a;
else
pMarker->m_Color.alpha = (float)a * 0.3f;
} else {
pMarker->m_Color.alpha = a;
}
}
pMarker->m_bIsUsed = true;
return pMarker;
}
void
C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
{
PlaceMarker(id, type, pos, size, r, g, b, a, pulsePeriod, pulseFraction, 1);
PlaceMarker(id, type, pos, size * 0.93f, r, g, b, a, pulsePeriod, pulseFraction, 2);
PlaceMarker(id, type, pos, size * 0.86f, r, g, b, a, pulsePeriod, pulseFraction, -1);
}
void
C3dMarkers::Update()
{
}
#define MONEY_MESSAGE_LIFETIME_MS 2000
@ -97,6 +384,15 @@ CMoneyMessages::RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8
}
STARTPATCHES
InjectHook(0x51B070, &C3dMarker::AddMarker, PATCH_JUMP);
InjectHook(0x51B170, &C3dMarker::DeleteMarkerObject, PATCH_JUMP);
InjectHook(0x51B1B0, &C3dMarker::Render, PATCH_JUMP);
InjectHook(0x51B2B0, C3dMarkers::Init, PATCH_JUMP);
InjectHook(0x51B480, C3dMarkers::PlaceMarker, PATCH_JUMP);
InjectHook(0x51BB80, C3dMarkers::PlaceMarkerSet, PATCH_JUMP);
InjectHook(0x51B400, C3dMarkers::Render, PATCH_JUMP);
InjectHook(0x51B3B0, C3dMarkers::Shutdown, PATCH_JUMP);
InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP);
InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP);
ENDPATCHES

View file

@ -36,10 +36,56 @@ public:
static void RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1 = 0, uint8 unk2 = 0, uint8 unk3 = 0);
};
enum
{
MARKERTYPE_0 = 0,
MARKERTYPE_ARROW,
MARKERTYPE_2,
MARKERTYPE_3,
MARKERTYPE_CYLINDER,
NUMMARKERTYPES,
MARKERTYPE_INVALID = 0x101
};
class C3dMarker
{
public:
CMatrix m_Matrix;
RpAtomic *m_pAtomic;
RpMaterial *m_pMaterial;
uint16 m_nType;
bool m_bIsUsed;
uint32 m_nIdentifier;
RwRGBA m_Color;
uint16 m_nPulsePeriod;
uint16 m_nRotateRate;
uint32 m_nStartTime;
float m_fPulseFraction;
float m_fStdSize;
float m_fSize;
float m_fBrightness;
float m_fCameraRange;
bool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
void DeleteMarkerObject();
void Render();
};
class C3dMarkers
{
public:
static void Init();
static void Shutdown();
static C3dMarker *PlaceMarker(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
static void PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
static void Render();
static void Update();
static C3dMarker(&m_aMarkerArray)[NUM3DMARKERS];
static int32 &NumActiveMarkers;
static RpClump* (&m_pRpClumpArray)[NUMMARKERTYPES];
};
class CMoneyMessage