GFX3D: The POLY and VERT structs have been converted to POD-style structs for better data consistency.

This commit is contained in:
rogerman 2023-02-02 02:19:49 -08:00
parent 9273c9ab13
commit cbbacdbf59
5 changed files with 145 additions and 175 deletions

View File

@ -1817,7 +1817,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
// drawing more accurate this way, but it also allows GFX3D_QUADS and
// GFX3D_QUAD_STRIP primitives to properly draw as wireframe without the
// extra diagonal line.
const size_t LUTIndex = (!thePoly.isWireframe()) ? thePoly.vtxFormat : (0x08 | thePoly.vtxFormat);
const size_t LUTIndex = (!GFX3D_IsPolyWireframe(thePoly)) ? thePoly.vtxFormat : (0x08 | thePoly.vtxFormat);
const GLenum polyPrimitive = oglPrimitiveType[LUTIndex];
// Increment the vertex count
@ -1862,7 +1862,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
indexBufferPtr,
thePoly.attribute.DepthEqualTest_Enable,
thePoly.attribute.TranslucentDepthWrite_Enable,
thePoly.isWireframe() || thePoly.isOpaque(),
GFX3D_IsPolyWireframe(thePoly) || GFX3D_IsPolyOpaque(thePoly),
thePoly.attribute.PolygonID,
this->_isPolyFrontFacing[i]);
}
@ -4214,7 +4214,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
// vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
{
if (j == 2)
{
@ -4229,7 +4229,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
}
else
{
const GLfloat thePolyAlpha = (thePoly.isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha];
const GLfloat thePolyAlpha = (GFX3D_IsPolyWireframe(thePoly)) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha];
for (size_t j = 0; j < polyType; j++)
{
@ -4249,7 +4249,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
// vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
{
if (j == 2)
{
@ -4879,9 +4879,9 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs
OGLRenderRef &OGLRef = *this->ref;
glUniform1i(OGLRef.uniformPolyMode[this->_geometryProgramFlags.value], thePoly.attribute.Mode);
glUniform1i(OGLRef.uniformPolyEnableFog[this->_geometryProgramFlags.value], (thePoly.attribute.Fog_Enable) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha[this->_geometryProgramFlags.value], (thePoly.isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha]);
glUniform1f(OGLRef.uniformPolyAlpha[this->_geometryProgramFlags.value], (GFX3D_IsPolyWireframe(thePoly)) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha]);
glUniform1i(OGLRef.uniformPolyID[this->_geometryProgramFlags.value], thePoly.attribute.PolygonID);
glUniform1i(OGLRef.uniformPolyIsWireframe[this->_geometryProgramFlags.value], (thePoly.isWireframe()) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolyIsWireframe[this->_geometryProgramFlags.value], (GFX3D_IsPolyWireframe(thePoly)) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent[this->_geometryProgramFlags.value], (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyDepthOffset[this->_geometryProgramFlags.value], 0.0f);
}
@ -5483,7 +5483,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co
// vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
{
if (j == 2)
{

View File

@ -2040,7 +2040,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
// vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP))
{
if (j == 2)
{
@ -2152,8 +2152,8 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
polyStates[i].PolygonID = thePoly.attribute.PolygonID;
polyStates[i].PolygonMode = thePoly.attribute.Mode;
polyStates[i].PolygonAlpha = (thePoly.isWireframe()) ? 0x1F : thePoly.attribute.Alpha;
polyStates[i].IsWireframe = (thePoly.isWireframe()) ? 1 : 0;
polyStates[i].PolygonAlpha = (GFX3D_IsPolyWireframe(thePoly)) ? 0x1F : thePoly.attribute.Alpha;
polyStates[i].IsWireframe = (GFX3D_IsPolyWireframe(thePoly)) ? 1 : 0;
polyStates[i].EnableFog = (thePoly.attribute.Fog_Enable) ? 1 : 0;
polyStates[i].SetNewDepthForTranslucent = (thePoly.attribute.TranslucentDepthWrite_Enable) ? 1 : 0;

View File

@ -412,70 +412,71 @@ GFX3D_Viewport GFX3D_ViewportParse(const u32 inValue)
return outViewport;
}
void POLY::save(EMUFILE &os)
void GFX3D_SaveStatePOLY(const POLY &p, EMUFILE &os)
{
os.write_32LE((u32)type);
os.write_16LE(vertIndexes[0]);
os.write_16LE(vertIndexes[1]);
os.write_16LE(vertIndexes[2]);
os.write_16LE(vertIndexes[3]);
os.write_32LE(attribute.value);
os.write_32LE(texParam.value);
os.write_32LE(texPalette);
os.write_32LE(viewportLegacySave.value);
os.write_floatLE(miny);
os.write_floatLE(maxy);
os.write_32LE((u32)p.type);
os.write_16LE(p.vertIndexes[0]);
os.write_16LE(p.vertIndexes[1]);
os.write_16LE(p.vertIndexes[2]);
os.write_16LE(p.vertIndexes[3]);
os.write_32LE(p.attribute.value);
os.write_32LE(p.texParam.value);
os.write_32LE(p.texPalette);
os.write_32LE(p.viewportLegacySave.value);
os.write_floatLE(p.miny);
os.write_floatLE(p.maxy);
}
void POLY::load(EMUFILE &is)
void GFX3D_LoadStatePOLY(POLY &p, EMUFILE &is)
{
u32 polyType32;
is.read_32LE(polyType32);
type = (PolygonType)polyType32;
p.type = (PolygonType)polyType32;
is.read_16LE(vertIndexes[0]);
is.read_16LE(vertIndexes[1]);
is.read_16LE(vertIndexes[2]);
is.read_16LE(vertIndexes[3]);
is.read_32LE(attribute.value);
is.read_32LE(texParam.value);
is.read_32LE(texPalette);
is.read_32LE(viewportLegacySave.value);
is.read_floatLE(miny);
is.read_floatLE(maxy);
is.read_16LE(p.vertIndexes[0]);
is.read_16LE(p.vertIndexes[1]);
is.read_16LE(p.vertIndexes[2]);
is.read_16LE(p.vertIndexes[3]);
is.read_32LE(p.attribute.value);
is.read_32LE(p.texParam.value);
is.read_32LE(p.texPalette);
is.read_32LE(p.viewportLegacySave.value);
is.read_floatLE(p.miny);
is.read_floatLE(p.maxy);
viewport = GFX3D_ViewportParse(viewportLegacySave.value);
p.viewport = GFX3D_ViewportParse(p.viewportLegacySave.value);
}
void VERT::save(EMUFILE &os)
void GFX3D_SaveStateVERT(const VERT &vtx, EMUFILE &os)
{
os.write_floatLE(x);
os.write_floatLE(y);
os.write_floatLE(z);
os.write_floatLE(w);
os.write_floatLE(u);
os.write_floatLE(v);
os.write_u8(color[0]);
os.write_u8(color[1]);
os.write_u8(color[2]);
os.write_floatLE(fcolor[0]);
os.write_floatLE(fcolor[1]);
os.write_floatLE(fcolor[2]);
os.write_floatLE(vtx.x);
os.write_floatLE(vtx.y);
os.write_floatLE(vtx.z);
os.write_floatLE(vtx.w);
os.write_floatLE(vtx.u);
os.write_floatLE(vtx.v);
os.write_u8(vtx.color[0]);
os.write_u8(vtx.color[1]);
os.write_u8(vtx.color[2]);
os.write_floatLE(vtx.fcolor[0]);
os.write_floatLE(vtx.fcolor[1]);
os.write_floatLE(vtx.fcolor[2]);
}
void VERT::load(EMUFILE &is)
void GFX3D_LoadStateVERT(VERT &vtx, EMUFILE &is)
{
is.read_floatLE(x);
is.read_floatLE(y);
is.read_floatLE(z);
is.read_floatLE(w);
is.read_floatLE(u);
is.read_floatLE(v);
is.read_u8(color[0]);
is.read_u8(color[1]);
is.read_u8(color[2]);
is.read_floatLE(fcolor[0]);
is.read_floatLE(fcolor[1]);
is.read_floatLE(fcolor[2]);
is.read_floatLE(vtx.x);
is.read_floatLE(vtx.y);
is.read_floatLE(vtx.z);
is.read_floatLE(vtx.w);
is.read_floatLE(vtx.u);
is.read_floatLE(vtx.v);
is.read_u8(vtx.color[0]);
is.read_u8(vtx.color[1]);
is.read_u8(vtx.color[2]);
is.read_floatLE(vtx.fcolor[0]);
is.read_floatLE(vtx.fcolor[1]);
is.read_floatLE(vtx.fcolor[2]);
}
void gfx3d_init()
@ -763,7 +764,10 @@ static void SetVertex()
vert.color[0] = GFX3D_5TO6_LOOKUP(colorRGB[0]);
vert.color[1] = GFX3D_5TO6_LOOKUP(colorRGB[1]);
vert.color[2] = GFX3D_5TO6_LOOKUP(colorRGB[2]);
vert.color_to_float();
vert.rf = (float)vert.r;
vert.gf = (float)vert.g;
vert.bf = (float)vert.b;
vert.af = (float)vert.a;
tempVertInfo.map[tempVertInfo.count] = (s32)pendingGList.vertListCount + tempVertInfo.count - continuation;
tempVertInfo.count++;
@ -1681,15 +1685,23 @@ static BOOL gfx3d_glBoxTest(u32 v)
{ __x, y_h, z_d, fixedOne }
};
#define SET_VERT_INDICES(p, a,b,c,d) \
polys[p].type = POLYGON_TYPE_QUAD; \
polys[p].vertIndexes[0] = a; \
polys[p].vertIndexes[1] = b; \
polys[p].vertIndexes[2] = c; \
polys[p].vertIndexes[3] = d;
//craft the faces of the box (clockwise)
POLY polys[6];
polys[0].setVertIndexes(7,6,5,4); //near
polys[1].setVertIndexes(0,1,2,3); //far
polys[2].setVertIndexes(0,3,7,4); //left
polys[3].setVertIndexes(6,2,1,5); //right
polys[4].setVertIndexes(3,2,6,7); //top
polys[5].setVertIndexes(0,4,5,1); //bottom
SET_VERT_INDICES(0, 7,6,5,4) // near
SET_VERT_INDICES(1, 0,1,2,3) // far
SET_VERT_INDICES(2, 0,3,7,4) // left
SET_VERT_INDICES(3, 6,2,1,5) // right
SET_VERT_INDICES(4, 3,2,6,7) // top
SET_VERT_INDICES(5, 0,4,5,1) // bottom
#undef SET_VERT_INDICES
//setup the clipper
CPoly tempClippedPoly;
boxtestClipper.SetClippedPolyBufferPtr(&tempClippedPoly);
@ -1732,10 +1744,10 @@ static BOOL gfx3d_glBoxTest(u32 v)
MatrixMultVec4x4(mtxCurrent[MATRIXMODE_PROJECTION], vtx[i].coord);
// TODO: Remove this fixed-point to floating-point conversion.
verts[i].set_coord( (float)(vtx[i].x) / 4096.0f,
(float)(vtx[i].y) / 4096.0f,
(float)(vtx[i].z) / 4096.0f,
(float)(vtx[i].w) / 4096.0f );
verts[i].x = (float)(vtx[i].x) / 4096.0f;
verts[i].y = (float)(vtx[i].y) / 4096.0f;
verts[i].z = (float)(vtx[i].z) / 4096.0f;
verts[i].w = (float)(vtx[i].w) / 4096.0f;
}
//clip each poly
@ -2378,7 +2390,7 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
const CPoly &clippedPoly = _clipper->GetClippedPolyByIndex(i);
if (!clippedPoly.poly->isTranslucent())
if ( !GFX3D_IsPolyTranslucent(*clippedPoly.poly) )
gfx3d.polyWorkingIndexList[ctr++] = (int)clippedPoly.index;
}
outGList.clippedPolyOpaqueCount = ctr;
@ -2387,7 +2399,7 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
const CPoly &clippedPoly = _clipper->GetClippedPolyByIndex(i);
if (clippedPoly.poly->isTranslucent())
if ( GFX3D_IsPolyTranslucent(*clippedPoly.poly) )
gfx3d.polyWorkingIndexList[ctr++] = (int)clippedPoly.index;
}
@ -2913,11 +2925,15 @@ void gfx3d_savestate(EMUFILE &os)
//dump the render lists
os.write_32LE((u32)gfx3d.gList[gfx3d.pendingListIndex].vertListCount);
for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].vertListCount; i++)
gfx3d.gList[gfx3d.pendingListIndex].vertList[i].save(os);
{
GFX3D_SaveStateVERT(gfx3d.gList[gfx3d.pendingListIndex].vertList[i], os);
}
os.write_32LE((u32)gfx3d.gList[gfx3d.pendingListIndex].polyCount);
for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].polyCount; i++)
gfx3d.gList[gfx3d.pendingListIndex].polyList[i].save(os);
{
GFX3D_SaveStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].polyList[i], os);
}
// Write matrix stack data
os.write_32LE(mtxStackIndex[MATRIXMODE_PROJECTION]);
@ -3000,7 +3016,7 @@ bool gfx3d_loadstate(EMUFILE &is, int size)
gfx3d.gList[gfx3d.appliedListIndex].vertListCount = vertListCount32;
for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].vertListCount; i++)
{
gfx3d.gList[gfx3d.pendingListIndex].vertList[i].load(is);
GFX3D_LoadStateVERT(gfx3d.gList[gfx3d.pendingListIndex].vertList[i], is);
gfx3d.gList[gfx3d.appliedListIndex].vertList[i] = gfx3d.gList[gfx3d.pendingListIndex].vertList[i];
}
@ -3009,7 +3025,7 @@ bool gfx3d_loadstate(EMUFILE &is, int size)
gfx3d.gList[gfx3d.appliedListIndex].polyCount = polyListCount32;
for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].polyCount; i++)
{
gfx3d.gList[gfx3d.pendingListIndex].polyList[i].load(is);
GFX3D_LoadStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].polyList[i], is);
gfx3d.gList[gfx3d.appliedListIndex].polyList[i] = gfx3d.gList[gfx3d.pendingListIndex].polyList[i];
}
}
@ -3207,6 +3223,35 @@ void ParseReg_DISP3DCNT()
gfx3d_parseCurrentDISP3DCNT();
}
bool GFX3D_IsPolyWireframe(const POLY &p)
{
return (p.attribute.Alpha == 0);
}
bool GFX3D_IsPolyOpaque(const POLY &p)
{
return (p.attribute.Alpha == 31);
}
bool GFX3D_IsPolyTranslucent(const POLY &p)
{
// First, check if the polygon is wireframe or opaque.
// If neither, then it must be translucent.
if ( !GFX3D_IsPolyWireframe(p) && !GFX3D_IsPolyOpaque(p) )
{
return true;
}
// Also check for translucent texture format.
const NDSTextureFormat texFormat = (NDSTextureFormat)p.texParam.PackedFormat;
const PolygonMode polyMode = (PolygonMode)p.attribute.Mode;
//a5i3 or a3i5 -> translucent
return ( ((texFormat == TEXMODE_A3I5) || (texFormat == TEXMODE_A5I3)) &&
(polyMode != POLYGON_MODE_DECAL) &&
(polyMode != POLYGON_MODE_SHADOW) );
}
template void gfx3d_glGetMatrix<MATRIXMODE_PROJECTION>(const int index, float(&dst)[16]);
template void gfx3d_glGetMatrix<MATRIXMODE_POSITION>(const int index, float(&dst)[16]);
template void gfx3d_glGetMatrix<MATRIXMODE_POSITION_VECTOR>(const int index, float(&dst)[16]);
@ -3251,7 +3296,10 @@ static FORCEINLINE VERT clipPoint(const VERT *inside, const VERT *outside)
case ClipperMode_Full:
INTERP(texcoord[0]); INTERP(texcoord[1]);
INTERP(color[0]); INTERP(color[1]); INTERP(color[2]);
ret.color_to_float();
ret.rf = (float)ret.r;
ret.gf = (float)ret.g;
ret.bf = (float)ret.b;
ret.af = (float)ret.a;
break;
case ClipperMode_FullColorInterpolate:

