Browse Source

Adding bullet physics.

enn0x 14 years ago
parent
commit
10a64db343
100 changed files with 10808 additions and 2 deletions
  1. 1 0
      direct/src/ffi/panda3d.py
  2. 11 0
      direct/src/p3d/panda3d.pdef
  3. 118 0
      dtool/src/parser-inc/btBulletDynamicsCommon.h
  4. 49 2
      makepanda/makepanda.py
  5. 20 0
      panda/metalibs/pandabullet/Sources.pp
  6. 27 0
      panda/metalibs/pandabullet/pandabullet.cxx
  7. 13 0
      panda/metalibs/pandabullet/pandabullet.h
  8. 222 0
      panda/src/bullet/Sources.pp
  9. 42 0
      panda/src/bullet/bulletAllHitsRayResult.I
  10. 166 0
      panda/src/bullet/bulletAllHitsRayResult.cxx
  11. 82 0
      panda/src/bullet/bulletAllHitsRayResult.h
  12. 205 0
      panda/src/bullet/bulletBodyNode.I
  13. 640 0
      panda/src/bullet/bulletBodyNode.cxx
  14. 152 0
      panda/src/bullet/bulletBodyNode.h
  15. 26 0
      panda/src/bullet/bulletBoxShape.I
  16. 84 0
      panda/src/bullet/bulletBoxShape.cxx
  17. 72 0
      panda/src/bullet/bulletBoxShape.h
  18. 47 0
      panda/src/bullet/bulletCapsuleShape.I
  19. 55 0
      panda/src/bullet/bulletCapsuleShape.cxx
  20. 67 0
      panda/src/bullet/bulletCapsuleShape.h
  21. 47 0
      panda/src/bullet/bulletCharacterControllerNode.I
  22. 434 0
      panda/src/bullet/bulletCharacterControllerNode.cxx
  23. 119 0
      panda/src/bullet/bulletCharacterControllerNode.h
  24. 30 0
      panda/src/bullet/bulletClosestHitRayResult.I
  25. 125 0
      panda/src/bullet/bulletClosestHitRayResult.cxx
  26. 59 0
      panda/src/bullet/bulletClosestHitRayResult.h
  27. 30 0
      panda/src/bullet/bulletClosestHitSweepResult.I
  28. 125 0
      panda/src/bullet/bulletClosestHitSweepResult.cxx
  29. 59 0
      panda/src/bullet/bulletClosestHitSweepResult.h
  30. 47 0
      panda/src/bullet/bulletConeShape.I
  31. 55 0
      panda/src/bullet/bulletConeShape.cxx
  32. 67 0
      panda/src/bullet/bulletConeShape.h
  33. 25 0
      panda/src/bullet/bulletConeTwistConstraint.I
  34. 95 0
      panda/src/bullet/bulletConeTwistConstraint.cxx
  35. 76 0
      panda/src/bullet/bulletConeTwistConstraint.h
  36. 24 0
      panda/src/bullet/bulletConstraint.I
  37. 85 0
      panda/src/bullet/bulletConstraint.cxx
  38. 71 0
      panda/src/bullet/bulletConstraint.h
  39. 128 0
      panda/src/bullet/bulletContactCallbacks.h
  40. 115 0
      panda/src/bullet/bulletContactResult.I
  41. 54 0
      panda/src/bullet/bulletContactResult.cxx
  42. 81 0
      panda/src/bullet/bulletContactResult.h
  43. 25 0
      panda/src/bullet/bulletConvexHullShape.I
  44. 102 0
      panda/src/bullet/bulletConvexHullShape.cxx
  45. 71 0
      panda/src/bullet/bulletConvexHullShape.h
  46. 36 0
      panda/src/bullet/bulletConvexPointCloudShape.I
  47. 91 0
      panda/src/bullet/bulletConvexPointCloudShape.cxx
  48. 69 0
      panda/src/bullet/bulletConvexPointCloudShape.h
  49. 58 0
      panda/src/bullet/bulletCylinderShape.I
  50. 83 0
      panda/src/bullet/bulletCylinderShape.cxx
  51. 69 0
      panda/src/bullet/bulletCylinderShape.h
  52. 47 0
      panda/src/bullet/bulletDebugNode.I
  53. 392 0
      panda/src/bullet/bulletDebugNode.cxx
  54. 135 0
      panda/src/bullet/bulletDebugNode.h
  55. 25 0
      panda/src/bullet/bulletDistanceConstraint.I
  56. 111 0
      panda/src/bullet/bulletDistanceConstraint.cxx
  57. 79 0
      panda/src/bullet/bulletDistanceConstraint.h
  58. 25 0
      panda/src/bullet/bulletGenericConstraint.I
  59. 115 0
      panda/src/bullet/bulletGenericConstraint.cxx
  60. 82 0
      panda/src/bullet/bulletGenericConstraint.h
  61. 51 0
      panda/src/bullet/bulletGhostNode.I
  62. 113 0
      panda/src/bullet/bulletGhostNode.cxx
  63. 83 0
      panda/src/bullet/bulletGhostNode.h
  64. 26 0
      panda/src/bullet/bulletHeightfieldShape.I
  65. 68 0
      panda/src/bullet/bulletHeightfieldShape.cxx
  66. 69 0
      panda/src/bullet/bulletHeightfieldShape.h
  67. 42 0
      panda/src/bullet/bulletHelper.I
  68. 307 0
      panda/src/bullet/bulletHelper.cxx
  69. 70 0
      panda/src/bullet/bulletHelper.h
  70. 25 0
      panda/src/bullet/bulletHingeConstraint.I
  71. 158 0
      panda/src/bullet/bulletHingeConstraint.cxx
  72. 88 0
      panda/src/bullet/bulletHingeConstraint.h
  73. 24 0
      panda/src/bullet/bulletManifoldPoint.I
  74. 103 0
      panda/src/bullet/bulletManifoldPoint.cxx
  75. 51 0
      panda/src/bullet/bulletManifoldPoint.h
  76. 24 0
      panda/src/bullet/bulletPersistentManifold.I
  77. 110 0
      panda/src/bullet/bulletPersistentManifold.cxx
  78. 56 0
      panda/src/bullet/bulletPersistentManifold.h
  79. 47 0
      panda/src/bullet/bulletPlaneShape.I
  80. 57 0
      panda/src/bullet/bulletPlaneShape.cxx
  81. 72 0
      panda/src/bullet/bulletPlaneShape.h
  82. 71 0
      panda/src/bullet/bulletRigidBodyNode.I
  83. 418 0
      panda/src/bullet/bulletRigidBodyNode.cxx
  84. 127 0
      panda/src/bullet/bulletRigidBodyNode.h
  85. 101 0
      panda/src/bullet/bulletShape.I
  86. 75 0
      panda/src/bullet/bulletShape.cxx
  87. 76 0
      panda/src/bullet/bulletShape.h
  88. 25 0
      panda/src/bullet/bulletSliderConstraint.I
  89. 157 0
      panda/src/bullet/bulletSliderConstraint.cxx
  90. 85 0
      panda/src/bullet/bulletSliderConstraint.h
  91. 556 0
      panda/src/bullet/bulletSoftBodyConfig.I
  92. 86 0
      panda/src/bullet/bulletSoftBodyConfig.cxx
  93. 115 0
      panda/src/bullet/bulletSoftBodyConfig.h
  94. 115 0
      panda/src/bullet/bulletSoftBodyMaterial.I
  95. 26 0
      panda/src/bullet/bulletSoftBodyMaterial.cxx
  96. 51 0
      panda/src/bullet/bulletSoftBodyMaterial.h
  97. 116 0
      panda/src/bullet/bulletSoftBodyNode.I
  98. 1039 0
      panda/src/bullet/bulletSoftBodyNode.cxx
  99. 232 0
      panda/src/bullet/bulletSoftBodyNode.h
  100. 28 0
      panda/src/bullet/bulletSoftBodyShape.I

+ 1 - 0
direct/src/ffi/panda3d.py

