diff --git a/engine/inc/renderer/core/3d/bbox/core_bbox.hpp b/engine/inc/renderer/core/3d/bbox/core_bbox.hpp index a9d8445..26596a9 100644 --- a/engine/inc/renderer/core/3d/bbox/core_bbox.hpp +++ b/engine/inc/renderer/core/3d/bbox/core_bbox.hpp @@ -15,6 +15,7 @@ #include "./core_bbox_frustum.hpp" #include "math/m4x4.hpp" #include "math/plane.hpp" +#include namespace Tyra { @@ -29,6 +30,7 @@ class CoreBBox { explicit CoreBBox(CoreBBox** t_bboxes, const u32& count); explicit CoreBBox(const std::vector& 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 frustumCheckVertices; }; } // namespace Tyra diff --git a/engine/inc/renderer/core/3d/bbox/render_bbox.hpp b/engine/inc/renderer/core/3d/bbox/render_bbox.hpp index cbf0a0f..f7d3e1c 100644 --- a/engine/inc/renderer/core/3d/bbox/render_bbox.hpp +++ b/engine/inc/renderer/core/3d/bbox/render_bbox.hpp @@ -24,9 +24,13 @@ class RenderBBox : public CoreBBox { explicit RenderBBox(CoreBBox** t_bboxes, const u32& count); explicit RenderBBox(const std::vector& 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 diff --git a/engine/src/renderer/3d/bbox/bbox.cpp b/engine/src/renderer/3d/bbox/bbox.cpp index b96a38f..afb09c3 100644 --- a/engine/src/renderer/3d/bbox/bbox.cpp +++ b/engine/src/renderer/3d/bbox/bbox.cpp @@ -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(); } diff --git a/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp b/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp index c7c1835..05bfc02 100644 --- a/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp +++ b/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp @@ -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; } diff --git a/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp b/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp index 8163dcd..cdfd096 100644 --- a/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp @@ -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; diff --git a/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp b/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp index 8fbb9ae..994b34b 100644 --- a/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp @@ -117,7 +117,7 @@ void MinecraftPipeline::render(std::vector 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 blocks, diff --git a/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp b/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp index 20207d6..30cb8a5 100644 --- a/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp +++ b/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp @@ -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(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); } } diff --git a/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp b/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp index 5b10287..2115d48 100644 --- a/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp +++ b/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp @@ -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) { diff --git a/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp b/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp index 2efa033..d9ec05e 100644 --- a/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp @@ -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; diff --git a/engine/src/renderer/core/3d/bbox/core_bbox.cpp b/engine/src/renderer/core/3d/bbox/core_bbox.cpp index 126189d..7c17b78 100644 --- a/engine/src/renderer/core/3d/bbox/core_bbox.cpp +++ b/engine/src/renderer/core/3d/bbox/core_bbox.cpp @@ -15,6 +15,8 @@ namespace Tyra { +std::array 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 diff --git a/engine/src/renderer/core/3d/bbox/render_bbox.cpp b/engine/src/renderer/core/3d/bbox/render_bbox.cpp index da22fcc..3dd27b5 100644 --- a/engine/src/renderer/core/3d/bbox/render_bbox.cpp +++ b/engine/src/renderer/core/3d/bbox/render_bbox.cpp @@ -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 diff --git a/tutorials/01-hello/src/tutorial_01.cpp b/tutorials/01-hello/src/tutorial_01.cpp index 95ab27e..331c920 100644 --- a/tutorials/01-hello/src/tutorial_01.cpp +++ b/tutorials/01-hello/src/tutorial_01.cpp @@ -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; }