Skip to content

Commit

Permalink
dxDrawModel3D reimplementation (#3266)
Browse files Browse the repository at this point in the history
  • Loading branch information
tederis authored Sep 3, 2024
1 parent 7daa694 commit 04ef14b
Show file tree
Hide file tree
Showing 23 changed files with 323 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Client/game_sa/CGameSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ CGameSA::CGameSA()
m_pPlantManager = new CPlantManagerSA();
m_pBuildingRemoval = new CBuildingRemovalSA();

m_pRenderer = std::make_unique<CRendererSA>();

// Normal weapon types (WEAPONSKILL_STD)
for (int i = 0; i < NUM_WeaponInfosStdSkill; i++)
{
Expand Down
6 changes: 5 additions & 1 deletion Client/game_sa/CGameSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "CStreamingSA.h"
#include "CCoverManagerSA.h"
#include "CPlantManagerSA.h"
#include "CRendererSA.h"

class CAnimBlendClumpDataSAInterface;
class CObjectGroupPhysicalPropertiesSA;
Expand Down Expand Up @@ -172,7 +173,8 @@ class CGameSA : public CGame
CCoverManagerSA* GetCoverManager() const noexcept { return m_pCoverManager; };
CPlantManagerSA* GetPlantManager() const noexcept { return m_pPlantManager; };
CBuildingRemoval* GetBuildingRemoval() { return m_pBuildingRemoval; }

CRenderer* GetRenderer() const noexcept override { return m_pRenderer.get(); }

CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD);
CModelInfo* GetModelInfo(DWORD dwModelID, bool bCanBeInvalid = false);
CObjectGroupPhysicalProperties* GetObjectGroupPhysicalProperties(unsigned char ucObjectGroup);
Expand Down Expand Up @@ -346,6 +348,8 @@ class CGameSA : public CGame
CPlantManagerSA* m_pPlantManager;
CBuildingRemoval* m_pBuildingRemoval;

std::unique_ptr<CRendererSA> m_pRenderer;

CPad* m_pPad;
CAERadioTrackManager* m_pCAERadioTrackManager;
CAudioEngine* m_pAudioEngine;
Expand Down
5 changes: 4 additions & 1 deletion Client/game_sa/CModelInfoSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,7 +2028,10 @@ void CModelInfoSA::RestoreAllObjectsPropertiesGroups()

eModelInfoType CModelInfoSA::GetModelType()
{
return ((eModelInfoType(*)())m_pInterface->VFTBL->GetModelType)();
if (auto pInterface = GetInterface())
return ((eModelInfoType(*)())pInterface->VFTBL->GetModelType)();

return eModelInfoType::UNKNOWN;
}

bool CModelInfoSA::IsTowableBy(CModelInfo* towingModel)
Expand Down
55 changes: 55 additions & 0 deletions Client/game_sa/CRendererSA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CRendererSA.cpp
* PURPOSE: Game renderer class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "CRendererSA.h"
#include "CModelInfoSA.h"
#include "CMatrix.h"
#include "gamesa_renderware.h"

CRendererSA::CRendererSA()
{
}

CRendererSA::~CRendererSA()
{
}

void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix)
{
CBaseModelInfoSAInterface* pModelInfoSAInterface = pModelInfo->GetInterface();
if (!pModelInfoSAInterface)
return;

RwObject* pRwObject = pModelInfoSAInterface->pRwObject;
if (!pRwObject)
return;

RwFrame* pFrame = RpGetFrame(pRwObject);

static RwMatrix rwMatrix;
rwMatrix.right = (RwV3d&)matrix.vRight;
rwMatrix.up = (RwV3d&)matrix.vFront;
rwMatrix.at = (RwV3d&)matrix.vUp;
rwMatrix.pos = (RwV3d&)matrix.vPos;
RwFrameTransform(pFrame, &rwMatrix, rwCOMBINEREPLACE);

if (pRwObject->type == RP_TYPE_ATOMIC)
{
RpAtomic* pRpAtomic = reinterpret_cast<RpAtomic*>(pRwObject);
pRpAtomic->renderCallback(reinterpret_cast<RpAtomic*>(pRwObject));
}
else
{
RpClump* pClump = reinterpret_cast<RpClump*>(pRwObject);
RpClumpRender(pClump);
}
}
23 changes: 23 additions & 0 deletions Client/game_sa/CRendererSA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CRendererSA.h
* PURPOSE: Game renderer class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include <game/CRenderer.h>

class CRendererSA : public CRenderer
{
public:
CRendererSA();
~CRendererSA();

void RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix) override;
};
7 changes: 7 additions & 0 deletions Client/game_sa/CVisibilityPluginsSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "StdInc.h"
#include "CVisibilityPluginsSA.h"

