Lots of updates - lua, narrator, logic, models

This commit is contained in:
2025-09-19 04:35:20 +03:00
parent 4249a0238b
commit 62e14cf075
19 changed files with 924 additions and 157 deletions

View 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++;
}
});
}