Skip to content

Commit

Permalink
Merge pull request Revolutionary-Games#64 from Revolutionary-Games/62…
Browse files Browse the repository at this point in the history
…-Collision-functionality

Implementation of custom collision events.
  • Loading branch information
bkloster committed Nov 20, 2013
2 parents 0f2fc5f + c4c3169 commit 3b85f78
Show file tree
Hide file tree
Showing 17 changed files with 903 additions and 45 deletions.
11 changes: 9 additions & 2 deletions res/scripts/microbe_stage/microbe.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,15 @@ function Microbe.createMicrobeEntity(name)
rigidBody.properties.linearFactor = Vector3(1, 1, 0)
rigidBody.properties.angularFactor = Vector3(0, 0, 1)
rigidBody.properties:touch()

local reactionHandler = CollisionComponent()
reactionHandler:addCollisionGroup("microbe")

local components = {
AgentAbsorberComponent(),
OgreSceneNodeComponent(),
MicrobeComponent(),
reactionHandler,
rigidBody
}
for _, component in ipairs(components) do
Expand All @@ -93,6 +98,7 @@ Microbe.COMPONENTS = {
microbe = MicrobeComponent.TYPE_ID,
rigidBody = RigidBodyComponent.TYPE_ID,
sceneNode = OgreSceneNodeComponent.TYPE_ID,
collisionHandler = CollisionComponent.TYPE_ID
}


Expand Down Expand Up @@ -391,7 +397,8 @@ function MicrobeSystem:__init()
AgentAbsorberComponent,
MicrobeComponent,
OgreSceneNodeComponent,
RigidBodyComponent
RigidBodyComponent,
CollisionComponent
},
true
)
Expand All @@ -401,7 +408,7 @@ end

function MicrobeSystem:init(gameState)
System.init(self, gameState)
self.entities:init(gameState)
self.entities:init(gameState)
end


Expand Down
8 changes: 6 additions & 2 deletions res/scripts/microbe_stage/setup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ local function setupEmitter()
)
rigidBody.properties:touch()
entity:addComponent(rigidBody)
local reactionHandler = CollisionComponent()
reactionHandler:addCollisionGroup("emitter")
entity:addComponent(reactionHandler)
-- Scene node
local sceneNode = OgreSceneNodeComponent()
sceneNode.meshName = "molecule.mesh"
Expand Down Expand Up @@ -278,6 +281,7 @@ local function createMicrobeStage(name)
UpdatePhysicsSystem(),
RigidBodyOutputSystem(),
BulletToOgreSystem(),
CollisionSystem(),
-- Graphics
OgreAddSceneNodeSystem(),
OgreUpdateSceneNodeSystem(),
Expand All @@ -301,5 +305,5 @@ end

GameState.MICROBE = createMicrobeStage("microbe")
GameState.MICROBE_ALTERNATE = createMicrobeStage("microbe_alternate")

