diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 47400d0c14..455d621b97 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -733,7 +733,7 @@ void DIRECTX9_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_VERTEXTYPE: if (diff) - shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_REGION1: diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index a917d149d8..d600201232 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -811,10 +811,22 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_BOUNDINGBOX: - if (data != 0) - WARN_LOG_REPORT_ONCE(boundingbox, G3D, "Unsupported bounding box: %06x", data); - // bounding box test. Let's assume the box was visible. - currentList->bboxResult = true; + if ((data % 8 == 0) && data < 64) { // Sanity check + void *control_points = Memory::GetPointer(gstate_c.vertexAddr); + if (gstate.vertType & GE_VTYPE_IDX_MASK) { + ERROR_LOG_REPORT_ONCE(boundingbox, G3D, "Indexed bounding box data not supported."); + // Data seems invalid. Let's assume the box test passed. + currentList->bboxResult = true; + break; + } + + // Test if the bounding box is within the drawing region. + currentList->bboxResult = transformDraw_.TestBoundingBox(control_points, data, gstate.vertType); + } else { + ERROR_LOG_REPORT_ONCE(boundingbox, G3D, "Bad bounding box data: %06x", data); + // Data seems invalid. Let's assume the box test passed. + currentList->bboxResult = true; + } break; case GE_CMD_VERTEXTYPE: diff --git a/GPU/GLES/Spline.cpp b/GPU/GLES/Spline.cpp index f86f4c9551..0f1e8a7375 100644 --- a/GPU/GLES/Spline.cpp +++ b/GPU/GLES/Spline.cpp @@ -23,14 +23,6 @@ // Here's how to evaluate them fast: // http://and-what-happened.blogspot.se/2012/07/evaluating-b-splines-aka-basis-splines.html -// PSP compatible format so we can use the end of the pipeline -struct SimpleVertex { - float uv[2]; - u8 color[4]; - Vec3f nrm; - Vec3f pos; -}; - // 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. diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index cfb8e2745e..4341d0b7c6 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -1247,3 +1247,50 @@ rotateVBO: host->GPUNotifyDraw(); #endif } + +bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount, u32 vertType) { + // Simplify away bones and morph before proceeding + + /* + SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12); + u8 *temp_buffer = decoded + 65536 * 24; + + u32 origVertType = vertType; + vertType = NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType); + + for (int cube = 0; cube < vertexCount / 8; cube++) { + // For each cube... + + for (int i = 0; i < 8; i++) { + const SimpleVertex &vert = corners[cube * 8 + i]; + + // To world space... + float worldPos[3]; + Vec3ByMatrix43(worldPos, (float *)&vert.pos.x, gstate.worldMatrix); + + // To view space... + float viewPos[3]; + Vec3ByMatrix43(viewPos, worldPos, gstate.viewMatrix); + + // And finally to screen space. + float frustumPos[4]; + Vec3ByMatrix44(frustumPos, viewPos, gstate.projMatrix); + + // Project to 2D + float x = frustumPos[0] / frustumPos[3]; + float y = frustumPos[1] / frustumPos[3]; + + // Rescale 2d position + // ... + } + } + */ + + + // Let's think. A better approach might be to take the edges of the drawing region and the projection + // matrix to build a frustum pyramid, and then clip the cube against those planes. If all vertices fail the same test, + // the cube is out. Otherwise it's in. + // TODO.... + + return true; +} diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 65a9d1ded2..b395c1177e 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -90,18 +90,24 @@ public: u16 drawsUntilNextFullHash; }; +// PSP compatible format so we can use the end of the pipeline in beziers etc +struct SimpleVertex { + float uv[2]; + u8 color[4]; + Vec3f nrm; + Vec3f pos; +}; // Handles transform, lighting and drawing. class TransformDrawEngine : public GfxResourceHolder { public: TransformDrawEngine(); virtual ~TransformDrawEngine(); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertexType, int forceIndexType, int *bytesRead); - void SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type); - void SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertex_type); - // legacy - void DrawBezier(int ucount, int vcount); + void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int forceIndexType, int *bytesRead); + void SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType); + void SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType); + bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType); void DecodeVerts(); void SetShaderManager(ShaderManager *shaderManager) { diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 7599e08d94..96bc383738 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -584,6 +584,14 @@ inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) vecOut[2] = v[0] * m[2] + v[1] * m[5] + v[2] * m[8] + m[11]; } +inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16]) +{ + vecOut[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[9]; + vecOut[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[10]; + vecOut[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[11]; + vecOut[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + m[15]; +} + inline void Norm3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) { vecOut[0] = v[0] * m[0] + v[1] * m[3] + v[2] * m[6];