#define FUNC_CVisibilityPlugins_InsertEntityIntoEntityList 0x733DD0

void CVisibilityPluginsSA::SetClumpAlpha(RpClump* pClump, int iAlpha)
{
DWORD dwFunc = FUNC_CVisiblityPlugins_SetClumpAlpha;
Expand Down Expand Up @@ -51,3 +53,8 @@ int CVisibilityPluginsSA::GetAtomicId(RwObject* pAtomic)
}
return iResult;
}

bool CVisibilityPluginsSA::InsertEntityIntoEntityList(void* entity, float distance, void* callback)
{
return ((bool(_cdecl*)(void*, float, void*))FUNC_CVisibilityPlugins_InsertEntityIntoEntityList)(entity, distance, callback);
}
2 changes: 2 additions & 0 deletions Client/game_sa/CVisibilityPluginsSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ class CVisibilityPluginsSA : public CVisibilityPlugins
public:
void SetClumpAlpha(RpClump* pClump, int iAlpha);
int GetAtomicId(RwObject* pAtomic);

bool InsertEntityIntoEntityList(void* entity, float distance, void* callback);
};
4 changes: 4 additions & 0 deletions Client/game_sa/gamesa_renderware.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef RwFrame*(__cdecl* RwFrameAddChild_t)(RwFrame* parent, RwFrame* child);
typedef RwFrame*(__cdecl* RwFrameRemoveChild_t)(RwFrame* child);
typedef RwFrame*(__cdecl* RwFrameForAllObjects_t)(RwFrame* frame, void* callback, void* data);
typedef RwFrame*(__cdecl* RwFrameTranslate_t)(RwFrame* frame, const RwV3d* v, RwTransformOrder order);
typedef RwFrame*(__cdecl* RwFrameTransform_t)(RwFrame* frame, const RwMatrix* m, RwOpCombineType combine);
typedef RwFrame*(__cdecl* RwFrameScale_t)(RwFrame* frame, const RwV3d* v, RwTransformOrder order);
typedef RwFrame*(__cdecl* RwFrameUpdateObjects_t)(RwFrame*);
typedef RwFrame*(__cdecl* RwFrameCreate_t)();
Expand Down Expand Up @@ -69,6 +70,7 @@ typedef RwTexture*(__cdecl* RwTexDictionaryAddTexture_t)(RwTexDictionary* dict,
typedef RwTexDictionary*(__cdecl* RwTexDictionaryGetCurrent_t)();
typedef RwTexture*(__cdecl* RwTexDictionaryFindNamedTexture_t)(RwTexDictionary* dict, const char* name);
typedef void(__cdecl* RpPrtStdGlobalDataSetStreamEmbedded_t)(void* value);
typedef RpClump*(__cdecl* RpClumpRender_t)(RpClump* clump);
typedef RpWorld*(__cdecl* RpWorldAddAtomic_t)(RpWorld* world, RpAtomic* atomic);
typedef RpWorld*(__cdecl* RpWorldAddClump_t)(RpWorld* world, RpClump* clump);
typedef RpWorld*(__cdecl* RpWorldAddLight_t)(RpWorld* world, RpLight* light);
Expand Down Expand Up @@ -125,6 +127,7 @@ RWFUNC(RwStreamSkip_t RwStreamSkip, (RwStreamSkip_t)0xDEAD)
RWFUNC(RpClumpDestroy_t RpClumpDestroy, (RpClumpDestroy_t)0xDEAD)
RWFUNC(RpClumpGetNumAtomics_t RpClumpGetNumAtomics, (RpClumpGetNumAtomics_t)0xDEAD)
RWFUNC(RwFrameTranslate_t RwFrameTranslate, (RwFrameTranslate_t)0xDEAD)
RWFUNC(RwFrameTransform_t RwFrameTransform, (RwFrameTransform_t)0xDEAD)
RWFUNC(RpClumpForAllAtomics_t RpClumpForAllAtomics, (RpClumpForAllAtomics_t)0xDEAD)
RWFUNC(RwFrameAddChild_t RwFrameAddChild, (RwFrameAddChild_t)0xDEAD)
RWFUNC(RpClumpAddAtomic_t RpClumpAddAtomic, (RpClumpAddAtomic_t)0xDEAD)
Expand All @@ -138,6 +141,7 @@ RWFUNC(RwTexDictionaryAddTexture_t RwTexDictionaryAddTexture, (RwTexDictionaryAd
RWFUNC(RwTexDictionaryStreamWrite_t RwTexDictionaryStreamWrite, (RwTexDictionaryStreamWrite_t)0xDEAD)
RWFUNC(rwD3D9NativeTextureRead_t rwD3D9NativeTextureRead, (rwD3D9NativeTextureRead_t)0xDEAD)
RWFUNC(RpPrtStdGlobalDataSetStreamEmbedded_t RpPrtStdGlobalDataSetStreamEmbedded, (RpPrtStdGlobalDataSetStreamEmbedded_t)0xDEAD)
RWFUNC(RpClumpRender_t RpClumpRender, (RpClumpRender_t)0xDEAD)
RWFUNC(RpClumpRemoveAtomic_t RpClumpRemoveAtomic, (RpClumpRemoveAtomic_t)0xDEAD)
RWFUNC(RpAtomicClone_t RpAtomicClone, (RpAtomicClone_t)0xDEAD)
RWFUNC(RwTexDictionaryFindNamedTexture_t RwTexDictionaryFindNamedTexture, (RwTexDictionaryFindNamedTexture_t)0xDEAD)
Expand Down
2 changes: 2 additions & 0 deletions Client/game_sa/gamesa_renderware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ void InitRwFunctions()
RwStreamSkip = (RwStreamSkip_t)0x007ECD00;
RpClumpDestroy = (RpClumpDestroy_t)0x0074A310;
RpClumpGetNumAtomics = (RpClumpGetNumAtomics_t)0x007498E0;
RwFrameTransform = (RwFrameTransform_t)0x007F0F70;
RwFrameTranslate = (RwFrameTranslate_t)0x007F0E30;
RpClumpForAllAtomics = (RpClumpForAllAtomics_t)0x00749B70;
RwFrameAddChild = (RwFrameAddChild_t)0x007F0B00;
Expand All @@ -34,6 +35,7 @@ void InitRwFunctions()
RwTexDictionaryStreamWrite = (RwTexDictionaryStreamWrite_t)0x008049F0;
rwD3D9NativeTextureRead = (rwD3D9NativeTextureRead_t)0x004CD820;
RpPrtStdGlobalDataSetStreamEmbedded = (RpPrtStdGlobalDataSetStreamEmbedded_t)0x0041B350;
RpClumpRender = (RpClumpRender_t)0x00749B20;
RpClumpRemoveAtomic = (RpClumpRemoveAtomic_t)0x0074A4C0;
RpAtomicClone = (RpAtomicClone_t)0x00749E60;
RwTexDictionaryFindNamedTexture = (RwTexDictionaryFindNamedTexture_t)0x007F39F0;
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/StdInc.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
#include <CScriptFile.h>
#include <CWeaponNames.h>
#include <CVehicleNames.h>
#include <CModelRenderer.h>
#include <lua/CLuaCFunctions.h>
#include <lua/CLuaArguments.h>
#include <lua/CLuaMain.h>
Expand Down
12 changes: 12 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo())
// Singular file download manager
m_pSingularFileDownloadManager = new CSingularFileDownloadManager();

// 3D model renderer
m_pModelRenderer = std::make_unique<CModelRenderer>();

// Register the message and the net packet handler
g_pMultiplayer->SetPreWeaponFireHandler(CClientGame::PreWeaponFire);
g_pMultiplayer->SetPostWeaponFireHandler(CClientGame::PostWeaponFire);
Expand All @@ -267,6 +270,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo())
g_pMultiplayer->SetRender3DStuffHandler(CClientGame::StaticRender3DStuffHandler);
g_pMultiplayer->SetPreRenderSkyHandler(CClientGame::StaticPreRenderSkyHandler);
g_pMultiplayer->SetRenderHeliLightHandler(CClientGame::StaticRenderHeliLightHandler);
g_pMultiplayer->SetRenderEverythingBarRoadsHandler(CClientGame::StaticRenderEverythingBarRoadsHandler);
g_pMultiplayer->SetChokingHandler(CClientGame::StaticChokingHandler);
g_pMultiplayer->SetPreWorldProcessHandler(CClientGame::StaticPreWorldProcessHandler);
g_pMultiplayer->SetPostWorldProcessHandler(CClientGame::StaticPostWorldProcessHandler);
Expand Down Expand Up @@ -470,6 +474,7 @@ CClientGame::~CClientGame()
g_pMultiplayer->SetRender3DStuffHandler(NULL);
g_pMultiplayer->SetPreRenderSkyHandler(NULL);
g_pMultiplayer->SetRenderHeliLightHandler(nullptr);
g_pMultiplayer->SetRenderEverythingBarRoadsHandler(nullptr);
g_pMultiplayer->SetChokingHandler(NULL);
g_pMultiplayer->SetPreWorldProcessHandler(NULL);
g_pMultiplayer->SetPostWorldProcessHandler(NULL);
Expand Down Expand Up @@ -3546,6 +3551,11 @@ void CClientGame::StaticRenderHeliLightHandler()
g_pClientGame->GetManager()->GetPointLightsManager()->RenderHeliLightHandler();
}

