Page MenuHome

BGE: get all contact points in collision callback
AbandonedPublic

Authored by Porteries Tristan (panzergame) on May 20 2015, 8:43 AM.

Details

Summary

Previously we only return the first point in the collision callback, now we return a python proxy (KX_CollisionContactPoints) which contains a
variable for the number of point (KX_CollisionContactPoints.numPoints) and return some contact point info :

KX_CollisionContactPointList.getContactPoint(index)

return a KX_CollisionContactPoint :

KX_CollisionContactPoint.localPointA
KX_CollisionContactPoint.localPointB
KX_CollisionContactPoint.worldPoint
KX_CollisionContactPoint.normal
KX_CollisionContactPoint.combinedFriction
KX_CollisionContactPoint.combinedRestitution
KX_CollisionContactPoint.appliedImpulse

example :

def onCollision(other, pointList):
    for i in range(pointList.numPoints):
        point = pointList.getContactPoint(i)
        print(point.localPointA, point.localPointB, point.worldPoint, point.normal, point.appliedImpulse)

obj.collisionCallbacks = [onCollision]

depends of D1363.

Diff Detail

Repository
rB Blender
Branch
ge_contact_point

Event Timeline

source/gameengine/Physics/common/PHY_DynamicTypes.h
38–39

Im' not sure about that, i think that an overide of getter is better like in PHY_IPhysicsController.

Thomas Szepe (hg1) requested changes to this revision.May 20 2015, 9:37 PM
Thomas Szepe (hg1) edited edge metadata.

Only style check.

Documentation changes are missing.

source/gameengine/Ketsji/KX_CollisionContactPoints.cpp
58

{ return NULL;} --> { return NULL; }

101

KX_CollisionContactPoints *self

110

Space missing if (!PyArg_ParseTuple(args, "i|i:getContactPoint", &index, &mode)) {

source/gameengine/Ketsji/KX_CollisionContactPoints.h
29

KX_CollisionContactPoints.h

38

I think the code block need to be indented here.

47

Only two forward slashes.

64

STR_String &GetName();

This revision now requires changes to proceed.May 20 2015, 9:37 PM
Porteries Tristan (panzergame) edited edge metadata.
  • Change the python API know we return a python class for a point to optimize conversion and improve usage.
  • Better way for PHY_CollData, know this struct is a class and overide by CcdCollData which contains a pointer to the Bullet point list.
for i in range(pointList.numPoints):
    point = pointList.getContactPoint(i)

This is rather un-Pythonic. Why use a range object and an explicit index? It's much more flexible to use generators here, and likely also more efficient. James Powell explains it really well in his talk Generators will free your mind.

Encapsulating the collision information into its own class is a good approach though.

EDIT: Maybe we shouldn't call them "points". A "point" is just a point in 3D space, and a "collision point object" contains much more information. IMO collisions would be a better name than pointList.

I agree

for i in range(pointList.numPoints):
    point = pointList.getContactPoint(i)

This is rather un-Pythonic. Why use a range object and an explicit index? It's much more flexible to use generators here, and likely also more efficient. James Powell explains it really well in his talk Generators will free your mind.

Encapsulating the collision information into its own class is a good approach though.

EDIT: Maybe we shouldn't call them "points". A "point" is just a point in 3D space, and a "collision point object" contains much more information. IMO collisions would be a better name than pointList.

As Sybren says, we really do not want to reintroduce a get/set API. Using a generator is likely the best idea, given that the number of contact points generated will be quite large, and only a subset are likely to be read by the user (especially if they're only provided via the callback API).

Comment inline, otherwise I further agree with sybren. Good work, though, Tristan.

source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
2295

Not sure why you need to allocate on the heap for this, just pass the manifold.

source/gameengine/Ketsji/KX_CollisionContactPoints.h
47

3 slashes is for doxygen doc like "/**"

source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
2295

Before it was a normal variable and we copied it after to a pointer. So to avoid copy we use directly pointer.

Defining KX_CollisionContactPoint seems a heavy weight option.

  • Why not just return a list/tuple of vectors?
  • Did you measure the speed cost of using a PyList?
  • Are there many cases you would only want to read a subset of the points?

Maybe am wrong, but suspect in practice - just getting a list of vectors may be OK.

I think that it's better to return a python proxy with getter instead of a tuple because we don't spend time to convert all elements and in this case we can use a lot of variables.

@Porteries Tristan (panzergame), What are the chances you would want to access only a small subset of contact points?

In my implementation (crowd simulation system) I only used the first contact point, which worked fine. I think that typically you'd use either zero, one, or all points (I don't see the use in using the first half, for example).

Has anyone solved the getImpulse issue for a callback?

with contact point ->localized to part forces in line with a object can have less damage then forces out of line with a axis,

example -> walking ragdoll falls lands on feet -> dont trigger 'Slack mode'

walking ragdoll is running and kicks a stair front -> Trip ragdoll

My method for generating a impulse does not take into account 2 equal and opposite forces

(own.worldLinV @ end oflast frame vs own.worldLinV on collision)

(getting squished between two cars still kills you)

Porteries Tristan (panzergame) edited edge metadata.

Support python generator.

Campbell Barton (campbellbarton) requested changes to this revision.Jul 6 2015, 7:46 AM
Campbell Barton (campbellbarton) edited edge metadata.

I find this patch quite confusing.

Firstly, I'm not sure how this is even a generator... in Python a generator looks like this.

http://anandology.com/python-practice-book/iterators.html#generators

(a function that yields a value, there are generator expressions too...)

A generator is a way to build iterators, see:
https://wiki.python.org/moin/Generators

From what I can see this is simply an array wrapper, since the list size is known of time and it allows index access (unlike generators). and this is simply a way to access the list...

How is this different from a CListValue?

This revision now requires changes to proceed.Jul 6 2015, 7:46 AM
From what I can see this is simply an array wrapper, since the list size is known of time and it allows index access (unlike generators). and this is simply a way to access the list...

tp_as_mapping is defined so python can create a basic generator on.

How is this different from a CListValue?

As i already said : CListValue required CValue items, in the case of contact point we can have 100 points, but convert all points to a CValue type will be too slow. So we convert the point only when access.

So the main difference is the type that it stores?

In this case it seems like this is more like a Python specific list type, where the parent class only defines basic access functions.

Its not a generator, its a wrapper getitem/setitem access.

rename CPythonGenerator to CPythonListWrapper seems good to you ?