Add BBOX support (very conservative test)

This commit is contained in:
Henrik Rydgard
2013-11-12 17:06:03 +01:00
parent 54217deb16
commit cf15ec8a53
2 changed files with 62 additions and 30 deletions
+1 -1
View File
@@ -849,7 +849,7 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) {
currentList->bboxResult = true;
break;
}
if ((data % 8 == 0) && data < 64) { // Sanity check
if (((data & 7) == 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.");
+61 -29
View File
@@ -87,6 +87,7 @@
#include "GPU/GLES/VertexDecoder.h"
#include "GPU/GLES/ShaderManager.h"
#include "GPU/GLES/GLES_GPU.h"
#include "GPU/Common/SplineCommon.h"
const GLuint glprim[8] = {
GL_POINTS,
@@ -1370,49 +1371,80 @@ rotateVBO:
#endif
}
struct Plane {
float x, y, z, w;
void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
float Test(float f[3]) const { return x * f[0] + y * f[1] + z * f[2] + w; }
};
void PlanesFromMatrix(float mtx[16], Plane planes[6]) {
// TODO: Which order is the most optimal?
planes[0].Set(mtx[3]-mtx[0], mtx[7]-mtx[4], mtx[11]-mtx[8], mtx[15]-mtx[12]);// Right clipping plane.
planes[1].Set(mtx[3]+mtx[0], mtx[7]+mtx[4], mtx[11]+mtx[8], mtx[15]+mtx[12]);// Left clipping plane.
planes[2].Set(mtx[3]+mtx[1], mtx[7]+mtx[5], mtx[11]+mtx[9], mtx[15]+mtx[13]);// Bottom clipping plane.
planes[3].Set(mtx[3]-mtx[1], mtx[7]-mtx[5], mtx[11]-mtx[9], mtx[15]-mtx[13]);// Top clipping plane.
planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near clipping plane.
planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]);// Far clipping plane.
}
// This code is HIGHLY unoptimized!
//
// It does the simplest and safest test possible: If all points of a bbox is outside a single of
// our clipping planes, we reject the box.
bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount, u32 vertType) {
// Simplify away bones and morph before proceeding
/*
// Special case for float positions only.
// This clip test is not very accurate but does succeed in removing some bboxes at least.
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];
Plane planes[6];
// To world space...
float worldPos[3];
Vec3ByMatrix43(worldPos, (float *)&vert.pos.x, gstate.worldMatrix);
PlanesFromMatrix(gstate.projMatrix, planes);
// To view space...
float viewPos[3];
Vec3ByMatrix43(viewPos, worldPos, gstate.viewMatrix);
for (int plane = 0; plane < 6; plane++) {
int inside = 0;
int out = 0;
for (int box = 0; box < vertexCount / 8; box++) {
// For each box...
for (int i = 0; i < 8; i++) {
const SimpleVertex &vert = corners[box * 8 + i];
// And finally to screen space.
float frustumPos[4];
Vec3ByMatrix44(frustumPos, viewPos, gstate.projMatrix);
// To world space...
float worldPos[3];
Vec3ByMatrix43(worldPos, (float *)&vert.pos.x, gstate.worldMatrix);
// Project to 2D
float x = frustumPos[0] / frustumPos[3];
float y = frustumPos[1] / frustumPos[3];
// To view space...
float viewPos[3];
Vec3ByMatrix43(viewPos, worldPos, gstate.viewMatrix);
// Rescale 2d position
// ...
// Here we can test against the frustum planes!
float value = planes[plane].Test(viewPos);
if (value < 0)
out++;
else
inside++;
// float frustumPos[4];
// Vec3ByMatrix44(frustumPos, viewPos, gstate.projMatrix);
}
}
}
*/
// 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....
if (inside == 0) {
// All out
return false;
}
// Any out. For testing that the planes are in the right locations.
//if (out != 0) {
// All out
// return false;
//}
}
return true;
}