2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 22:27:41 +00:00

Humungous refactor

This commit is contained in:
Jack Andersen
2016-03-04 13:04:53 -10:00
parent 552ec1db4a
commit 783fb4c4fe
330 changed files with 2943 additions and 3077 deletions

View File

@@ -1,7 +1,7 @@
#ifndef __PSHAG_CBOORENDERER_HPP__
#define __PSHAG_CBOORENDERER_HPP__
namespace pshag
namespace urde
{
class IObjectStore;
class CMemorySys;

View File

@@ -0,0 +1,230 @@
#include "Graphics/CGraphics.hpp"
#include "zeus/Math.hpp"
#undef near
#undef far
namespace urde
{
CGraphics::CProjectionState CGraphics::g_Proj;
float CGraphics::g_ProjAspect = 1.f;
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;
int CGraphics::g_ViewportSamples = 1;
bool CGraphics::g_IsGXModelMatrixIdentity;
void CGraphics::DisableAllLights()
{
g_NumLightsActive = 0;
g_LightActive = ERglLight::None;
// TODO: turn lights off for real
}
void CGraphics::EnableLight(ERglLight light)
{
if ((light & g_LightActive) == ERglLight::None)
{
g_LightActive |= light;
++g_NumLightsActive;
// TODO: turn light on for real
}
g_LightsWereOn = g_LightActive;
}
void CGraphics::SetLightState(ERglLight lightState)
{
// TODO: set state for real
g_LightActive = lightState;
g_NumLightsActive = zeus::PopCount(lightState);
}
void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write)
{
}
void CGraphics::SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp)
{
}
void CGraphics::SetCullMode(ERglCullMode)
{
}
void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1)
{
}
void CGraphics::SetViewPointMatrix(const zeus::CTransform& xf)
{
g_ViewMatrix = xf;
g_ViewPoint = xf.m_origin;
zeus::CMatrix3f tmp(xf.m_basis[0], xf.m_basis[2], -xf.m_basis[1]);
g_GXViewPointMatrix = zeus::CTransform(tmp.transposed());
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)
{
g_ProjAspect = aspect;
float tfov = std::tan(zeus::degToRad(fovy * 0.5f));
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,
g_ViewportResolution.y - (int(projPt.y * g_ViewportResolutionHalf.y) + g_ViewportResolutionHalf.y)};
}
SClipScreenRect CGraphics::ClipScreenRectFromMS(const zeus::CVector3f& p1,
const zeus::CVector3f& p2)
{
zeus::CVector3f xf1 = g_GXModelView * p1;
zeus::CVector3f xf2 = g_GXModelView * p2;
return ClipScreenRectFromVS(xf1, xf2);
}
SClipScreenRect CGraphics::ClipScreenRectFromVS(const zeus::CVector3f& p1,
const zeus::CVector3f& p2)
{
if (p1.x == 0.f && p1.y == 0.f && p1.z == 0.f)
return {};
if (p2.x == 0.f && p2.y == 0.f && p2.z == 0.f)
return {};
if (p1.y < GetProjectionState().x14_near || p2.y < GetProjectionState().x14_near)
return {};
if (p1.y > GetProjectionState().x18_far || p2.y > GetProjectionState().x18_far)
return {};
zeus::CVector2i sp1 = ProjectPoint(p1);
zeus::CVector2i sp2 = ProjectPoint(p2);
int minX = std::min(sp2.x, sp1.x);
int minX2 = minX & 0xfffffffe;
int minY = std::min(sp2.y, sp1.y);
int minY2 = minY & 0xfffffffe;
if (minX2 >= g_ViewportResolution.x)
return {};
int maxX = abs(sp1.x - sp2.x) + minX;
int maxX2 = (maxX + 2) & 0xfffffffe;
if (maxX2 <= 0 /* ViewportX origin */)
return {};
int finalMinX = std::max(minX, 0 /* ViewportX origin */);
int finalMaxX = std::min(maxX, g_ViewportResolution.x);
if (minY2 >= g_ViewportResolution.y)
return {};
int maxY = abs(sp1.y - sp2.y) + minY;
int maxY2 = (maxY + 2) & 0xfffffffe;
if (maxY2 <= 0 /* ViewportY origin */)
return {};
int finalMinY = std::max(minY, 0 /* ViewportY origin */);
int finalMaxY = std::min(maxY, g_ViewportResolution.y);
int width = maxX2 - minX2;
int height = maxY2 - minY2;
return {true, minX2, minY2, width, height, width,
minX2 / float(g_ViewportResolution.x), maxX2 / float(g_ViewportResolution.x),
1.f - maxY2 / float(g_ViewportResolution.y), 1.f - minY2 / float(g_ViewportResolution.y)};
}
zeus::CVector3f CGraphics::ProjectModelPointToViewportSpace(const zeus::CVector3f& point)
{
zeus::CVector3f pt = g_GXModelView * point;
return GetPerspectiveProjectionMatrix().multiplyOneOverW(pt);
}
void CGraphics::SetViewportResolution(const zeus::CVector2i& res)
{
g_ViewportResolution = res;
g_ViewportResolutionHalf = {res.x / 2, res.y / 2};
}
boo::IGraphicsDataFactory* CGraphics::g_BooFactory = nullptr;
boo::IGraphicsCommandQueue* CGraphics::g_BooMainCommandQueue = nullptr;
boo::ITextureR* CGraphics::g_SpareTexture = nullptr;
}

