Lots of updates - lua, narrator, logic, models
This commit is contained in:
255
src/gamedata/EventTriggerModule.cpp
Normal file
255
src/gamedata/EventTriggerModule.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
#include <iostream>
|
||||
#include <OgreBullet.h>
|
||||
#include <OgreMeshManager.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "LuaData.h"
|
||||
#include "EventTriggerModule.h"
|
||||
|
||||
struct TriggerBody {
|
||||
btPairCachingGhostObject *mBody;
|
||||
btCylinderShape *shape;
|
||||
Ogre::SceneNode *mSceneNode;
|
||||
std::set<const btCollisionObject *> contactBodies;
|
||||
};
|
||||
struct DeepPenetrationContactResultCallback : public btManifoldResult {
|
||||
DeepPenetrationContactResultCallback(
|
||||
const btCollisionObjectWrapper *body0Wrap,
|
||||
const btCollisionObjectWrapper *body1Wrap)
|
||||
: btManifoldResult(body0Wrap, body1Wrap)
|
||||
, mPenetrationDistance(0)
|
||||
, mOtherIndex(0)
|
||||
{
|
||||
}
|
||||
float mPenetrationDistance;
|
||||
int mOtherIndex;
|
||||
btVector3 mNormal, mPoint;
|
||||
void reset()
|
||||
{
|
||||
mPenetrationDistance = 0.0f;
|
||||
}
|
||||
bool hasHit()
|
||||
{
|
||||
return mPenetrationDistance < 0.0f;
|
||||
}
|
||||
virtual void addContactPoint(const btVector3 &normalOnBInWorld,
|
||||
const btVector3 &pointInWorldOnB,
|
||||
btScalar depth)
|
||||
{
|
||||
#ifdef VDEBUG
|
||||
std::cout
|
||||
<< "contact: " << Ogre::Bullet::convert(pointInWorldOnB)
|
||||
<< " " << Ogre::Bullet::convert(normalOnBInWorld)
|
||||
<< "\n";
|
||||
#endif
|
||||
if (mPenetrationDistance > depth) { // Has penetration?
|
||||
|
||||
const bool isSwapped =
|
||||
m_manifoldPtr->getBody0() !=
|
||||
m_body0Wrap->getCollisionObject();
|
||||
mPenetrationDistance = depth;
|
||||
mOtherIndex = isSwapped ? m_index0 : m_index1;
|
||||
mPoint = isSwapped ? (pointInWorldOnB +
|
||||
(normalOnBInWorld * depth)) :
|
||||
pointInWorldOnB;
|
||||
|
||||
mNormal = isSwapped ? normalOnBInWorld * -1 :
|
||||
normalOnBInWorld;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<EventTriggerModule>();
|
||||
ecs.component<EventTriggerExit>();
|
||||
ecs.component<TriggerBody>().on_add([](flecs::entity e,
|
||||
TriggerBody &body) {
|
||||
bool kinematic = false;
|
||||
if (e.get<EventTrigger>().parent) {
|
||||
body.mSceneNode =
|
||||
e.get<EventTrigger>()
|
||||
.parent->createChildSceneNode(
|
||||
e.get<EventTrigger>().position,
|
||||
Ogre::Quaternion(0, 0, 0, 1));
|
||||
kinematic = true;
|
||||
} else {
|
||||
body.mSceneNode =
|
||||
ECS::get<EngineData>()
|
||||
.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode(
|
||||
e.get<EventTrigger>().position,
|
||||
Ogre::Quaternion(0, 0, 0, 1));
|
||||
}
|
||||
Ogre::MeshPtr mesh =
|
||||
Ogre::MeshManager::getSingleton().createManual(
|
||||
"trigger", "General");
|
||||
Ogre::Entity *ent =
|
||||
ECS::get<EngineData>().mScnMgr->createEntity(mesh);
|
||||
body.mSceneNode->attachObject(ent);
|
||||
body.mBody = new btPairCachingGhostObject();
|
||||
body.mBody->getWorldTransform().setOrigin(Ogre::Bullet::convert(
|
||||
body.mSceneNode->_getDerivedPosition()));
|
||||
float h = e.get<EventTrigger>().halfheight;
|
||||
float r = e.get<EventTrigger>().radius;
|
||||
Ogre::Vector3 position = e.get<EventTrigger>().position;
|
||||
body.shape = new btCylinderShape(btVector3(r, h, r));
|
||||
body.mBody->setCollisionShape(body.shape);
|
||||
int flags = body.mBody->getCollisionFlags();
|
||||
flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
|
||||
if (kinematic)
|
||||
flags |= btCollisionObject::CF_STATIC_OBJECT;
|
||||
body.mBody->setCollisionFlags(flags);
|
||||
ECS::get<EngineData>().mWorld->attachCollisionObject(
|
||||
body.mBody, ent, 16, 0x1);
|
||||
});
|
||||
ecs.component<EventTrigger>().on_set(
|
||||
[](flecs::entity e, EventTrigger &ev) {
|
||||
e.add<TriggerBody>();
|
||||
});
|
||||
ecs.system<const EngineData, const EventTrigger, TriggerBody>(
|
||||
"CheckCollisions")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const EventTrigger &evt, TriggerBody &body) {
|
||||
btDispatcher *dispatch =
|
||||
eng.mWorld->getBtWorld()->getDispatcher();
|
||||
btHashedOverlappingPairCache *cache =
|
||||
body.mBody->getOverlappingPairCache();
|
||||
int i;
|
||||
int count = cache->getNumOverlappingPairs();
|
||||
std::set<const btCollisionObject *> currentContactBodies;
|
||||
if (count > 0) {
|
||||
btManifoldArray contacts;
|
||||
btBroadphasePairArray &collisionPairs =
|
||||
cache->getOverlappingPairArray();
|
||||
for (i = 0; i < count; i++) {
|
||||
contacts.resize(0);
|
||||
if (collisionPairs[i].m_algorithm) {
|
||||
collisionPairs[i]
|
||||
.m_algorithm
|
||||
->getAllContactManifolds(
|
||||
contacts);
|
||||
OgreAssert(false,
|
||||
"Not implemented");
|
||||
} else {
|
||||
const btBroadphasePair *collisionPairPtr =
|
||||
eng.mWorld->getBtWorld()
|
||||
->getBroadphase()
|
||||
->getOverlappingPairCache()
|
||||
->findPair(
|
||||
collisionPairs[i]
|
||||
.m_pProxy0,
|
||||
collisionPairs[i]
|
||||
.m_pProxy1);
|
||||
if (collisionPairPtr) {
|
||||
const btBroadphasePair
|
||||
&collisionPair =
|
||||
*collisionPairPtr;
|
||||
const btCollisionObject *objA = static_cast<
|
||||
btCollisionObject
|
||||
*>(
|
||||
collisionPair
|
||||
.m_pProxy0
|
||||
->m_clientObject);
|
||||
const btCollisionObject *objB = static_cast<
|
||||
btCollisionObject
|
||||
*>(
|
||||
collisionPair
|
||||
.m_pProxy1
|
||||
->m_clientObject);
|
||||
const btCollisionObject
|
||||
*me,
|
||||
*other;
|
||||
if (objA ==
|
||||
static_cast<
|
||||
btCollisionObject
|
||||
*>(
|
||||
body.mBody)) {
|
||||
me = objA;
|
||||
other = objB;
|
||||
} else {
|
||||
me = objB;
|
||||
other = objA;
|
||||
}
|
||||
const btCollisionShape *my_shape =
|
||||
me->getCollisionShape();
|
||||
const btCollisionShape *other_shape =
|
||||
other->getCollisionShape();
|
||||
btCollisionObjectWrapper obA(
|
||||
NULL, my_shape,
|
||||
body.mBody,
|
||||
body.mBody
|
||||
->getWorldTransform(),
|
||||
-1, i);
|
||||
btCollisionObjectWrapper obB(
|
||||
NULL,
|
||||
other_shape,
|
||||
other,
|
||||
other->getWorldTransform(),
|
||||
-1, 0);
|
||||
btCollisionAlgorithm *algorithm =
|
||||
dispatch->findAlgorithm(
|
||||
&obA,
|
||||
&obB,
|
||||
NULL,
|
||||
BT_CONTACT_POINT_ALGORITHMS);
|
||||
DeepPenetrationContactResultCallback
|
||||
contactPointResult(
|
||||
&obA,
|
||||
&obB);
|
||||
|
||||
algorithm->processCollision(
|
||||
&obA, &obB,
|
||||
eng.mWorld
|
||||
->getBtWorld()
|
||||
->getDispatchInfo(),
|
||||
&contactPointResult);
|
||||
algorithm
|
||||
->~btCollisionAlgorithm();
|
||||
dispatch->freeCollisionAlgorithm(
|
||||
algorithm);
|
||||
if (contactPointResult
|
||||
.hasHit()) {
|
||||
currentContactBodies
|
||||
.insert(other);
|
||||
if (body.contactBodies
|
||||
.find(other) ==
|
||||
body.contactBodies
|
||||
.end()) {
|
||||
body.contactBodies
|
||||
.insert(other);
|
||||
ECS::get<
|
||||
LuaBase>()
|
||||
.mLua
|
||||
->call_handler(
|
||||
evt.event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::set<const btCollisionObject *>::iterator it =
|
||||
body.contactBodies.begin();
|
||||
while (it != body.contactBodies.end()) {
|
||||
if (currentContactBodies.find(*it) ==
|
||||
currentContactBodies.end()) {
|
||||
if (e.has<EventTriggerExit>()) {
|
||||
const Ogre::String &exit_event =
|
||||
ECS::get<
|
||||
EventTriggerExit>()
|
||||
.event;
|
||||
ECS::get<LuaBase>()
|
||||
.mLua->call_handler(
|
||||
exit_event);
|
||||
} else {
|
||||
std::cout << "body exited"
|
||||
<< std::endl;
|
||||
}
|
||||
body.contactBodies.erase(*it);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user