diff --git a/rawrbox.gltf/include/rawrbox/gltf/importer.hpp b/rawrbox.gltf/include/rawrbox/gltf/importer.hpp index 202f0606..6d2ffdbc 100644 --- a/rawrbox.gltf/include/rawrbox/gltf/importer.hpp +++ b/rawrbox.gltf/include/rawrbox/gltf/importer.hpp @@ -26,6 +26,8 @@ namespace rawrbox { const uint32_t IMPORT_ANIMATIONS = 1 << 3; const uint32_t IMPORT_BLEND_SHAPES = 1 << 4; + const uint32_t CALCULATE_BBOX = 1 << 5; + namespace Debug { const uint32_t PRINT_BONE_STRUCTURE = 1 << 10; const uint32_t PRINT_MATERIALS = 1 << 11; @@ -151,7 +153,6 @@ namespace rawrbox { struct GLTFMesh : public rawrbox::GLTFNode { public: rawrbox::BBOX bbox = {}; - std::vector primitives = {}; ozz::animation::Skeleton* skeleton = nullptr; diff --git a/rawrbox.gltf/src/importer.cpp b/rawrbox.gltf/src/importer.cpp index 528a91e1..b10299c5 100644 --- a/rawrbox.gltf/src/importer.cpp +++ b/rawrbox.gltf/src/importer.cpp @@ -740,6 +740,20 @@ namespace rawrbox { } } // ---------------- + + // BBOX CALCULATION -- + if ((this->loadFlags & rawrbox::ModelLoadFlags::CALCULATE_BBOX) > 0) { + gltfMesh->bbox.min = rawrbox::Vector3f(std::numeric_limits::max()); + gltfMesh->bbox.max = rawrbox::Vector3f(std::numeric_limits::min()); + + for (const auto& vertex : rawrPrimitive.vertices) { + gltfMesh->bbox.min = gltfMesh->bbox.min.min(vertex.position); + gltfMesh->bbox.max = gltfMesh->bbox.max.max(vertex.position); + } + + gltfMesh->bbox.size = gltfMesh->bbox.max - gltfMesh->bbox.min; + } + // ------------- } // ------------------- diff --git a/rawrbox.math/include/rawrbox/math/bbox.hpp b/rawrbox.math/include/rawrbox/math/bbox.hpp index 451c26e3..0e0f3dd3 100644 --- a/rawrbox.math/include/rawrbox/math/bbox.hpp +++ b/rawrbox.math/include/rawrbox/math/bbox.hpp @@ -37,15 +37,18 @@ namespace rawrbox { return pos.x >= this->min.x && pos.x <= this->max.x && pos.y >= this->min.y && pos.y <= this->max.y && pos.z >= this->min.z && pos.z <= this->max.z; } - void combine(const BBOX_t& b) { + void combine(const BBOXType& b) { this->min = {std::min(this->min.x, b.min.x), std::min(this->min.y, b.min.y), std::min(this->min.z, b.min.z)}; this->max = {std::max(this->max.x, b.max.x), std::max(this->max.y, b.max.y), std::max(this->max.z, b.max.z)}; this->size = this->min.abs() + this->max.abs(); } - bool operator==(const BBOX_t& other) const { return this->size == other.size; } - bool operator!=(const BBOX_t& other) const { return !operator==(other); } + bool operator==(const BBOXType& other) const { return this->size == other.size; } + bool operator!=(const BBOXType& other) const { return !operator==(other); } + + BBOXType operator*(NumberType other) const { return BBOXType(this->min * other, this->max * other, this->size * other); } + BBOXType operator*(const rawrbox::Vector3_t& other) const { return BBOXType(this->min * other, this->max * other, this->size * other); } }; using BBOXd = BBOX_t; diff --git a/rawrbox.math/tests/bbox.spec.cpp b/rawrbox.math/tests/bbox.spec.cpp index 35738619..3242e48c 100644 --- a/rawrbox.math/tests/bbox.spec.cpp +++ b/rawrbox.math/tests/bbox.spec.cpp @@ -52,7 +52,7 @@ TEST_CASE("BBOX should behave as expected", "[rawrbox::BBOX]") { REQUIRE(bbox1.max == rawrbox::Vector3f(2, 2, 2)); } - SECTION("rawrbox::BBOX::operators") { + SECTION("rawrbox::BBOX::operator==") { rawrbox::BBOX bbox1(rawrbox::Vector3f(0, 0, 0), rawrbox::Vector3f(1, 1, 1), rawrbox::Vector3f(1, 1, 1)); rawrbox::BBOX bbox2(rawrbox::Vector3f(0, 0, 0), rawrbox::Vector3f(1, 1, 1), rawrbox::Vector3f(1, 1, 1)); rawrbox::BBOX bbox3(rawrbox::Vector3f(0, 0, 0), rawrbox::Vector3f(2, 2, 2), rawrbox::Vector3f(2, 2, 2)); @@ -60,4 +60,13 @@ TEST_CASE("BBOX should behave as expected", "[rawrbox::BBOX]") { REQUIRE(bbox1 == bbox2); REQUIRE(bbox1 != bbox3); } + + SECTION("rawrbox::BBOX::operator*") { + rawrbox::BBOX bbox(rawrbox::Vector3f(0, 0, 0), rawrbox::Vector3f(1, 1, 1), rawrbox::Vector3f(1, 1, 1)); + rawrbox::BBOX scaledBbox = bbox * 2.0F; + + REQUIRE(scaledBbox.min == rawrbox::Vector3f(0, 0, 0)); + REQUIRE(scaledBbox.max == rawrbox::Vector3f(2, 2, 2)); + REQUIRE(scaledBbox.size == rawrbox::Vector3f(2, 2, 2)); + } } diff --git a/rawrbox.render/include/rawrbox/render/models/mesh.hpp b/rawrbox.render/include/rawrbox/render/models/mesh.hpp index 8b7d0b17..448e69ca 100644 --- a/rawrbox.render/include/rawrbox/render/models/mesh.hpp +++ b/rawrbox.render/include/rawrbox/render/models/mesh.hpp @@ -167,7 +167,7 @@ namespace rawrbox { [[nodiscard]] virtual const std::vector& getVertices() const { return this->vertices; } [[nodiscard]] virtual const std::vector& getIndices() const { return this->indices; } - [[nodiscard]] virtual const rawrbox::BBOX& getBBOX() const { return this->bbox; } + [[nodiscard]] virtual rawrbox::BBOX getBBOX() const { return this->bbox * this->_scale; } [[nodiscard]] virtual bool empty() const { return this->indices.empty() || this->vertices.empty(); diff --git a/rawrbox.render/include/rawrbox/render/models/model.hpp b/rawrbox.render/include/rawrbox/render/models/model.hpp index dfc33bf7..5ac28498 100644 --- a/rawrbox.render/include/rawrbox/render/models/model.hpp +++ b/rawrbox.render/include/rawrbox/render/models/model.hpp @@ -367,7 +367,7 @@ namespace rawrbox { this->updateLights(); } - [[nodiscard]] virtual const rawrbox::BBOX& getBBOX() const { return this->_bbox; } + [[nodiscard]] virtual rawrbox::BBOX getBBOX() { return this->_bbox * this->getScale(); } [[nodiscard]] virtual size_t totalMeshes() const { return this->_meshes.size(); } diff --git a/rawrbox.scripting/include/rawrbox/scripting/wrappers/math/bbox.hpp b/rawrbox.scripting/include/rawrbox/scripting/wrappers/math/bbox.hpp index 8e482a3e..c9a39a8e 100644 --- a/rawrbox.scripting/include/rawrbox/scripting/wrappers/math/bbox.hpp +++ b/rawrbox.scripting/include/rawrbox/scripting/wrappers/math/bbox.hpp @@ -9,6 +9,7 @@ namespace rawrbox { requires(std::is_integral_v || std::is_floating_point_v) static void registerTemplate(lua_State* L, const std::string& name) { using BBOXT = rawrbox::BBOX_t; + using VECT = rawrbox::Vector3_t; luabridge::getGlobalNamespace(L) .beginClass(name.c_str()) @@ -21,6 +22,10 @@ namespace rawrbox { .addFunction("isEmpty", &BBOXT::isEmpty) .addFunction("combine", &BBOXT::combine) + .addFunction("__mul", + luabridge::overload(&BBOXT::operator*), + luabridge::overload(&BBOXT::operator*)) + .addFunction("__eq", &BBOXT::operator==) .addFunction("__ne", &BBOXT::operator!=) diff --git a/samples/009-gltf/include/gltf/game.hpp b/samples/009-gltf/include/gltf/game.hpp index 9525ef69..3cac6970 100644 --- a/samples/009-gltf/include/gltf/game.hpp +++ b/samples/009-gltf/include/gltf/game.hpp @@ -21,6 +21,8 @@ namespace gltf { std::unique_ptr> _wolfLit; std::unique_ptr> _modelGrid; + std::unique_ptr> _bbox; + std::unique_ptr> _text; bool _ready = false; diff --git a/samples/009-gltf/src/game.cpp b/samples/009-gltf/src/game.cpp index 68bb81d6..a701c154 100644 --- a/samples/009-gltf/src/game.cpp +++ b/samples/009-gltf/src/game.cpp @@ -62,7 +62,7 @@ namespace gltf { void Game::loadContent() { std::vector> initialContentFiles = { {"./assets/models/ps1_phasmophobia/scene.glb", rawrbox::ModelLoadFlags::IMPORT_TEXTURES | rawrbox::ModelLoadFlags::IMPORT_LIGHT | rawrbox::ModelLoadFlags::Optimizer::MESH}, - {"./assets/models/shape_keys/shape_keys.glb", rawrbox::ModelLoadFlags::IMPORT_TEXTURES | rawrbox::ModelLoadFlags::IMPORT_BLEND_SHAPES | rawrbox::ModelLoadFlags::Debug::PRINT_BLENDSHAPES}, + {"./assets/models/shape_keys/shape_keys.glb", rawrbox::ModelLoadFlags::CALCULATE_BBOX | rawrbox::ModelLoadFlags::IMPORT_TEXTURES | rawrbox::ModelLoadFlags::IMPORT_BLEND_SHAPES | rawrbox::ModelLoadFlags::Debug::PRINT_BLENDSHAPES}, {"./assets/models/wolf/wolf.glb", rawrbox::ModelLoadFlags::IMPORT_TEXTURES | rawrbox::ModelLoadFlags::IMPORT_ANIMATIONS | rawrbox::ModelLoadFlags::Optimizer::SKELETON_ANIMATIONS | rawrbox::ModelLoadFlags::Debug::PRINT_ANIMATIONS}, {"./assets/models/anim_test.glb", rawrbox::ModelLoadFlags::IMPORT_ANIMATIONS}, {"./assets/models/grandma_tv/scene.gltf", rawrbox::ModelLoadFlags::IMPORT_TEXTURES | rawrbox::ModelLoadFlags::IMPORT_ANIMATIONS | rawrbox::ModelLoadFlags::Debug::PRINT_MATERIALS}}; @@ -77,6 +77,8 @@ namespace gltf { void Game::contentLoaded() { if (this->_ready) return; + this->_bbox = std::make_unique>(); + // PHASMO { auto* mdl = rawrbox::RESOURCES::getFile("./assets/models/ps1_phasmophobia/scene.glb")->get(); @@ -118,6 +120,8 @@ namespace gltf { this->_blendTest->setPos({-5, 0, 0}); this->_blendTest->upload(rawrbox::UploadType::FIXED_DYNAMIC); + + this->_bbox->addMesh(rawrbox::MeshUtils::generateBBOX({-5, 0, 0}, this->_blendTest->getBBOX())); } // ---------- @@ -184,6 +188,8 @@ namespace gltf { } // ---- + this->_bbox->upload(); + // LIGHT ---- rawrbox::LIGHTS::add(rawrbox::Vector3f{-1, 1.6F, -1.4F}, rawrbox::Colors::White() * 100, 1.6F); rawrbox::LIGHTS::add(rawrbox::Vector3f{-1, 0.6F, -1.4F}, rawrbox::Colors::White() * 100, 1.6F); @@ -224,6 +230,7 @@ namespace gltf { this->_text.reset(); this->_animTest.reset(); this->_phasmo.reset(); + this->_bbox.reset(); rawrbox::RESOURCES::shutdown(); } @@ -275,6 +282,8 @@ namespace gltf { // TEXT ---- if (this->_text != nullptr) this->_text->draw(); // ---- + + if (this->_bbox != nullptr) this->_bbox->draw(); } void Game::draw() {