View File

@@ -0,0 +1,229 @@
#ifndef __PSHAG_CGRAPHICS_HPP__
#define __PSHAG_CGRAPHICS_HPP__
#include "RetroTypes.hpp"
#include "zeus/CTransform.hpp"
#include "zeus/CVector2i.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
namespace urde
{
enum class ERglLight : u8
{
None = 0,
Zero = 1,
One = 1 << 1,
Two = 1 << 2,
Three = 1 << 3,
Four = 1 << 4,
Five = 1 << 5,
Six = 1 << 6,
Seven = 1 << 7
};
ENABLE_BITWISE_ENUM(ERglLight)
enum class ERglEnum
{
Never = 0,
Less = 1,
Equal = 2,
LEqual = 3,
Greater = 4,
NEqual = 5,
GEqual = 6,
Always = 7
};
enum class ERglBlendMode
{
None = 0,
Blend = 1,
Logic = 2,
Subtract = 3
};
enum class ERglBlendFactor
{
Zero = 0,
One = 1,
SrcColor = 2,
InvSrcColor = 3,
SrcAlpha = 4,
InvSrcAlpha = 5,
DstAlpha = 6,
InvDstAlpha = 7
};
enum class ERglLogicOp
{
Clear = 0,
And = 1,
RevAnd = 2,
Copy = 3,
InvAnd = 4,
NoOp = 5,
Xor = 6,
Or = 7,
Nor = 8,
Equiv = 9,
Inv = 10,
RevOr = 11,
InvCopy = 12,
InvOr = 13,
NAnd = 14,
Set = 15
};
enum class ERglCullMode
{
None = 0,
Front = 1,
Back = 2,
All = 3
};
enum class ERglAlphaFunc
{
Never = 0,
Less = 1,
Equal = 2,
LEqual = 3,
Greater = 4,
NEqual = 5,
GEqual = 6,
Always = 7
};
enum class ERglAlphaOp
{
And = 0,
Or = 1,
Xor = 2,
XNor = 3
};
struct SClipScreenRect
{
bool x0_valid;
int x4_left;
int x8_top;
int xc_width;
int x10_height;
int x14_dstWidth;
float x18_uvXMin;
float x1c_uvXMax;
float x20_uvYMin;
float x24_uvYMax;
};
enum class ETexelFormat
{
I4 = 0,
I8 = 1,
IA4 = 2,
IA8 = 3,
C4 = 4,
C8 = 5,
C14X2 = 6,
RGB565 = 7,
RGB5A3 = 8,
RGBA8 = 9,
CMPR = 10
};
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 float g_ProjAspect;
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 int g_ViewportSamples;
static bool g_IsGXModelMatrixIdentity;
static void DisableAllLights();
static void EnableLight(ERglLight light);
static void SetLightState(ERglLight lightState);
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 fovy, float aspect, float near, float far);
static void FlushProjection();
static zeus::CVector2i ProjectPoint(const zeus::CVector3f& point);
static SClipScreenRect ClipScreenRectFromMS(const zeus::CVector3f& p1, const zeus::CVector3f& p2);
static SClipScreenRect ClipScreenRectFromVS(const zeus::CVector3f& p1, const zeus::CVector3f& p2);
static zeus::CVector3f ProjectModelPointToViewportSpace(const zeus::CVector3f& point);
static void SetViewportResolution(const zeus::CVector2i& res);
static boo::IGraphicsDataFactory* g_BooFactory;
static boo::IGraphicsCommandQueue* g_BooMainCommandQueue;
static boo::ITextureR* g_SpareTexture;
static void InitializeBoo(boo::IGraphicsDataFactory* factory,
boo::IGraphicsCommandQueue* cc,
boo::ITextureR* spareTex)
{
g_BooFactory = factory;
g_BooMainCommandQueue = cc;
g_SpareTexture = spareTex;
}
static boo::IGraphicsBufferD* NewDynamicGPUBuffer(boo::BufferUse use, size_t stride, size_t count)
{
return g_BooFactory->newDynamicBuffer(use, stride, count);
}
static boo::GraphicsDataToken CommitResources()
{
return g_BooFactory->commit();
}
static void SetShaderDataBinding(boo::IShaderDataBinding* binding)
{
g_BooMainCommandQueue->setShaderDataBinding(binding);
}
static void ResolveSpareTexture(const SClipScreenRect& rect)
{
boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height};
g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, true, false);
}
static void DrawInstances(size_t start, size_t count, size_t instCount)
{
g_BooMainCommandQueue->drawInstances(start, count, instCount);
}
static void DrawArray(size_t start, size_t count)
{
g_BooMainCommandQueue->draw(start, count);
}
};
}
#endif // __PSHAG_CGRAPHICS_HPP__

