Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • gamedev/fggl
  • onuralpsezer/fggl
2 results
Show changes
Showing
with 1477 additions and 19 deletions
# bullet integration support
find_package( Bullet CONFIG )
if ( NOT Bullet_FOUND )
message(WARNING "Bullet not found - disabling bullet physics integration")
else()
message( STATUS "Bullet is poorly packaged, you might need to disable support for it" )
add_library(fgglbt STATIC)
if ( MSVC )
# see https://github.com/microsoft/vcpkg/issues/7877
target_link_libraries(fgglbt PUBLIC LinearMath Bullet3Common BulletDynamics BulletSoftBody BulletCollision BulletInverseDynamics)
else()
# FIXME: this shouldn't be necessary, for modern cmake, linking the libraries should be enough
target_compile_definitions(fgglbt PUBLIC ${BULLET_DEFINITIONS})
if ( BULLET_INCLUDE_DIRS STREQUAL "include/bullet" )
message( STATUS "Bullet include path is relative - hard-coding" )
# FIXME possible debian packing bug: path is relative in BulletConfig.cmake
# FIXME debian packaging bug: BulletConfig.cmake lists BulletInverseDynamics, but that's packaged in bullet-extras
target_include_directories(fgglbt PUBLIC ${BULLET_ROOT_DIR}/${BULLET_INCLUDE_DIRS})
else()
target_include_directories(fgglbt PUBLIC ${BULLET_INCLUDE_DIRS})
endif()
target_link_libraries(fgglbt PUBLIC ${BULLET_LIBRARIES})
endif()
target_link_libraries( fgglbt PUBLIC fggl )
target_include_directories( fgglbt
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# bullet cpp files
target_sources( fgglbt
PRIVATE
src/module.cpp
src/simulation.cpp
src/phys_draw.cpp
src/service.cpp
)
endif()
/*
* 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/>.
*/
/*
* 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 24/04/22.
//
#ifndef FGGL_PHYS_BULLET_BULLET_HPP
#define FGGL_PHYS_BULLET_BULLET_HPP
#define FGGL_MODULE_BULLET fggl::phys::Bullet3
#include "fggl/phys/types.hpp"
#include "fggl/phys/bullet/types.hpp"
#include "fggl/phys/bullet/module.hpp"
#endif //FGGL_PHYS_BULLET_BULLET_HPP
/*
* 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/service.hpp"
#include "fggl/phys/bullet/types.hpp"
namespace fggl::phys::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 = {
phys::PhysicsProvider::service
};
constexpr static const std::array<modules::ModuleService, 1> depends = {
entity::EntityFactory::service
};
static bool factory(modules::ModuleService name, modules::Services& serviceManager);
};
} // namespace fggl::phys::bullet
namespace fggl::phys {
using Bullet3 = bullet::Bullet;
} // namespace fggl::phys
#endif //FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_MODULE_HPP
/*
* 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/>.
*/
/*
* 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 11/06/22.
//
#ifndef FGGL_PHYS_BULLET_MOTION_HPP
#define FGGL_PHYS_BULLET_MOTION_HPP
#include "types.hpp"
#include "fggl/debug/logging.hpp"
namespace fggl::phys::bullet {
class FgglMotionState : public btMotionState {
public:
FgglMotionState(entity::EntityManager* world, entity::EntityID entity) : m_world(world), m_entity(entity) {
}
~FgglMotionState() override = default;
void getWorldTransform(btTransform& worldTrans) const override {
const auto* transform = m_world->tryGet<fggl::math::Transform>(m_entity);
if ( transform == nullptr ) {
debug::error("BT: attempted to get transform of entity without transform component.");
return;
}
worldTrans.setFromOpenGLMatrix(glm::value_ptr(transform->model()));
}
void setWorldTransform(const btTransform& worldTrans) override {
auto& transform = m_world->get<fggl::math::Transform>(m_entity);
// set position
auto btOrigin = worldTrans.getOrigin();
transform.origin( {btOrigin.x(), btOrigin.y(), btOrigin.z()} );
// set rotation
math::vec3 angles;
worldTrans.getRotation().getEulerZYX(angles.x, angles.y, angles.z);
transform.euler(angles);
}
private:
entity::EntityManager* m_world;
entity::EntityID m_entity;
};
} // namespace fggl::phys::bullet
#endif //FGGL_PHYS_BULLET_INTEGRATIONS_HPP
/*
* 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 30/05/22.
//
#ifndef FGGL_PHYS_BULLET_PHYS_DRAW_HPP
#define FGGL_PHYS_BULLET_PHYS_DRAW_HPP
# if WIN32
#include "bullet/LinearMath/btIDebugDraw.h"
# else
#include "LinearMath/btIDebugDraw.h"
# endif
#include "fggl/gfx/ogl/types.hpp"
#include <array>
#include <variant>
#include <vector>
namespace fggl::debug {
class BulletDebugDrawList : public btIDebugDraw {
public:
BulletDebugDrawList();
virtual ~BulletDebugDrawList() = default;
void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColour, const btVector3& toColour) override;
void drawLine(const btVector3& from, const btVector3& to, const btVector3& colour) override;
void drawSphere(const btVector3& p, btScalar radius, const btVector3& color) override;
void drawTriangle(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& color, btScalar alpha) override;
void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
void reportErrorWarning(const char* warningString) override;
void draw3dText(const btVector3& location, const char* textString) override;
inline void setDebugMode(int debugMode) override {
m_mode = debugMode;
}
inline int getDebugMode() const override {
return m_mode;
}
private:
int m_mode;
};
}
#endif //FGGL_PHYS_BULLET_PHYS_DRAW_HPP
/*
* 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 01/08/22.
//
#ifndef FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_BULLETSERVICE_H
#define FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_BULLETSERVICE_H
#include "fggl/phys/service.hpp"
namespace fggl::phys::bullet {
class BulletProvider : public phys::PhysicsProvider {
public:
PhysicsEngine* create(entity::EntityManager* entityManager, entity::EntityFactory* factory) override;
};
}
#endif //FGGL_INTEGRATIONS_BULLET_PHYS_BULLET_BULLETSERVICE_H
/*
* 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/>.
*/
/*
* 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 24/04/22.
//
#ifndef FGGL_PHYS_BULLET_TYPES_HPP
#define FGGL_PHYS_BULLET_TYPES_HPP
#include "fggl/phys/types.hpp"
#include "phys_draw.hpp"
#include <bullet/btBulletDynamicsCommon.h>
#include <bullet/btBulletCollisionCommon.h>
namespace fggl::phys::bullet {
struct BulletConfiguration {
btBroadphaseInterface* broadphase;
btCollisionConfiguration* collisionConfiguration;
btDispatcher* dispatcher;
btConstraintSolver* solver;
};
/**
* Bullet component.
*/
struct BulletBody {
constexpr static const char* name = "phys::bullet::body";
btMotionState* motion;
btRigidBody* body;
inline void release() {
delete motion;
delete body;
motion = nullptr;
body = nullptr;
}
};
/**
* Bullet physics engine implementation.
*
* This wraps the bullet physics world and provides the systems needed for integrating it into our ECS. The state
* is responsible for creating and manging this object.
*/
class BulletPhysicsEngine : public PhysicsEngine {
public:
explicit BulletPhysicsEngine(entity::EntityManager* world);
~BulletPhysicsEngine() override;
// copy is not allowed
BulletPhysicsEngine(const BulletPhysicsEngine&) = delete;
BulletPhysicsEngine& operator=(const BulletPhysicsEngine&) = delete;
// move is not allowed
BulletPhysicsEngine(BulletPhysicsEngine&&) = delete;
BulletPhysicsEngine& operator=(BulletPhysicsEngine&&) = delete;
void step() override;
void onEntityDeath(entity::EntityID entity);
std::vector<ContactPoint> scanCollisions(entity::EntityID entity) override;
entity::EntityID raycast(math::vec3 from, math::vec3 to) override;
std::vector<entity::EntityID> raycastAll(math::vec3 from, math::vec3 to) override;
std::vector<entity::EntityID> sweep(PhyShape& shape, math::Transform& from, math::Transform& to) override;
/**
* Add a rigid body to the physics world.
*
* The body should not currently be in the simulation. Physics position will be synced with the motion
* state prior to it being added to the simulation. This method should not need to be called manually, it
* is called when the entity is decoded.
*
* @param entity the entity the BulletBody is attached to.
* @param body the pre-configured bullet body.
*/
void addBody(entity::EntityID entity, BulletBody& body);
void setDebugDraw(bool enabled) override;
private:
entity::EntityManager* m_ecs;
BulletConfiguration m_config;
btDiscreteDynamicsWorld* m_world;
std::unique_ptr<debug::BulletDebugDrawList> m_debug;
ContactCache m_contactCache;
/**
* Force position and rotation in the ECS to match those from the physics world.
*
* As FGGL uses motion states, this should not be required. As it iterates all entities in a scene this is
* also a very expensive operation.
*/
void syncTransformToECS();
/**
* Deal with physics collisions
*/
void pollCollisions();
// bullet callback functions
void onCollisionCreate( ContactPoint point );
void onCollisionProcess( ContactPoint point );
void onCollisionDestroyed( ContactPoint point );
};
} // namespace fggl::phys::bullet
#endif //FGGL_PHYS_BULLET_TYPES_HPP
/*
* 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/service.hpp"
namespace fggl::phys::bullet {
bool Bullet::factory(modules::ModuleService service, modules::Services& services) {
if ( service == phys::PhysicsProvider::service ) {
services.bind<phys::PhysicsProvider, BulletProvider>();
}
return false;
}
} // namespace fggl::phys::bullet
\ No newline at end of file
/*
* 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/>.
*/
/*
* 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 30/05/22.
//
#include "../include/fggl/phys/bullet/phys_draw.hpp"
#include "fggl/debug/draw.hpp"
#include <iostream>
namespace fggl::debug {
using btdd = debug::BulletDebugDrawList;
void btdd::drawLine(const btVector3 &from,
const btVector3 &to,
const btVector3 &fromColour,
const btVector3 &toColour) {
dd::line(from, to, fromColour);
}
void btdd::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &colour) {
dd::line(from, to, colour);
}
void btdd::drawSphere(const btVector3 &p, btScalar radius, const btVector3 &color) {
dd::sphere(p, color, radius);
}
void btdd::drawTriangle(const btVector3 &a,
const btVector3 &b,
const btVector3 &c,
const btVector3 &color,
btScalar alpha) {
dd::line(a, b, color);
dd::line(b, c, color);
dd::line(c, a, color);
}
void btdd::drawContactPoint(const btVector3 &PointOnB,
const btVector3 &normalOnB,
btScalar distance,
int lifeTime,
const btVector3 &color) {
}
void btdd::reportErrorWarning(const char *warningString) {
std::cerr << warningString << std::endl;
}
void btdd::draw3dText(const btVector3 &location, const char *textString) {
dd::screenText(textString, location, dd::colors::Wheat);
}
BulletDebugDrawList::BulletDebugDrawList() : m_mode( DBG_DrawAabb ) {
}
}
\ No newline at end of file
/*
* 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 01/08/22.
//
#include "fggl/phys/bullet/service.hpp"
#include "fggl/phys/bullet/types.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
if ( type == BodyType::DYNAMIC ) {
manager.add<phys::Dynamics>(id);
}
}
PhysicsEngine* BulletProvider::create(entity::EntityManager* entityManager, entity::EntityFactory* factory) {
auto* engine = new BulletPhysicsEngine(entityManager);
// FIXME: this won't work across multiple scenes - reactive approach might be better...
factory->bind(util::make_guid("phys::Body"), add_bt_body, [engine](auto& manager, const auto& entity) {
debug::trace("adding entity {} to physics scene...", (uint64_t)entity);
auto& physComp = manager.template get<BulletBody>(entity);
engine->addBody(entity, physComp);
});
return engine;
}
} // namespace fggl::phys::bullet
\ No newline at end of file
/*
* 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/>.
*/
/*
* 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/>.
*/
#include "../include/fggl/phys/bullet/types.hpp"
#include "../include/fggl/phys/bullet/motion.hpp"
namespace fggl::phys::bullet {
inline btVector3 to_bullet(const math::vec3 fgglVec) {
return {fgglVec.x, fgglVec.y, fgglVec.z};
}
BulletPhysicsEngine::BulletPhysicsEngine(entity::EntityManager* world) : m_ecs(world), m_config(), m_world(nullptr), m_debug(nullptr) {
m_config.broadphase = new btDbvtBroadphase();
m_config.collisionConfiguration = new btDefaultCollisionConfiguration();
m_config.dispatcher = new btCollisionDispatcher(m_config.collisionConfiguration);
m_config.solver = new btSequentialImpulseConstraintSolver();
m_world = new btDiscreteDynamicsWorld(
m_config.dispatcher,
m_config.broadphase,
m_config.solver,
m_config.collisionConfiguration);
// callbacks (for handling bullet -> ecs)
// ensure we deal with ecs -> bullet changes
//m_ecs->addDeathListener( [this](auto entity) { this->onEntityDeath(entity);} );
}
void BulletPhysicsEngine::step() {
// this is now handled on creation
//checkForPhys();
auto dynamicEnts = m_ecs->find<phys::Dynamics, phys::bullet::BulletBody>();
for (auto& ent : dynamicEnts) {
auto& dynamicComp = m_ecs->get<phys::Dynamics>(ent);
auto& bulletProxy = m_ecs->get<phys::bullet::BulletBody>(ent);
const auto forceVec = dynamicComp.force;
if ( glm::length(forceVec) != 0.F ) {
bulletProxy.body->applyCentralForce({forceVec.x, forceVec.y, forceVec.z});
bulletProxy.body->activate();
dynamicComp.force = math::VEC3_ZERO;
}
}
m_world->stepSimulation(60.0F);
//syncToECS();
pollCollisions();
// if debug draw is enabled, trigger a draw call
if ( m_debug != nullptr ) {
m_world->debugDrawWorld();
}
}
void BulletPhysicsEngine::addBody(entity::EntityID /*entity*/, BulletBody &body) {
// ensure static objects are placed correctly by setting their transforms to the correct value
btTransform transform;
body.body->getMotionState()->getWorldTransform(transform);
body.body->setWorldTransform(transform);
m_world->addRigidBody(body.body);
}
void BulletPhysicsEngine::setDebugDraw(bool active) {
if ( active ) {
m_debug = std::make_unique<debug::BulletDebugDrawList>();
m_world->setDebugDrawer(m_debug.get());
m_debug->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
} else {
m_debug = nullptr;
}
}
void BulletPhysicsEngine::syncTransformToECS() {
const auto physEnts = m_ecs->find<math::Transform, BulletBody>();
for (const auto& ent : physEnts) {
auto& physBody = m_ecs->get<BulletBody>(ent);
// don't bother syncing things with motion states, it's not necessary
if ( physBody.motion != nullptr ) {
continue;
}
auto& transform = m_ecs->get<math::Transform>(ent);
if ( physBody.body->isKinematicObject() ) {
continue;
}
btTransform bTransform;
physBody.motion->getWorldTransform(bTransform);
// set calculate and set ecs position
auto& btPos = bTransform.getOrigin();
math::vec3 pos{btPos.x(), btPos.y(), btPos.z()};
transform.origin( pos );
// set the rotation
const auto& btRot = bTransform.getRotation();
math::vec3 rot;
btRot.getEulerZYX(rot.x, rot.y, rot.z);
transform.euler(rot);
}
}
BulletPhysicsEngine::~BulletPhysicsEngine() {
// clean up the rigid bodies
auto entRB = m_ecs->find<BulletBody>();
for (const auto& ent : entRB) {
auto& bulletBody = m_ecs->get<BulletBody>(ent);
if ( bulletBody.body != nullptr ) {
m_world->removeCollisionObject(bulletBody.body);
}
// release resources and delete
bulletBody.release();
}
// delete the world
delete m_world;
// cleanup the configuration object
delete m_config.solver;
delete m_config.broadphase;
delete m_config.dispatcher;
delete m_config.collisionConfiguration;
}
static void handleCollisionCallbacks(entity::EntityManager* world, entity::EntityID owner, entity::EntityID other) {
if ( !world->has<CollisionCallbacks>(owner) ) {
return;
}
auto* callbacks = world->tryGet<CollisionCallbacks>(owner);
auto* cache = world->tryGet<CollisionCache>(owner);
if ( cache != nullptr ) {
auto itr = cache->collisions.find(other);
if ( itr == cache->collisions.end() ) {
if ( callbacks->onEnter != nullptr ) {
callbacks->onEnter(owner, other);
}
cache->collisions.insert( other );
} else {
if ( callbacks->onStay != nullptr ) {
callbacks->onStay(owner, other);
}
}
}
}
void BulletPhysicsEngine::pollCollisions() {
// flush collision caches
auto caches = m_ecs->find<CollisionCache>();
for( const auto& ent : caches) {
auto& cache = m_ecs->get<CollisionCache>(ent);
std::swap(cache.collisions, cache.lastFrame);
cache.collisions.clear();
}
// deal with the number of manifolds
const auto numManifolds = m_config.dispatcher->getNumManifolds();
for ( int i=0; i< numManifolds; ++i) {
auto* contactManifold = m_config.dispatcher->getManifoldByIndexInternal(i);
const auto* body0 = contactManifold->getBody0();
const auto* body1 = contactManifold->getBody1();
int numContacts = contactManifold->getNumContacts();
for ( auto contactIdx = 0; contactIdx < numContacts; ++contactIdx ) {
auto& point = contactManifold->getContactPoint(contactIdx);
if ( point.getDistance() < 0.0F ) {
auto worldPosA = point.getPositionWorldOnA();
auto worldPosB = point.getPositionWorldOnB();
auto normal = point.m_normalWorldOnB;
}
}
//handleCollisionCallbacks(m_ecs, body0->getUserIndex(), body1->getUserIndex());
//handleCollisionCallbacks(m_ecs, body1->getUserIndex(), body0->getUserIndex());
}
// note contacts that have ended
caches = m_ecs->find<CollisionCache>(); // re-fetch, entities can (and probably do) die in handlers.
for( const auto& ent : caches) {
auto& cache = m_ecs->get<CollisionCache>(ent);
// if we don't have an exit callback, it's pointless checking the cache
auto* callbacks = m_ecs->tryGet<CollisionCallbacks>(ent);
if ( callbacks == nullptr || callbacks->onExit == nullptr){
continue;
}
// check if a collision has ended
for (const auto& other : cache.lastFrame) {
auto itr = cache.collisions.find(other);
if (itr == cache.collisions.end()) {
callbacks->onExit( ent,other);
}
}
}
}
void BulletPhysicsEngine::onEntityDeath(entity::EntityID entity) {
auto* btPhysics = m_ecs->tryGet<BulletBody>(entity);
if ( btPhysics != nullptr) {
// decouple physics from entity
//btPhysics->body->setUserIndex( entity::INVALID );
m_world->removeRigidBody( btPhysics->body );
btPhysics->release();
}
}
void BulletPhysicsEngine::onCollisionCreate(ContactPoint point) {
m_contactCache.created.push_back(point);
}
void BulletPhysicsEngine::onCollisionProcess(ContactPoint point) {
m_contactCache.modified.push_back( point );
}
void BulletPhysicsEngine::onCollisionDestroyed(ContactPoint point) {
m_contactCache.removed.push_back(point);
}
entity::EntityID BulletPhysicsEngine::raycast(math::vec3 from, math::vec3 to) {
const auto btFrom = to_bullet(from);
const auto btTo = to_bullet(to);
btCollisionWorld::ClosestRayResultCallback rayTestResult(btFrom, btTo);
m_world->rayTest(btFrom, btTo, rayTestResult);
if ( !rayTestResult.hasHit() ) {
return entity::INVALID;
}
// tell the user what it hit
return entity::INVALID;
// return rayTestResult.m_collisionObject->getUserIndex();
}
std::vector<ContactPoint> BulletPhysicsEngine::scanCollisions(entity::EntityID entity) {
return std::vector<ContactPoint>();
}
std::vector<entity::EntityID> BulletPhysicsEngine::raycastAll(math::vec3 fromPos, math::vec3 toPos) {
const auto btFrom = to_bullet(fromPos);
const auto btTo = to_bullet(toPos);
btCollisionWorld::AllHitsRayResultCallback rayTestResult(btFrom, btTo);
m_world->rayTest(btFrom, btTo, rayTestResult);
// we didn't hit anything
if ( !rayTestResult.hasHit() ) {
return {};
}
// hit processing
const auto hits = rayTestResult.m_collisionObjects.size();
std::vector<entity::EntityID> hitVec;
hitVec.reserve(hits);
for ( auto i = 0; i < hits; ++i) {
auto entity = rayTestResult.m_collisionObjects[i]->getUserIndex();
//hitVec.push_back(entity);
}
return hitVec;
}
std::vector<entity::EntityID> BulletPhysicsEngine::sweep(PhyShape &shape,
math::Transform &from,
math::Transform &to) {
return std::vector<entity::EntityID>();
}
} // namespace fggl::phys::bullet
\ No newline at end of file
add_library(fggl-lua)
find_package(Lua REQUIRED)
target_link_libraries(fggl-lua PUBLIC ${LUA_LIBRARIES})
target_include_directories(fggl-lua INTERFACE ${LUA_INCLUDE_DIR})
# Link to FGGL
target_link_libraries(fggl-lua PUBLIC fggl)
# sources and include directories
target_sources(fggl-lua
PRIVATE
src/engine.cpp
src/module.cpp
)
target_include_directories(fggl-lua
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
$<INSTALL_INTERFACE:include>
)
/*
* 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 15/10/22.
//
#ifndef FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_ENGINE_HPP
#define FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_ENGINE_HPP
#include "fggl/script/engine.hpp"
#include "fggl/data/storage.hpp"
extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
};
namespace fggl::script::lua {
class LuaScriptEngine : public ScriptEngine {
public:
LuaScriptEngine(data::Storage* storage);
virtual ~LuaScriptEngine();
void onActivate() override;
void onDeactivate() override;
void onUpdate() override;
void onEvent(const std::string& name) override;
// running scripts
bool run(const char* script) override;
bool load(const char* filename) override;
// variables
void setGlobal(const char* name, void* ptr) override;
private:
data::Storage* m_storage;
lua_State* m_state;
void release();
};
class LuaScriptProvider : public ScriptProvider {
public:
LuaScriptProvider(data::Storage* storage);
virtual ~LuaScriptProvider() = default;
LuaScriptEngine* create() override;
private:
data::Storage* m_storage;
};
}
#endif //FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_ENGINE_HPP
/*
* 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 15/10/22.
//
#ifndef FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_MODULE_HPP
#define FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_MODULE_HPP
#define FGGL_HAS_LUA
#include "fggl/modules/module.hpp"
#include "fggl/entity/module.hpp"
#include "fggl/script/engine.hpp"
#include "fggl/data/module.hpp"
#include "fggl/assets/packed/adapter.hpp"
namespace fggl::script::lua {
constexpr auto MIME_LUA = assets::from_mime("text/lua");
constexpr auto SCRIPT_LUA = assets::make_asset_type("script/lua");
struct Lua {
constexpr static const char* name = "fggl::script::lua";
constexpr static const std::array<modules::ServiceName, 1> provides = {
script::ScriptProvider::service
};
constexpr static const std::array<modules::ServiceName, 2> depends = {
data::SERVICE_STORAGE,
assets::CheckinAdapted::service
};
static bool factory(modules::ServiceName name, modules::Services& serviceManager);
};
} // namespace fggl::script::lua
namespace fggl::script {
using Lua = lua::Lua;
} // namespace fggl::script
#endif //FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_MODULE_HPP
/*
* 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 15/10/22.
//
#include "fggl/script/lua/engine.hpp"
#include "fggl/debug/logging.hpp"
#include "fggl/scenes/game.hpp"
#include "fggl/entity/loader/loader.hpp"
#include <cassert>
extern "C" {
int lua_switch_scene(lua_State *L) {
auto *scene = lua_tostring(L, -1);
auto *statePtr = (fggl::AppState *) (lua_topointer(L, -2));
statePtr->owner().change_state(scene);
return 0;
}
int lua_create_entity(lua_State *L) {
/*auto *prototype = lua_tostring(L, -1);
auto *statePtr = (fggl::scenes::Game*) (lua_topointer(L, -2));
auto *factory = statePtr->owner().service<fggl::entity::EntityFactory>();
//factory->create( statePtr->world(), , [](){} );
*/
return 0;
}
static void open_lua_fggl(lua_State *L) {
// switch scene
lua_pushcfunction(L, lua_switch_scene);
lua_setglobal(L, "switch_scene");
}
}
namespace fggl::script::lua {
LuaScriptProvider::LuaScriptProvider(data::Storage *storage) : m_storage(storage) {
}
LuaScriptEngine *LuaScriptProvider::create() {
return new LuaScriptEngine(m_storage);
}
LuaScriptEngine::LuaScriptEngine(data::Storage* storage) : m_state(luaL_newstate()), m_storage(storage) {
luaL_openlibs(m_state);
open_lua_fggl(m_state);
}
LuaScriptEngine::~LuaScriptEngine() {
release();
}
void LuaScriptEngine::release() {
if ( m_state != nullptr ) {
lua_close(m_state);
m_state = nullptr;
}
}
void LuaScriptEngine::onActivate() {
lua_getglobal(m_state, "print");
lua_pushstring(m_state, "LUA activate triggered");
lua_call(m_state, 1, 0);
}
void LuaScriptEngine::onDeactivate() {
lua_getglobal(m_state, "print");
lua_pushstring(m_state, "LUA deactivate triggered");
lua_call(m_state, 1, 0);
}
void LuaScriptEngine::onUpdate() {
lua_getglobal(m_state, "print");
lua_pushstring(m_state, "LUA update triggered");
lua_call(m_state, 1, 0);
}
void LuaScriptEngine::onEvent(const std::string &name) {
lua_getglobal(m_state, "print");
lua_pushstring(m_state, "LUA event triggered");
lua_call(m_state, 1, 0);
}
bool LuaScriptEngine::run(const char *script) {
auto result = luaL_dostring(m_state, script);
if ( !result ) {
fggl::debug::warning("lua error: {}", lua_tostring(m_state, -1));
}
return result;
}
bool LuaScriptEngine::load(const char *filename) {
assert( filename != nullptr);
auto path = m_storage->resolvePath(data::StorageType::Data, filename);
if ( !std::filesystem::exists(path) ) {
fggl::debug::warning("lua error: file does not exist: {}", path.c_str());
return false;
}
// load the file ( OK = 0 = false because reasons...)
auto result = !luaL_dofile(m_state, path.c_str());
if ( !result ) {
fggl::debug::warning("lua error: {}", lua_tostring(m_state, -1));
return false;
}
return true;
}
void LuaScriptEngine::setGlobal(const char *name, void *ptr) {
lua_pushlightuserdata(m_state, ptr);
lua_setglobal(m_state, name);
}
}
\ No newline at end of file
/*
* 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 15/10/22.
//
#include "fggl/script/lua/module.hpp"
#include "fggl/script/lua/engine.hpp"
namespace fggl::script::lua {
static assets::AssetTypeID is_lua(std::filesystem::path path) {
if ( path.extension() == ".lua" ) {
return SCRIPT_LUA;
}
return assets::INVALID_ASSET_TYPE;
}
bool Lua::factory(modules::ServiceName service, modules::Services &serviceManager) {
if ( service == ScriptProvider::service ) {
auto *storageService = serviceManager.get<data::Storage>();
serviceManager.bind<ScriptProvider,LuaScriptProvider>(storageService);
auto *assetPacker = serviceManager.get<assets::CheckinAdapted>();
assetPacker->setLoader(MIME_LUA, assets::NEEDS_CHECKIN, is_lua);
return true;
}
return false;
}
}
\ No newline at end of file
find_package(Threads REQUIRED)
# GTest Dependency
find_package(GTest)
find_package( GTest REQUIRED )
if ( NOT GTest_FOUND )
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/release-1.11.0.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
message(NOTICE "GTest not found, installing...")
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/release-1.11.0.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
endif ()
add_subdirectory(testfggl)
enable_testing()
add_executable( fggl_test
# TestFggl.cpp
ecs/ecs.cpp
ecs3/ecs.cpp
math/types.cpp
ecs3/easing.cpp
# TestFggl.cpp
# ecs/ecs.cpp
# ecs3/ecs.cpp
# ecs3/easing.cpp
# math/types.cpp
util/guid.cpp
util/safety.cpp
)
target_include_directories(fggl_test
PUBLIC
......@@ -14,14 +16,10 @@ target_include_directories(fggl_test
target_link_libraries(fggl_test
fggl
gtest
gtest_main
gmock
)
include(GoogleTest)
gtest_discover_tests(fggl_test)
add_test(
NAME gtest
COMMAND $<TARGET_FILE:fggl_test>
)
/*
* 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 23/07/22.
//
#include <gtest/gtest.h>
#include "fggl/util/guid.hpp"
namespace {
// expect blank (0-width) strings to be the offset basis
TEST(UtilHash32, Empty) {
auto value = fggl::util::hash_fnv1a_32("");
EXPECT_EQ( fggl::util::FNV_OFFSET_BASIS_32, value );
}
TEST(UtilHash64, Empty) {
auto value = fggl::util::hash_fnv1a_64("");
EXPECT_EQ( fggl::util::FNV_OFFSET_BASIS_64, value );
}
// expect single characters to work correctly
TEST(UtilHash32, SingleChar) {
auto value = fggl::util::hash_fnv1a_32("a");
EXPECT_EQ( 0xe40c292c, value );
}
TEST(UtilHash64, SingleChar) {
auto value = fggl::util::hash_fnv1a_64("a");
EXPECT_EQ( 0xaf63dc4c8601ec8c, value );
}
// expect hello world to known values
TEST(UtilHash32, HelloWorld) {
auto value = fggl::util::hash_fnv1a_32("Hello World");
EXPECT_EQ( 0xb3902527, value );
}
TEST(UtilHash64, HelloWorld) {
auto value = fggl::util::hash_fnv1a_64("Hello World");
EXPECT_EQ( 0x3d58dee72d4e0c27, value );
}
// expect scoped (::) notation to work correctly
TEST(UtilHash32, Scoped) {
auto value = fggl::util::hash_fnv1a_32("fggl::test::scoped");
EXPECT_EQ( 0x27fd4589, value );
}
TEST(UtilHash64, Scoped) {
auto value = fggl::util::hash_fnv1a_64("fggl::test::scoped");
EXPECT_EQ( 0xd2929655f3b0cf49, value );
}
// sanity checks
TEST(UtilHash32, RepeatsAreEqual) {
auto value = fggl::util::hash_fnv1a_32("fggl::test::scoped");
auto value2 = fggl::util::hash_fnv1a_32("fggl::test::scoped");
EXPECT_EQ( value, value2 );
EXPECT_EQ( false, value < value2);
EXPECT_EQ( false, value2 < value);
}
TEST(UtilHash64, RepeatsAreEqual) {
auto value = fggl::util::hash_fnv1a_64("fggl::test::scoped");
auto value2 = fggl::util::hash_fnv1a_64("fggl::test::scoped");
EXPECT_EQ( value, value2 );
EXPECT_EQ( false, value < value2);
EXPECT_EQ( false, value2 < value);
}
// GUID tests
TEST(GuidTest, GuidSuffix) {
auto guid = fggl::util::make_guid("test");
auto guidSuffix = "test"_fid;
EXPECT_EQ(guid, guidSuffix);
EXPECT_EQ( false, guid < guidSuffix);
EXPECT_EQ( false, guidSuffix < guid);
}
TEST(GuidTest, OrderingLE) {
auto guid1 = fggl::util::GUID::make(0);
auto guid2 = fggl::util::GUID::make(1);
EXPECT_NE(guid1, guid2);
EXPECT_EQ( true, guid1 < guid2);
EXPECT_EQ( false, guid2 < guid1);
}
TEST(GuidTest, OrderingGE) {
auto guid1 = fggl::util::GUID::make(15);
auto guid2 = fggl::util::GUID::make(36);
EXPECT_NE(guid1, guid2);
EXPECT_EQ( true, guid1 < guid2);
EXPECT_EQ( false, guid2 < guid1);
}
#ifdef DEBUG
TEST(GuidTest, GuidToString) {
fggl::util::GUID guid = fggl::util::internString("test");
EXPECT_EQ("test", fggl::util::guidToString(guid));
}
#endif
}
/*
* 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 23/07/22.
//
#include <gtest/gtest.h>
#include "fggl/util/safety.hpp"
namespace {
using TestType = fggl::util::OpaqueName<unsigned int, struct TestTag>;
TEST(SafetyHandle, CheckZero) {
auto v1 = TestType::make(0);
auto v2 = TestType::make(0);
EXPECT_EQ(v1, v2);
}
TEST(SafetyHandle, CheckValue) {
auto v1 = TestType::make(0x12345678);
auto v2 = TestType::make(0x12345678);
EXPECT_EQ(v1, v2);
}
TEST(SafetyHandle, CheckValueNE) {
auto v1 = TestType::make(0x12345678);
auto v2 = TestType::make(0x87654321);
EXPECT_NE(v1, v2);
}
}
\ No newline at end of file