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 "./core_bbox_frustum.hpp"
#include "math/m4x4.hpp" #include "math/m4x4.hpp"
#include "math/plane.hpp" #include "math/plane.hpp"
#include <array>
namespace Tyra { namespace Tyra {
@@ -29,6 +30,7 @@ class CoreBBox {
explicit CoreBBox(CoreBBox** t_bboxes, const u32& count); explicit CoreBBox(CoreBBox** t_bboxes, const u32& count);
explicit CoreBBox(const std::vector<CoreBBox>& t_bboxes, explicit CoreBBox(const std::vector<CoreBBox>& t_bboxes,
const u32& startIndex, const u32& stopIndex); 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); 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()); } void print(const std::string& name) const { print(name.c_str()); }
std::string getPrint(const char* name = nullptr) const; 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 * @brief Check if bbox is in view frustum
* *
* @param frustumPlanes Available in * @param frustumPlanes Available in
* engine.renderer.core.renderer3D.frustumPlanes * engine.renderer.core.renderer3D.frustumPlanes
* @param model Model matrix * @param model Model matrix if you want to fix bbox by model matrix
* @param margins Optional margins
*/ */
CoreBBoxFrustum isInFrustum(const Plane* frustumPlanes, const M4x4& model, bool isInFrustum(const Plane* frustumPlanes, const M4x4& model) const;
const float* margins = nullptr) const; bool isInFrustum(const Plane* frustumPlanes) const;
private:
static std::array<Vec4, 8> frustumCheckVertices;
}; };
} // namespace Tyra } // namespace Tyra
@@ -24,9 +24,13 @@ class RenderBBox : public CoreBBox {
explicit RenderBBox(CoreBBox** t_bboxes, const u32& count); explicit RenderBBox(CoreBBox** t_bboxes, const u32& count);
explicit RenderBBox(const std::vector<CoreBBox>& t_bboxes, explicit RenderBBox(const std::vector<CoreBBox>& t_bboxes,
const u32& startIndex, const u32& stopIndex); const u32& startIndex, const u32& stopIndex);
explicit RenderBBox(const RenderBBox& t_bbox, const M4x4& t_matrix);
CoreBBoxFrustum clipIsInFrustum(const Plane* frustumPlanes, CoreBBoxFrustum clipFrustumCheck(const Plane* frustumPlanes,
const M4x4& model) const; const M4x4& model) const;
/** Get new transformed BBox by model matrix */
RenderBBox getTransformed(const M4x4& t_matrix) const;
}; };
} // namespace Tyra } // 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) : CoreBBox(t_bbox) { setData(); }
BBox::BBox(const BBox& t_bbox, const M4x4& t_matrix) { BBox::BBox(const BBox& t_bbox, const M4x4& t_matrix)
for (u32 i = 0; i < 8; i++) { : CoreBBox(t_bbox, t_matrix) {
vertices[i] = t_matrix * t_bbox.vertices[i];
}
setData(); setData();
} }
@@ -126,7 +126,7 @@ void DynPipCore::render(DynPipBag** bags, const u32& count) {
auto* bag = bags[i]; auto* bag = bags[i];
CoreBBox bbox(bag->verticesTo, bag->count); CoreBBox bbox(bag->verticesTo, bag->count);
if (bbox.isInFrustum(rendererCore->renderer3D.frustumPlanes.getAll(), if (bbox.frustumCheck(rendererCore->renderer3D.frustumPlanes.getAll(),
*bag->info->model) == *bag->info->model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) { CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
continue; continue;
@@ -65,7 +65,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
if (options->frustumCulling == PipelineFrustumCulling_Simple) { if (options->frustumCulling == PipelineFrustumCulling_Simple) {
auto* frameTo = mesh->frames[mesh->animation.getState().nextFrame]; auto* frameTo = mesh->frames[mesh->animation.getState().nextFrame];
if (frameTo->bbox->isInFrustum( if (frameTo->bbox->frustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), model) == rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) { CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
return; return;
@@ -117,7 +117,7 @@ void MinecraftPipeline::render(std::vector<McpipBlock*> blocks, Texture* t_tex,
CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const { CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const {
const auto* frustumPlanes = rendererCore->renderer3D.frustumPlanes.getAll(); 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, void MinecraftPipeline::cull(std::vector<McpipBlock*> blocks,
@@ -105,12 +105,14 @@ CoreBBoxFrustum StaPipBagPackager::checkFrustum(const StaPipBagPackage& pkg) {
if (pkg.size <= (maxVertCount / 3)) { // Is subpackage if (pkg.size <= (maxVertCount / 3)) { // Is subpackage
auto& bbox = renderBBox->getChildBBox1By3(pkg.indexOf1By3BBox); 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 } else { // Is package
const auto& indexOfPart = pkg.indexOf1By3BBox; const auto& indexOfPart = pkg.indexOf1By3BBox;
auto partSize = ceil(pkg.size / static_cast<float>(maxVertCount / 3)); auto partSize = ceil(pkg.size / static_cast<float>(maxVertCount / 3));
auto bbox = renderBBox->createChildBBox(indexOfPart, partSize); 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 else
renderBbox = bbox; renderBbox = bbox;
frustumCheck = renderBbox->getMainBBox()->clipIsInFrustum( frustumCheck = renderBbox->getMainBBox()->clipFrustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model); rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model);
if (frustumCheck == OUTSIDE_FRUSTUM) { if (frustumCheck == OUTSIDE_FRUSTUM) {
@@ -62,7 +62,7 @@ void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) {
if (options->frustumCulling == PipelineFrustumCulling_Simple) { if (options->frustumCulling == PipelineFrustumCulling_Simple) {
auto* frame = mesh->frame; auto* frame = mesh->frame;
if (frame->bbox->isInFrustum( if (frame->bbox->frustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), model) == rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) { CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
return; return;
+78 -5
View File
@@ -15,6 +15,8 @@
namespace Tyra { namespace Tyra {
std::array<Vec4, 8> CoreBBox::frustumCheckVertices;
CoreBBox::CoreBBox() { CoreBBox::CoreBBox() {
for (u32 i = 0; i < 8; i++) { for (u32 i = 0; i < 8; i++) {
vertices[i] = Vec4(0.0F, 0.0F, 0.0F, 1.0F); 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); 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) { CoreBBox::CoreBBox(const CoreBBox& t_bbox) {
for (auto i = 0; i < 8; i++) for (auto i = 0; i < 8; i++)
Vec4::copy(&vertices[i], t_bbox.vertices[i].xyzw); 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) { void CoreBBox::operator=(const CoreBBox& v) {
for (auto i = 0; i < 8; i++) Vec4::copy(&vertices[i], v.vertices[i].xyzw); 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; return bbox;
} }
CoreBBoxFrustum CoreBBox::isInFrustum(const Plane* frustumPlanes, CoreBBoxFrustum CoreBBox::frustumCheck(const Plane* frustumPlanes,
const M4x4& model, const M4x4& model,
const float* margins) const { const float* margins) const {
CoreBBoxFrustum result = IN_FRUSTUM; CoreBBoxFrustum result = IN_FRUSTUM;
Vec4 boxCalcTemp;
u8 boxIn = 0, boxOut = 0; u8 boxIn = 0, boxOut = 0;
s8 calculatedBboxVertexIndex = -1;
for (u8 i = 0; i < 6; i++) { for (u8 i = 0; i < 6; i++) {
const auto margin = margins == nullptr ? 0.0F : margins[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 ... // for each corner of the box do ...
// get out of the cycle as soon as a box as corners // get out of the cycle as soon as a box as corners
// both inside and out of the frustum // both inside and out of the frustum
for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) { for (s8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) {
boxCalcTemp = model * vertices[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) if (isOut)
boxOut++; boxOut++;
@@ -241,4 +257,61 @@ CoreBBoxFrustum CoreBBox::isInFrustum(const Plane* frustumPlanes,
return result; 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 } // namespace Tyra
@@ -29,6 +29,13 @@ RenderBBox::RenderBBox(Vec4* t_vertices, u32 count)
RenderBBox::RenderBBox(Vec4* t_vertices) : CoreBBox(t_vertices) {} 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. * @brief Frustum checker for renderer.
* Background: We want to really put as low as possible polys to clipper. * 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, * we are adding some margins, and checking again if it really needs clipping,
* because "Cull" renderer can handle easy clip cases and its faster. * because "Cull" renderer can handle easy clip cases and its faster.
*/ */
CoreBBoxFrustum RenderBBox::clipIsInFrustum(const Plane* frustumPlanes, CoreBBoxFrustum RenderBBox::clipFrustumCheck(const Plane* frustumPlanes,
const M4x4& model) const { const M4x4& model) const {
auto result = isInFrustum(frustumPlanes, model); auto result = frustumCheck(frustumPlanes, model);
if (result != PARTIALLY_IN_FRUSTUM) { if (result != PARTIALLY_IN_FRUSTUM) {
return result; return result;
@@ -56,7 +63,7 @@ CoreBBoxFrustum RenderBBox::clipIsInFrustum(const Plane* frustumPlanes,
guardBand[4] = -10.0F; // NEAR guardBand[4] = -10.0F; // NEAR
guardBand[5] = -10.0F; // FAR 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
} // namespace Tyra } // namespace Tyra
+13 -17
View File
@@ -39,12 +39,12 @@ Sprite* get2DPicture(Renderer* renderer);
void Tutorial01 ::init() { void Tutorial01 ::init() {
// Song // Song
engine->audio.load(FileUtils::fromCwd("mafikizolo-loot.wav")); engine->audio.song.load(FileUtils::fromCwd("mafikizolo-loot.wav"));
engine->audio.setSongLoop(true); engine->audio.song.inLoop = true;
engine->audio.setVolume(30); engine->audio.song.setVolume(30);
adpcmSample = engine->audio.load(FileUtils::fromCwd("walk.adpcm")); adpcmSample = engine->audio.adpcm.load(FileUtils::fromCwd("walk.adpcm"));
engine->audio.setVolume(80, 1); engine->audio.adpcm.setVolume(80, 1);
engine->renderer.setClearScreenColor(Color(64.0F, 64.0F, 64.0F)); engine->renderer.setClearScreenColor(Color(64.0F, 64.0F, 64.0F));
@@ -66,10 +66,7 @@ void Tutorial01 ::init() {
warriors[i]->translation.translateZ(-10.0F); warriors[i]->translation.translateZ(-10.0F);
warriors[i]->translation.rotateX(-1.5F); warriors[i]->translation.rotateX(-1.5F);
warriorTex->addLink(warriors[i]->materials[0]->id); warriorTex->addLink(warriors[i]->materials[0]->id);
warriors[i]->playAnimation(0, warriors[i]->frames.size() - 1); warriors[i]->animation.speed = getRandomFloat(0.1F, 0.9F);
warriors[i]->animState.currentFrame =
getRandomInt(0, warriors[i]->frames.size() - 1);
warriors[i]->setAnimSpeed(getRandomFloat(0.1F, 0.9F));
} }
staOptions = getStaPipOptions(); staOptions = getStaPipOptions();
@@ -147,8 +144,8 @@ void Tutorial01 ::loop() {
counter = 0; counter = 0;
} }
for (u8 i = 0; i < warriorsCount; i++) warriors[i]->animate(); for (u8 i = 0; i < warriorsCount; i++) warriors[i]->update();
cube->animate(); cube->update();
skybox->rotation.rotateY(0.02F); skybox->rotation.rotateY(0.02F);
@@ -176,7 +173,7 @@ void Tutorial01 ::loop() {
engine->renderer.renderer3D.usePipeline(&dynpip); engine->renderer.renderer3D.usePipeline(&dynpip);
{ {
dynpip.render(cube); // dynpip.render(cube);
Threading::switchThread(); Threading::switchThread();
for (u8 i = 0; i < warriorsCount; i++) { for (u8 i = 0; i < warriorsCount; i++) {
dynpip.render(warriors[i], dynOptions); dynpip.render(warriors[i], dynOptions);
@@ -236,8 +233,7 @@ DynamicMesh* getWarrior(Renderer* renderer) {
renderer->core.texture.repository.addByMesh(result, FileUtils::getCwd(), renderer->core.texture.repository.addByMesh(result, FileUtils::getCwd(),
"png"); "png");
result->playAnimation(0, result->frames.size() - 1); result->animation.speed = 0.15F;
result->setAnimSpeed(0.15F);
return result; return result;
} }
@@ -248,13 +244,13 @@ DynamicMesh* getCube(Renderer* renderer) {
options.animation.count = 2; options.animation.count = 2;
options.scale = 3.0F; options.scale = 3.0F;
auto* data = loader.load(FileUtils::fromCwd("untitled.obj"), options); auto* data = loader.load(FileUtils::fromCwd("untitled.obj"), options);
data->normalsEnabled = false;
data->textureCoordsEnabled = false;
auto* result = new DynamicMesh(*data); auto* result = new DynamicMesh(*data);
result->translation.translateZ(-30.0F); result->translation.translateZ(-30.0F);
delete data; delete data;
result->playAnimation(0, result->frames.size() - 1); result->animation.speed = 0.15F;
result->setAnimSpeed(0.15F);
return result; return result;
} }