From 920fe2e74b62142ae899920b15068bb452361715 Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Sun, 31 Jul 2022 13:40:30 +0100 Subject: [PATCH] fix error in config import --- demo/data/redbook/debug_frag.glsl | 16 ++++ demo/data/redbook/debug_vert.glsl | 24 +++++ demo/data/redbook/lighting_frag.glsl | 2 - demo/data/redbook/lighting_vert.glsl | 11 ++- demo/data/rollball.yml | 10 +- demo/data/topdown.yml | 10 +- demo/demo/topdown.cpp | 2 +- fggl/gfx/ogl/renderer.cpp | 2 + fggl/gfx/ogl4/models.cpp | 39 +++----- fggl/gfx/ogl4/module.cpp | 14 ++- fggl/platform/linux/paths.cpp | 4 +- include/fggl/debug/impl/logging_std20.hpp | 30 +++--- include/fggl/entity/loader/serialise.hpp | 42 +++++++- include/fggl/modules/module.hpp | 1 + integrations/bullet/CMakeLists.txt | 1 + .../include/fggl/phys/bullet/bullet.hpp | 42 +------- .../include/fggl/phys/bullet/module.hpp | 51 ++++++++++ integrations/bullet/src/module.cpp | 95 +++++++++++++++++++ 18 files changed, 286 insertions(+), 110 deletions(-) create mode 100644 demo/data/redbook/debug_frag.glsl create mode 100644 demo/data/redbook/debug_vert.glsl create mode 100644 integrations/bullet/include/fggl/phys/bullet/module.hpp create mode 100644 integrations/bullet/src/module.cpp diff --git a/demo/data/redbook/debug_frag.glsl b/demo/data/redbook/debug_frag.glsl new file mode 100644 index 0000000..04ed267 --- /dev/null +++ b/demo/data/redbook/debug_frag.glsl @@ -0,0 +1,16 @@ +/** + * OpenGL RedBook Shader. + * Examples 7.8, 7.9 and 7.10. + */ +#version 330 core + +in vec4 Position; +in vec3 Normal; +in vec4 Colour; + +out vec4 FragColour; + +void main() { + vec3 normalScale = 0.5 + (Normal / 2); + FragColour = vec4(normalScale, 1); +} \ No newline at end of file diff --git a/demo/data/redbook/debug_vert.glsl b/demo/data/redbook/debug_vert.glsl new file mode 100644 index 0000000..02d3cd9 --- /dev/null +++ b/demo/data/redbook/debug_vert.glsl @@ -0,0 +1,24 @@ +/** + * OpenGL RedBook Shader. + * Example 7.8 + */ +#version 330 core + +layout (location = 0) in vec3 VertexPosition; +layout (location = 1) in vec3 VertexNormal; +layout (location = 2) in vec3 VertexColour; + +uniform mat4 MVPMatrix; +uniform mat4 MVMatrix; +uniform mat3 NormalMatrix; + +out vec4 Position; +out vec3 Normal; +out vec4 Colour; + +void main() { + Colour = vec4(0.5, 0.5, 0.5, 1.0f); + Normal = NormalMatrix * VertexNormal; + Position = MVMatrix * vec4(VertexPosition, 1); + gl_Position = MVPMatrix * vec4(VertexPosition, 1); +} \ No newline at end of file diff --git a/demo/data/redbook/lighting_frag.glsl b/demo/data/redbook/lighting_frag.glsl index 78242e7..cd417d9 100644 --- a/demo/data/redbook/lighting_frag.glsl +++ b/demo/data/redbook/lighting_frag.glsl @@ -86,8 +86,6 @@ void main() { } float diffuse = max(0.0, dot(Normal, lightDirection)); - - if (diffuse == 0.0) specular = 0.0; else diff --git a/demo/data/redbook/lighting_vert.glsl b/demo/data/redbook/lighting_vert.glsl index 435d901..9085329 100644 --- a/demo/data/redbook/lighting_vert.glsl +++ b/demo/data/redbook/lighting_vert.glsl @@ -8,9 +8,9 @@ uniform mat4 MVPMatrix; uniform mat4 MVMatrix; uniform mat3 NormalMatrix; -in vec4 VertexPosition; -in vec3 VertexNormal; -in vec4 VertexColour; +layout (location = 0) in vec3 VertexPosition; +layout (location = 1) in vec3 VertexNormal; +layout (location = 2) in vec3 VertexColour; out vec4 Position; out vec3 Normal; @@ -20,7 +20,8 @@ out int matIndex; void main() { Colour = vec4(1.0, 1.0, 1.0, 1.0f); Normal = NormalMatrix * VertexNormal; - Position = MVMatrix * VertexPosition; - gl_Position = MVPMatrix * VertexPosition; + Position = MVMatrix * vec4(VertexPosition, 1.0); matIndex = 0; + + gl_Position = MVPMatrix * vec4(VertexPosition, 1.0); } \ No newline at end of file diff --git a/demo/data/rollball.yml b/demo/data/rollball.yml index d31c966..61598f8 100644 --- a/demo/data/rollball.yml +++ b/demo/data/rollball.yml @@ -4,7 +4,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: redbook/lighting + pipeline: redbook/debug shape: type: box scale: [1.0, 5.0, 41] @@ -23,7 +23,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: redbook/lighting + pipeline: redbook/debug shape: type: box scale: [39, 5, 1] @@ -41,7 +41,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: redbook/lighting + pipeline: redbook/debug shape: type: box # we don't (currently) support planes... scale: [39, 0.5, 39] @@ -59,7 +59,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: redbook/lighting + pipeline: redbook/debug shape: type: sphere gfx::material: @@ -75,7 +75,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: redbook/lighting + pipeline: redbook/debug shape: type: box gfx::material: diff --git a/demo/data/topdown.yml b/demo/data/topdown.yml index d6c6658..0b1c8c5 100644 --- a/demo/data/topdown.yml +++ b/demo/data/topdown.yml @@ -4,7 +4,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: phong + pipeline: redbook/debug shape: type: box scale: [1.0, 5.0, 41] @@ -23,7 +23,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: phong + pipeline: redbook/debug shape: type: box scale: [39, 5, 1] @@ -41,7 +41,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: phong + pipeline: redbook/debug shape: type: box # we don't (currently) support planes... scale: [39, 0.5, 39] @@ -59,7 +59,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: phong + pipeline: redbook/lighting shape: type: sphere gfx::material: @@ -75,7 +75,7 @@ prefabs: components: Transform: StaticMesh: - pipeline: phong + pipeline: redbook/lighting shape: type: box gfx::material: diff --git a/demo/demo/topdown.cpp b/demo/demo/topdown.cpp index 4316c2a..fb313b6 100644 --- a/demo/demo/topdown.cpp +++ b/demo/demo/topdown.cpp @@ -154,7 +154,7 @@ void TopDown::pick_object() { if ( hit != fggl::entity::INVALID) { //fggl::debug::log("hit: {}", hit); } else { - fggl::debug::log("no hit"); + fggl::debug::info("no hit"); } } diff --git a/fggl/gfx/ogl/renderer.cpp b/fggl/gfx/ogl/renderer.cpp index 722a232..8f38d34 100644 --- a/fggl/gfx/ogl/renderer.cpp +++ b/fggl/gfx/ogl/renderer.cpp @@ -168,8 +168,10 @@ namespace fggl::gfx { m_canvasPipeline = m_cache->get(ogl4::FALLBACK_CANVAS_PIPELINE); } + // FIXME this should not be hard-coded, it should be part of the scene loading process m_cache->load(ShaderFromName("phong")); m_cache->load(ShaderFromName("redbook/lighting")); + m_cache->load(ShaderFromName("redbook/debug")); // rendering helpers m_canvasRenderer = std::make_unique<ogl4::CanvasRenderer>(fonts); diff --git a/fggl/gfx/ogl4/models.cpp b/fggl/gfx/ogl4/models.cpp index 5a99963..c00e08f 100644 --- a/fggl/gfx/ogl4/models.cpp +++ b/fggl/gfx/ogl4/models.cpp @@ -36,9 +36,9 @@ namespace fggl::gfx::ogl4 { auto normalAttr = ogl::attribute<data::Vertex, math::vec3>(offsetof(data::Vertex, normal)); auto colAttr = ogl::attribute<data::Vertex, math::vec3>(offsetof(data::Vertex, colour)); - vao->setAttribute( *buff.get(), 0, posAttr ); - vao->setAttribute( *buff.get(), 1, normalAttr ); - vao->setAttribute( *buff.get(), 3, colAttr ); + vao->setAttribute( *buff, 0, posAttr ); + vao->setAttribute( *buff, 1, normalAttr ); + vao->setAttribute( *buff, 2, colAttr ); return buff; } @@ -118,14 +118,14 @@ namespace fggl::gfx::ogl4 { auto cameras = world.find<gfx::Camera>(); // if there are no cameras, we can't do anything... - if ( cameras.size() == 0) { + if ( cameras.empty() ) { spdlog::warn("asked to render static models, but there were no cameras"); return; } // perform a rendering pass for each camera (will usually only be one...) - for ( auto& cameraEnt : cameras ){ - //TODO should be cliping this to only visible objects + for ( const auto& cameraEnt : cameras ){ + //TODO should be clipping this to only visible objects // enable required OpenGL state glEnable( GL_CULL_FACE ); @@ -149,7 +149,7 @@ namespace fggl::gfx::ogl4 { for ( const auto& entity : renderables ){ // ensure that the model pipeline actually exists... - const StaticModel& model = world.get<StaticModel>(entity); + const auto& model = world.get<StaticModel>(entity); if ( model.pipeline == nullptr ) { spdlog::warn("shader was null, aborting render"); continue; @@ -168,15 +168,11 @@ namespace fggl::gfx::ogl4 { // set model transform const auto& transform = world.get<math::Transform>(entity); - if (shader->hasUniform("model")) { - shader->setUniformMtx(shader->uniform("model"), transform.model()); - } else { - shader->setUniformMtx(shader->uniform("MVPMatrix"), projectionMatrix * viewMatrix * transform.model()); - shader->setUniformMtx(shader->uniform("MVMatrix"), viewMatrix * transform.model()); - - auto normalMatrix = glm::mat3(glm::transpose(inverse(transform.model()))); - shader->setUniformMtx(shader->uniform("NormalMatrix"), normalMatrix); - } + shader->setUniformMtx(shader->uniform("MVPMatrix"), projectionMatrix * viewMatrix * transform.model() ); + shader->setUniformMtx(shader->uniform("MVMatrix"), viewMatrix * transform.model()); + + auto normalMatrix = glm::mat3(glm::transpose(inverse(transform.model()))); + shader->setUniformMtx(shader->uniform("NormalMatrix"), normalMatrix); // setup lighting mode if ( shader->hasUniform("lights[0].isEnabled") ) { @@ -215,12 +211,7 @@ namespace fggl::gfx::ogl4 { // material detection with fallback const auto& material = world.get<PhongMaterial>(entity); - if ( shader->hasUniform("material.ambient") ) { - shader->setUniformF(shader->uniform("material.ambient"), material.ambient); - shader->setUniformF(shader->uniform("material.diffuse"), material.diffuse); - shader->setUniformF(shader->uniform("material.specular"), material.specular); - shader->setUniformF(shader->uniform("material.shininess"), material.shininess); - } else { + if ( shader->hasUniform("materials[0].ambient") ) { shader->setUniformF(shader->uniform("materials[0].emission"), material.emission); shader->setUniformF(shader->uniform("materials[0].ambient"), material.ambient); shader->setUniformF(shader->uniform("materials[0].diffuse"), material.diffuse); @@ -236,12 +227,12 @@ namespace fggl::gfx::ogl4 { vao->bind(); model.vertexData->bind(); - if ( model.restartIndex != NO_RESTART_IDX) { glEnable(GL_PRIMITIVE_RESTART); glPrimitiveRestartIndex(model.restartIndex); } - auto elements = model.elements.get(); + + auto* elements = model.elements.get(); vao->drawElements( *elements, model.drawType, model.elementCount); if ( model.restartIndex != NO_RESTART_IDX) { glDisable(GL_PRIMITIVE_RESTART); diff --git a/fggl/gfx/ogl4/module.cpp b/fggl/gfx/ogl4/module.cpp index 4f44bf3..d0c2b33 100644 --- a/fggl/gfx/ogl4/module.cpp +++ b/fggl/gfx/ogl4/module.cpp @@ -31,15 +31,13 @@ namespace fggl::gfx { static void process_shape(const YAML::Node& node, data::Mesh& mesh) { auto transform = data::OFFSET_NONE; - if ( node["offset"] ) { - auto offset = node["offset"].as<math::vec3>(); - transform = glm::translate(transform, offset); - } - if ( node["scale"] ) { - auto offset = node["scale"].as<math::vec3>(); - transform = glm::scale(transform, offset); - } + auto offset = node["offset"].as<math::vec3>(math::VEC3_ZERO); + transform = glm::translate(transform, offset); + + auto scale = node["scale"].as<math::vec3>(math::VEC3_ONES); + transform = glm::scale(transform, scale); + debug::debug("scale: {}, {}, {}", scale.x, scale.y, scale.z); // now the shape itself auto type = node["type"].as<std::string>(); diff --git a/fggl/platform/linux/paths.cpp b/fggl/platform/linux/paths.cpp index d53cc7b..b1aba8c 100644 --- a/fggl/platform/linux/paths.cpp +++ b/fggl/platform/linux/paths.cpp @@ -83,7 +83,7 @@ namespace fggl::platform { // check system paths for ( const auto& path : paths.dataDirs ) { auto fullPath = path / relPath; - debug::log(debug::Level::debug, "Checking data path: {}, {}", fullPath.c_str(), std::filesystem::exists(fullPath)); + debug::trace("Checking data path: {}, exists: {}", fullPath.c_str(), std::filesystem::exists(fullPath)); if ( std::filesystem::exists(fullPath) ) { return fullPath; } @@ -92,7 +92,7 @@ namespace fggl::platform { // if debug mode, try CWD as well. auto debugPath = std::filesystem::current_path() / "data" / relPath; if ( std::filesystem::exists(debugPath) ) { - debug::log(debug::Level::debug, "Checking debug path: {}, {}", debugPath.c_str(), std::filesystem::exists(debugPath)); + debug::trace("Checking debug path: {}, exists: {}", debugPath.c_str(), std::filesystem::exists(debugPath)); return debugPath; } diff --git a/include/fggl/debug/impl/logging_std20.hpp b/include/fggl/debug/impl/logging_std20.hpp index 81e55bd..afc2a74 100644 --- a/include/fggl/debug/impl/logging_std20.hpp +++ b/include/fggl/debug/impl/logging_std20.hpp @@ -80,34 +80,36 @@ namespace fggl::debug { fmt::print(CERR_FMT, level_to_string(level), fmtStr); } - template<typename ...T> - void error(FmtType fmt, T &&...args) { - log( Level::error, fmt, args...); - } + // inlined, pre-set level versions of the log function above template<typename ...T> - void warning(FmtType fmt, T &&...args) { - log( Level::warning, fmt, args...); + inline void error(FmtType fmt, T &&...args) { + auto fmtStr = fmt::format(fmt::runtime(fmt), args...); + fmt::print(CERR_FMT, level_to_string(Level::error), fmtStr); } template<typename ...T> - void info(FmtType fmt, T &&...args) { - log( Level::info, fmt, args... ); + inline void warning(FmtType fmt, T &&...args) { + auto fmtStr = fmt::format(fmt::runtime(fmt), args...); + fmt::print(CERR_FMT, level_to_string(Level::warning), fmtStr); } template<typename ...T> - void log(FmtType fmt, T &&...args) { - log( Level::info, fmt, args...); + inline void info(FmtType fmt, T &&...args) { + auto fmtStr = fmt::format(fmt::runtime(fmt), args...); + fmt::print(CERR_FMT, level_to_string(Level::info), fmtStr); } template<typename ...T> - void debug(FmtType fmt, T &&...args) { - log( Level::debug, fmt, args...); + inline void debug(FmtType fmt, T &&...args) { + auto fmtStr = fmt::format(fmt::runtime(fmt), args...); + fmt::print(CERR_FMT, level_to_string(Level::debug), fmtStr); } template<typename ...T> - void trace(FmtType fmt, T &&...args) { - log( Level::trace, fmt, args...); + inline void trace(FmtType fmt, T &&...args) { + auto fmtStr = fmt::format(fmt::runtime(fmt), args...); + fmt::print(CERR_FMT, level_to_string(Level::trace), fmtStr); } } diff --git a/include/fggl/entity/loader/serialise.hpp b/include/fggl/entity/loader/serialise.hpp index 6650351..85783c4 100644 --- a/include/fggl/entity/loader/serialise.hpp +++ b/include/fggl/entity/loader/serialise.hpp @@ -23,6 +23,7 @@ #include "fggl/math/types.hpp" #include "fggl/data/model.hpp" +#include "fggl/phys/types.hpp" namespace YAML { @@ -42,8 +43,8 @@ namespace YAML { } rhs.x = node[0].as<float>(); - rhs.y = node[0].as<float>(); - rhs.z = node[0].as<float>(); + rhs.y = node[1].as<float>(); + rhs.z = node[2].as<float>(); return true; } }; @@ -63,7 +64,7 @@ namespace YAML { } rhs.x = node[0].as<float>(); - rhs.y = node[0].as<float>(); + rhs.y = node[1].as<float>(); return true; } }; @@ -92,6 +93,41 @@ namespace YAML { } }; + template<> + struct convert<fggl::phys::BodyType> { + static Node encode(const fggl::phys::BodyType& rhs) { + Node node; + if ( rhs == fggl::phys::BodyType::STATIC ) { + node = "static"; + } else if ( rhs == fggl::phys::BodyType::DYNAMIC ) { + node = "dynamic"; + } else if ( rhs == fggl::phys::BodyType::KINEMATIC ) { + node = "kinematic"; + } + return node; + } + + static bool decode(const Node& node, fggl::phys::BodyType& rhs) { + auto strVal = node.as<std::string>(); + if ( strVal == "static" ) { + rhs = fggl::phys::BodyType::STATIC; + return true; + } + + if ( strVal == "dynamic" ) { + rhs = fggl::phys::BodyType::DYNAMIC; + return true; + } + + if ( strVal == "kinematic" ) { + rhs = fggl::phys::BodyType::KINEMATIC; + return true; + } + + return false; + } + }; + template<> struct convert<fggl::util::GUID> { static Node encode(const fggl::util::GUID& rhs) { diff --git a/include/fggl/modules/module.hpp b/include/fggl/modules/module.hpp index 5ff0317..6fac536 100644 --- a/include/fggl/modules/module.hpp +++ b/include/fggl/modules/module.hpp @@ -24,6 +24,7 @@ #include <functional> #include <map> #include <memory> + #include "fggl/util/safety.hpp" namespace fggl::modules { diff --git a/integrations/bullet/CMakeLists.txt b/integrations/bullet/CMakeLists.txt index 30b2f8f..f128ed8 100644 --- a/integrations/bullet/CMakeLists.txt +++ b/integrations/bullet/CMakeLists.txt @@ -32,6 +32,7 @@ else() # bullet cpp files target_sources( fggl PRIVATE + src/module.cpp src/simulation.cpp src/phys_draw.cpp ) diff --git a/integrations/bullet/include/fggl/phys/bullet/bullet.hpp b/integrations/bullet/include/fggl/phys/bullet/bullet.hpp index a65250a..b0d2ba0 100644 --- a/integrations/bullet/include/fggl/phys/bullet/bullet.hpp +++ b/integrations/bullet/include/fggl/phys/bullet/bullet.hpp @@ -37,46 +37,6 @@ #include "fggl/phys/types.hpp" #include "fggl/phys/bullet/types.hpp" - -namespace fggl::phys::bullet { - - /** - * Bullet integration module. - * - * This provides the ability for FGGL to use bullet as a physics backened. Bullet is mature, stable physics - * engine which makes it suitable for most use cases. For use with FGGL there is a reasonable amount of copying - * back and forth to keep the two states in sync. - */ - /*struct BulletModule : ecs3::Module { - public: - BulletModule() = default; - - [[nodiscard]] - std::string name() const override { - return "phys::Bullet3"; - } - - void onLoad(ecs3::ModuleManager&, ecs3::TypeRegistry &types) override { - // dependencies - types.make<phys::CollisionCallbacks>(); - types.make<phys::CollisionCache>(); - - types.make<phys::RigidBody>(); - types.make<phys::Dynamics>(); - - // my types - types.make<phys::bullet::BulletBody>(); - } - - };*/ - -} // namespace fggl::phys::bullet - -namespace fggl::phys { - - // allows using fggl::phys::Bullet3 as the module name - //using Bullet3 = bullet::BulletModule; - -} // namespace fggl::phys +#include "fggl/phys/bullet/module.hpp" #endif //FGGL_PHYS_BULLET_BULLET_HPP diff --git a/integrations/bullet/include/fggl/phys/bullet/module.hpp b/integrations/bullet/include/fggl/phys/bullet/module.hpp new file mode 100644 index 0000000..7ef91f6 --- /dev/null +++ b/integrations/bullet/include/fggl/phys/bullet/module.hpp @@ -0,0 +1,51 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 31/07/22. +// + +#ifndef FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_MODULE_HPP +#define FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_MODULE_HPP + +#include "fggl/modules/module.hpp" +#include "fggl/entity/module.hpp" + +#include "fggl/phys/types.hpp" +#include "fggl/phys/bullet/types.hpp" + +namespace fggl::phys::bullet { + + constexpr modules::ModuleService BIND_BULLET = modules::make_service("bind_bullet"); + constexpr util::GUID CONFIG_PHYS_BODY = util::make_guid("phys::body"); + + struct Bullet { + constexpr static const char* name = "fggl::phys::bullet"; + constexpr static const std::array<modules::ModuleService, 1> provides = { + BIND_BULLET + }; + constexpr static const std::array<modules::ModuleService, 1> depends = { + entity::EntityFactory::service + }; + static const modules::ServiceFactory factory; + }; + +} // namespace fggl::phys::bullet + +namespace fggl::phys { + using Bullet3 = bullet::Bullet; + +} // namespace fggl::phys + +#endif //FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_MODULE_HPP diff --git a/integrations/bullet/src/module.cpp b/integrations/bullet/src/module.cpp new file mode 100644 index 0000000..da7d6d4 --- /dev/null +++ b/integrations/bullet/src/module.cpp @@ -0,0 +1,95 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 31/07/22. +// + +#include "fggl/phys/bullet/module.hpp" +#include "fggl/phys/bullet/motion.hpp" + +namespace fggl::phys::bullet { + + constexpr float UNIT_EXTENT = 0.5F; + + btCollisionShape* create_bullet_shape(const YAML::Node& node) { + auto type = node["type"].as<std::string>("MISSING"); + if ( type == "sphere" ) { + auto radius = node["radius"].as<float>(UNIT_EXTENT); + return new btSphereShape(radius); + } else if ( type == "box" ) { + auto extents = node["extents"].as<math::vec3>(math::vec3(UNIT_EXTENT)); + return new btBoxShape(btVector3(extents.x, extents.y, extents.z)); + } else { + debug::warning("unknown shape type: {}, assuming unit sphere", type); + return new btSphereShape(0.5F); + } + } + + void setup_body(BodyType type, btRigidBody& body) { + if ( type != BodyType::STATIC ) { + body.setRestitution(0.5F); + body.setRollingFriction(0.0F); + + // kinematic bodies cannot sleep + if (type == BodyType::KINEMATIC) { + auto flags = (body.getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + body.setCollisionFlags(flags); + body.setActivationState(DISABLE_DEACTIVATION); + } + } + } + + void add_bt_body(const entity::ComponentSpec& spec, entity::EntityManager& manager, const entity::EntityID& id) { + auto& body = manager.add<BulletBody>(id); + body.motion = new FgglMotionState(&manager, id); + + auto type = spec.get<BodyType>("type", BodyType::DYNAMIC); + auto mass = 0.0F; + + // non-static objects can have mass + if ( type != BodyType::STATIC ) { + mass = spec.get<float>("mass", 1.0F); + } + + // calculate inertia + btCollisionShape* shape = create_bullet_shape(spec.config["shape"]); + btVector3 inertia(0, 0, 0); + if ( type != BodyType::STATIC ) { + shape->calculateLocalInertia(mass, inertia); + } + + // construction information for the simulation + btRigidBody::btRigidBodyConstructionInfo constructionInfo { + mass, + body.motion, + shape, + inertia + }; + body.body = new btRigidBody(constructionInfo); + setup_body(type, *body.body); + + // add the body to the simulation + } + + bool bullet_factory(modules::ModuleService service, modules::Services& services) { + if ( service == BIND_BULLET ) { + auto* entityFactory = services.get<entity::EntityFactory>(); + entityFactory->bind(CONFIG_PHYS_BODY, add_bt_body); + } + return false; + } + const modules::ServiceFactory Bullet::factory = bullet_factory; + +} // namespace fggl::phys::bullet \ No newline at end of file -- GitLab