mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
Python callback for collision filtering
This commit is contained in:
parent
d280ad2a81
commit
48b3b4dc55
@ -52,6 +52,10 @@ INLINE BulletWorld::
|
|||||||
delete _configuration;
|
delete _configuration;
|
||||||
delete _dispatcher;
|
delete _dispatcher;
|
||||||
delete _broadphase;
|
delete _broadphase;
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
Py_XDECREF(_filter_cb3._python_callback);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -19,6 +19,14 @@
|
|||||||
|
|
||||||
#include "collideMask.h"
|
#include "collideMask.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
#include "py_panda.h"
|
||||||
|
#include "typedReferenceCount.h"
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_PandaNode;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define clamp(x, x_min, x_max) max(min(x, x_max), x_min)
|
#define clamp(x, x_min, x_max) max(min(x, x_max), x_min)
|
||||||
|
|
||||||
TypeHandle BulletWorld::_type_handle;
|
TypeHandle BulletWorld::_type_handle;
|
||||||
@ -105,6 +113,9 @@ BulletWorld() {
|
|||||||
case FA_groups_mask:
|
case FA_groups_mask:
|
||||||
_world->getPairCache()->setOverlapFilterCallback(&_filter_cb2);
|
_world->getPairCache()->setOverlapFilterCallback(&_filter_cb2);
|
||||||
break;
|
break;
|
||||||
|
case FA_python_callback:
|
||||||
|
_world->getPairCache()->setOverlapFilterCallback(&_filter_cb3);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
bullet_cat.error() << "no proper filter algorithm!" << endl;
|
bullet_cat.error() << "no proper filter algorithm!" << endl;
|
||||||
}
|
}
|
||||||
@ -748,27 +759,8 @@ get_collision_object(PandaNode *node) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BulletWorld::clean_manifolds_for_node
|
// Function: BulletWorld::set_group_collision_flag
|
||||||
// Access: Public
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void BulletWorld::
|
|
||||||
clean_manifolds_for_node(PandaNode *node) {
|
|
||||||
|
|
||||||
btCollisionObject *object = get_collision_object(node);
|
|
||||||
if (object) {
|
|
||||||
btBroadphaseProxy* proxy = object->getBroadphaseHandle();
|
|
||||||
if (proxy) {
|
|
||||||
_world->getPairCache()->cleanProxyFromPairs(proxy, _dispatcher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: BulletWorld::get_collision_object
|
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -794,6 +786,31 @@ get_group_collision_flag(unsigned int group1, unsigned int group2) const {
|
|||||||
return _filter_cb2._collide[group1].get_bit(group2);
|
return _filter_cb2._collide[group1].get_bit(group2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BulletWorld::set_python_filter_callback
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void BulletWorld::
|
||||||
|
set_python_filter_callback(PyObject *callback) {
|
||||||
|
|
||||||
|
nassertv(callback != NULL);
|
||||||
|
|
||||||
|
if (!PyCallable_Check(callback)) {
|
||||||
|
PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bullet_filter_algorithm != FA_python_callback) {
|
||||||
|
bullet_cat.warning() << "filter algorithm is not 'python-callback'" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
_filter_cb3._python_callback = callback;
|
||||||
|
Py_XINCREF(_filter_cb3._python_callback);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BulletWorld::FilterCallback1::needBroadphaseCollision
|
// Function: BulletWorld::FilterCallback1::needBroadphaseCollision
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -853,6 +870,61 @@ needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) co
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BulletWorld::FilterCallback3::needBroadphaseCollision
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool BulletWorld::btFilterCallback3::
|
||||||
|
needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const {
|
||||||
|
|
||||||
|
nassertr(_python_callback, false);
|
||||||
|
|
||||||
|
btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject;
|
||||||
|
btCollisionObject *obj1 = (btCollisionObject *) proxy1->m_clientObject;
|
||||||
|
|
||||||
|
nassertr(obj0, false);
|
||||||
|
nassertr(obj1, false);
|
||||||
|
|
||||||
|
PandaNode *node0 = (PandaNode *) obj0->getUserPointer();
|
||||||
|
PandaNode *node1 = (PandaNode *) obj1->getUserPointer();
|
||||||
|
|
||||||
|
nassertr(node0, false);
|
||||||
|
nassertr(node1, false);
|
||||||
|
|
||||||
|
PyObject *p0 = DTool_CreatePyInstanceTyped(node0, Dtool_PandaNode, true, false, node0->get_type_index());
|
||||||
|
PyObject *p1 = DTool_CreatePyInstanceTyped(node1, Dtool_PandaNode, true, false, node1->get_type_index());
|
||||||
|
|
||||||
|
PyObject *result = PyEval_CallFunction(_python_callback, "OO", p0, p1);
|
||||||
|
|
||||||
|
bool collide = false;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
bullet_cat.error() << "An error occurred while calling python function!" << endl;
|
||||||
|
PyErr_Print();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int v = PyObject_IsTrue(result);
|
||||||
|
if (v == 1) {
|
||||||
|
collide = true;
|
||||||
|
}
|
||||||
|
else if (v == 0) {
|
||||||
|
collide = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bullet_cat.error() << "Python callback function must return a bool object" << endl;
|
||||||
|
}
|
||||||
|
Py_DECREF(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_XDECREF(p0);
|
||||||
|
//Py_XDECREF(p1);
|
||||||
|
|
||||||
|
return collide;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BulletWorld::BroadphaseAlgorithm ostream operator
|
// Function: BulletWorld::BroadphaseAlgorithm ostream operator
|
||||||
// Description:
|
// Description:
|
||||||
@ -908,8 +980,12 @@ operator << (ostream &out, BulletWorld::FilterAlgorithm algorithm) {
|
|||||||
|
|
||||||
case BulletWorld::FA_groups_mask:
|
case BulletWorld::FA_groups_mask:
|
||||||
return out << "groups-mask";
|
return out << "groups-mask";
|
||||||
};
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
case BulletWorld::FA_python_callback:
|
||||||
|
return out << "python-callback";
|
||||||
|
#endif
|
||||||
|
};
|
||||||
return out << "**invalid BulletWorld::FilterAlgorithm(" << (int)algorithm << ")**";
|
return out << "**invalid BulletWorld::FilterAlgorithm(" << (int)algorithm << ")**";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -928,6 +1004,11 @@ operator >> (istream &in, BulletWorld::FilterAlgorithm &algorithm) {
|
|||||||
else if (word == "groups-mask") {
|
else if (word == "groups-mask") {
|
||||||
algorithm = BulletWorld::FA_groups_mask;
|
algorithm = BulletWorld::FA_groups_mask;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
else if (word == "python-callback") {
|
||||||
|
algorithm = BulletWorld::FA_python_callback;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else {
|
else {
|
||||||
bullet_cat.error()
|
bullet_cat.error()
|
||||||
<< "Invalid BulletWorld::FilterAlgorithm: " << word << "\n";
|
<< "Invalid BulletWorld::FilterAlgorithm: " << word << "\n";
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
#include "collideMask.h"
|
#include "collideMask.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
#include "py_panda.h"
|
||||||
|
#include "Python.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class BulletPersistentManifold;
|
class BulletPersistentManifold;
|
||||||
class BulletShape;
|
class BulletShape;
|
||||||
class BulletSoftBodyWorldInfo;
|
class BulletSoftBodyWorldInfo;
|
||||||
@ -150,8 +155,15 @@ PUBLISHED:
|
|||||||
enum FilterAlgorithm {
|
enum FilterAlgorithm {
|
||||||
FA_mask,
|
FA_mask,
|
||||||
FA_groups_mask,
|
FA_groups_mask,
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
FA_python_callback,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
void set_python_filter_callback(PyObject *callback);
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static btCollisionObject *get_collision_object(PandaNode *node);
|
static btCollisionObject *get_collision_object(PandaNode *node);
|
||||||
|
|
||||||
@ -190,6 +202,16 @@ private:
|
|||||||
CollideMask _collide[32];
|
CollideMask _collide[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
struct btFilterCallback3 : public btOverlapFilterCallback {
|
||||||
|
virtual bool needBroadphaseCollision(
|
||||||
|
btBroadphaseProxy* proxy0,
|
||||||
|
btBroadphaseProxy* proxy1) const;
|
||||||
|
|
||||||
|
PyObject *_python_callback;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
btBroadphaseInterface *_broadphase;
|
btBroadphaseInterface *_broadphase;
|
||||||
btCollisionConfiguration *_configuration;
|
btCollisionConfiguration *_configuration;
|
||||||
btCollisionDispatcher *_dispatcher;
|
btCollisionDispatcher *_dispatcher;
|
||||||
@ -201,6 +223,10 @@ private:
|
|||||||
btFilterCallback1 _filter_cb1;
|
btFilterCallback1 _filter_cb1;
|
||||||
btFilterCallback2 _filter_cb2;
|
btFilterCallback2 _filter_cb2;
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
btFilterCallback3 _filter_cb3;
|
||||||
|
#endif
|
||||||
|
|
||||||
btSoftBodyWorldInfo _info;
|
btSoftBodyWorldInfo _info;
|
||||||
|
|
||||||
PT(BulletDebugNode) _debug;
|
PT(BulletDebugNode) _debug;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user