diff options
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) }; |