Page MenuHome

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

Authored by Porteries Tristan (panzergame) on Apr 15 2015, 3:39 PM.

Details

Summary

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 :


left mouse click on two planes and see console messages.

Somewhat more elaborate test file by @Sybren A. Stüvel (sybren):


Look around and click on the cubes. One cube lamp responds, the other doesn't, based on their collision groups.

Diff Detail

Repository
rB Blender
Branch
ge_ray_cast_mask_filter

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
source/gameengine/Ketsji/KX_GameObject.cpp
3739

But, "between 1 and 65535" means 1 < x < 65355, so it's required to state 0 and SHORT_MAX + 1 as the limits (meaning x lies between those values, NOT including)!
:)

Fix mask check range and message

doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
854

Test is now correct but I think between 0 and 65536 will confuse the most users. I think the will try to set 0 or 65536 and will get an error.
I think with min value 1 and max value 65535 is better here.
But I am no native English speaker I leave this to agoose77.

source/gameengine/Ketsji/KX_ConstraintActuator.h
118–122

KX_ClientObjectInfo *

source/gameengine/Ketsji/KX_GameObject.cpp
2362

I think that sentence will confuse the most users. Maybe we should change it to.
bit field min value 1 and max value %i", USHRT_MAX)

2387

same as above.

3739

Same as for the other comment.

3793

Same as for the other error messages.

source/gameengine/Ketsji/KX_GameObject.h
670–673

KX_ClientObjectInfo *client

source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
201

KX_ClientObjectInfo *client

source/gameengine/Ketsji/KX_MouseFocusSensor.h
95–98

KX_ClientObjectInfo *client

source/gameengine/Ketsji/KX_RaySensor.h
79–82

KX_ClientObjectInfo *client

Fix message renage error + asterix

Angus Hollands (agoose77) accepted this revision.

Nice work, looks good to me.

This revision is now accepted and ready to land.Jun 18 2015, 1:35 AM
Sybren A. Stüvel (sybren) added inline comments.
doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
854

This mask needs more explanation. It's not enough to know that it's a bit field. What is it compared with? Can every object have a custom collision mask? Or are the bits compared to layer numbers? This should be documented.

source/gameengine/Ketsji/KX_ConstraintActuator.h
118–122

What is data? Everything could be called "data", so the name itself doesn't hold any information, so should be clarified with a comment.

source/gameengine/Ketsji/KX_GameObject.cpp
2361–2362

The code rejects 0, but the error message allows 0.

2362

Why not simply write "0 < collisionGroup <= %i" ? A bit of mathematical notation goes a long way in making things clear.

3611

Why is there a need to perform such a pointer cast? Why not simply pass a RayCastData * directly? Some comments about this (probably in the header file) might be useful.

source/gameengine/Ketsji/KX_ConstraintActuator.h
118–122

"data" is some extra arguments for this function. do you have a better name ? extraargs/args ?

source/gameengine/Ketsji/KX_GameObject.cpp
3611

The argument data is extra arguments so no special type, depends on the user. The struct RayCastData is only for the extra argument needed by KX_GameObject not byy KX_RaySensor…

source/gameengine/Ketsji/KX_ConstraintActuator.h
118–122

Right now things are confusing. Further down, you use a cast to a certain type, implying that the data type is actually fixed. However, in this explanation you seem to imply that the data type is up to the user, and thus not fixed. Which one is it?

source/gameengine/Ketsji/KX_GameObject.cpp
3611

So does that mean that the cast can fail because there is other data passed in there? If so, use dynamic_cast instead, and do a runtime check. Otherwise a static_cast + good documentation is preferred.

Porteries Tristan (panzergame) marked 8 inline comments as done.Jun 18 2015, 5:27 PM
Porteries Tristan (panzergame) updated this revision to Diff 4447.
  • Fix mask out of range error message.
  • Add more complete documentation for mask argument.
  • Add documentation for data arg of NeedRayCast and RayHit
source/gameengine/Ketsji/KX_ConstraintActuator.h
118–122

see KX_RayCast.data doc and KX_GameObject.RayCastData

Sybren A. Stüvel (sybren) requested changes to this revision.
Sybren A. Stüvel (sybren) added inline comments.
source/gameengine/Ketsji/KX_GameObject.cpp
3608

I still don't understand why this is a void * when your code will crash (or worse: be unpredictably wrong) if a non-RayCastData pointer is given.

This revision now requires changes to proceed.Jun 18 2015, 5:42 PM
source/gameengine/Ketsji/KX_GameObject.cpp
3608

