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.
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.
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.
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();
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.