|
|
|
@ -52,6 +52,7 @@ static int s_texmtxread = 0;
|
|
|
|
|
|
|
|
|
|
static int loop_counter;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Vertex loaders read these. Although the scale ones should be baked into the shader.
|
|
|
|
|
int tcIndex;
|
|
|
|
|
int colIndex;
|
|
|
|
@ -60,9 +61,20 @@ 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),
|
|
|
|
@ -102,47 +114,326 @@ void LOADERDECL UpdateBoundingBoxPrepare()
|
|
|
|
|
VertexManager::s_pCurBufferPointer = (u8*)s_bbox_vertex_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LOADERDECL UpdateBoundingBox()
|
|
|
|
|
{
|
|
|
|
|
if (!PixelEngine::bbox_active)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// reset videodata pointer
|
|
|
|
|
// Reset videodata pointer
|
|
|
|
|
VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig;
|
|
|
|
|
|
|
|
|
|
// copy vertex pointers
|
|
|
|
|
// 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.
|
|
|
|
|
// Then convert to screen space and update the bounding box.
|
|
|
|
|
float p[3] = {s_bbox_vertex_buffer[0], s_bbox_vertex_buffer[1], s_bbox_vertex_buffer[2]};
|
|
|
|
|
// We must transform the just loaded point by the current world and projection matrix - in software
|
|
|
|
|
float transformed[3];
|
|
|
|
|
float screenPoint[3];
|
|
|
|
|
|
|
|
|
|
const float *world_matrix = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
|
|
|
|
|
const float *proj_matrix = &g_fProjectionMatrix[0];
|
|
|
|
|
// 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 + MatrixIndexA.PosNormalMtxIdx * 4;
|
|
|
|
|
const float * const proj_matrix = xfregs.projection.rawProjection;
|
|
|
|
|
|
|
|
|
|
float t[3];
|
|
|
|
|
t[0] = p[0] * world_matrix[0] + p[1] * world_matrix[1] + p[2] * world_matrix[2] + world_matrix[3];
|
|
|
|
|
t[1] = p[0] * world_matrix[4] + p[1] * world_matrix[5] + p[2] * world_matrix[6] + world_matrix[7];
|
|
|
|
|
t[2] = p[0] * world_matrix[8] + p[1] * world_matrix[9] + p[2] * world_matrix[10] + world_matrix[11];
|
|
|
|
|
// 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];
|
|
|
|
|
|
|
|
|
|
float o[3];
|
|
|
|
|
o[0] = t[0] * proj_matrix[0] + t[1] * proj_matrix[1] + t[2] * proj_matrix[2] + proj_matrix[3];
|
|
|
|
|
o[1] = t[0] * proj_matrix[4] + t[1] * proj_matrix[5] + t[2] * proj_matrix[6] + proj_matrix[7];
|
|
|
|
|
o[2] = t[0] * proj_matrix[12] + t[1] * proj_matrix[13] + t[2] * proj_matrix[14] + proj_matrix[15];
|
|
|
|
|
// Transform by projection matrix
|
|
|
|
|
switch (xfregs.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;
|
|
|
|
|
|
|
|
|
|
o[0] /= o[2];
|
|
|
|
|
o[1] /= o[2];
|
|
|
|
|
// 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];
|
|
|
|
|
|
|
|
|
|
// Max width seems to be 608, while max height is 480
|
|
|
|
|
// Here height is set to 484 as BBox bottom always seems to be off by a few pixels
|
|
|
|
|
o[0] = (o[0] + 1.0f) * 304.0f;
|
|
|
|
|
o[1] = (1.0f - o[1]) * 242.0f;
|
|
|
|
|
// We don't really have to care about z here
|
|
|
|
|
screenPoint[2] = -0.2f;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (o[0] < PixelEngine::bbox[0]) PixelEngine::bbox[0] = (u16) std::max(0.0f, o[0]);
|
|
|
|
|
if (o[0] > PixelEngine::bbox[1]) PixelEngine::bbox[1] = (u16) o[0];
|
|
|
|
|
if (o[1] < PixelEngine::bbox[2]) PixelEngine::bbox[2] = (u16) std::max(0.0f, o[1]);
|
|
|
|
|
if (o[1] > PixelEngine::bbox[3]) PixelEngine::bbox[3] = (u16) o[1];
|
|
|
|
|
default:
|
|
|
|
|
ERROR_LOG(VIDEO, "Unknown projection type: %d", xfregs.projection.type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.5 + (16.0f * (screenPoint[0] * xfregs.viewport.wd + (xfregs.viewport.xOrig - 342.0f))))) + 6) >> 4;
|
|
|
|
|
s_bbox_points[s_bbox_currPoint].y = (((s32)(0.5 + (16.0f * (screenPoint[1] * xfregs.viewport.ht + (xfregs.viewport.yOrig - 342.0f))))) + 6) >> 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) ? 1 : 0) << 1) | (((p0.x > 607) ? 1 : 0) << 2) | (((p0.y > 479) ? 1 : 0) << 3);
|
|
|
|
|
u8 b1 = ((p1.x > 0) ? 1 : 0) | (((p1.y > 0) ? 1 : 0) << 1) | (((p1.x > 607) ? 1 : 0) << 2) | (((p1.y > 479) ? 1 : 0) << 3);
|
|
|
|
|
|
|
|
|
|
// 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) ? 1 : 0) << 1) | (((p2.x > 607) ? 1 : 0) << 2) | (((p2.y > 479) ? 1 : 0) << 3);
|
|
|
|
|
|
|
|
|
|
// 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))
|
|
|
|
|
{
|
|
|
|
|
// Line
|
|
|
|
|
if (numPoints == 2)
|
|
|
|
|
{
|
|
|
|
|
left = (p0.x < p1.x) ? p0.x : p1.x;
|
|
|
|
|
top = (p0.y < p1.y) ? p0.y : p1.y;
|
|
|
|
|
right = (p0.x > p1.x) ? p0.x : p1.x;
|
|
|
|
|
bottom = (p0.y > p1.y) ? p0.y : p1.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Triangle
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
left = (p0.x < p1.x) ? (p0.x < p2.x) ? p0.x : p2.x : (p1.x < p2.x) ? p1.x : p2.x;
|
|
|
|
|
top = (p0.y < p1.y) ? (p0.y < p2.y) ? p0.y : p2.y : (p1.y < p2.y) ? p1.y : p2.y;
|
|
|
|
|
right = (p0.x > p1.x) ? (p0.x > p2.x) ? p0.x : p2.x : (p1.x > p2.x) ? p1.x : p2.x;
|
|
|
|
|
bottom = (p0.y > p1.y) ? (p0.y > p2.y) ? p0.y : p2.y : (p1.y > p2.y) ? p1.y : 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 = (p1.x < left) ? p1.x : left;
|
|
|
|
|
top = (p1.y < top) ? p1.y : top;
|
|
|
|
|
right = (p1.x > right) ? p1.x : right;
|
|
|
|
|
bottom = (p1.y > bottom) ? p1.y : bottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Third point inside
|
|
|
|
|
if ((b2 == 3) && (numPoints == 3))
|
|
|
|
|
{
|
|
|
|
|
left = (p2.x < left) ? p2.x : left;
|
|
|
|
|
top = (p2.y < top) ? p2.y : top;
|
|
|
|
|
right = (p2.x > right) ? p2.x : right;
|
|
|
|
|
bottom = (p2.y > bottom) ? 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 = (s < top) ? s : top; bottom = (s > bottom) ? s : bottom; }
|
|
|
|
|
if (i0 & 2) { s = (s32)((-c / m) + roundUp); if (s >= 0 && s <= 607) top = 0; left = (s < left) ? s : left; right = (s > right) ? s : right; }
|
|
|
|
|
if (i0 & 4) { s = (s32)((m * 607) + c + roundUp); if (s >= 0 && s <= 479) right = 607; top = (s < top) ? s : top; bottom = (s > bottom) ? s : bottom; }
|
|
|
|
|
if (i0 & 8) { s = (s32)(((479 - c) / m) + roundUp); if (s >= 0 && s <= 607) bottom = 479; left = (s < left) ? s : left; right = (s > right) ? 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 = (s < top) ? s : top; bottom = (s > bottom) ? s : bottom; }
|
|
|
|
|
if (i1 & 2) { s = (s32)((-c / m) + roundUp); if (s >= 0 && s <= 607) top = 0; left = (s < left) ? s : left; right = (s > right) ? s : right; }
|
|
|
|
|
if (i1 & 4) { s = (s32)((m * 607) + c + roundUp); if (s >= 0 && s <= 479) right = 607; top = (s < top) ? s : top; bottom = (s > bottom) ? s : bottom; }
|
|
|
|
|
if (i1 & 8) { s = (s32)(((479 - c) / m) + roundUp); if (s >= 0 && s <= 607) bottom = 479; left = (s < left) ? s : left; right = (s > right) ? 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 = (s < top) ? s : top; bottom = (s > bottom) ? s : bottom; }
|
|
|
|
|
if (i2 & 2) { s = (s32)((-c / m) + roundUp); if (s >= 0 && s <= 607) top = 0; left = (s < left) ? s : left; right = (s > right) ? s : right; }
|
|
|
|
|
if (i2 & 4) { s = (s32)((m * 607) + c + roundUp); if (s >= 0 && s <= 479) right = 607; top = (s < top) ? s : top; bottom = (s > bottom) ? s : bottom; }
|
|
|
|
|
if (i2 & 8) { s = (s32)(((479 - c) / m) + roundUp); if (s >= 0 && s <= 607) bottom = 479; left = (s < left) ? s : left; right = (s > right) ? 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];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LOADERDECL TexMtx_ReadDirect_UByte()
|
|
|
|
@ -584,6 +875,11 @@ int VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const
|
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
|
colElements[i] = m_VtxAttr.color[i].Elements;
|
|
|
|
|
|
|
|
|
|
// Prepare bounding box
|
|
|
|
|
s_bbox_primitive = primitive;
|
|
|
|
|
s_bbox_currPoint = 0;
|
|
|
|
|
s_bbox_loadedPoints = 0;
|
|
|
|
|
|
|
|
|
|
VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|