Browse Source

extension functions for ODE classes

rdb 11 years ago
parent
commit
3b1e193abb

+ 26 - 0
panda/src/ode/odeBody_ext.I

@@ -0,0 +1,26 @@
+// Filename: odeBody_ext.I
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "odeJoint_ext.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeBody::get_converted_joint
+//       Access: Published
+//  Description: Equivalent to get_joint().convert()
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *Extension<OdeBody>::
+get_converted_joint(int i) const {
+  OdeJoint j = _this->get_joint(i);
+  return invoke_extension(&j).convert();
+}

+ 43 - 0
panda/src/ode/odeBody_ext.h

@@ -0,0 +1,43 @@
+// Filename: odeBody_ext.h
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ODEBODY_EXT_H
+#define ODEBODY_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "config_ode.h"
+#include "odeBody.h"
+#include "extension.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<OdeBody>
+// Description : This class defines the extension methods for
+//               NodePathCollection, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<OdeBody> : public ExtensionBase<OdeBody> {
+public:
+  INLINE PyObject *get_converted_joint(int i) const;
+};
+
+#include "odeBody_ext.I"
+
+#endif  // HAVE_PYTHON
+
+#endif  // ODEBODY_EXT_H

+ 47 - 0
panda/src/ode/odeGeom_ext.I

@@ -0,0 +1,47 @@
+// Filename: odeGeom_ext.I
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "odeSpace_ext.h"
+#include "lpoint3.h"
+
+#ifndef CPPPARSER
+IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeGeom::get_AA_bounds
+//       Access: Published
+//  Description: A more Pythonic way of calling getAABB()
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *Extension<OdeGeom>::
+get_AA_bounds() const {
+  LPoint3f *min_point = new LPoint3f;
+  LPoint3f *max_point = new LPoint3f;
+  _this->get_AABB(*min_point, *max_point);
+
+  PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false);
+  PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false);
+  return Py_BuildValue("NN", min_inst, max_inst);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeGeom::get_converted_space
+//       Access: Published
+//  Description: Equivalent to get_space().convert()
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *Extension<OdeGeom>::
+get_converted_space() const {
+  OdeSpace s = _this->get_space();
+  return invoke_extension(&s).convert();
+}

+ 133 - 0
panda/src/ode/odeGeom_ext.cxx

