diff options
| author | crudelios <crudelios@gmail.com> | 2014-09-14 17:52:51 +0100 |
|---|---|---|
| committer | crudelios <crudelios@gmail.com> | 2014-10-10 12:27:06 +0100 |
| commit | 2d4b7e3f3f67f48ec2fb3d8eb8b2af3b70e4afcc (patch) | |
| tree | f81d5e738022be0234af2033badc51adef39ba49 /Source/Core/VideoCommon | |
| parent | b7aed97508ba74116858a111030bbd5783a633cb (diff) | |
Reimplement Bounding Box calculation using the software renderer.
Diffstat (limited to 'Source/Core/VideoCommon')
| -rw-r--r-- | Source/Core/VideoCommon/BPStructs.cpp | 11 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/BoundingBox.cpp | 150 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/BoundingBox.h | 41 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/PixelEngine.cpp | 18 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/PixelEngine.h | 12 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VertexLoader.cpp | 473 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoCommon.vcxproj | 6 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoCommon.vcxproj.filters | 10 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoState.cpp | 5 |
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 } |
