summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorcrudelios <crudelios@gmail.com>2014-09-14 17:52:51 +0100
committercrudelios <crudelios@gmail.com>2014-10-10 12:27:06 +0100
commit2d4b7e3f3f67f48ec2fb3d8eb8b2af3b70e4afcc (patch)
treef81d5e738022be0234af2033badc51adef39ba49 /Source/Core/VideoCommon
parentb7aed97508ba74116858a111030bbd5783a633cb (diff)
Reimplement Bounding Box calculation using the software renderer.
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/BPStructs.cpp11
-rw-r--r--Source/Core/VideoCommon/BoundingBox.cpp150
-rw-r--r--Source/Core/VideoCommon/BoundingBox.h41
-rw-r--r--Source/Core/VideoCommon/PixelEngine.cpp18
-rw-r--r--Source/Core/VideoCommon/PixelEngine.h12
-rw-r--r--Source/Core/VideoCommon/VertexLoader.cpp473
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj6
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj.filters10
-rw-r--r--Source/Core/VideoCommon/VideoState.cpp5
9 files changed, 236 insertions, 490 deletions
diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp
index 152d15a7d5..b307cbf2f4 100644
--- a/Source/Core/VideoCommon/BPStructs.cpp
+++ b/Source/Core/VideoCommon/BPStructs.cpp
@@ -19,6 +19,7 @@
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureDecoder.h"
+#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/VertexLoader.h"
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoCommon.h"
@@ -231,7 +232,7 @@ static void BPWritten(const BPCmd& bp)
// here. Not sure if there's a better spot to put this.
// the number of lines copied is determined by the y scale * source efb height
- PixelEngine::bbox_active = false;
+ BoundingBox::active = false;
float yScale;
if (PE_copy.scale_invert)
@@ -378,13 +379,13 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_CLEARBBOX2:
// Don't compute bounding box if this frame is being skipped!
// Wrong but valid values are better than bogus values...
- if (g_ActiveConfig.bUseBBox && !g_bSkipCurrentFrame)
+ if (!g_bSkipCurrentFrame)
{
u8 offset = bp.address & 2;
- PixelEngine::bbox[offset] = bp.newvalue & 0x3ff;
- PixelEngine::bbox[offset | 1] = bp.newvalue >> 10;
- PixelEngine::bbox_active = true;
+ BoundingBox::coords[offset] = bp.newvalue & 0x3ff;
+ BoundingBox::coords[offset + 1] = bp.newvalue >> 10;
+ BoundingBox::active = true;
}
return;
case BPMEM_TEXINVALIDATE:
diff --git a/Source/Core/VideoCommon/BoundingBox.cpp b/Source/Core/VideoCommon/BoundingBox.cpp
new file mode 100644
index 0000000000..b76db60dab
--- /dev/null
+++ b/Source/Core/VideoCommon/BoundingBox.cpp
@@ -0,0 +1,150 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "VideoCommon/PixelShaderManager.h"
+#include "VideoBackends/Software/SetupUnit.h"
+#include "VideoBackends/Software/TransformUnit.h"
+#include "VideoBackends/Software/Clipper.h"
+#include "VideoBackends/Software/Rasterizer.h"
+
+#include "VideoCommon/BoundingBox.h"
+
+namespace BoundingBox
+{
+
+// External vars
+bool active = false;
+u16 coords[4] = { 0x80, 0xA0, 0x80, 0xA0 };
+u8 posMtxIdx;
+u8 texMtxIdx[8];
+
+
+// Internal vars
+SetupUnit vtxUnit;
+VAT myVat;
+u8 * bufferPos;
+TVtxDesc vertexDesc;
+PortableVertexDeclaration vertexDecl;
+
+// Gets the pointer to the current buffer position
+void LOADERDECL SetVertexBufferPosition()
+{
+ bufferPos = VertexManager::s_pCurBufferPointer;
+}
+
+// Prepares the bounding box for new primitive data
+void Prepare(const VAT & vat, int primitive, const TVtxDesc & vtxDesc, const PortableVertexDeclaration & vtxDecl)
+{
+ if (!active)
+ return;
+
+ myVat = vat;
+ vertexDesc = vtxDesc;
+ vertexDecl = vtxDecl;
+
+ vtxUnit.Init(primitive);
+
+ // Initialize the SW renderer
+ static bool SWinit = false;
+
+ if (!SWinit)
+ {
+ Clipper::Init();
+ Rasterizer::Init();
+ SWinit = true;
+ }
+
+ // Update SW renderer values
+ Clipper::SetViewOffset();
+ Rasterizer::SetScissor();
+
+ for (u8 i = 0; i < 4; ++i)
+ {
+ Rasterizer::SetTevReg(i, 0, true, (s16)PixelShaderManager::constants.kcolors[i][0]);
+ Rasterizer::SetTevReg(i, 1, true, (s16)PixelShaderManager::constants.kcolors[i][1]);
+ Rasterizer::SetTevReg(i, 2, true, (s16)PixelShaderManager::constants.kcolors[i][2]);
+ Rasterizer::SetTevReg(i, 3, true, (s16)PixelShaderManager::constants.kcolors[i][3]);
+
+ Rasterizer::SetTevReg(i, 0, false, (s16)PixelShaderManager::constants.colors[i][0]);
+ Rasterizer::SetTevReg(i, 1, false, (s16)PixelShaderManager::constants.colors[i][1]);
+ Rasterizer::SetTevReg(i, 2, false, (s16)PixelShaderManager::constants.colors[i][2]);
+ Rasterizer::SetTevReg(i, 3, false, (s16)PixelShaderManager::constants.colors[i][3]);
+ }
+}
+
+// Updates the bounding box
+void LOADERDECL Update()
+{
+ if (!active)
+ return;
+
+ // Grab vertex input data and transform to output vertex
+ InputVertexData myVertex;
+ OutputVertexData * outVertex = vtxUnit.GetVertex();
+
+ // Feed vertex position and matrix
+ myVertex.position = Vec3((const float *)bufferPos);
+ myVertex.posMtx = vertexDesc.PosMatIdx ? posMtxIdx : MatrixIndexA.PosNormalMtxIdx;
+
+ // Transform position
+ TransformUnit::TransformPosition(&myVertex, outVertex);
+
+ if (g_VtxDesc.Normal != NOT_PRESENT)
+ {
+ // Feed normal input data and transform
+ myVat.g0.NormalIndex3;
+
+ memcpy((u8 *)myVertex.normal, bufferPos + vertexDecl.normals[0].offset, sizeof(float) * 3 * ((myVat.g0.NormalElements) ? 3 : 1));
+
+ TransformUnit::TransformNormal(&myVertex, myVat.g0.NormalElements, outVertex);
+ }
+
+ // Feed color input data
+ for (int i = 0; i < 2; ++i)
+ {
+ if (vertexDecl.colors[i].enable)
+ {
+ u32 color;
+ memcpy((u8 *)&color, bufferPos + vertexDecl.colors[i].offset, sizeof(u32));
+ *(u32*)myVertex.color[i] = Common::swap32(color);
+ }
+ }
+
+ // Transform color
+ TransformUnit::TransformColor(&myVertex, outVertex);
+
+ // Feed texture matrices
+ int idx = 0;
+
+ myVertex.texMtx[0] = (vertexDesc.Tex0MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex0MtxIdx;
+ myVertex.texMtx[1] = (vertexDesc.Tex1MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex1MtxIdx;
+ myVertex.texMtx[2] = (vertexDesc.Tex2MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex2MtxIdx;
+ myVertex.texMtx[3] = (vertexDesc.Tex3MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex3MtxIdx;
+ myVertex.texMtx[4] = (vertexDesc.Tex4MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex4MtxIdx;
+ myVertex.texMtx[5] = (vertexDesc.Tex5MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex5MtxIdx;
+ myVertex.texMtx[6] = (vertexDesc.Tex6MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex6MtxIdx;
+ myVertex.texMtx[7] = (vertexDesc.Tex7MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex7MtxIdx;
+
+ // Feed texture coordinate data
+ for (int i = 0; i < 8; ++i)
+ {
+ if (vertexDecl.texcoords[i].enable)
+ memcpy((u8 *)&myVertex.texCoords[i], bufferPos + vertexDecl.texcoords[i].offset, sizeof(float) * 2);
+ }
+
+ // Transform texture coordinate
+ TransformUnit::TransformTexCoord(&myVertex, outVertex, false);
+
+ // Render the vertex in SW to calculate bbox
+ vtxUnit.SetupVertex();
+}
+
+// Save state
+void DoState(PointerWrap &p)
+{
+ p.Do(active);
+ p.Do(coords);
+}
+
+} // namespace BoundingBox
diff --git a/Source/Core/VideoCommon/BoundingBox.h b/Source/Core/VideoCommon/BoundingBox.h
new file mode 100644
index 0000000000..d6952b184e
--- /dev/null
+++ b/Source/Core/VideoCommon/BoundingBox.h
@@ -0,0 +1,41 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "VideoCommon/VertexLoader.h"
+
+// Bounding Box manager
+
+namespace BoundingBox
+{
+
+// Determines if bounding box is active
+extern bool active;
+
+// Bounding box current coordinates
+extern u16 coords[4];
+
+enum
+{
+ LEFT = 0,
+ RIGHT = 1,
+ TOP = 2,
+ BOTTOM = 3
+};
+
+// Current position matrix index
+extern u8 posMtxIdx;
+
+// Texture matrix indexes
+extern u8 texMtxIdx[8];
+
+void LOADERDECL SetVertexBufferPosition();
+void LOADERDECL Update();
+void Prepare(const VAT & vat, int primitive, const TVtxDesc & vtxDesc, const PortableVertexDeclaration & vtxDecl);
+
+// Save state
+void DoState(PointerWrap &p);
+
+}; // end of namespace BoundingBox
diff --git a/Source/Core/VideoCommon/PixelEngine.cpp b/Source/Core/VideoCommon/PixelEngine.cpp
index da36e2d019..877acf916c 100644
--- a/Source/Core/VideoCommon/PixelEngine.cpp
+++ b/Source/Core/VideoCommon/PixelEngine.cpp
@@ -16,6 +16,7 @@
#include "Core/HW/ProcessorInterface.h"
#include "VideoCommon/CommandProcessor.h"
#include "VideoCommon/PixelEngine.h"
+#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoCommon.h"
@@ -106,9 +107,6 @@ static int et_SetFinishOnMainThread;
static volatile u32 interruptSetToken = 0;
static volatile u32 interruptSetFinish = 0;
-u16 bbox[4];
-bool bbox_active;
-
enum
{
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
@@ -128,9 +126,6 @@ void DoState(PointerWrap &p)
p.Do(g_bSignalFinishInterrupt);
p.Do(interruptSetToken);
p.Do(interruptSetFinish);
-
- p.Do(bbox);
- p.Do(bbox_active);
}
void UpdateInterrupts();
@@ -155,13 +150,6 @@ void Init()
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
-
- bbox[0] = 0x80;
- bbox[1] = 0xA0;
- bbox[2] = 0x80;
- bbox[3] = 0xA0;
-
- bbox_active = false;
}
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
@@ -244,8 +232,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
mmio->Register(base | (PE_BBOX_LEFT + 2 * i),
MMIO::ComplexRead<u16>([i](u32) {
- bbox_active = false;
- return bbox[i];
+ BoundingBox::active = false;
+ return BoundingBox::coords[i];
}),
MMIO::InvalidWrite<u16>()
);
diff --git a/Source/Core/VideoCommon/PixelEngine.h b/Source/Core/VideoCommon/PixelEngine.h
index 28df0ddb6e..b79449f5c8 100644
--- a/Source/Core/VideoCommon/PixelEngine.h
+++ b/Source/Core/VideoCommon/PixelEngine.h
@@ -18,10 +18,10 @@ enum
PE_ALPHAREAD = 0x08, // Alpha Read
PE_CTRL_REGISTER = 0x0a, // Control
PE_TOKEN_REG = 0x0e, // Token
- PE_BBOX_LEFT = 0x10, // Flip Left
- PE_BBOX_RIGHT = 0x12, // Flip Right
- PE_BBOX_TOP = 0x14, // Flip Top
- PE_BBOX_BOTTOM = 0x16, // Flip Bottom
+ PE_BBOX_LEFT = 0x10, // Bounding Box Left Pixel
+ PE_BBOX_RIGHT = 0x12, // Bounding Box Right Pixel
+ PE_BBOX_TOP = 0x14, // Bounding Box Top Pixel
+ PE_BBOX_BOTTOM = 0x16, // Bounding Box Bottom Pixel
// NOTE: Order not verified
// These indicate the number of quads that are being used as input/output for each particular stage
@@ -63,8 +63,4 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish();
UPEAlphaReadReg GetAlphaReadMode();
-// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
-extern u16 bbox[4];
-extern bool bbox_active;
-
} // end of namespace PixelEngine
diff --git a/Source/Core/VideoCommon/VertexLoader.cpp b/Source/Core/VideoCommon/VertexLoader.cpp
index b2f3cd7a4e..8bef28cc90 100644
--- a/Source/Core/VideoCommon/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/VertexLoader.cpp
@@ -14,6 +14,7 @@
#include "VideoCommon/LookUpTables.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/VertexLoader.h"
+#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/VertexLoader_Color.h"
#include "VideoCommon/VertexLoader_Normal.h"
#include "VideoCommon/VertexLoader_Position.h"
@@ -21,8 +22,6 @@
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
-//BBox
-#include "VideoCommon/XFMemory.h"
#define COMPILED_CODE_SIZE 4096
@@ -45,21 +44,6 @@ int colElements[2];
float posScale;
float tcScale[8];
-// bbox variables
-// bbox must read vertex position, so convert it to this buffer
-static float s_bbox_vertex_buffer[3];
-static u8 *s_bbox_pCurBufferPointer_orig;
-static int s_bbox_primitive;
-static struct Point
-{
- s32 x;
- s32 y;
- float z;
-} s_bbox_points[3];
-static u8 s_bbox_currPoint;
-static u8 s_bbox_loadedPoints;
-static const u8 s_bbox_primitivePoints[8] = { 3, 0, 3, 3, 3, 2, 2, 1 };
-
static const float fractionTable[32] = {
1.0f / (1U << 0), 1.0f / (1U << 1), 1.0f / (1U << 2), 1.0f / (1U << 3),
1.0f / (1U << 4), 1.0f / (1U << 5), 1.0f / (1U << 6), 1.0f / (1U << 7),
@@ -75,7 +59,7 @@ using namespace Gen;
static void LOADERDECL PosMtx_ReadDirect_UByte()
{
- s_curposmtx = DataReadU8() & 0x3f;
+ BoundingBox::posMtxIdx = s_curposmtx = DataReadU8() & 0x3f;
PRIM_LOG("posmtx: %d, ", s_curposmtx);
}
@@ -85,437 +69,12 @@ static void LOADERDECL PosMtx_Write()
DataWrite<u8>(0);
DataWrite<u8>(0);
DataWrite<u8>(0);
-
- // Resetting current position matrix to default is needed for bbox to behave
- s_curposmtx = (u8) g_main_cp_state.matrix_index_a.PosNormalMtxIdx;
-}
-
-static void LOADERDECL UpdateBoundingBoxPrepare()
-{
- if (!PixelEngine::bbox_active)
- return;
-
- // set our buffer as videodata buffer, so we will get a copy of the vertex positions
- // this is a big hack, but so we can use the same converting function then without bbox
- s_bbox_pCurBufferPointer_orig = VertexManager::s_pCurBufferPointer;
- VertexManager::s_pCurBufferPointer = (u8*)s_bbox_vertex_buffer;
-}
-
-static inline bool UpdateBoundingBoxVars()
-{
- switch (s_bbox_primitive)
- {
- // Quads: fill 0,1,2 (check),1 (check, clear, repeat)
- case 0:
- ++s_bbox_loadedPoints;
- if (s_bbox_loadedPoints == 3)
- {
- s_bbox_currPoint = 1;
- return true;
- }
- if (s_bbox_loadedPoints == 4)
- {
- s_bbox_loadedPoints = 0;
- s_bbox_currPoint = 0;
- return true;
- }
- ++s_bbox_currPoint;
- return false;
-
- // Triangles: 0,1,2 (check, clear, repeat)
- case 2:
- ++s_bbox_loadedPoints;
- if (s_bbox_loadedPoints == 3)
- {
- s_bbox_loadedPoints = 0;
- s_bbox_currPoint = 0;
- return true;
- }
- ++s_bbox_currPoint;
- return false;
-
- // Triangle strip: 0, 1, 2 (check), 0 (check), 1, (check), 2 (check, repeat checking 0, 1, 2)
- case 3:
- if (++s_bbox_currPoint == 3)
- s_bbox_currPoint = 0;
-
- if (s_bbox_loadedPoints == 2)
- return true;
-
- ++s_bbox_loadedPoints;
- return false;
-
- // Triangle fan: 0,1,2 (check), 1 (check), 2 (check, repeat checking 1,2)
- case 4:
- s_bbox_currPoint ^= s_bbox_currPoint ? 3 : 1;
-
- if (s_bbox_loadedPoints == 2)
- return true;
-
- ++s_bbox_loadedPoints;
- return false;
-
- // Lines: 0,1 (check, clear, repeat)
- case 5:
- ++s_bbox_loadedPoints;
- if (s_bbox_loadedPoints == 2)
- {
- s_bbox_loadedPoints = 0;
- s_bbox_currPoint = 0;
- return true;
- }
- ++s_bbox_currPoint;
- return false;
-
- // Line strip: 0,1 (check), 0 (check), 1 (check, repeat checking 0,1)
- case 6:
- s_bbox_currPoint ^= 1;
-
- if (s_bbox_loadedPoints == 1)
- return true;
-
- ++s_bbox_loadedPoints;
- return false;
-
- // Points: 0 (check, clear, repeat)
- case 7:
- return true;
-
- // This should not happen!
- default:
- return false;
- }
-}
-
-static void LOADERDECL UpdateBoundingBox()
-{
- if (!PixelEngine::bbox_active)
- return;
-
- // Reset videodata pointer
- VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig;
-
- // Copy vertex pointers
- memcpy(VertexManager::s_pCurBufferPointer, s_bbox_vertex_buffer, 12);
- VertexManager::s_pCurBufferPointer += 12;
-
- // We must transform the just loaded point by the current world and projection matrix - in software
- float transformed[3];
- float screenPoint[3];
-
- // We need to get the raw projection values for the bounding box calculation
- // to work properly. That means, no projection hacks!
- const float * const orig_point = s_bbox_vertex_buffer;
- const float * const world_matrix = (float*)xfmem.posMatrices + s_curposmtx * 4;
- const float * const proj_matrix = xfmem.projection.rawProjection;
-
- // Transform by world matrix
- // Only calculate what we need, discard the rest
- transformed[0] = orig_point[0] * world_matrix[0] + orig_point[1] * world_matrix[1] + orig_point[2] * world_matrix[2] + world_matrix[3];
- transformed[1] = orig_point[0] * world_matrix[4] + orig_point[1] * world_matrix[5] + orig_point[2] * world_matrix[6] + world_matrix[7];
-
- // Transform by projection matrix
- switch (xfmem.projection.type)
- {
- // Perspective projection, we must divide by w
- case GX_PERSPECTIVE:
- transformed[2] = orig_point[0] * world_matrix[8] + orig_point[1] * world_matrix[9] + orig_point[2] * world_matrix[10] + world_matrix[11];
- screenPoint[0] = (transformed[0] * proj_matrix[0] + transformed[2] * proj_matrix[1]) / (-transformed[2]);
- screenPoint[1] = (transformed[1] * proj_matrix[2] + transformed[2] * proj_matrix[3]) / (-transformed[2]);
- screenPoint[2] = ((transformed[2] * proj_matrix[4] + proj_matrix[5]) * (1.0f - (float) 1e-7)) / (-transformed[2]);
- break;
-
- // Orthographic projection
- case GX_ORTHOGRAPHIC:
- screenPoint[0] = transformed[0] * proj_matrix[0] + proj_matrix[1];
- screenPoint[1] = transformed[1] * proj_matrix[2] + proj_matrix[3];
-
- // We don't really have to care about z here
- screenPoint[2] = -0.2f;
- break;
-
- default:
- ERROR_LOG(VIDEO, "Unknown projection type: %d", xfmem.projection.type);
- screenPoint[0] = screenPoint[1] = screenPoint[2] = 1;
- }
-
- // Convert to screen space and add the point to the list - round like the real hardware
- s_bbox_points[s_bbox_currPoint].x = (((s32) (0.5f + (16.0f * (screenPoint[0] * xfmem.viewport.wd + (xfmem.viewport.xOrig - 342.0f))))) + 3) >> 4;
- s_bbox_points[s_bbox_currPoint].y = (((s32) (0.5f + (16.0f * (screenPoint[1] * xfmem.viewport.ht + (xfmem.viewport.yOrig - 342.0f))))) + 3) >> 4;
- s_bbox_points[s_bbox_currPoint].z = screenPoint[2];
-
- // Update point list for primitive
- bool check_bbox = UpdateBoundingBoxVars();
-
- // If we do not have enough points to check the bounding box yet, we are done for now
- if (!check_bbox)
- return;
-
- // How many points does our primitive have?
- const u8 numPoints = s_bbox_primitivePoints[s_bbox_primitive];
-
- // If the primitive is a point, update the bounding box now
- if (numPoints == 1)
- {
- Point & p = s_bbox_points[0];
-
- // Point is out of bounds
- if (p.x < 0 || p.x > 607 || p.y < 0 || p.y > 479 || p.z >= 0.0f)
- return;
-
- // Point is in bounds. Update bounding box if necessary and return
- PixelEngine::bbox[0] = (p.x < PixelEngine::bbox[0]) ? p.x : PixelEngine::bbox[0];
- PixelEngine::bbox[1] = (p.x > PixelEngine::bbox[1]) ? p.x : PixelEngine::bbox[1];
- PixelEngine::bbox[2] = (p.y < PixelEngine::bbox[2]) ? p.y : PixelEngine::bbox[2];
- PixelEngine::bbox[3] = (p.y > PixelEngine::bbox[3]) ? p.y : PixelEngine::bbox[3];
-
- return;
- }
-
- // Now comes the fun part. We must clip the triangles/lines to the viewport - also in software
- Point & p0 = s_bbox_points[0], &p1 = s_bbox_points[1], &p2 = s_bbox_points[2];
-
- // Check for z-clip. This crude method is required for Mickey's Magical Mirror, at least
- if ((p0.z > 0.0f) || (p1.z > 0.0f) || ((numPoints == 3) && (p2.z > 0.0f)))
- return;
-
- // Check points for bounds
- u8 b0 = ((p0.x > 0) ? 1 : 0) | ((p0.y > 0) ? 2 : 0) | ((p0.x > 607) ? 4 : 0) | ((p0.y > 479) ? 8 : 0);
- u8 b1 = ((p1.x > 0) ? 1 : 0) | ((p1.y > 0) ? 2 : 0) | ((p1.x > 607) ? 4 : 0) | ((p1.y > 479) ? 8 : 0);
-
- // Let's be practical... If we only have a line, setting b2 to 3 saves an "if"-clause later on
- u8 b2 = 3;
-
- // Otherwise if we have a triangle, we need to check the third point
- if (numPoints == 3)
- b2 = ((p2.x > 0) ? 1 : 0) | ((p2.y > 0) ? 2 : 0) | ((p2.x > 607) ? 4 : 0) | ((p2.y > 479) ? 8 : 0);
-
- // These are the internal bbox vars
- s32 left = 608, right = -1, top = 480, bottom = -1;
-
- // If the polygon is inside viewport, let's update the bounding box and be done with it
- if ((b0 == 3) && (b0 == b1) && (b0 == b2))
- {
- left = std::min(p0.x, p1.x);
- top = std::min(p0.y, p1.y);
- right = std::max(p0.x, p1.x);
- bottom = std::max(p0.y, p1.y);
-
- // Triangle
- if (numPoints == 3)
- {
- left = std::min(left, p2.x);
- top = std::min(top, p2.y);
- right = std::max(right, p2.x);
- bottom = std::max(bottom, p2.y);
- }
-
- // Update bounding box
- PixelEngine::bbox[0] = (left < PixelEngine::bbox[0]) ? left : PixelEngine::bbox[0];
- PixelEngine::bbox[1] = (right > PixelEngine::bbox[1]) ? right : PixelEngine::bbox[1];
- PixelEngine::bbox[2] = (top < PixelEngine::bbox[2]) ? top : PixelEngine::bbox[2];
- PixelEngine::bbox[3] = (bottom > PixelEngine::bbox[3]) ? bottom : PixelEngine::bbox[3];
-
- return;
- }
-
- // If it is not inside, then either it is completely outside, or it needs clipping.
- // Check the primitive's lines
- u8 i0 = b0 ^ b1;
- u8 i1 = (numPoints == 3) ? (b1 ^ b2) : i0;
- u8 i2 = (numPoints == 3) ? (b0 ^ b2) : i0;
-
- // Primitive out of bounds - return
- if (!(i0 | i1 | i2))
- return;
-
- // First point inside viewport - update internal bbox
- if (b0 == 3)
- {
- left = p0.x;
- top = p0.y;
- right = p0.x;
- bottom = p0.y;
- }
-
- // Second point inside
- if (b1 == 3)
- {
- left = std::min(p1.x, left);
- top = std::min(p1.y, top);
- right = std::max(p1.x, right);
- bottom = std::max(p1.y, bottom);
- }
-
- // Third point inside
- if ((b2 == 3) && (numPoints == 3))
- {
- left = std::min(p2.x, left);
- top = std::min(p2.y, top);
- right = std::max(p2.x, right);
- bottom = std::max(p2.y, bottom);
- }
-
- // Triangle equation vars
- float m, c;
-
- // Some definitions to help with rounding later on
- const float highNum = 89374289734.0f;
- const float roundUp = 0.001f;
-
- // Intersection result
- s32 s;
-
- // First line intersects
- if (i0)
- {
- m = (p1.x - p0.x) ? ((p1.y - p0.y) / (p1.x - p0.x)) : highNum;
- c = p0.y - (m * p0.x);
- if (i0 & 1)
- {
- s = (s32)(c + roundUp);
- if (s >= 0 && s <= 479)
- left = 0;
- top = std::min(s, top);
- bottom = std::max(s, bottom);
- }
-
- if (i0 & 2)
- {
- s = (s32)((-c / m) + roundUp);
- if (s >= 0 && s <= 607)
- top = 0;
- left = std::min(s, left);
- right = std::max(s, right);
- }
-
- if (i0 & 4)
- {
- s = (s32)((m * 607) + c + roundUp);
- if (s >= 0 && s <= 479)
- right = 607;
- top = std::min(s, top);
- bottom = std::max(s, bottom);
- }
-
- if (i0 & 8)
- {
- s = (s32)(((479 - c) / m) + roundUp);
- if (s >= 0 && s <= 607)
- bottom = 479;
- left = std::min(s, left);
- right = std::max(s, right);
- }
- }
-
- // Only check other lines if we are dealing with a triangle
- if (numPoints == 3)
- {
- // Second line intersects
- if (i1)
- {
- m = (p2.x - p1.x) ? ((p2.y - p1.y) / (p2.x - p1.x)) : highNum;
- c = p1.y - (m * p1.x);
- if (i1 & 1)
- {
- s = (s32)(c + roundUp);
- if (s >= 0 && s <= 479)
- left = 0;
- top = std::min(s, top);
- bottom = std::max(s, bottom);
- }
-
- if (i1 & 2)
- {
- s = (s32)((-c / m) + roundUp);
- if (s >= 0 && s <= 607)
- top = 0;
- left = std::min(s, left);
- right = std::max(s, right);
- }
-
- if (i1 & 4)
- {
- s = (s32)((m * 607) + c + roundUp);
- if (s >= 0 && s <= 479)
- right = 607;
- top = std::min(s, top);
- bottom = std::max(s, bottom);
- }
-
- if (i1 & 8)
- {
- s = (s32)(((479 - c) / m) + roundUp);
- if (s >= 0 && s <= 607)
- bottom = 479;
- left = std::min(s, left);
- right = std::max(s, right);
- }
- }
-
- // Third line intersects
- if (i2)
- {
- m = (p2.x - p0.x) ? ((p2.y - p0.y) / (p2.x - p0.x)) : highNum;
- c = p0.y - (m * p0.x);
- if (i2 & 1)
- {
- s = (s32)(c + roundUp);
- if (s >= 0 && s <= 479)
- left = 0;
- top = std::min(s, top);
- bottom = std::max(s, bottom);
- }
-
- if (i2 & 2)
- {
- s = (s32)((-c / m) + roundUp);
- if (s >= 0 && s <= 607)
- top = 0;
- left = std::min(s, left);
- right = std::max(s, right);
- }
-
- if (i2 & 4)
- {
- s = (s32)((m * 607) + c + roundUp);
- if (s >= 0 && s <= 479)
- right = 607;
- top = std::min(s, top);
- bottom = std::max(s, bottom);
- }
-
- if (i2 & 8)
- {
- s = (s32)(((479 - c) / m) + roundUp);
- if (s >= 0 && s <= 607)
- bottom = 479;
- left = std::min(s, left);
- right = std::max(s, right);
- }
- }
- }
-
- // Wrong bounding box values, discard this polygon (it is outside)
- if (left > 607 || top > 479 || right < 0 || bottom < 0)
- return;
-
- // Trim bounding box to viewport
- left = (left < 0) ? 0 : left;
- top = (top < 0) ? 0 : top;
- right = (right > 607) ? 607 : right;
- bottom = (bottom > 479) ? 479 : bottom;
-
- // Update bounding box
- PixelEngine::bbox[0] = (left < PixelEngine::bbox[0]) ? left : PixelEngine::bbox[0];
- PixelEngine::bbox[1] = (right > PixelEngine::bbox[1]) ? right : PixelEngine::bbox[1];
- PixelEngine::bbox[2] = (top < PixelEngine::bbox[2]) ? top : PixelEngine::bbox[2];
- PixelEngine::bbox[3] = (bottom > PixelEngine::bbox[3]) ? bottom : PixelEngine::bbox[3];
}
static void LOADERDECL TexMtx_ReadDirect_UByte()
{
- s_curtexmtx[s_texmtxread] = DataReadU8() & 0x3f;
+ BoundingBox::texMtxIdx[s_texmtxread] = s_curtexmtx[s_texmtxread] = DataReadU8() & 0x3f;
+
PRIM_LOG("texmtx%d: %d, ", s_texmtxread, s_curtexmtx[s_texmtxread]);
s_texmtxread++;
}
@@ -611,6 +170,10 @@ void VertexLoader::CompileVertexTranslator()
m_numPipelineStages = 0;
#endif
+ // Get the pointer to this vertex's buffer data for the bounding box
+ if (g_ActiveConfig.bUseBBox)
+ WriteCall(BoundingBox::SetVertexBufferPosition);
+
// Colors
const u64 col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
// TextureCoord
@@ -643,16 +206,8 @@ void VertexLoader::CompileVertexTranslator()
if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); }
// Write vertex position loader
- if (g_ActiveConfig.bUseBBox)
- {
- WriteCall(UpdateBoundingBoxPrepare);
- WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
- WriteCall(UpdateBoundingBox);
- }
- else
- {
- WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
- }
+ WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+
m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements);
nat_offset += 12;
m_native_vtx_decl.position.components = 3;
@@ -826,6 +381,10 @@ void VertexLoader::CompileVertexTranslator()
}
}
+ // Update the bounding box
+ if (g_ActiveConfig.bUseBBox)
+ WriteCall(BoundingBox::Update);
+
if (m_VtxDesc.PosMatIdx)
{
WriteCall(PosMtx_Write);
@@ -901,9 +460,7 @@ void VertexLoader::SetupRunVertices(const VAT& vat, int primitive, int const cou
colElements[i] = m_VtxAttr.color[i].Elements;
// Prepare bounding box
- s_bbox_primitive = primitive;
- s_bbox_currPoint = 0;
- s_bbox_loadedPoints = 0;
+ BoundingBox::Prepare(vat, primitive, m_VtxDesc, m_native_vtx_decl);
}
void VertexLoader::ConvertVertices ( int count )
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj
index 7f7de6b040..bda73f396c 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@@ -36,6 +36,7 @@
<PropertyGroup Label="UserMacros" />
<ItemGroup>
<ClCompile Include="AVIDump.cpp" />
+ <ClCompile Include="BoundingBox.cpp" />
<ClCompile Include="BPFunctions.cpp" />
<ClCompile Include="BPMemory.cpp" />
<ClCompile Include="BPStructs.cpp" />
@@ -80,6 +81,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="AVIDump.h" />
+ <ClInclude Include="BoundingBox.h" />
<ClInclude Include="BPFunctions.h" />
<ClInclude Include="BPMemory.h" />
<ClInclude Include="BPStructs.h" />
@@ -147,4 +149,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
index 24dcf3b610..c662422200 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Base">
@@ -140,6 +140,9 @@
<ClCompile Include="TextureDecoder_x64.cpp">
<Filter>Decoding</Filter>
</ClCompile>
+ <ClCompile Include="BoundingBox.cpp">
+ <Filter>Util</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CommandProcessor.h" />
@@ -269,8 +272,11 @@
<ClInclude Include="VertexLoaderManager.h">
<Filter>Vertex Loading</Filter>
</ClInclude>
+ <ClInclude Include="BoundingBox.h">
+ <Filter>Util</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Source/Core/VideoCommon/VideoState.cpp b/Source/Core/VideoCommon/VideoState.cpp
index dd0eb2fb88..1f23d5318d 100644
--- a/Source/Core/VideoCommon/VideoState.cpp
+++ b/Source/Core/VideoCommon/VideoState.cpp
@@ -14,6 +14,7 @@
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoState.h"
#include "VideoCommon/XFMemory.h"
+#include "VideoCommon/BoundingBox.h"
static void DoState(PointerWrap &p)
{
@@ -52,6 +53,10 @@ static void DoState(PointerWrap &p)
VertexManager::DoState(p);
p.DoMarker("VertexManager");
+ BoundingBox::DoState(p);
+ p.DoMarker("BoundingBox");
+
+
// TODO: search for more data that should be saved and add it here
}