View File

@@ -0,0 +1,24 @@
#include "CLight.hpp"
namespace urde
{
CLight CLight::BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color)
{
return {};
}
CLight CLight::BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
const zeus::CColor& color, float angle)
{
return {};
}
CLight CLight::BuildCustom(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
const zeus::CColor& color, float constAtt, float linearAtt, float quadAtt,
float intensity, float, float)
{
return {};
}
}

View File

@@ -1,8 +1,39 @@
#ifndef __PSHAG_CLIGHT_HPP__
#define __PSHAG_CLIGHT_HPP__
class CLight
#include "zeus/CVector3f.hpp"
#include "zeus/CColor.hpp"
namespace urde
{
enum class ELightType
{
LocalAmbient,
Directional,
Custom,
Spot,
Spot2,
LocalAmbient2
};
enum class EFalloffType
{
Constant,
Linear,
Quadratic
};
class CLight
{
public:
static CLight BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color);
static CLight BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
const zeus::CColor& color, float angle);
static CLight BuildCustom(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
const zeus::CColor& color, float constAtt, float linearAtt, float quadAtt,
float intensity, float, float);
};
}
#endif // __PSHAG_CLIGHT_HPP__

View File

@@ -1,9 +1,9 @@
#include "CLineRenderer.hpp"
#include "CLineRendererShaders.hpp"
namespace pshag
namespace urde
{
LogVisor::LogModule LineRendererLog("pshag::CLineRenderer");
logvisor::Module LineRendererLog("urde::CLineRenderer");
boo::IShaderPipeline* CLineRendererShaders::m_texAlpha = nullptr;
boo::IShaderPipeline* CLineRendererShaders::m_texAdditive = nullptr;
@@ -66,20 +66,20 @@ void CLineRenderer::Shutdown()
struct SDrawVertTex
{
Zeus::CVector4f pos;
Zeus::CColor color;
Zeus::CVector2f uv;
zeus::CVector4f pos;
zeus::CColor color;
zeus::CVector2f uv;
};
struct SDrawVertNoTex
{
Zeus::CVector4f pos;
Zeus::CColor color;
zeus::CVector4f pos;
zeus::CColor color;
};
struct SDrawUniform
{
Zeus::CColor moduColor;
zeus::CColor moduColor;
};
void CLineRendererShaders::BuildShaderDataBinding(CLineRenderer& renderer,
@@ -109,7 +109,7 @@ CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, boo::ITexture* t
{
if (maxVerts < 2)
{
LineRendererLog.report(LogVisor::FatalError, _S("maxVerts < 2, maxVerts = %i"), maxVerts);
LineRendererLog.report(logvisor::Fatal, _S("maxVerts < 2, maxVerts = %i"), maxVerts);
return;
}
m_textured = texture != nullptr;
@@ -139,11 +139,11 @@ CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, boo::ITexture* t
static rstl::reserved_vector<SDrawVertTex, 256> g_StaticLineVertsTex;
static rstl::reserved_vector<SDrawVertNoTex, 256> g_StaticLineVertsNoTex;
static Zeus::CVector2f IntersectLines(const Zeus::CVector2f& pa1, const Zeus::CVector2f& pa2,
const Zeus::CVector2f& pb1, const Zeus::CVector2f& pb2)
static zeus::CVector2f IntersectLines(const zeus::CVector2f& pa1, const zeus::CVector2f& pa2,
const zeus::CVector2f& pb1, const zeus::CVector2f& pb2)
{
Zeus::CVector2f pa1mpa2 = pa1 - pa2;
Zeus::CVector2f pb1mpb2 = pb1 - pb2;
zeus::CVector2f pa1mpa2 = pa1 - pa2;
zeus::CVector2f pb1mpb2 = pb1 - pb2;
float denom = pa1mpa2.x * pb1mpb2.y - pa1mpa2.y * pb1mpb2.x;
float numt1 = pa1.x * pa2.y - pa1.y * pa2.x;
float numt2 = pb1.x * pb2.y - pb1.y * pb2.x;
@@ -161,14 +161,14 @@ void CLineRenderer::Reset()
g_StaticLineVertsNoTex.clear();
}
void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColor& color, float width,
const Zeus::CVector2f& uv)
void CLineRenderer::AddVertex(const zeus::CVector3f& position, const zeus::CColor& color, float width,
const zeus::CVector2f& uv)
{
if (m_final || !m_shaderBind || m_nextVert >= m_maxVerts)
return;
float adjWidth = width / 480.f;
Zeus::CVector3f projPt = CGraphics::ProjectModelPointToViewportSpace(position);
zeus::CVector3f projPt = CGraphics::ProjectModelPointToViewportSpace(position);
if (m_mode == EPrimitiveMode::LineLoop)
{
@@ -188,13 +188,13 @@ void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColo
if (m_nextVert > 1)
{
Zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f();
zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f();
if (!dva.canBeNormalized())
dva = {0.f, 1.f};
dva = dva.normalized().perpendicularVector() * m_lastWidth;
dva.x /= CGraphics::g_ProjAspect;
Zeus::CVector2f dvb = (projPt - m_lastPos).toVec2f();
zeus::CVector2f dvb = (projPt - m_lastPos).toVec2f();
if (!dvb.canBeNormalized())
dvb = {0.f, 1.f};
dvb = dvb.normalized().perpendicularVector() * m_lastWidth;
@@ -219,11 +219,11 @@ void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColo
}
else
{
Zeus::CVector3f intersect1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva,
zeus::CVector3f intersect1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva,
m_lastPos.toVec2f() + dvb, projPt.toVec2f() + dvb);
intersect1.z = m_lastPos.z;
Zeus::CVector3f intersect2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva,
zeus::CVector3f intersect2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva,
m_lastPos.toVec2f() - dvb, projPt.toVec2f() - dvb);
intersect2.z = m_lastPos.z;
@@ -250,11 +250,11 @@ void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColo
}
else
{
Zeus::CVector3f intersect1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva,
zeus::CVector3f intersect1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva,
m_lastPos.toVec2f() + dvb, projPt.toVec2f() + dvb);
intersect1.z = m_lastPos.z;
Zeus::CVector3f intersect2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva,
zeus::CVector3f intersect2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva,
m_lastPos.toVec2f() - dvb, projPt.toVec2f() - dvb);
intersect2.z = m_lastPos.z;
@@ -265,7 +265,7 @@ void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColo
}
else if (m_nextVert == 1)
{
Zeus::CVector2f dv = (projPt - m_lastPos).toVec2f();
zeus::CVector2f dv = (projPt - m_lastPos).toVec2f();
if (!dv.canBeNormalized())
dv = {0.f, 1.f};
dv = dv.normalized().perpendicularVector() * m_lastWidth;
@@ -290,30 +290,30 @@ void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColo
++m_nextVert;
}
void CLineRenderer::Render(const Zeus::CColor& moduColor)
void CLineRenderer::Render(const zeus::CColor& moduColor)
{
if (!m_final && m_nextVert > 1)
{
if (m_mode == EPrimitiveMode::LineLoop)
{
{
Zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f();
zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f();
if (!dva.canBeNormalized())
dva = {0.f, 1.f};
dva = dva.normalized().perpendicularVector() * m_lastWidth;
dva.x /= CGraphics::g_ProjAspect;
Zeus::CVector2f dvb = (m_firstPos - m_lastPos).toVec2f();
zeus::CVector2f dvb = (m_firstPos - m_lastPos).toVec2f();
if (!dvb.canBeNormalized())
dvb = {0.f, 1.f};
dvb = dvb.normalized().perpendicularVector() * m_lastWidth;
dvb.x /= CGraphics::g_ProjAspect;
Zeus::CVector3f intersect1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva,
zeus::CVector3f intersect1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva,
m_lastPos.toVec2f() + dvb, m_firstPos.toVec2f() + dvb);
intersect1.z = m_lastPos.z;
Zeus::CVector3f intersect2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva,
zeus::CVector3f intersect2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva,
m_lastPos.toVec2f() - dvb, m_firstPos.toVec2f() - dvb);
intersect2.z = m_lastPos.z;
@@ -329,23 +329,23 @@ void CLineRenderer::Render(const Zeus::CColor& moduColor)
}
}
{
Zeus::CVector2f dva = (m_firstPos - m_lastPos).toVec2f();
zeus::CVector2f dva = (m_firstPos - m_lastPos).toVec2f();
if (!dva.canBeNormalized())
dva = {0.f, 1.f};
dva = dva.normalized().perpendicularVector() * m_firstWidth;
dva.x /= CGraphics::g_ProjAspect;
Zeus::CVector2f dvb = (m_secondPos - m_firstPos).toVec2f();
zeus::CVector2f dvb = (m_secondPos - m_firstPos).toVec2f();
if (!dvb.canBeNormalized())
dvb = {0.f, 1.f};
dvb = dvb.normalized().perpendicularVector() * m_firstWidth;
dvb.x /= CGraphics::g_ProjAspect;
Zeus::CVector3f intersect1 = IntersectLines(m_lastPos.toVec2f() + dva, m_firstPos.toVec2f() + dva,
zeus::CVector3f intersect1 = IntersectLines(m_lastPos.toVec2f() + dva, m_firstPos.toVec2f() + dva,
m_firstPos.toVec2f() + dvb, m_secondPos.toVec2f() + dvb);
intersect1.z = m_firstPos.z;
Zeus::CVector3f intersect2 = IntersectLines(m_lastPos.toVec2f() - dva, m_firstPos.toVec2f() - dva,
zeus::CVector3f intersect2 = IntersectLines(m_lastPos.toVec2f() - dva, m_firstPos.toVec2f() - dva,
m_firstPos.toVec2f() - dvb, m_secondPos.toVec2f() - dvb);
intersect2.z = m_firstPos.z;
@@ -363,7 +363,7 @@ void CLineRenderer::Render(const Zeus::CColor& moduColor)
}
else
{
Zeus::CVector2f dv = (m_lastPos - m_lastPos2).toVec2f();
zeus::CVector2f dv = (m_lastPos - m_lastPos2).toVec2f();
if (!dv.canBeNormalized())
dv = {0.f, 1.f};
dv = dv.normalized().perpendicularVector() * m_lastWidth;

View File

@@ -2,11 +2,11 @@
#define __PSHAG_CLINERENDERER_HPP__
#include "RetroTypes.hpp"
#include "CVector3f.hpp"
#include "CColor.hpp"
#include "zeus/CVector3f.hpp"
#include "zeus/CColor.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace pshag
namespace urde
{
class CLineRenderer
@@ -26,16 +26,16 @@ private:
bool m_final = false;
bool m_textured;
Zeus::CVector3f m_firstPos;
Zeus::CVector3f m_secondPos;
Zeus::CVector2f m_firstUV;
Zeus::CColor m_firstColor;
zeus::CVector3f m_firstPos;
zeus::CVector3f m_secondPos;
zeus::CVector2f m_firstUV;
zeus::CColor m_firstColor;
float m_firstWidth;
Zeus::CVector3f m_lastPos;
Zeus::CVector3f m_lastPos2;
Zeus::CVector2f m_lastUV;
Zeus::CColor m_lastColor;
zeus::CVector3f m_lastPos;
zeus::CVector3f m_lastPos2;
zeus::CVector2f m_lastUV;
zeus::CColor m_lastColor;
float m_lastWidth;
public:
@@ -47,9 +47,9 @@ public:
CLineRenderer(EPrimitiveMode mode, u32 maxVerts, boo::ITexture* texture, bool additive);
void Reset();
void AddVertex(const Zeus::CVector3f& position, const Zeus::CColor& color, float width,
const Zeus::CVector2f& uv=Zeus::CVector2f::skZero);
void Render(const Zeus::CColor& moduColor=Zeus::CColor::skWhite);
void AddVertex(const zeus::CVector3f& position, const zeus::CColor& color, float width,
const zeus::CVector2f& uv=zeus::CVector2f::skZero);
void Render(const zeus::CColor& moduColor=zeus::CColor::skWhite);
static void Initialize();
static void Shutdown();

View File

@@ -1,13 +1,13 @@
#ifndef __PSHAG_CLINERENDERERSHADERS_HPP__
#define __PSHAG_CLINERENDERERSHADERS_HPP__
#include "CGraphics.hpp"
#include "Graphics/CGraphics.hpp"
#include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/D3D.hpp"
#include "boo/graphicsdev/Metal.hpp"
#include "boo/graphicsdev/Vulkan.hpp"
namespace pshag
namespace urde
{
class CLineRenderer;

View File

@@ -1,7 +1,7 @@
#include "CLineRendererShaders.hpp"
#include "CLineRenderer.hpp"
namespace pshag
namespace urde
{
static const char* VS_GLSL_TEX =

View File

@@ -1,7 +1,7 @@
#include "CLineRendererShaders.hpp"
#include "CLineRenderer.hpp"
namespace pshag
namespace urde
{
static const char* VS_HLSL_TEX =

View File

@@ -1,7 +1,7 @@
#include "CLineRendererShaders.hpp"
#include "CLineRenderer.hpp"
namespace pshag
namespace urde
{
static const char* VS_METAL_TEX =

View File

@@ -10,5 +10,8 @@ add_library(RuntimeCommonGraphics
CLineRenderer.hpp CLineRenderer.cpp
CLineRendererShaders.hpp CLineRendererShadersGLSL.cpp
CMetroidModelInstance.hpp
CLight.hpp
CLight.hpp CLight.cpp
CTexture.hpp CTextureBoo.cpp
CModel.hpp CModelBoo.cpp
CGraphics.hpp CGraphics.cpp
${PLAT_SRCS})

View File

@@ -1,7 +1,7 @@
#ifndef __PSHAG_CMETROIDMODELINSTANCE_HPP__
#define __PSHAG_CMETROIDMODELINSTANCE_HPP__
namespace pshag
namespace urde
{
class CMetroidModelInstance

View File

@@ -0,0 +1,26 @@
#ifndef __PSHAG_CMODEL_HPP__
#define __PSHAG_CMODEL_HPP__
#include "RetroTypes.hpp"
#include "zeus/CColor.hpp"
namespace urde
{
struct CModelFlags
{
u8 f1;
u8 f2;
u16 f3;
zeus::CColor color;
};
class CModel
{
public:
void Draw(const CModelFlags& flags) const;
};
}
#endif // __PSHAG_CMODEL_HPP__

View File

@@ -0,0 +1,10 @@
#include "Graphics/CModel.hpp"
namespace urde
{
void CModel::Draw(const CModelFlags& flags) const
{
}
}

View File

@@ -0,0 +1,55 @@
#ifndef __PSHAG_CTEXTURE_HPP__
#define __PSHAG_CTEXTURE_HPP__
#include "GCNTypes.hpp"
#include "IObj.hpp"
#include "IOStreams.hpp"
#include "Graphics/CGraphics.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace urde
{
class CVParamTransfer;
class CTexture
{
ETexelFormat x0_fmt;
u16 x4_w;
u16 x6_h;
u32 x8_mips;
boo::GraphicsDataToken m_booToken;
boo::ITexture* m_booTex;
size_t ComputeMippedTexelCount();
size_t ComputeMippedBlockCountDXT1();
void BuildI4FromGCN(CInputStream& in);
void BuildI8FromGCN(CInputStream& in);
void BuildIA4FromGCN(CInputStream& in);
void BuildIA8FromGCN(CInputStream& in);
void BuildC4FromGCN(CInputStream& in);
void BuildC8FromGCN(CInputStream& in);
void BuildC14X2FromGCN(CInputStream& in);
void BuildRGB565FromGCN(CInputStream& in);
void BuildRGB5A3FromGCN(CInputStream& in);
void BuildRGBA8FromGCN(CInputStream& in);
void BuildDXT1FromGCN(CInputStream& in);
public:
CTexture(CInputStream& in);
enum class EClampMode
{
None,
One
};
ETexelFormat GetTexelFormat() const {return x0_fmt;}
u16 GetWidth() const {return x4_w;}
u16 GetHeight() const {return x6_h;}
void Load(int slot, EClampMode clamp);
boo::ITexture* GetBooTexture() {return m_booTex;}
};
std::unique_ptr<IObj> FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms);
}
#endif // __PSHAG_CTEXTURE_HPP__

View File

@@ -0,0 +1,695 @@
#include "CTexture.hpp"
#include "CSimplePool.hpp"
#include "CToken.hpp"
#include "Graphics/CGraphics.hpp"
namespace urde
{
/* GX uses this upsampling technique to prevent banding on downsampled texture formats */
static inline uint8_t Convert3To8(uint8_t v)
{
/* Swizzle bits: 00000123 -> 12312312 */
return (v << 5) | (v << 2) | (v >> 1);
}
static inline uint8_t Convert4To8(uint8_t v)
{
/* Swizzle bits: 00001234 -> 12341234 */
return (v << 4) | v;
}
static inline uint8_t Convert5To8(uint8_t v)
{
/* Swizzle bits: 00012345 -> 12345123 */
return (v << 3) | (v >> 2);
}
static inline uint8_t Convert6To8(uint8_t v)
{
/* Swizzle bits: 00123456 -> 12345612 */
return (v << 2) | (v >> 4);
}
size_t CTexture::ComputeMippedTexelCount()
{
size_t w = x4_w;
size_t h = x6_h;
size_t ret = w * h;
for (int i=x8_mips ; i>1 ; --i)
{
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
ret += w * h;
}
return ret;
}
size_t CTexture::ComputeMippedBlockCountDXT1()
{
size_t w = x4_w / 4;
size_t h = x6_h / 4;
size_t ret = w * h;
for (int i=x8_mips ; i>1 ; --i)
{
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
ret += w * h;
}
return ret;
}
struct RGBA8
{
u8 r;
u8 g;
u8 b;
u8 a;
};
void CTexture::BuildI4FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 7) / 8;
int bheight = (h + 7) / 8;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 8;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 8;
for (int y=0 ; y<8 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[4];
in.readBytesToBuf(source, 4);
for (int x=0 ; x<8 ; ++x)
{
target[x].r = Convert4To8(source[x/2] >> ((x&1)?0:4) & 0xf);
target[x].g = target[x].r;
target[x].b = target[x].r;
target[x].a = target[x].r;
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildI8FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 8;
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x=0 ; x<8 ; ++x)
{
target[x].r = source[x];
target[x].g = source[x];
target[x].b = source[x];
target[x].a = source[x];
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildIA4FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 8;
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x=0 ; x<8 ; ++x)
{
u8 intensity = Convert4To8(source[x] >> 4 & 0xf);
target[x].r = intensity;
target[x].g = intensity;
target[x].b = intensity;
target[x].a = Convert4To8(source[x] & 0xf);
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildIA8FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 4;
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u16 source[4];
in.readBytesToBuf(source, 8);
for (int x=0 ; x<4 ; ++x)
{
u8 intensity = source[x] >> 8;
target[x].r = intensity;
target[x].g = intensity;
target[x].b = intensity;
target[x].a = source[x] & 0xff;
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
static std::vector<RGBA8> DecodePalette(int numEntries, CInputStream& in)
{
std::vector<RGBA8> ret;
ret.reserve(numEntries);
enum class EPaletteType
{
IA8,
RGB565,
RGB5A3
};
EPaletteType format = EPaletteType(in.readUint32Big());
in.readUint32Big();
switch (format)
{
case EPaletteType::IA8:
{
for (int e=0 ; e<numEntries ; ++e)
{
u8 intensity = in.readUByte();
u8 alpha = in.readUByte();
ret.push_back({intensity, intensity, intensity, alpha});
}
break;
}
case EPaletteType::RGB565:
{
for (int e=0 ; e<numEntries ; ++e)
{
u16 texel = in.readUint16Big();
ret.push_back({Convert5To8(texel >> 11 & 0x1f),
Convert6To8(texel >> 5 & 0x3f),
Convert5To8(texel & 0x1f),
0xff});
}
break;
}
case EPaletteType::RGB5A3:
{
for (int e=0 ; e<numEntries ; ++e)
{
u16 texel = in.readUint16Big();
if (texel & 0x8000)
{
ret.push_back({Convert5To8(texel >> 10 & 0x1f),
Convert5To8(texel >> 5 & 0x1f),
Convert5To8(texel & 0x1f),
0xff});
}
else
{
ret.push_back({Convert4To8(texel >> 8 & 0xf),
Convert4To8(texel >> 4 & 0xf),
Convert4To8(texel & 0xf),
Convert3To8(texel >> 12 & 0x7)});
}
}
break;
}
}
return ret;
}
void CTexture::BuildC4FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
std::vector<RGBA8> palette = DecodePalette(16, in);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 7) / 8;
int bheight = (h + 7) / 8;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 8;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 8;
for (int y=0 ; y<8 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[4];
in.readBytesToBuf(source, 4);
for (int x=0 ; x<8 ; ++x)
target[x] = palette[source[x/2] >> ((x&1)?0:4) & 0xf];
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildC8FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
std::vector<RGBA8> palette = DecodePalette(256, in);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 8;
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x=0 ; x<8 ; ++x)
target[x] = palette[source[x]];
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildC14X2FromGCN(CInputStream& in)
{
}
void CTexture::BuildRGB565FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 4;
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (int x=0 ; x<4 ; ++x)
{
u16 texel = in.readUint16Big();
target[x].r = Convert5To8(texel >> 11 & 0x1f);
target[x].g = Convert6To8(texel >> 5 & 0x3f);
target[x].b = Convert5To8(texel & 0x1f);
target[x].a = 0xff;
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildRGB5A3FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 4;
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (int x=0 ; x<4 ; ++x)
{
u16 texel = in.readUint16Big();
if (texel & 0x8000)
{
target[x].r = Convert5To8(texel >> 10 & 0x1f);
target[x].g = Convert5To8(texel >> 5 & 0x1f);
target[x].b = Convert5To8(texel & 0x1f);
target[x].a = 0xff;
}
else
{
target[x].r = Convert4To8(texel >> 8 & 0xf);
target[x].g = Convert4To8(texel >> 4 & 0xf);
target[x].b = Convert4To8(texel & 0xf);
target[x].a = Convert3To8(texel >> 12 & 0x7);
}
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
void CTexture::BuildRGBA8FromGCN(CInputStream& in)
{
size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 4;
for (int c=0 ; c<2 ; ++c)
{
for (int y=0 ; y<4 ; ++y)
{
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x=0 ; x<4 ; ++x)
{
if (c)
{
target[x].g = source[x*2];
target[x].b = source[x*2+1];
}
else
{
target[x].a = source[x*2];
target[x].r = source[x*2+1];
}
}
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::RGBA8,
buf.get(), texelCount * 4, tmp);
m_booTex = tmp;
}
struct DXT1Block
{
uint16_t color1;
uint16_t color2;
uint8_t lines[4];
};
void CTexture::BuildDXT1FromGCN(CInputStream& in)
{
size_t blockCount = ComputeMippedBlockCountDXT1();
std::unique_ptr<DXT1Block[]> buf(new DXT1Block[blockCount]);
int w = x4_w / 4;
int h = x6_h / 4;
DXT1Block* targetMip = buf.get();
for (int mip=0 ; mip<x8_mips ; ++mip)
{
int bwidth = (w + 1) / 2;
int bheight = (h + 1) / 2;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 2;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 2;
for (int y=0 ; y<2 ; ++y)
{
DXT1Block* target = targetMip + (baseY + y) * w + baseX;
DXT1Block source[2];
in.readBytesToBuf(source, 16);
for (int x=0 ; x<2 ; ++x)
{
target[x].color1 = hecl::SBig(source[x].color1);
target[x].color2 = hecl::SBig(source[x].color2);
for (int i=0 ; i<4 ; ++i)
{
u8 ind[4];
u8 packed = source[x].lines[i];
ind[3] = packed & 0x3;
ind[2] = (packed >> 2) & 0x3;
ind[1] = (packed >> 4) & 0x3;
ind[0] = (packed >> 6) & 0x3;
target[x].lines[i] = ind[0] | (ind[1] << 2) | (ind[2] << 4) | (ind[3] << 6);
}
}
}
}
}
targetMip += w * h;
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
}
boo::ITextureS* tmp;
m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
boo::TextureFormat::DXT1,
buf.get(), blockCount * 8, tmp);
m_booTex = tmp;
}
CTexture::CTexture(CInputStream& in)
{
x0_fmt = ETexelFormat(in.readUint32Big());
x4_w = in.readUint16Big();
x6_h = in.readUint16Big();
x8_mips = in.readUint32Big();
switch (x0_fmt)
{
case ETexelFormat::I4:
BuildI4FromGCN(in);
break;
case ETexelFormat::I8:
BuildI8FromGCN(in);
break;
case ETexelFormat::IA4:
BuildIA4FromGCN(in);
break;
case ETexelFormat::IA8:
BuildIA8FromGCN(in);
break;
case ETexelFormat::C4:
BuildC4FromGCN(in);
break;
case ETexelFormat::C8:
BuildC8FromGCN(in);
break;
case ETexelFormat::C14X2:
BuildC14X2FromGCN(in);
break;
case ETexelFormat::RGB565:
BuildRGB565FromGCN(in);
break;
case ETexelFormat::RGB5A3:
BuildRGB5A3FromGCN(in);
break;
case ETexelFormat::RGBA8:
BuildRGBA8FromGCN(in);
break;
case ETexelFormat::CMPR:
BuildDXT1FromGCN(in);
break;
}
}
void CTexture::Load(int slot, EClampMode clamp)
{
}
std::unique_ptr<IObj> FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms)
{
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(in));
}
}

View File

@@ -4,12 +4,12 @@
#include <vector>
#include "../RetroTypes.hpp"
#include "../CToken.hpp"
#include "CAABox.hpp"
#include "CPlane.hpp"
#include "zeus/CAABox.hpp"
#include "zeus/CPlane.hpp"
#include "CFrustum.hpp"
#include "CColor.hpp"
#include "zeus/CColor.hpp"
namespace pshag
namespace urde
{
class CMetroidModelInstance;
class CLight;