void CClientGame::StaticRenderEverythingBarRoadsHandler()
{
g_pClientGame->GetModelRenderer()->Render();
}

bool CClientGame::StaticChokingHandler(unsigned char ucWeaponType)
{
return g_pClientGame->ChokingHandler(ucWeaponType);
Expand Down Expand Up @@ -3853,6 +3863,8 @@ void CClientGame::PostWorldProcessPedsAfterPreRenderHandler()
{
CLuaArguments Arguments;
m_pRootEntity->CallEvent("onClientPedsProcessed", Arguments, false);

g_pClientGame->GetModelRenderer()->Update();
}

void CClientGame::IdleHandler()
Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ class CClientGame
CRemoteCalls* GetRemoteCalls() { return m_pRemoteCalls; }
CResourceFileDownloadManager* GetResourceFileDownloadManager() { return m_pResourceFileDownloadManager; }

CModelRenderer* GetModelRenderer() const noexcept { return m_pModelRenderer.get(); }

SharedUtil::CAsyncTaskScheduler* GetAsyncTaskScheduler() { return m_pAsyncTaskScheduler; }

// Status toggles
Expand Down Expand Up @@ -504,6 +506,7 @@ class CClientGame
static void StaticRender3DStuffHandler();
static void StaticPreRenderSkyHandler();
static void StaticRenderHeliLightHandler();
static void StaticRenderEverythingBarRoadsHandler();
static bool StaticChokingHandler(unsigned char ucWeaponType);
static void StaticPreWorldProcessHandler();
static void StaticPostWorldProcessHandler();
Expand Down Expand Up @@ -698,6 +701,8 @@ class CClientGame
CRemoteCalls* m_pRemoteCalls;
CResourceFileDownloadManager* m_pResourceFileDownloadManager;

std::unique_ptr<CModelRenderer> m_pModelRenderer;

// Revised facilities
CServer m_Server;

Expand Down
72 changes: 72 additions & 0 deletions Client/mods/deathmatch/logic/CModelRenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CModelRenderer.cpp
* PURPOSE: 3D models renderer
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "game\CRenderer.h"
#include "game\CVisibilityPlugins.h"

bool CModelRenderer::EnqueueModel(CModelInfo* pModelInfo, const CMatrix& matrix)
{
if (g_pCore->IsWindowMinimized())
return false;

if (pModelInfo && pModelInfo->IsLoaded())
{
m_Queue.emplace_back(pModelInfo, matrix);
return true;
}

return false;
}

void CModelRenderer::Update()
{
CVisibilityPlugins* pVisibilityPlugins = g_pGame->GetVisibilityPlugins();
assert(pVisibilityPlugins);

for (auto& modelDesc : m_Queue)
{
// Insert transparent entities into a sorted list
if (modelDesc.pModelInfo->GetIdeFlag(eModelIdeFlag::DRAW_LAST))
{
const CVector& vecCameraPosition = *(CVector*)0xB76870; // CRenderer::ms_vecCameraPosition
const float fDistance = (modelDesc.matrix.GetPosition() - vecCameraPosition).Length();

pVisibilityPlugins->InsertEntityIntoEntityList(&modelDesc, fDistance, RenderEntity);
}
}
}

void CModelRenderer::Render()
{
CRenderer* pRenderer = g_pGame->GetRenderer();
assert(pRenderer);

// Draw opaque entities
for (auto& modelDesc : m_Queue)
{
if (modelDesc.pModelInfo->IsLoaded() && !modelDesc.pModelInfo->GetIdeFlag(eModelIdeFlag::DRAW_LAST))
pRenderer->RenderModel(modelDesc.pModelInfo, modelDesc.matrix);
}

m_Queue.clear();
}

void CModelRenderer::RenderEntity(SModelToRender* modelDesc, float distance)
{
if (!modelDesc->pModelInfo->IsLoaded())
return;

CRenderer* pRenderer = g_pGame->GetRenderer();
assert(pRenderer);

pRenderer->RenderModel(modelDesc->pModelInfo, modelDesc->matrix);
}
40 changes: 40 additions & 0 deletions Client/mods/deathmatch/logic/CModelRenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CModelRenderer.h
* PURPOSE: 3D models renderer
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

class CModelRenderer final
{
public:
struct SModelToRender final
{
CModelInfo* pModelInfo;
CMatrix matrix;

SModelToRender(CModelInfo* pModelInfo, const CMatrix& matrix) :
pModelInfo(pModelInfo),
matrix(matrix)
{
}
};

bool EnqueueModel(CModelInfo* pModelInfo, const CMatrix& matrix);

void Update();

void Render();

static void RenderEntity(SModelToRender* entity, float distance);

private:

std::vector<SModelToRender> m_Queue;
};
Loading

0 comments on commit 04ef14b

Please sign in to comment.