More CGraphics support functions

This commit is contained in:
Jack Andersen 2016-02-13 17:42:36 -10:00
parent f5de9a3033
commit 24c2176073
5 changed files with 255 additions and 26 deletions

View File

@ -4,10 +4,19 @@
namespace pshag
{
CGraphics::CProjectionState CGraphics::g_Proj;
u32 CGraphics::g_NumLightsActive = 0;
ERglLight CGraphics::g_LightActive = ERglLight::None;
ERglLight CGraphics::g_LightsWereOn = ERglLight::None;
Zeus::CTransform CGraphics::g_GXModelView;
Zeus::CTransform CGraphics::g_GXModelMatrix;
Zeus::CTransform CGraphics::g_ViewMatrix;
Zeus::CVector3f CGraphics::g_ViewPoint;
Zeus::CTransform CGraphics::g_GXViewPointMatrix;
Zeus::CTransform CGraphics::g_CameraMatrix;
Zeus::CVector2i CGraphics::g_ViewportResolution;
Zeus::CVector2i CGraphics::g_ViewportResolutionHalf;
bool CGraphics::g_IsGXModelMatrixIdentity;
void CGraphics::DisableAllLights()
{
@ -34,7 +43,7 @@ void CGraphics::SetLightState(ERglLight lightState)
g_NumLightsActive = Zeus::Math::PopCount(lightState);
}
void CGraphics::SetDepthWriteMode(bool, ERglEnum, bool)
void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write)
{
}
@ -51,8 +60,144 @@ void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ER
{
}
void CGraphics::SetViewPointMatrix(const Zeus::CTransform& xf)
{
g_ViewMatrix = xf;
g_ViewPoint = xf.m_origin;
g_GXViewPointMatrix.m_basis = g_ViewMatrix.m_basis.transposed();
g_GXViewPointMatrix.m_origin = -g_ViewPoint;
SetViewMatrix();
}
void CGraphics::SetViewMatrix()
{
g_CameraMatrix = g_GXViewPointMatrix * Zeus::CTransform::Translate(-g_ViewPoint);
if (g_IsGXModelMatrixIdentity)
g_GXModelView = g_CameraMatrix;
else
g_GXModelView = g_CameraMatrix * g_GXModelMatrix;
/* Load position matrix */
/* Inverse-transpose */
/* Load normal matrix */
}
void CGraphics::SetModelMatrix(const Zeus::CTransform& xf)
{
g_IsGXModelMatrixIdentity = false;
g_GXModelMatrix = xf;
SetViewMatrix();
}
Zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix()
{
float rml = g_Proj.x8_right - g_Proj.x4_left;
float rpl = g_Proj.x8_right + g_Proj.x4_left;
float tmb = g_Proj.xc_top - g_Proj.x10_bottom;
float tpb = g_Proj.xc_top + g_Proj.x10_bottom;
float fmn = g_Proj.x18_far - g_Proj.x14_near;
float fpn = g_Proj.x18_far + g_Proj.x14_near;
return Zeus::CMatrix4f(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f,
0.f, 2.f * g_Proj.x14_near / tmb, tpb / tmb, 0.f,
0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn,
0.f, 0.f, -1.f, 0.f);
}
const CGraphics::CProjectionState& CGraphics::GetProjectionState()
{
return g_Proj;
}
void CGraphics::SetProjectionState(const CGraphics::CProjectionState& proj)
{
g_Proj = proj;
FlushProjection();
}
void CGraphics::SetPerspective(float fovy, float aspect, float near, float far)
{
float tfov = tanf(fovy * 0.5f * M_PI / 180.f);
g_Proj.x0_persp = true;
g_Proj.x14_near = near;
g_Proj.x18_far = far;
g_Proj.xc_top = near * tfov;
g_Proj.x10_bottom = -g_Proj.xc_top;
g_Proj.x8_right = aspect * near * tfov;
g_Proj.x4_left = -g_Proj.x8_right;
}
void CGraphics::FlushProjection()
{
if (g_Proj.x0_persp)
{
// Convert and load persp
}
else
{
// Convert and load ortho
}
}
Zeus::CVector2i CGraphics::ProjectPoint(const Zeus::CVector3f& point)
{
Zeus::CVector3f projPt = GetPerspectiveProjectionMatrix().multiplyOneOverW(point);
return {int(projPt.x * g_ViewportResolutionHalf.x) + g_ViewportResolutionHalf.x,
int(projPt.y * g_ViewportResolutionHalf.y) + g_ViewportResolutionHalf.y};
}
SClipScreenRect CGraphics::ClipScreenRectFromMS(const Zeus::CVector3f& pos,
const Zeus::CVector3f& extent,
ETexelFormat fmt)
{
Zeus::CVector3f xfExt = (g_GXModelMatrix * extent) - g_ViewMatrix.m_origin;
xfExt = g_ViewMatrix.transposeRotate(xfExt);
Zeus::CVector3f xfPos = (g_GXModelMatrix * pos) - g_ViewMatrix.m_origin;
xfPos = g_ViewMatrix.transposeRotate(xfPos);
return ClipScreenRectFromVS(xfPos, xfExt, fmt);
}
SClipScreenRect CGraphics::ClipScreenRectFromVS(const Zeus::CVector3f& pos,
const Zeus::CVector3f& extent,
ETexelFormat fmt)
{
if (pos.x == 0.f && pos.y == 0.f && pos.z == 0.f)
return {};
if (extent.x == 0.f && extent.y == 0.f && extent.z == 0.f)
return {};
if (pos.y < GetProjectionState().x14_near || extent.y < GetProjectionState().x14_near)
return {};
if (pos.y > GetProjectionState().x18_far || extent.y > GetProjectionState().x18_far)
return {};
Zeus::CVector2i pt1 = ProjectPoint(pos);
Zeus::CVector2i pt2 = ProjectPoint(extent);
int minX = std::min(pt2.x, pt1.x);
int minX2 = minX & 0xfffffffe;
int minY = std::min(pt2.y, pt1.y);
int minY2 = minY & 0xfffffffe;
if (minX2 >= g_ViewportResolution.x)
return {};
int minX3 = (abs(pt1.x - pt2.x) + 2 + minX) & 0xfffffffe;
if (minX3 <= 0 /* ViewportX origin */)
return {};
int outX = std::max(minX2, 0 /* ViewportX origin */);
if (minY2 >= g_ViewportResolution.y)
return {};
int minY3 = (abs(pt1.y - pt2.y) + 2 + minY) & 0xfffffffe;
if (minY3 <= 0 /* ViewportY origin */)
return {};
int outY = std::max(minY2, 0 /* ViewportY origin */);
}
}

