Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
616 changes: 346 additions & 270 deletions Client/core/Graphics/CGraphics.cpp

Large diffs are not rendered by default.

73 changes: 41 additions & 32 deletions Client/core/Graphics/CGraphics.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: core/CGraphics.h
* PURPOSE: Header file for general graphics subsystem class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: core/CGraphics.h
* PURPOSE: Header file for general graphics subsystem class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

class CGraphics;

Expand All @@ -26,6 +26,8 @@ class CGraphics;
class CTileBatcher;
class CLine3DBatcher;
class CMaterialLine3DBatcher;
class CPrimitiveBatcher;
class CPrimitiveMaterialBatcher;
class CAspectRatioConverter;
struct IDirect3DDevice9;
struct IDirect3DSurface9;
Expand Down Expand Up @@ -60,10 +62,11 @@ struct sFontInfo
class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>
{
friend class CDirect3DEvents9;
friend CPrimitiveMaterialBatcher;

public:
ZERO_ON_NEW
CGraphics(CLocalGUI* pGUI);
CGraphics(CLocalGUI* pGUI);
~CGraphics(void);

// DirectX misc. functions
Expand All @@ -75,13 +78,13 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>

// DirectX drawing functions
void DrawString(int iLeft, int iTop, int iRight, int iBottom, unsigned long dwColor, const char* wszText, float fScaleX, float fScaleY,
unsigned long ulFormat, ID3DXFont* pDXFont = NULL, bool bOutline = false);
unsigned long ulFormat, ID3DXFont* pDXFont = NULL, bool bOutline = false);
void DrawString(int iX, int iY, unsigned long dwColor, float fScale, const char* szText, ...);
void DrawLine3D(const CVector& vecBegin, const CVector& vecEnd, unsigned long ulColor, float fWidth = 1.0f);
void DrawRectangle(float fX, float fY, float fWidth, float fHeight, unsigned long ulColor, bool bSubPixelPositioning = false);
void DrawStringOutline(const RECT& rect, unsigned long ulColor, const wchar_t* szText, unsigned long ulFormat, LPD3DXFONT pDXFont);
void DrawCircleInternal(float fX, float fY, float fRadius, float fStartAngle, float fStopAngle, unsigned long ulColor, unsigned long ulColorCenter,
short siSegments, float fRatio, bool bPostGUI);
short siSegments, float fRatio, bool bPostGUI);

void SetBlendMode(EBlendModeType blendMode);
EBlendModeType GetBlendMode(void);
Expand Down Expand Up @@ -118,8 +121,8 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>

// Textures
void DrawTexture(CTextureItem* texture, float fX, float fY, float fScaleX = 1.0f, float fScaleY = 1.0f, float fRotation = 0.0f, float fCenterX = 0.0f,
float fCenterY = 0.0f, DWORD dwColor = 0xFFFFFFFF, float fU = 0, float fV = 0, float fSizeU = 1, float fSizeV = 1,
bool bRelativeUV = true);
float fCenterY = 0.0f, DWORD dwColor = 0xFFFFFFFF, float fU = 0, float fV = 0, float fSizeU = 1, float fSizeV = 1,
bool bRelativeUV = true);

// Interface functions
void SetCursorPosition(int iX, int iY, DWORD Flags);
Expand All @@ -130,20 +133,22 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>
void DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, bool bPostGUI);

void DrawMaterialLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, CMaterialItem* pMaterial, float fU = 0,
float fV = 0, float fSizeU = 1, float fSizeV = 1, bool bRelativeUV = true, bool bUseFaceToward = false,
const CVector& vecFaceToward = CVector(), bool bPostGUI = false);
float fV = 0, float fSizeU = 1, float fSizeV = 1, bool bRelativeUV = true, bool bUseFaceToward = false,
const CVector& vecFaceToward = CVector(), bool bPostGUI = false);

void DrawRectQueued(float fX, float fY, float fWidth, float fHeight, unsigned long ulColor, bool bPostGUI, bool bSubPixelPositioning = false);

void DrawTextureQueued(float fX, float fY, float fWidth, float fHeight, float fU, float fV, float fSizeU, float fSizeV, bool bRelativeUV,
CMaterialItem* pMaterial, float fRotation, float fRotCenOffX, float fRotCenOffY, unsigned long ulColor, bool bPostGUI);
CMaterialItem* pMaterial, float fRotation, float fRotCenOffX, float fRotCenOffY, unsigned long ulColor, bool bPostGUI);

void DrawStringQueued(float iLeft, float iTop, float iRight, float iBottom, unsigned long dwColor, const char* wszText, float fScaleX, float fScaleY,
unsigned long ulFormat, ID3DXFont* pDXFont = NULL, bool bPostGUI = false, bool bColorCoded = false, bool bSubPixelPositioning = false,
float fRotation = 0, float fRotationCenterX = 0, float fRotationCenterY = 0);
unsigned long ulFormat, ID3DXFont* pDXFont = NULL, bool bPostGUI = false, bool bColorCoded = false, bool bSubPixelPositioning = false,
float fRotation = 0, float fRotationCenterX = 0, float fRotationCenterY = 0);