@@ -0,0 +1,133 @@
+// Filename: odeGeom_ext.cxx
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "odeGeom_ext.h"
+
+#include "odeBoxGeom.h"
+//#include "odeConvexGeom.h"
+#include "odeGeom.h"
+#include "odeHashSpace.h"
+#include "odeCappedCylinderGeom.h"
+//#include "odeHeightfieldGeom.h"
+#include "odePlaneGeom.h"
+#include "odeQuadTreeSpace.h"
+#include "odeRayGeom.h"
+#include "odeSimpleSpace.h"
+#include "odeSpace.h"
+#include "odeSphereGeom.h"
+#include "odeTriMeshGeom.h"
+
+#ifdef HAVE_PYTHON
+
+#ifndef CPPPARSER
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeBoxGeom;
+//extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeConvexGeom;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeGeom;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHashSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeCappedCylinderGeom;
+//extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHeightfieldGeom;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdePlaneGeom;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeQuadTreeSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeRayGeom;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSimpleSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSphereGeom;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeTriMeshGeom;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeGeom::convert
+//       Access: Published
+//  Description: Do a sort of pseudo-downcast on this space in
+//               order to expose its specialized functions.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<OdeGeom>::
+convert() const {
+  Dtool_PyTypedObject *class_type;
+  TypedObject *geom;
+
+  switch (_this->get_class()) {
+  case OdeGeom::GC_sphere:
+    geom = new OdeSphereGeom(_this->get_id());
+    class_type = &Dtool_OdeSphereGeom;
+    break;
+
+  case OdeGeom::GC_box:
+    geom = new OdeBoxGeom(_this->get_id());
+    class_type = &Dtool_OdeBoxGeom;
+    break;
+
+  case OdeGeom::GC_capped_cylinder:
+    geom = new OdeCappedCylinderGeom(_this->get_id());
+    class_type = &Dtool_OdeCappedCylinderGeom;
+    break;
+
+  case OdeGeom::GC_plane:
+    geom = new OdePlaneGeom(_this->get_id());
+    class_type = &Dtool_OdePlaneGeom;
+    break;
+
+  case OdeGeom::GC_ray:
+    geom = new OdeRayGeom(_this->get_id());
+    class_type = &Dtool_OdeRayGeom;
+    break;
+
+  //case OdeGeom::GC_convex:
+  //  geom = new OdeConvexGeom(_this->get_id());
+  //  class_type = &Dtool_OdeConvexGeom;
+  //  break;
+
+  case OdeGeom::GC_tri_mesh:
+    geom = new OdeTriMeshGeom(_this->get_id());
+    class_type = &Dtool_OdeTriMeshGeom;
+    break;
+
+  //case OdeGeom::GC_heightfield:
+  //  geom = new OdeHeightfieldGeom(_this->get_id());
+  //  class_type = &Dtool_OdeHeightfieldGeom;
+  //  break;
+
+  case OdeGeom::GC_simple_space:
+    geom = new OdeSimpleSpace((dSpaceID) _this->get_id());
+    class_type = &Dtool_OdeSimpleSpace;
+    break;
+
+  case OdeGeom::GC_hash_space:
+    geom = new OdeHashSpace((dSpaceID) _this->get_id());
+    class_type = &Dtool_OdeHashSpace;
+    break;
+
+  case OdeGeom::GC_quad_tree_space:
+    geom = new OdeQuadTreeSpace((dSpaceID) _this->get_id());
+    class_type = &Dtool_OdeQuadTreeSpace;
+    break;
+
+  default:
+    // This shouldn't happen, but if it does, we
+    // should just return a regular OdeGeom or OdeSpace.
+    if (_this->is_space()) {
+      geom = new OdeSpace((dSpaceID) _this->get_id());
+      class_type = &Dtool_OdeSpace;
+
+    } else {
+      geom = new OdeGeom(_this->get_id());
+      class_type = &Dtool_OdeGeom;
+    }
+  }
+
+  return DTool_CreatePyInstanceTyped((void *)geom, *class_type,
+                                     true, false, geom->get_type_index());
+}
+
+#endif  // HAVE_PYTHON

+ 46 - 0
panda/src/ode/odeGeom_ext.h

@@ -0,0 +1,46 @@
+// Filename: odeGeom_ext.h
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ODEGEOM_EXT_H
+#define ODEGEOM_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "config_ode.h"
+#include "odeGeom.h"
+#include "extension.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<OdeGeom>
+// Description : This class defines the extension methods for
+//               NodePathCollection, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<OdeGeom> : public ExtensionBase<OdeGeom> {
+public:
+  INLINE PyObject *get_AA_bounds() const;
+
+  PyObject *convert() const;
+  INLINE PyObject *get_converted_space() const;
+};
+
+#include "odeGeom_ext.I"
+
+#endif  // HAVE_PYTHON
+
+#endif  // ODEGEOM_EXT_H

+ 144 - 0
panda/src/ode/odeJoint_ext.cxx