View File

@ -3,6 +3,7 @@
#include "RetroTypes.hpp"
#include "CTransform.hpp"
#include "CVector2i.hpp"
namespace pshag
{
@ -101,21 +102,68 @@ enum class ERglAlphaOp
XNor = 3
};
struct SClipScreenRect
{
bool x0_valid;
u32 x4_left;
u32 x8_top;
u32 xc_width;
u32 x10_height;
u32 x14_dstWidth;
float x18_uvXMin;
float x1c_uvXMax;
float x20_uvYMin;
float x24_uvYMax;
};
enum class ETexelFormat
{
};
class CGraphics
{
public:
struct CProjectionState
{
bool x0_persp;
float x4_left;
float x8_right;
float xc_top;
float x10_bottom;
float x14_near;
float x18_far;
};
static CProjectionState g_Proj;
static u32 g_NumLightsActive;
static ERglLight g_LightActive;
static ERglLight g_LightsWereOn;
static Zeus::CTransform g_GXModelView;
static Zeus::CTransform g_GXModelMatrix;
static Zeus::CTransform g_ViewMatrix;
static Zeus::CVector3f g_ViewPoint;
static Zeus::CTransform g_GXViewPointMatrix;
static Zeus::CTransform g_CameraMatrix;
static Zeus::CVector2i g_ViewportResolution;
static Zeus::CVector2i g_ViewportResolutionHalf;
static bool g_IsGXModelMatrixIdentity;
static void DisableAllLights();
static void EnableLight(ERglLight light);
static void SetLightState(ERglLight lightState);
static void SetDepthWriteMode(bool, ERglEnum, bool);
static void SetDepthWriteMode(bool test, ERglEnum comp, bool write);
static void SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp);
static void SetCullMode(ERglCullMode);
static void SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1);
static void SetViewPointMatrix(const Zeus::CTransform& xf);
static void SetViewMatrix();
static void SetModelMatrix(const Zeus::CTransform& xf);
static Zeus::CMatrix4f GetPerspectiveProjectionMatrix();
static const CProjectionState& GetProjectionState();
static void SetProjectionState(const CProjectionState&);
static void SetPerspective(float, float, float, float);
static void FlushProjection();
static Zeus::CVector2i ProjectPoint(const Zeus::CVector3f& point);
static SClipScreenRect ClipScreenRectFromMS(const Zeus::CVector3f& pos, const Zeus::CVector3f& extent, ETexelFormat);
static SClipScreenRect ClipScreenRectFromVS(const Zeus::CVector3f& pos, const Zeus::CVector3f& extent, ETexelFormat);
};
}