@@ -9,6 +9,7 @@ panda3d_modules = {
     "direct"      : "libp3direct",
     "egg"         : "libpandaegg",
     "ode"         : "libpandaode",
+    "bullet"      : "libpandabullet",
     "vision"      : "libp3vision",
     "physx"       : "libpandaphysx",
     "ai"          : "libpandaai",

+ 11 - 0
direct/src/p3d/panda3d.pdef

@@ -69,6 +69,7 @@ class panda3d(package):
     # except for skel - this is useless in a shipped game anyways.
     excludeModule('libpandaegg')
     excludeModule('libpandaode')
+    excludeModule('libpandabullet')
     excludeModule('libp3vision')
     excludeModule('libpandaskel')
     excludeModule('libpandaphysx')
@@ -264,6 +265,16 @@ class ode(package):
 
     file('libpandaode.dll', required = True)
 
+class bullet(package):
+    # This package contains the code for the Bullet integration.
+    # As not every application uses the Bullet layers, and to cut down
+    # the download size, it is provided as separate package.
+
+    config(display_name = "Panda3D Bullet integration")
+    require('panda3d')
+
+    file('libpandabullet.dll', required = True)
+
 class physx(package):
     # This package contains the code for the NVIDIA PhysX integration.
     # As not every application uses the NVIDIA PhysX layers, and to cut down

+ 118 - 0
dtool/src/parser-inc/btBulletDynamicsCommon.h

@@ -0,0 +1,118 @@
+
+class bt32BitAxisSweep3;
+class btActionInterface;
+class btAxisSweep3;
+class btBoxShape;
+class btBroadphaseInterface;
+class btBulletWorldImporter;
+class btBvhTriangleMeshShape;
+class btCapsuleShape;
+class btCapsuleShapeX;
+class btCapsuleShapeZ;
+class btCharacterControllerInterface;
+class btCollisionConfiguration;
+class btCollisionDispatcher;
+class btCollisionObject;
+class btCollisionShape;
+class btCompoundShape;
+class btConcaveShape;
+class btConeShape;
+class btConeShapeX;
+class btConeShapeZ;
+class btConeTwistConstraint;
+class btConstraintSolver;
+class btContactConstraint;
+class btContinuousDynamicsWorld;
+class btConvexShape;
+class btConvexHullShape;
+class btConvexInternalShape;
+class btConvexPointCloudShape;
+class btCylinderShape;
+class btCylinderShapeX;
+class btCylinderShapeZ;
+class btDefaultCollisionConfiguration;
+class btDefaultMotionState;
+class btDiscreteDynamicsWorld;
+class btDispatcher;
+class btDynamicsWorld;
+class btEmptyShape;
+class btGeneric6DofConstraint;
+class btGeneric6DofSpringConstraint;
+class btGhostPairCallback;
+class btGhostObject;
+class btGImpactMeshShape;
+class btHeightfieldTerrainShape;
+class btHingeConstraint;
+class btHinge2Constraint;
+class btIDebugDraw;
+class btKinematicCharacterController;
+class btManifoldPoint;
+class btMatrix3x3;
+class btMotionState;
+class btPairCachingGhostObject;
+class btParalleSequentialImpulseSolver;
+class btPersistentManifold;
+class btPlaneShape;
+class btPoint2PointConstraint;
+class btPolyhedralConvexShape;
+class btQuaternion;
+class btSequentialImpulseConstraintSolver;
+class btScalar;
+class btSliderConstraint;
+class btSoftBodyHelpers;
+class btSoftBodyRigidBodyCollisionConfiguration;
+class btSoftBodyCollisionShape;
+class btSoftBodyWorldInfo;
+class btSoftRigidDynamicsWorld;
+class btSphereShape;
+class btStaticPlaneShape;
+class btStridingMeshInterface;
+class btTransform;
+class btTriangleMesh;
+class btTypedConstraint;
+class btTypedObject;
+class btVector3;
+class btVehicleRaycaster;
+class btWheelInfo;
+
+class btCollisionWorld {
+public:
+  struct LocalRayResult;
+  struct ClosestRayResultCallback;
+  struct RayResultCallback;
+  struct ContactResultCallback;
+  struct AllHitsRayResultCallback;
+  struct ClosestConvexResultCallback;
+};
+
+class btRaycastVehicle {
+public:
+  class btVehicleTuning;
+};
+
+class btRigidBody {
+public:
+  class btRigidBodyConstructionInfo;
+};
+
+class btSoftBody {
+public:
+  struct Config;
+  struct Joint;
+  struct Link;
+  struct Material;
+  struct Node;
+};
+
+// BulletCollision/CollisionDispatch/btCollisionObject.h
+#define ACTIVE_TAG 1
+#define ISLAND_SLEEPING 2
+#define WANTS_DEACTIVATION 3
+#define DISABLE_DEACTIVATION 4
+#define DISABLE_SIMULATION 5
+
+// BulletCollision/CollisionDispatch/btManifoldResult.h
+typedef bool (*ContactAddedCallback);
+typedef bool (*ContactProcessedCallback);
+typedef bool (*ContactDestroyedCallback);
+

+ 49 - 2
makepanda/makepanda.py

@@ -60,7 +60,7 @@ PkgListSet(["PYTHON", "DIRECT",                        # Python support
   "GL", "GLES", "GLES2"] + DXVERSIONS + ["TINYDISPLAY", "NVIDIACG", # 3D graphics
   "EGL",                                               # OpenGL (ES) integration
   "OPENAL", "FMODEX", "FFMPEG",                        # Multimedia
-  "ODE", "PHYSX",                                      # Physics
+  "ODE", "PHYSX", "BULLET",                            # Physics
   "SPEEDTREE",                                         # SpeedTree
   "ZLIB", "PNG", "JPEG", "TIFF", "SQUISH", "FREETYPE", # 2D Formats support
   ] + MAYAVERSIONS + MAXVERSIONS + [ "FCOLLADA",       # 3D Formats support
@@ -506,6 +506,12 @@ if (COMPILER=="MSVC"):
         if (SDK["SPEEDTREEAPI"] == "OpenGL"):
             LibName("SPEEDTREE",  "%sglew32.lib" % (libdir))
         IncDirectory("SPEEDTREE", SDK["SPEEDTREE"] + "/Include")
+    if (PkgSkip("BULLET")==0):
+        LibName("BULLET", GetThirdpartyDir() + "bullet/lib/LinearMath.lib")
+        LibName("BULLET", GetThirdpartyDir() + "bullet/lib/BulletCollision.lib")
+        LibName("BULLET", GetThirdpartyDir() + "bullet/lib/BulletDynamics.lib")
+        LibName("BULLET", GetThirdpartyDir() + "bullet/lib/BulletSoftBody.lib")
+        LibName("BULLET", GetThirdpartyDir() + "bullet/lib/BulletMultiThreaded.lib")
 
 if (COMPILER=="LINUX"):
     PkgDisable("AWESOMIUM")
@@ -670,6 +676,9 @@ if (COMPILER=="LINUX"):
             LibName("PHYSX", "-lPhysXLoader")
             LibName("PHYSX", "-lNxCharacter")
 
+    #if (PkgSkip("BULLET")==0):
+    #    TODO
+
 DefSymbol("ALWAYS", "MAKEPANDA", "")
 DefSymbol("WITHINPANDA", "WITHIN_PANDA", "1")
 IncDirectory("ALWAYS", GetOutputDir()+"/tmp")
@@ -744,8 +753,10 @@ def CompileCxx(obj,src,opts):
         cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 "
 
         # Enables Windows 7 mode if SDK is detected.
+        # But only if it is Windows 7 (0x601) and not e. g. Vista (0x600)
         platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v7.0", "InstallationFolder")
-        if platsdk and os.path.isdir(platsdk):
+        winver = sys.getwindowsversion()
+        if platsdk and os.path.isdir(platsdk) and winver[0] >= 6 and winver[1] >= 1:
             cmd += "/DPANDA_WIN7 /DWINVER=0x601 "
 
         cmd += "/Fo" + obj + " /nologo /c"
@@ -1472,6 +1483,7 @@ DTOOL_CONFIG=[
     ("_SECURE_SCL",                    '1',                      'UNDEF'),
     ("_SECURE_SCL_THROWS",             '0',                      'UNDEF'),
     ("HAVE_P3D_PLUGIN",                'UNDEF',                  'UNDEF'),
+    ("HAVE_BULLET",                    'UNDEF',                  'UNDEF'),
 ]
 
 PRC_PARAMETERS=[
@@ -2057,6 +2069,10 @@ if (PkgSkip("PHYSX")==0):
     CopyAllHeaders('panda/src/physx')
     CopyAllHeaders('panda/metalibs/pandaphysx')
 
+if (PkgSkip("BULLET")==0):
+    CopyAllHeaders('panda/src/bullet')
+    CopyAllHeaders('panda/metalibs/pandabullet')
+
 if (PkgSkip("SPEEDTREE")==0):
     CopyAllHeaders('panda/src/speedtree')
 
@@ -3450,6 +3466,35 @@ if (PkgSkip("ODE")==0 and not RUNTIME):
   TargetAdd('libpandaode.dll', input=COMMON_PANDA_LIBS)
   TargetAdd('libpandaode.dll', opts=['WINUSER', 'ODE'])
 
+#
+# DIRECTORY: panda/src/bullet/
+#
+if (PkgSkip("BULLET")==0 and not RUNTIME):
+  OPTS=['DIR:panda/src/bullet', 'BUILDING:PANDABULLET', 'BULLET']
+  TargetAdd('bullet_composite.obj', opts=OPTS, input='bullet_composite.cxx')
+  IGATEFILES=GetDirectoryContents('panda/src/bullet', ["*.h", "*_composite.cxx"])
+  TargetAdd('libpandabullet.in', opts=OPTS, input=IGATEFILES)
+  TargetAdd('libpandabullet.in', opts=['IMOD:pandabullet', 'ILIB:libpandabullet', 'SRCDIR:panda/src/bullet'])
+  TargetAdd('libpandabullet_igate.obj', input='libpandabullet.in', opts=["DEPENDENCYONLY"])
+
+#
+# DIRECTORY: panda/metalibs/pandabullet/
+#
+if (PkgSkip("BULLET")==0 and not RUNTIME):
+  OPTS=['DIR:panda/metalibs/pandabullet', 'BUILDING:PANDABULLET', 'BULLET']
+  TargetAdd('pandabullet_pandabullet.obj', opts=OPTS, input='pandabullet.cxx')
+
+  TargetAdd('libpandabullet_module.obj', input='libpandabullet.in')
+  TargetAdd('libpandabullet_module.obj', opts=OPTS)
+  TargetAdd('libpandabullet_module.obj', opts=['IMOD:pandabullet', 'ILIB:libpandabullet'])
+
+  TargetAdd('libpandabullet.dll', input='pandabullet_pandabullet.obj')
+  TargetAdd('libpandabullet.dll', input='libpandabullet_module.obj')
+  TargetAdd('libpandabullet.dll', input='bullet_composite.obj')
+  TargetAdd('libpandabullet.dll', input='libpandabullet_igate.obj')
+  TargetAdd('libpandabullet.dll', input=COMMON_PANDA_LIBS)
+  TargetAdd('libpandabullet.dll', opts=['WINUSER', 'BULLET'])
+
 #
 # DIRECTORY: panda/src/physx/
 #
@@ -4869,6 +4914,8 @@ if (PkgSkip("PYTHON")==0 and not RUNTIME):
     TargetAdd('PandaModules.py', input='libp3awesomium.dll')
   if (PkgSkip("ODE")==0):
     TargetAdd('PandaModules.py', input='libpandaode.dll')
+  if (PkgSkip("BULLET")==0):
+    TargetAdd('PandaModules.py', input='libpandabullet.dll')
 
 #
 # Generate the models directory and samples directory

+ 20 - 0
panda/metalibs/pandabullet/Sources.pp

@@ -0,0 +1,20 @@
+// DIR_TYPE "metalib" indicates we are building a shared library that
+// consists mostly of references to other shared libraries.  Under
+// Windows, this directly produces a DLL (as opposed to the regular
+// src libraries, which don't produce anything but a pile of OBJ files
+// under Windows).
+
+#define DIR_TYPE metalib
+#define BUILD_DIRECTORY $[HAVE_BULLET]
+#define BUILDING_DLL BUILDING_PANDABULLET
+
+#define COMPONENT_LIBS bullet
+#define LOCAL_LIBS linmath putil express
+#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
+                   dtoolutil:c dtoolbase:c dtool:m prc:c
+
+#begin metalib_target
+    #define TARGET pandabullet
+    #define SOURCES pandabullet.cxx pandabullet.h
+    #define INSTALL_HEADERS pandabullet.h
+#end metalib_target

+ 27 - 0
panda/metalibs/pandabullet/pandabullet.cxx

@@ -0,0 +1,27 @@
+// Filename: pandabullet.cxx
+// Created by:  enn0x (10May2011)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "pandabullet.h"
+#include "config_bullet.h"
+
+// By including checkPandaVersion.h, we guarantee that runtime
+// attempts to load libpandabullet.so/.dll will fail if they
+// inadvertently link with the wrong version of libdtool.so/.dll.
+
+#include "checkPandaVersion.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libpandabullet
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libpandabullet() {
+  init_libbullet();
+}
+

+ 13 - 0
panda/metalibs/pandabullet/pandabullet.h

@@ -0,0 +1,13 @@
+// Filename: pandabullet.h
+// Created by:  enn0x (10May2011)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef PANDABULLET_H
+#define PANDABULLET_H
+
+#include "pandabase.h"
+
+EXPCL_PANDABULLET void init_libpandabullet();
+
+#endif

+ 222 - 0
panda/src/bullet/Sources.pp

@@ -0,0 +1,222 @@
+#define BUILD_DIRECTORY $[HAVE_BULLET]
+#define BUILDING_DLL BUILDING_PANDABULLET
+
+#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m dtoolutil:c dtoolbase:c dtool:m prc:c
+
+#begin lib_target
+  #define TARGET bullet
+  #define LOCAL_LIBS pgraph linmath grutil
+  #define USE_PACKAGES bullet
+  #define COMBINED_SOURCES $[TARGET]_composite.cxx
+
+  #define SOURCES \
+    bulletAllHitsRayResult.I \
+    bulletAllHitsRayResult.h \
+    bulletBodyNode.I \
+    bulletBodyNode.h \
+    bulletBoxShape.I \
+    bulletBoxShape.h \
+    bulletCapsuleShape.I \
+    bulletCapsuleShape.h \
+    bulletCharacterControllerNode.I \
+    bulletCharacterControllerNode.h \
+    bulletClosestHitRayResult.I \
+    bulletClosestHitRayResult.h \
+    bulletClosestHitSweepResult.I \
+    bulletClosestHitSweepResult.h \
+    bulletConeShape.I \
+    bulletConeShape.h \
+    bulletConeTwistConstraint.I \
+    bulletConeTwistConstraint.h \
+    bulletConstraint.I \
+    bulletConstraint.h \
+    bulletContactCallbacks.h \
+    bulletContactResult.I \
+    bulletContactResult.h \
+    bulletConvexHullShape.I \
+    bulletConvexHullShape.h \
+    bulletConvexPointCloudShape.I \
+    bulletConvexPointCloudShape.h \
+    bulletCylinderShape.I \
+    bulletCylinderShape.h \
+    bulletDebugNode.I \
+    bulletDebugNode.h \
+    bulletDistanceConstraint.I \
+    bulletDistanceConstraint.h \
+    bulletGenericConstraint.I \
+    bulletGenericConstraint.h \
+    bulletGhostNode.I \
+    bulletGhostNode.h \
+    bulletHeightfieldShape.I \
+    bulletHeightfieldShape.h \
+    bulletHelper.I \
+    bulletHelper.h \
+    bulletHingeConstraint.I \
+    bulletHingeConstraint.h \
+    bulletManifoldPoint.I \
+    bulletManifoldPoint.h \
+    bulletPersistentManifold.I \
+    bulletPersistentManifold.h \
+    bulletPlaneShape.I \
+    bulletPlaneShape.h \
+    bulletRigidBodyNode.I \
+    bulletRigidBodyNode.h \
+    bulletShape.I \
+    bulletShape.h \
+    bulletSliderConstraint.I \
+    bulletSliderConstraint.h \
+    bulletSoftBodyConfig.I \
+    bulletSoftBodyConfig.h \
+    bulletSoftBodyMaterial.I \
+    bulletSoftBodyMaterial.h \
+    bulletSoftBodyNode.I \
+    bulletSoftBodyNode.h \
+    bulletSoftBodyShape.I \
+    bulletSoftBodyShape.h \
+    bulletSoftBodyWorldInfo.I \
+    bulletSoftBodyWorldInfo.h \
+    bulletSphereShape.I \
+    bulletSphereShape.h \
+    bulletTriangleMesh.I \
+    bulletTriangleMesh.h \
+    bulletTriangleMeshShape.I \
+    bulletTriangleMeshShape.h \
+    bulletVehicle.I \
+    bulletVehicle.h \
+    bulletWheel.I \
+    bulletWheel.h \
+    bulletWorld.I \
+    bulletWorld.h \
+    bullet_includes.h \
+    bullet_utils.I \
+    bullet_utils.h \
+    config_bullet.h \
+
+  #define INCLUDED_SOURCES \
+    bulletAllHitsRayResult.cxx \
+    bulletBodyNode.cxx \
+    bulletBoxShape.cxx \
+    bulletCapsuleShape.cxx \
+    bulletCharacterControllerNode.cxx \
+    bulletClosestHitRayResult.cxx \
+    bulletClosestHitSweepResult.cxx \
+    bulletConeShape.cxx \
+    bulletConeTwistConstraint.cxx \
+    bulletConstraint.cxx \
+    bulletContactResult.cxx \
+    bulletConvexHullShape.cxx \
+    bulletConvexPointCloudShape.cxx \
+    bulletCylinderShape.cxx \
+    bulletDebugNode.cxx \
+    bulletDistanceConstraint.cxx \
+    bulletGenericConstraint.cxx \
+    bulletGhostNode.cxx \
+    bulletHeightfieldShape.cxx \
+    bulletHelper.cxx \
+    bulletHingeConstraint.cxx \
+    bulletManifoldPoint.cxx \
+    bulletPersistentManifold.cxx \
+    bulletPlaneShape.cxx \
+    bulletRigidBodyNode.cxx \
+    bulletShape.cxx \
+    bulletSliderConstraint.cxx \
+    bulletSoftBodyConfig.cxx \
+    bulletSoftBodyMaterial.cxx \
+    bulletSoftBodyNode.cxx \
+    bulletSoftBodyShape.cxx \
+    bulletSoftBodyWorldInfo.cxx \
+    bulletSphereShape.cxx \
+    bulletTriangleMesh.cxx \
+    bulletTriangleMeshShape.cxx \
+    bulletVehicle.cxx \
+    bulletWheel.cxx \
+    bulletWorld.cxx \
+    bullet_composite.cxx \
+    bullet_utils.cxx \
+    config_bullet.cxx \
+
+  #define INSTALL_HEADERS \
+    bulletAllHitsRayResult.I \
+    bulletAllHitsRayResult.h \
+    bulletBodyNode.I \
+    bulletBodyNode.h \
+    bulletBoxShape.I \
+    bulletBoxShape.h \
+    bulletCapsuleShape.I \
+    bulletCapsuleShape.h \
+    bulletCharacterControllerNode.I \
+    bulletCharacterControllerNode.h \
+    bulletClosestHitRayResult.I \
+    bulletClosestHitRayResult.h \
+    bulletClosestHitSweepResult.I \
+    bulletClosestHitSweepResult.h \
+    bulletConeShape.I \
+    bulletConeShape.h \
+    bulletConeTwistConstraint.I \
+    bulletConeTwistConstraint.h \
+    bulletConstraint.I \
+    bulletConstraint.h \
+    bulletContactCallbacks.h \
+    bulletContactResult.I \
+    bulletContactResult.h \
+    bulletConvexHullShape.I \
+    bulletConvexHullShape.h \
+    bulletConvexPointCloudShape.I \
+    bulletConvexPointCloudShape.h \
+    bulletCylinderShape.I \
+    bulletCylinderShape.h \
+    bulletDebugNode.I \
+    bulletDebugNode.h \
+    bulletDistanceConstraint.I \
+    bulletDistanceConstraint.h \
+    bulletGenericConstraint.I \
+    bulletGenericConstraint.h \
+    bulletGhostNode.I \
+    bulletGhostNode.h \
+    bulletHeightfieldShape.I \
+    bulletHeightfieldShape.h \
+    bulletHelper.I \
+    bulletHelper.h \
+    bulletHingeConstraint.I \
+    bulletHingeConstraint.h \
+    bulletManifoldPoint.I \
+    bulletManifoldPoint.h \
+    bulletPersistentManifold.I \
+    bulletPersistentManifold.h \
+    bulletPlaneShape.I \
+    bulletPlaneShape.h \
+    bulletRigidBodyNode.I \
+    bulletRigidBodyNode.h \
+    bulletShape.I \
+    bulletShape.h \
+    bulletSliderConstraint.I \
+    bulletSliderConstraint.h \
+    bulletSoftBodyConfig.I \
+    bulletSoftBodyConfig.h \
+    bulletSoftBodyMaterial.I \
+    bulletSoftBodyMaterial.h \
+    bulletSoftBodyNode.I \
+    bulletSoftBodyNode.h \
+    bulletSoftBodyShape.I \
+    bulletSoftBodyShape.h \
+    bulletSoftBodyWorldInfo.I \
+    bulletSoftBodyWorldInfo.h \
+    bulletSphereShape.I \
+    bulletSphereShape.h \
+    bulletTriangleMesh.I \
+    bulletTriangleMesh.h \
+    bulletTriangleMeshShape.I \
+    bulletTriangleMeshShape.h \
+    bulletVehicle.I \
+    bulletVehicle.h \
+    bulletWheel.I \
+    bulletWheel.h \
+    bulletWorld.I \
+    bulletWorld.h \
+    bullet_includes.h \
+    bullet_utils.I \
+    bullet_utils.h \
+
+  #define IGATESCAN all
+
+#end lib_target

+ 42 - 0
panda/src/bullet/bulletAllHitsRayResult.I

@@ -0,0 +1,42 @@
+// Filename: bulletAllHitsRayResult.I
+// Created by:  enn0x (21Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::empty
+//       Access: Published
+//  Description: Named constructor intended to be used for asserts
+//               with have to return a concrete value.
+////////////////////////////////////////////////////////////////////
+INLINE BulletAllHitsRayResult BulletAllHitsRayResult::
+empty() {
+
+  btVector3 from;
+  btVector3 to;
+
+  return BulletAllHitsRayResult(from, to, CollideMask::all_on());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRayHit::empty
+//       Access: Published
+//  Description: Named constructor intended to be used for asserts
+//               with have to return a concrete value.
+////////////////////////////////////////////////////////////////////
+INLINE BulletRayHit BulletRayHit::
+empty() {
+
+  return BulletRayHit();
+}
+

+ 166 - 0
panda/src/bullet/bulletAllHitsRayResult.cxx

@@ -0,0 +1,166 @@
+// Filename: bulletAllHitsRayResult.cxx
+// Created by:  enn0x (21Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletAllHitsRayResult.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletAllHitsRayResult::
+BulletAllHitsRayResult(const btVector3 &from_pos, const btVector3 &to_pos, const CollideMask &mask) 
+ : btCollisionWorld::AllHitsRayResultCallback(from_pos, to_pos), _mask(mask) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::needsCollision
+//       Access: Protected
+//  Description: Override default implementation.
+////////////////////////////////////////////////////////////////////
+bool BulletAllHitsRayResult::
+needsCollision(btBroadphaseProxy* proxy0) const {
+
+  // Original implementation:
+  //bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+  //collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+  //return collides;
+
+  btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject;
+  PandaNode *node0 = (PandaNode *) obj0->getUserPointer();
+  CollideMask mask0 = node0->get_into_collide_mask();
+
+  return (_mask & mask0) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::get_from_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletAllHitsRayResult::
+get_from_pos() const {
+
+  return btVector3_to_LPoint3f(m_rayFromWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::get_to_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletAllHitsRayResult::
+get_to_pos() const {
+
+  return btVector3_to_LPoint3f(m_rayToWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::has_hits
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletAllHitsRayResult::
+has_hits() const {
+
+  return hasHit();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::get_closest_hit_fraction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletAllHitsRayResult::
+get_closest_hit_fraction() const {
+
+  return m_closestHitFraction;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::get_num_hits
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+int BulletAllHitsRayResult::
+get_num_hits() const {
+
+  return m_collisionObjects.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletAllHitsRayResult::get_hit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+const BulletRayHit BulletAllHitsRayResult::
+get_hit(int idx) const {
+
+  nassertr(idx >= 0 && idx < get_num_hits(), BulletRayHit::empty());
+
+  BulletRayHit hit;
+
+  hit._object = m_collisionObjects[idx];
+  hit._normal = m_hitNormalWorld[idx];
+  hit._pos = m_hitPointWorld[idx];
+  hit._fraction = m_hitFractions[idx];
+
+  return hit;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRayHit::get_hit_fraction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletRayHit::
+get_hit_fraction() const {
+
+  return _fraction;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRayHit::get_node
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaNode *BulletRayHit::
+get_node() const {
+
+  return (_object) ? (PandaNode *)_object->getUserPointer() : NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRayHit::get_hit_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletRayHit::
+get_hit_pos() const {
+
+  return btVector3_to_LPoint3f(_pos);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRayHit::get_hit_normal
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3f BulletRayHit::
+get_hit_normal() const {
+
+  return btVector3_to_LVector3f(_normal);
+}
+

+ 82 - 0
panda/src/bullet/bulletAllHitsRayResult.h

@@ -0,0 +1,82 @@
+// Filename: bulletAllHitsRayResult.h
+// Created by:  enn0x (21Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_ALL_HITS_RAY_RESULT_H__
+#define __BULLET_ALL_HITS_RAY_RESULT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+
+#include "luse.h"
+#include "pandaNode.h"
+#include "collideMask.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletRayHit
+// Description : 
+////////////////////////////////////////////////////////////////////
+struct BulletRayHit {
+
+PUBLISHED:
+  INLINE static BulletRayHit empty();
+
+  PandaNode *get_node() const;
+  LPoint3f get_hit_pos() const;
+  LVector3f get_hit_normal() const;
+  float get_hit_fraction() const;
+
+private:
+  btCollisionObject *_object; 
+  btVector3 _normal;
+  btVector3 _pos;
+  btScalar _fraction;
+
+  friend struct BulletAllHitsRayResult;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletAllHitsRayResult
+// Description : 
+////////////////////////////////////////////////////////////////////
+struct EXPCL_PANDABULLET BulletAllHitsRayResult : public btCollisionWorld::AllHitsRayResultCallback {
+
+PUBLISHED:
+  INLINE static BulletAllHitsRayResult empty();
+
+  LPoint3f get_from_pos() const;
+  LPoint3f get_to_pos() const;
+
+  bool has_hits() const;
+  float get_closest_hit_fraction() const;
+
+  int get_num_hits() const;
+  const BulletRayHit get_hit(int idx) const;
+  MAKE_SEQ(get_hits, get_num_hits, get_hit);
+
+public:
+  virtual bool needsCollision(btBroadphaseProxy* proxy0) const;
+
+private:
+  BulletAllHitsRayResult(const btVector3 &from_pos, const btVector3 &to_pos, const CollideMask &mask);
+
+  CollideMask _mask;
+
+  friend class BulletWorld;
+};
+
+#include "bulletAllHitsRayResult.I"
+
+#endif // __BULLET_ALL_HITS_RAY_RESULT_H__

+ 205 - 0
panda/src/bullet/bulletBodyNode.I

@@ -0,0 +1,205 @@
+// Filename: bulletBodyNode.I
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletBodyNode::
+~BulletBodyNode() {
+
+  if (_shape && (
+      _shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE || 
+      _shape->getShapeType() == EMPTY_SHAPE_PROXYTYPE)) {
+    delete _shape;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::notify_collisions
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletBodyNode::
+notify_collisions(bool value) {
+
+  set_collision_flag(btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK, value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::notifies_collisions
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletBodyNode::
+notifies_collisions() const {
+
+  return get_collision_flag(btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_collision_flag
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletBodyNode::
+set_collision_flag(int flag, bool value) {
+
+  int flags = get_object()->getCollisionFlags();
+
+  if (value == true) {
+    flags |= flag;
+  }
+  else {
+    flags &= ~(flag);
+  }
+
+  get_object()->setCollisionFlags(flags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_collision_flag
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletBodyNode::
+get_collision_flag(int flag) const {
+
+  return (get_object()->getCollisionFlags() & flag) ? true : false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::is_static
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletBodyNode::
+is_static() const {
+
+  return get_object()->isStaticObject();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::is_kinematic
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletBodyNode::
+is_kinematic() const {
+
+  return get_object()->isKinematicObject();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_static
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletBodyNode::
+set_static(bool value) {
+
+  set_collision_flag(btCollisionObject::CF_STATIC_OBJECT, value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_kinematic
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletBodyNode::
+set_kinematic(bool value) {
+
+  set_collision_flag(btCollisionObject::CF_KINEMATIC_OBJECT, value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_restitution
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletBodyNode::
+get_restitution() const {
+
+  return get_object()->getRestitution();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_restitution
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletBodyNode::
+set_restitution(float restitution) {
+
+  return get_object()->setRestitution(restitution);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_friction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletBodyNode::
+get_friction() const {
+
+  return get_object()->getFriction();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_friction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletBodyNode::
+set_friction(float friction) {
+
+  return get_object()->setFriction(friction);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::has_anisotropic_friction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletBodyNode::
+has_anisotropic_friction() const {
+
+  return get_object()->hasAnisotropicFriction();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_num_shapes
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int BulletBodyNode::
+get_num_shapes() const {
+
+  return _shapes.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_shape
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletShape *BulletBodyNode::
+get_shape(int idx) const {
+
+  nassertr(idx >= 0 && idx < (int)_shapes.size(), NULL);
+  return _shapes[idx];
+}
+

+ 640 - 0
panda/src/bullet/bulletBodyNode.cxx

@@ -0,0 +1,640 @@
+// Filename: bulletBodyNode.cxx
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletBodyNode.h"
+#include "bulletShape.h"
+#include "bulletWorld.h"
+#include "bulletTriangleMesh.h"
+
+#include "collisionBox.h"
+#include "collisionPlane.h"
+#include "collisionSphere.h"
+#include "collisionPolygon.h"
+
+TypeHandle BulletBodyNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletBodyNode::
+BulletBodyNode(const char *name) : PandaNode(name) {
+
+  // Shape
+  _shape = new btEmptyShape();
+
+  // Transform changed callback
+  _disable_transform_changed = false;
+
+  // Default collide mask
+  set_into_collide_mask(CollideMask::all_on());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_legal_collide_mask
+//       Access: Public, virtual
+//  Description: Returns the subset of CollideMask bits that may be
+//               set for this particular type of PandaNode.  For 
+//               BodyNodes this returns all bits on.
+////////////////////////////////////////////////////////////////////
+CollideMask BulletBodyNode::
+get_legal_collide_mask() const {
+
+  return CollideMask::all_on();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::safe_to_flatten
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to flatten out
+//               this particular kind of Node by duplicating
+//               instances, false otherwise (for instance, a Camera
+//               cannot be safely flattened, because the Camera
+//               pointer itself is meaningful).
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+safe_to_flatten() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::safe_to_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to transform
+//               this particular kind of Node by calling the xform()
+//               method, false otherwise.  For instance, it's usually
+//               a bad idea to attempt to xform a Character.
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+safe_to_transform() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::safe_to_modify_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is safe to automatically adjust
+//               the transform on this kind of node.  Usually, this is
+//               only a bad idea if the user expects to find a
+//               particular transform on the node.
+//
+//               ModelNodes with the preserve_transform flag set are
+//               presently the only kinds of nodes that should not
+//               have their transform even adjusted.
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+safe_to_modify_transform() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::safe_to_combine
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to combine this
+//               particular kind of PandaNode with other kinds of
+//               PandaNodes of compatible type, adding children or
+//               whatever.  For instance, an LODNode should not be
+//               combined with any other PandaNode, because its set of
+//               children is meaningful.
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+safe_to_combine() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::safe_to_combine_children
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to combine the
+//               children of this PandaNode with each other.  For
+//               instance, an LODNode's children should not be
+//               combined with each other, because the set of children
+//               is meaningful.
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+safe_to_combine_children() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::safe_to_flatten_below
+//       Access: Public, Virtual
+//  Description: Returns true if a flatten operation may safely
+//               continue past this node, or false if nodes below this
+//               node may not be molested.
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+safe_to_flatten_below() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::transform_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+transform_changed() {
+
+  // Apply scale to collision shape
+  CPT(TransformState) xform = this->get_transform();
+  if (xform->has_scale()) {
+    LVecBase3f scale = xform->get_scale();
+    _shape->setLocalScaling(LVecBase3f_to_btVector3(scale));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::add_shape
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+add_shape(BulletShape *shape, CPT(TransformState) xform) {
+
+  nassertv(get_object());
+
+  // Transform
+  btTransform trans;
+  if (xform) {
+    trans = LMatrix4f_to_btTrans(xform->get_mat());
+  }
+  else {
+    trans.setIdentity();
+  }
+
+  // Root shape
+  btCollisionShape *previous = get_object()->getCollisionShape();
+  btCollisionShape *next;
+
+  if (_shapes.size() == 0) {
+    nassertv(previous->getShapeType() == EMPTY_SHAPE_PROXYTYPE);
+
+    if (xform) {
+      // One shape, with transform
+      next = new btCompoundShape();
+      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+    }
+    else {
+      // One shape, w/o transform
+      next = shape->ptr();
+    }
+
+    get_object()->setCollisionShape(next);
+    _shape = next;
+
+    delete previous;
+  }
+  else if (_shapes.size() == 1) {
+    // Two shapes. Previous shape might already be a compound.
+    if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
+      next = previous;
+    }
+    else {
+      next = new btCompoundShape();
+
+      btTransform previous_trans = btTransform::getIdentity();
+      ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
+    }
+
+    ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+
+    get_object()->setCollisionShape(next);
+    _shape = next;
+  }
+  else {
+    // Three or more shapes. Previous shape is always a compound
+    nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
+
+    ((btCompoundShape *)previous)->addChildShape(trans, shape->ptr());
+  }
+
+  _shapes.push_back(shape);
+
+  shape_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::remove_shape
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+remove_shape(BulletShape *shape) {
+
+  nassertv(get_object());
+
+  BulletShapes::iterator found;
+  PT(BulletShape) ptshape = shape;
+  found = find(_shapes.begin(), _shapes.end(), ptshape);
+
+  if (found == _shapes.end()) {
+    bullet_cat.warning() << "shape not attached" << endl;
+  }
+  else {
+    _shapes.erase(found);
+
+    // Determine the new root shape
+    btCollisionShape *previous = get_object()->getCollisionShape();
+    btCollisionShape *next;
+
+    if (_shapes.size() == 0) {
+      // No more shapes remaining
+      next = new btEmptyShape();
+
+      get_object()->setCollisionShape(next);
+      _shape = next;
+
+      // The previous shape might be a compound. Then delete it.
+      if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
+        delete previous;
+      }
+    }
+    else if (_shapes.size() == 1) {
+      // Only one shape remaining
+      nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+
+      btCompoundShape *compound = (btCompoundShape *)previous;
+      compound->removeChildShape(shape->ptr());
+
+      nassertv(compound->getNumChildShapes() == 1);
+
+      // The compound is no longer required if the remaining shape 
+      // has no transform
+      btTransform trans = compound->getChildTransform(0);
+      if (is_identity(trans)) {
+        next = compound->getChildShape(0);
+
+        get_object()->setCollisionShape(next);
+        _shape = next;
+
+        delete compound;
+      }
+    }
+    else {
+      // More than one shape are remaining
+      nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+
+      btCompoundShape *compound = (btCompoundShape *)previous;
+      compound->removeChildShape(shape->ptr());
+    }
+
+    shape_changed();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::is_identity
+//       Access: Private
+//  Description: Returns TRUE if the transform is an identity
+//               transform, otherwise FALSE.
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+is_identity(btTransform &trans) {
+
+  btVector3 null(0, 0, 0);
+
+  return (trans.getOrigin() == null 
+       && trans.getRotation().getAxis() == null);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_shape_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletBodyNode::
+get_shape_pos(int idx) const {
+
+  nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3f::zero());
+  return get_shape_mat(idx).get_row3(3);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_shape_mat
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LMatrix4f BulletBodyNode::
+get_shape_mat(int idx) const {
+
+  nassertr(idx >= 0 && idx < (int)_shapes.size(), LMatrix4f::ident_mat());
+
+  btCollisionShape *root = get_object()->getCollisionShape();
+  if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
+    btCompoundShape *compound = (btCompoundShape *)root;
+
+    btTransform xform = compound->getChildTransform(idx);
+    return btTrans_to_LMatrix4f(xform);
+
+    // The above code assumes that shape's index in _shapes member
+    // is the same as the shapes index within the compound. If it
+    // turns out that this is not always true we could use the
+    // following code:
+    /*
+    btCollisionShape *shape = get_shape(idx)->ptr();
+    for (int i=0; i<compound->getNumChildShapes(); i++) {
+      if (compound->getChildShape(i) == shape) {
+         btTransform xform = compound->getChildTransform(idx);
+         return btTrans_to_LMatrix4f(xform);
+      }
+    }
+    */
+  }
+
+  return LMatrix4f::ident_mat();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::shape_changed
+//       Access: Published
+//  Description: Hook which will be called whenever the total shape
+//               of a body changed. Used for example to update
+//               the mass properties (inertia) of a rigid body.
+//               The default implementation does nothing.
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+shape_changed() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_deactivation_time
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_deactivation_time(float dt) {
+
+  get_object()->setDeactivationTime(dt);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_deactivation_time
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletBodyNode::
+get_deactivation_time() const {
+
+  return get_object()->getDeactivationTime();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::is_active
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+is_active() const {
+
+  return get_object()->isActive();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_active
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_active(bool active, bool force) {
+
+  if (active) {
+    get_object()->activate(force);
+  }
+  else {
+    if (force) {
+      get_object()->forceActivationState(ISLAND_SLEEPING);
+    }
+    else {
+      get_object()->setActivationState(ISLAND_SLEEPING);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_disable_deactivation
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_disable_deactivation(bool disable, bool force) {
+
+  int state = (disable) ? DISABLE_DEACTIVATION : WANTS_DEACTIVATION;
+
+  if (force) {
+    get_object()->forceActivationState(state);
+  }
+  else {
+    get_object()->setActivationState(state);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_disable_deactivation
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+get_disable_deactivation() const {
+
+  return (get_object()->getActivationState() & DISABLE_DEACTIVATION) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::check_collision_with
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+check_collision_with(PandaNode *node) {
+
+  btCollisionObject *obj = BulletWorld::get_collision_object(node);
+
+  if (obj) {
+    return get_object()->checkCollideWith(obj);
+  }
+  else {
+    return false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_anisotropic_friction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVecBase3f BulletBodyNode::
+get_anisotropic_friction() const {
+
+  return btVector3_to_LVecBase3f(get_object()->getAnisotropicFriction());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_anisotropic_friction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_anisotropic_friction(const LVecBase3f &friction) {
+
+  nassertv(!friction.is_nan());
+  get_object()->setAnisotropicFriction(LVecBase3f_to_btVector3(friction));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::has_contact_response
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+has_contact_response() const {
+
+  return get_object()->hasContactResponse();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_contact_processing_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletBodyNode::
+get_contact_processing_threshold() const {
+
+  return get_object()->getContactProcessingThreshold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_contact_processing_threshold
+//       Access: Published
+//  Description: The constraint solver can discard solving
+//               contacts, if the distance is above this threshold.
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_contact_processing_threshold(float threshold) {
+
+  get_object()->setContactProcessingThreshold(threshold);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_ccd_swept_sphere_radius
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletBodyNode::
+get_ccd_swept_sphere_radius() const {
+
+  return get_object()->getCcdSweptSphereRadius();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_ccd_swept_sphere_radius
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_ccd_swept_sphere_radius(float radius) {
+
+  return get_object()->setCcdSweptSphereRadius(radius);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_ccd_motion_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletBodyNode::
+get_ccd_motion_threshold() const {
+
+  return get_object()->getCcdMotionThreshold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::set_ccd_motion_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+set_ccd_motion_threshold(float threshold) {
+
+  return get_object()->setCcdMotionThreshold(threshold);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::add_shapes_from_collision_solids
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+add_shapes_from_collision_solids(CollisionNode *cnode) {
+
+  PT(BulletTriangleMesh) mesh = NULL;
+
+  for (int j=0; j<cnode->get_num_solids(); j++) {
+    CPT(CollisionSolid) solid = cnode->get_solid(j);
+    TypeHandle type = solid->get_type();
+
+    // CollisionSphere
+    if (CollisionSphere::get_class_type() == type) {
+      CPT(CollisionSphere) sphere = DCAST(CollisionSphere, solid);
+      CPT(TransformState) ts = TransformState::make_pos(sphere->get_center());
+
+      add_shape(BulletSphereShape::make_from_solid(sphere), ts);
+    }
+
+    // CollisionBox
+    else if (CollisionBox::get_class_type() == type) {
+      CPT(CollisionBox) box = DCAST(CollisionBox, solid);
+      CPT(TransformState) ts = TransformState::make_pos(box->get_approx_center());
+
+      add_shape(BulletBoxShape::make_from_solid(box), ts);
+    }
+
+    // CollisionPlane
+    else if (CollisionPlane::get_class_type() == type) {
+      CPT(CollisionPlane) plane = DCAST(CollisionPlane, solid);
+
+      add_shape(BulletPlaneShape::make_from_solid(plane));
+    }
+
+    // CollisionGeom
+    else if (CollisionPolygon::get_class_type() == type) {
+      CPT(CollisionPolygon) polygon = DCAST(CollisionPolygon, solid);
+
+      if (!mesh) {
+         mesh = new BulletTriangleMesh();
+      }
+
+      for (int i=2; i < polygon->get_num_points(); i++ ) {
+        LPoint3f p1 = polygon->get_point(0);
+        LPoint3f p2 = polygon->get_point(i-1);
+        LPoint3f p3 = polygon->get_point(i);
+
+        mesh->add_triangle(p1, p2, p3, true);
+      }
+    }
+  }
+
+  if (mesh && mesh->get_num_triangles() > 0) {
+    add_shape(new BulletTriangleMeshShape(mesh, true));
+  }
+}
+

+ 152 - 0
panda/src/bullet/bulletBodyNode.h

@@ -0,0 +1,152 @@
+// Filename: bulletBodyNode.h
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_BODY_NODE_H__
+#define __BULLET_BODY_NODE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+
+#include "pandaNode.h"
+#include "collideMask.h"
+#include "collisionNode.h"
+#include "transformState.h"
+
+class BulletShape;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletBodyNode
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletBodyNode : public PandaNode {
+
+PUBLISHED:
+  BulletBodyNode(const char *name);
+  INLINE ~BulletBodyNode();
+
+  // Shapes
+  void add_shape(BulletShape *shape, CPT(TransformState) xform=NULL);
+  void remove_shape(BulletShape *shape);
+
+  INLINE int get_num_shapes() const;
+  INLINE BulletShape *get_shape(int idx) const;
+  MAKE_SEQ(get_shapes, get_num_shapes, get_shape);
+
+  LPoint3f get_shape_pos(int idx) const;
+  LMatrix4f get_shape_mat(int idx) const;
+
+  void add_shapes_from_collision_solids(CollisionNode *cnode);
+
+  // Static and kinematic
+  INLINE bool is_static() const;
+  INLINE bool is_kinematic() const;
+
+  INLINE void set_static(bool value);
+  INLINE void set_kinematic(bool value);
+
+  // Contacts
+  INLINE void notify_collisions(bool value);
+  INLINE bool notifies_collisions() const;
+
+  bool check_collision_with(PandaNode *node);
+
+  bool has_contact_response() const;
+
+  float get_contact_processing_threshold() const;
+  void set_contact_processing_threshold(float threshold);
+
+  // Deactivation
+  bool is_active() const;
+  void set_active(bool active, bool force=false);
+
+  void set_deactivation_time(float dt);
+  float get_deactivation_time() const;
+
+  void set_disable_deactivation(bool disable, bool force=false);
+  bool get_disable_deactivation() const;
+
+  // Friction and Restitution
+  INLINE float get_restitution() const;
+  INLINE void set_restitution(float restitution);
+
+  INLINE float get_friction() const;
+  INLINE void set_friction(float friction);
+
+  INLINE bool has_anisotropic_friction() const;
+  void set_anisotropic_friction(const LVecBase3f &friction);
+  LVecBase3f get_anisotropic_friction() const;
+
+  // CCD
+  float get_ccd_swept_sphere_radius() const;
+  float get_ccd_motion_threshold() const;
+  void set_ccd_swept_sphere_radius(float radius);
+  void set_ccd_motion_threshold(float threshold);
+
+public:
+  virtual btCollisionObject *get_object() const = 0;
+
+  virtual CollideMask get_legal_collide_mask() const;
+
+  virtual bool safe_to_flatten() const;
+  virtual bool safe_to_transform() const;
+  virtual bool safe_to_modify_transform() const;
+  virtual bool safe_to_combine() const;
+  virtual bool safe_to_combine_children() const;
+  virtual bool safe_to_flatten_below() const;
+
+protected:
+  INLINE void set_collision_flag(int flag, bool value);
+  INLINE bool get_collision_flag(int flag) const;
+
+  btCollisionShape *_shape;
+
+  typedef PTA(PT(BulletShape)) BulletShapes;
+  BulletShapes _shapes;
+
+  bool _disable_transform_changed;
+  virtual void transform_changed();
+
+private:
+  virtual void shape_changed();
+
+  static bool is_identity(btTransform &trans);
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PandaNode::init_type();
+    register_type(_type_handle, "BulletBodyNode", 
+                  PandaNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletBodyNode.I"
+
+#endif // __BULLET_BODY_NODE_H__
+

+ 26 - 0
panda/src/bullet/bulletBoxShape.I

@@ -0,0 +1,26 @@
+// Filename: bulletBoxShape.I
+// Created by:  enn0x (24Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletBoxShape::
+~BulletBoxShape() {
+
+  delete _shape;
+}
+

+ 84 - 0
panda/src/bullet/bulletBoxShape.cxx

@@ -0,0 +1,84 @@
+// Filename: bulletBoxShape.cxx
+// Created by:  enn0x (24Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletBoxShape.h"
+#include "bullet_utils.h"
+
+TypeHandle BulletBoxShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletBoxShape::
+BulletBoxShape(const LVecBase3f &halfExtents) {
+
+  btVector3 btHalfExtents = LVecBase3f_to_btVector3(halfExtents);
+
+  _shape = new btBoxShape(btHalfExtents);
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletBoxShape::
+ptr() const {
+
+  return _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::get_half_extents_without_marging
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVecBase3f BulletBoxShape::
+get_half_extents_without_marging() const {
+
+  return btVector3_to_LVecBase3f(_shape->getHalfExtentsWithoutMargin());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::get_half_extents_with_marging
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVecBase3f BulletBoxShape::
+get_half_extents_with_marging() const {
+
+  return btVector3_to_LVecBase3f(_shape->getHalfExtentsWithMargin());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::make_from_solid
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletBoxShape *BulletBoxShape::
+make_from_solid(const CollisionBox *solid) {
+
+  LPoint3f p0 = solid->get_min();
+  LPoint3f p1 = solid->get_max();
+
+  LVecBase3f extents(p1.get_x() - p0.get_x() / 2.0,
+                     p1.get_y() - p0.get_y() / 2.0,
+                     p1.get_z() - p0.get_z() / 2.0);
+
+  return new BulletBoxShape(extents);
+}
+

+ 72 - 0
panda/src/bullet/bulletBoxShape.h

@@ -0,0 +1,72 @@
+// Filename: bulletBoxShape.h
+// Created by:  enn0x (24Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_BOX_SHAPE_H__
+#define __BULLET_BOX_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bulletShape.h"
+
+#include "lvector3.h"
+
+#include "collisionBox.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletBoxShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletBoxShape : public BulletShape {
+
+PUBLISHED:
+  BulletBoxShape(const LVecBase3f &halfExtents);
+  INLINE ~BulletBoxShape();
+
+  LVecBase3f get_half_extents_without_marging() const;
+  LVecBase3f get_half_extents_with_marging() const;
+
+  static BulletBoxShape *make_from_solid(const CollisionBox *solid);
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btBoxShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletBoxShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletBoxShape.I"
+
+#endif // __BULLET_BOX_SHAPE_H__

+ 47 - 0
panda/src/bullet/bulletCapsuleShape.I

@@ -0,0 +1,47 @@
+// Filename: bulletCapsuleShape.I
+// Created by:  enn0x (27Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCapsuleShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletCapsuleShape::
+~BulletCapsuleShape() {
+
+  delete _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCapsuleShape::get_radius
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletCapsuleShape::
+get_radius() const {
+
+  return _shape->getRadius();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCapsuleShape::get_half_height
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletCapsuleShape::
+get_half_height() const {
+
+  return _shape->getHalfHeight();
+}
+

+ 55 - 0
panda/src/bullet/bulletCapsuleShape.cxx

@@ -0,0 +1,55 @@
+// Filename: bulletCapsuleShape.cxx
+// Created by:  enn0x (27Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletCapsuleShape.h"
+
+TypeHandle BulletCapsuleShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCapsuleShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletCapsuleShape::
+BulletCapsuleShape(float radius, float height, BulletUpAxis up) {
+
+  switch (up) {
+  case X_up:
+    _shape = new btCapsuleShapeX(radius, height);
+    break;
+  case Y_up:
+    _shape = new btCapsuleShape(radius, height);
+    break;
+  case Z_up:
+    _shape = new btCapsuleShapeZ(radius, height);
+    break;
+  default:
+    bullet_cat.error() << "invalid up-axis:" << up << endl;
+    break;
+  }
+
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCapsuleShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletCapsuleShape::
+ptr() const {
+
+  return _shape;
+}
+

+ 67 - 0
panda/src/bullet/bulletCapsuleShape.h

@@ -0,0 +1,67 @@
+// Filename: bulletCapsuleShape.h
+// Created by:  enn0x (27Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CAPSULE_SHAPE_H__
+#define __BULLET_CAPSULE_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletShape.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletCapsuleShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletCapsuleShape : public BulletShape {
+
+PUBLISHED:
+  BulletCapsuleShape(float radius, float height, BulletUpAxis up=Z_up);
+  INLINE ~BulletCapsuleShape();
+
+  INLINE float get_radius() const;
+  INLINE float get_half_height() const;
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btCapsuleShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletCapsuleShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletCapsuleShape.I"
+
+#endif // __BULLET_CAPSULE_SHAPE_H__

+ 47 - 0
panda/src/bullet/bulletCharacterControllerNode.I

@@ -0,0 +1,47 @@
+// Filename: bulletCharacterControllerNode.I
+// Created by:  enn0x (21Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletCharacterControllerNode::
+~BulletCharacterControllerNode() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::get_ghost
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE btPairCachingGhostObject *BulletCharacterControllerNode::
+get_ghost() const {
+
+  return _ghost;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::get_character
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE btKinematicCharacterController *BulletCharacterControllerNode::
+get_character() const {
+
+  return _character;
+}
+

+ 434 - 0
panda/src/bullet/bulletCharacterControllerNode.cxx

@@ -0,0 +1,434 @@
+// Filename: bulletCharacterControllerNode.cxx
+// Created by:  enn0x (21Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletCharacterControllerNode.h"
+
+TypeHandle BulletCharacterControllerNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletCharacterControllerNode::
+BulletCharacterControllerNode(BulletShape *shape, float step_height, const char *name) : PandaNode(name) {
+
+  // Setup initial transform
+  btTransform trans = btTransform::getIdentity();
+
+  // Get convex shape
+  if (!shape->is_convex()) {
+    bullet_cat.error() << "a convex shape is required!" << endl;
+  }
+
+  btConvexShape *convex = dynamic_cast<btConvexShape *>(shape->ptr());
+
+  // Setup ghost object
+  _ghost = new btPairCachingGhostObject();
+  _ghost->setUserPointer(this);
+
+  _ghost->setWorldTransform(trans);
+  _ghost->setInterpolationWorldTransform(trans);
+  _ghost->setCollisionShape(convex);
+  _ghost->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT
+                          | btCollisionObject::CF_KINEMATIC_OBJECT);
+
+  // Setup up axis
+  _up = get_default_up_axis();
+
+  // Movement
+  _linear_velocity_is_local = false;
+  _linear_velocity.set(0.0f, 0.0f, 0.0f);
+  _angular_velocity = 0.0f;
+
+  // Setup character controller
+  _character = new btKinematicCharacterController(_ghost, convex, step_height, _up);
+  _character->setGravity((btScalar)9.81f);
+
+  // Retain a pointer to the shape
+  _shape = shape;
+
+  // The 'transform changed' hook has to be disabled when updating the node's
+  // transform from inside the post_step method!
+  _disable_transform_changed = false;
+
+  // Default collide mask
+  set_into_collide_mask(CollideMask::all_on());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::get_legal_collide_mask
+//       Access: Public, virtual
+//  Description: Returns the subset of CollideMask bits that may be
+//               set for this particular type of PandaNode.  For 
+//               CharacterControllerNodes this returns all bits on.
+////////////////////////////////////////////////////////////////////
+CollideMask BulletCharacterControllerNode::
+get_legal_collide_mask() const {
+
+  return CollideMask::all_on();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::safe_to_flatten
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to flatten out
+//               this particular kind of Node by duplicating
+//               instances, false otherwise (for instance, a Camera
+//               cannot be safely flattened, because the Camera
+//               pointer itself is meaningful).
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+safe_to_flatten() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::safe_to_modify_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is safe to automatically adjust
+//               the transform on this kind of node.  Usually, this is
+//               only a bad idea if the user expects to find a
+//               particular transform on the node.
+//
+//               ModelNodes with the preserve_transform flag set are
+//               presently the only kinds of nodes that should not
+//               have their transform even adjusted.
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+safe_to_modify_transform() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::safe_to_combine
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to combine this
+//               particular kind of PandaNode with other kinds of
+//               PandaNodes of compatible type, adding children or
+//               whatever.  For instance, an LODNode should not be
+//               combined with any other PandaNode, because its set of
+//               children is meaningful.
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+safe_to_combine() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::safe_to_combine_children
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to combine the
+//               children of this PandaNode with each other.  For
+//               instance, an LODNode's children should not be
+//               combined with each other, because the set of children
+//               is meaningful.
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+safe_to_combine_children() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::safe_to_flatten_below
+//       Access: Public, Virtual
+//  Description: Returns true if a flatten operation may safely
+//               continue past this node, or false if nodes below this
+//               node may not be molested.
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+safe_to_flatten_below() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::safe_to_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to transform
+//               this particular kind of Node by calling the xform()
+//               method, false otherwise.  For instance, it's usually
+//               a bad idea to attempt to xform a Character.
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+safe_to_transform() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_linear_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_linear_velocity(const LVector3f &velocity, bool is_local) {
+
+  nassertv(!velocity.is_nan());
+
+  _linear_velocity = velocity;
+  _linear_velocity_is_local = is_local;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_angular_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_angular_velocity(float omega) {
+
+  _angular_velocity = omega;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::pre_step
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+pre_step(float dt) {
+
+ // Angular rotation
+  btScalar angle = dt * deg_2_rad(_angular_velocity);
+
+  btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
+  btVector3 up = m[_up];
+
+  m *= btMatrix3x3(btQuaternion(up, angle));
+
+  _ghost->getWorldTransform().setBasis(m);
+
+  // Linear movement
+  btVector3 v;
+  if (_linear_velocity_is_local) {
+    btTransform xform;
+    xform = _ghost->getWorldTransform();
+    xform.setOrigin(btVector3(0.0f, 0.0f, 0.0f));
+    v = xform(LVecBase3f_to_btVector3(_linear_velocity));
+  }
+  else {
+    v = LVecBase3f_to_btVector3(_linear_velocity);
+  }
+
+  _character->setVelocityForTimeInterval(v, dt);
+  //_character->setWalkDirection(v * dt);
+
+  _angular_velocity = 0.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::post_step
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+post_step() {
+
+  btTransform& trans = _ghost->getWorldTransform();
+  CPT(TransformState) ts = btTrans_to_TransformState(trans);
+
+  _disable_transform_changed = true;
+
+  NodePath np = NodePath::any_path((PandaNode *)this);
+  np.set_transform(np.get_top(), ts);
+
+  _disable_transform_changed = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::transform_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+transform_changed() {
+
+  if (_disable_transform_changed) return;
+
+  // Get translation and heading
+  NodePath np = NodePath::any_path((PandaNode *)this);
+  CPT(TransformState) ts = np.get_transform(np.get_top());
+
+  LPoint3f pos = ts->get_pos();
+  float heading = ts->get_hpr().get_x();
+
+  // Set translation
+  _character->warp(LVecBase3f_to_btVector3(pos));
+
+  // Set Heading
+  btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
+  btVector3 up = m[_up];
+
+  m = btMatrix3x3(btQuaternion(up, heading));
+
+  _ghost->getWorldTransform().setBasis(m);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::get_shape
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletShape *BulletCharacterControllerNode::
+get_shape() const {
+
+  return _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::is_on_ground
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+is_on_ground() const {
+
+  return _character->onGround();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::can_jump
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletCharacterControllerNode::
+can_jump() const {
+
+  return _character->canJump();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::do_jump
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+do_jump() {
+
+  _character->jump();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_fall_speed
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_fall_speed(float fall_speed) {
+
+  _character->setFallSpeed(fall_speed);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_jump_speed
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_jump_speed(float jump_speed) {
+
+  _character->setJumpSpeed(jump_speed);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_max_jump_height
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_max_jump_height(float max_jump_height) {
+
+  _character->setMaxJumpHeight(max_jump_height);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_max_slope
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_max_slope(float max_slope) {
+
+  _character->setMaxSlope(max_slope);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::get_max_slope
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletCharacterControllerNode::
+get_max_slope() const {
+
+  return _character->getMaxSlope();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::get_gravity
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletCharacterControllerNode::
+get_gravity() const {
+
+  return _character->getGravity();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_gravity
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_gravity(float gravity) {
+
+  _character->setGravity((btScalar) gravity);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::set_use_ghost_sweep_test
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+set_use_ghost_sweep_test(bool value) {
+
+  return _character->setUseGhostSweepTest(value);
+}
+
+/*
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::parents_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+parents_changed() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCharacterControllerNode::children_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletCharacterControllerNode::
+children_changed() {
+
+}
+*/
+

+ 119 - 0
panda/src/bullet/bulletCharacterControllerNode.h

@@ -0,0 +1,119 @@
+// Filename: bulletCharacterControllerNode.h
+// Created by:  enn0x (21Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CHARACTER_CONTROLLER_NODE_H__
+#define __BULLET_CHARACTER_CONTROLLER_NODE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletShape.h"
+
+#include "pandaNode.h"
+#include "collideMask.h"
+#include "luse.h"
+#include "transformState.h"
+#include "nodePath.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletCharacterControllerNode
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletCharacterControllerNode : public PandaNode {
+
+PUBLISHED:
+  BulletCharacterControllerNode(BulletShape *shape, float step_height, const char *name="character");
+  INLINE ~BulletCharacterControllerNode();
+
+  void set_linear_velocity(const LVector3f &velocity, bool is_local);
+  void set_angular_velocity(float omega);
+
+  BulletShape *get_shape() const;
+
+  float get_gravity() const;
+  float get_max_slope() const;
+
+  void set_fall_speed(float fall_speed);
+  void set_jump_speed(float jump_speed);
+  void set_max_jump_height(float max_jump_height);
+  void set_max_slope(float max_slope);
+  void set_gravity(float gravity);
+  void set_use_ghost_sweep_test(bool value);
+
+  bool is_on_ground() const;
+  bool can_jump() const;
+  void do_jump();
+
+public:
+  virtual CollideMask get_legal_collide_mask() const;
+
+  virtual bool safe_to_flatten() const;
+  virtual bool safe_to_transform() const;
+  virtual bool safe_to_modify_transform() const;
+  virtual bool safe_to_combine() const;
+  virtual bool safe_to_combine_children() const;
+  virtual bool safe_to_flatten_below() const;
+
+  INLINE btPairCachingGhostObject *get_ghost() const;
+  INLINE btKinematicCharacterController *get_character() const;
+
+  void pre_step(float dt);
+  void post_step();
+
+protected:
+  //virtual void parents_changed();
+  //virtual void children_changed();
+  virtual void transform_changed();
+
+private:
+  BulletUpAxis _up;
+
+  btKinematicCharacterController *_character;
+  btPairCachingGhostObject *_ghost;
+
+  PT(BulletShape) _shape;
+
+  LVector3f _linear_velocity;
+  bool _linear_velocity_is_local;
+  float _angular_velocity;
+
+  bool _disable_transform_changed;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PandaNode::init_type();
+    register_type(_type_handle, "BulletCharacterControllerNode", 
+                  PandaNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletCharacterControllerNode.I"
+
+#endif // __BULLET_CHARACTER_CONTROLLER_NODE_H__
+

+ 30 - 0
panda/src/bullet/bulletClosestHitRayResult.I

@@ -0,0 +1,30 @@
+// Filename: bulletClosestHitRayResult.I
+// Created by:  enn0x (21Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::empty
+//       Access: Public
+//  Description: Named constructor intended to be used for asserts
+//               with have to return a concrete value.
+////////////////////////////////////////////////////////////////////
+INLINE BulletClosestHitRayResult BulletClosestHitRayResult::
+empty() {
+
+  btVector3 from;
+  btVector3 to;
+
+  return BulletClosestHitRayResult(from, to, CollideMask::all_on());
+}
+

+ 125 - 0
panda/src/bullet/bulletClosestHitRayResult.cxx

@@ -0,0 +1,125 @@
+// Filename: bulletClosestHitRayResult.cxx
+// Created by:  enn0x (21Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletClosestHitRayResult.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletClosestHitRayResult::
+BulletClosestHitRayResult(const btVector3 &from_pos, const btVector3 &to_pos, const CollideMask &mask) 
+ : btCollisionWorld::ClosestRayResultCallback(from_pos, to_pos), _mask(mask) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::needsCollision
+//       Access: Protected
+//  Description: Override default implementation.
+////////////////////////////////////////////////////////////////////
+bool BulletClosestHitRayResult::
+needsCollision(btBroadphaseProxy* proxy0) const {
+
+  // Original implementation:
+  //bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+  //collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+  //return collides;
+
+  btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject;
+  PandaNode *node0 = (PandaNode *) obj0->getUserPointer();
+  CollideMask mask0 = node0->get_into_collide_mask();
+
+  return (_mask & mask0) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::has_hit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletClosestHitRayResult::
+has_hit() const {
+
+  return hasHit();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::get_hit_fraction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletClosestHitRayResult::
+get_hit_fraction() const {
+
+  return m_closestHitFraction;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::get_node
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaNode *BulletClosestHitRayResult::
+get_node() const {
+
+  btCollisionObject *objectPtr = m_collisionObject;
+  return (objectPtr) ? (PandaNode *)objectPtr->getUserPointer() : NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::get_hit_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletClosestHitRayResult::
+get_hit_pos() const {
+
+  return btVector3_to_LPoint3f(m_hitPointWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::get_hit_normal
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3f BulletClosestHitRayResult::
+get_hit_normal() const {
+
+  return btVector3_to_LVector3f(m_hitNormalWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::get_from_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletClosestHitRayResult::
+get_from_pos() const {
+
+  return btVector3_to_LPoint3f(m_rayFromWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitRayResult::get_to_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletClosestHitRayResult::
+get_to_pos() const {
+
+  return btVector3_to_LPoint3f(m_rayToWorld);
+}
+

+ 59 - 0
panda/src/bullet/bulletClosestHitRayResult.h

@@ -0,0 +1,59 @@
+// Filename: bulletClosestHitRayResult.h
+// Created by:  enn0x (21Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CLOSEST_HIT_RAY_RESULT_H__
+#define __BULLET_CLOSEST_HIT_RAY_RESULT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+
+#include "luse.h"
+#include "pandaNode.h"
+#include "collideMask.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletClosestHitRayResult
+// Description : 
+////////////////////////////////////////////////////////////////////
+struct EXPCL_PANDABULLET BulletClosestHitRayResult : public btCollisionWorld::ClosestRayResultCallback {
+
+PUBLISHED:
+  INLINE static BulletClosestHitRayResult empty();
+
+  LPoint3f get_from_pos() const;
+  LPoint3f get_to_pos() const;
+
+  bool has_hit() const;
+
+  PandaNode *get_node() const;
+  LPoint3f get_hit_pos() const;
+  LVector3f get_hit_normal() const;
+  float get_hit_fraction() const;
+
+public:
+  virtual bool needsCollision(btBroadphaseProxy* proxy0) const;
+
+private:
+  BulletClosestHitRayResult(const btVector3 &from_pos, const btVector3 &to_pos, const CollideMask &mask);
+
+  CollideMask _mask;
+
+  friend class BulletWorld;
+};
+
+#include "bulletClosestHitRayResult.I"
+
+#endif // __BULLET_CLOSEST_HIT_RAY_RESULT_H__

+ 30 - 0
panda/src/bullet/bulletClosestHitSweepResult.I

@@ -0,0 +1,30 @@
+// Filename: bulletClosestHitSweepResult.I
+// Created by:  enn0x (01Dec10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestSweepRayResult::empty
+//       Access: Public
+//  Description: Named constructor intended to be used for asserts
+//               with have to return a concrete value.
+////////////////////////////////////////////////////////////////////
+INLINE BulletClosestHitSweepResult BulletClosestHitSweepResult::
+empty() {
+
+  btVector3 from;
+  btVector3 to;
+
+  return BulletClosestHitSweepResult(from, to, CollideMask::all_on());
+}
+

+ 125 - 0
panda/src/bullet/bulletClosestHitSweepResult.cxx

@@ -0,0 +1,125 @@
+// Filename: bulletClosestHitSweepResult.cxx
+// Created by:  enn0x (01Dec10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletClosestHitSweepResult.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletClosestHitSweepResult::
+BulletClosestHitSweepResult(const btVector3 &from_pos, const btVector3 &to_pos, const CollideMask &mask) 
+ : btCollisionWorld::ClosestConvexResultCallback(from_pos, to_pos), _mask(mask) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::needsCollision
+//       Access: Protected
+//  Description: Override default implementation.
+////////////////////////////////////////////////////////////////////
+bool BulletClosestHitSweepResult::
+needsCollision(btBroadphaseProxy* proxy0) const {
+
+  // Original implementation:
+  //bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+  //collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+  //return collides;
+
+  btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject;
+  PandaNode *node0 = (PandaNode *) obj0->getUserPointer();
+  CollideMask mask0 = node0->get_into_collide_mask();
+
+  return (_mask & mask0) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::has_hit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletClosestHitSweepResult::
+has_hit() const {
+
+  return hasHit();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::get_hit_fraction
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletClosestHitSweepResult::
+get_hit_fraction() const {
+
+  return m_closestHitFraction;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::get_node
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaNode *BulletClosestHitSweepResult::
+get_node() const {
+
+  btCollisionObject *objectPtr = m_hitCollisionObject;
+  return (objectPtr) ? (PandaNode *)objectPtr->getUserPointer() : NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::get_hit_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletClosestHitSweepResult::
+get_hit_pos() const {
+
+  return btVector3_to_LPoint3f(m_hitPointWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::get_hit_normal
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3f BulletClosestHitSweepResult::
+get_hit_normal() const {
+
+  return btVector3_to_LVector3f(m_hitNormalWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::get_from_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletClosestHitSweepResult::
+get_from_pos() const {
+
+  return btVector3_to_LPoint3f(m_convexFromWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletClosestHitSweepResult::get_to_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletClosestHitSweepResult::
+get_to_pos() const {
+
+  return btVector3_to_LPoint3f(m_convexToWorld);
+}
+

+ 59 - 0
panda/src/bullet/bulletClosestHitSweepResult.h

@@ -0,0 +1,59 @@
+// Filename: bulletClosestHitSweepResult.h
+// Created by:  enn0x (01Dec10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CLOSEST_HIT_SWEEP_RESULT_H__
+#define __BULLET_CLOSEST_HIT_SWEEP_RESULT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+
+#include "luse.h"
+#include "pandaNode.h"
+#include "collideMask.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletClosestHitSweepResult
+// Description : 
+////////////////////////////////////////////////////////////////////
+struct EXPCL_PANDABULLET BulletClosestHitSweepResult : public btCollisionWorld::ClosestConvexResultCallback {
+
+PUBLISHED:
+  INLINE static BulletClosestHitSweepResult empty();
+
+  LPoint3f get_from_pos() const;
+  LPoint3f get_to_pos() const;
+
+  bool has_hit() const;
+
+  PandaNode *get_node() const;
+  LPoint3f get_hit_pos() const;
+  LVector3f get_hit_normal() const;
+  float get_hit_fraction() const;
+
+public:
+  virtual bool needsCollision(btBroadphaseProxy* proxy0) const;  
+
+private:
+  BulletClosestHitSweepResult(const btVector3 &from_pos, const btVector3 &to_pos, const CollideMask &mask);
+
+  CollideMask _mask;
+
+  friend class BulletWorld;
+};
+
+#include "bulletClosestHitSweepResult.I"
+
+#endif // __BULLET_CLOSEST_HIT_SWEEP_RESULT_H__

+ 47 - 0
panda/src/bullet/bulletConeShape.I

@@ -0,0 +1,47 @@
+// Filename: bulletConeShape.I
+// Created by:  enn0x (24Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletConeShape::
+~BulletConeShape() {
+
+  delete _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeShape::get_radius
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletConeShape::
+get_radius() const {
+
+  return _shape->getRadius();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeShape::get_height
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletConeShape::
+get_height() const {
+
+  return _shape->getHeight();
+}
+

+ 55 - 0
panda/src/bullet/bulletConeShape.cxx

@@ -0,0 +1,55 @@
+// Filename: bulletConeShape.cxx
+// Created by:  enn0x (24Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletConeShape.h"
+
+TypeHandle BulletConeShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletConeShape::
+BulletConeShape(float radius, float height, BulletUpAxis up) {
+
+  switch (up) {
+  case X_up:
+    _shape = new btConeShapeX(radius, height);
+    break;
+  case Y_up:
+    _shape = new btConeShape(radius, height);
+    break;
+  case Z_up:
+    _shape = new btConeShapeZ(radius, height);
+    break;
+  default:
+    bullet_cat.error() << "invalid up-axis:" << up << endl;
+    break;
+  }
+
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletConeShape::
+ptr() const {
+
+  return _shape;
+}
+

+ 67 - 0
panda/src/bullet/bulletConeShape.h

@@ -0,0 +1,67 @@
+// Filename: bulletConeShape.h
+// Created by:  enn0x (24Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONE_SHAPE_H__
+#define __BULLET_CONE_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletShape.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletConeShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletConeShape : public BulletShape {
+
+PUBLISHED:
+  BulletConeShape(float radius, float height, BulletUpAxis up=Z_up);
+  INLINE ~BulletConeShape();
+
+  INLINE float get_radius() const;
+  INLINE float get_height() const;
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btConeShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletConeShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletConeShape.I"
+
+#endif // __BULLET_CONE_SHAPE_H__

+ 25 - 0
panda/src/bullet/bulletConeTwistConstraint.I

@@ -0,0 +1,25 @@
+// Filename: bulletConeTwistConstraint.I
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeTwistConstraint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletConeTwistConstraint::
+~BulletConeTwistConstraint() {
+
+  delete _constraint;
+}
+

+ 95 - 0
panda/src/bullet/bulletConeTwistConstraint.cxx

@@ -0,0 +1,95 @@
+// Filename: bulletConeTwistConstraint.cxx
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletConeTwistConstraint.h"
+#include "bulletRigidBodyNode.h"
+
+#include "deg_2_rad.h"
+
+TypeHandle BulletConeTwistConstraint::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeTwistConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletConeTwistConstraint::
+BulletConeTwistConstraint(const BulletRigidBodyNode *node_a, 
+                          const TransformState &frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btTransform trans_a = LMatrix4f_to_btTrans(frame_a.get_mat());
+
+  _constraint = new btConeTwistConstraint(*ptr_a, trans_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeTwistConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletConeTwistConstraint::
+BulletConeTwistConstraint(const BulletRigidBodyNode *node_a,
+                          const BulletRigidBodyNode *node_b,
+                          const TransformState &frame_a,
+                          const TransformState &frame_b) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btTransform trans_a = LMatrix4f_to_btTrans(frame_a.get_mat());
+
+  btRigidBody *ptr_b = btRigidBody::upcast(node_b->get_object());
+  btTransform trans_b = LMatrix4f_to_btTrans(frame_b.get_mat());
+
+  _constraint = new btConeTwistConstraint(*ptr_a, *ptr_b, trans_a, trans_b);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeTwistConstraint::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btTypedConstraint *BulletConeTwistConstraint::
+ptr() const {
+
+  return _constraint;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeTwistConstraint::set_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConeTwistConstraint::
+set_limit(int index, float value) {
+ 
+  value = deg_2_rad(value);
+
+  _constraint->setLimit(index, value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConeTwistConstraint::set_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConeTwistConstraint::
+set_limit(float swing1, float swing2, float twist, float softness, float bias, float relaxation) {
+
+  swing1 = deg_2_rad(swing1);
+  swing2 = deg_2_rad(swing2);
+  twist  = deg_2_rad(twist);
+
+  _constraint->setLimit(swing1, swing2, twist, softness, bias, relaxation);
+}
+

+ 76 - 0
panda/src/bullet/bulletConeTwistConstraint.h

@@ -0,0 +1,76 @@
+// Filename: bulletConeTwistConstraint.h
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONE_TWIST_CONSTRAINT_H__
+#define __BULLET_CONE_TWIST_CONSTRAINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletConstraint.h"
+
+#include "transformState.h"
+
+class BulletRigidBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletConeTwistConstraint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletConeTwistConstraint : public BulletConstraint {
+
+PUBLISHED:
+  BulletConeTwistConstraint(const BulletRigidBodyNode *node_a, 
+                            const TransformState &frame_a);
+  BulletConeTwistConstraint(const BulletRigidBodyNode *node_a,
+                            const BulletRigidBodyNode *node_b,
+                            const TransformState &frame_a,
+                            const TransformState &frame_b);
+  INLINE ~BulletConeTwistConstraint();
+
+  void set_limit(int index, float value);
+  void set_limit(float swing1, float swing2, float twist, float softness=1.0f, float bias=0.3f, float relaxation=1.0f);
+
+public:
+  virtual btTypedConstraint *ptr() const;
+
+private:
+  btConeTwistConstraint *_constraint;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletConstraint::init_type();
+    register_type(_type_handle, "BulletConeTwistConstraint", 
+                  BulletConstraint::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletConeTwistConstraint.I"
+
+#endif // __BULLET_CONE_TWIST_CONSTRAINT_H__

+ 24 - 0
panda/src/bullet/bulletConstraint.I

@@ -0,0 +1,24 @@
+// Filename: bulletConstraint.I
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletConstraint::
+~BulletConstraint() {
+
+}
+

+ 85 - 0
panda/src/bullet/bulletConstraint.cxx

@@ -0,0 +1,85 @@
+// Filename: bulletConstraint.cxx
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletConstraint.h"
+#include "bulletRigidBodyNode.h"
+
+TypeHandle BulletConstraint::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::enable_feedback
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConstraint::
+enable_feedback(bool value) {
+
+  ptr()->enableFeedback(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::get_applied_impulse
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletConstraint::
+get_applied_impulse() const {
+
+  return ptr()->getAppliedImpulse();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::set_dbg_draw_size
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConstraint::
+set_debug_draw_size(float size) {
+
+  ptr()->setDbgDrawSize(size);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::get_dbg_draw_size
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletConstraint::
+get_debug_draw_size() {
+
+  return ptr()->getDbgDrawSize();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::get_rigid_body_a
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletRigidBodyNode *BulletConstraint::
+get_rigid_body_a() {
+
+  return (BulletRigidBodyNode *)ptr()->getRigidBodyA().getUserPointer();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConstraint::get_rigid_body_b
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletRigidBodyNode *BulletConstraint::
+get_rigid_body_b() {
+
+  return (BulletRigidBodyNode *)ptr()->getRigidBodyB().getUserPointer();
+}
+

+ 71 - 0
panda/src/bullet/bulletConstraint.h

@@ -0,0 +1,71 @@
+// Filename: bulletConstraint.h
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONSTRAINT_H__
+#define __BULLET_CONSTRAINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+#include "typedReferenceCount.h"
+
+class BulletRigidBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletConstraint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletConstraint : public TypedReferenceCount {
+
+PUBLISHED:
+  INLINE virtual ~BulletConstraint();
+
+  BulletRigidBodyNode *get_rigid_body_a();
+  BulletRigidBodyNode *get_rigid_body_b();
+
+  void enable_feedback(bool value);
+  void set_debug_draw_size(float size);
+
+  float get_applied_impulse() const;
+  float get_debug_draw_size();
+
+public:
+  virtual btTypedConstraint *ptr() const = 0;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedReferenceCount::init_type();
+    register_type(_type_handle, "BulletConstraint", 
+                  TypedReferenceCount::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletConstraint.I"
+
+#endif // __BULLET_CONSTRAINT_H__

+ 128 - 0
panda/src/bullet/bulletContactCallbacks.h

@@ -0,0 +1,128 @@
+// Filename: bulletContactCallbacks.h
+// Created by:  enn0x (10Apr10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONTACT_CALLBACKS_H__
+#define __BULLET_CONTACT_CALLBACKS_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+#include "config_bullet.h" // required for: bullet_cat.debug()
+
+#include "event.h"
+#include "eventQueue.h"
+#include "eventParameter.h"
+#include "eventStorePandaNode.h"
+#include "pandaNode.h"
+
+struct UserPersitentData {
+  PT(PandaNode) node0;
+  PT(PandaNode) node1;
+};
+
+////////////////////////////////////////////////////////////////////
+//     Function: contact_added_callback
+//  Description: 
+////////////////////////////////////////////////////////////////////
+static bool
+contact_added_callback(btManifoldPoint &cp,
+                       const btCollisionObject *obj0,
+                       int id0,
+                       int index0,
+                       const btCollisionObject *obj1,
+                       int id1,
+                       int index1) {
+
+  if (cp.m_userPersistentData == NULL) {
+    PT(PandaNode) node0 = (PandaNode *)obj0->getUserPointer();
+    PT(PandaNode) node1 = (PandaNode *)obj1->getUserPointer();
+
+    bullet_cat.debug() << "contact added: " << cp.m_userPersistentData << endl;
+
+    // Gather persistent data
+    UserPersitentData *data = new UserPersitentData();
+    data->node0 = node0;
+    data->node1 = node1;
+
+    cp.m_userPersistentData = (void *)data;
+
+    // Send event
+    if (bullet_enable_contact_events) {
+
+      Event *event = new Event("bullet-contact-added");
+      event->add_parameter(EventParameter(new EventStorePandaNode(node0)));
+      event->add_parameter(EventParameter(new EventStorePandaNode(node1)));
+
+      EventQueue::get_global_event_queue()->queue_event(event);
+    }
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: contact_processed_callback
+//  Description: 
+////////////////////////////////////////////////////////////////////
+static bool
+contact_processed_callback(btManifoldPoint &cp,
+                           void *body0,
+                           void *body1) {
+
+/*
+  btCollisionObject *obj0 = (btCollisionObject *)body0;
+  btCollisionObject *colobj1Obj1 = (btCollisionObject *)body1;
+
+  int flags0 = obj0->getCollisionFlags();
+  int flags1 = obj1->getCollisionFlags();
+
+  if ((flags0 & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)
+   || (flags1 & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)) {
+
+    // do something...
+  }
+*/
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: contact_destroyed_callback
+//  Description: 
+////////////////////////////////////////////////////////////////////
+static bool
+contact_destroyed_callback(void *userPersistentData) {
+
+  bullet_cat.debug() << "contact removed: " << userPersistentData << endl;
+
+  UserPersitentData *data = (UserPersitentData *)userPersistentData;
+
+  // Send event
+  if (bullet_enable_contact_events) {
+
+    Event *event = new Event("bullet-contact-destroyed");
+    event->add_parameter(EventParameter(new EventStorePandaNode(data->node0)));
+    event->add_parameter(EventParameter(new EventStorePandaNode(data->node1)));
+
+    EventQueue::get_global_event_queue()->queue_event(event);
+  }
+
+  // Delete persitent data
+  delete data;
+
+  return false;
+}
+
+#endif // __BULLET_CONTACT_CALLBACKS_H__

+ 115 - 0
panda/src/bullet/bulletContactResult.I

@@ -0,0 +1,115 @@
+// Filename: bulletContactResult.I
+// Created by:  enn0x (08Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_node0
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const PandaNode *BulletContact::
+get_node0() const {
+
+  return _obj0 ? (PandaNode *)_obj0->getUserPointer() : NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_node1
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const PandaNode *BulletContact::
+get_node1() const {
+
+  return _obj1 ? (PandaNode *)_obj1->getUserPointer() : NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_manifold_point
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const BulletManifoldPoint *BulletContact::
+get_manifold_point() const {
+
+  return new BulletManifoldPoint(*_mp);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_idx0
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const int BulletContact::
+get_idx0() const {
+
+  return _idx0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_idx1
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const int BulletContact::
+get_idx1() const {
+
+  return _idx1;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_part_id0
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const int BulletContact::
+get_part_id0() const {
+
+  return _part_id0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_part_id1
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const int BulletContact::
+get_part_id1() const {
+
+  return _part_id1;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_num_contacts
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int BulletContactResult::
+get_num_contacts() const {
+
+  return _contacts.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::get_contact
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const BulletContact &BulletContactResult::
+get_contact(int idx) const {
+
+  nassertr(idx >= 0 && idx < (int)_contacts.size(), _empty);
+  return _contacts[idx];
+}
+

+ 54 - 0
panda/src/bullet/bulletContactResult.cxx

@@ -0,0 +1,54 @@
+// Filename: bulletContactResult.cxx
+// Created by:  enn0x (08Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletContactResult.h"
+
+BulletContact BulletContactResult::_empty;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletContactResult::
+BulletContactResult() : btCollisionWorld::ContactResultCallback() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletContactResult::addSingleResult
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+btScalar BulletContactResult::
+addSingleResult(btManifoldPoint &mp,
+                const btCollisionObject *obj0, int part_id0, int idx0,
+                const btCollisionObject *obj1, int part_id1, int idx1) {
+
+
+  BulletContact contact;
+
+  contact._mp = &mp;
+  contact._obj0 = obj0;
+  contact._obj1 = obj1;
+  contact._part_id0 = part_id0;
+  contact._part_id1 = part_id1;
+  contact._idx0 = idx0;
+  contact._idx1 = idx1;
+
+  _contacts.push_back(contact);
+
+  return 1.0f;
+}
+

+ 81 - 0
panda/src/bullet/bulletContactResult.h

@@ -0,0 +1,81 @@
+// Filename: bulletContactResult.h
+// Created by:  enn0x (08Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONTACT_RESULT_H__
+#define __BULLET_CONTACT_RESULT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bulletManifoldPoint.h"
+
+#include "pvector.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletContact
+// Description : 
+////////////////////////////////////////////////////////////////////
+struct EXPCL_PANDABULLET BulletContact {
+
+PUBLISHED:
+  INLINE const BulletManifoldPoint *get_manifold_point() const;
+  INLINE const PandaNode *get_node0() const;
+  INLINE const PandaNode *get_node1() const;
+  INLINE const int get_idx0() const;
+  INLINE const int get_idx1() const;
+  INLINE const int get_part_id0() const;
+  INLINE const int get_part_id1() const;
+
+private:
+  btManifoldPoint *_mp;
+  const btCollisionObject *_obj0;
+  const btCollisionObject *_obj1;
+  int _part_id0;
+  int _part_id1;
+  int _idx0;
+  int _idx1;
+
+  friend struct BulletContactResult;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletContactResult
+// Description : 
+////////////////////////////////////////////////////////////////////
+struct EXPCL_PANDABULLET BulletContactResult : public btCollisionWorld::ContactResultCallback {
+
+PUBLISHED:
+  INLINE int get_num_contacts() const;
+  INLINE const BulletContact &get_contact(int idx) const;
+  MAKE_SEQ(get_contacts, get_num_contacts, get_contact);
+
+public:
+  virtual btScalar addSingleResult(btManifoldPoint &mp,
+      const btCollisionObject *obj0, int part_id0, int idx0,
+      const btCollisionObject *obj1, int part_id1, int idx1);
+
+protected:
+  BulletContactResult();
+
+private:
+  static BulletContact _empty;
+
+  pvector<BulletContact> _contacts;
+
+  friend class BulletWorld;
+};
+
+#include "bulletContactResult.I"
+
+#endif // __BULLET_CONTACT_RESULT_H__

+ 25 - 0
panda/src/bullet/bulletConvexHullShape.I

@@ -0,0 +1,25 @@
+// Filename: bulletConvexHullShape.I
+// Created by:  enn0x (26Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletConvexHullShape::
+~BulletConvexHullShape() {
+
+  delete _shape;
+}
+

+ 102 - 0
panda/src/bullet/bulletConvexHullShape.cxx

@@ -0,0 +1,102 @@
+// Filename: bulletConvexHullShape.cxx
+// Created by:  enn0x (26Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletConvexHullShape.h"
+
+#include "nodePathCollection.h"
+#include "geomNode.h"
+#include "geomVertexReader.h"
+
+TypeHandle BulletConvexHullShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletConvexHullShape::
+BulletConvexHullShape() {
+
+  _shape = new btConvexHullShape(NULL, 0);
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletConvexHullShape::
+ptr() const {
+
+  return _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::add_point
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+add_point(const LPoint3f &p) {
+
+  _shape->addPoint(LVecBase3f_to_btVector3(p));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+add_array(const PTA_LVecBase3f &points) {
+
+  _shape = new btConvexHullShape(NULL, 0);
+  _shape->setUserPointer(this);
+
+  PTA_LVecBase3f::const_iterator it;
+  for (it=points.begin(); it!=points.end(); it++) {
+    LVecBase3f v = *it;
+    _shape->addPoint(LVecBase3f_to_btVector3(v));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+add_geom(const Geom *geom) {
+
+  // Collect points
+  pvector<LPoint3f> points;
+
+  CPT(GeomVertexData) vdata = geom->get_vertex_data();
+  GeomVertexReader reader = GeomVertexReader(vdata, InternalName::get_vertex());
+
+  while (!reader.is_at_end()) {
+    points.push_back(reader.get_data3f());
+  }
+
+  // Create shape
+  _shape = new btConvexHullShape(NULL, 0);
+  _shape->setUserPointer(this);
+
+  pvector<LPoint3f>::const_iterator it;
+  for (it=points.begin(); it!=points.end(); it++) {
+    _shape->addPoint(LVecBase3f_to_btVector3(*it));
+  }
+}
+

+ 71 - 0
panda/src/bullet/bulletConvexHullShape.h

@@ -0,0 +1,71 @@
+// Filename: bulletConvexHullShape.h
+// Created by:  enn0x (26Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONVEX_HULL_SHAPE_H__
+#define __BULLET_CONVEX_HULL_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bulletShape.h"
+
+#include "lpoint3.h"
+#include "geom.h"
+#include "pta_LVecBase3f.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletConvexHullShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletConvexHullShape : public BulletShape {
+
+PUBLISHED:
+  BulletConvexHullShape();
+  INLINE ~BulletConvexHullShape();
+
+  void add_point(const LPoint3f &p);
+  void add_array(const PTA_LVecBase3f &points);
+  void add_geom(const Geom *geom);
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btConvexHullShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletConvexHullShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletConvexHullShape.I"
+
+#endif // __BULLET_CONVEX_HULL_SHAPE_H__

+ 36 - 0
panda/src/bullet/bulletConvexPointCloudShape.I

@@ -0,0 +1,36 @@
+// Filename: bulletConvexPointCloudShape.I
+// Created by:  enn0x (30Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexPointCloudShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletConvexPointCloudShape::
+~BulletConvexPointCloudShape() {
+
+  delete _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexPointCloudShape::get_num_points
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int BulletConvexPointCloudShape::
+get_num_points() const {
+
+  return _shape->getNumPoints();
+}
+

+ 91 - 0
panda/src/bullet/bulletConvexPointCloudShape.cxx

@@ -0,0 +1,91 @@
+// Filename: bulletConvexPointCloudShape.cxx
+// Created by:  enn0x (30Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletConvexPointCloudShape.h"
+
+#include "geomVertexReader.h"
+
+TypeHandle BulletConvexPointCloudShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexPointCloudShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletConvexPointCloudShape::
+BulletConvexPointCloudShape(const PTA_LVecBase3f &points, LVecBase3f scale) {
+
+  btVector3 btScale = LVecBase3f_to_btVector3(scale);
+
+  // Convert points
+  btVector3 *btPoints = new btVector3[points.size()];
+
+  int i = 0;
+  PTA_LVecBase3f::const_iterator it;
+  for (it=points.begin(); it!=points.end(); it++) {
+    btPoints[i] = LVecBase3f_to_btVector3(*it);
+    i++;
+  }
+
+  // Create shape
+  _shape = new btConvexPointCloudShape(btPoints, points.size(), btScale);
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexPointCloudShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletConvexPointCloudShape::
+ptr() const {
+
+  return _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexPointCloudShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletConvexPointCloudShape::
+BulletConvexPointCloudShape(const Geom *geom, LVecBase3f scale) {
+
+  btVector3 btScale = LVecBase3f_to_btVector3(scale);
+
+  // Collect points
+  pvector<LPoint3f> points;
+
+  CPT(GeomVertexData) vdata = geom->get_vertex_data();
+  GeomVertexReader reader = GeomVertexReader(vdata, InternalName::get_vertex());
+
+  while (!reader.is_at_end()) {
+    points.push_back(reader.get_data3f());
+  }
+
+  // Convert points
+  btVector3 *btPoints = new btVector3[points.size()];
+
+  int i = 0;
+  pvector<LPoint3f>::const_iterator it;
+  for (it=points.begin(); it!=points.end(); it++) {
+    btPoints[i] = LVecBase3f_to_btVector3(*it);
+    i++;
+  }
+
+  // Create
+  _shape = new btConvexPointCloudShape(btPoints, points.size(), btScale);
+  _shape->setUserPointer(this);
+}
+

+ 69 - 0
panda/src/bullet/bulletConvexPointCloudShape.h

@@ -0,0 +1,69 @@
+// Filename: bulletConvexPointCloudShape.h
+// Created by:  enn0x (30Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CONVEX_POINT_CLOUD_SHAPE_H__
+#define __BULLET_CONVEX_POINT_CLOUD_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bulletShape.h"
+
+#include "geom.h"
+#include "pta_LVecBase3f.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletConvexPointCloudShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletConvexPointCloudShape : public BulletShape {
+
+PUBLISHED:
+  BulletConvexPointCloudShape(const PTA_LVecBase3f &points, LVecBase3f scale=LVecBase3f(1.));
+  BulletConvexPointCloudShape(const Geom *geom, LVecBase3f scale=LVecBase3f(1.));
+  INLINE ~BulletConvexPointCloudShape();
+
+  INLINE int get_num_points() const;
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btConvexPointCloudShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletConvexPointCloudShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletConvexPointCloudShape.I"
+
+#endif // __BULLET_CONVEX_POINT_CLOUD_SHAPE_H__

+ 58 - 0
panda/src/bullet/bulletCylinderShape.I

@@ -0,0 +1,58 @@
+// Filename: bulletCylinderShape.I
+// Created by:  enn0x (17Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletCylinderShape::
+~BulletCylinderShape() {
+
+  delete _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::get_radius
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletCylinderShape::
+get_radius() const {
+
+  return _shape->getRadius();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::get_half_extents_without_marging
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase3f BulletCylinderShape::
+get_half_extents_without_marging() const {
+
+  return btVector3_to_LVecBase3f(_shape->getHalfExtentsWithoutMargin());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::get_half_extents_with_marging
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase3f BulletCylinderShape::
+get_half_extents_with_marging() const {
+
+  return btVector3_to_LVecBase3f(_shape->getHalfExtentsWithMargin());
+}
+

+ 83 - 0
panda/src/bullet/bulletCylinderShape.cxx

@@ -0,0 +1,83 @@
+// Filename: bulletCylinderShape.cxx
+// Created by:  enn0x (17Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletCylinderShape.h"
+
+TypeHandle BulletCylinderShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletCylinderShape::
+BulletCylinderShape(const LVector3f &half_extents, BulletUpAxis up) {
+
+  btVector3 btHalfExtents = LVecBase3f_to_btVector3(half_extents);
+
+  switch (up) {
+  case X_up:
+    _shape = new btCylinderShapeX(btHalfExtents);
+    break;
+  case Y_up:
+    _shape = new btCylinderShape(btHalfExtents);
+    break;
+  case Z_up:
+    _shape = new btCylinderShapeZ(btHalfExtents);
+    break;
+  default:
+    bullet_cat.error() << "invalid up-axis:" << up << endl;
+    break;
+  }
+
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletCylinderShape::
+BulletCylinderShape(float radius, float height, BulletUpAxis up) {
+
+  switch (up) {
+  case X_up:
+    _shape = new btCylinderShapeX(btVector3(0.5 * height, radius, 0.0f));
+    break;
+  case Y_up:
+    _shape = new btCylinderShape(btVector3(radius, 0.5 * height, 0.0f));
+    break;
+  case Z_up:
+    _shape = new btCylinderShapeZ(btVector3(radius, 0.0f, 0.5 * height));
+    break;
+  default:
+    bullet_cat.error() << "invalid up-axis:" << up << endl;
+    break;
+  }
+
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletCylinderShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletCylinderShape::
+ptr() const {
+
+  return _shape;
+}
+

+ 69 - 0
panda/src/bullet/bulletCylinderShape.h

@@ -0,0 +1,69 @@
+// Filename: bulletCylinderShape.h
+// Created by:  enn0x (17Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_CYLINDER_SHAPE_H__
+#define __BULLET_CYLINDER_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletShape.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletCylinderShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletCylinderShape : public BulletShape {
+
+PUBLISHED:
+  BulletCylinderShape(const LVector3f &half_extents, BulletUpAxis up=Z_up);
+  BulletCylinderShape(float radius, float height, BulletUpAxis up=Z_up);
+  INLINE ~BulletCylinderShape();
+
+  INLINE float get_radius() const;
+  INLINE LVecBase3f get_half_extents_without_marging() const;
+  INLINE LVecBase3f get_half_extents_with_marging() const;
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btCylinderShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletCylinderShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletCylinderShape.I"
+
+#endif // __BULLET_CYLINDER_SHAPE_H__

+ 47 - 0
panda/src/bullet/bulletDebugNode.I

@@ -0,0 +1,47 @@
+// Filename: bulletDebugNode.I
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletDebugNode::
+~BulletDebugNode() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::set_verbose
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void BulletDebugNode::
+set_verbose(bool verbose) {
+
+  _verbose = verbose;
+  draw_mask_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::get_verbose
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletDebugNode::
+get_verbose() const {
+
+  return _verbose;
+}
+

+ 392 - 0
panda/src/bullet/bulletDebugNode.cxx

@@ -0,0 +1,392 @@
+// Filename: bulletDebugNode.cxx
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletDebugNode.h"
+
+#include "geomVertexFormat.h"
+#include "geomVertexWriter.h"
+
+TypeHandle BulletDebugNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletDebugNode::
+BulletDebugNode(const char *name) : GeomNode(name), _verbose(false) {
+
+  set_overall_hidden(true);
+
+  _vdata = new GeomVertexData("", GeomVertexFormat::get_v3c4(), Geom::UH_stream);
+
+  // Lines
+  _prim_lines = new GeomLines(Geom::UH_stream);
+  _prim_lines->set_shade_model(Geom::SM_uniform);
+
+  _geom_lines = new Geom(_vdata);
+  _geom_lines->add_primitive(_prim_lines);
+
+  add_geom(_geom_lines);
+
+  // Triangles
+  _prim_triangles = new GeomTriangles(Geom::UH_stream);
+  _prim_triangles->set_shade_model(Geom::SM_uniform);
+
+  _geom_triangles = new Geom(_vdata);
+  _geom_triangles->add_primitive(_prim_triangles);
+
+  add_geom(_geom_triangles);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::safe_to_flatten
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to flatten out
+//               this particular kind of Node by duplicating
+//               instances, false otherwise (for instance, a Camera
+//               cannot be safely flattened, because the Camera
+//               pointer itself is meaningful).
+////////////////////////////////////////////////////////////////////
+bool BulletDebugNode::
+safe_to_flatten() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::safe_to_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to transform
+//               this particular kind of Node by calling the xform()
+//               method, false otherwise.  For instance, it's usually
+//               a bad idea to attempt to xform a Character.
+////////////////////////////////////////////////////////////////////
+bool BulletDebugNode::
+safe_to_transform() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::safe_to_modify_transform
+//       Access: Public, Virtual
+//  Description: Returns true if it is safe to automatically adjust
+//               the transform on this kind of node.  Usually, this is
+//               only a bad idea if the user expects to find a
+//               particular transform on the node.
+//
+//               ModelNodes with the preserve_transform flag set are
+//               presently the only kinds of nodes that should not
+//               have their transform even adjusted.
+////////////////////////////////////////////////////////////////////
+bool BulletDebugNode::
+safe_to_modify_transform() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::safe_to_combine
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to combine this
+//               particular kind of PandaNode with other kinds of
+//               PandaNodes of compatible type, adding children or
+//               whatever.  For instance, an LODNode should not be
+//               combined with any other PandaNode, because its set of
+//               children is meaningful.
+////////////////////////////////////////////////////////////////////
+bool BulletDebugNode::
+safe_to_combine() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::safe_to_combine_children
+//       Access: Public, Virtual
+//  Description: Returns true if it is generally safe to combine the
+//               children of this PandaNode with each other.  For
+//               instance, an LODNode's children should not be
+//               combined with each other, because the set of children
+//               is meaningful.
+////////////////////////////////////////////////////////////////////
+bool BulletDebugNode::
+safe_to_combine_children() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::safe_to_flatten_below
+//       Access: Public, Virtual
+//  Description: Returns true if a flatten operation may safely
+//               continue past this node, or false if nodes below this
+//               node may not be molested.
+////////////////////////////////////////////////////////////////////
+bool BulletDebugNode::
+safe_to_flatten_below() const {
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::draw_mask_changed
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+draw_mask_changed() {
+
+  if (is_overall_hidden()) {
+    _drawer.setDebugMode(DebugDraw::DBG_NoDebug);
+  }
+  else {
+    if (_verbose) {
+      _drawer.setDebugMode(DebugDraw::DBG_DrawWireframe |
+                           DebugDraw::DBG_DrawAabb |
+                           DebugDraw::DBG_DrawContactPoints |
+                           DebugDraw::DBG_DrawConstraints |
+                           DebugDraw::DBG_DrawConstraintLimits);
+    }
+    else {
+      _drawer.setDebugMode(DebugDraw::DBG_DrawWireframe |
+                           DebugDraw::DBG_DrawConstraints |
+                           DebugDraw::DBG_FastWireframe);
+
+    }
+  } 
+}
+
+/*
+DBG_DrawWireframe
+DBG_DrawAabb
+DBG_DrawText
+DBG_DrawFeaturesText
+DBG_DrawContactPoints
+DBG_DrawConstraints
+DBG_DrawConstraintLimits
+DBG_NoDeactivation
+DBG_NoHelpText
+DBG_EnableSatComparison
+DBG_DisableBulletLCP
+DBG_ProfileTimings
+DBG_EnableCCD
+DBG_FastWireframe
+*/
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::post_step
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+post_step(btDynamicsWorld *world) {
+
+  // Collect debug geometry data
+  world->debugDrawWorld();
+
+  // Render collected data
+  _prim_lines->clear_vertices();
+  _prim_triangles->clear_vertices();
+
+  GeomVertexWriter vwriter(_vdata, InternalName::get_vertex());
+  GeomVertexWriter cwriter(_vdata, InternalName::get_color());
+
+  int v = 0;
+
+  pvector<Line>::const_iterator lit;
+  pvector<Triangle>::const_iterator tit;
+
+  for (lit = _drawer._lines.begin(); lit != _drawer._lines.end(); lit++) {
+    Line line = *lit;
+
+    vwriter.add_data3f(line._p0);
+    cwriter.add_data4f(line._color);
+    vwriter.add_data3f(line._p1);
+    cwriter.add_data4f(line._color);
+
+    _prim_lines->add_vertex(v++);
+    _prim_lines->add_vertex(v++);
+
+    _prim_lines->close_primitive();
+  }
+
+  for (tit = _drawer._triangles.begin(); tit != _drawer._triangles.end(); tit++) {
+    Triangle tri = *tit;
+
+    vwriter.add_data3f(tri._p0);
+    cwriter.add_data4f(tri._color);
+    vwriter.add_data3f(tri._p1);
+    cwriter.add_data4f(tri._color);
+    vwriter.add_data3f(tri._p2);
+    cwriter.add_data4f(tri._color);
+
+    _prim_triangles->add_vertex(v++);
+    _prim_triangles->add_vertex(v++);
+    _prim_triangles->add_vertex(v++);
+
+    _prim_triangles->close_primitive();
+  }
+
+  // Clear the collected data again
+  _drawer._lines.clear();
+  _drawer._triangles.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::setDebugMode
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+setDebugMode(int mode) {
+
+  _mode = mode;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::getDebugMode
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int BulletDebugNode::DebugDraw::
+getDebugMode() const {
+
+  return _mode;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::reportErrorWarning
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+reportErrorWarning(const char *warning) {
+
+  bullet_cat.error() << warning << endl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::drawLine
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color) {
+
+  float r = color.getX();
+  float g = color.getY();
+  float b = color.getZ();
+
+  Line line;
+
+  line._p0 = LVecBase3f(from.getX(), from.getY(), from.getZ());
+  line._p1 = LVecBase3f(to.getX(), to.getY(), to.getZ());
+  line._color = Colorf(r, g, b, 1.0f);
+
+  _lines.push_back(line);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::drawTriangle
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &color, btScalar) {
+
+  float r = color.getX();
+  float g = color.getY();
+  float b = color.getZ();
+
+  Triangle tri;
+
+  tri._p0 = LVecBase3f(v0.getX(), v0.getY(), v0.getZ());
+  tri._p1 = LVecBase3f(v1.getX(), v1.getY(), v1.getZ());
+  tri._p2 = LVecBase3f(v2.getX(), v2.getY(), v2.getZ());
+  tri._color = Colorf(r, g, b, 1.0f);
+
+  _triangles.push_back(tri);
+
+
+  // Draw the triangle's normal
+/*
+  btVector3 x1 = v1 - v0;
+  btVector3 x2 = v2 - v0;
+  btVector3 normal = v1.cross(v2).normalize();
+
+  btVector3 from = (v0 + v1 + v2) * 0.3333;
+  btVector3 to = from + normal;
+  drawLine(from, to, color);
+*/
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::drawTriangle
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &n0, const btVector3 &n1, const btVector3 &n2, const btVector3 &color, btScalar alpha) {
+
+  // TODO
+  bullet_cat.debug() << "drawTriangle(2) - not yet implemented!" << endl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::drawContactPoint
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+drawContactPoint(const btVector3 &point, const btVector3 &normal, btScalar distance, int lifetime, const btVector3 &color) {
+
+  const btVector3 to = point + normal * distance;
+  const btVector3 &from = point;
+
+  drawLine(from, to, color);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::draw3dText
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+draw3dText(const btVector3 &location, const char *text) {
+
+  // TODO
+  bullet_cat.debug() << "draw3dText - not yet implemented!" << endl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::DebugDraw::drawSphere
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::DebugDraw::
+drawSphere(btScalar radius, const btTransform &transform, const btVector3 &color) {
+
+  btVector3 center = transform.getOrigin();
+
+  const btVector3 xoffs = transform.getBasis() * btVector3(1, 0, 0);
+  const btVector3 yoffs = transform.getBasis() * btVector3(0, 1, 0);
+  const btVector3 zoffs = transform.getBasis() * btVector3(0, 0, 1);
+
+  drawArc(center, xoffs, yoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
+  drawArc(center, yoffs, zoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
+  drawArc(center, zoffs, xoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
+}
+

+ 135 - 0
panda/src/bullet/bulletDebugNode.h

@@ -0,0 +1,135 @@
+// Filename: bulletDebugNode.h
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_DEBUG_NODE_H__
+#define __BULLET_DEBUG_NODE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+#include "geomNode.h"
+#include "geom.h"
+#include "geomVertexData.h"
+#include "geomLines.h"
+#include "geomTriangles.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletDebugNode
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletDebugNode : public GeomNode {
+
+PUBLISHED:
+  BulletDebugNode(const char *name="debug");
+  INLINE ~BulletDebugNode();
+
+  virtual void draw_mask_changed();
+
+  INLINE void set_verbose(bool verbose);
+  INLINE bool get_verbose() const;
+
+public:
+  virtual bool safe_to_flatten() const;
+  virtual bool safe_to_transform() const;
+  virtual bool safe_to_modify_transform() const;
+  virtual bool safe_to_combine() const;
+  virtual bool safe_to_combine_children() const;
+  virtual bool safe_to_flatten_below() const;
+
+private:
+  void post_step(btDynamicsWorld *world);
+
+  struct Line {
+    LVecBase3f _p0;
+    LVecBase3f _p1;
+    Colorf _color;
+  };
+
+  struct Triangle {
+    LVecBase3f _p0;
+    LVecBase3f _p1;
+    LVecBase3f _p2;
+    Colorf _color;
+  };
+
+  class DebugDraw : public btIDebugDraw {
+
+  public:
+    DebugDraw() {};
+
+    virtual void setDebugMode(int mode);
+    virtual int getDebugMode() const;
+    virtual void reportErrorWarning(const char *warning);
+
+    virtual void drawLine(const btVector3 &from, const btVector3 &to,
+      const btVector3 &color);
+    virtual void drawContactPoint(const btVector3 &point, 
+      const btVector3 &normal, btScalar distance, int lifetime, 
+      const btVector3 &color);
+    virtual void draw3dText(const btVector3 &location, const char *text);
+    virtual void drawTriangle(const btVector3 &v0, const btVector3 &v1, 
+      const btVector3 &v2, const btVector3 &color, btScalar);
+    virtual void drawTriangle(const btVector3 &v0, const btVector3 &v1, 
+      const btVector3 &v2, const btVector3 &n0, const btVector3 &n1, 
+      const btVector3 &n2, const btVector3 &color, btScalar alpha);
+    virtual void drawSphere(btScalar radius, const btTransform &transform, 
+      const btVector3 &color);
+
+  public:
+    pvector<Line> _lines;
+    pvector<Triangle> _triangles;
+
+  private:
+    int _mode;
+  };
+
+  DebugDraw _drawer;
+
+  bool _verbose;
+
+  PT(GeomVertexData) _vdata;
+  PT(Geom) _geom_lines;
+  PT(GeomLines) _prim_lines;
+  PT(Geom) _geom_triangles;
+  PT(GeomTriangles) _prim_triangles;
+
+  friend class BulletWorld;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PandaNode::init_type();
+    register_type(_type_handle, "BulletDebugNode", 
+                  PandaNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletDebugNode.I"
+
+#endif // __BULLET_DEBUG_NODE_H__
+

+ 25 - 0
panda/src/bullet/bulletDistanceConstraint.I

@@ -0,0 +1,25 @@
+// Filename: bulletDistanceConstraint.I
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletDistanceConstraint::
+~BulletDistanceConstraint() {
+
+  delete _constraint;
+}
+

+ 111 - 0
panda/src/bullet/bulletDistanceConstraint.cxx

@@ -0,0 +1,111 @@
+// Filename: bulletDistanceConstraint.cxx
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletDistanceConstraint.h"
+#include "bulletRigidBodyNode.h"
+
+TypeHandle BulletDistanceConstraint::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletDistanceConstraint::
+BulletDistanceConstraint(const BulletRigidBodyNode *node_a, 
+                         const LPoint3f &pivot_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btVector3 pos_a = LVecBase3f_to_btVector3(pivot_a);
+
+  _constraint = new btPoint2PointConstraint(*ptr_a, pos_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletDistanceConstraint::
+BulletDistanceConstraint(const BulletRigidBodyNode *node_a,
+                         const BulletRigidBodyNode *node_b,
+                         const LPoint3f &pivot_a,
+                         const LPoint3f &pivot_b) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btVector3 pos_a = LVecBase3f_to_btVector3(pivot_a);
+
+  btRigidBody *ptr_b = btRigidBody::upcast(node_b->get_object());
+  btVector3 pos_b = LVecBase3f_to_btVector3(pivot_b);
+
+  _constraint = new btPoint2PointConstraint(*ptr_a, *ptr_b, pos_a, pos_b);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btTypedConstraint *BulletDistanceConstraint::
+ptr() const {
+
+  return _constraint;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::set_pivot_a
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletDistanceConstraint::
+set_pivot_a(const LPoint3f &pivot_a) {
+
+  nassertv(!pivot_a.is_nan());
+  _constraint->setPivotA(LVecBase3f_to_btVector3(pivot_a));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::set_pivot_b
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletDistanceConstraint::
+set_pivot_b(const LPoint3f &pivot_b) {
+
+  nassertv(!pivot_b.is_nan());
+  _constraint->setPivotA(LVecBase3f_to_btVector3(pivot_b));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::set_pivot_in_a
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletDistanceConstraint::
+get_pivot_in_a() const {
+
+  return btVector3_to_LPoint3f(_constraint->getPivotInA());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDistanceConstraint::set_pivot_in_b
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletDistanceConstraint::
+get_pivot_in_b() const {
+
+  return btVector3_to_LPoint3f(_constraint->getPivotInB());
+}
+

+ 79 - 0
panda/src/bullet/bulletDistanceConstraint.h

@@ -0,0 +1,79 @@
+// Filename: bulletDistanceConstraint.h
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_DISTANCE_CONSTRAINT_H__
+#define __BULLET_DISTANCE_CONSTRAINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletConstraint.h"
+
+#include "lpoint3.h"
+
+class BulletRigidBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletDistanceConstraint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletDistanceConstraint : public BulletConstraint {
+
+PUBLISHED:
+  BulletDistanceConstraint(const BulletRigidBodyNode *node_a, 
+                           const LPoint3f &pivot_a);
+  BulletDistanceConstraint(const BulletRigidBodyNode *node_a,
+                           const BulletRigidBodyNode *node_b,
+                           const LPoint3f &pivot_a,
+                           const LPoint3f &pivot_b);
+  INLINE ~BulletDistanceConstraint();
+
+  void set_pivot_a(const LPoint3f &pivot_a);
+  void set_pivot_b(const LPoint3f &pivot_b);
+
+  LPoint3f get_pivot_in_a() const;
+  LPoint3f get_pivot_in_b() const;
+
+public:
+  virtual btTypedConstraint *ptr() const;
+
+private:
+  btPoint2PointConstraint *_constraint;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletConstraint::init_type();
+    register_type(_type_handle, "BulletDistanceConstraint", 
+                  BulletConstraint::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletDistanceConstraint.I"
+
+#endif // __BULLET_DISTANCE_CONSTRAINT_H__

+ 25 - 0
panda/src/bullet/bulletGenericConstraint.I

@@ -0,0 +1,25 @@
+// Filename: bulletGenericConstraint.I
+// Created by:  enn0x (02Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletGenericConstraint::
+~BulletGenericConstraint() {
+
+  delete _constraint;
+}
+

+ 115 - 0
panda/src/bullet/bulletGenericConstraint.cxx

@@ -0,0 +1,115 @@
+// Filename: bulletGenericConstraint.cxx
+// Created by:  enn0x (02Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletGenericConstraint.h"
+#include "bulletRigidBodyNode.h"
+
+TypeHandle BulletGenericConstraint::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletGenericConstraint::
+BulletGenericConstraint(const BulletRigidBodyNode *node_a, 
+                        const TransformState &frame_a,
+                        bool use_frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btTransform trans_a = LMatrix4f_to_btTrans(frame_a.get_mat());
+
+  _constraint = new btGeneric6DofConstraint(*ptr_a, trans_a, use_frame_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletGenericConstraint::
+BulletGenericConstraint(const BulletRigidBodyNode *node_a,
+                        const BulletRigidBodyNode *node_b,
+                        const TransformState &frame_a,
+                        const TransformState &frame_b,
+                        bool use_frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btTransform trans_a = LMatrix4f_to_btTrans(frame_a.get_mat());
+
+  btRigidBody *ptr_b = btRigidBody::upcast(node_b->get_object());
+  btTransform trans_b = LMatrix4f_to_btTrans(frame_b.get_mat());
+
+  _constraint = new btGeneric6DofConstraint(*ptr_a, *ptr_b, trans_a, trans_b, use_frame_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btTypedConstraint *BulletGenericConstraint::
+ptr() const {
+
+  return _constraint;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::set_linear_lower_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGenericConstraint::
+set_linear_lower_limit(const LPoint3f &limit) {
+
+  nassertv(!limit.is_nan());
+  _constraint->setLinearLowerLimit(LVecBase3f_to_btVector3(limit));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::set_linear_upper_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGenericConstraint::
+set_linear_upper_limit(const LPoint3f &limit) {
+
+  nassertv(!limit.is_nan());
+  _constraint->setLinearUpperLimit(LVecBase3f_to_btVector3(limit));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::set_angular_lower_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGenericConstraint::
+set_angular_lower_limit(const LVector3f &limit) {
+
+  nassertv(!limit.is_nan());
+  _constraint->setAngularLowerLimit(LVecBase3f_to_btVector3(limit));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGenericConstraint::set_angular_upper_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGenericConstraint::
+set_angular_upper_limit(const LVector3f &limit) {
+
+  nassertv(!limit.is_nan());
+  _constraint->setAngularUpperLimit(LVecBase3f_to_btVector3(limit));
+}
+

+ 82 - 0
panda/src/bullet/bulletGenericConstraint.h

@@ -0,0 +1,82 @@
+// Filename: bulletGenericConstraint.h
+// Created by:  enn0x (02Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_GENERIC_CONSTRAINT_H__
+#define __BULLET_GENERIC_CONSTRAINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletConstraint.h"
+
+#include "transformState.h"
+#include "lpoint3.h"
+#include "lvector3.h"
+
+class BulletRigidBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletGenericConstraint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletGenericConstraint : public BulletConstraint {
+
+PUBLISHED:
+  BulletGenericConstraint(const BulletRigidBodyNode *node_a, 
+                          const TransformState &frame_a,
+                          bool use_frame_a);
+  BulletGenericConstraint(const BulletRigidBodyNode *node_a,
+                          const BulletRigidBodyNode *node_b,
+                          const TransformState &frame_a,
+                          const TransformState &frame_b,
+                          bool use_frame_a);
+  INLINE ~BulletGenericConstraint();
+
+  void set_linear_lower_limit(const LPoint3f &limit);
+  void set_linear_upper_limit(const LPoint3f &limit);
+  void set_angular_lower_limit(const LVector3f &limit);
+  void set_angular_upper_limit(const LVector3f &limit);
+
+public:
+  virtual btTypedConstraint *ptr() const;
+
+private:
+  btGeneric6DofConstraint *_constraint;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletConstraint::init_type();
+    register_type(_type_handle, "BulletGenericConstraint", 
+                  BulletConstraint::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletGenericConstraint.I"
+
+#endif // __BULLET_GENERIC_CONSTRAINT_H__

+ 51 - 0
panda/src/bullet/bulletGhostNode.I

@@ -0,0 +1,51 @@
+// Filename: bulletGhostNode.I
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletGhostNode::
+~BulletGhostNode() {
+
+  delete _ghost;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::get_num_overlapping_nodes
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int BulletGhostNode::
+get_num_overlapping_nodes() const {
+
+  return _ghost->getNumOverlappingObjects();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::get_overlapping_node
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PandaNode *BulletGhostNode::
+get_overlapping_node(int idx) const {
+
+  nassertr(idx >=0 && idx < _ghost->getNumOverlappingObjects(), NULL);
+
+  btCollisionObject *object = _ghost->getOverlappingObject(idx);
+  return (object) ? (PandaNode *)object->getUserPointer() : NULL;
+}
+

+ 113 - 0
panda/src/bullet/bulletGhostNode.cxx

@@ -0,0 +1,113 @@
+// Filename: bulletGhostNode.cxx
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletGhostNode.h"
+#include "bulletShape.h"
+
+TypeHandle BulletGhostNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletGhostNode::
+BulletGhostNode(const char *name) : BulletBodyNode(name) {
+
+  // Setup initial transform
+  btTransform trans = btTransform::getIdentity();
+
+  // Setup ghost object
+  _ghost = new btPairCachingGhostObject();
+  _ghost->setUserPointer(this);
+  _ghost->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
+  _ghost->setWorldTransform(trans);
+  _ghost->setInterpolationWorldTransform(trans);
+  _ghost->setCollisionShape(_shape);
+
+  // Autosync is off by default
+  _sync_transform = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::get_object
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionObject *BulletGhostNode::
+get_object() const {
+
+  return _ghost;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::parents_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGhostNode::
+parents_changed() {
+
+  // Enable autosync if one of the parents is suited for this
+  Parents parents = get_parents();
+  for (int i=0; i < parents.get_num_parents(); ++i) {
+    PandaNode *parent = parents.get_parent(i);
+    TypeHandle type = parent->get_type();
+
+    if (BulletRigidBodyNode::get_class_type() == type ||
+        BulletSoftBodyNode::get_class_type() == type ||
+        BulletGhostNode::get_class_type() == type ||
+        BulletCharacterControllerNode::get_class_type() == type) {
+      _sync_transform = true;
+      return;
+    }
+  }
+
+  // None of the parents is suited for autosync
+  _sync_transform = false;
+
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::transform_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGhostNode::
+transform_changed() {
+
+  if (_disable_transform_changed) return;
+
+  btTransform trans;
+  get_node_transform(trans, this);
+  _ghost->setWorldTransform(trans);
+  _ghost->setInterpolationWorldTransform(trans);
+
+  BulletBodyNode::transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletGhostNode::pre_step
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletGhostNode::
+pre_step() {
+
+  if (_sync_transform) {
+    transform_changed();
+  }
+}
+

+ 83 - 0
panda/src/bullet/bulletGhostNode.h

@@ -0,0 +1,83 @@
+// Filename: bulletGhostNode.h
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_GHOST_NODE_H__
+#define __BULLET_GHOST_NODE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletBodyNode.h"
+
+#include "pandaNode.h"
+#include "collideMask.h"
+
+class BulletShape;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletGhostNode
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletGhostNode : public BulletBodyNode {
+
+PUBLISHED:
+  BulletGhostNode(const char *name="ghost");
+  INLINE ~BulletGhostNode();
+
+  // Overlapping
+  INLINE int get_num_overlapping_nodes() const;
+  INLINE PandaNode *get_overlapping_node(int idx) const;
+  MAKE_SEQ(get_overlapping_nodes, get_num_overlapping_nodes, get_overlapping_node);
+
+public:
+  virtual btCollisionObject *get_object() const;
+
+  void pre_step();
+
+protected:
+  virtual void parents_changed();
+  virtual void transform_changed();
+
+private:
+  btPairCachingGhostObject *_ghost;
+
+  bool _sync_transform;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletBodyNode::init_type();
+    register_type(_type_handle, "BulletGhostNode", 
+                  BulletBodyNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletGhostNode.I"
+
+#endif // __BULLET_GHOST_NODE_H__
+

+ 26 - 0
panda/src/bullet/bulletHeightfieldShape.I

@@ -0,0 +1,26 @@
+// Filename: bulletHeightfieldShape.I
+// Created by:  enn0x (05Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHeightfieldShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletHeightfieldShape::
+~BulletHeightfieldShape() {
+
+  delete _shape;
+  delete _data;
+}
+

+ 68 - 0
panda/src/bullet/bulletHeightfieldShape.cxx

@@ -0,0 +1,68 @@
+// Filename: bulletHeightfieldShape.cxx
+// Created by:  enn0x (05Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletHeightfieldShape.h"
+
+TypeHandle BulletHeightfieldShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHeightfieldShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletHeightfieldShape::
+BulletHeightfieldShape(const PNMImage &image, float max_height, BulletUpAxis up) {
+
+  int num_rows = image.get_x_size();
+  int num_columns = image.get_y_size();
+
+  _data = new float[num_rows * num_columns];
+
+  for (int row=0; row < num_rows; row++) {
+    for (int column=0; column < num_columns; column++) {
+      _data[num_columns * row + column] = 
+        max_height * image.get_bright(column, num_columns - row - 1);
+    }
+  }
+
+  _shape = new btHeightfieldTerrainShape(num_rows, num_columns,
+                                         _data,
+                                         max_height,
+                                         up,
+                                         true, false);
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHeightfieldShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletHeightfieldShape::
+ptr() const {
+
+  return _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHeightfieldShape::set_use_diamond_subdivision
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletHeightfieldShape::
+set_use_diamond_subdivision(bool flag) {
+
+  return _shape->setUseDiamondSubdivision(flag);
+}
+

+ 69 - 0
panda/src/bullet/bulletHeightfieldShape.h

@@ -0,0 +1,69 @@
+// Filename: bulletHeightfieldShape.h
+// Created by:  enn0x (05Feb10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_HEIGHTFIELD_SHAPE_H__
+#define __BULLET_HEIGHTFIELD_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletShape.h"
+
+#include "pnmImage.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletHeightfieldShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletHeightfieldShape : public BulletShape {
+
+PUBLISHED:
+  BulletHeightfieldShape(const PNMImage &image, float max_height, BulletUpAxis up=Z_up);
+  INLINE ~BulletHeightfieldShape();
+
+  void set_use_diamond_subdivision(bool flag=true);
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  float *_data;
+  btHeightfieldTerrainShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletHeightfieldShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletHeightfieldShape.I"
+
+#endif // __BULLET_HEIGHTFIELD_SHAPE_H__

+ 42 - 0
panda/src/bullet/bulletHelper.I

@@ -0,0 +1,42 @@
+// Filename: bulletHelper.I
+// Created by:  enn0x (19Jan11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::get_sb_index
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) BulletHelper::
+get_sb_index() {
+
+  if (_sb_index == (InternalName *)NULL) {
+    _sb_index = InternalName::make("sb_index");
+  }
+  return _sb_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::get_sb_flip
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) BulletHelper::
+get_sb_flip() {
+
+  if (_sb_flip == (InternalName *)NULL) {
+    _sb_flip = InternalName::make("sb_flip");
+  }
+  return _sb_flip;
+}

+ 307 - 0
panda/src/bullet/bulletHelper.cxx

@@ -0,0 +1,307 @@
+// Filename: bulletHelper.cxx
+// Created by:  enn0x (19Jan11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletHelper.h"
+#include "bulletRigidBodyNode.h"
+#include "bulletGhostNode.h"
+
+#include "geomVertexRewriter.h"
+
+PT(InternalName) BulletHelper::_sb_index;
+PT(InternalName) BulletHelper::_sb_flip;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::from_collision_solids
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+NodePathCollection BulletHelper::
+from_collision_solids(NodePath &np, bool clear) {
+
+  NodePathCollection result;
+
+  // Iterate over all CollisionNodes below the given node
+  NodePathCollection npc = np.find_all_matches( "**/+CollisionNode" );
+
+  for (int i=0; i<npc.get_num_paths(); i++) {
+    NodePath cnp = npc.get_path(i);
+    CollisionNode *cnode = DCAST(CollisionNode, cnp.node());
+
+    PT(PandaNode) bnode = NULL;
+
+    // Create a either a new rigid body or a new ghost for each CollisionNode,
+    // and add one shape per CollisionSolid contained in the CollisionNode
+    if (is_tangible(cnode)) {
+      PT(BulletRigidBodyNode) body;
+
+      body = new BulletRigidBodyNode();
+      body->add_shapes_from_collision_solids(cnode);
+      body->set_transform(cnp.get_transform(np));
+      body->set_into_collide_mask(cnode->get_into_collide_mask());
+      body->set_mass(0.0f);
+      body->set_name(cnode->get_name());
+
+      bnode = body;
+    }
+    else {
+      PT(BulletGhostNode) ghost;
+
+      ghost = new BulletGhostNode();
+      ghost->add_shapes_from_collision_solids(cnode);
+      ghost->set_transform(cnp.get_transform(np));
+      ghost->set_into_collide_mask(cnode->get_into_collide_mask());
+      ghost->set_name(cnode->get_name());
+
+      bnode = ghost;
+    }
+
+    // Remove collision node if requested
+    if (clear) {
+      cnp.remove_node();
+    }
+
+    result.add_path(NodePath::any_path(bnode));
+  }
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::is_tangible
+//       Access: Private
+//  Description: Returns TRUE if at least one CollisionSolid of
+//               the given CollisionNode is tangible. Returns FALSE
+//               if all CollisionSolids are intangible.
+////////////////////////////////////////////////////////////////////
+bool BulletHelper::
+is_tangible(CollisionNode *cnode) {
+
+  for (int j=0; j<cnode->get_num_solids(); j++) {
+    CPT(CollisionSolid) solid = cnode->get_solid(j);
+    if (solid->is_tangible()) {
+        return true;
+    }
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::add_sb_index_column
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(GeomVertexFormat) BulletHelper::
+add_sb_index_column(const GeomVertexFormat *format) {
+
+  PT(InternalName) name = BulletHelper::get_sb_index();
+
+  if (format->has_column(name)) return format;
+
+  PT(GeomVertexArrayFormat) array;
+  PT(GeomVertexFormat) unregistered_format;
+  CPT(GeomVertexFormat) registered_format;
+
+  array = new GeomVertexArrayFormat();
+  array->add_column(name, 1, Geom::NT_uint16, Geom::C_index);
+
+  unregistered_format = new GeomVertexFormat(*format);
+  unregistered_format->add_array(array);
+
+  registered_format = GeomVertexFormat::register_format(unregistered_format);
+
+  return registered_format;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::add_sb_flip_column
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(GeomVertexFormat) BulletHelper::
+add_sb_flip_column(const GeomVertexFormat *format) {
+
+  PT(InternalName) name = BulletHelper::get_sb_flip();
+
+  if (format->has_column(name)) return format;
+
+  PT(GeomVertexArrayFormat) array;
+  PT(GeomVertexFormat) unregistered_format;
+  CPT(GeomVertexFormat) registered_format;
+
+  array = new GeomVertexArrayFormat();
+  array->add_column(name, 1, Geom::NT_uint8, Geom::C_other);
+
+  unregistered_format = new GeomVertexFormat(*format);
+  unregistered_format->add_array(array);
+
+  registered_format = GeomVertexFormat::register_format(unregistered_format);
+
+  return registered_format;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::make_geom_from_faces
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(Geom) BulletHelper::
+make_geom_from_faces(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sided) {
+
+  return make_geom(node, format, two_sided, true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::make_geom_from_links
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(Geom) BulletHelper::
+make_geom_from_links(BulletSoftBodyNode *node, const GeomVertexFormat *format) {
+
+  return make_geom(node, format, false, false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::make_geom
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(Geom) BulletHelper::
+make_geom(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sided, bool use_faces) {
+
+  btTransform trans;
+  get_node_transform(trans, node);
+
+  btSoftBody *body = (btSoftBody *)node->get_object();
+
+  PT(Geom) geom;
+  PT(GeomPrimitive) prim;
+  PT(GeomVertexData) vdata;
+
+  CPT(GeomVertexFormat) fmt = (format) ? format : GeomVertexFormat::get_v3n3t2();
+  fmt = BulletHelper::add_sb_flip_column(fmt);
+
+  nassertr(fmt->has_column(InternalName::get_vertex()), NULL);
+  nassertr(fmt->has_column(InternalName::get_normal()), NULL);
+
+  btSoftBody::tNodeArray &nodes(body->m_nodes);
+
+  // Vertex data
+  vdata = new GeomVertexData("", fmt, Geom::UH_stream);
+
+  GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
+  GeomVertexWriter nwriter(vdata, InternalName::get_normal());
+  GeomVertexWriter fwriter(vdata, BulletHelper::get_sb_flip());
+
+  for (int j=0; j<nodes.size(); ++j) {
+    btVector3 v = nodes[j].m_x;
+    btVector3 &n = nodes[j].m_n;
+
+    v = trans.invXform(v);
+
+    vwriter.add_data3f(v.getX(), v.getY(), v.getZ());
+    nwriter.add_data3f(n.getX(), n.getY(), n.getZ());
+    fwriter.add_data1i(0);
+  }
+
+  if (two_sided) {
+    for (int j=0; j<nodes.size(); ++j) {
+      btVector3 &v = nodes[j].m_x;
+      btVector3 &n = nodes[j].m_n;
+
+      vwriter.add_data3f(v.getX(), v.getY(), v.getZ());
+      nwriter.add_data3f(n.getX(), n.getY(), n.getZ());
+      fwriter.add_data1i(1);
+    }
+  }
+
+  // Indices
+  btSoftBody::Node *node0 = &nodes[0];
+
+  if (use_faces) {
+    btSoftBody::tFaceArray &faces(body->m_faces);
+
+    prim = new GeomTriangles(Geom::UH_stream);
+    prim->set_shade_model(Geom::SM_uniform);
+
+    for (int j=0; j<faces.size(); ++j) {
+      prim->add_vertices(int(faces[j].m_n[0] - node0),
+                         int(faces[j].m_n[1] - node0),
+                         int(faces[j].m_n[2] - node0));
+      prim->close_primitive();
+
+      if (two_sided) {
+        prim->add_vertices(nodes.size() + int(faces[j].m_n[0] - node0),
+                           nodes.size() + int(faces[j].m_n[2] - node0),
+                           nodes.size() + int(faces[j].m_n[1] - node0));
+        prim->close_primitive();
+      }
+    }
+  }
+  else {
+    btSoftBody::tLinkArray &links(body->m_links);
+
+    prim = new GeomLines(Geom::UH_stream);
+    prim->set_shade_model(Geom::SM_uniform);
+
+    for (int j=0; j<links.size(); ++j) {
+      prim->add_vertices(int(links[j].m_n[0] - node0),
+                         int(links[j].m_n[1] - node0));
+      prim->close_primitive();
+    }
+  }
+
+  // Geom
+  geom = new Geom(vdata);
+  geom->add_primitive(prim);
+
+  return geom;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHelper::make_texcoords_for_patch
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletHelper::
+make_texcoords_for_patch(Geom *geom, int resx, int resy) {
+
+  PT(GeomVertexData) vdata = geom->modify_vertex_data();
+
+  nassertv(vdata->has_column(InternalName::get_texcoord()));
+
+  GeomVertexRewriter texcoords(vdata, InternalName::get_texcoord());
+
+  int n = resx * resy;
+  int i = 0;
+  int ix;
+  int iy;
+  float u;
+  float v;
+
+  while (!texcoords.is_at_end()) {
+    ix = i / resx;
+    iy = i % resy;
+
+    if (i > n) ix -= 1;
+
+    u = (float)ix/(float)(resx - 1);
+    v = (float)iy/(float)(resy - 1);
+
+    texcoords.set_data2f(u, v);
+    i++;
+  }
+}
+

+ 70 - 0
panda/src/bullet/bulletHelper.h

@@ -0,0 +1,70 @@
+// Filename: bulletHelper.h
+// Created by:  enn0x (19Jan11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_HELPER_H__
+#define __BULLET_HELPER_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+
+#include "collisionNode.h"
+#include "nodePath.h"
+#include "nodePathCollection.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletHelper
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletHelper {
+
+PUBLISHED:
+
+  // Collision shapes
+  static NodePathCollection from_collision_solids(NodePath &np, bool clear=false);
+
+  // Internal names
+  INLINE static PT(InternalName) get_sb_index();
+  INLINE static PT(InternalName) get_sb_flip();
+
+  // Geom vertex data
+  static CPT(GeomVertexFormat) add_sb_index_column(const GeomVertexFormat *format);
+  static CPT(GeomVertexFormat) add_sb_flip_column(const GeomVertexFormat *format);
+
+  // Geom utils
+  static PT(Geom) make_geom_from_faces(BulletSoftBodyNode *node, 
+      const GeomVertexFormat *format=NULL,
+      bool two_sided=false);
+
+  static PT(Geom) make_geom_from_links(BulletSoftBodyNode *node,
+      const GeomVertexFormat *format=NULL);
+
+  static void make_texcoords_for_patch(Geom *geom, int resx, int resy);
+
+private:
+  static PT(InternalName) _sb_index;
+  static PT(InternalName) _sb_flip;
+
+  static bool is_tangible(CollisionNode *cnode);
+
+  static PT(Geom) make_geom(BulletSoftBodyNode *node, 
+      const GeomVertexFormat *format,
+      bool use_faces,
+      bool two_sided);
+};
+
+#include "bulletHelper.I"
+
+#endif // __BULLET_HELPER_H__

+ 25 - 0
panda/src/bullet/bulletHingeConstraint.I

@@ -0,0 +1,25 @@
+// Filename: bulletHingeConstraint.I
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletHingeConstraint::
+~BulletHingeConstraint() {
+
+  delete _constraint;
+}
+

+ 158 - 0
panda/src/bullet/bulletHingeConstraint.cxx

@@ -0,0 +1,158 @@
+// Filename: bulletHingeConstraint.cxx
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletHingeConstraint.h"
+#include "bulletRigidBodyNode.h"
+
+#include "deg_2_rad.h"
+
+TypeHandle BulletHingeConstraint::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletHingeConstraint::
+BulletHingeConstraint(const BulletRigidBodyNode *node_a, 
+                      const LPoint3f &pivot_a,
+                      const LVector3f &axis_a,
+                      bool use_frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btVector3 pos_a = LVecBase3f_to_btVector3(pivot_a);
+  btVector3 vec_a = LVecBase3f_to_btVector3(axis_a);
+
+  _constraint = new btHingeConstraint(*ptr_a, pos_a, vec_a, use_frame_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletHingeConstraint::
+BulletHingeConstraint(const BulletRigidBodyNode *node_a,
+                      const BulletRigidBodyNode *node_b,
+                      const LPoint3f &pivot_a,
+                      const LPoint3f &pivot_b,
+                      const LVector3f &axis_a,
+                      const LVector3f &axis_b,
+                      bool use_frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btVector3 pos_a = LVecBase3f_to_btVector3(pivot_a);
+  btVector3 vec_a = LVecBase3f_to_btVector3(axis_a);
+
+  btRigidBody *ptr_b = btRigidBody::upcast(node_b->get_object());
+  btVector3 pos_b = LVecBase3f_to_btVector3(pivot_b);
+  btVector3 vec_b = LVecBase3f_to_btVector3(axis_b);
+
+  _constraint = new btHingeConstraint(*ptr_a, *ptr_b, pos_a, pos_b, vec_a, vec_b, use_frame_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btTypedConstraint *BulletHingeConstraint::
+ptr() const {
+
+  return _constraint;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::set_angular_only
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletHingeConstraint::
+set_angular_only(bool value) {
+
+  return _constraint->setAngularOnly(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::get_angular_only
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletHingeConstraint::
+get_angular_only() const {
+
+  return _constraint->getAngularOnly();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::set_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletHingeConstraint::
+set_limit(float low, float high, float softness, float bias, float relaxation) {
+
+  low  = deg_2_rad(low);
+  high = deg_2_rad(high);
+
+  _constraint->setLimit(low, high, softness, bias, relaxation);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::set_axis
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletHingeConstraint::
+set_axis(const LVector3f &axis) {
+
+  nassertv(!axis.is_nan());
+
+  btVector3 v = LVecBase3f_to_btVector3(axis);
+  _constraint->setAxis(v);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::get_lower_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletHingeConstraint::
+get_lower_limit() const {
+
+  return rad_2_deg(_constraint->getLowerLimit());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::get_upper_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletHingeConstraint::
+get_upper_limit() const {
+
+  return rad_2_deg(_constraint->getUpperLimit());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletHingeConstraint::get_hinge_angle
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletHingeConstraint::
+get_hinge_angle() {
+
+  return rad_2_deg(_constraint->getHingeAngle());
+}
+

+ 88 - 0
panda/src/bullet/bulletHingeConstraint.h

@@ -0,0 +1,88 @@
+// Filename: bulletHingeConstraint.h
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_HINGE_CONSTRAINT_H__
+#define __BULLET_HINGE_CONSTRAINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletConstraint.h"
+
+#include "lpoint3.h"
+#include "lvector3.h"
+
+class BulletRigidBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletHingeConstraint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletHingeConstraint : public BulletConstraint {
+
+PUBLISHED:
+  BulletHingeConstraint(const BulletRigidBodyNode *node_a, 
+                        const LPoint3f &pivot_a,
+                        const LVector3f &axis_a,
+                        bool use_frame_a=false);
+  BulletHingeConstraint(const BulletRigidBodyNode *node_a,
+                        const BulletRigidBodyNode *node_b,
+                        const LPoint3f &pivot_a,
+                        const LPoint3f &pivot_b,
+                        const LVector3f &axis_a,
+                        const LVector3f &axis_b,
+                        bool use_frame_a=false);
+  INLINE ~BulletHingeConstraint();
+
+  float get_hinge_angle();
+  float get_lower_limit() const;
+  float get_upper_limit() const;
+  bool get_angular_only() const;
+
+  void set_angular_only(bool value);
+  void set_limit(float low, float high, float softness=0.9f, float bias=0.3f, float relaxation=1.0f);
+  void set_axis(const LVector3f &axis);
+
+public:
+  virtual btTypedConstraint *ptr() const;
+
+private:
+  btHingeConstraint *_constraint;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletConstraint::init_type();
+    register_type(_type_handle, "BulletHingeConstraint", 
+                  BulletConstraint::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletHingeConstraint.I"
+
+#endif // __BULLET_HINGE_CONSTRAINT_H__

+ 24 - 0
panda/src/bullet/bulletManifoldPoint.I

@@ -0,0 +1,24 @@
+// Filename: bulletManifoldPoint.I
+// Created by:  enn0x (07Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletManifoldPoint::
+~BulletManifoldPoint() {
+
+}
+

+ 103 - 0
panda/src/bullet/bulletManifoldPoint.cxx

@@ -0,0 +1,103 @@
+// Filename: bulletManifoldPoint.cxx
+// Created by:  enn0x (07Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletManifoldPoint.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletManifoldPoint::
+BulletManifoldPoint(btManifoldPoint &pt) : _pt(pt) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_lift_time
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+int BulletManifoldPoint::
+get_lift_time() const {
+
+  return _pt.getLifeTime();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_distance
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletManifoldPoint::
+get_distance() const {
+
+  return _pt.getDistance();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_applied_impulse
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletManifoldPoint::
+get_applied_impulse() const {
+
+  return _pt.getAppliedImpulse();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_position_world_on_a
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletManifoldPoint::
+get_position_world_on_a() const {
+
+  return btVector3_to_LPoint3f(_pt.getPositionWorldOnA());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_position_world_on_b
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletManifoldPoint::
+get_position_world_on_b() const {
+
+  return btVector3_to_LPoint3f(_pt.getPositionWorldOnB());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_local_point_a
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletManifoldPoint::
+get_local_point_a() const {
+
+  return btVector3_to_LPoint3f(_pt.m_localPointA);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletManifoldPoint::get_local_point_b
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletManifoldPoint::
+get_local_point_b() const {
+
+  return btVector3_to_LPoint3f(_pt.m_localPointB);
+}
+

+ 51 - 0
panda/src/bullet/bulletManifoldPoint.h

@@ -0,0 +1,51 @@
+// Filename: bulletManifoldPoint.h
+// Created by:  enn0x (07Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_MANIFOLD_POINT_H__
+#define __BULLET_MANIFOLD_POINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+
+#include "lpoint3.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletManifoldPoint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletManifoldPoint {
+
+PUBLISHED:
+  INLINE ~BulletManifoldPoint();
+
+  int get_lift_time() const;
+  float get_distance() const;
+  float get_applied_impulse() const;
+  LPoint3f get_position_world_on_a() const;
+  LPoint3f get_position_world_on_b() const;
+  LPoint3f get_local_point_a() const;
+  LPoint3f get_local_point_b() const;
+
+public:
+  BulletManifoldPoint(btManifoldPoint &pt);
+
+private:
+  btManifoldPoint &_pt;
+};
+
+#include "bulletManifoldPoint.I"
+
+#endif // __BULLET_MANIFOLD_POINT_H__

+ 24 - 0
panda/src/bullet/bulletPersistentManifold.I

@@ -0,0 +1,24 @@
+// Filename: bulletPersistentManifold.I
+// Created by:  enn0x (07Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletPersistentManifold::
+~BulletPersistentManifold() {
+
+}
+

+ 110 - 0
panda/src/bullet/bulletPersistentManifold.cxx

@@ -0,0 +1,110 @@
+// Filename: bulletPersistentManifold.cxx
+// Created by:  enn0x (07Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletPersistentManifold.h"
+#include "bulletManifoldPoint.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletPersistentManifold::
+BulletPersistentManifold(btPersistentManifold *manifold) : _manifold(manifold) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::get_contact_breaking_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletPersistentManifold::
+get_contact_breaking_threshold() const {
+
+  return _manifold->getContactBreakingThreshold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::get_contact_processing_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletPersistentManifold::
+get_contact_processing_threshold() const {
+
+  return _manifold->getContactProcessingThreshold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::set_suspension_stiffness
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletPersistentManifold::
+clear_manifold() {
+
+  _manifold->clearManifold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::get_node0
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaNode *BulletPersistentManifold::
+get_node0() {
+
+  btCollisionObject *obj = static_cast<btCollisionObject *>(_manifold->getBody0());
+
+  return (obj) ? (PandaNode *)obj->getUserPointer(): NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::get_node1
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaNode *BulletPersistentManifold::
+get_node1() {
+
+  btCollisionObject *obj = static_cast<btCollisionObject *>(_manifold->getBody1());
+
+  return (obj) ? (PandaNode *)obj->getUserPointer(): NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::get_num_manifold_points
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+int BulletPersistentManifold::
+get_num_manifold_points() const {
+
+  return _manifold->getNumContacts();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPersistentManifold::get_manifold_point
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletManifoldPoint *BulletPersistentManifold::
+get_manifold_point(int idx) const {
+
+  nassertr(idx < _manifold->getNumContacts(), NULL)
+
+  return new BulletManifoldPoint(_manifold->getContactPoint(idx));
+}
+

+ 56 - 0
panda/src/bullet/bulletPersistentManifold.h

@@ -0,0 +1,56 @@
+// Filename: bulletPersistentManifold.h
+// Created by:  enn0x (07Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_PERSISTENT_MANIFOLD_H__
+#define __BULLET_PERSISTENT_MANIFOLD_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+#include "pandaNode.h"
+
+class BulletManifoldPoint;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletPersistentManifold
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletPersistentManifold {
+
+PUBLISHED:
+  INLINE ~BulletPersistentManifold();
+
+  PandaNode *get_node0();
+  PandaNode *get_node1();
+
+  int get_num_manifold_points() const;
+  BulletManifoldPoint *get_manifold_point(int idx) const;
+  MAKE_SEQ(get_manifold_points, get_num_manifold_points, get_manifold_point);
+
+  float get_contact_breaking_threshold() const;
+  float get_contact_processing_threshold() const;
+
+  void clear_manifold();
+
+public:
+  BulletPersistentManifold(btPersistentManifold *manifold);
+
+private:
+  btPersistentManifold *_manifold;
+};
+
+#include "bulletPersistentManifold.I"
+
+#endif // __BULLET_PERSISTENT_MANIFOLD_H__

+ 47 - 0
panda/src/bullet/bulletPlaneShape.I

@@ -0,0 +1,47 @@
+// Filename: bulletPlaneShape.I
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletPlaneShape::
+~BulletPlaneShape() {
+
+  delete _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::get_plane_constant
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletPlaneShape::
+get_plane_constant() const {
+
+  return _shape->getPlaneConstant();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::get_plane_normal
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE LVector3f BulletPlaneShape::
+get_plane_normal() const {
+
+  return btVector3_to_LVector3f(_shape->getPlaneNormal());
+}
+

+ 57 - 0
panda/src/bullet/bulletPlaneShape.cxx

@@ -0,0 +1,57 @@
+// Filename: bulletPlaneShape.cxx
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletPlaneShape.h"
+
+TypeHandle BulletPlaneShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletPlaneShape::
+BulletPlaneShape(const LVector3f &normal, float constant) {
+
+  btVector3 btNormal = LVecBase3f_to_btVector3(normal);
+
+  _shape = new btStaticPlaneShape(btNormal, constant);
+  _shape->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionShape *BulletPlaneShape::
+ptr() const {
+
+  return _shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::make_from_solid
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletPlaneShape *BulletPlaneShape::
+make_from_solid(const CollisionPlane *solid) {
+
+  LVector3f normal = solid->get_normal();
+  float constant = solid->dist_to_plane(LPoint3f(0, 0, 0));
+
+  return new BulletPlaneShape(normal, constant);
+}
+

+ 72 - 0
panda/src/bullet/bulletPlaneShape.h

@@ -0,0 +1,72 @@
+// Filename: bulletPlaneShape.h
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_PLANE_SHAPE_H__
+#define __BULLET_PLANE_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletShape.h"
+
+#include "collisionPlane.h"
+#include "lvector3.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletPlaneShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletPlaneShape : public BulletShape {
+
+PUBLISHED:
+  BulletPlaneShape(const LVector3f &normal, float constant);
+  INLINE ~BulletPlaneShape();
+
+  INLINE LVector3f get_plane_normal() const;
+  INLINE float get_plane_constant() const;
+
+  static BulletPlaneShape *make_from_solid(const CollisionPlane *solid);
+
+public:
+  virtual btCollisionShape *ptr() const;
+
+private:
+  btStaticPlaneShape *_shape;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletShape::init_type();
+    register_type(_type_handle, "BulletPlaneShape", 
+                  BulletShape::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletPlaneShape.I"
+
+#endif // __BULLET_PLANE_SHAPE_H__

+ 71 - 0
panda/src/bullet/bulletRigidBodyNode.I

@@ -0,0 +1,71 @@
+// Filename: bulletRigidBodyNode.I
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletRigidBodyNode::
+~BulletRigidBodyNode() {
+
+  delete _body;
+  delete _motion;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_linear_damping
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletRigidBodyNode::
+set_linear_damping(float value) {
+
+  _body->setDamping(value, _body->getAngularDamping());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_angular_damping
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void BulletRigidBodyNode::
+set_angular_damping(float value) {
+
+  _body->setDamping(_body->getLinearDamping(), value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_linear_damping
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletRigidBodyNode::
+get_linear_damping() const {
+
+  return _body->getLinearDamping();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_angular_damping
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletRigidBodyNode::
+get_angular_damping() const {
+
+  return _body->getAngularDamping();
+}
+

+ 418 - 0
panda/src/bullet/bulletRigidBodyNode.cxx

@@ -0,0 +1,418 @@
+// Filename: bulletRigidBodyNode.cxx
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletRigidBodyNode.h"
+#include "bulletShape.h"
+
+TypeHandle BulletRigidBodyNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletRigidBodyNode::
+BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {
+
+  // Setup motion state
+  _motion = new MotionState(this);
+
+  // Setup mass properties
+  btScalar mass(0.0);
+  btVector3 inertia(0, 0, 0);
+
+  btRigidBody::btRigidBodyConstructionInfo ci(mass, _motion, _shape, inertia);
+
+  // Enable additional damping
+  if (bullet_additional_damping) {
+    ci.m_additionalDamping = true;
+    ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor;
+    ci.m_additionalLinearDampingThresholdSqr = bullet_additional_damping_linear_threshold;
+    ci.m_additionalAngularDampingFactor = bullet_additional_damping_angular_factor;
+    ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold;
+  }
+
+  // Setup rigid body
+  _body = new btRigidBody(ci);
+  _body->setUserPointer(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_object
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionObject *BulletRigidBodyNode::
+get_object() const {
+
+  return _body;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::shape_changed
+//       Access: Published
+//  Description: Hook which will be called whenever the total shape
+//               of a body changed. Used for example to update
+//               the mass properties (inertia) of a rigid body.
+//               The default implementation does nothing.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+shape_changed() {
+
+  set_mass(get_mass());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_mass(float mass) {
+
+  btVector3 inertia(0.0f, 0.0f, 0.0f);
+
+  if (mass > 0.0f) {
+    _body->getCollisionShape()->calculateLocalInertia(mass, inertia);
+  }
+
+  _body->setMassProps(mass, inertia);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletRigidBodyNode::
+get_mass() const {
+
+  btScalar invMass = _body->getInvMass();
+
+  if (invMass == 0.0f) {
+    return 0.0f;
+  }
+  else {
+    return 1.0f / invMass;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::apply_force
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+apply_force(const LVector3f &force, const LPoint3f &pos) {
+
+  nassertv_always(!force.is_nan());
+  nassertv_always(!pos.is_nan());
+
+  _body->applyForce(LVecBase3f_to_btVector3(force),
+                    LVecBase3f_to_btVector3(pos));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::apply_central_force
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+apply_central_force(const LVector3f &force) {
+
+  nassertv_always(!force.is_nan());
+
+  _body->applyCentralForce(LVecBase3f_to_btVector3(force));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::apply_torque
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+apply_torque(const LVector3f &torque) {
+
+  nassertv_always(!torque.is_nan());
+
+  _body->applyTorque(LVecBase3f_to_btVector3(torque));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::apply_torque_impulse
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+apply_torque_impulse(const LVector3f &torque) {
+
+  nassertv_always(!torque.is_nan());
+
+  _body->applyTorqueImpulse(LVecBase3f_to_btVector3(torque));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::apply_impulse
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+apply_impulse(const LVector3f &impulse, const LPoint3f &pos) {
+
+  nassertv_always(!impulse.is_nan());
+  nassertv_always(!pos.is_nan());
+
+  _body->applyImpulse(LVecBase3f_to_btVector3(impulse),
+                      LVecBase3f_to_btVector3(pos));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::apply_central_impulse
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+apply_central_impulse(const LVector3f &impulse) {
+
+  nassertv_always(!impulse.is_nan());
+
+  _body->applyCentralImpulse(LVecBase3f_to_btVector3(impulse));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::parents_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+parents_changed() {
+
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::transform_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+transform_changed() {
+
+  if (_disable_transform_changed) return;
+
+  btTransform trans;
+  get_node_transform(trans, this);
+  _body->setWorldTransform(trans);
+  _body->setInterpolationWorldTransform(trans);
+
+  BulletBodyNode::transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::MotionState::getWorldTransform
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::MotionState::
+getWorldTransform(btTransform &trans) const {
+
+  get_node_transform(trans, _node);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::MotionState::setWorldTransform
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::MotionState::
+setWorldTransform(const btTransform &trans) {
+
+  if (trans.getOrigin().getX() != trans.getOrigin().getX()) {
+    bullet_cat.error() << "setWorldTransform: trans is NAN!" << endl;
+    return;
+  }
+
+  LVecBase3f scale = _node->get_transform()->get_scale();
+  CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
+
+  // Disable transform_changed callback
+  _node->_disable_transform_changed = true;
+
+  if (_node->get_num_parents() == 0) {
+    _node->set_transform(ts);
+  }
+  else {
+    NodePath np = NodePath::any_path(_node);
+    np.set_transform(np.get_top(), ts);
+  }
+
+  // Re-enable transform_changed callback again
+  _node->_disable_transform_changed = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_center_of_mass_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_center_of_mass_pos(const LPoint3f &pos) {
+
+  nassertv_always(!pos.is_nan());
+
+  btTransform xform;
+  xform.setIdentity();
+  xform.setOrigin(LVecBase3f_to_btVector3(pos));
+
+  _body->setCenterOfMassTransform(xform);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_center_of_mass_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LPoint3f BulletRigidBodyNode::
+get_center_of_mass_pos() const {
+
+  return btVector3_to_LPoint3f(_body->getCenterOfMassPosition());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_linear_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3f BulletRigidBodyNode::
+get_linear_velocity() const {
+
+  return btVector3_to_LVector3f(_body->getLinearVelocity());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_angular_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3f BulletRigidBodyNode::
+get_angular_velocity() const {
+
+  return btVector3_to_LVector3f(_body->getAngularVelocity());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_linear_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_linear_velocity(const LVector3f &velocity) {
+
+  nassertv_always(!velocity.is_nan());
+
+  _body->setLinearVelocity(LVecBase3f_to_btVector3(velocity));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_angular_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_angular_velocity(const LVector3f &velocity) {
+
+  nassertv_always(!velocity.is_nan());
+
+  _body->setAngularVelocity(LVecBase3f_to_btVector3(velocity));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::clear_forces
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+clear_forces() {
+
+  _body->clearForces();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_linear_sleep_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletRigidBodyNode::
+get_linear_sleep_threshold() const {
+
+  return _body->getLinearSleepingThreshold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_angular_sleep_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletRigidBodyNode::
+get_angular_sleep_threshold() const {
+
+  return _body->getAngularSleepingThreshold();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_linear_sleep_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_linear_sleep_threshold(float threshold) {
+
+  _body->setSleepingThresholds(_body->getLinearSleepingThreshold(), threshold);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_angular_sleep_threshold
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_angular_sleep_threshold(float threshold) {
+
+  _body->setSleepingThresholds(threshold, _body->getAngularSleepingThreshold());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::set_gravity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+set_gravity(const LVector3f &gravity) {
+
+  nassertv_always(!gravity.is_nan());
+
+  _body->setGravity(LVecBase3f_to_btVector3(gravity));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_gravity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3f BulletRigidBodyNode::
+get_gravity() const {
+
+  return btVector3_to_LVector3f(_body->getGravity());
+}
+

+ 127 - 0
panda/src/bullet/bulletRigidBodyNode.h

@@ -0,0 +1,127 @@
+// Filename: bulletRigidBodyNode.h
+// Created by:  enn0x (19Nov10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_RIGID_BODY_NODE_H__
+#define __BULLET_RIGID_BODY_NODE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletBodyNode.h"
+
+#include "pandaNode.h"
+#include "collideMask.h"
+
+class BulletShape;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletRigidBodyNode
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletRigidBodyNode : public BulletBodyNode {
+
+PUBLISHED:
+  BulletRigidBodyNode(const char *name="rigid");
+  INLINE ~BulletRigidBodyNode();
+
+  // Mass
+  LPoint3f get_center_of_mass_pos() const;
+  float get_mass() const;
+  void set_center_of_mass_pos(const LPoint3f &pos);
+  void set_mass(float mass);
+
+  // Velocity
+  LVector3f get_linear_velocity() const;
+  LVector3f get_angular_velocity() const;
+  void set_linear_velocity(const LVector3f &velocity);
+  void set_angular_velocity(const LVector3f &velocity);
+
+  // Damping
+  INLINE float get_linear_damping() const;
+  INLINE float get_angular_damping() const;
+  INLINE void set_linear_damping(float value);
+  INLINE void set_angular_damping(float value);
+
+  // Forces
+  void clear_forces();
+  void apply_force(const LVector3f &force, const LPoint3f &pos);
+  void apply_central_force(const LVector3f &force);
+  void apply_impulse(const LVector3f &impulse, const LPoint3f &pos);
+  void apply_central_impulse(const LVector3f &impulse);
+  void apply_torque(const LVector3f &torque);
+  void apply_torque_impulse(const LVector3f &torque);
+
+  // Deactivation thresholds
+  float get_linear_sleep_threshold() const;
+  float get_angular_sleep_threshold() const;
+  void set_linear_sleep_threshold(float threshold);
+  void set_angular_sleep_threshold(float threshold);
+
+  // Gravity
+  void set_gravity(const LVector3f &gravity);
+  LVector3f get_gravity() const;
+
+public:
+  virtual btCollisionObject *get_object() const;
+
+protected:
+  virtual void parents_changed();
+  virtual void transform_changed();
+
+private:
+  virtual void shape_changed();
+
+  class MotionState : public btMotionState {
+
+  public:
+    MotionState(BulletRigidBodyNode *node) : _node(node) {};
+    ~MotionState() {};
+
+    virtual void getWorldTransform(btTransform &trans) const;
+    virtual void setWorldTransform(const btTransform &trans);
+
+  private:
+    BulletRigidBodyNode *_node;
+  };
+
+  btRigidBody *_body;
+  MotionState *_motion;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletBodyNode::init_type();
+    register_type(_type_handle, "BulletRigidBodyNode", 
+                  BulletBodyNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletRigidBodyNode.I"
+
+#endif // __BULLET_RIGID_BODY_NODE_H__
+

+ 101 - 0
panda/src/bullet/bulletShape.I

@@ -0,0 +1,101 @@
+// Filename: bulletShape.I
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletShape::
+~BulletShape() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_polyhedral
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_polyhedral() const {
+
+  return ptr()->isPolyhedral();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_convex
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_convex() const {
+
+  return ptr()->isConvex();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_convex_2d
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_convex_2d() const {
+
+  return ptr()->isConvex2d();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_concave
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_concave() const {
+
+  return ptr()->isConcave();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_infinite
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_infinite() const {
+
+  return ptr()->isInfinite();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_non_moving
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_non_moving() const {
+
+  return ptr()->isNonMoving();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::is_soft_body
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool BulletShape::
+is_soft_body() const {
+
+  return ptr()->isSoftBody();
+}
+

+ 75 - 0
panda/src/bullet/bulletShape.cxx

@@ -0,0 +1,75 @@
+// Filename: bulletShape.cxx
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletShape.h"
+#include "bullet_utils.h"
+
+TypeHandle BulletShape::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::get_name
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+const char *BulletShape::
+get_name() const {
+
+  return ptr()->getName();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::get_margin
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletShape::
+get_margin() const {
+
+  return ptr()->getMargin();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::set_margin
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletShape::
+set_margin(float margin) {
+
+  ptr()->setMargin(margin);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::get_local_scale
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVecBase3f BulletShape::
+get_local_scale() const {
+
+  return btVector3_to_LVecBase3f(ptr()->getLocalScaling());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletShape::set_local_scale
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletShape::
+set_local_scale(const LVecBase3f &scale) {
+
+  nassertv(!scale.is_nan());
+  ptr()->setLocalScaling(LVecBase3f_to_btVector3(scale));
+}
+

+ 76 - 0
panda/src/bullet/bulletShape.h

@@ -0,0 +1,76 @@
+// Filename: bulletShape.h
+// Created by:  enn0x (23Jan10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_SHAPE_H__
+#define __BULLET_SHAPE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+#include "typedReferenceCount.h"
+//#include "lvector3.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletShape
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletShape : public TypedReferenceCount {
+
+PUBLISHED:
+  INLINE virtual ~BulletShape();
+
+  INLINE bool is_polyhedral() const;
+  INLINE bool is_convex() const;
+  INLINE bool is_convex_2d() const;
+  INLINE bool is_concave() const;
+  INLINE bool is_infinite() const;
+  INLINE bool is_non_moving() const;
+  INLINE bool is_soft_body() const;
+
+  void set_margin(float margin);
+  void set_local_scale(const LVecBase3f &scaling);
+
+  const char *get_name() const;
+  float get_margin() const;
+  LVecBase3f get_local_scale() const;
+
+public:
+  virtual btCollisionShape *ptr() const = 0;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedReferenceCount::init_type();
+    register_type(_type_handle, "BulletShape", 
+                  TypedReferenceCount::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletShape.I"
+
+#endif // __BULLET_SHAPE_H__

+ 25 - 0
panda/src/bullet/bulletSliderConstraint.I

@@ -0,0 +1,25 @@
+// Filename: bulletSliderConstraint.I
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletSliderConstraint::
+~BulletSliderConstraint() {
+
+  delete _constraint;
+}
+

+ 157 - 0
panda/src/bullet/bulletSliderConstraint.cxx

@@ -0,0 +1,157 @@
+// Filename: bulletSliderConstraint.cxx
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletSliderConstraint.h"
+#include "bulletRigidBodyNode.h"
+
+#include "deg_2_rad.h"
+
+TypeHandle BulletSliderConstraint::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSliderConstraint::
+BulletSliderConstraint(const BulletRigidBodyNode *node_a, 
+                       const TransformState &frame_a,
+                       bool use_frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btTransform trans_a = LMatrix4f_to_btTrans(frame_a.get_mat());
+
+  _constraint = new btSliderConstraint(*ptr_a, trans_a, use_frame_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSliderConstraint::
+BulletSliderConstraint(const BulletRigidBodyNode *node_a,
+                       const BulletRigidBodyNode *node_b,
+                       const TransformState &frame_a,
+                       const TransformState &frame_b,
+                       bool use_frame_a) {
+
+  btRigidBody *ptr_a = btRigidBody::upcast(node_a->get_object());
+  btTransform trans_a = LMatrix4f_to_btTrans(frame_a.get_mat());
+
+  btRigidBody *ptr_b = btRigidBody::upcast(node_b->get_object());
+  btTransform trans_b = LMatrix4f_to_btTrans(frame_b.get_mat());
+
+  _constraint = new btSliderConstraint(*ptr_a, *ptr_b, trans_a, trans_b, use_frame_a);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::ptr
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btTypedConstraint *BulletSliderConstraint::
+ptr() const {
+
+  return _constraint;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::get_lower_linear_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSliderConstraint::
+get_lower_linear_limit() {
+
+  return _constraint->getLowerLinLimit();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::get_upper_linear_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSliderConstraint::
+get_upper_linear_limit() {
+
+  return _constraint->getUpperLinLimit();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::get_lower_angular_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSliderConstraint::
+get_lower_angular_limit() {
+
+  return rad_2_deg(_constraint->getLowerAngLimit());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::get_upper_angular_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSliderConstraint::
+get_upper_angular_limit() {
+
+  return rad_2_deg(_constraint->getUpperAngLimit());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::set_lower_linear_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSliderConstraint::
+set_lower_linear_limit(float value) {
+
+  _constraint->setLowerLinLimit(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::set_upper_linear_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSliderConstraint::
+set_upper_linear_limit(float value) {
+
+  _constraint->setUpperLinLimit(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::set_lower_angular_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSliderConstraint::
+set_lower_angular_limit(float value) {
+
+  _constraint->setLowerAngLimit(deg_2_rad(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSliderConstraint::set_upper_angular_limit
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSliderConstraint::
+set_upper_angular_limit(float value) {
+
+  _constraint->setUpperAngLimit(deg_2_rad(value));
+}
+

+ 85 - 0
panda/src/bullet/bulletSliderConstraint.h

@@ -0,0 +1,85 @@
+// Filename: bulletSliderConstraint.h
+// Created by:  enn0x (01Mar10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_SLIDER_CONSTRAINT_H__
+#define __BULLET_SLIDER_CONSTRAINT_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletConstraint.h"
+
+#include "transformState.h"
+
+class BulletRigidBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletSliderConstraint
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletSliderConstraint : public BulletConstraint {
+
+PUBLISHED:
+  BulletSliderConstraint(const BulletRigidBodyNode *node_a, 
+                         const TransformState &frame_a,
+                         bool useFrame_a);
+  BulletSliderConstraint(const BulletRigidBodyNode *node_a,
+                         const BulletRigidBodyNode *node_b,
+                         const TransformState &frame_a,
+                         const TransformState &frame_b,
+                         bool use_frame_a);
+  INLINE ~BulletSliderConstraint();
+
+  float get_lower_linear_limit();
+  float get_upper_linear_limit();
+  float get_lower_angular_limit();
+  float get_upper_angular_limit();
+
+  void set_lower_linear_limit(float value);
+  void set_upper_linear_limit(float value);
+  void set_lower_angular_limit(float value);
+  void set_upper_angular_limit(float value);
+
+public:
+  virtual btTypedConstraint *ptr() const;
+
+private:
+  btSliderConstraint *_constraint;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletConstraint::init_type();
+    register_type(_type_handle, "BulletSliderConstraint", 
+                  BulletConstraint::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletSliderConstraint.I"
+
+#endif // __BULLET_SLIDER_CONSTRAINT_H__

+ 556 - 0
panda/src/bullet/bulletSoftBodyConfig.I

@@ -0,0 +1,556 @@
+// Filename: bulletSoftBodyConfig.I
+// Created by:  enn0x (12Apr10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyConfig::
+~BulletSoftBodyConfig() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_velocities_correction_factor
+//       Access: Published
+//  Description: Getter for property kVCF.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_velocities_correction_factor() const {
+
+  return _cfg.kVCF;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_velocities_correction_factor
+//       Access: Published
+//  Description: Setter for property kVCF.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_velocities_correction_factor(float value) {
+
+  _cfg.kVCF = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_damping_coefficient
+//       Access: Published
+//  Description: Getter for property kDP.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_damping_coefficient() const {
+
+  return _cfg.kDP;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_damping_coefficient
+//       Access: Published
+//  Description: Setter for property kDP.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_damping_coefficient(float value) {
+
+  _cfg.kDP = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_drag_coefficient
+//       Access: Published
+//  Description: Getter for property kDG.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_drag_coefficient() const {
+
+  return _cfg.kDG;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_drag_coefficient
+//       Access: Published
+//  Description: Setter for property kDG.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_drag_coefficient(float value) {
+
+  _cfg.kDG = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_lift_coefficient
+//       Access: Published
+//  Description: Getter for property kLF.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_lift_coefficient() const {
+
+  return _cfg.kLF;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_lift_coefficient
+//       Access: Published
+//  Description: Setter for property kLF.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_lift_coefficient(float value) {
+
+  _cfg.kLF = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_pressure_coefficient
+//       Access: Published
+//  Description: Getter for property kPR.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_pressure_coefficient() const {
+
+  return _cfg.kPR;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_pressure_coefficient
+//       Access: Published
+//  Description: Setter for property kPR.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_pressure_coefficient(float value) {
+
+  _cfg.kPR = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_volume_conversation_coefficient
+//       Access: Published
+//  Description: Getter for property kVC.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_volume_conversation_coefficient() const {
+
+  return _cfg.kVC;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_volume_conversation_coefficient
+//       Access: Published
+//  Description: Setter for property kVC.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_volume_conversation_coefficient(float value) {
+
+  _cfg.kVC = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_dynamic_friction_coefficient
+//       Access: Published
+//  Description: Getter for property kDF.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_dynamic_friction_coefficient() const {
+
+  return _cfg.kDF;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_dynamic_friction_coefficient
+//       Access: Published
+//  Description: Setter for property kDF.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_dynamic_friction_coefficient(float value) {
+
+  _cfg.kDF = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_pose_matching_coefficient
+//       Access: Published
+//  Description: Getter for property kMT.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_pose_matching_coefficient() const {
+
+  return _cfg.kMT;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_pose_matching_coefficient
+//       Access: Published
+//  Description: Setter for property kMT.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_pose_matching_coefficient(float value) {
+
+  _cfg.kMT = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_rigid_contacts_hardness
+//       Access: Published
+//  Description: Getter for property kCHR.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_rigid_contacts_hardness() const {
+
+  return _cfg.kCHR;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_rigid_contacts_hardness
+//       Access: Published
+//  Description: Setter for property kCHR.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_rigid_contacts_hardness(float value) {
+
+  _cfg.kCHR = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_kinetic_contacts_hardness
+//       Access: Published
+//  Description: Getter for property kKHR.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_kinetic_contacts_hardness() const {
+
+  return _cfg.kKHR;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_kinetic_contacts_hardness
+//       Access: Published
+//  Description: Setter for property kKHR.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_kinetic_contacts_hardness(float value) {
+
+  _cfg.kKHR = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_contacts_hardness
+//       Access: Published
+//  Description: Getter for property kSHR.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_contacts_hardness() const {
+
+  return _cfg.kSHR;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_contacts_hardness
+//       Access: Published
+//  Description: Setter for property kSHR.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_contacts_hardness(float value) {
+
+  _cfg.kSHR = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_anchors_hardness
+//       Access: Published
+//  Description: Getter for property kAHR.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_anchors_hardness() const {
+
+  return _cfg.kAHR;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_anchors_hardness
+//       Access: Published
+//  Description: Setter for property kAHR.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_anchors_hardness(float value) {
+
+  _cfg.kAHR = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_vs_rigid_hardness
+//       Access: Published
+//  Description: Getter for property kSRHR_CL.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_vs_rigid_hardness() const {
+
+  return _cfg.kSRHR_CL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_vs_rigid_hardness
+//       Access: Published
+//  Description: Setter for property kSRHR_CL.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_vs_rigid_hardness(float value) {
+
+  _cfg.kSRHR_CL = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_vs_kinetic_hardness
+//       Access: Published
+//  Description: Getter for property kSKHR_CL.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_vs_kinetic_hardness() const {
+
+  return _cfg.kSKHR_CL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_vs_kinetic_hardness
+//       Access: Published
+//  Description: Setter for property kSKHR_CL.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_vs_kinetic_hardness(float value) {
+
+  _cfg.kSKHR_CL = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_vs_soft_hardness
+//       Access: Published
+//  Description: Getter for property kSSHR_CL.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_vs_soft_hardness() const {
+
+  return _cfg.kSSHR_CL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_vs_soft_hardness
+//       Access: Published
+//  Description: Setter for property kSSHR_CL.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_vs_soft_hardness(float value) {
+
+  _cfg.kSSHR_CL = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_vs_rigid_impulse_split
+//       Access: Published
+//  Description: Getter for property kSR_SPLT_CL.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_vs_rigid_impulse_split() const {
+
+  return _cfg.kSR_SPLT_CL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_vs_rigid_impulse_split
+//       Access: Published
+//  Description: Setter for property kSR_SPLT_CL.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_vs_rigid_impulse_split(float value) {
+
+  _cfg.kSR_SPLT_CL = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_vs_kinetic_impulse_split
+//       Access: Published
+//  Description: Getter for property kSK_SPLT_CL.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_vs_kinetic_impulse_split() const {
+
+  return _cfg.kSK_SPLT_CL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_vs_kinetic_impulse_split
+//       Access: Published
+//  Description: Setter for property kSK_SPLT_CL.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_vs_kinetic_impulse_split(float value) {
+
+  _cfg.kSK_SPLT_CL = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_soft_vs_soft_impulse_split
+//       Access: Published
+//  Description: Getter for property kSS_SPLT_CL.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_soft_vs_soft_impulse_split() const {
+
+  return _cfg.kSS_SPLT_CL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_soft_vs_soft_impulse_split
+//       Access: Published
+//  Description: Setter for property kSS_SPLT_CL.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_soft_vs_soft_impulse_split(float value) {
+
+  _cfg.kSS_SPLT_CL = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_maxvolume
+//       Access: Published
+//  Description: Getter for property maxvolume.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_maxvolume() const {
+
+  return _cfg.maxvolume;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_maxvolume
+//       Access: Published
+//  Description: Setter for property maxvolume.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_maxvolume(float value) {
+
+  _cfg.maxvolume = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_timescale
+//       Access: Published
+//  Description: Getter for property timescale.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyConfig::
+get_timescale() const {
+
+  return _cfg.timescale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_timescale
+//       Access: Published
+//  Description: Setter for property timescale.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_timescale(float value) {
+
+  _cfg.timescale = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_positions_solver_iterations
+//       Access: Published
+//  Description: Getter for property piterations.
+////////////////////////////////////////////////////////////////////
+INLINE int BulletSoftBodyConfig::
+get_positions_solver_iterations() const {
+
+  return _cfg.piterations;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_positions_solver_iterations
+//       Access: Published
+//  Description: Setter for property piterations.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_positions_solver_iterations(int value) {
+
+  nassertv(value > 0);
+  _cfg.piterations = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_velocities_solver_iterations
+//       Access: Published
+//  Description: Getter for property viterations.
+////////////////////////////////////////////////////////////////////
+INLINE int BulletSoftBodyConfig::
+get_velocities_solver_iterations() const {
+
+  return _cfg.viterations;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_velocities_solver_iterations
+//       Access: Published
+//  Description: Setter for property viterations.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_velocities_solver_iterations(int value) {
+
+  nassertv(value > 0);
+  _cfg.viterations = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_drift_solver_iterations
+//       Access: Published
+//  Description: Getter for property diterations.
+////////////////////////////////////////////////////////////////////
+INLINE int BulletSoftBodyConfig::
+get_drift_solver_iterations() const {
+
+  return _cfg.diterations;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_drift_solver_iterations
+//       Access: Published
+//  Description: Setter for property diterations.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_drift_solver_iterations(int value) {
+
+  nassertv(value > 0);
+  _cfg.diterations = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_cluster_solver_iterations
+//       Access: Published
+//  Description: Getter for property citerations.
+////////////////////////////////////////////////////////////////////
+INLINE int BulletSoftBodyConfig::
+get_cluster_solver_iterations() const {
+
+  return _cfg.citerations;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_cluster_solver_iterations
+//       Access: Published
+//  Description: Setter for property citerations.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyConfig::
+set_cluster_solver_iterations(int value) {
+
+  nassertv(value > 0);
+  _cfg.citerations = value;
+}
+

+ 86 - 0
panda/src/bullet/bulletSoftBodyConfig.cxx

@@ -0,0 +1,86 @@
+// Filename: bulletSoftBodyConfig.cxx
+// Created by:  enn0x (12Apr10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletSoftBodyConfig.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyConfig::
+BulletSoftBodyConfig(btSoftBody::Config &cfg) : _cfg(cfg) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::clear_collisions
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyConfig::
+clear_all_collision_flags() {
+
+  _cfg.collisions = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_collisions
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyConfig::
+set_collision_flag(CollisionFlag flag, bool value) {
+
+  if (value == true) {
+    _cfg.collisions |= flag;
+  }
+  else {
+    _cfg.collisions &= ~(flag);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_collisions
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool BulletSoftBodyConfig::
+get_collision_flag(CollisionFlag flag) const {
+
+  return (_cfg.collisions & flag) ? true : false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::set_aero_model
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyConfig::
+set_aero_model(AeroModel value) {
+
+  _cfg.aeromodel = (btSoftBody::eAeroModel::_)value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyConfig::get_aero_model
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyConfig::AeroModel BulletSoftBodyConfig::
+get_aero_model() const {
+
+  return (AeroModel)_cfg.aeromodel;
+}
+

+ 115 - 0
panda/src/bullet/bulletSoftBodyConfig.h

@@ -0,0 +1,115 @@
+// Filename: bulletSoftBodyConfig.h
+// Created by:  enn0x (12Apr10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_SOFT_BODY_CONFIG_H__
+#define __BULLET_SOFT_BODY_CONFIG_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletSoftBodyConfig
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletSoftBodyConfig {
+
+PUBLISHED:
+  INLINE ~BulletSoftBodyConfig();
+
+  enum CollisionFlag {
+    CF_rigid__vs_soft_mask   = 0x000f, // RVSmask: Rigid versus soft mask
+    CF_sdf_rigid_soft        = 0x0001, // SDF_RS:  SDF based rigid vs soft
+    CF_cluster_rigid_soft    = 0x0002, // CL_RS:   Cluster vs convex rigid vs soft
+    CF_soft_vs_soft_mask     = 0x0030, // SVSmask: Soft versus soft mask
+    CF_vertex_face_soft_soft = 0x0010, // VF_SS:   Vertex vs face soft vs soft handling
+    CF_cluster_soft_soft     = 0x0020, // CL_SS:   Cluster vs cluster soft vs soft handling
+    CF_cluster_self          = 0x0040, // CL_SELF: Cluster soft body self collision
+  };
+
+  enum AeroModel {
+    AM_vertex_point,     // V_Point:    Vertex normals are oriented toward velocity
+    AM_vertex_two_sided, // V_TwoSided: Vertex normals are fliped to match velocity
+    AM_vertex_one_sided, // V_OneSided: Vertex normals are taken as it is
+    AM_face_two_sided,   // F_TwoSided: Face normals are fliped to match velocity
+    AM_face_one_sided,   // F_OneSided: Face normals are taken as it is
+  };
+
+  void clear_all_collision_flags();
+  void set_collision_flag(CollisionFlag flag, bool value);
+  bool get_collision_flag(CollisionFlag flag) const;
+
+  void set_aero_model(AeroModel value);
+  AeroModel get_aero_model() const;
+
+  INLINE void set_velocities_correction_factor(float value);
+  INLINE void set_damping_coefficient(float value);
+  INLINE void set_drag_coefficient(float value);
+  INLINE void set_lift_coefficient(float value);
+  INLINE void set_pressure_coefficient(float value);
+  INLINE void set_volume_conversation_coefficient(float value);
+  INLINE void set_dynamic_friction_coefficient(float value);
+  INLINE void set_pose_matching_coefficient(float value);
+  INLINE void set_rigid_contacts_hardness(float value);
+  INLINE void set_kinetic_contacts_hardness(float value);
+  INLINE void set_soft_contacts_hardness(float value);
+  INLINE void set_anchors_hardness(float value);
+  INLINE void set_soft_vs_rigid_hardness(float value);
+  INLINE void set_soft_vs_kinetic_hardness(float value);
+  INLINE void set_soft_vs_soft_hardness(float value);
+  INLINE void set_soft_vs_rigid_impulse_split(float value);
+  INLINE void set_soft_vs_kinetic_impulse_split(float value);
+  INLINE void set_soft_vs_soft_impulse_split(float value);
+  INLINE void set_maxvolume(float value);
+  INLINE void set_timescale(float value);
+  INLINE void set_positions_solver_iterations(int value);
+  INLINE void set_velocities_solver_iterations(int value);
+  INLINE void set_drift_solver_iterations( int value);
+  INLINE void set_cluster_solver_iterations(int value);
+
+  INLINE float get_velocities_correction_factor() const;
+  INLINE float get_damping_coefficient() const;
+  INLINE float get_drag_coefficient() const;
+  INLINE float get_lift_coefficient() const;
+  INLINE float get_pressure_coefficient() const;
+  INLINE float get_volume_conversation_coefficient() const;
+  INLINE float get_dynamic_friction_coefficient() const;
+  INLINE float get_pose_matching_coefficient() const;
+  INLINE float get_rigid_contacts_hardness() const;
+  INLINE float get_kinetic_contacts_hardness() const;
+  INLINE float get_soft_contacts_hardness() const;
+  INLINE float get_anchors_hardness() const;
+  INLINE float get_soft_vs_rigid_hardness() const;
+  INLINE float get_soft_vs_kinetic_hardness() const;
+  INLINE float get_soft_vs_soft_hardness() const;
+  INLINE float get_soft_vs_rigid_impulse_split() const;
+  INLINE float get_soft_vs_kinetic_impulse_split() const;
+  INLINE float get_soft_vs_soft_impulse_split() const;
+  INLINE float get_maxvolume() const;
+  INLINE float get_timescale() const;
+  INLINE int get_positions_solver_iterations() const;
+  INLINE int get_velocities_solver_iterations() const;
+  INLINE int get_drift_solver_iterations() const;
+  INLINE int get_cluster_solver_iterations() const;
+
+public:
+  BulletSoftBodyConfig(btSoftBody::Config &cfg);
+
+private:
+  btSoftBody::Config &_cfg;
+};
+
+#include "bulletSoftBodyConfig.I"
+
+#endif // __BULLET_SOFT_BODY_CONFIG_H__

+ 115 - 0
panda/src/bullet/bulletSoftBodyMaterial.I

@@ -0,0 +1,115 @@
+// Filename: bulletSoftBodyMaterial.I
+// Created by:  enn0x (19Mar11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyMaterial::
+~BulletSoftBodyMaterial() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::empty
+//       Access: Published
+//  Description: Named constructor intended to be used for asserts
+//               with have to return a concrete value.
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyMaterial BulletSoftBodyMaterial::
+empty() {
+
+  static btSoftBody::Material material;
+
+  return BulletSoftBodyMaterial(material);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyWorldInfo::get_material
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE btSoftBody::Material &BulletSoftBodyMaterial::
+get_material() const {
+
+  return _material;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::getLinearStiffness
+//       Access: Published
+//  Description: Getter for the property m_kLST.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyMaterial::
+getLinearStiffness() const {
+
+  return _material.m_kLST;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::setLinearStiffness
+//       Access: Published
+//  Description: Setter for the property m_kLST.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyMaterial::
+setLinearStiffness(float value) {
+
+  _material.m_kLST = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::getAngularStiffness
+//       Access: Published
+//  Description: Getter for the property m_kAST.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyMaterial::
+getAngularStiffness() const {
+
+  return _material.m_kAST;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::setAngularStiffness
+//       Access: Published
+//  Description: Setter for the property m_kAST.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyMaterial::
+setAngularStiffness(float value) {
+
+  _material.m_kAST = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::getVolumePreservation
+//       Access: Published
+//  Description: Getter for the property m_kVST.
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyMaterial::
+getVolumePreservation() const {
+
+  return _material.m_kVST;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::setVolumePreservation
+//       Access: Published
+//  Description: Setter for the property m_kVST.
+////////////////////////////////////////////////////////////////////
+INLINE void BulletSoftBodyMaterial::
+setVolumePreservation(float value) {
+
+  _material.m_kVST = value;
+}
+

+ 26 - 0
panda/src/bullet/bulletSoftBodyMaterial.cxx

@@ -0,0 +1,26 @@
+// Filename: bulletSoftBodyMaterial.cxx
+// Created by:  enn0x (19Mar11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletSoftBodyMaterial.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyMaterial::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyMaterial::
+BulletSoftBodyMaterial(btSoftBody::Material &material) : _material(material) {
+
+}
+

+ 51 - 0
panda/src/bullet/bulletSoftBodyMaterial.h

@@ -0,0 +1,51 @@
+// Filename: bulletSoftBodyMaterial.h
+// Created by:  enn0x (19Mar11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_SOFT_BODY_MATERIAL_H__
+#define __BULLET_SOFT_BODY_MATERIAL_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletSoftBodyMaterial
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletSoftBodyMaterial {
+
+PUBLISHED:
+  INLINE ~BulletSoftBodyMaterial();
+  INLINE static BulletSoftBodyMaterial empty();
+
+  INLINE void setLinearStiffness(float value);
+  INLINE void setAngularStiffness(float value);
+  INLINE void setVolumePreservation(float value);
+
+  INLINE float getLinearStiffness() const;
+  INLINE float getAngularStiffness() const;
+  INLINE float getVolumePreservation() const;
+
+public:
+  BulletSoftBodyMaterial(btSoftBody::Material &material);
+
+  INLINE btSoftBody::Material &get_material() const;
+
+private:
+  btSoftBody::Material &_material;
+};
+
+#include "bulletSoftBodyMaterial.I"
+
+#endif // __BULLET_SOFT_BODY_MATERIAL_H__

+ 116 - 0
panda/src/bullet/bulletSoftBodyNode.I

@@ -0,0 +1,116 @@
+// Filename: bulletSoftBodyNode.I
+// Created by:  enn0x (27Dec10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyNode::
+~BulletSoftBodyNode() {
+
+  delete _body;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyNodeElement::
+~BulletSoftBodyNodeElement() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::empty
+//       Access: Published
+//  Description: Named constructor intended to be used for asserts
+//               with have to return a concrete value.
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyNodeElement BulletSoftBodyNodeElement::
+empty() {
+
+  static btSoftBody::Node node;
+
+  return BulletSoftBodyNodeElement(node);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::get_pos
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE LPoint3f BulletSoftBodyNodeElement::
+get_pos() const {
+
+  return btVector3_to_LPoint3f(_node.m_x);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::get_normal
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE LVector3f BulletSoftBodyNodeElement::
+get_normal() const {
+
+  return btVector3_to_LVector3f(_node.m_n);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::get_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE LVector3f BulletSoftBodyNodeElement::
+get_velocity() const {
+
+  return btVector3_to_LVector3f(_node.m_v);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::get_inv_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyNodeElement::
+get_inv_mass() const {
+
+  return _node.m_im;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::get_area
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE float BulletSoftBodyNodeElement::
+get_area() const {
+
+  return _node.m_area;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::is_attached
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int BulletSoftBodyNodeElement::
+is_attached() const {
+
+  return _node.m_battach;
+}
+

+ 1039 - 0
panda/src/bullet/bulletSoftBodyNode.cxx

@@ -0,0 +1,1039 @@
+// Filename: bulletSoftBodyNode.cxx
+// Created by:  enn0x (27Dec10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "bulletSoftBodyNode.h"
+#include "bulletSoftBodyConfig.h"
+#include "bulletSoftBodyMaterial.h"
+#include "bulletSoftBodyShape.h"
+#include "bulletSoftBodyWorldInfo.h"
+#include "bulletHelper.h"
+
+#include "geomVertexRewriter.h"
+#include "geomVertexReader.h"
+
+TypeHandle BulletSoftBodyNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyNode::
+BulletSoftBodyNode(btSoftBody *body, const char *name) : BulletBodyNode(name) {
+
+  // Setup body
+  _body = body;
+  _body->setUserPointer(this);
+
+  // Shape
+  btCollisionShape *shape_ptr = _body->getCollisionShape();
+
+  nassertv(shape_ptr != NULL);
+  nassertv(shape_ptr->getShapeType() == SOFTBODY_SHAPE_PROXYTYPE);
+
+  _shapes.push_back(new BulletSoftBodyShape((btSoftBodyCollisionShape *)shape_ptr));
+
+  // Rendering
+  _geom = NULL;
+  _curve = NULL;
+  _surface = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_object
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+btCollisionObject *BulletSoftBodyNode::
+get_object() const {
+
+  return _body;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_cfg
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyConfig BulletSoftBodyNode::
+get_cfg() {
+
+  return BulletSoftBodyConfig(_body->m_cfg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_world_info
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyWorldInfo BulletSoftBodyNode::
+get_world_info() {
+
+  return BulletSoftBodyWorldInfo(*(_body->m_worldInfo));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_num_materials
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+int BulletSoftBodyNode::
+get_num_materials() const {
+
+  return _body->m_materials.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_material
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyMaterial BulletSoftBodyNode::
+get_material(int idx) const {
+
+  nassertr(idx >= 0 && idx < get_num_materials(), BulletSoftBodyMaterial::empty());
+
+  btSoftBody::Material *material = _body->m_materials[idx];
+  return BulletSoftBodyMaterial(*material);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_num_nodes
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+int BulletSoftBodyNode::
+get_num_nodes() const {
+
+  return _body->m_nodes.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_node
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyNodeElement BulletSoftBodyNode::
+get_node(int idx) const {
+
+  nassertr(idx >=0 && idx < get_num_nodes(), BulletSoftBodyNodeElement::empty());
+  return BulletSoftBodyNodeElement(_body->m_nodes[idx]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::append_material
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyMaterial BulletSoftBodyNode::
+append_material() {
+
+  btSoftBody::Material *material = _body->appendMaterial();
+  nassertr(material, BulletSoftBodyMaterial::empty());
+
+  return BulletSoftBodyMaterial(*material);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::generate_bending_constraints
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+generate_bending_constraints(int distance, BulletSoftBodyMaterial *material) {
+
+  if (material) {
+    _body->generateBendingConstraints(distance, &(material->get_material()));
+  }
+  else {
+    _body->generateBendingConstraints(distance);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::randomize_constraints
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+randomize_constraints() {
+
+  _body->randomizeConstraints();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::parents_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+parents_changed() {
+
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::transform_changed
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+transform_changed() {
+
+  if (_disable_transform_changed) return;
+
+  btTransform trans;
+  get_node_transform(trans, this);
+  trans *= _body->m_initialWorldTransform.inverse();
+  _body->transform(trans);
+
+  BulletBodyNode::transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::post_step
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+post_step() {
+
+  if (_geom) {
+    btTransform trans;
+    get_node_transform(trans, this);
+
+    PT(GeomVertexData) vdata = _geom->modify_vertex_data();
+
+    GeomVertexRewriter vertices(vdata, InternalName::get_vertex());
+    GeomVertexRewriter normals(vdata, InternalName::get_normal());
+    GeomVertexReader indices(vdata, BulletHelper::get_sb_index());
+    GeomVertexReader flips(vdata, BulletHelper::get_sb_flip());
+
+    while (!vertices.is_at_end()) {
+      btSoftBody::Node node = _body->m_nodes[indices.get_data1i()];
+      btVector3 v = trans.invXform(node.m_x);
+      btVector3 n = node.m_n;
+
+      if (flips.get_data1i() > 0) n *= -1;
+
+      vertices.set_data3f(v.getX(), v.getY(), v.getZ());
+      normals.set_data3f(n.getX(), n.getY(), n.getZ());
+    }
+  }
+
+  if (_curve) {
+    btSoftBody::tNodeArray &nodes(_body->m_nodes);
+
+    for (int i=0; i < nodes.size(); i++) {
+      btVector3 pos = nodes[i].m_x;
+      _curve->set_vertex(i, btVector3_to_LPoint3f(pos));
+    }
+  }
+
+  if (_surface) {
+    btSoftBody::tNodeArray &nodes(_body->m_nodes);
+
+    int num_u = _surface->get_num_u_vertices();
+    int num_v = _surface->get_num_v_vertices();
+    nassertv(num_u * num_v == nodes.size());
+
+    for (int u=0; u < num_u; u++) {
+      for (int v=0; v < num_v; v++) {
+        btVector3 pos = nodes[u * num_u + v].m_x;
+        _surface->set_vertex(u, v, btVector3_to_LPoint3f(pos));
+      }
+    }
+  }
+
+  // It is ok to pass the address of a temporary object here, because
+  // set_bounds does not store the pointer - it makes a copy using
+  // volume->make_copy().
+  BoundingBox bb = this->get_aabb();
+  CPT(TransformState) xform = TransformState::make_pos(bb.get_approx_center());
+
+  _disable_transform_changed = true;
+  this->set_transform(xform);
+  _disable_transform_changed = false;
+
+  Thread *current_thread = Thread::get_current_thread();
+  this->r_mark_geom_bounds_stale(current_thread);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_closest_node_index
+//       Access: Published
+//  Description: Returns the index of the node which is closest
+//               to the given point. The distance between each node
+//               and the given point is computed in world space
+//               if local=false, and in local space if local=true.
+////////////////////////////////////////////////////////////////////
+int BulletSoftBodyNode::
+get_closest_node_index(LVecBase3f point, bool local) {
+
+  btScalar max_dist_sqr = 1e30;
+  btVector3 point_x = LVecBase3f_to_btVector3(point);
+
+  btTransform trans;
+  if (local == true) {
+    get_node_transform(trans, this);
+  }
+  else {
+    trans.setIdentity();
+  }
+
+  btSoftBody::tNodeArray &nodes(_body->m_nodes);
+  int node_idx = 0;
+
+  for (int i=0; i<nodes.size(); ++i) {
+
+    btVector3 node_x = nodes[i].m_x;
+    btScalar dist_sqr = (trans.invXform(node_x) - point_x).length2();
+
+    if (dist_sqr < max_dist_sqr) {
+      max_dist_sqr = dist_sqr;
+      node_idx = i;
+    }
+  }
+
+  return node_idx;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::link_geom
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+link_geom(Geom *geom) {
+
+  nassertv(geom->get_vertex_data()->has_column(InternalName::get_vertex()));
+  nassertv(geom->get_vertex_data()->has_column(InternalName::get_normal()));
+
+  _geom = geom;
+
+  PT(GeomVertexData) vdata = _geom->modify_vertex_data();
+
+  if (!vdata->has_column(BulletHelper::get_sb_index())) {
+    CPT(GeomVertexFormat) format = vdata->get_format();
+    format = BulletHelper::add_sb_index_column(format);
+    vdata->set_format(format);
+  }
+
+  if (!vdata->has_column(BulletHelper::get_sb_flip())) {
+    CPT(GeomVertexFormat) format = vdata->get_format();
+    format = BulletHelper::add_sb_flip_column(format);
+    vdata->set_format(format);
+  }
+
+  GeomVertexReader vertices(vdata, InternalName::get_vertex());
+  GeomVertexRewriter indices(vdata, BulletHelper::get_sb_index());
+
+  while (!vertices.is_at_end()) {
+    LVecBase3f point = vertices.get_data3f();
+    int node_idx = get_closest_node_index(point, true);
+    indices.set_data1i(node_idx);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::unlink_geom
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+unlink_geom() {
+
+  _geom = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::link_curve
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+link_curve(NurbsCurveEvaluator *curve) {
+
+  nassertv(curve->get_num_vertices() == _body->m_nodes.size());
+
+  _curve = curve;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::unlink_curve
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+unlink_curve() {
+
+  _curve = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::link_surface
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+link_surface(NurbsSurfaceEvaluator *surface) {
+
+  nassertv(surface->get_num_u_vertices() * surface->get_num_v_vertices() == _body->m_nodes.size());
+
+  _surface = surface;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::unlink_surface
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+unlink_surface() {
+
+  _surface = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_aabb
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+BoundingBox BulletSoftBodyNode::
+get_aabb() const {
+
+  btVector3 pMin;
+  btVector3 pMax;
+
+  _body->getAabb(pMin, pMax);
+
+  return BoundingBox(
+    btVector3_to_LPoint3f(pMin),
+    btVector3_to_LPoint3f(pMax)
+    );
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_volume_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_volume_mass(float mass) {
+
+  _body->setVolumeMass(mass);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_total_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_total_mass(float mass, bool fromfaces) {
+
+  _body->setTotalMass(mass, fromfaces);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_volume_density
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_volume_density(float density) {
+
+  _body->setVolumeDensity(density);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_total_density
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_total_density(float density) {
+
+  _body->setTotalDensity(density);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_mass(int node, float mass) {
+
+  _body->setMass(node, mass);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSoftBodyNode::
+get_mass(int node) const {
+
+  return _body->getMass(node);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_total_mass
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSoftBodyNode::
+get_total_mass() const {
+
+  return _body->getTotalMass();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_volume
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+float BulletSoftBodyNode::
+get_volume() const {
+
+  return _body->getVolume();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::add_force
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+add_force(const LVector3f &force) {
+
+  nassertv(!force.is_nan());
+  _body->addForce(LVecBase3f_to_btVector3(force));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::add_force
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+add_force(const LVector3f &force, int node) {
+
+  nassertv(!force.is_nan());
+  _body->addForce(LVecBase3f_to_btVector3(force), node);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_velocity(const LVector3f &velocity) {
+
+  nassertv(!velocity.is_nan());
+  _body->setVelocity(LVecBase3f_to_btVector3(velocity));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::add_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+add_velocity(const LVector3f &velocity) {
+
+  nassertv(!velocity.is_nan());
+  _body->addVelocity(LVecBase3f_to_btVector3(velocity));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::add_velocity
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+add_velocity(const LVector3f &velocity, int node) {
+
+  nassertv(!velocity.is_nan());
+  _body->addVelocity(LVecBase3f_to_btVector3(velocity), node);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::generate_clusters
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+generate_clusters(int k, int maxiterations) {
+
+  _body->generateClusters(k, maxiterations);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::release_clusters
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+release_clusters() {
+
+  _body->releaseClusters();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::release_cluster
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+release_cluster(int index) {
+
+  _body->releaseCluster(index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_num_clusters
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+int BulletSoftBodyNode::
+get_num_clusters() const {
+
+  return _body->clusterCount();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::cluster_com
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVecBase3f BulletSoftBodyNode::
+cluster_com(int cluster) const {
+
+  return btVector3_to_LVecBase3f(_body->clusterCom(cluster));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::set_pose
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+set_pose(bool bvolume, bool bframe) {
+
+  _body->setPose(bvolume, bframe);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::append_anchor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+append_anchor(int node, BulletRigidBodyNode *body, bool disable) {
+
+  nassertv(node < _body->m_nodes.size())
+  nassertv(body);
+
+  btRigidBody *ptr =(btRigidBody *)body->get_object();
+  _body->appendAnchor(node, ptr, disable);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::append_anchor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void BulletSoftBodyNode::
+append_anchor(int node, BulletRigidBodyNode *body, const LVector3f &pivot, bool disable) {
+
+  nassertv(node < _body->m_nodes.size())
+  nassertv(body);
+  nassertv(!pivot.is_nan());
+
+  btRigidBody *ptr =(btRigidBody *)body->get_object();
+  _body->appendAnchor(node, ptr, LVecBase3f_to_btVector3(pivot), disable);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNodeElement::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BulletSoftBodyNodeElement::
+BulletSoftBodyNodeElement(btSoftBody::Node &node) : _node(node) {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::get_point_index
+//       Access: Private
+//  Description: Returns the index of the first point within an
+//               array of points which has about the same 
+//               coordinates as the given point. If no points
+//               is found -1 is returned.
+////////////////////////////////////////////////////////////////////
+int BulletSoftBodyNode::
+get_point_index(LVecBase3f p, PTA_LVecBase3f points) {
+
+  float eps = 1.0e-6f; // TODO make this a config option
+
+  for (PTA_LVecBase3f::size_type i=0; i<points.size(); i++) {
+    if (points[i].almost_equal(p, eps)) {
+      return i; // Found
+    }
+  }
+
+  return -1; // Not found
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::next_line
+//       Access: Published
+//  Description: Read on until the next linebreak is detected, or
+//               the end of file has been reached.
+////////////////////////////////////////////////////////////////////
+int BulletSoftBodyNode::
+next_line(const char* buffer) {
+
+  int num_bytes_read = 0;
+
+  while (*buffer != '\n') {
+    buffer++;
+    num_bytes_read++;
+  }
+  
+  if (buffer[0] == 0x0a) {
+    buffer++;
+    num_bytes_read++;
+  }
+
+  return num_bytes_read;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_rope
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_rope(BulletSoftBodyWorldInfo &info, const LPoint3f &from, const LPoint3f &to, int res, int fixeds) {
+
+  btSoftBody *body = btSoftBodyHelpers::CreateRope(
+    info.get_info(),
+    LVecBase3f_to_btVector3(from),
+    LVecBase3f_to_btVector3(to),
+    res,
+    fixeds);
+
+  PT(BulletSoftBodyNode) node = new BulletSoftBodyNode(body);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_patch
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_patch(BulletSoftBodyWorldInfo &info, const LPoint3f &corner00, const LPoint3f &corner10, const LPoint3f &corner01, const LPoint3f &corner11, int resx, int resy, int fixeds, bool gendiags) {
+
+  btSoftBody *body = btSoftBodyHelpers::CreatePatch(
+    info.get_info(),
+    LVecBase3f_to_btVector3(corner00),
+    LVecBase3f_to_btVector3(corner10),
+    LVecBase3f_to_btVector3(corner01),
+    LVecBase3f_to_btVector3(corner11),
+    resx,
+    resy,
+    fixeds,
+    gendiags);
+
+  PT(BulletSoftBodyNode) node = new BulletSoftBodyNode(body);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_ellipsoid
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_ellipsoid(BulletSoftBodyWorldInfo &info, const LPoint3f &center, const LVecBase3f &radius, int res) {
+
+  btSoftBody *body = btSoftBodyHelpers::CreateEllipsoid(
+    info.get_info(),
+    LVecBase3f_to_btVector3(center),
+    LVecBase3f_to_btVector3(radius),
+    res);
+
+  PT(BulletSoftBodyNode) node = new BulletSoftBodyNode(body);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_tri_mesh
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_tri_mesh(BulletSoftBodyWorldInfo &info, PTA_LVecBase3f points, PTA_int indices, bool randomizeConstraints) {
+
+  // Eliminate duplicate vertices
+  PTA_LVecBase3f mapped_points;
+  PTA_int mapped_indices;
+
+  pmap<int, int> mapping;
+
+  for (PTA_LVecBase3f::size_type i=0; i<points.size(); i++) {
+    LVecBase3f p = points[i];
+    int j = get_point_index(p, mapped_points);
+    if (j < 0) {
+      mapping[i] = mapped_points.size();
+      mapped_points.push_back(p);
+    }
+    else {
+      mapping[i] = j;
+    }
+  }
+
+  for (PTA_int::size_type i=0; i<indices.size(); i++) {
+    int idx = indices[i];
+    int mapped_idx = mapping[idx];
+    mapped_indices.push_back(mapped_idx);
+  }
+
+  points = mapped_points;
+  indices = mapped_indices;
+
+  // Convert arrays
+  int num_vertices = points.size();
+  int num_triangles = indices.size() / 3;
+
+  btScalar *vertices = new btScalar[num_vertices * 3];
+  for (int i=0; i < num_vertices; i++) {
+    vertices[3*i]   = points[i].get_x();
+    vertices[3*i+1] = points[i].get_y();
+    vertices[3*i+2] = points[i].get_z();
+  }
+
+  int *triangles = new int[num_triangles * 3];
+  for (int i=0; i < num_triangles * 3; i++) {
+    triangles[i] = indices[i];
+  }
+
+  // Create body
+  btSoftBody *body = btSoftBodyHelpers::CreateFromTriMesh(
+    info.get_info(),
+    vertices,
+    triangles,
+    num_triangles,
+    randomizeConstraints);
+
+  nassertr(body, NULL);
+
+  delete[] vertices;
+  delete[] triangles;
+
+  PT(BulletSoftBodyNode) node = new BulletSoftBodyNode(body);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_tri_mesh
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_tri_mesh(BulletSoftBodyWorldInfo &info, const Geom *geom, bool randomizeConstraints) {
+
+  // Read vertex data
+  PTA_LVecBase3f points;
+  PTA_int indices;
+
+  CPT(GeomVertexData) vdata = geom->get_vertex_data();
+
+  nassertr(vdata->has_column(InternalName::get_vertex()), NULL);
+
+  GeomVertexReader vreader(vdata, InternalName::get_vertex());
+
+  while (!vreader.is_at_end()) {
+    LVecBase3f v = vreader.get_data3f();
+    points.push_back(v);
+  }
+
+  // Read indices
+  for (int i=0; i<geom->get_num_primitives(); i++) {
+
+    CPT(GeomPrimitive) prim = geom->get_primitive(i);
+    prim = prim->decompose();
+
+    for (int j=0; j<prim->get_num_primitives(); j++) {
+
+      int s = prim->get_primitive_start(j);
+      int e = prim->get_primitive_end(j);
+
+      for (int k=s; k<e; k++) {
+        indices.push_back(prim->get_vertex(k));
+      }
+    }
+  }
+
+  // Create body
+  return make_tri_mesh(info, points, indices, randomizeConstraints);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_tet_mesh
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_tet_mesh(BulletSoftBodyWorldInfo &info, PTA_LVecBase3f points, PTA_int indices, bool tetralinks) {
+
+  // Points
+  btAlignedObjectArray<btVector3> pos;
+  pos.resize(points.size());
+  for (PTA_LVecBase3f::size_type i=0; i<points.size(); i++) {
+    LVecBase3f point = points[i];
+    pos[i] = LVecBase3f_to_btVector3(point);
+  }
+
+  // Body
+  btSoftBody* body = new btSoftBody(&info.get_info(), pos.size(), &pos[0], 0);
+
+  // Indices
+  for (PTA_int::size_type i=0; i<indices.size() / 4; i++) {
+    int ni[4];
+
+    ni[0] = indices[4*i];
+    ni[1] = indices[4*i+1];
+    ni[2] = indices[4*i+2];
+    ni[3] = indices[4*i+3];
+
+    body->appendTetra(ni[0],ni[1],ni[2],ni[3]);
+
+    if (tetralinks) {
+      body->appendLink(ni[0], ni[1], 0, true);
+      body->appendLink(ni[1], ni[2], 0, true);
+      body->appendLink(ni[2], ni[0], 0, true);
+      body->appendLink(ni[0], ni[3], 0, true);
+      body->appendLink(ni[1], ni[3], 0, true);
+      body->appendLink(ni[2], ni[3], 0, true);
+    }
+  }
+
+  // Node
+  PT(BulletSoftBodyNode) node = new BulletSoftBodyNode(body);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyNode::make_tet_mesh
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(BulletSoftBodyNode) BulletSoftBodyNode::
+make_tet_mesh(BulletSoftBodyWorldInfo &info, const char *ele, const char *face, const char *node) {
+
+  nassertr(node && node[0], NULL);
+
+  // Nodes
+  btAlignedObjectArray<btVector3> pos;
+
+  int npos = 0;
+  int ndims = 0; // not used
+  int nattrb = 0; // not used
+  int hasbounds = 0; // not used
+
+  sscanf(node, "%d %d %d %d", &npos, &ndims, &nattrb, &hasbounds);
+  node += next_line(node);
+
+  pos.resize(npos);
+
+  for (int i=0; i<pos.size(); ++i) {
+    int index = 0;
+    float x, y, z;
+
+    sscanf(node, "%d %f %f %f", &index, &x, &y, &z);
+    node += next_line(node);
+
+    pos[index].setX(btScalar(x));
+    pos[index].setY(btScalar(y));
+    pos[index].setZ(btScalar(z));
+  }
+
+  // Body
+  btSoftBody *body = new btSoftBody(&info.get_info(), npos, &pos[0], 0);
+
+  // Faces
+  if (face && face[0]) {
+    int nface = 0;
+    int hasbounds = 0; // not used
+
+    sscanf(face, "%d %d", &nface, &hasbounds);
+    face += next_line(face);
+
+    for (int i=0; i<nface; ++i) {
+      int index = 0;
+      int ni[3];
+
+      sscanf(face, "%d %d %d %d", &index, &ni[0], &ni[1], &ni[2]);
+      face += next_line(face);
+
+      body->appendFace(ni[0], ni[1], ni[2]);
+    }
+  }
+
+  // Links
+  if (ele && ele[0]) {
+    int ntetra = 0;
+    int ncorner = 0;
+    int neattrb = 0;
+
+    sscanf(ele, "%d %d %d", &ntetra, &ncorner, &neattrb);
+    ele += next_line(ele);
+
+    for (int i=0; i<ntetra; ++i) {
+      int index = 0;
+      int ni[4];
+
+      sscanf(ele, "%d %d %d %d %d", &index, &ni[0], &ni[1], &ni[2], &ni[3]);
+      ele += next_line(ele);
+
+      body->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+
+      body->appendLink(ni[0], ni[1], 0, true);
+      body->appendLink(ni[1], ni[2], 0, true);
+      body->appendLink(ni[2], ni[0], 0, true);
+      body->appendLink(ni[0], ni[3], 0, true);
+      body->appendLink(ni[1], ni[3], 0, true);
+      body->appendLink(ni[2], ni[3], 0, true);
+    }
+  }
+
+  // Node
+  PT(BulletSoftBodyNode) sbnode = new BulletSoftBodyNode(body);
+
+  return sbnode;
+}
+

+ 232 - 0
panda/src/bullet/bulletSoftBodyNode.h

@@ -0,0 +1,232 @@
+// Filename: bulletSoftBodyNode.h
+// Created by:  enn0x (27Dec10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 __BULLET_SOFT_BODY_NODE_H__
+#define __BULLET_SOFT_BODY_NODE_H__
+
+#include "pandabase.h"
+
+#include "bullet_includes.h"
+#include "bullet_utils.h"
+#include "bulletBodyNode.h"
+
+#include "collideMask.h"
+#include "geom.h"
+#include "geomNode.h"
+#include "geomVertexFormat.h"
+#include "boundingBox.h"
+#include "nurbsCurveEvaluator.h"
+#include "nurbsSurfaceEvaluator.h"
+#include "pta_LVecBase3f.h"
+
+class BulletSoftBodyConfig;
+class BulletSoftBodyMaterial;
+class BulletSoftBodyWorldInfo;
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletSoftBodyNodeElement
+// Description : 
+////////////////////////////////////////////////////////////////////
+class BulletSoftBodyNodeElement {
+
+PUBLISHED:
+  INLINE ~BulletSoftBodyNodeElement();
+  INLINE static BulletSoftBodyNodeElement empty();
+
+  INLINE LPoint3f get_pos() const;
+  INLINE LVector3f get_velocity() const;
+  INLINE LVector3f get_normal() const;
+  INLINE float get_inv_mass() const;
+  INLINE float get_area() const;
+  INLINE int is_attached() const;
+
+public:
+  BulletSoftBodyNodeElement(btSoftBody::Node &node);
+
+private:
+  btSoftBody::Node &_node;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : BulletSoftBodyNode
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDABULLET BulletSoftBodyNode : public BulletBodyNode {
+
+public:
+  BulletSoftBodyNode(btSoftBody *body, const char *name="softbody");
+
+PUBLISHED:
+  INLINE ~BulletSoftBodyNode();
+
+  BulletSoftBodyConfig get_cfg();
+  BulletSoftBodyWorldInfo get_world_info();
+
+  void generate_bending_constraints(int distance, BulletSoftBodyMaterial *material=NULL);
+  void randomize_constraints(); 
+
+  // Mass, volume, density
+  void set_volume_mass(float mass);
+  void set_volume_density(float density);
+  void set_total_mass(float mass, bool fromfaces=false);
+  void set_total_density(float density);
+  void set_mass(int node, float mass);
+
+  float get_mass(int node) const;
+  float get_total_mass() const;
+  float get_volume() const;
+
+  // Force
+  void add_force(const LVector3f &force);
+  void add_force(const LVector3f &force, int node);
+
+  void set_velocity(const LVector3f &velocity);
+  void add_velocity(const LVector3f &velocity);
+  void add_velocity(const LVector3f &velocity, int node);
+
+  void set_pose(bool bvolume, bool bframe);
+
+  BoundingBox get_aabb() const;
+
+  // Cluster
+  void generate_clusters(int k, int maxiterations=8192);
+  void release_cluster(int index);
+  void release_clusters();
+  int get_num_clusters() const;
+  LVecBase3f cluster_com(int cluster) const;
+
+  // Rendering
+  void link_geom(Geom *geom);
+  void unlink_geom();
+
+  void link_curve(NurbsCurveEvaluator *curve);
+  void unlink_curve();
+
+  void link_surface(NurbsSurfaceEvaluator *surface);
+  void unlink_surface();
+
+  // Anchors
+  void append_anchor(int node, BulletRigidBodyNode *body, 
+      bool disable=false);
+  void append_anchor(int node, BulletRigidBodyNode *body, 
+      const LVector3f &pivot,
+      bool disable=false);
+
+  // Materials
+  int get_num_materials() const;
+  BulletSoftBodyMaterial get_material(int idx) const;
+  MAKE_SEQ(get_materials, get_num_materials, get_material);
+
+  BulletSoftBodyMaterial append_material();
+
+  // Nodes
+  int get_num_nodes() const;
+  BulletSoftBodyNodeElement get_node(int idx) const;
+  MAKE_SEQ(get_nodes, get_num_nodes, get_node);
+
+  int get_closest_node_index(LVecBase3f point, bool local);
+
+  // Factory
+  static PT(BulletSoftBodyNode) make_rope(
+      BulletSoftBodyWorldInfo &info,
+      const LPoint3f &from,
+      const LPoint3f &to,
+      int res,
+      int fixeds);
+
+  static PT(BulletSoftBodyNode) make_patch(
+      BulletSoftBodyWorldInfo &info,
+      const LPoint3f &corner00,
+      const LPoint3f &corner10,
+      const LPoint3f &corner01,
+      const LPoint3f &corner11,
+      int resx,
+      int resy,
+      int fixeds,
+      bool gendiags);
+
+  static PT(BulletSoftBodyNode) make_ellipsoid(
+      BulletSoftBodyWorldInfo &info,
+      const LPoint3f &center,
+      const LVecBase3f &radius,
+      int res);
+
+  static PT(BulletSoftBodyNode) make_tri_mesh(
+      BulletSoftBodyWorldInfo &info,
+      const Geom *geom,
+      bool randomizeConstraints=true);
+
+  static PT(BulletSoftBodyNode) make_tri_mesh(
+      BulletSoftBodyWorldInfo &info,
+      PTA_LVecBase3f points, 
+      PTA_int indices,
+      bool randomizeConstraints=true);
+
+  static PT(BulletSoftBodyNode) make_tet_mesh(
+      BulletSoftBodyWorldInfo &info,
+      PTA_LVecBase3f points,
+      PTA_int indices,
+      bool tetralinks=true);
+
+  static PT(BulletSoftBodyNode) make_tet_mesh(
+      BulletSoftBodyWorldInfo &info,
+      const char *ele,
+      const char *face,
+      const char *node);
+
+public:
+  virtual btCollisionObject *get_object() const;
+
+  void post_step();
+
+protected:
+  virtual void parents_changed();
+  virtual void transform_changed();
+
+private:
+  btSoftBody *_body;
+
+  PT(Geom) _geom;
+  PT(NurbsCurveEvaluator) _curve;
+  PT(NurbsSurfaceEvaluator) _surface;
+
+  static int get_point_index(LVecBase3f p, PTA_LVecBase3f points);
+  static int next_line(const char *buffer);
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    BulletBodyNode::init_type();
+    register_type(_type_handle, "BulletSoftBodyNode", 
+                  BulletBodyNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "bulletSoftBodyNode.I"
+
+#endif // __BULLET_SOFT_BODY_NODE_H__
+

+ 28 - 0
panda/src/bullet/bulletSoftBodyShape.I

@@ -0,0 +1,28 @@
+// Filename: bulletSoftBodyShape.I
+// Created by:  enn0x (06May10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSoftBodyShape::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE BulletSoftBodyShape::
+~BulletSoftBodyShape() {
+
+  // The btSoftBodyShape _shape is created and deleted internally
+  // by the owning btSoftBody object. It must not be deleted
+  // here!
+}
+

Some files were not shown because too many files changed in this diff