Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Bolsee <benoit.bolsee@online.be>2012-05-29 01:36:29 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2012-05-29 01:36:29 +0400
commitdfc19a1ff7968e547c33ef3304849f69ddf76f4f (patch)
tree62764fb4d5ebf37785a1d34dcda7e01d4392bc18 /source/gameengine
parent4e0492e3bc59a4adca8ea5075a96bc78cd6bb67a (diff)
BGE patch #28476: Character object physics type
=============================================== This patch adds a new "Character" BGE physics type which uses Bullet's btKinematicCharacter for simulation instead of full-blown dynamics. It is appropiate for (player-controlled) characters, for which the other physics types often result unexpected results (bouncing off walls, sliding etc.) and for which simple kinematics offers much more precision. "Character" can be chosen like any other physics type in the "Physics" section of the properties window. Current settings for tweaking are "Step Height" (to make the object automatically climb small steps if it collides with them), "Fall Speed" (the maximum speed that the object can have when falling) and "Jump Speed", which is currently not used. See http://projects.blender.org/tracker/?func=detail&atid=127&aid=28476&group_id=9 for sample blends and a discussion on the patch: how to use it and what influences the behavior of the character object. Known problem: there is a crash if the "compound" option is set in the physics panel of the Character object.
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.h2
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.h11
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp5
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp50
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h12
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp8
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h3
12 files changed, 111 insertions, 13 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 196f032e584..3d73ca66c92 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1346,6 +1346,11 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero
shapeProps->m_clamp_vel_min = blenderobject->min_vel;
shapeProps->m_clamp_vel_max = blenderobject->max_vel;
+// Character physics properties
+ shapeProps->m_step_height = blenderobject->step_height;
+ shapeProps->m_jump_speed = blenderobject->jump_speed;
+ shapeProps->m_fall_speed = blenderobject->fall_speed;
+
return shapeProps;
}
@@ -1638,6 +1643,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
+ objprop.m_character = (blenderobject->gameflag & OB_CHARACTER) != 0;
///contact processing threshold is only for rigid bodies and static geometry, not 'dynamic'
if (objprop.m_angular_rigidbody || !objprop.m_dyna )
@@ -1754,6 +1760,11 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_boundclass = KX_BOUNDMESH;
}
+ if ((blenderobject->gameflag & OB_CHARACTER) && !(blenderobject->gameflag & OB_BOUNDS))
+ {
+ objprop.m_boundclass = KX_BOUNDSPHERE;
+ }
+
KX_BoxBounds bb;
DerivedMesh* dm = NULL;
if (gameobj->GetDeformer())
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index f5926818e7d..abc2460a5ba 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -20,8 +20,8 @@
#include "BulletSoftBody/btSoftBody.h"
-KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool compound)
-: KX_IPhysicsController(dyna,sensor,compound,(PHY_IPhysicsController*)this),
+KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool character, bool compound)
+: KX_IPhysicsController(dyna,sensor,character,compound,(PHY_IPhysicsController*)this),
CcdPhysicsController(ci),
m_savedCollisionFlags(0),
m_savedCollisionFilterGroup(0),
@@ -472,7 +472,7 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode)
void KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly)
{
- if (!m_bDyna && !m_bSensor)
+ if (!m_bDyna && !m_bSensor && !m_bCharacter)
{
btCollisionObject* object = GetRigidBody();
object->setActivationState(ACTIVE_TAG);
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
index d2f56bccaa0..4ced21aa2d8 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
@@ -26,7 +26,7 @@ private:
public:
#ifdef USE_BULLET
- KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool compound);
+ KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool character, bool compound);
virtual ~KX_BulletPhysicsController ();
#endif
///////////////////////////////////
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
index f1f58d7da9a..0f1ce403881 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -72,6 +72,7 @@ struct KX_ObjectProperties
class KX_GameObject* m_dynamic_parent;
bool m_isactor;
bool m_sensor;
+ bool m_character;
bool m_concave;
bool m_isdeformable;
bool m_disableSleeping;
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index e0e8e2d9b3f..227ca39281f 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -100,6 +100,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
bool isbulletdyna = false;
bool isbulletsensor = false;
+ bool isbulletchar = false;
bool useGimpact = false;
CcdConstructionInfo ci;
class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
@@ -122,9 +123,13 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min;
ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max;
ci.m_margin = objprop->m_margin;
+ ci.m_stepHeight = objprop->m_character ? shapeprops->m_step_height : 0.f;
+ ci.m_jumpSpeed = objprop->m_character ? shapeprops->m_jump_speed : 0.f;
+ ci.m_fallSpeed = objprop->m_character ? shapeprops->m_fall_speed : 0.f;
shapeInfo->m_radius = objprop->m_radius;
isbulletdyna = objprop->m_dyna;
isbulletsensor = objprop->m_sensor;
+ isbulletchar = objprop->m_character;
useGimpact = ((isbulletdyna || isbulletsensor) && !objprop->m_softbody);
ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
@@ -400,21 +405,24 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
////////////////////
ci.m_collisionFilterGroup =
(isbulletsensor) ? short(CcdConstructionInfo::SensorFilter) :
- (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) :
+ (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) :
+ (isbulletchar) ? short(CcdConstructionInfo::CharacterFilter) :
short(CcdConstructionInfo::StaticFilter);
ci.m_collisionFilterMask =
(isbulletsensor) ? short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter) :
(isbulletdyna) ? short(CcdConstructionInfo::AllFilter) :
+ (isbulletchar) ? short(CcdConstructionInfo::AllFilter) :
short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
ci.m_contactProcessingThreshold = objprop->m_contactProcessingThreshold;//todo: expose this in advanced settings, just like margin, default to 10000 or so
ci.m_bSoft = objprop->m_softbody;
ci.m_bSensor = isbulletsensor;
+ ci.m_bCharacter = isbulletchar;
ci.m_bGimpact = useGimpact;
MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
- KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,isbulletsensor,objprop->m_hasCompoundChildren);
+ KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,isbulletsensor,isbulletchar,objprop->m_hasCompoundChildren);
// shapeInfo is reference counted, decrement now as we don't use it anymore
if (shapeInfo)
shapeInfo->Release();
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.cpp b/source/gameengine/Ketsji/KX_IPhysicsController.cpp
index bd75246a97f..f0e57ceac02 100644
--- a/source/gameengine/Ketsji/KX_IPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.cpp
@@ -33,10 +33,11 @@
#include "PHY_DynamicTypes.h"
-KX_IPhysicsController::KX_IPhysicsController(bool dyna, bool sensor, bool compound, void* userdata)
+KX_IPhysicsController::KX_IPhysicsController(bool dyna, bool sensor, bool character, bool compound, void* userdata)
: m_bDyna(dyna),
m_bSensor(sensor),
+ m_bCharacter(character),
m_bCompound(compound),
m_suspendDynamics(false),
m_userdata(userdata)
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h
index 68577f09414..528bf00d574 100644
--- a/source/gameengine/Ketsji/KX_IPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.h
@@ -53,11 +53,12 @@ class KX_IPhysicsController : public SG_Controller
protected:
bool m_bDyna;
bool m_bSensor;
+ bool m_bCharacter;
bool m_bCompound;
bool m_suspendDynamics;
void* m_userdata;
public:
- KX_IPhysicsController(bool dyna,bool sensor,bool compound, void* userdata);
+ KX_IPhysicsController(bool dyna,bool sensor,bool character,bool compound, void* userdata);
virtual ~KX_IPhysicsController();
@@ -109,6 +110,10 @@ public:
m_bSensor = isSensor;
}
+ void SetCharacter(bool isCharacter) {
+ m_bCharacter = isCharacter;
+ }
+
bool IsDyna(void) {
return m_bDyna;
}
@@ -117,6 +122,10 @@ public:
return m_bSensor;
}
+ bool IsCharacter(void) {
+ return m_bCharacter;
+ }
+
bool IsCompound(void) {
return m_bCompound;
}
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 503c16fae9c..4f0ae4261c9 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -2267,7 +2267,10 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
!ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") )
return NULL;
-
+ if (!m_inactivelist->SearchValue(ob)) {
+ PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (second argument): object does not belong to scene");
+ return NULL;
+ }
SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time);
// release here because AddReplicaObject AddRef's
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 6c1e2998bdb..92a9b405b7c 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -22,6 +22,7 @@ subject to the following restrictions:
#include "CcdPhysicsController.h"
#include "btBulletDynamicsCommon.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
@@ -88,7 +89,7 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
m_shapeInfo->AddRef();
m_bulletMotionState = 0;
-
+ m_characterController = 0;
CreateRigidbody();
@@ -151,6 +152,24 @@ public:
};
+class BlenderBulletCharacterController : public btKinematicCharacterController
+{
+private:
+ btMotionState* m_motionState;
+
+public:
+ BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
+ : btKinematicCharacterController(ghost,shape,stepHeight,2),
+ m_motionState(motionState)
+ {
+ }
+
+ virtual void updateAction(btCollisionWorld *collisionWorld, btScalar dt)
+ {
+ btKinematicCharacterController::updateAction(collisionWorld,dt);
+ m_motionState->setWorldTransform(getGhostObject()->getWorldTransform());
+ }
+};
btRigidBody* CcdPhysicsController::GetRigidBody()
{
@@ -164,6 +183,10 @@ btSoftBody* CcdPhysicsController::GetSoftBody()
{
return btSoftBody::upcast(m_object);
}
+btKinematicCharacterController* CcdPhysicsController::GetCharacterController()
+{
+ return m_characterController;
+}
#include "BulletSoftBody/btSoftBodyHelpers.h"
@@ -425,6 +448,29 @@ bool CcdPhysicsController::CreateSoftbody()
return true;
}
+bool CcdPhysicsController::CreateCharacterController()
+{
+ if (!m_cci.m_bCharacter)
+ return false;
+
+ m_object = new btPairCachingGhostObject();
+ m_object->setCollisionShape(m_collisionShape);
+ m_object->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
+
+ btTransform trans;
+ m_bulletMotionState->getWorldTransform(trans);
+ m_object->setWorldTransform(trans);
+
+ m_characterController = new BlenderBulletCharacterController(m_bulletMotionState,(btPairCachingGhostObject*)m_object,(btConvexShape*)m_collisionShape,m_cci.m_stepHeight);
+
+ PHY__Vector3 gravity;
+ m_cci.m_physicsEnv->getGravity(gravity);
+ m_characterController->setGravity(-gravity.m_vec[2]); // need positive gravity
+ m_characterController->setJumpSpeed(m_cci.m_jumpSpeed);
+ m_characterController->setFallSpeed(m_cci.m_fallSpeed);
+
+ return true;
+}
void CcdPhysicsController::CreateRigidbody()
{
@@ -433,7 +479,7 @@ void CcdPhysicsController::CreateRigidbody()
m_bulletMotionState = new BlenderBulletMotionState(m_MotionState);
///either create a btCollisionObject, btRigidBody or btSoftBody
- if (CreateSoftbody())
+ if (CreateSoftbody() || CreateCharacterController())
// soft body created, done
return;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 2228b6511ce..63c267443aa 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -29,6 +29,7 @@ subject to the following restrictions:
/// PHY_IPhysicsController is the abstract simplified Interface to a physical object.
/// It contains the IMotionState and IDeformableMesh Interfaces.
#include "btBulletDynamicsCommon.h"
+#include "BulletDynamics/Character/btKinematicCharacterController.h"
#include "LinearMath/btTransform.h"
#include "PHY_IMotionState.h"
@@ -221,7 +222,8 @@ struct CcdConstructionInfo
KinematicFilter = 4,
DebrisFilter = 8,
SensorFilter = 16,
- AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorFilter,
+ CharacterFilter = 32,
+ AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorFilter | CharacterFilter,
};
@@ -301,6 +303,10 @@ struct CcdConstructionInfo
btScalar m_margin;
////////////////////
+ float m_stepHeight;
+ float m_jumpSpeed;
+ float m_fallSpeed;
+
int m_gamesoftFlag;
float m_soft_linStiff; /* linear stiffness 0..1 */
float m_soft_angStiff; /* angular stiffness 0..1 */
@@ -343,6 +349,7 @@ struct CcdConstructionInfo
bool m_bRigid;
bool m_bSoft;
bool m_bSensor;
+ bool m_bCharacter;
bool m_bGimpact; // use Gimpact for mesh body
///optional use of collision group/mask:
@@ -391,6 +398,7 @@ class CcdPhysicsController : public PHY_IPhysicsController
{
protected:
btCollisionObject* m_object;
+ btKinematicCharacterController* m_characterController;
class PHY_IMotionState* m_MotionState;
@@ -417,6 +425,7 @@ protected:
void CreateRigidbody();
bool CreateSoftbody();
+ bool CreateCharacterController();
bool Register() {
return (m_registerCount++ == 0) ? true : false;
@@ -453,6 +462,7 @@ protected:
btRigidBody* GetRigidBody();
btCollisionObject* GetCollisionObject();
btSoftBody* GetSoftBody();
+ btKinematicCharacterController* GetCharacterController();
CcdShapeConstructionInfo* GetShapeInfo() { return m_shapeInfo; }
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index ba0d3f18b1d..767d99583b8 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -26,6 +26,7 @@ subject to the following restrictions:
#include <algorithm>
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
@@ -369,6 +370,7 @@ m_scalingPropagated(false)
m_filterCallback = new CcdOverlapFilterCallBack(this);
m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
+ m_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
setSolverType(1);//issues with quickstep and memory allocations
// m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
@@ -406,7 +408,11 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
{
if (obj->getCollisionShape())
{
- m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
+ m_dynamicsWorld->addCollisionObject(obj, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
+ }
+ if (ctrl->GetCharacterController())
+ {
+ m_dynamicsWorld->addAction(ctrl->GetCharacterController());
}
}
}
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
index 110d4731cdc..b930177d3a8 100644
--- a/source/gameengine/Physics/common/PHY_Pro.h
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -46,6 +46,9 @@ struct PHY_ShapeProps {
bool m_do_anisotropic; // Should I do anisotropic friction?
bool m_do_fh; // Should the object have a linear Fh spring?
bool m_do_rot_fh; // Should the object have an angular Fh spring?
+ MT_Scalar m_step_height; // Max height of climbable steps (Character)
+ MT_Scalar m_jump_speed; // Velocity of jumps (Character)
+ MT_Scalar m_fall_speed; // Max velocity of falling (Character)
};