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:
authorMitchell Stokes <mogurijin@gmail.com>2012-10-30 19:44:16 +0400
committerMitchell Stokes <mogurijin@gmail.com>2012-10-30 19:44:16 +0400
commit3bf9bb3b13521c8bba4d559f308c5b2c04973df8 (patch)
tree2f1e92d25671239d16b51df88f57ffc6dea93c79
parent5753ede9a5cda9e23cc346ca57f6fb677e9fbb92 (diff)
BGE: Adding support for Bullet's collision masks. Each object now has a collision mask and a collision group. Object A and object B collide if object A's groups is in object B's mask and object B's group is in object A's mask. In other words, the group defines what the object is (collision wise) and the group defines what the object can collide with.
The majority of this patch was provided by Kupoman with some edits from me and heavy testing by z0r.
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py8
-rw-r--r--source/blender/blenkernel/intern/object.c4
-rw-r--r--source/blender/blenloader/intern/readfile.c10
-rw-r--r--source/blender/makesdna/DNA_object_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_object.c70
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp13
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h11
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp21
9 files changed, 150 insertions, 3 deletions
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 5ff49a7d369..bf0c9eb762a 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -190,6 +190,14 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
layout.operator("mesh.navmesh_reset")
layout.operator("mesh.navmesh_clear")
+ if physics_type not in {'NO_COLLISION', 'OCCLUDE'}:
+ layout.separator()
+ split = layout.split()
+
+ col = split.column()
+ col.prop(game, "collision_group")
+ col = split.column()
+ col.prop(game, "collision_mask")
class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
bl_label = "Collision Bounds"
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 431f2c04f7d..a7b53370d1d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -854,7 +854,9 @@ Object *BKE_object_add_only_object(int type, const char *name)
ob->step_height = 0.15f;
ob->jump_speed = 10.0f;
ob->fall_speed = 55.0f;
-
+ ob->col_group = 0x01;
+ ob->col_mask = 0xff;
+
/* NT fluid sim defaults */
ob->fluidsimSettings = NULL;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index de9e5f5e08e..d694de61131 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8247,6 +8247,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
+ {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->col_group == 0) {
+ ob->col_group = 0x01;
+ ob->col_mask = 0xff;
+ }
+ }
+ }
+
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 2fc04c4a5db..932d209f2c7 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -243,6 +243,9 @@ typedef struct Object {
short recalc; /* dependency flag */
float anisotropicFriction[3];
+ /** Collision mask settings */
+ unsigned short col_group, col_mask, col_pad[2];
+
ListBase constraints; /* object constraints */
ListBase nlastrips DNA_DEPRECATED; // XXX deprecated... old animation system
ListBase hooks DNA_DEPRECATED; // XXX deprecated... old animation system
@@ -479,6 +482,9 @@ typedef struct DupliObject {
/* controller state */
#define OB_MAX_STATES 30
+/* collision masks */
+#define OB_MAX_COL_MASKS 8
+
/* ob->gameflag */
#define OB_DYNAMIC 1
#define OB_CHILD 2
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 0c1ec0b02f9..7b5feff614c 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1111,6 +1111,63 @@ static void rna_GameObjectSettings_used_state_get(PointerRNA *ptr, int *values)
}
}
+static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values)
+{
+ Object *ob = (Object*)ptr->data;
+ int i;
+
+ for (i = 0; i < OB_MAX_COL_MASKS; i++)
+ values[i] = (ob->col_group & (1<<i));
+}
+
+static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *values)
+{
+ Object *ob = (Object*)ptr->data;
+ int i, tot = 0;
+
+ /* ensure we always have some group selected */
+ for (i = 0; i < OB_MAX_COL_MASKS; i++)
+ if(values[i])
+ tot++;
+
+ if (tot==0)
+ return;
+
+ for (i = 0; i < OB_MAX_COL_MASKS; i++) {
+ if (values[i]) ob->col_group |= (1<<i);
+ else ob->col_group &= ~(1<<i);
+ }
+}
+
+static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values)
+{
+ Object *ob = (Object*)ptr->data;
+ int i;
+
+ for (i = 0; i < OB_MAX_COL_MASKS; i++)
+ values[i] = (ob->col_mask & (1<<i));
+}
+
+static void rna_GameObjectSettings_col_mask_set(PointerRNA *ptr, const int *values)
+{
+ Object *ob = (Object*)ptr->data;
+ int i, tot = 0;
+
+ /* ensure we always have some mask selected */
+ for (i = 0; i < OB_MAX_COL_MASKS; i++)
+ if(values[i])
+ tot++;
+
+ if (tot==0)
+ return;
+
+ for (i = 0; i < OB_MAX_COL_MASKS; i++) {
+ if (values[i]) ob->col_mask |= (1<<i);
+ else ob->col_mask &= ~(1<<i);
+ }
+}
+
+
static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
Object *ob = (Object *)ptr->id.data;
@@ -1456,6 +1513,8 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ int default_col_mask[8] = {1,0,0,0, 0,0,0,0};
+
static EnumPropertyItem body_type_items[] = {
{OB_BODY_TYPE_NO_COLLISION, "NO_COLLISION", 0, "No Collision", "Disable collision for this object"},
{OB_BODY_TYPE_STATIC, "STATIC", 0, "Static", "Stationary object"},
@@ -1578,6 +1637,17 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
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");
+ prop = RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER);
+ RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1);
+ RNA_def_property_array(prop, OB_MAX_COL_MASKS);
+ RNA_def_property_ui_text(prop, "Collision Group", "The collision group of the object");
+ RNA_def_property_boolean_funcs(prop, "rna_GameObjectSettings_col_group_get", "rna_GameObjectSettings_col_group_set");
+
+ prop = RNA_def_property(srna, "collision_mask", PROP_BOOLEAN, PROP_LAYER_MEMBER);
+ RNA_def_property_boolean_sdna(prop, NULL, "col_mask", 1);
+ RNA_def_property_array(prop, OB_MAX_COL_MASKS);
+ RNA_def_property_ui_text(prop, "Collision Mask", "The groups this object can collide with");
+ RNA_def_property_boolean_funcs(prop, "rna_GameObjectSettings_col_mask_get", "rna_GameObjectSettings_col_mask_set");
/* lock position */
prop = RNA_def_property(srna, "lock_location_x", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 982988cc088..58ae415e9d3 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1587,8 +1587,16 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
//bool bRigidBody = (userigidbody == 0);
// object has physics representation?
- if (!(blenderobject->gameflag & OB_COLLISION))
+ if (!(blenderobject->gameflag & OB_COLLISION)) {
+ // Respond to all collisions so that Near sensors work on No Collision
+ // objects.
+ gameobj->SetUserCollisionGroup(0xff);
+ gameobj->SetUserCollisionMask(0xff);
return;
+ }
+
+ gameobj->SetUserCollisionGroup(blenderobject->col_group);
+ gameobj->SetUserCollisionMask(blenderobject->col_mask);
// get Root Parent of blenderobject
struct Object* parent= blenderobject->parent;
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 48a45c2d1c2..a669f4346ea 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -531,6 +531,19 @@ void KX_GameObject::ActivateGraphicController(bool recurse)
}
}
+void KX_GameObject::SetUserCollisionGroup(short group)
+{
+ m_userCollisionGroup = group;
+}
+void KX_GameObject::SetUserCollisionMask(short mask)
+{
+ m_userCollisionMask = mask;
+}
+
+bool KX_GameObject::CheckCollision(KX_GameObject* other)
+{
+ return this->m_userCollisionGroup & other->m_userCollisionMask;
+}
CValue* KX_GameObject::GetReplica()
{
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 5ceef2c60c9..d5ae13eb702 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -98,6 +98,10 @@ protected:
bool m_bIsNegativeScaling;
MT_Vector4 m_objectColor;
+ // Bit fields for user control over physics collisions
+ short m_userCollisionGroup;
+ short m_userCollisionMask;
+
// visible = user setting
// culled = while rendering, depending on camera
bool m_bVisible;
@@ -494,6 +498,13 @@ public:
*/
void ActivateGraphicController(bool recurse);
+ void SetUserCollisionGroup(short filter);
+ void SetUserCollisionMask(short mask);
+ /**
+ * Extra broadphase check for user controllable collisions
+ */
+ bool CheckCollision(KX_GameObject *other);
+
/**
* \section Coordinate system manipulation functions
*/
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index e43ddb303e9..687fc116234 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -2208,10 +2208,29 @@ bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0
{
btCollisionObject *colObj0, *colObj1;
CcdPhysicsController *sensorCtrl, *objCtrl;
+
+ KX_GameObject *kxObj0 = KX_GameObject::GetClientObject(
+ (KX_ClientObjectInfo*)
+ ((CcdPhysicsController*)
+ (((btCollisionObject*)proxy0->m_clientObject)->getUserPointer()))
+ ->getNewClientInfo());
+ KX_GameObject *kxObj1 = KX_GameObject::GetClientObject(
+ (KX_ClientObjectInfo*)
+ ((CcdPhysicsController*)
+ (((btCollisionObject*)proxy1->m_clientObject)->getUserPointer()))
+ ->getNewClientInfo());
+
+ // First check the filters. Note that this is called during scene
+ // conversion, so we can't assume the KX_GameObject instances exist. This
+ // may make some objects erroneously collide on the first frame, but the
+ // alternative is to have them erroneously miss.
bool collides;
- // first check the filters
collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ if (kxObj0 && kxObj1) {
+ collides = collides && kxObj0->CheckCollision(kxObj1);
+ collides = collides && kxObj1->CheckCollision(kxObj0);
+ }
if (!collides)
return false;