@@ -0,0 +1,144 @@
+// Filename: odeJoint_ext.cxx
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "odeJoint_ext.h"
+
+#ifdef HAVE_PYTHON
+
+#include "odeJoint.h"
+#include "odeBallJoint.h"
+#include "odeHingeJoint.h"
+#include "odeSliderJoint.h"
+#include "odeContactJoint.h"
+#include "odeUniversalJoint.h"
+#include "odeHinge2Joint.h"
+#include "odeFixedJoint.h"
+#include "odeNullJoint.h"
+#include "odeAMotorJoint.h"
+#include "odeLMotorJoint.h"
+#include "odePlane2dJoint.h"
+
+#ifndef CPPPARSER
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeBallJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHingeJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSliderJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeContactJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeUniversalJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHinge2Joint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeFixedJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeNullJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeAMotorJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeLMotorJoint;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdePlane2dJoint;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeJoint::attach
+//       Access: Published
+//  Description: Attach two bodies together.  If either body is None,
+//               the other will be attached to the environment.
+////////////////////////////////////////////////////////////////////
+void Extension<OdeJoint>::
+attach(const OdeBody *body1, const OdeBody *body2) {
+  if (body1 && body2) {
+    _this->attach_bodies(*body1, *body2);
+
+  } else if (body1 && !body2) {
+    _this->attach_body(*body1, 0);
+
+  } else if (!body1 && body2) {
+    _this->attach_body(*body2, 1);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeJoint::convert
+//       Access: Published
+//  Description: Do a sort of pseudo-downcast on this space in
+//               order to expose its specialized functions.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<OdeJoint>::
+convert() const {
+  Dtool_PyTypedObject *class_type;
+  OdeJoint *joint;
+
+  switch (_this->get_joint_type()) {
+  case OdeJoint::JT_ball:
+    joint = new OdeBallJoint(_this->get_id());
+    class_type = &Dtool_OdeBallJoint;
+    break;
+
+  case OdeJoint::JT_hinge:
+    joint = new OdeHingeJoint(_this->get_id());
+    class_type = &Dtool_OdeHingeJoint;
+    break;
+
+  case OdeJoint::JT_slider:
+    joint = new OdeSliderJoint(_this->get_id());
+    class_type = &Dtool_OdeSliderJoint;
+    break;
+
+  case OdeJoint::JT_contact:
+    joint = new OdeContactJoint(_this->get_id());
+    class_type = &Dtool_OdeContactJoint;
+    break;
+
+  case OdeJoint::JT_universal:
+    joint = new OdeUniversalJoint(_this->get_id());
+    class_type = &Dtool_OdeUniversalJoint;
+    break;
+
+  case OdeJoint::JT_hinge2:
+    joint = new OdeHinge2Joint(_this->get_id());
+    class_type = &Dtool_OdeHinge2Joint;
+    break;
+
+  case OdeJoint::JT_fixed:
+    joint = new OdeFixedJoint(_this->get_id());
+    class_type = &Dtool_OdeFixedJoint;
+    break;
+
+  case OdeJoint::JT_null:
+    joint = new OdeNullJoint(_this->get_id());
+    class_type = &Dtool_OdeNullJoint;
+    break;
+
+  case OdeJoint::JT_a_motor:
+    joint = new OdeAMotorJoint(_this->get_id());
+    class_type = &Dtool_OdeAMotorJoint;
+    break;
+
+  case OdeJoint::JT_l_motor:
+    joint = new OdeLMotorJoint(_this->get_id());
+    class_type = &Dtool_OdeLMotorJoint;
+    break;
+
+  case OdeJoint::JT_plane2d:
+    joint = new OdePlane2dJoint(_this->get_id());
+    class_type = &Dtool_OdePlane2dJoint;
+    break;
+
+  default:
+    // This shouldn't happen, but if it does, we
+    // should just return a regular OdeJoint.
+    joint = new OdeJoint(_this->get_id());
+    class_type = &Dtool_OdeJoint;
+  }
+
+  return DTool_CreatePyInstanceTyped((void *)joint, *class_type,
+                                     true, false, joint->get_type_index());
+}
+
+#endif  // HAVE_PYTHON

+ 43 - 0
panda/src/ode/odeJoint_ext.h

@@ -0,0 +1,43 @@
+// Filename: odeJoint_ext.h
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ODEJOINT_EXT_H
+#define ODEJOINT_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "config_ode.h"
+#include "odeJoint.h"
+#include "extension.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<OdeJoint>
+// Description : This class defines the extension methods for
+//               NodePathCollection, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<OdeJoint> : public ExtensionBase<OdeJoint> {
+public:
+  void attach(const OdeBody *body1, const OdeBody *body2);
+
+  PyObject *convert() const;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // ODEJOINT_EXT_H

+ 58 - 0
panda/src/ode/odeSpace_ext.I

@@ -0,0 +1,58 @@
+// Filename: odeSpace_ext.I
+// Created by:  rdb (11Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+/* okcircular */
+#include "odeGeom_ext.h"
+
+#ifndef CPPPARSER
+IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeSpace::get_AA_bounds
+//       Access: Published
+//  Description: A more Pythonic way of calling getAABB()
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *Extension<OdeSpace>::
+get_AA_bounds() const {
+  LPoint3f *min_point = new LPoint3f;
+  LPoint3f *max_point = new LPoint3f;
+  _this->get_AABB(*min_point, *max_point);
+
+  PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false);
+  PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false);
+  return Py_BuildValue("NN", min_inst, max_inst);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeSpace::get_converted_geom
+//       Access: Published
+//  Description: Equivalent to get_geom(index).convert()
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *Extension<OdeSpace>::
+get_converted_geom(int index) const {
+  OdeGeom g = _this->get_geom(index);
+  return invoke_extension(&g).convert();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeSpace::get_converted_space
+//       Access: Published
+//  Description: Equivalent to get_space().convert()
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *Extension<OdeSpace>::
+get_converted_space() const {
+  OdeSpace s = _this->get_space();
+  return invoke_extension(&s).convert();
+}

+ 112 - 0
panda/src/ode/odeSpace_ext.cxx

@@ -0,0 +1,112 @@
+// Filename: odeSpace_ext.cxx
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "odeSpace_ext.h"
+#include "config_ode.h"
+
+#ifdef HAVE_PYTHON
+
+#include "odeGeom.h"
+#include "odeHashSpace.h"
+#include "odeSimpleSpace.h"
+#include "odeSpace.h"
+#include "odeQuadTreeSpace.h"
+
+#ifndef CPPPARSER
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeHashSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSimpleSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeSpace;
+extern EXPCL_PANDAODE Dtool_PyTypedObject Dtool_OdeQuadTreeSpace;
+#endif
+
+PyObject *Extension<OdeSpace>::_python_callback = NULL;
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeSpace::convert
+//       Access: Published
+//  Description: Do a sort of pseudo-downcast on this space in
+//               order to expose its specialized functions.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<OdeSpace>::
+convert() const {
+  Dtool_PyTypedObject *class_type;
+  OdeSpace *space;
+
+  switch (_this->get_class()) {
+  case OdeGeom::GC_simple_space:
+    space = new OdeSimpleSpace(_this->get_id());
+    class_type = &Dtool_OdeSimpleSpace;
+    break;
+
+  case OdeGeom::GC_hash_space:
+    space = new OdeHashSpace(_this->get_id());
+    class_type = &Dtool_OdeHashSpace;
+    break;
+
+  case OdeGeom::GC_quad_tree_space:
+    space = new OdeQuadTreeSpace(_this->get_id());
+    class_type = &Dtool_OdeQuadTreeSpace;
+    break;
+
+  default:
+    // This shouldn't happen, but if it does, we
+    // should just return a regular OdeSpace.
+    space = new OdeSpace(_this->get_id());
+    class_type = &Dtool_OdeSpace;
+  }
+
+  return DTool_CreatePyInstanceTyped((void *)space, *class_type,
+                                     true, false, space->get_type_index());
+}
+
+int Extension<OdeSpace>::
+collide(PyObject* arg, PyObject* callback) {
+  nassertr(callback != NULL, -1);
+
+  if (!PyCallable_Check(callback)) {
+    PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name);
+    return -1;
+
+  } else if (_this->get_id() == NULL) {
+    // Well, while we're in the mood of python exceptions, let's make this one too.
+    PyErr_Format(PyExc_TypeError, "OdeSpace is not valid!");
+    return -1;
+
+  } else {
+    _python_callback = (PyObject*) callback;
+    Py_XINCREF(_python_callback);
+    dSpaceCollide(_this->get_id(), (void*) arg, &near_callback);
+    Py_XDECREF(_python_callback);
+    return 0;
+  }
+}
+
+void Extension<OdeSpace>::
+near_callback(void *data, dGeomID o1, dGeomID o2) {
+  OdeGeom g1 (o1);
+  OdeGeom g2 (o2);
+  PyObject* p1 = invoke_extension(&g1).convert();
+  PyObject* p2 = invoke_extension(&g2).convert();
+  PyObject *result = PyObject_CallFunctionObjArgs(_python_callback, (PyObject*) data, p1, p2, NULL);
+  if (!result) {
+    odespace_cat.error() << "An error occurred while calling python function!\n";
+    PyErr_Print();
+  } else {
+    Py_DECREF(result);
+  }
+  Py_XDECREF(p2);
+  Py_XDECREF(p1);
+}
+
+#endif  // HAVE_PYTHON

+ 54 - 0
panda/src/ode/odeSpace_ext.h

@@ -0,0 +1,54 @@
+// Filename: odeSpace_ext.h
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ODESPACE_EXT_H
+#define ODESPACE_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "config_ode.h"
+#include "odeSpace.h"
+#include "extension.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<OdeSpace>
+// Description : This class defines the extension methods for
+//               NodePathCollection, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<OdeSpace> : public ExtensionBase<OdeSpace> {
+public:
+  INLINE PyObject *get_AA_bounds() const;
+
+  PyObject *convert() const;
+  INLINE PyObject *get_converted_geom(int index) const;
+  INLINE PyObject *get_converted_space() const;
+
+  int collide(PyObject* arg, PyObject* near_callback);
+
+private:
+  static void near_callback(void*, dGeomID, dGeomID);
+
+  static PyObject *_python_callback;
+};
+
+#include "odeSpace_ext.I"
+
+#endif  // HAVE_PYTHON
+
+#endif  // ODESPACE_EXT_H

