From 07c7687052804834a50dbbdaebeaac92b07b551e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Sep 2014 00:45:11 +0200 Subject: [PATCH] More code deduplication. Also normalized some line endings. --- GPU/Common/DrawEngineCommon.cpp | 323 ++++++++++++++++++---------- GPU/Common/DrawEngineCommon.h | 6 +- GPU/Directx9/SplineDX9.cpp | 105 +-------- GPU/Directx9/TransformPipelineDX9.h | 3 - GPU/GLES/Spline.cpp | 105 +-------- GPU/GLES/TransformPipeline.h | 2 - GPU/Software/TransformUnit.cpp | 2 +- 7 files changed, 222 insertions(+), 324 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 1101fdbd86..c4ebf1dbe7 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -21,6 +21,8 @@ #include "GPU/ge_constants.h" #include "GPU/GPUState.h" +#include "Core/Config.h" + #include DrawEngineCommon::~DrawEngineCommon() { } @@ -39,31 +41,31 @@ static void PlanesFromMatrix(float mtx[16], Plane planes[6]) { planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far } - -static Vec3f ClipToScreen(const Vec4f& coords) { - // TODO: Check for invalid parameters (x2 < x1, etc) - float vpx1 = getFloat24(gstate.viewportx1); - float vpx2 = getFloat24(gstate.viewportx2); - float vpy1 = getFloat24(gstate.viewporty1); - float vpy2 = getFloat24(gstate.viewporty2); - float vpz1 = getFloat24(gstate.viewportz1); - float vpz2 = getFloat24(gstate.viewportz2); - - float retx = coords.x * vpx1 / coords.w + vpx2; - float rety = coords.y * vpy1 / coords.w + vpy2; - float retz = coords.z * vpz1 / coords.w + vpz2; - - // 16 = 0xFFFF / 4095.9375 - return Vec3f(retx * 16, rety * 16, retz); -} - -static Vec3f ScreenToDrawing(const Vec3f& coords) { - Vec3f ret; - ret.x = (coords.x - gstate.getOffsetX16()) * (1.0f / 16.0f); - ret.y = (coords.y - gstate.getOffsetY16()) * (1.0f / 16.0f); - ret.z = coords.z; - return ret; -} + +static Vec3f ClipToScreen(const Vec4f& coords) { + // TODO: Check for invalid parameters (x2 < x1, etc) + float vpx1 = getFloat24(gstate.viewportx1); + float vpx2 = getFloat24(gstate.viewportx2); + float vpy1 = getFloat24(gstate.viewporty1); + float vpy2 = getFloat24(gstate.viewporty2); + float vpz1 = getFloat24(gstate.viewportz1); + float vpz2 = getFloat24(gstate.viewportz2); + + float retx = coords.x * vpx1 / coords.w + vpx2; + float rety = coords.y * vpy1 / coords.w + vpy2; + float retz = coords.z * vpz1 / coords.w + vpz2; + + // 16 = 0xFFFF / 4095.9375 + return Vec3f(retx * 16, rety * 16, retz); +} + +static Vec3f ScreenToDrawing(const Vec3f& coords) { + Vec3f ret; + ret.x = (coords.x - gstate.getOffsetX16()) * (1.0f / 16.0f); + ret.y = (coords.y - gstate.getOffsetY16()) * (1.0f / 16.0f); + ret.z = coords.z; + return ret; +} // This code is HIGHLY unoptimized! // @@ -135,104 +137,207 @@ bool DrawEngineCommon::TestBoundingBox(void* control_points, int vertexCount, u3 return true; } + +// TODO: This probably is not the best interface. +bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + // This is always for the current vertices. + u16 indexLowerBound = 0; + u16 indexUpperBound = count - 1; + + bool savedVertexFullAlpha = gstate_c.vertexFullAlpha; + + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + const u8 *inds = Memory::GetPointer(gstate_c.indexAddr); + const u16 *inds16 = (const u16 *)inds; + + if (inds) { + GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound); + indices.resize(count); + switch (gstate.vertType & GE_VTYPE_IDX_MASK) { + case GE_VTYPE_IDX_16BIT: + for (int i = 0; i < count; ++i) { + indices[i] = inds16[i]; + } + break; + case GE_VTYPE_IDX_8BIT: + for (int i = 0; i < count; ++i) { + indices[i] = inds[i]; + } + break; + default: + return false; + } + } else { + indices.clear(); + } + } else { + indices.clear(); + } + + static std::vector temp_buffer; + static std::vector simpleVertices; + temp_buffer.resize(std::max((int)indexUpperBound, 8192) * 128 / sizeof(u32)); + simpleVertices.resize(indexUpperBound + 1); + NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType); + + float world[16]; + float view[16]; + float worldview[16]; + float worldviewproj[16]; + ConvertMatrix4x3To4x4(world, gstate.worldMatrix); + ConvertMatrix4x3To4x4(view, gstate.viewMatrix); + Matrix4ByMatrix4(worldview, world, view); + Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix); + + vertices.resize(indexUpperBound + 1); + for (int i = indexLowerBound; i <= indexUpperBound; ++i) { + const SimpleVertex &vert = simpleVertices[i]; + + if (gstate.isModeThrough()) { + if (gstate.vertType & GE_VTYPE_TC_MASK) { + vertices[i].u = vert.uv[0]; + vertices[i].v = vert.uv[1]; + } else { + vertices[i].u = 0.0f; + vertices[i].v = 0.0f; + } + vertices[i].x = vert.pos.x; + vertices[i].y = vert.pos.y; + vertices[i].z = vert.pos.z; + if (gstate.vertType & GE_VTYPE_COL_MASK) { + memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c)); + } else { + memset(vertices[i].c, 0, sizeof(vertices[i].c)); + } + } else { + float clipPos[4]; + Vec3ByMatrix44(clipPos, vert.pos.AsArray(), worldviewproj); + Vec3f screenPos = ClipToScreen(clipPos); + Vec3f drawPos = ScreenToDrawing(screenPos); + + if (gstate.vertType & GE_VTYPE_TC_MASK) { + vertices[i].u = vert.uv[0]; + vertices[i].v = vert.uv[1]; + } else { + vertices[i].u = 0.0f; + vertices[i].v = 0.0f; + } + vertices[i].x = drawPos.x; + vertices[i].y = drawPos.y; + vertices[i].z = drawPos.z; + if (gstate.vertType & GE_VTYPE_COL_MASK) { + memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c)); + } else { + memset(vertices[i].c, 0, sizeof(vertices[i].c)); + } + } + } + + gstate_c.vertexFullAlpha = savedVertexFullAlpha; + + return true; +} + -// TODO: This probably is not the best interface. -bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { - // This is always for the current vertices. - u16 indexLowerBound = 0; - u16 indexUpperBound = count - 1; +// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning. +// The rest of the transform pipeline like lighting will go as normal, either hardware or software. +// The implementation is initially a bit inefficient but shouldn't be a big deal. +// An intermediate buffer of not-easy-to-predict size is stored at bufPtr. +u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) { + // First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate + // implementation of the vertex decoder. + dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound); - bool savedVertexFullAlpha = gstate_c.vertexFullAlpha; + // OK, morphing eliminated but bones still remain to be taken care of. + // Let's do a partial software transform where we only do skinning. - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - const u8 *inds = Memory::GetPointer(gstate_c.indexAddr); - const u16 *inds16 = (const u16 *)inds; + VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType); - if (inds) { - GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound); - indices.resize(count); - switch (gstate.vertType & GE_VTYPE_IDX_MASK) { - case GE_VTYPE_IDX_16BIT: - for (int i = 0; i < count; ++i) { - indices[i] = inds16[i]; - } - break; - case GE_VTYPE_IDX_8BIT: - for (int i = 0; i < count; ++i) { - indices[i] = inds[i]; - } - break; - default: - return false; + SimpleVertex *sverts = (SimpleVertex *)outPtr; + + const u8 defaultColor[4] = { + (u8)gstate.getMaterialAmbientR(), + (u8)gstate.getMaterialAmbientG(), + (u8)gstate.getMaterialAmbientB(), + (u8)gstate.getMaterialAmbientA(), + }; + + // Let's have two separate loops, one for non skinning and one for skinning. + if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { + int numBoneWeights = vertTypeGetNumBoneWeights(vertType); + for (int i = lowerBound; i <= upperBound; i++) { + reader.Goto(i); + SimpleVertex &sv = sverts[i]; + if (vertType & GE_VTYPE_TC_MASK) { + reader.ReadUV(sv.uv); } - } else { - indices.clear(); + + if (vertType & GE_VTYPE_COL_MASK) { + reader.ReadColor0_8888(sv.color); + } else { + memcpy(sv.color, defaultColor, 4); + } + + float nrm[3], pos[3]; + float bnrm[3], bpos[3]; + + if (vertType & GE_VTYPE_NRM_MASK) { + // Normals are generated during tesselation anyway, not sure if any need to supply + reader.ReadNrm(nrm); + } else { + nrm[0] = 0; + nrm[1] = 0; + nrm[2] = 1.0f; + } + reader.ReadPos(pos); + + // Apply skinning transform directly + float weights[8]; + reader.ReadWeights(weights); + // Skinning + Vec3Packedf psum(0, 0, 0); + Vec3Packedf nsum(0, 0, 0); + for (int w = 0; w < numBoneWeights; w++) { + if (weights[w] != 0.0f) { + Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12); + Vec3Packedf tpos(bpos); + psum += tpos * weights[w]; + + Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12); + Vec3Packedf tnorm(bnrm); + nsum += tnorm * weights[w]; + } + } + sv.pos = psum; + sv.nrm = nsum; } } else { - indices.clear(); - } - - static std::vector temp_buffer; - static std::vector simpleVertices; - temp_buffer.resize(std::max((int)indexUpperBound, 8192) * 128 / sizeof(u32)); - simpleVertices.resize(indexUpperBound + 1); - NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType); - - float world[16]; - float view[16]; - float worldview[16]; - float worldviewproj[16]; - ConvertMatrix4x3To4x4(world, gstate.worldMatrix); - ConvertMatrix4x3To4x4(view, gstate.viewMatrix); - Matrix4ByMatrix4(worldview, world, view); - Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix); - - vertices.resize(indexUpperBound + 1); - for (int i = indexLowerBound; i <= indexUpperBound; ++i) { - const SimpleVertex &vert = simpleVertices[i]; - - if (gstate.isModeThrough()) { - if (gstate.vertType & GE_VTYPE_TC_MASK) { - vertices[i].u = vert.uv[0]; - vertices[i].v = vert.uv[1]; + for (int i = lowerBound; i <= upperBound; i++) { + reader.Goto(i); + SimpleVertex &sv = sverts[i]; + if (vertType & GE_VTYPE_TC_MASK) { + reader.ReadUV(sv.uv); } else { - vertices[i].u = 0.0f; - vertices[i].v = 0.0f; + sv.uv[0] = 0; // This will get filled in during tesselation + sv.uv[1] = 0; } - vertices[i].x = vert.pos.x; - vertices[i].y = vert.pos.y; - vertices[i].z = vert.pos.z; - if (gstate.vertType & GE_VTYPE_COL_MASK) { - memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c)); + if (vertType & GE_VTYPE_COL_MASK) { + reader.ReadColor0_8888(sv.color); } else { - memset(vertices[i].c, 0, sizeof(vertices[i].c)); + memcpy(sv.color, defaultColor, 4); } - } else { - float clipPos[4]; - Vec3ByMatrix44(clipPos, vert.pos.AsArray(), worldviewproj); - Vec3f screenPos = ClipToScreen(clipPos); - Vec3f drawPos = ScreenToDrawing(screenPos); - - if (gstate.vertType & GE_VTYPE_TC_MASK) { - vertices[i].u = vert.uv[0]; - vertices[i].v = vert.uv[1]; + if (vertType & GE_VTYPE_NRM_MASK) { + // Normals are generated during tesselation anyway, not sure if any need to supply + reader.ReadNrm((float *)&sv.nrm); } else { - vertices[i].u = 0.0f; - vertices[i].v = 0.0f; - } - vertices[i].x = drawPos.x; - vertices[i].y = drawPos.y; - vertices[i].z = drawPos.z; - if (gstate.vertType & GE_VTYPE_COL_MASK) { - memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c)); - } else { - memset(vertices[i].c, 0, sizeof(vertices[i].c)); + sv.nrm.x = 0; + sv.nrm.y = 0; + sv.nrm.z = 1.0f; } + reader.ReadPos((float *)&sv.pos); } } - gstate_c.vertexFullAlpha = savedVertexFullAlpha; - - return true; + // Okay, there we are! Return the new type (but keep the index bits) + return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH)); } - diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 18439ed3a7..19ab1cc333 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -23,6 +23,8 @@ #include "GPU/Common/GPUDebugInterface.h" +class VertexDecoder; + class DrawEngineCommon { public: virtual ~DrawEngineCommon(); @@ -32,7 +34,9 @@ public: // TODO: This can be shared once the decoder cache / etc. are. virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) = 0; - bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); + bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); + + static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType); protected: // Vertex collector buffers diff --git a/GPU/Directx9/SplineDX9.cpp b/GPU/Directx9/SplineDX9.cpp index a74ef30ad1..9a43f48e7c 100644 --- a/GPU/Directx9/SplineDX9.cpp +++ b/GPU/Directx9/SplineDX9.cpp @@ -22,114 +22,11 @@ #include "GPU/Common/VertexDecoderCommon.h" namespace DX9 { - -// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning. -// The rest of the transform pipeline like lighting will go as normal, either hardware or software. -// The implementation is initially a bit inefficient but shouldn't be a big deal. -// An intermediate buffer of not-easy-to-predict size is stored at bufPtr. -u32 TransformDrawEngineDX9::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) { - // First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate - // implementation of the vertex decoder. - dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound); - - // OK, morphing eliminated but bones still remain to be taken care of. - // Let's do a partial software transform where we only do skinning. - - VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType); - - SimpleVertex *sverts = (SimpleVertex *)outPtr; - - const u8 defaultColor[4] = { - (u8)gstate.getMaterialAmbientR(), - (u8)gstate.getMaterialAmbientG(), - (u8)gstate.getMaterialAmbientB(), - (u8)gstate.getMaterialAmbientA(), - }; - - // Let's have two separate loops, one for non skinning and one for skinning. - if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { - int numBoneWeights = vertTypeGetNumBoneWeights(vertType); - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } - - if (vertType & GE_VTYPE_COL_MASK) { - reader.ReadColor0_8888(sv.color); - } else { - memcpy(sv.color, defaultColor, 4); - } - - float nrm[3], pos[3]; - float bnrm[3], bpos[3]; - - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tesselation anyway, not sure if any need to supply - reader.ReadNrm(nrm); - } else { - nrm[0] = 0; - nrm[1] = 0; - nrm[2] = 1.0f; - } - reader.ReadPos(pos); - - // Apply skinning transform directly - float weights[8]; - reader.ReadWeights(weights); - // Skinning - Vec3Packedf psum(0,0,0); - Vec3Packedf nsum(0,0,0); - for (int w = 0; w < numBoneWeights; w++) { - if (weights[w] != 0.0f) { - Vec3ByMatrix43(bpos, pos, gstate.boneMatrix+w*12); - Vec3Packedf tpos(bpos); - psum += tpos * weights[w]; - - Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix+w*12); - Vec3Packedf tnorm(bnrm); - nsum += tnorm * weights[w]; - } - } - sv.pos = psum; - sv.nrm = nsum; - } - } else { - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } else { - sv.uv[0] = 0; // This will get filled in during tesselation - sv.uv[1] = 0; - } - if (vertType & GE_VTYPE_COL_MASK) { - reader.ReadColor0_8888(sv.color); - } else { - memcpy(sv.color, defaultColor, 4); - } - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tesselation anyway, not sure if any need to supply - reader.ReadNrm((float *)&sv.nrm); - } else { - sv.nrm.x = 0; - sv.nrm.y = 0; - sv.nrm.z = 1.0f; - } - reader.ReadPos((float *)&sv.pos); - } - } - - // Okay, there we are! Return the new type (but keep the index bits) - return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH)); -} u32 TransformDrawEngineDX9::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) { const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); VertexDecoder *dec = GetVertexDecoder(vertTypeID); - return NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType); + return DrawEngineCommon::NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType); } void TransformDrawEngineDX9::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) { diff --git a/GPU/Directx9/TransformPipelineDX9.h b/GPU/Directx9/TransformPipelineDX9.h index d0500b8e98..a5fd2f064c 100644 --- a/GPU/Directx9/TransformPipelineDX9.h +++ b/GPU/Directx9/TransformPipelineDX9.h @@ -185,9 +185,6 @@ private: IDirect3DVertexDeclaration9 *SetupDecFmtForDraw(VSShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt); - // Preprocessing for spline/bezier - u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType); - u32 ComputeMiniHash(); u32 ComputeHash(); // Reads deferred vertex data. void MarkUnreliable(VertexArrayInfoDX9 *vai); diff --git a/GPU/GLES/Spline.cpp b/GPU/GLES/Spline.cpp index 063fb93883..4d23f6fa52 100644 --- a/GPU/GLES/Spline.cpp +++ b/GPU/GLES/Spline.cpp @@ -25,113 +25,10 @@ // Here's how to evaluate them fast: // http://and-what-happened.blogspot.se/2012/07/evaluating-b-splines-aka-basis-splines.html -// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning. -// The rest of the transform pipeline like lighting will go as normal, either hardware or software. -// The implementation is initially a bit inefficient but shouldn't be a big deal. -// An intermediate buffer of not-easy-to-predict size is stored at bufPtr. -u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) { - // First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate - // implementation of the vertex decoder. - dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound); - - // OK, morphing eliminated but bones still remain to be taken care of. - // Let's do a partial software transform where we only do skinning. - - VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType); - - SimpleVertex *sverts = (SimpleVertex *)outPtr; - - const u8 defaultColor[4] = { - (u8)gstate.getMaterialAmbientR(), - (u8)gstate.getMaterialAmbientG(), - (u8)gstate.getMaterialAmbientB(), - (u8)gstate.getMaterialAmbientA(), - }; - - // Let's have two separate loops, one for non skinning and one for skinning. - if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { - int numBoneWeights = vertTypeGetNumBoneWeights(vertType); - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } - - if (vertType & GE_VTYPE_COL_MASK) { - reader.ReadColor0_8888(sv.color); - } else { - memcpy(sv.color, defaultColor, 4); - } - - float nrm[3], pos[3]; - float bnrm[3], bpos[3]; - - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tesselation anyway, not sure if any need to supply - reader.ReadNrm(nrm); - } else { - nrm[0] = 0; - nrm[1] = 0; - nrm[2] = 1.0f; - } - reader.ReadPos(pos); - - // Apply skinning transform directly - float weights[8]; - reader.ReadWeights(weights); - // Skinning - Vec3Packedf psum(0,0,0); - Vec3Packedf nsum(0,0,0); - for (int w = 0; w < numBoneWeights; w++) { - if (weights[w] != 0.0f) { - Vec3ByMatrix43(bpos, pos, gstate.boneMatrix+w*12); - Vec3Packedf tpos(bpos); - psum += tpos * weights[w]; - - Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix+w*12); - Vec3Packedf tnorm(bnrm); - nsum += tnorm * weights[w]; - } - } - sv.pos = psum; - sv.nrm = nsum; - } - } else { - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } else { - sv.uv[0] = 0; // This will get filled in during tesselation - sv.uv[1] = 0; - } - if (vertType & GE_VTYPE_COL_MASK) { - reader.ReadColor0_8888(sv.color); - } else { - memcpy(sv.color, defaultColor, 4); - } - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tesselation anyway, not sure if any need to supply - reader.ReadNrm((float *)&sv.nrm); - } else { - sv.nrm.x = 0; - sv.nrm.y = 0; - sv.nrm.z = 1.0f; - } - reader.ReadPos((float *)&sv.pos); - } - } - - // Okay, there we are! Return the new type (but keep the index bits) - return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH)); -} - u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) { const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); VertexDecoder *dec = GetVertexDecoder(vertTypeID); - return NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType); + return DrawEngineCommon::NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType); } void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) { diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index d26c953262..e8bcab3c75 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -169,8 +169,6 @@ public: bool IsCodePtrVertexDecoder(const u8 *ptr) const; - static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType); - protected: // Preprocessing for spline/bezier virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) override; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index ef7868be23..aa63350728 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -538,7 +538,7 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vector