added option for automatic facing in steering actuator

This commit is contained in:
Nick Samarin 2010-08-15 12:58:13 +00:00
parent 3a8f3dd3f5
commit b822f0bb7a
7 changed files with 163 additions and 13 deletions

@ -472,6 +472,8 @@ void init_actuator(bActuator *act)
sta->turnspeed = 120.f; sta->turnspeed = 120.f;
sta->dist = 1.f; sta->dist = 1.f;
sta->velocity= 3.f; sta->velocity= 3.f;
sta->flag = ACT_STEERING_AUTOMATICFACING;
sta->facingaxis = 1;
default: default:
; /* this is very severe... I cannot make any memory for this */ ; /* this is very severe... I cannot make any memory for this */
/* logic brick... */ /* logic brick... */

@ -4348,6 +4348,12 @@ static void draw_actuator_steering(uiLayout *layout, PointerRNA *ptr)
uiItemR(row, ptr, "acceleration", 0, NULL, 0); uiItemR(row, ptr, "acceleration", 0, NULL, 0);
uiItemR(row, ptr, "turnspeed", 0, NULL, 0); uiItemR(row, ptr, "turnspeed", 0, NULL, 0);
row = uiLayoutRow(layout, 0); row = uiLayoutRow(layout, 0);
uiItemR(row, ptr, "facing", 0, NULL, 0);
if (RNA_boolean_get(ptr, "facing"))
{
uiItemR(row, ptr, "facingaxis", 0, NULL, 0);
}
row = uiLayoutRow(layout, 0);
uiItemR(row, ptr, "selfterminated", 0, NULL, 0); uiItemR(row, ptr, "selfterminated", 0, NULL, 0);
if (RNA_enum_get(ptr, "mode")==ACT_STEERING_PATHFOLLOWING) if (RNA_enum_get(ptr, "mode")==ACT_STEERING_PATHFOLLOWING)
{ {

@ -224,8 +224,9 @@ typedef struct bArmatureActuator {
} bArmatureActuator; } bArmatureActuator;
typedef struct bSteeringActuator { typedef struct bSteeringActuator {
char pad[7]; char pad[5];
char flag; char flag;
short facingaxis;
int type; /* 0=seek, 1=flee, 2=path following */ int type; /* 0=seek, 1=flee, 2=path following */
float dist; float dist;
float velocity; float velocity;
@ -525,6 +526,7 @@ typedef struct bActuator {
/* steeringactuator->flag */ /* steeringactuator->flag */
#define ACT_STEERING_SELFTERMINATED 1 #define ACT_STEERING_SELFTERMINATED 1
#define ACT_STEERING_ENABLEVISUALIZATION 2 #define ACT_STEERING_ENABLEVISUALIZATION 2
#define ACT_STEERING_AUTOMATICFACING 4
#endif #endif

@ -1892,6 +1892,15 @@ static void rna_def_steering_actuator(BlenderRNA *brna)
{ACT_STEERING_PATHFOLLOWING, "PATHFOLLOWING", 0, "Path following", ""}, {ACT_STEERING_PATHFOLLOWING, "PATHFOLLOWING", 0, "Path following", ""},
{0, NULL, 0, NULL, NULL}}; {0, NULL, 0, NULL, NULL}};
static EnumPropertyItem facingaxis_items[] ={
{1, "X", 0, "X", ""},
{2, "Y", 0, "Y", ""},
{3, "Z", 0, "Z", ""},
{4, "-X", 0, "-X", ""},
{5, "-Y", 0, "-Y", ""},
{6, "-Z", 0, "-Z", ""},
{0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "SteeringActuator", "Actuator"); srna= RNA_def_struct(brna, "SteeringActuator", "Actuator");
RNA_def_struct_ui_text(srna, "Steering Actuator", ""); RNA_def_struct_ui_text(srna, "Steering Actuator", "");
RNA_def_struct_sdna_from(srna, "bSteeringActuator", "data"); RNA_def_struct_sdna_from(srna, "bSteeringActuator", "data");
@ -1956,6 +1965,18 @@ static void rna_def_steering_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "NavMesh Object", "Navigation mesh"); RNA_def_property_ui_text(prop, "NavMesh Object", "Navigation mesh");
RNA_def_property_pointer_funcs(prop, NULL, "rna_SteeringActuator_navmesh_set", NULL, NULL); RNA_def_property_pointer_funcs(prop, NULL, "rna_SteeringActuator_navmesh_set", NULL, NULL);
RNA_def_property_update(prop, NC_LOGIC, NULL); RNA_def_property_update(prop, NC_LOGIC, NULL);
prop= RNA_def_property(srna, "facing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_STEERING_AUTOMATICFACING);
RNA_def_property_ui_text(prop, "Facing", "Enable automatic facing");
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop= RNA_def_property(srna, "facingaxis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "facingaxis");
RNA_def_property_enum_items(prop, facingaxis_items);
RNA_def_property_ui_text(prop, "Axis", "Axis for automatic facing");
RNA_def_property_update(prop, NC_LOGIC, NULL);
} }
void RNA_def_actuator(BlenderRNA *brna) void RNA_def_actuator(BlenderRNA *brna)

@ -1059,11 +1059,12 @@ void BL_ConvertActuators(char* maggiename,
bool selfTerminated = (stAct->flag & ACT_STEERING_SELFTERMINATED) !=0; bool selfTerminated = (stAct->flag & ACT_STEERING_SELFTERMINATED) !=0;
bool enableVisualization = (stAct->flag & ACT_STEERING_ENABLEVISUALIZATION) !=0; bool enableVisualization = (stAct->flag & ACT_STEERING_ENABLEVISUALIZATION) !=0;
short facingMode = (stAct->flag & ACT_STEERING_AUTOMATICFACING) ? stAct->facingaxis : 0;
KX_SteeringActuator *tmpstact KX_SteeringActuator *tmpstact
= new KX_SteeringActuator(gameobj, mode, targetob, navmeshob,stAct->dist, = new KX_SteeringActuator(gameobj, mode, targetob, navmeshob,stAct->dist,
stAct->velocity, stAct->acceleration, stAct->turnspeed, stAct->velocity, stAct->acceleration, stAct->turnspeed,
selfTerminated, stAct->updateTime, selfTerminated, stAct->updateTime,
scene->GetObstacleSimulation(), enableVisualization); scene->GetObstacleSimulation(), facingMode, enableVisualization);
baseact = tmpstact; baseact = tmpstact;
break; break;
} }

@ -38,6 +38,7 @@
#include "KX_NavMeshObject.h" #include "KX_NavMeshObject.h"
#include "KX_ObstacleSimulation.h" #include "KX_ObstacleSimulation.h"
#include "KX_PythonInit.h" #include "KX_PythonInit.h"
#include "KX_PyMath.h"
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -55,6 +56,7 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
bool isSelfTerminated, bool isSelfTerminated,
int pathUpdatePeriod, int pathUpdatePeriod,
KX_ObstacleSimulation* simulation, KX_ObstacleSimulation* simulation,
short facingmode,
bool enableVisualization) : bool enableVisualization) :
SCA_IActuator(gameobj, KX_ACT_STEERING), SCA_IActuator(gameobj, KX_ACT_STEERING),
m_mode(mode), m_mode(mode),
@ -69,9 +71,11 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
m_isActive(false), m_isActive(false),
m_simulation(simulation), m_simulation(simulation),
m_enableVisualization(enableVisualization), m_enableVisualization(enableVisualization),
m_facingMode(facingmode),
m_obstacle(NULL), m_obstacle(NULL),
m_pathLen(0), m_pathLen(0),
m_wayPointIdx(-1) m_wayPointIdx(-1),
m_steerVec(MT_Vector3(0, 0, 0))
{ {
m_navmesh = static_cast<KX_NavMeshObject*>(navmesh); m_navmesh = static_cast<KX_NavMeshObject*>(navmesh);
if (m_navmesh) if (m_navmesh)
@ -81,6 +85,13 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
if (m_simulation) if (m_simulation)
m_obstacle = m_simulation->GetObstacle((KX_GameObject*)gameobj); m_obstacle = m_simulation->GetObstacle((KX_GameObject*)gameobj);
KX_GameObject* parent = ((KX_GameObject*)gameobj)->GetParent();
if (m_facingMode>0 && parent)
{
m_parentlocalmat = parent->GetSGNode()->GetLocalOrientation();
}
else
m_parentlocalmat.setIdentity();
} }
KX_SteeringActuator::~KX_SteeringActuator() KX_SteeringActuator::~KX_SteeringActuator()
@ -175,7 +186,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
MT_Vector3 vectotarg = targpos - mypos; MT_Vector3 vectotarg = targpos - mypos;
MT_Vector3 vectotarg2d = vectotarg; MT_Vector3 vectotarg2d = vectotarg;
vectotarg2d.z() = 0; vectotarg2d.z() = 0;
MT_Vector3 steervec = MT_Vector3(0, 0, 0); m_steerVec = MT_Vector3(0, 0, 0);
bool apply_steerforce = false; bool apply_steerforce = false;
bool terminate = true; bool terminate = true;
@ -184,8 +195,8 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
if (vectotarg2d.length2()>m_distance*m_distance) if (vectotarg2d.length2()>m_distance*m_distance)
{ {
terminate = false; terminate = false;
steervec = vectotarg; m_steerVec = vectotarg;
steervec.normalize(); m_steerVec.normalize();
apply_steerforce = true; apply_steerforce = true;
} }
break; break;
@ -193,8 +204,8 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
if (vectotarg2d.length2()<m_distance*m_distance) if (vectotarg2d.length2()<m_distance*m_distance)
{ {
terminate = false; terminate = false;
steervec = -vectotarg; m_steerVec = -vectotarg;
steervec.normalize(); m_steerVec.normalize();
apply_steerforce = true; apply_steerforce = true;
} }
break; break;
@ -228,7 +239,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
waypoint.setValue(&m_path[3*m_wayPointIdx]); waypoint.setValue(&m_path[3*m_wayPointIdx]);
} }
steervec = waypoint - mypos; m_steerVec = waypoint - mypos;
apply_steerforce = true; apply_steerforce = true;
@ -248,10 +259,10 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
{ {
bool isdyna = obj->IsDynamic(); bool isdyna = obj->IsDynamic();
if (isdyna) if (isdyna)
steervec.z() = 0; m_steerVec.z() = 0;
if (!steervec.fuzzyZero()) if (!m_steerVec.fuzzyZero())
steervec.normalize(); m_steerVec.normalize();
MT_Vector3 newvel = m_velocity*steervec; MT_Vector3 newvel = m_velocity*m_steerVec;
//adjust velocity to avoid obstacles //adjust velocity to avoid obstacles
if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/) if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/)
@ -264,6 +275,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.,1.,0.)); KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.,1.,0.));
} }
HandleActorFace(newvel);
if (isdyna) if (isdyna)
{ {
//temporary solution: set 2D steering velocity directly to obj //temporary solution: set 2D steering velocity directly to obj
@ -295,6 +307,96 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
return true; return true;
} }
const MT_Vector3& KX_SteeringActuator::GetSteeringVec()
{
if (m_isActive)
return m_steerVec;
else
return MT_Vector3(0, 0, 0);
}
void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity)
{
if (m_facingMode==0)
return;
MT_Vector3 dir = velocity;
if (dir.fuzzyZero())
return;
dir.normalize();
MT_Vector3 up(0,0,1);
MT_Vector3 left;
MT_Matrix3x3 mat;
switch (m_facingMode)
{
case 1: // TRACK X
{
left = dir.safe_normalized();
dir = -(left.cross(up)).safe_normalized();
break;
};
case 2: // TRACK Y
{
left = (dir.cross(up)).safe_normalized();
break;
}
case 3: // track Z
{
left = up.safe_normalized();
up = dir.safe_normalized();
dir = left;
left = (dir.cross(up)).safe_normalized();
break;
}
case 4: // TRACK -X
{
left = -dir.safe_normalized();
dir = -(left.cross(up)).safe_normalized();
break;
};
case 5: // TRACK -Y
{
left = (-dir.cross(up)).safe_normalized();
dir = -dir;
break;
}
case 6: // track -Z
{
left = up.safe_normalized();
up = -dir.safe_normalized();
dir = left;
left = (dir.cross(up)).safe_normalized();
break;
}
}
mat.setValue (
left[0], dir[0],up[0],
left[1], dir[1],up[1],
left[2], dir[2],up[2]
);
KX_GameObject* curobj = (KX_GameObject*) GetParent();
KX_GameObject* parentObject = curobj->GetParent();
if(parentObject)
{
MT_Point3 localpos;
localpos = curobj->GetSGNode()->GetLocalPosition();
MT_Matrix3x3 parentmatinv;
parentmatinv = parentObject->NodeGetWorldOrientation ().inverse ();
mat = parentmatinv * mat;
mat = m_parentlocalmat * mat;
curobj->NodeSetLocalOrientation(mat);
curobj->NodeSetLocalPosition(localpos);
}
else
{
curobj->NodeSetLocalOrientation(mat);
}
}
#ifndef DISABLE_PYTHON #ifndef DISABLE_PYTHON
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -338,6 +440,7 @@ PyAttributeDef KX_SteeringActuator::Attributes[] = {
KX_PYATTRIBUTE_FLOAT_RW("turnspeed", 0.0f, 720.0f, KX_SteeringActuator, m_turnspeed), KX_PYATTRIBUTE_FLOAT_RW("turnspeed", 0.0f, 720.0f, KX_SteeringActuator, m_turnspeed),
KX_PYATTRIBUTE_BOOL_RW("selfterminated", KX_SteeringActuator, m_isSelfTerminated), KX_PYATTRIBUTE_BOOL_RW("selfterminated", KX_SteeringActuator, m_isSelfTerminated),
KX_PYATTRIBUTE_BOOL_RW("enableVisualization", KX_SteeringActuator, m_enableVisualization), KX_PYATTRIBUTE_BOOL_RW("enableVisualization", KX_SteeringActuator, m_enableVisualization),
KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec),
KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod), KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod),
{ NULL } //Sentinel { NULL } //Sentinel
}; };
@ -404,6 +507,13 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
return PY_SET_ATTR_SUCCESS; return PY_SET_ATTR_SUCCESS;
} }
PyObject* KX_SteeringActuator::pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SteeringActuator* actuator = static_cast<KX_SteeringActuator*>(self);
const MT_Vector3& steeringVec = actuator->GetSteeringVec();
return PyObjectFrom(steeringVec);
}
#endif // DISABLE_PYTHON #endif // DISABLE_PYTHON
/* eof */ /* eof */

