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
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.
-rw-r--r--extern/bullet2/CMakeLists.txt4
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h2
-rw-r--r--extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp2
-rw-r--r--extern/bullet2/src/SConscript2
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py9
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/makesdna/DNA_object_types.h8
-rw-r--r--source/blender/makesrna/intern/rna_object.c41
-rw-r--r--source/blender/python/generic/py_capi_utils.c2
-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
21 files changed, 168 insertions, 29 deletions
diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt
index 51b295e897f..ae7d282ca55 100644
--- a/extern/bullet2/CMakeLists.txt
+++ b/extern/bullet2/CMakeLists.txt
@@ -118,6 +118,7 @@ set(SRC
src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+ src/BulletDynamics/Character/btKinematicCharacterController.cpp
src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
@@ -154,7 +155,6 @@ set(SRC
# src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
# src/BulletCollision/CollisionShapes/btBox2dShape.cpp
# src/BulletCollision/CollisionShapes/btConvex2dShape.cpp
- # src/BulletDynamics/Character/btKinematicCharacterController.cpp
# src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
# src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
@@ -274,6 +274,7 @@ set(SRC
src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
src/BulletDynamics/Character/btCharacterControllerInterface.h
+ src/BulletDynamics/Character/btKinematicCharacterController.h
src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
src/BulletDynamics/ConstraintSolver/btConstraintSolver.h
src/BulletDynamics/ConstraintSolver/btContactConstraint.h
@@ -343,7 +344,6 @@ set(SRC
# src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
# src/BulletCollision/CollisionShapes/btBox2dShape.h
# src/BulletCollision/CollisionShapes/btConvex2dShape.h
- # src/BulletDynamics/Character/btKinematicCharacterController.h
# src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
# src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
)
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
index 51b27afe686..9e247d125f5 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -339,7 +339,7 @@ public:
///***************************************** expert/internal use only *************************
- void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+ void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.5));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
void buildInternal();
diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
index 9732553130d..f733dc0cd22 100644
--- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -84,7 +84,7 @@ public:
} else
{
///need to transform normal into worldspace
- hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+ hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
}
btScalar dotUp = m_up.dot(hitNormalWorld);
diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript
index f59bcba9fa6..cd94df257ec 100644
--- a/extern/bullet2/src/SConscript
+++ b/extern/bullet2/src/SConscript
@@ -23,7 +23,7 @@ elif sys.platform=='darwin':
linearmath_src = env.Glob("LinearMath/*.cpp")
-bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp")
+bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") + env.Glob("BulletDynamics/Character/*.cpp")
collision_broadphase_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp")
collision_dispatch_src = env.Glob("BulletCollision/CollisionDispatch/*.cpp")
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 2aff07bd98e..857afbd9f09 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -49,7 +49,12 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
physics_type = game.physics_type
- if physics_type in {'DYNAMIC', 'RIGID_BODY'}:
+ if physics_type == 'CHARACTER':
+ layout.prop(game, "step_height", slider=True)
+ layout.prop(game, "jump_speed")
+ layout.prop(game, "fall_speed")
+
+ elif physics_type in {'DYNAMIC', 'RIGID_BODY'}:
split = layout.split()
col = split.column()
@@ -192,7 +197,7 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
def poll(cls, context):
game = context.object.game
rd = context.scene.render
- return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC'}) and (rd.engine in cls.COMPAT_ENGINES)
+ return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC', 'CHARACTER'}) and (rd.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
game = context.active_object.game
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 098d702a7e2..04631729d7a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -835,6 +835,9 @@ Object *BKE_object_add_only_object(int type, const char *name)
/* ob->pad3 == Contact Processing Threshold */
ob->m_contactProcessingThreshold = 1.0f;
ob->obstacleRad = 1.0f;
+ ob->step_height = 0.15f;
+ ob->jump_speed = 10.0f;
+ ob->fall_speed = 55.0f;
/* NT fluid sim defaults */
ob->fluidsimSettings = NULL;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 1ea50ec9c1a..11ca1f1fa8e 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -204,6 +204,12 @@ typedef struct Object {
float min_vel; /* clamp the maximum velocity 0.0 is disabled */
float m_contactProcessingThreshold;
float obstacleRad;
+
+ /* "Character" physics properties */
+ float step_height;
+ float jump_speed;
+ float fall_speed;
+ char pad1[4];
short rotmode; /* rotation mode - uses defines set out in DNA_action_types.h for PoseChannel rotations... */
@@ -483,6 +489,7 @@ typedef struct DupliObject {
#define OB_SENSOR 0x80000
#define OB_NAVMESH 0x100000
#define OB_HASOBSTACLE 0x200000
+#define OB_CHARACTER 0x400000
/* ob->gameflag2 */
#define OB_NEVER_DO_ACTIVITY_CULLING 1
@@ -504,6 +511,7 @@ typedef struct DupliObject {
#define OB_BODY_TYPE_OCCLUDER 5
#define OB_BODY_TYPE_SENSOR 6
#define OB_BODY_TYPE_NAVMESH 7
+#define OB_BODY_TYPE_CHARACTER 8
/* ob->scavisflag */
#define OB_VIS_SENS 1
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 21c9187cbb8..7e3b368aa64 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -891,6 +891,9 @@ static int rna_GameObjectSettings_physics_type_get(PointerRNA *ptr)
ob->body_type = OB_BODY_TYPE_NO_COLLISION;
}
}
+ else if (ob->gameflag & OB_CHARACTER) {
+ ob->body_type = OB_BODY_TYPE_CHARACTER;
+ }
else if (ob->gameflag & OB_SENSOR) {
ob->body_type = OB_BODY_TYPE_SENSOR;
}
@@ -922,16 +925,16 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
switch (ob->body_type) {
case OB_BODY_TYPE_SENSOR:
ob->gameflag |= OB_SENSOR | OB_COLLISION | OB_GHOST;
- ob->gameflag &= ~(OB_OCCLUDER | OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_ACTOR |
+ ob->gameflag &= ~(OB_OCCLUDER | OB_CHARACTER | OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_ACTOR |
OB_ANISOTROPIC_FRICTION | OB_DO_FH | OB_ROT_FH | OB_COLLISION_RESPONSE | OB_NAVMESH);
break;
case OB_BODY_TYPE_OCCLUDER:
ob->gameflag |= OB_OCCLUDER;
- ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_DYNAMIC | OB_NAVMESH);
+ ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_DYNAMIC | OB_NAVMESH);
break;
case OB_BODY_TYPE_NAVMESH:
ob->gameflag |= OB_NAVMESH;
- ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_DYNAMIC | OB_OCCLUDER);
+ ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_DYNAMIC | OB_OCCLUDER);
if (ob->type == OB_MESH) {
/* could be moved into mesh UI but for now ensure mesh data layer */
@@ -940,24 +943,29 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
break;
case OB_BODY_TYPE_NO_COLLISION:
- ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_OCCLUDER | OB_DYNAMIC | OB_NAVMESH);
+ ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_OCCLUDER | OB_DYNAMIC | OB_NAVMESH);
break;
+ case OB_BODY_TYPE_CHARACTER:
+ ob->gameflag |= OB_COLLISION | OB_GHOST | OB_CHARACTER;
+ ob->gameflag &= ~(OB_SENSOR | OB_OCCLUDER | OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_ACTOR
+ | OB_ANISOTROPIC_FRICTION | OB_DO_FH | OB_ROT_FH | OB_COLLISION_RESPONSE | OB_NAVMESH);
+ break;
case OB_BODY_TYPE_STATIC:
ob->gameflag |= OB_COLLISION;
- ob->gameflag &= ~(OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_OCCLUDER | OB_SENSOR | OB_NAVMESH);
+ ob->gameflag &= ~(OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_OCCLUDER | OB_CHARACTER | OB_SENSOR | OB_NAVMESH);
break;
case OB_BODY_TYPE_DYNAMIC:
ob->gameflag |= OB_COLLISION | OB_DYNAMIC | OB_ACTOR;
- ob->gameflag &= ~(OB_RIGID_BODY | OB_SOFT_BODY | OB_OCCLUDER | OB_SENSOR | OB_NAVMESH);
+ ob->gameflag &= ~(OB_RIGID_BODY | OB_SOFT_BODY | OB_OCCLUDER | OB_CHARACTER | OB_SENSOR | OB_NAVMESH);
break;
case OB_BODY_TYPE_RIGID:
ob->gameflag |= OB_COLLISION | OB_DYNAMIC | OB_RIGID_BODY | OB_ACTOR;
- ob->gameflag &= ~(OB_SOFT_BODY | OB_OCCLUDER | OB_SENSOR | OB_NAVMESH);
+ ob->gameflag &= ~(OB_SOFT_BODY | OB_OCCLUDER | OB_CHARACTER | OB_SENSOR | OB_NAVMESH);
break;
default:
case OB_BODY_TYPE_SOFT:
ob->gameflag |= OB_COLLISION | OB_DYNAMIC | OB_SOFT_BODY | OB_ACTOR;
- ob->gameflag &= ~(OB_RIGID_BODY | OB_OCCLUDER | OB_SENSOR | OB_NAVMESH);
+ ob->gameflag &= ~(OB_RIGID_BODY | OB_OCCLUDER | OB_CHARACTER | OB_SENSOR | OB_NAVMESH);
/* assume triangle mesh, if no bounds chosen for soft body */
if ((ob->gameflag & OB_BOUNDS) && (ob->boundtype < OB_BOUND_TRIANGLE_MESH)) {
@@ -1436,6 +1444,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
"Collision Sensor, detects static and dynamic objects but not the other "
"collision sensor objects"},
{OB_BODY_TYPE_NAVMESH, "NAVMESH", 0, "Navigation Mesh", "Navigation mesh"},
+ {OB_BODY_TYPE_CHARACTER, "CHARACTER", 0, "Character", "Simple kinematic physics appropiate for game characters"},
{0, NULL, 0, NULL, NULL}
};
@@ -1529,6 +1538,22 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "max_vel");
RNA_def_property_range(prop, 0.0, 1000.0);
RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed");
+
+ prop= RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "step_height");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over");
+
+ prop= RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "jump_speed");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping (with the Motion actuator)");
+
+ prop= RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "fall_speed");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall");
+
/* lock position */
prop = RNA_def_property(srna, "lock_location_x", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 3a405575926..fd12f7f483d 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -489,7 +489,7 @@ void PyC_SetHomePath(const char *py_path_bundle)
/* cmake/MSVC debug build crashes without this, why only
* in this case is unknown.. */
{
- BLI_setenv("PYTHONPATH", py_path_bundle);
+ /*BLI_setenv("PYTHONPATH", py_path_bundle)*/;
}
#endif
#endif
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)
};