[Bf-blender-cvs] [720d452] master: BGE : Collision mask support in raycast + and raycast cleanup.

Porteries Tristan noreply at git.blender.org
Wed Oct 7 22:11:37 CEST 2015


Commit: 720d4521cdd0986d9c6df97924b72eed72e5a3af
Author: Porteries Tristan
Date:   Wed Oct 7 22:14:43 2015 +0200
Branches: master
https://developer.blender.org/rB720d4521cdd0986d9c6df97924b72eed72e5a3af

BGE : Collision mask support in raycast + and raycast cleanup.

I have removed the m_pHitObject, m_xray and m_testPropName and replace them by a temporary struct "RayCastData" which contains these datas and a collision mask. Finally i add a collision mask argument in the python function "rayCast" :
```
rayCast(to, from, dist, prop, face, xray, poly, mask)
```

It can be useful to hit only object which are on the right colision layer. for example if you have hitbox for a charater or vehicle you don't want to hit it with raycast.

test file : {F237337}
left mouse click on two planes and see console messages.

Somewhat more elaborate test file by @sybren: {F237779}
Look around and click on the cubes. One cube lamp responds, the other doesn't, based on their collision groups.

Reviewers: moguri, hg1, agoose77, campbellbarton, sybren

Reviewed By: agoose77, campbellbarton, sybren

Subscribers: campbellbarton, sergey, blueprintrandom, sybren

Projects: #game_engine, #game_physics

Differential Revision: https://developer.blender.org/D1239

===================================================================

M	doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
M	source/gameengine/Ketsji/KX_ConstraintActuator.cpp
M	source/gameengine/Ketsji/KX_ConstraintActuator.h
M	source/gameengine/Ketsji/KX_GameObject.cpp
M	source/gameengine/Ketsji/KX_GameObject.h
M	source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
M	source/gameengine/Ketsji/KX_MouseFocusSensor.h
M	source/gameengine/Ketsji/KX_RayCast.h
M	source/gameengine/Ketsji/KX_RaySensor.cpp
M	source/gameengine/Ketsji/KX_RaySensor.h
M	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
M	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h

===================================================================

diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
index 74df50d..d8cc5e4 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
@@ -799,7 +799,7 @@ base class --- :class:`SCA_IObject`
       :return: the first object hit or None if no object or object does not match prop
       :rtype: :class:`KX_GameObject`
 
-   .. method:: rayCast(objto, objfrom, dist, prop, face, xray, poly)
+   .. method:: rayCast(objto, objfrom, dist, prop, face, xray, poly, mask)
 
       Look from a point/object to another point/object and find first object hit within dist that matches prop.
       if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None, None, None) if no hit.
@@ -851,6 +851,8 @@ base class --- :class:`SCA_IObject`
          * 2: return value is a 5-tuple and the 5th element is a 2-tuple (u, v) with the UV mapping of the hit point or None if no hit, or the object doesn't use a mesh collision shape, or doesn't have a UV mapping.
 
       :type poly: integer
+      :arg mask: collision mask: The collision mask (16 layers mapped to a 16-bit integer) is combined with each object's collision group, to hit only a subset of the objects in the scene. Only those objects for which ``collisionGroup & mask`` is true can be hit.
+      :type mask: bitfield
       :return: (object, hitpoint, hitnormal) or (object, hitpoint, hitnormal, polygon) or (object, hitpoint, hitnormal, polygon, hituv).
 
          * object, hitpoint and hitnormal are None if no hit.
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index e07660c..fecd60e 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -117,7 +117,7 @@ KX_ConstraintActuator::~KX_ConstraintActuator()
 	// there's nothing to be done here, really....
 } /* end of destructor */
 
-bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void * const data)
+bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void *UNUSED(data))
 {
 
 	m_hitObject = client->m_gameobject;
@@ -153,7 +153,7 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *resu
 /* This function is used to pre-filter the object before casting the ray on them.
  * This is useful for "X-Ray" option when we want to see "through" unwanted object.
  */
-bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo *client)
+bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo *client, void *UNUSED(data))
 {
 	if (client->m_type > KX_ClientObjectInfo::ACTOR)
 	{
@@ -347,7 +347,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
 						spc = parent->GetPhysicsController();
 					}
 				}
-				KX_RayCast::Callback<KX_ConstraintActuator> callback(this,dynamic_cast<PHY_IPhysicsController*>(spc));
+				KX_RayCast::Callback<KX_ConstraintActuator, void> callback(this,dynamic_cast<PHY_IPhysicsController*>(spc));
 				result = KX_RayCast::RayTest(pe, position, topoint, callback);
 				if (result)	{
 					MT_Vector3 newnormal = callback.m_hitNormal;
@@ -459,7 +459,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
 				m_hitObject = NULL;
 				// distance of Fh area is stored in m_minimum
 				MT_Point3 topoint = position + (m_minimumBound+spc->GetRadius()) * direction;
-				KX_RayCast::Callback<KX_ConstraintActuator> callback(this, spc);
+				KX_RayCast::Callback<KX_ConstraintActuator, void> callback(this, spc);
 				result = KX_RayCast::RayTest(pe, position, topoint, callback);
 				// we expect a hit object
 				if (!m_hitObject)
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
index edb2e5e..af61765 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.h
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -37,6 +37,8 @@
 #include "MT_Vector3.h"
 #include "KX_ClientObjectInfo.h"
 
+#include "BLI_utildefines.h"
+
 class KX_RayCast;
 class KX_GameObject;
 
@@ -113,9 +115,11 @@ protected:
 		KX_ACT_CONSTRAINT_LOCAL = 1024,
 		KX_ACT_CONSTRAINT_DOROTFH = 2048
 	};
