2014-09-14 14:04:09 -07:00
|
|
|
// Copyright (c) 2013- PPSSPP Project.
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
// Official git repository and contact information can be found at
|
|
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
|
|
|
#include "GPU/Common/DrawEngineCommon.h"
|
|
|
|
#include "GPU/Common/SplineCommon.h"
|
|
|
|
#include "GPU/ge_constants.h"
|
|
|
|
#include "GPU/GPUState.h"
|
|
|
|
|
2014-09-13 15:13:34 +02:00
|
|
|
DrawEngineCommon::~DrawEngineCommon() { }
|
2014-09-14 14:04:09 -07:00
|
|
|
|
|
|
|
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; }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void PlanesFromMatrix(float mtx[16], Plane planes[6]) {
|
|
|
|
planes[0].Set(mtx[3]-mtx[0], mtx[7]-mtx[4], mtx[11]-mtx[8], mtx[15]-mtx[12]); // Right
|
|
|
|
planes[1].Set(mtx[3]+mtx[0], mtx[7]+mtx[4], mtx[11]+mtx[8], mtx[15]+mtx[12]); // Left
|
|
|
|
planes[2].Set(mtx[3]+mtx[1], mtx[7]+mtx[5], mtx[11]+mtx[9], mtx[15]+mtx[13]); // Bottom
|
|
|
|
planes[3].Set(mtx[3]-mtx[1], mtx[7]-mtx[5], mtx[11]-mtx[9], mtx[15]-mtx[13]); // Top
|
|
|
|
planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near
|
|
|
|
planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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. Tighter bounds would be desirable but would take more calculations.
|
|
|
|
bool DrawEngineCommon::TestBoundingBox(void* control_points, int vertexCount, u32 vertType) {
|
|
|
|
SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12);
|
|
|
|
float *verts = (float *)(decoded + 65536 * 18);
|
|
|
|
|
|
|
|
// Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder
|
|
|
|
// and a large vertex format.
|
|
|
|
if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT) {
|
|
|
|
// memcpy(verts, control_points, 12 * vertexCount);
|
|
|
|
verts = (float *)control_points;
|
|
|
|
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT) {
|
|
|
|
const s8 *vtx = (const s8 *)control_points;
|
|
|
|
for (int i = 0; i < vertexCount * 3; i++) {
|
|
|
|
verts[i] = vtx[i] * (1.0f / 128.0f);
|
|
|
|
}
|
|
|
|
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT) {
|
|
|
|
const s16 *vtx = (const s16*)control_points;
|
|
|
|
for (int i = 0; i < vertexCount * 3; i++) {
|
|
|
|
verts[i] = vtx[i] * (1.0f / 32768.0f);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Simplify away bones and morph before proceeding
|
|
|
|
u8 *temp_buffer = decoded + 65536 * 24;
|
|
|
|
NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType);
|
|
|
|
// Special case for float positions only.
|
|
|
|
const float *ctrl = (const float *)control_points;
|
|
|
|
for (int i = 0; i < vertexCount; i++) {
|
|
|
|
verts[i * 3] = corners[i].pos.x;
|
|
|
|
verts[i * 3 + 1] = corners[i].pos.y;
|
|
|
|
verts[i * 3 + 2] = corners[i].pos.z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Plane planes[6];
|
|
|
|
|
|
|
|
float world[16];
|
|
|
|
float view[16];
|
|
|
|
float worldview[16];
|
|
|
|
float worldviewproj[16];
|
|
|
|
ConvertMatrix4x3To4x4(world, gstate.worldMatrix);
|
|
|
|
ConvertMatrix4x3To4x4(view, gstate.viewMatrix);
|
|
|
|
Matrix4ByMatrix4(worldview, world, view);
|
|
|
|
Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix);
|
|
|
|
PlanesFromMatrix(worldviewproj, planes);
|
|
|
|
for (int plane = 0; plane < 6; plane++) {
|
|
|
|
int inside = 0;
|
|
|
|
int out = 0;
|
|
|
|
for (int i = 0; i < vertexCount; i++) {
|
|
|
|
// Here we can test against the frustum planes!
|
|
|
|
float value = planes[plane].Test(verts + i * 3);
|
|
|
|
if (value < 0)
|
|
|
|
out++;
|
|
|
|
else
|
|
|
|
inside++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inside == 0) {
|
|
|
|
// All out
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Any out. For testing that the planes are in the right locations.
|
|
|
|
// if (out != 0) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|