View File

@ -520,87 +520,35 @@ union GFX3D_Viewport
};
typedef union GFX3D_Viewport GFX3D_Viewport;
struct POLY {
struct POLY
{
PolygonType type; //tri or quad
PolygonPrimitiveType vtxFormat;
u16 vertIndexes[4]; //up to four verts can be referenced by this poly
POLYGON_ATTR attribute;
TEXIMAGE_PARAM texParam;
u32 texPalette; //the hardware rendering params
GFX3D_Viewport viewport;
IOREG_VIEWPORT viewportLegacySave; // Exists for save state compatibility.
float miny, maxy;
void setVertIndexes(int a, int b, int c, int d=-1)
{
vertIndexes[0] = a;
vertIndexes[1] = b;
vertIndexes[2] = c;
if(d != -1) { vertIndexes[3] = d; type = POLYGON_TYPE_QUAD; }
else type = POLYGON_TYPE_TRIANGLE;
}
bool isWireframe() const
{
return (this->attribute.Alpha == 0);
}
bool isOpaque() const
{
return (this->attribute.Alpha == 31);
}
bool isTranslucent() const
{
// First, check if the polygon is wireframe or opaque.
// If neither, then it must be translucent.
if (!this->isWireframe() && !this->isOpaque())
{
return true;
}
// Also check for translucent texture format.
const NDSTextureFormat texFormat = (NDSTextureFormat)this->texParam.PackedFormat;
const PolygonMode mode = (PolygonMode)this->attribute.Mode;
//a5i3 or a3i5 -> translucent
if ( (texFormat == TEXMODE_A3I5 || texFormat == TEXMODE_A5I3) && (mode != POLYGON_MODE_DECAL && mode != POLYGON_MODE_SHADOW) )
{
return true;
}
return false;
}
void save(EMUFILE &os);
void load(EMUFILE &is);
float miny;
float maxy;
};
typedef struct POLY POLY;
// TODO: Handle these polygon utility functions in a class rather than as standalone functions.
// Most likely, the class will be some kind of polygon processing class, such as a polygon list
// handler or a polygon clipping handler. But before such a class is designed, simply handle
// these function here so that the POLY struct can remain as a POD struct.
bool GFX3D_IsPolyWireframe(const POLY &p);
bool GFX3D_IsPolyOpaque(const POLY &p);
bool GFX3D_IsPolyTranslucent(const POLY &p);
#define POLYLIST_SIZE 20000
#define VERTLIST_SIZE (POLYLIST_SIZE * 4)
#define INDEXLIST_SIZE (POLYLIST_SIZE * 4)
//just a vert with a 4 float position
struct VERT_POS4f
{
union {
float coord[4];
struct {
float x,y,z,w;
};
struct {
float x,y,z,w;
} position;
};
void set_coord(float x, float y, float z, float w)
{
this->x = x;
this->y = y;
this->z = z;
this->w = w;
}
};
#include "PACKED.h"
// This struct is padded in such a way so that each component can be accessed with a 16-byte alignment.
@ -645,34 +593,8 @@ struct VERT
};
u8 padFinal[12]; // Final padding to bring the struct to exactly 64 bytes.
void set_coord(float x, float y, float z, float w)
{
this->x = x;
this->y = y;
this->z = z;
this->w = w;
}
void set_coord(float* coords)
{
x = coords[0];
y = coords[1];
z = coords[2];
w = coords[3];
}
void color_to_float()
{
rf = (float)r;
gf = (float)g;
bf = (float)b;
af = (float)a;
}
void save(EMUFILE &os);
void load(EMUFILE &is);
};
typedef struct VERT VERT;
#include "PACKED_END.h"

View File

@ -1297,7 +1297,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::Render()
const bool useLineHack = USELINEHACK && (thePoly.vtxFormat & 4);
polyAttr = thePoly.attribute;
const bool isTranslucent = thePoly.isTranslucent();
const bool isTranslucent = GFX3D_IsPolyTranslucent(thePoly);
if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette)
{