Engine:setCurrentGameState(GameState.MICROBE)
Engine:setCurrentGameState(GameState.MICROBE)
4 changes: 4 additions & 0 deletions src/bullet/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ add_sources(
${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h
${CMAKE_CURRENT_SOURCE_DIR}/update_physics_system.cpp
${CMAKE_CURRENT_SOURCE_DIR}/update_physics_system.h
${CMAKE_CURRENT_SOURCE_DIR}/collision_system.cpp
${CMAKE_CURRENT_SOURCE_DIR}/collision_system.h
${CMAKE_CURRENT_SOURCE_DIR}/collision_filter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/collision_filter.h
)

129 changes: 129 additions & 0 deletions src/bullet/collision_filter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include "collision_filter.h"
#include <luabind/iterator_policy.hpp>
#include "engine/game_state.h"
#include "scripting/luabind.h"



using namespace thrive;

struct CollisionFilter::Implementation {

Implementation(
const std::string& collisionGroup1,
const std::string& collisionGroup2
) : m_signature(collisionGroup1, collisionGroup2)
{
}

CollisionMap m_collisions;

Signature m_signature;

CollisionSystem* m_collisionSystem = nullptr;

};


luabind::scope
CollisionFilter::luaBindings() {
using namespace luabind;
return class_<CollisionFilter>("CollisionFilter")
.def(constructor<const std::string&, const std::string&>())
.def("init", &CollisionFilter::init)
.def("shutdown", &CollisionFilter::shutdown)
.def("collisions", &CollisionFilter::collisions, return_stl_iterator)
.def("clearCollisions", &CollisionFilter::clearCollisions)
;
}


CollisionFilter::CollisionFilter(
const std::string& collisionGroup1,
const std::string& collisionGroup2
) : m_impl(new Implementation(collisionGroup1, collisionGroup2))
{
}

CollisionFilter::~CollisionFilter(){}

void
CollisionFilter::init(
GameState* gameState
) {
m_impl->m_collisionSystem = gameState->findSystem<CollisionSystem>();
m_impl->m_collisionSystem->registerCollisionFilter(*this);
}

void
CollisionFilter::shutdown() {
m_impl->m_collisionSystem->unregisterCollisionFilter(*this);
m_impl->m_collisionSystem = nullptr;
}

const CollisionFilter::CollisionIterator
CollisionFilter::collisions() {
return m_impl->m_collisions | boost::adaptors::map_values;
}


void
CollisionFilter::addCollision(
Collision collision
) {
CollisionMap::iterator foundCollision = m_impl->m_collisions.find(CollisionId(collision.entityId1, collision.entityId2));
if (foundCollision != m_impl->m_collisions.end())
foundCollision->second.addedCollisionDuration += collision.addedCollisionDuration; //Add collision time.
else
{
CollisionId key(collision.entityId1, collision.entityId2);
m_impl->m_collisions.emplace(key, collision);
}

}


typename CollisionFilter::CollisionIterator::iterator
CollisionFilter::begin() const {
return (m_impl->m_collisions | boost::adaptors::map_values).begin();
}


typename CollisionFilter::CollisionIterator::iterator
CollisionFilter::end() const {
return (m_impl->m_collisions | boost::adaptors::map_values).end();
}


void
CollisionFilter::clearCollisions() {
m_impl->m_collisions.clear();
}


const CollisionFilter::Signature&
CollisionFilter::getCollisionSignature() const {
return m_impl->m_signature;
}


size_t
CollisionFilter::IdHash::operator() (
const CollisionId& collisionId
) const {
std::size_t hash1 = std::hash<EntityId>()(collisionId.first);
std::size_t hash2 = std::hash<EntityId>()(collisionId.second);
// Hash needs to be symmetric so that hash(entityId1, entityId2) == hash(entityId2, entityId1)
return hash1 ^ hash2;
}


bool
CollisionFilter::IdEquals::operator() (
const CollisionId& lhs,
const CollisionId& rhs
) const{
// Equality needs to be symmetric for collisions
return (lhs.first == rhs.first && lhs.second == rhs.second) ||
(lhs.first == rhs.second && lhs.second == rhs.first);
}
172 changes: 172 additions & 0 deletions src/bullet/collision_filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#pragma once

#include <boost/range/adaptor/map.hpp>

#include "bullet/collision_system.h"

#include <iostream>
#include <string>

#include <unordered_set>
#include <utility>


namespace luabind {
class scope;
}

namespace thrive {

class Collision;
class CollisionSystem;

/**
* @brief Filters for collisions that contain specific collision groups
*
* Collision filter makes it easy for systems and other peices of code to get easy
* access to the right collisions
*
*/

class CollisionFilter {

public:

using CollisionId = std::pair<EntityId, EntityId>;

using Signature = std::pair<std::string, std::string>;

struct IdHash {
std::size_t
operator() (
const CollisionId& collisionId
) const;
};

struct IdEquals {
bool
operator() (
const CollisionId& lhs,
const CollisionId& rhs
) const;
};

using CollisionMap = std::unordered_map<CollisionId, Collision, IdHash, IdEquals>;
using CollisionIterator = boost::range_detail::select_second_mutable_range<CollisionMap>;

/**
* @brief Constructor
*
* @param collisionGroup1
* The first collision group to monitor
*
* @param collisionGroup2
* The second collision group to monitor
*
*/
CollisionFilter(
const std::string& collisionGroup1,
const std::string& collisionGroup2
);

/**
* @brief Destructor
*/
~CollisionFilter();

/**
* @brief Initialized the collision filter
*
* @param gameState
* The gamestate the filter belongs in.
*/
void
init(
GameState* gameState
);

/**
* @brief Shuts down the filter.
*/
void
shutdown();

/**
* @brief Lua bindings
*
* Exposes the following \b constructors:
* - CollisionFilter(const std::string&, const std::string&)
* - CollisionFilter::init(GameState*)
* - CollisionFilter::shutdown()
* - CollisionFilter::collisions()
* - CollisionFilter::clearCollisions()
*/
static luabind::scope
luaBindings();

/**
* @brief Returns the collisions that has occoured
*
* Is only reset when clearCollisions() is called
*/
const CollisionIterator
collisions();

/**
* @brief Clears the collisions
*/
void
clearCollisions();

/**
* @brief Adds a collision
*
* @param collision
* Collision to add
*/
void
addCollision(Collision collision);

/**
* @brief Iterator
*
* Equivalent to
* \code
* collisions().cbegin()
* \endcode
*
* @return An iterator to the first collision
*/
typename CollisionIterator::iterator
begin() const;

/**
* @brief Iterator
*
* Equivalent to
* \code
* collisions().cend()
* \endcode
*
* @return An iterator to the end of the collisions
*/
typename CollisionIterator::iterator
end() const;

/**
* @brief Returns the signature of the collision filter
*
* @return
* A pair of the two collision group strings.
*/
const Signature&
getCollisionSignature() const;

private:

struct Implementation;
std::unique_ptr<Implementation> m_impl;

};

}
Loading

0 comments on commit 3b85f78

Please sign in to comment.