frustum check refactor
This commit is contained in:
@@ -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,
|
||||
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
|
||||
|
||||
@@ -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,7 +126,7 @@ 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(),
|
||||
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;
|
||||
|
||||
@@ -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,
|
||||
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,
|
||||
CoreBBoxFrustum RenderBBox::clipFrustumCheck(const Plane* frustumPlanes,
|
||||
const M4x4& model) const {
|
||||
auto result = isInFrustum(frustumPlanes, model);
|
||||
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
|
||||
|
||||
@@ -39,12 +39,12 @@ Sprite* get2DPicture(Renderer* renderer);
|
||||
|
||||
void Tutorial01 ::init() {
|
||||
// Song
|
||||
engine->audio.load(FileUtils::fromCwd("mafikizolo-loot.wav"));
|
||||
engine->audio.setSongLoop(true);
|
||||
engine->audio.setVolume(30);
|
||||
engine->audio.song.load(FileUtils::fromCwd("mafikizolo-loot.wav"));
|
||||
engine->audio.song.inLoop = true;
|
||||
engine->audio.song.setVolume(30);
|
||||
|
||||
adpcmSample = engine->audio.load(FileUtils::fromCwd("walk.adpcm"));
|
||||
engine->audio.setVolume(80, 1);
|
||||
adpcmSample = engine->audio.adpcm.load(FileUtils::fromCwd("walk.adpcm"));
|
||||
engine->audio.adpcm.setVolume(80, 1);
|
||||
|
||||
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.rotateX(-1.5F);
|
||||
warriorTex->addLink(warriors[i]->materials[0]->id);
|
||||
warriors[i]->playAnimation(0, warriors[i]->frames.size() - 1);
|
||||
warriors[i]->animState.currentFrame =
|
||||
getRandomInt(0, warriors[i]->frames.size() - 1);
|
||||
warriors[i]->setAnimSpeed(getRandomFloat(0.1F, 0.9F));
|
||||
warriors[i]->animation.speed = getRandomFloat(0.1F, 0.9F);
|
||||
}
|
||||
|
||||
staOptions = getStaPipOptions();
|
||||
@@ -147,8 +144,8 @@ void Tutorial01 ::loop() {
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
for (u8 i = 0; i < warriorsCount; i++) warriors[i]->animate();
|
||||
cube->animate();
|
||||
for (u8 i = 0; i < warriorsCount; i++) warriors[i]->update();
|
||||
cube->update();
|
||||
|
||||
skybox->rotation.rotateY(0.02F);
|
||||
|
||||
@@ -176,7 +173,7 @@ void Tutorial01 ::loop() {
|
||||
|
||||
engine->renderer.renderer3D.usePipeline(&dynpip);
|
||||
{
|
||||
dynpip.render(cube);
|
||||
// dynpip.render(cube);
|
||||
Threading::switchThread();
|
||||
for (u8 i = 0; i < warriorsCount; i++) {
|
||||
dynpip.render(warriors[i], dynOptions);
|
||||
@@ -236,8 +233,7 @@ DynamicMesh* getWarrior(Renderer* renderer) {
|
||||
renderer->core.texture.repository.addByMesh(result, FileUtils::getCwd(),
|
||||
"png");
|
||||
|
||||
result->playAnimation(0, result->frames.size() - 1);
|
||||
result->setAnimSpeed(0.15F);
|
||||
result->animation.speed = 0.15F;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -248,13 +244,13 @@ DynamicMesh* getCube(Renderer* renderer) {
|
||||
options.animation.count = 2;
|
||||
options.scale = 3.0F;
|
||||
auto* data = loader.load(FileUtils::fromCwd("untitled.obj"), options);
|
||||
|
||||
data->normalsEnabled = false;
|
||||
data->textureCoordsEnabled = false;
|
||||
auto* result = new DynamicMesh(*data);
|
||||
result->translation.translateZ(-30.0F);
|
||||
delete data;
|
||||
|
||||
result->playAnimation(0, result->frames.size() - 1);
|
||||
result->setAnimSpeed(0.15F);
|
||||
result->animation.speed = 0.15F;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user