void DrawPrimitiveQueued(const std::vector<PrimitiveVertice>& vecVertices, D3DPRIMITIVETYPE type, bool bPostGUI = false);
void DrawMaterialPrimitiveQueued(const std::vector<PrimitiveMaterialVertice>& vertices, D3DPRIMITIVETYPE type, CMaterialItem* pMaterial, bool bPostGUI);
void DrawCircleQueued(float fX, float fY, float fRadius, float fStartAngle, float fStopAngle, unsigned long ulColor, unsigned long ulColorCenter,
short siSegments, float fRatio, bool bPostGUI);
short siSegments, float fRatio, bool bPostGUI);

void OnChangingRenderTarget(uint uiNewViewportSizeX, uint uiNewViewportSizeY);

Expand All @@ -162,7 +167,7 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>

// Texture data manipulation
bool ResizeTextureData(const void* pData, uint uiDataPitch, uint uiWidth, uint uiHeight, uint d3dFormat, uint uiNewWidth, uint uiNewHeight,
CBuffer& outBuffer);
CBuffer& outBuffer);
bool CopyDataToSurface(IDirect3DSurface9* pSurface, const uchar* pPixelsData, uint uiDataPitch);
bool CopyDataFromSurface(IDirect3DSurface9* pSurface, CBuffer& outBuffer);

Expand All @@ -185,8 +190,8 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>
ID3DXFont* MaybeGetBigFont(ID3DXFont* pDXFont, float& fScaleX, float& fScaleY);
void CheckModes(EDrawModeType newDrawMode, EBlendModeType newBlendMode = EBlendMode::NONE);
void DrawColorCodedTextLine(float fLeft, float fRight, float fY, SColor& currentColor, const wchar_t* wszText, float fScaleX, float fScaleY,
unsigned long ulFormat, ID3DXFont* pDXFont, bool bPostGUI, bool bSubPixelPositioning, float fRotation, float fRotationCenterX,
float fRotationCenterY);
unsigned long ulFormat, ID3DXFont* pDXFont, bool bPostGUI, bool bSubPixelPositioning, float fRotation, float fRotationCenterX,
float fRotationCenterY);

CLocalGUI* m_pGUI;

Expand All @@ -200,15 +205,19 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>

IDirect3DDevice9* m_pDevice;

CRenderItemManager* m_pRenderItemManager;
CScreenGrabberInterface* m_pScreenGrabber;
CPixelsManagerInterface* m_pPixelsManager;
CTileBatcher* m_pTileBatcher;
CLine3DBatcher* m_pLine3DBatcherPreGUI;
CLine3DBatcher* m_pLine3DBatcherPostGUI;
CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPreGUI;
CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPostGUI;
CAspectRatioConverter* m_pAspectRatioConverter;
CRenderItemManager* m_pRenderItemManager;
CScreenGrabberInterface* m_pScreenGrabber;
CPixelsManagerInterface* m_pPixelsManager;
CTileBatcher* m_pTileBatcher;
CLine3DBatcher* m_pLine3DBatcherPreGUI;
CLine3DBatcher* m_pLine3DBatcherPostGUI;
CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPreGUI;
CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPostGUI;
CPrimitiveBatcher* m_pPrimitiveBatcherPreGUI;
CPrimitiveBatcher* m_pPrimitiveBatcherPostGUI;
CPrimitiveMaterialBatcher* m_pPrimitiveMaterialBatcherPreGUI;
CPrimitiveMaterialBatcher* m_pPrimitiveMaterialBatcherPostGUI;
CAspectRatioConverter* m_pAspectRatioConverter;