-	bool IsValidMode(KX_CONSTRAINTTYPE m); 
-	bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
-	bool NeedRayCast(KX_ClientObjectInfo*);
+	bool IsValidMode(KX_CONSTRAINTTYPE m);
+	/// \see KX_RayCast
+	bool RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void *UNUSED(data));
+	/// \see KX_RayCast
+	bool NeedRayCast(KX_ClientObjectInfo *client, void *UNUSED(data));
 
 	KX_ConstraintActuator(SCA_IObject* gameobj,
 						  int posDamptime,
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index c3da80b..d7a94f0 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -47,7 +47,6 @@
 #include "KX_MeshProxy.h"
 #include "KX_PolyProxy.h"
 #include <stdio.h> // printf
-#include <climits> // USHRT_MAX
 #include "SG_Controller.h"
 #include "PHY_IGraphicController.h"
 #include "SG_Node.h"
@@ -108,8 +107,6 @@ KX_GameObject::KX_GameObject(
       m_bOccluder(false),
       m_pPhysicsController(NULL),
       m_pGraphicController(NULL),
-      m_xray(false),
-      m_pHitObject(NULL),
       m_pObstacleSimulation(NULL),
       m_pInstanceObjects(NULL),
       m_pDupliGroupObject(NULL),
@@ -2361,8 +2358,8 @@ int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_
 		return PY_SET_ATTR_FAIL;
 	}
 
-	if (val < 0 || val > USHRT_MAX) {
-		PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX);
+	if (val == 0 || val & ~((1 << OB_MAX_COL_MASKS) - 1)) {
+		PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field, 0 < group < %i", (1 << OB_MAX_COL_MASKS));
 		return PY_SET_ATTR_FAIL;
 	}
 
@@ -2386,8 +2383,8 @@ int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_D
 		return PY_SET_ATTR_FAIL;
 	}
 
-	if (val < 0 || val > USHRT_MAX) {
-		PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX);
+	if (val == 0 || val & ~((1 << OB_MAX_COL_MASKS) - 1)) {
+		PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field, 0 < mask < %i", (1 << OB_MAX_COL_MASKS));
 		return PY_SET_ATTR_FAIL;
 	}
 
@@ -3572,15 +3569,32 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
 	return returnValue;
 }
 
-bool KX_GameObject::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void * const data)
+struct KX_GameObject::RayCastData
+{
+	RayCastData(STR_String prop, bool xray, short mask)
+		:m_prop(prop),
+		m_xray(xray),
+		m_mask(mask),
+		m_hitObject(NULL)
+	{
+	}
+
+	STR_String m_prop;
+	bool m_xray;
+	unsigned short m_mask;
+	KX_GameObject *m_hitObject;
+};
+
+bool KX_GameObject::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, RayCastData *rayData)
 {
 	KX_GameObject* hitKXObj = client->m_gameobject;
-	
+
 	// if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
 	// if not, all objects were tested and the front one may not be the correct one.
-	if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+	if ((rayData->m_xray || rayData->m_prop.Length() == 0 || hitKXObj->GetProperty(rayData->m_prop) != NULL) && 
+		hitKXObj->GetUserCollisionGroup() & rayData->m_mask)
 	{
-		m_pHitObject = hitKXObj;
+		rayData->m_hitObject = hitKXObj;
 		return true;
 	}
 	// return true to stop RayCast::RayTest from looping, the above test was decisive
@@ -3591,10 +3605,10 @@ bool KX_GameObject::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
 /* this function is used to pre-filter the object before casting the ray on them.
  * This is useful for "X-Ray" option when we want to see "through" unwanted object.
  */
-bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo *client)
+bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo *client, RayCastData *rayData)
 {
 	KX_GameObject* hitKXObj = client->m_gameobject;
-	
+
 	if (client->m_type > KX_ClientObjectInfo::ACTOR)
 	{
 		// Unknown type of object, skip it.
@@ -3605,7 +3619,8 @@ bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo *client)
 	
 	// if X-Ray option is selected, skip object that don't match the criteria as we see through them
 	// if not, test all objects because we don't know yet which one will be on front
-	if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+	if ((!rayData->m_xray || rayData->m_prop.Length() == 0 || hitKXObj->GetProperty(rayData->m_prop) != NULL) && 
+		hitKXObj->GetUserCollisionGroup() & rayData->m_mask)
 	{
 		return true;
 	}
@@ -3652,17 +3667,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
 	KX_GameObject *parent = GetParent();
 	if (!spc && parent)
 		spc = parent->GetPhysicsController();
-	
-	m_pHitObject = NULL;
-	if (propName)
-		m_testPropName = propName;
-	else
-		m_testPropName.SetLength(0);
-	KX_RayCast::Callback<KX_GameObject> callback(this,spc);
-	KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
-	if (m_pHitObject)
-		return m_pHitObject->GetProxy();
+	RayCastData rayData(propName, false, (1 << OB_MAX_COL_MASKS) - 1);
+	KX_RayCast::Callback<KX_GameObject, RayCastData> callback(this, spc, &rayData);
+	if (KX_RayCast::RayTest(pe, fromPoint, toPoint, callback))
+		return rayData.m_hitObject->GetProxy();
 	
 	Py_RETURN_NONE;
 }
@@ -3713,7 +3722,7 @@ static PyObject *none_tuple_5()
 }
 
 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
-				   "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) or 4-tuple (object,hit,normal,polygon,hituv) of contact point with object within dist that matches prop.\n"
+				   "rayCast(to,from,dist,prop,face,xray,poly,mask): cast a ray and return 3-tuple (object,hit,normal) or 4-tup

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list