View File

@ -1,4 +1,5 @@
#include "CCollisionResponseData.hpp"
#include "CSimplePool.hpp"
namespace pshag
{

View File

@ -5,6 +5,8 @@
#include "CParticleElectric.hpp"
#include "CModel.hpp"
#define MAX_GLOBAL_PARTICLES 2560
namespace pshag
{
static LogVisor::LogModule Log("Retro::CElementGen");
@ -16,8 +18,8 @@ int CElementGen::g_ParticleSystemAliveCount;
s32 CElementGen::g_FreeIndex;
bool CElementGen::g_StaticListInitialized = false;
bool CElementGen::g_MoveRedToAlphaBuffer = false;
static rstl::reserved_vector<CElementGen::CParticle, 2560> g_StaticParticleList;
static rstl::reserved_vector<u16, 2560> g_StaticFreeList;
static rstl::reserved_vector<CElementGen::CParticle, MAX_GLOBAL_PARTICLES> g_StaticParticleList;
static rstl::reserved_vector<u16, MAX_GLOBAL_PARTICLES> g_StaticFreeList;
void CElementGen::Initialize()
{
if (g_StaticListInitialized)
@ -28,21 +30,15 @@ void CElementGen::Initialize()
g_ParticleSystemAliveCount = 0;
g_StaticParticleList.clear();
g_StaticParticleList.insert(g_StaticParticleList.end(), 2560, CParticle());
g_StaticParticleList.insert(g_StaticParticleList.end(), MAX_GLOBAL_PARTICLES, CParticle());
g_StaticFreeList.clear();
int c=0;
for (int i=0 ; i<512 ; ++i)
{
g_StaticFreeList.push_back(c++);
g_StaticFreeList.push_back(c++);
g_StaticFreeList.push_back(c++);
g_StaticFreeList.push_back(c++);
g_StaticFreeList.push_back(c++);
}
for (int i=0 ; i<MAX_GLOBAL_PARTICLES ; ++i)
g_StaticFreeList.push_back(i);
g_FreeIndex = 2559;
Log.report(LogVisor::Info, "size %d (%d each part).", (56 + 2) * 2560, 56);
g_FreeIndex = MAX_GLOBAL_PARTICLES - 1;
Log.report(LogVisor::Info, "size %d (%d each part).",
(sizeof(CParticle) + sizeof(u16)) * MAX_GLOBAL_PARTICLES, 56);
g_StaticListInitialized = true;
}
@ -1177,11 +1173,12 @@ void CElementGen::RenderParticles()
}
}
Zeus::CTransform xf(CGraphics::g_ViewMatrix);
Zeus::CTransform xf2 = xf.inverse() * x1d8_globalOrientation;
Zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix);
systemViewPointMatrix.m_origin.zeroOut();
Zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x1d8_globalOrientation;
systemViewPointMatrix = ((Zeus::CTransform::Translate(x88_globalTranslation) * xac_globalScaleTransform) * systemViewPointMatrix) * x118_localScaleTransform;
CGraphics::SetModelMatrix(systemViewPointMatrix);
xf = ((Zeus::CTransform::Translate(x88_globalTranslation) * xac_globalScaleTransform) * xf) * x118_localScaleTransform;
CGraphics::SetModelMatrix(xf);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
@ -1219,7 +1216,7 @@ void CElementGen::RenderParticles()
for (CParticleListItem& item : x2c_particleLists)
{
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
item.x4_viewPoint = xf2 * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
}
std::sort(x2c_particleLists.begin(), x2c_particleLists.end(),
@ -1302,7 +1299,7 @@ void CElementGen::RenderParticles()
if (desc->x44_28_SORT)
viewPoint = item.x4_viewPoint;
else
viewPoint = xf2 * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
if (!constTexr)
{
@ -1390,7 +1387,7 @@ void CElementGen::RenderParticles()
for (int i=0 ; i<mbspVal ; ++i)
{
vec += mbspVec;
Zeus::CVector3f vec2 = xf2 * vec;
Zeus::CVector3f vec2 = systemCameraMatrix * vec;
/* Draw: */
/* Pos: {vec2.x + size, vec2.y, vec2.z + size} Color: particle.color UV0: {uv[2], uv[3]} */
/* Pos: {vec2.x - size, vec2.y, vec2.z + size} Color: particle.color UV0: {uv[0], uv[3]} */
@ -1407,7 +1404,7 @@ void CElementGen::RenderParticles()
for (int i=0 ; i<mbspVal ; ++i)
{
vec += mbspVec;
Zeus::CVector3f vec2 = xf2 * vec;
Zeus::CVector3f vec2 = systemCameraMatrix * vec;
/* Draw:
vec2.x + sinT + cosT;
vec2.y;
@ -1440,6 +1437,44 @@ void CElementGen::RenderParticlesIndirectTexture()
{
CGenDescription* desc = x1c_genDesc.GetObj();
Zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix);
systemViewPointMatrix.m_origin.zeroOut();
Zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x1d8_globalOrientation;
systemViewPointMatrix = ((Zeus::CTransform::Translate(x88_globalTranslation) * xac_globalScaleTransform) * systemViewPointMatrix) * x118_localScaleTransform;
CGraphics::SetModelMatrix(systemViewPointMatrix);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
if (x224_26_AAPH)
{
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
}
else
{
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, x224_27_ZBUF);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear);
}
CUVElement* texr = desc->x54_TEXR.get();
CParticle& firstParticle = g_StaticParticleList[x2c_particleLists[0].x0_partIdx];
int partFrame = x50_curFrame - firstParticle.x28_startFrame;
CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::One);
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
bool constTexr = texr->HasConstantTexture();
texr->GetValueUV(partFrame, uvs);
bool constUVs = texr->HasConstantUV();
CUVElement* tind = desc->x58_TIND.get();
CTexture* cachedIndTex = tind->GetValueTexture(partFrame).GetObj();
cachedIndTex->Load(2, CTexture::EClampMode::One);
SUVElementSet uvsInd = {0.f, 0.f, 1.f, 1.f};
bool constIndTexr = tind->HasConstantTexture();
bool constIndUVs = tind->HasConstantUV();
tind->GetValueUV(partFrame, uvsInd);
}

@ -1 +1 @@
Subproject commit a8d0a73f5fff9d6d49d921507451bf55ba368a2a
Subproject commit 524f9e05c3937d68a9f8949ab1c0e84ac003499e