// Fonts
ID3DXFont* m_pDXFonts[NUM_FONTS];
Expand Down
214 changes: 214 additions & 0 deletions Client/core/Graphics/CPrimitiveBatcher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* (Shared logic for modifications)
* LICENSE: See LICENSE in the top level directory
* FILE: CPrimitiveBatcher.cpp
* PURPOSE:
*
*
*****************************************************************************/
#include <StdInc.h>
#include "CPrimitiveBatcher.h"
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::CPrimitiveBatcher
//
//
//
////////////////////////////////////////////////////////////////
CPrimitiveBatcher::CPrimitiveBatcher(bool m_bZTest)
{
m_bZTest = m_bZTest;
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::~CPrimitiveBatcher
//
//
//
////////////////////////////////////////////////////////////////
CPrimitiveBatcher::~CPrimitiveBatcher(void)
{
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::OnDeviceCreate
//
//
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::OnDeviceCreate(IDirect3DDevice9* pDevice, float fViewportSizeX, float fViewportSizeY)
{
m_pDevice = pDevice;
// Cache matrices
UpdateMatrices(fViewportSizeX, fViewportSizeY);
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::OnRenderTargetChange
//
//
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::OnChangingRenderTarget(uint uiNewViewportSizeX, uint uiNewViewportSizeY)
{
// Flush dx draws
Flush();
// Make new projection transform
UpdateMatrices(uiNewViewportSizeX, uiNewViewportSizeY);
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::UpdateMatrices
//
//
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::UpdateMatrices(float fViewportSizeX, float fViewportSizeY)
{
m_fViewportSizeX = fViewportSizeX;
m_fViewportSizeY = fViewportSizeY;
D3DXMatrixIdentity(&m_MatView);
D3DXMatrixIdentity(&m_MatProjection);
// Make projection 3D friendly, so shaders can alter the z coord for fancy effects
float fFarPlane = 10000;
float fNearPlane = 100;
float Q = fFarPlane / (fFarPlane - fNearPlane);
float fAdjustZFactor = 1000.f;
float rcpSizeX = 2.0f / m_fViewportSizeX;
float rcpSizeY = -2.0f / m_fViewportSizeY;
rcpSizeX *= fAdjustZFactor;
rcpSizeY *= fAdjustZFactor;
m_MatProjection.m[0][0] = rcpSizeX;
m_MatProjection.m[1][1] = rcpSizeY;
m_MatProjection.m[2][2] = Q;
m_MatProjection.m[2][3] = 1;
m_MatProjection.m[3][0] = (-m_fViewportSizeX / 2.0f - 0.5f) * rcpSizeX;
m_MatProjection.m[3][1] = (-m_fViewportSizeY / 2.0f - 0.5f) * rcpSizeY;
m_MatProjection.m[3][2] = -Q * fNearPlane;
m_MatProjection.m[3][3] = 0;
m_MatView.m[3][2] = fAdjustZFactor;
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::Flush
//
// Send all buffered vertices to D3D
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::Flush(void)
{
if (m_primitiveList.empty())
return;

// Save render states
IDirect3DStateBlock9* pSavedStateBlock = nullptr;
m_pDevice->CreateStateBlock(D3DSBT_ALL, &pSavedStateBlock);
// Set transformations
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
m_pDevice->SetTransform(D3DTS_VIEW, &m_MatView);
m_pDevice->SetTransform(D3DTS_PROJECTION, &m_MatProjection);

// Set vertex FVF
m_pDevice->SetFVF(PrimitiveVertice::FNV);

// Set states
m_pDevice->SetRenderState(D3DRS_ZENABLE, m_bZTest ? D3DZB_TRUE : D3DZB_FALSE);
m_pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
m_pDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
m_pDevice->SetRenderState(D3DRS_ALPHAREF, 0x01);
m_pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
m_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a new function void CPrimitiveMaterialBatcher::SetRenderStates (), call m_pDevice->SetRenderState within that function.

m_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a new function void CPrimitiveMaterialBatcher::SetTextureStageStates (), call m_pDevice->SetTextureStageState within that function.


// Draw
m_pDevice->SetTexture(0, nullptr);
for (int i = 0; i < m_primitiveList.size(); i++)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use (auto& primitive : m_primitiveList)?

{
sDrawQueuePrimitive primitive = m_primitiveList[i];

const void* pVertexStreamZeroData = &primitive.vertices[0];
uint uiVertexStreamZeroStride = sizeof(PrimitiveVertice);

DrawPrimitive(primitive.type, primitive.vertices.size(), pVertexStreamZeroData, uiVertexStreamZeroStride);
}

// Clean up
ClearQueue();
// Restore render states
if (pSavedStateBlock)
{
pSavedStateBlock->Apply();
SAFE_RELEASE(pSavedStateBlock);
}
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::DrawPrimitive
//
// Draws the primitives on render target
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::DrawPrimitive(D3DPRIMITIVETYPE eType, size_t iCollectionSize, const void* pDataAddr, size_t uiVertexStride)
{
int iSize = 1;
switch (eType)
{
case D3DPT_POINTLIST:
iSize = iCollectionSize;
break;
case D3DPT_LINELIST:
iSize = iCollectionSize / 2;
break;
case D3DPT_LINESTRIP:
iSize = iCollectionSize - 1;
break;
case D3DPT_TRIANGLEFAN:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case D3DPT_TRIANGLEFAN:
    break;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D3DPT_TRIANGLEFANsize needs to be same as D3DPT_TRIANGLESTRIP, so break is unnecessary, it uses shared case

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that makes sense.

case D3DPT_TRIANGLESTRIP:
iSize = iCollectionSize - 2;
break;
case D3DPT_TRIANGLELIST:
iSize = iCollectionSize / 3;
break;
}
m_pDevice->DrawPrimitiveUP(eType, iSize, pDataAddr, uiVertexStride);
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::ClearQueue
//
// Clears all primitives in current queue
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::ClearQueue()
{
// Clean up
size_t prevSize = m_primitiveList.size();
m_primitiveList.clear();
m_primitiveList.reserve(prevSize);
}
////////////////////////////////////////////////////////////////
//
// CPrimitiveBatcher::AddTriangle
//
// Add a new primitive to the list
//
////////////////////////////////////////////////////////////////
void CPrimitiveBatcher::AddPrimitive(sDrawQueuePrimitive primitive)
{
m_primitiveList.push_back(primitive);
}
Loading