/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
//
// Avoiding Obstacles v2
//
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
#include "CKAll.h"
CKObjectDeclaration *FillBehaviorAvoidingObstacles2Decl();
CKERROR CreateAvoidingObstacles2Proto(CKBehaviorPrototype **);
int AvoidingObstacles2(const CKBehaviorContext& behcontext);
CKObjectDeclaration *FillBehaviorAvoidingObstacles2Decl()
{
CKObjectDeclaration *od = CreateCKObjectDeclaration("Avoid Obstacles");
od->SetDescription("Modifies the 'Direction' input parameter to avoid obstacles.");
/* rem:
In: triggers the process
Loop In: triggers the next step in the process loop.
Loop Out: is activated when the needs to loop.
Direction: initial direction.
Referential: referential in which the direction is expressed.
Inertia: affects the variation of direction. Ranged from 0 to 1, a high inertia decreases the direction changes.
Influence Factor: determines the radius of the influence sphere of an obstacle : Radius = Influence Factor * Radius of Obstacle Bounding Sphere.
Keep On Floor: if this boolean is set to TRUE, the object will stay on the floor
New Direction : the direction modified by the proximity of obstacles.
*/
/* warning:
- Each 3D entity to be considered as obstacle should be added to the collision manager's list using 'Add Obstacle'.
- This building block doesn't prevent object to intersect from each other. It acts in best to avoid collisions with influence spheres.
*/
od->SetCategory("Collisions/Influence");
od->SetType( CKDLL_BEHAVIORPROTOTYPE);
od->SetGuid(CKGUID(0x39460907,0x30f329af));
od->SetAuthorGuid(VIRTOOLS_GUID);
od->SetAuthorName("Virtools");
od->SetVersion(0x00020000);
od->SetCreationFunction(CreateAvoidingObstacles2Proto);
od->SetCompatibleClassId(CKCID_3DENTITY);
od->NeedManager(COLLISION_MANAGER_GUID);
return od;
}
CKERROR CreateAvoidingObstacles2Proto(CKBehaviorPrototype **pproto)
{
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("Avoid Obstacles");
if(!proto) return CKERR_OUTOFMEMORY;
proto->DeclareInput("In");
proto->DeclareInput("Loop In");
proto->DeclareOutput("Loop Out");
proto->DeclareInParameter("Direction", CKPGUID_VECTOR,"0,0,1");
proto->DeclareInParameter("Referential", CKPGUID_3DENTITY);
proto->DeclareInParameter("Inertia", CKPGUID_FLOAT,"0.5");
proto->DeclareInParameter("Influence Factor", CKPGUID_FLOAT,"2");
proto->DeclareInParameter("Keep On Floor", CKPGUID_BOOL,"TRUE");
proto->DeclareOutParameter("New Direction", CKPGUID_VECTOR);
proto->SetFlags(CK_BEHAVIORPROTOTYPE_OBSOLETE);
//proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
proto->SetFunction(AvoidingObstacles2);
proto->SetBehaviorFlags(CKBEHAVIOR_TARGETABLE);
*pproto = proto;
return CK_OK;
}
int AvoidingObstacles2(const CKBehaviorContext& behcontext)
{
CKBehavior* beh = behcontext.Behavior;
// Set Input state
if ( beh->IsInputActive(0) )
beh->ActivateInput(0,FALSE);
else
beh->ActivateInput(1,FALSE);
CK3dEntity *Entity = (CK3dEntity *) beh->GetTarget();
if (!Entity) {
beh->ActivateOutput(0,TRUE);
return CKBR_OWNERERROR;
}
// Get Initial Direction
VxVector Direction;
beh->GetInputParameterValue(0,&Direction);
// Get Referential
CK3dEntity *Referential = (CK3dEntity *) beh->GetInputParameterObject(1);
if (Referential)
Referential->TransformVector(&Direction,&Direction);
Direction.Normalize();
// Get inertia
float Inertia=0.5f;
beh->GetInputParameterValue(2,&Inertia);
//Inertia = 0.7f + Inertia/10.0f;
// Get influence factor
float Factor=2.0f;
beh->GetInputParameterValue(3,&Factor);
// Keep on floor ?
BOOL KeepOnFloor = TRUE;
beh->GetInputParameterValue(4,&KeepOnFloor);
CKContext* ctx = behcontext.Context;
CKCollisionManager* cm = (CKCollisionManager*)ctx->GetManagerByGuid(COLLISION_MANAGER_GUID);
CKFloorManager* FloorManager = (CKFloorManager*)ctx->GetManagerByGuid(FLOOR_MANAGER_GUID);
if (KeepOnFloor)
{
const VxBbox& box = Entity->GetBoundingBox();
VxVector pos;
pos=(box.Max+box.Min)/2.0f;
pos.y=box.Min.y;
float distup,distdown;
CK3dEntity *eup,*edown;
CKFloorPoint fp;
if (FloorManager->GetNearestFloors(pos,&fp)) {
distup = fp.m_UpDistance;
distdown = fp.m_DownDistance;
eup = (CK3dEntity*)ctx->GetObject(fp.m_UpFloor);
edown = (CK3dEntity*)ctx->GetObject(fp.m_DownFloor);
Entity->GetPosition(&pos);
if (eup)
pos.y+=distup;
else
if (edown)
pos.y+=distdown;
Entity->SetPosition(&pos);
}
}
// Compute deviation generated by the Obstacles, store it in Deviation
CK3dEntity *Obstacle;
VxVector EntityCenter,ObstacleCenter,Deviation(0.0f,0.0f,0.0f),V;
Entity->GetBaryCenter(&EntityCenter);
float R,dist,amplitude,A=10.0f;
int ObstacleCount = cm->GetObstacleCount();
for (int i=0;iGetObstacle(i);
if (!Obstacle) {
beh->ActivateOutput(0,TRUE);
return CKBR_PARAMETERERROR;
}
Obstacle->GetBaryCenter(&ObstacleCenter);
R=Obstacle->GetRadius();
dist = Magnitude(ObstacleCenter-EntityCenter);
if (distInverseTransformVector(&Direction,&Direction);
Direction.Normalize();
beh->SetOutputParameterValue(0,&Direction);
beh->ActivateOutput(0,TRUE);
return CKBR_OK;
}