@ -38,6 +38,7 @@
#include "SCA_IActuator.h" #include "SCA_IActuator.h"
#include "SCA_LogicManager.h" #include "SCA_LogicManager.h"
#include "MT_Matrix3x3.h"
class KX_GameObject; class KX_GameObject;
class KX_NavMeshObject; class KX_NavMeshObject;
@ -64,11 +65,15 @@ class KX_SteeringActuator : public SCA_IActuator
bool m_isActive; bool m_isActive;
bool m_isSelfTerminated; bool m_isSelfTerminated;
bool m_enableVisualization; bool m_enableVisualization;
short m_facingMode;
float m_path[MAX_PATH_LENGTH*3]; float m_path[MAX_PATH_LENGTH*3];
int m_pathLen; int m_pathLen;
int m_pathUpdatePeriod; int m_pathUpdatePeriod;
double m_pathUpdateTime; double m_pathUpdateTime;
int m_wayPointIdx; int m_wayPointIdx;
MT_Matrix3x3 m_parentlocalmat;
MT_Vector3 m_steerVec;
void HandleActorFace(MT_Vector3& velocity);
public: public:
enum KX_STEERINGACT_MODE enum KX_STEERINGACT_MODE
{ {
@ -90,6 +95,7 @@ public:
bool isSelfTerminated, bool isSelfTerminated,
int pathUpdatePeriod, int pathUpdatePeriod,
KX_ObstacleSimulation* simulation, KX_ObstacleSimulation* simulation,
short facingmode,
bool enableVisualization); bool enableVisualization);
virtual ~KX_SteeringActuator(); virtual ~KX_SteeringActuator();
virtual bool Update(double curtime, bool frame); virtual bool Update(double curtime, bool frame);
@ -98,6 +104,7 @@ public:
virtual void ProcessReplica(); virtual void ProcessReplica();
virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
virtual bool UnlinkObject(SCA_IObject* clientobj); virtual bool UnlinkObject(SCA_IObject* clientobj);
const MT_Vector3& GetSteeringVec();
#ifndef DISABLE_PYTHON #ifndef DISABLE_PYTHON
@ -110,6 +117,7 @@ public:
static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
#endif // DISABLE_PYTHON #endif // DISABLE_PYTHON