Nonstatic triggers

ebol

22-11-2007 13:24:17

Hi,

I'm trying to implement AI sensors to use them in obstacle avoidance for moving characters and I'm trying to use triggers for this.

I did some digging and reading, but still I have some problems.

1) Kinematic triggers don't fire up their events (onEnter, onLeave etc) - I'm using derived InheritedCallback class and pass it to trigger mTrigger->setCallback(this);

2) The same setup works with static triggers...

3) I found betajaen suggestion, that its better to use Intersections for this, but the problem is, that intersection works only with actors, and I need to avoid other characters in the scene too.

Has anyone got any suggestions? Am I missing something or doing something wrong, or this can't currently be done with triggers? I could use raycasting, but one ray probably wont be enough and I worry, that if all moving characters will cast a lots of rays in every movement step, the performance will seriously drop.

betajaen

22-11-2007 13:48:22

Perhaps I should add Characters to Intersections just like Triggers.

ebol

22-11-2007 13:56:54

Thats actually a good idea I think, could be useful, if its not too much work. Would appreciate it betajaen :)

For now, I'm experimenting with creating actor and setting it shape flag to NX_TRIGGER_ENABLE and using mMonster->mScene->getNxScene()->setUserTriggerReport(this);

What approach in your opinion would be better for this task?

betajaen

22-11-2007 14:16:23

You could write a CharacterIntersection class.

I'll do the hard work here. (it goes in NxOgreIntersection.h/.cpp).

class NxExport CharacterIntersection : public Characters, public NxUserEntityReport<NxShape*> {

public:

CharacterIntersection(Scene*, SimpleShape*, NxShapesType shapeFilter = NX_ALL_SHAPES);
~CharacterIntersection();

void setShape(SimpleShape*);
void intersect();
bool onEvent(NxU32, NxShape**);

protected:

Scene* mScene;
NxShapesType mShapeFilter;

private:

SimpleShape* mShape;
};


CharacterIntersection::CharacterIntersection(Scene* scene, NxOgre::SimpleShape* shape, NxShapesType shapeFilter)
: Actors(), mShape(shape), mShapeFilter(shapeFilter), mScene(scene)
{
intersect();
}

/////////////////////////////////////////////////////////////////////////////////////////

CharacterIntersection::~CharacterIntersection() {

if (mShape)
delete mShape;
}

/////////////////////////////////////////////////////////////////////////////////////////

void CharacterIntersection::setShape(SimpleShape* shape) {

if (mShape)
delete mShape;
mShape = shape;

}

/////////////////////////////////////////////////////////////////////////////////////////

void CharacterIntersection::intersect() {

if (mShape == 0)
return;

empty();

switch (mShape->getType()) {

case SimpleShape::SST_Box:
{
SimpleBox* shape = static_cast<SimpleBox*>(mShape);
NxBox box = NxBox(shape->getPose().t, shape->getDimensions(), shape->getPose().M);
mScene->getNxScene()->overlapOBBShapes(box, mShapeFilter, 0, NULL, this);
}
break;

case SimpleShape::SST_Sphere:
{
SimpleSphere* shape = static_cast<SimpleSphere*>(mShape);
NxSphere sphere = NxSphere(shape->getPose().t, shape->getRadius());
mScene->getNxScene()->overlapSphereShapes(sphere, mShapeFilter, 0, NULL, this);
}
break;

case SimpleShape::SST_Capsule:
{
// SimpleCapsule* shape = static_cast<SimpleCapsule*>(mShape);
// NxSphere sphere = NxCapsule(NxSegment(
// mScene->getNxScene()->overlapSphereShapes(sphere, mShapeFilter, 0, NULL, this);
}
break;

case SimpleShape::SST_Convex:
{
//
//
}
break;

}

}

/////////////////////////////////////////////////////////////////////////////////////////

bool CharacterIntersection::onEvent(NxU32 nbShapes, NxShape** shapes) {

for (NxU32 i = 0; i < nbShapes; i++) {

if (shapes[i]->getActor().userData == 0)
continue;

NxActorUserData* aud = static_cast< NxActorUserData* >(shapes[i]->getActor().userData);

if (aud->getType() == NxActorUserData::T_Character) {
Character* a = aud->toCharacter();
insert(a->getName(), a);
}
}

return true;
}



I haven't tested it, or even compiled but it's a good start.

ebol

22-11-2007 14:35:13

Thanks betajaen :) I'll add this to NxOgre and see how it works, I think I can take it from here.

One question thou, I see you created a new class CharacterIntersection, so I assume this will only report intersections with characters. So I should do intersection test twice - one to check if there are any actors and second test for characters, right? So then, If I'm interested in the nearest obstacle to avoid, I should check which one of top elements in both containers (actors and characters) is closer to the character that is performing the test. So if I'm right, it would be better to put this all in one intersection test, and report it similar to raycasting results.

betajaen

22-11-2007 14:38:42

Sadly how intersections are designed you can't combine Actors and Characters together. Actors and Characters both being typedefs for Container<Actor*> and Container<Character*> and an inherited class of Intersection.

So you'll have to do an intersection test twice.

ebol

22-11-2007 14:44:44

Ah, I get, it makes sense. Again, thanks!

betajaen

22-11-2007 14:52:52

I suppose I could just not inherit those classes but make them variables, but then I would have to do some clever workaround so I could do these:

Actor* a = intersection.begin();
Character* c = intersection.begin();

ebol

22-11-2007 15:00:26

About your code, I'll manage to compile it, but I had to do little changes in it, it was pure cosmetics, but I'll post it, maybe someone will want to use this too.

In constructor



CharacterIntersection::CharacterIntersection(Scene* scene, NxOgre::SimpleShape* shape, NxShapesType shapeFilter)
: Actors(), mShape(shape), mShapeFilter(shapeFilter), mScene(scene)
{
intersect();
}


changed Actors() to Characters()

and included NxOgreCharacters.h in the header file.

I haven't tested the code yet, but I'm about to do so.