It's like client pointer, we don't know the type it depends… so we use a void *. The data argument is a temporary instance create only for the ray cast. in the case of KX_GameObject KX_GameObject::RayCastData is used only two time : in KX_GaleObject::NeedRayCast and in KX_Gameobject::RayHit. But there no reason to use the same think for RAS_Rasterizer::RayHit or KX_RaySensor::RayHit, these classes can use their own temporary ray cast extra info type. There no common point for this argument so an inheritance will be useless.
This behaviour was already implemented for RayHit but not for NeedRayCast so i just extend it (it should be for both functions already).

I have been wanting this for 3rd person actor controls for some time :D

Porteries Tristan (panzergame) updated this revision to Diff 4595.

Use template for data argument. Now to create the ray callback we must pass the data argument type like : KX_RayCast::Callback<UserClass, DataClass>(user, …).

Porteries Tristan (panzergame) updated this revision to Diff 4605.

Add doxygen link, and doc for NeedRayCast in KX_RayCast.h

source/gameengine/Ketsji/KX_GameObject.h
671

bool RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, RayCastData *rayData);

source/gameengine/Ketsji/KX_RayCast.h
116

Callback(T *_self, PHY_IPhysicsController *controller = NULL, dataT *_data = NULL, bool faceNormal = false, bool faceUV = false)

Sergey Sharybin (sergey) added inline comments.
source/gameengine/Ketsji/KX_ConstraintActuator.h
118–123

If it's always expecting to pass RayCastData then it makes sense to get rid of void* and use proper struct name in the declarations.

Campbell Barton (campbellbarton) requested changes to this revision.
Campbell Barton (campbellbarton) added inline comments.
source/gameengine/Ketsji/KX_GameObject.cpp
3792

Nicer to use define:

if ((mask == 0) || (mask & ~((1 << OB_MAX_COL_MASKS) - 1))) {
    ....
}
This revision now requires changes to proceed.Jul 8 2015, 9:55 AM
Porteries Tristan (panzergame) updated this revision to Diff 4610.

Use OB_MAX_COL_MASKS macro, fix * place.

source/gameengine/Ketsji/KX_ConstraintActuator.h
118–123

For raycast function in KX_ConstraintActuator we don't use the data argument so it's a void*.

Porteries Tristan (panzergame) updated this revision to Diff 4611.

use OB_MAX_COL_MASKS for collisionMask/Group attributs.

source/gameengine/Ketsji/KX_GameObject.cpp
2361–2362

val > ((1 << OB_MAX_COL_MASKS) - 1)) isnt normal logic here...

Typically you want to check "are any bits set besides OB_MAX_COL_MASKS"

So for that the check is: val & ~((1 << OB_MAX_COL_MASKS) - 1))

so you just want to check at least one bit is set, and that all bits are from 1-16

so...

if ((val == 0) || (val & ~((1 << OB_MAX_COL_MASKS) - 1))))

Use operator & ~ instead of >

source/gameengine/Ketsji/KX_GameObject.cpp
2387

Would add (), if ((val == 0) || (val & ~((1 << OB_MAX_COL_MASKS) - 1))) {

otherwise fine.

KX_GameObject::NeedRayCast takes a RayCastData *data, whereas other NeedRayCast methods take a void *const data. I can make a guess that RayCastData is only relevant in KX_GameObject, and thus a void * is enough in the other cases. Is this correct? How free are people in the void * case to pass other types?

Secondly, why is one a *const and the other not?

source/gameengine/Ketsji/KX_ConstraintActuator.h
118–123

I aree with Sergey; the type of a parameter doesn't depend on whether the parameter is used or not. It depends on the type of the data when it is used.

Porteries Tristan (panzergame) marked 2 inline comments as done.EditedSep 12 2015, 10:38 PM
Porteries Tristan (panzergame) updated this revision to Diff 5060.
  • Replace data pointer by double pointer in rasterizer RayHit function. Use UNUSED macro for case where void *data is unused.
Campbell Barton (campbellbarton) accepted this revision.

LGTM

source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
1218

Shouldn't this be a const double * ?

Porteries Tristan (panzergame) updated this revision to Diff 5083.
  • Fix type* name to type *name
doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
854

The 0 < mask < 65536 part of the comment seems odd. You could just note that its an int where 16 bits are used for layers.

doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
854

There are still some things that could be described clearer. Mentioning "(16 layers)" just after the word "scene" could suggest that you're talking about scene layers. Furthermore, "a category of objects" is vague, and you don't explicitly describe how the mask is applied. I would write something like this:

"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 collision_group & mask is true can be hit."

  • Fix python rayCast mask argument description.
  • Add markup around collisionGroup & mask
This revision is now accepted and ready to land.Oct 7 2015, 12:04 PM

I can't wait to test it out :D