frustum check refactor

This commit is contained in:
h4570
2022-08-18 09:51:13 +02:00
parent b9cde6346f
commit 1ba2cb55b7
12 changed files with 146 additions and 47 deletions
+24 -4
View File
@@ -15,6 +15,7 @@
#include "./core_bbox_frustum.hpp"
#include "math/m4x4.hpp"
#include "math/plane.hpp"
#include <array>
namespace Tyra {
@@ -29,6 +30,7 @@ class CoreBBox {
explicit CoreBBox(CoreBBox** t_bboxes, const u32& count);
explicit CoreBBox(const std::vector<CoreBBox>& t_bboxes,
const u32& startIndex, const u32& stopIndex);
explicit CoreBBox(const CoreBBox& t_bbox, const M4x4& t_matrix);
static CoreBBox create(const Vec4& center, const float& size);
@@ -55,16 +57,34 @@ class CoreBBox {
void print(const std::string& name) const { print(name.c_str()); }
std::string getPrint(const char* name = nullptr) const;
/** Get new transformed BBox by model matrix */
CoreBBox getTransformed(const M4x4& t_matrix) const;
/**
* @brief Check if bbox is in/partially/outside view frustum
*
* @param frustumPlanes Available in
* engine.renderer.core.renderer3D.frustumPlanes
* @param model Model matrix if you want to fix bbox by model matrix
* @param margins Optional margins
*/
CoreBBoxFrustum frustumCheck(const Plane* frustumPlanes, const M4x4& model,
const float* margins = nullptr) const;
CoreBBoxFrustum frustumCheck(const Plane* frustumPlanes,
const float* margins = nullptr) const;
/**
* @brief Check if bbox is in view frustum
*
* @param frustumPlanes Available in
* engine.renderer.core.renderer3D.frustumPlanes
* @param model Model matrix
* @param margins Optional margins
* @param model Model matrix if you want to fix bbox by model matrix
*/
CoreBBoxFrustum isInFrustum(const Plane* frustumPlanes, const M4x4& model,
const float* margins = nullptr) const;
bool isInFrustum(const Plane* frustumPlanes, const M4x4& model) const;
bool isInFrustum(const Plane* frustumPlanes) const;
private:
static std::array<Vec4, 8> frustumCheckVertices;
};
} // namespace Tyra
@@ -24,9 +24,13 @@ class RenderBBox : public CoreBBox {
explicit RenderBBox(CoreBBox** t_bboxes, const u32& count);
explicit RenderBBox(const std::vector<CoreBBox>& t_bboxes,
const u32& startIndex, const u32& stopIndex);
explicit RenderBBox(const RenderBBox& t_bbox, const M4x4& t_matrix);
CoreBBoxFrustum clipIsInFrustum(const Plane* frustumPlanes,
const M4x4& model) const;
CoreBBoxFrustum clipFrustumCheck(const Plane* frustumPlanes,
const M4x4& model) const;
/** Get new transformed BBox by model matrix */
RenderBBox getTransformed(const M4x4& t_matrix) const;
};
} // namespace Tyra
+2 -5
View File
@@ -27,11 +27,8 @@ BBox::BBox(Vec4* t_vertices, u32* faces, u32 count)
BBox::BBox(const BBox& t_bbox) : CoreBBox(t_bbox) { setData(); }
BBox::BBox(const BBox& t_bbox, const M4x4& t_matrix) {
for (u32 i = 0; i < 8; i++) {
vertices[i] = t_matrix * t_bbox.vertices[i];
}
BBox::BBox(const BBox& t_bbox, const M4x4& t_matrix)
: CoreBBox(t_bbox, t_matrix) {
setData();
}
@@ -126,8 +126,8 @@ void DynPipCore::render(DynPipBag** bags, const u32& count) {
auto* bag = bags[i];
CoreBBox bbox(bag->verticesTo, bag->count);
if (bbox.isInFrustum(rendererCore->renderer3D.frustumPlanes.getAll(),
*bag->info->model) ==
if (bbox.frustumCheck(rendererCore->renderer3D.frustumPlanes.getAll(),
*bag->info->model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
continue;
}
@@ -65,7 +65,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
if (options->frustumCulling == PipelineFrustumCulling_Simple) {
auto* frameTo = mesh->frames[mesh->animation.getState().nextFrame];
if (frameTo->bbox->isInFrustum(
if (frameTo->bbox->frustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
return;
@@ -117,7 +117,7 @@ void MinecraftPipeline::render(std::vector<McpipBlock*> blocks, Texture* t_tex,
CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const {
const auto* frustumPlanes = rendererCore->renderer3D.frustumPlanes.getAll();
return bbox->clipIsInFrustum(frustumPlanes, *block.model);
return bbox->clipFrustumCheck(frustumPlanes, *block.model);
}
void MinecraftPipeline::cull(std::vector<McpipBlock*> blocks,
@@ -105,12 +105,14 @@ CoreBBoxFrustum StaPipBagPackager::checkFrustum(const StaPipBagPackage& pkg) {
if (pkg.size <= (maxVertCount / 3)) { // Is subpackage
auto& bbox = renderBBox->getChildBBox1By3(pkg.indexOf1By3BBox);
return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model);
return bbox.clipFrustumCheck(frustumPlanes->getAll(),
*pkg.bag->info->model);
} else { // Is package
const auto& indexOfPart = pkg.indexOf1By3BBox;
auto partSize = ceil(pkg.size / static_cast<float>(maxVertCount / 3));
auto bbox = renderBBox->createChildBBox(indexOfPart, partSize);
return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model);
return bbox.clipFrustumCheck(frustumPlanes->getAll(),
*pkg.bag->info->model);
}
}
@@ -119,7 +119,7 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) {
else
renderBbox = bbox;
frustumCheck = renderBbox->getMainBBox()->clipIsInFrustum(
frustumCheck = renderBbox->getMainBBox()->clipFrustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model);
if (frustumCheck == OUTSIDE_FRUSTUM) {
@@ -62,7 +62,7 @@ void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) {
if (options->frustumCulling == PipelineFrustumCulling_Simple) {
auto* frame = mesh->frame;
if (frame->bbox->isInFrustum(
if (frame->bbox->frustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
return;
+80 -7
View File
@@ -15,6 +15,8 @@
namespace Tyra {
std::array<Vec4, 8> CoreBBox::frustumCheckVertices;
CoreBBox::CoreBBox() {
for (u32 i = 0; i < 8; i++) {
vertices[i] = Vec4(0.0F, 0.0F, 0.0F, 1.0F);
@@ -138,11 +140,21 @@ CoreBBox::CoreBBox(Vec4* t_vertices, u32 count) {
vertices[7].set(hiX, hiY, hiZ);
}
CoreBBox::CoreBBox(const CoreBBox& t_bbox, const M4x4& t_matrix) {
for (u32 i = 0; i < 8; i++) {
vertices[i] = t_matrix * t_bbox.vertices[i];
}
}
CoreBBox::CoreBBox(const CoreBBox& t_bbox) {
for (auto i = 0; i < 8; i++)
Vec4::copy(&vertices[i], t_bbox.vertices[i].xyzw);
}
CoreBBox CoreBBox::getTransformed(const M4x4& t_matrix) const {
return CoreBBox(*this, t_matrix);
}
void CoreBBox::operator=(const CoreBBox& v) {
for (auto i = 0; i < 8; i++) Vec4::copy(&vertices[i], v.vertices[i].xyzw);
}
@@ -206,12 +218,12 @@ CoreBBox CoreBBox::create(const Vec4& center, const float& size) {
return bbox;
}
CoreBBoxFrustum CoreBBox::isInFrustum(const Plane* frustumPlanes,
const M4x4& model,
const float* margins) const {
CoreBBoxFrustum CoreBBox::frustumCheck(const Plane* frustumPlanes,
const M4x4& model,
const float* margins) const {
CoreBBoxFrustum result = IN_FRUSTUM;
Vec4 boxCalcTemp;
u8 boxIn = 0, boxOut = 0;
s8 calculatedBboxVertexIndex = -1;
for (u8 i = 0; i < 6; i++) {
const auto margin = margins == nullptr ? 0.0F : margins[i];
@@ -221,10 +233,14 @@ CoreBBoxFrustum CoreBBox::isInFrustum(const Plane* frustumPlanes,
// for each corner of the box do ...
// get out of the cycle as soon as a box as corners
// both inside and out of the frustum
for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) {
boxCalcTemp = model * vertices[y];
for (s8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) {
if (y > calculatedBboxVertexIndex) {
frustumCheckVertices[y] = model * vertices[y];
calculatedBboxVertexIndex = y;
}
auto isOut = frustumPlanes[i].distanceTo(boxCalcTemp) <= margin;
auto isOut =
frustumPlanes[i].distanceTo(frustumCheckVertices[y]) <= margin;
if (isOut)
boxOut++;
@@ -241,4 +257,61 @@ CoreBBoxFrustum CoreBBox::isInFrustum(const Plane* frustumPlanes,
return result;
}
CoreBBoxFrustum CoreBBox::frustumCheck(const Plane* frustumPlanes,
const float* margins) const {
CoreBBoxFrustum result = IN_FRUSTUM;
u8 boxIn = 0, boxOut = 0;
for (u8 i = 0; i < 6; i++) {
const auto margin = margins == nullptr ? 0.0F : margins[i];
boxOut = 0;
boxIn = 0;
for (s8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) {
auto isOut = frustumPlanes[i].distanceTo(vertices[y]) <= margin;
if (isOut)
boxOut++;
else
boxIn++;
}
// if all corners are out
if (!boxIn)
return OUTSIDE_FRUSTUM;
else if (boxOut)
result = PARTIALLY_IN_FRUSTUM;
}
return result;
}
bool CoreBBox::isInFrustum(const Plane* frustumPlanes,
const M4x4& model) const {
s8 calculatedBboxVertexIndex = -1;
for (u8 i = 0; i < 6; i++) {
for (s8 y = 0; y < 8; y++) {
if (y > calculatedBboxVertexIndex) {
frustumCheckVertices[y] = model * vertices[y];
calculatedBboxVertexIndex = y;
}
auto isIn = frustumPlanes[i].distanceTo(frustumCheckVertices[y]) > 0.0F;
if (isIn) return true;
}
}
return false;
}
bool CoreBBox::isInFrustum(const Plane* frustumPlanes) const {
for (u8 i = 0; i < 6; i++) {
for (s8 y = 0; y < 8; y++) {
auto isIn = frustumPlanes[i].distanceTo(vertices[y]) > 0.0F;
if (isIn) return true;
}
}
return false;
}
} // namespace Tyra
@@ -29,6 +29,13 @@ RenderBBox::RenderBBox(Vec4* t_vertices, u32 count)
RenderBBox::RenderBBox(Vec4* t_vertices) : CoreBBox(t_vertices) {}
RenderBBox::RenderBBox(const RenderBBox& t_bbox, const M4x4& t_matrix)
: CoreBBox(t_bbox, t_matrix) {}
RenderBBox RenderBBox::getTransformed(const M4x4& t_matrix) const {
return RenderBBox(*this, t_matrix);
}
/**
* @brief Frustum checker for renderer.
* Background: We want to really put as low as possible polys to clipper.
@@ -36,9 +43,9 @@ RenderBBox::RenderBBox(Vec4* t_vertices) : CoreBBox(t_vertices) {}
* we are adding some margins, and checking again if it really needs clipping,
* because "Cull" renderer can handle easy clip cases and its faster.
*/
CoreBBoxFrustum RenderBBox::clipIsInFrustum(const Plane* frustumPlanes,
const M4x4& model) const {
auto result = isInFrustum(frustumPlanes, model);
CoreBBoxFrustum RenderBBox::clipFrustumCheck(const Plane* frustumPlanes,
const M4x4& model) const {
auto result = frustumCheck(frustumPlanes, model);
if (result != PARTIALLY_IN_FRUSTUM) {
return result;
@@ -56,7 +63,7 @@ CoreBBoxFrustum RenderBBox::clipIsInFrustum(const Plane* frustumPlanes,
guardBand[4] = -10.0F; // NEAR
guardBand[5] = -10.0F; // FAR
return isInFrustum(frustumPlanes, model, guardBand); // Let's check it again
return frustumCheck(frustumPlanes, model, guardBand); // Let's check it again
} // namespace Tyra
} // namespace Tyra