+ 66 - 0
panda/src/ode/odeUtil_ext.cxx

@@ -0,0 +1,66 @@
+// Filename: odeUtil_ext.cxx
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "odeUtil_ext.h"
+#include "config_ode.h"
+#include "odeGeom.h"
+#include "odeGeom_ext.h"
+
+#ifdef HAVE_PYTHON
+
+PyObject *Extension<OdeUtil>::_python_callback = NULL;
+
+////////////////////////////////////////////////////////////////////
+//     Function: OdeUtil::collide2
+//       Access: Public, Static
+//  Description: Calls the callback for all potentially intersecting
+//               pairs that contain one geom from geom1 and one geom
+//               from geom2.
+////////////////////////////////////////////////////////////////////
+int Extension<OdeUtil>::
+collide2(const OdeGeom &geom1, const OdeGeom &geom2, PyObject* arg, PyObject* callback) {
+  nassertr(callback != NULL, -1);
+  if (!PyCallable_Check(callback)) {
+    PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name);
+    return -1;
+  } else {
+    _python_callback = (PyObject*) callback;
+    Py_XINCREF(_python_callback);
+    dSpaceCollide2(geom1.get_id(), geom2.get_id(), (void*) arg, &near_callback);
+    Py_XDECREF(_python_callback);
+    return 0;
+  }
+}
+
+void Extension<OdeUtil>::
+near_callback(void *data, dGeomID o1, dGeomID o2) {
+  if (ode_cat.is_spam()) {
+    ode_cat.spam()
+      << "near_callback called, data: " << data << ", dGeomID1: " << o1 << ", dGeomID2: " << o2 << "\n";
+  }
+
+  OdeGeom g1 (o1);
+  OdeGeom g2 (o2);
+  PyObject* p1 = invoke_extension(&g1).convert();
+  PyObject* p2 = invoke_extension(&g2).convert();
+  PyObject* result = PyObject_CallFunctionObjArgs(_python_callback, (PyObject*) data, p1, p2, NULL);
+  if (!result) {
+    ode_cat.error() << "An error occurred while calling python function!\n";
+    PyErr_Print();
+  }
+  Py_XDECREF(p1);
+  Py_XDECREF(p2);
+}
+
+#endif  // HAVE_PYTHON

+ 47 - 0
panda/src/ode/odeUtil_ext.h

@@ -0,0 +1,47 @@
+// Filename: odeUtil_ext.h
+// Created by:  rdb (10Dec13)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ODEUTIL_EXT_H
+#define ODEUTIL_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "config_ode.h"
+#include "odeUtil.h"
+#include "extension.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<OdeUtil>
+// Description : This class defines the extension methods for
+//               NodePathCollection, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<OdeUtil> : public ExtensionBase<OdeUtil> {
+public:
+  static int collide2(const OdeGeom &geom1, const OdeGeom &geom2,
+                      PyObject* arg, PyObject* callback);
+
+private:
+  static void near_callback(void*, dGeomID, dGeomID);
+
+  static PyObject *_python_callback;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // ODEUTIL_EXT_H