Browse Source

Moving to PhysX SDK 2.8.4 (win only), and added first experimental SoftBody code.

enn0x 15 năm trước cách đây
mục cha
commit
e2093b1c2d
37 tập tin đã thay đổi với 3499 bổ sung32 xóa
  1. 3 3
      makepanda/makepanda.py
  2. 3 1
      makepanda/makepandacore.py
  3. 18 0
      panda/src/physx/Sources.pp
  4. 6 0
      panda/src/physx/config_physx.cxx
  5. 12 9
      panda/src/physx/physxCloth.cxx
  6. 37 2
      panda/src/physx/physxEnums.h
  7. 47 0
      panda/src/physx/physxKitchen.cxx
  8. 4 0
      panda/src/physx/physxKitchen.h
  9. 24 0
      panda/src/physx/physxManager.cxx
  10. 10 0
      panda/src/physx/physxManager.h
  11. 84 0
      panda/src/physx/physxMeshHash.I
  12. 263 0
      panda/src/physx/physxMeshHash.cxx
  13. 78 0
      panda/src/physx/physxMeshHash.h
  14. 76 1
      panda/src/physx/physxMeshPool.cxx
  15. 5 4
      panda/src/physx/physxMeshPool.h
  16. 1 1
      panda/src/physx/physxScene.I
  17. 67 10
      panda/src/physx/physxScene.cxx
  18. 10 1
      panda/src/physx/physxScene.h
  19. 66 0
      panda/src/physx/physxSoftBody.I
  20. 914 0
      panda/src/physx/physxSoftBody.cxx
  21. 218 0
      panda/src/physx/physxSoftBody.h
  22. 60 0
      panda/src/physx/physxSoftBodyDesc.I
  23. 403 0
      panda/src/physx/physxSoftBodyDesc.cxx
  24. 84 0
      panda/src/physx/physxSoftBodyDesc.h
  25. 59 0
      panda/src/physx/physxSoftBodyMesh.I
  26. 76 0
      panda/src/physx/physxSoftBodyMesh.cxx
  27. 75 0
      panda/src/physx/physxSoftBodyMesh.h
  28. 72 0
      panda/src/physx/physxSoftBodyMeshDesc.I
  29. 96 0
      panda/src/physx/physxSoftBodyMeshDesc.cxx
  30. 57 0
      panda/src/physx/physxSoftBodyMeshDesc.h
  31. 45 0
      panda/src/physx/physxSoftBodyNode.I
  32. 414 0
      panda/src/physx/physxSoftBodyNode.cxx
  33. 99 0
      panda/src/physx/physxSoftBodyNode.h
  34. 1 0
      panda/src/physx/physxVehicle.h
  35. 1 0
      panda/src/physx/physxWheelShape.h
  36. 6 0
      panda/src/physx/physx_composite.cxx
  37. 5 0
      panda/src/physx/physx_includes.h

+ 3 - 3
makepanda/makepanda.py

@@ -707,9 +707,9 @@ def CompileCxx(obj,src,opts):
         cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 "
         
         # Enables Windows 7 mode if SDK is detected.
-        platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v7.0", "InstallationFolder")
-        if platsdk and os.path.isdir(platsdk):
-            cmd += "/DPANDA_WIN7 /DWINVER=0x601 "
+        #platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v7.0", "InstallationFolder")
+        #if platsdk and os.path.isdir(platsdk):
+        #    cmd += "/DPANDA_WIN7 /DWINVER=0x601 "
             
         cmd += "/Fo" + obj + " /nologo /c"
         for x in ipath: cmd += " /I" + x

+ 3 - 1
makepanda/makepandacore.py

@@ -1469,6 +1469,7 @@ def SdkLocateMacOSX(osxtarget=None):
 PHYSXVERSIONINFO=[
     ("PHYSX281","v2.8.1"),
     ("PHYSX283","v2.8.3"),
+    ("PHYSX284","v2.8.4"),
 ]
 
 def SdkLocatePhysX():
@@ -1476,7 +1477,8 @@ def SdkLocatePhysX():
         if (sys.platform == "win32"):
             folders = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Folders"
             for folder in ListRegistryValues(folders):
-                if folder.endswith("NVIDIA PhysX SDK\\%s\\SDKs\\" % key):
+                if folder.endswith("NVIDIA PhysX SDK\\%s\\SDKs\\" % key) or \
+                   folder.endswith("NVIDIA PhysX SDK\\%s_win\\SDKs\\" % key):
                     SDK["PHYSX"] = folder
                     SDK["PHYSXVERSION"] = ver
         elif (sys.platform.startswith("linux")):

+ 18 - 0
panda/src/physx/Sources.pp

@@ -84,6 +84,7 @@
     physxMemoryReadBuffer.h \
     physxMemoryWriteBuffer.h \
     physxMeshPool.I physxMeshPool.h \
+    physxMeshHash.I physxMeshHash.h \
     physxMotorDesc.I physxMotorDesc.h \
     physxObject.I physxObject.h \
     physxObjectCollection.I physxObjectCollection.h \
@@ -110,6 +111,11 @@
     physxSegment.I physxSegment.h \
     physxShape.I physxShape.h \
     physxShapeDesc.I physxShapeDesc.h \
+    physxSoftBody.I physxSoftBody.h \
+    physxSoftBodyDesc.I physxSoftBodyDesc.h \
+    physxSoftMeshBody.I physxSoftMeshBody.h \
+    physxSoftBodyMeshDesc.I physxSoftBodyMeshDesc.h \
+    physxSoftBodyNode.I physxSoftBodyNode.h \
     physxSphere.I physxSphere.h \
     physxSphereForceFieldShape.I physxSphereForceFieldShape.h \
     physxSphereForceFieldShapeDesc.I physxSphereForceFieldShapeDesc.h \
@@ -205,6 +211,7 @@
     physxMemoryReadBuffer.cxx \
     physxMemoryWriteBuffer.cxx \
     physxMeshPool.cxx \
+    physxMeshHash.cxx \
     physxMotorDesc.cxx \
     physxObject.cxx \
     physxObjectCollection.cxx \
@@ -231,6 +238,11 @@
     physxSegment.cxx \
     physxShape.cxx \
     physxShapeDesc.cxx \
+    physxSoftBody.cxx \
+    physxSoftBodyDesc.cxx \
+    physxSoftMeshBody.cxx \
+    physxSoftBodyMeshDesc.cxx \
+    physxSoftBodyNode.cxx \
     physxSphere.cxx \
     physxSphereForceFieldShape.cxx \
     physxSphereForceFieldShapeDesc.cxx \
@@ -326,6 +338,7 @@
     physxMemoryReadBuffer.h \
     physxMemoryWriteBuffer.h \
     physxMeshPool.I physxMeshPool.h \
+    physxMeshHash.I physxMeshHash.h \
     physxMotorDesc.I physxMotorDesc.h \
     physxObject.I physxObject.h \
     physxObjectCollection.I physxObjectCollection.h \
@@ -352,6 +365,11 @@
     physxSegment.I physxSegment.h \
     physxShape.I physxShape.h \
     physxShapeDesc.I physxShapeDesc.h \
+    physxSoftBody.I physxSoftBody.h \
+    physxSoftBodyDesc.I physxSoftBodyDesc.h \
+    physxSoftMeshBody.I physxSoftMeshBody.h \
+    physxSoftBodyMeshDesc.I physxSoftBodyMeshDesc.h \
+    physxSoftBodyNode.I physxSoftBodyNode.h \
     physxSphere.I physxSphere.h \
     physxSphereForceFieldShape.I physxSphereForceFieldShape.h \
     physxSphereForceFieldShapeDesc.I physxSphereForceFieldShapeDesc.h \

+ 6 - 0
panda/src/physx/config_physx.cxx

@@ -52,6 +52,9 @@
 #include "physxRevoluteJoint.h"
 #include "physxScene.h"
 #include "physxShape.h"
+#include "physxSoftBody.h"
+#include "physxSoftBodyMesh.h"
+#include "physxSoftBodyNode.h"
 #include "physxSphereForceFieldShape.h"
 #include "physxSphereShape.h"
 #include "physxSphericalJoint.h"
@@ -150,6 +153,9 @@ init_libphysx() {
   PhysxRevoluteJoint::init_type();
   PhysxScene::init_type();
   PhysxShape::init_type();
+  PhysxSoftBody::init_type();
+  PhysxSoftBodyMesh::init_type();
+  PhysxSoftBodyNode::init_type();
   PhysxSphereForceFieldShape::init_type();
   PhysxSphereShape::init_type();
   PhysxSphericalJoint::init_type();

+ 12 - 9
panda/src/physx/physxCloth.cxx

@@ -83,16 +83,19 @@ release() {
 void PhysxCloth::
 update() {
 
-  // Update node mesh data
-  _node->update();
+  if (_node) {
 
-  // Update node bounding volume
-  NxBounds3 bounds;
-  _ptr->getWorldBounds(bounds);
+    // Update node mesh data
+    _node->update();
 
-  BoundingBox bb(PhysxManager::nxVec3_to_point3(bounds.min),
-                 PhysxManager::nxVec3_to_point3(bounds.max));
-  _node->set_bounds(&bb);
+    // Update node bounding volume
+    NxBounds3 bounds;
+    _ptr->getWorldBounds(bounds);
+
+    BoundingBox bb(PhysxManager::nxVec3_to_point3(bounds.min),
+                   PhysxManager::nxVec3_to_point3(bounds.max));
+    _node->set_bounds(&bb);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -200,7 +203,7 @@ void PhysxCloth::
 set_thickness(float thickness) {
 
   nassertv(_error_type == ET_ok);
-  _ptr->setFriction(thickness);
+  _ptr->setThickness(thickness);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 37 - 2
panda/src/physx/physxEnums.h

@@ -107,10 +107,10 @@
 #define NX_FORCE_FIELD_CUSTOM_KERNEL_EPSILON 97
 #define NX_IMPROVED_SPRING_SOLVER 98
 
-#ifdef PHYSX283
+#ifndef PHYSX281
 #define NX_FAST_MASSIVE_BP_VOLUME_DELETION 99
 #define NX_LEGACY_JOINT_DRIVE 100
-#endif /* PHYSX283 */
+#endif /* PHYSX281 */
 
 // PhysxActorFlag
 #define NX_AF_DISABLE_COLLISION 1<<0
@@ -297,6 +297,23 @@
 #define NX_DYNAMIC_SHAPES 1<<1
 #define NX_ALL_SHAPES (1<<0|1<<1)
 
+// PhysxSoftBodyFlag
+#define NX_SBF_STATIC 1<<1
+#define NX_SBF_DISABLE_COLLISION 1<<2
+#define NX_SBF_SELFCOLLISION 1<<3
+#define NX_SBF_VISUALIZATION 1<<4
+#define NX_SBF_GRAVITY 1<<5
+#define NX_SBF_VOLUME_CONSERVATION 1<<6
+#define NX_SBF_DAMPING 1<<7
+#define NX_SBF_COLLISION_TWOWAY 1<<8
+#define NX_SBF_TEARABLE 1<<9
+#define NX_SBF_HARDWARE 1<<10
+#define NX_SBF_COMDAMPING 1<<11
+#define NX_SBF_VALIDBOUNDS 1<<12
+#define NX_SBF_FLUID_COLLISION 1<<13
+#define NX_SBF_DISABLE_DYNAMIC_CCD 1<<14
+#define NX_SBF_ADHERE 1<<15
+
 // PhysxSphericalJointFlag
 #define NX_SJF_TWIST_LIMIT_ENABLED 1<<0
 #define NX_SJF_SWING_LIMIT_ENABLED 1<<1
@@ -634,6 +651,24 @@ PUBLISHED:
     SF_softbody_twoway            = NX_SF_SOFTBODY_TWOWAY
   };
 
+  enum PhysxSoftBodyFlag {
+    SBF_static              = NX_SBF_STATIC,
+    SBF_disable_collision   = NX_SBF_DISABLE_COLLISION,
+    SBF_selfcollision       = NX_SBF_SELFCOLLISION,
+    SBF_visualization       = NX_SBF_VISUALIZATION,
+    SBF_gravity             = NX_SBF_GRAVITY,
+    SBF_volume_conservtion  = NX_SBF_VOLUME_CONSERVATION,
+    SBF_damping             = NX_SBF_DAMPING,
+    SBF_collision_twoway    = NX_SBF_COLLISION_TWOWAY,
+    SBF_tearable            = NX_SBF_TEARABLE,
+    SBF_hardware            = NX_SBF_HARDWARE,
+    SBF_comdamping          = NX_SBF_COMDAMPING,
+    SBF_validbounds         = NX_SBF_VALIDBOUNDS,
+    SBF_fluid_collision     = NX_SBF_FLUID_COLLISION,
+    SBF_disable_dynamic_ccd = NX_SBF_DISABLE_DYNAMIC_CCD,
+    SBF_adhere              = NX_SBF_ADHERE
+  };
+
   enum PhysxShapesType {
     ST_static   = NX_STATIC_SHAPES ,
     ST_dynamic  = NX_DYNAMIC_SHAPES ,

+ 47 - 0
panda/src/physx/physxKitchen.cxx

@@ -22,6 +22,8 @@
 #include "physxMemoryWriteBuffer.h"
 #include "physxClothMesh.h"
 #include "physxClothMeshDesc.h"
+#include "physxSoftBodyMesh.h"
+#include "physxSoftBodyMeshDesc.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxKitchen::set_cooking_params
@@ -101,6 +103,22 @@ cook_cloth_mesh(const PhysxClothMeshDesc &meshDesc, const Filename &filename) {
   return _cooking->NxCookClothMesh(meshDesc.get_desc(), fs);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxKitchen::cook_soft_body_mesh
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PhysxKitchen::
+cook_soft_body_mesh(const PhysxSoftBodyMeshDesc &meshDesc, const Filename &filename) {
+
+  nassertr_always(!filename.empty(), false);
+  nassertr_always(filename.touch(), false);
+  nassertr_always(meshDesc.is_valid(), false);
+
+  PhysxFileStream fs = PhysxFileStream(filename, false);
+  return _cooking->NxCookSoftBodyMesh(meshDesc.get_desc(), fs);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxKitchen::cook_texcoords
 //       Access: Published
@@ -229,3 +247,32 @@ cook_cloth_mesh(const PhysxClothMeshDesc &meshDesc) {
   return mesh;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxKitchen::cook_soft_body_mesh
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PhysxSoftBodyMesh *PhysxKitchen::
+cook_soft_body_mesh(const PhysxSoftBodyMeshDesc &meshDesc) {
+
+  nassertr_always(meshDesc.is_valid(), false);
+
+  PhysxMemoryWriteBuffer wbuffer;
+  bool status = _cooking->NxCookSoftBodyMesh(meshDesc.get_desc(), wbuffer);
+  nassertr(status, NULL);
+
+  NxPhysicsSDK *sdk = NxGetPhysicsSDK();
+  nassertr(sdk, NULL);
+
+  PhysxSoftBodyMesh *mesh = new PhysxSoftBodyMesh();
+  nassertr(mesh, NULL);
+
+  PhysxMemoryReadBuffer rbuffer(wbuffer.data);
+  NxSoftBodyMesh *meshPtr = sdk->createSoftBodyMesh(rbuffer);
+  nassertr(meshPtr, NULL);
+
+  mesh->link(meshPtr);
+
+  return mesh;
+}
+

+ 4 - 0
panda/src/physx/physxKitchen.h

@@ -26,6 +26,8 @@ class PhysxTriangleMesh;
 class PhysxTriangleMeshDesc;
 class PhysxClothMesh;
 class PhysxClothMeshDesc;
+class PhysxSoftBodyMesh;
+class PhysxSoftBodyMeshDesc;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PhysxKitchen
@@ -42,11 +44,13 @@ PUBLISHED:
   bool cook_convex_mesh(const PhysxConvexMeshDesc &meshDesc, const Filename &filename);
   bool cook_triangle_mesh(const PhysxTriangleMeshDesc &meshDesc, const Filename &filename);
   bool cook_cloth_mesh(const PhysxClothMeshDesc &meshDesc, const Filename &filename);
+  bool cook_soft_body_mesh(const PhysxSoftBodyMeshDesc &meshDesc, const Filename &filename);
   bool cook_texcoords(const PhysxClothMeshDesc &meshDesc, const Filename &filename);
 
   PhysxConvexMesh *cook_convex_mesh(const PhysxConvexMeshDesc &meshDesc);
   PhysxTriangleMesh *cook_triangle_mesh(const PhysxTriangleMeshDesc &meshDesc);
   PhysxClothMesh *cook_cloth_mesh(const PhysxClothMeshDesc &meshDesc);
+  PhysxSoftBodyMesh *cook_soft_body_mesh(const PhysxSoftBodyMeshDesc &meshDesc);
 
 private:
   NxCookingInterface *_cooking;

+ 24 - 0
panda/src/physx/physxManager.cxx

@@ -295,6 +295,30 @@ get_cloth_mesh(unsigned int idx) {
   return (PhysxClothMesh *)_cloth_meshes[idx];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxManager::get_num_soft_body_meshes
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxManager::
+get_num_soft_body_meshes() {
+
+  return _sdk->getNbSoftBodyMeshes();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxManager::get_soft_body_mesh
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PhysxSoftBodyMesh *PhysxManager::
+get_soft_body_mesh(unsigned int idx) {
+
+  nassertr_always(idx < _sdk->getNbSoftBodyMeshes(), NULL);
+
+  return (PhysxSoftBodyMesh *)_softbody_meshes[idx];
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxManager::is_hardware_available
 //       Access: Published

+ 10 - 0
panda/src/physx/physxManager.h

@@ -27,6 +27,11 @@ class PhysxScene;
 class PhysxSceneDesc;
 class PhysxHeightField;
 class PhysxHeightFieldDesc;
+class PhysxTriangleMesh;
+class PhysxConvexMesh;
+class PhysxClothMesh;
+class PhysxSoftBodyMesh;
+class PhysxOutputStream;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PhysxManager
@@ -75,6 +80,10 @@ PUBLISHED:
   PhysxClothMesh *get_cloth_mesh(unsigned int idx);
   MAKE_SEQ(get_cloth_meshes, get_num_cloth_meshes, get_cloth_mesh);
 
+  unsigned int get_num_soft_body_meshes();
+  PhysxSoftBodyMesh *get_soft_body_mesh(unsigned int idx);
+  MAKE_SEQ(get_soft_body_meshes, get_num_soft_body_meshes, get_soft_body_mesh);
+
   INLINE void ls() const;
   INLINE void ls(ostream &out, int indent_level=0) const;
 
@@ -86,6 +95,7 @@ public:
   PhysxObjectCollection<PhysxConvexMesh> _convex_meshes;
   PhysxObjectCollection<PhysxTriangleMesh> _triangle_meshes;
   PhysxObjectCollection<PhysxClothMesh> _cloth_meshes;
+  PhysxObjectCollection<PhysxSoftBodyMesh> _softbody_meshes;
 
   INLINE static NxVec3 vec3_to_nxVec3(const LVector3f &v);
   INLINE static LVector3f nxVec3_to_vec3(const NxVec3 &v);

+ 84 - 0
panda/src/physx/physxMeshHash.I

@@ -0,0 +1,84 @@
+// Filename: physMeshHash.I
+// Created by: enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: PhysxMeshHash::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxMeshHash::
+PhysxMeshHash() {
+
+  _time = 1;
+  MeshHashRoot *r = _hashIndex;
+
+  for (int i=0; i < _hashIndexSize; i++) {
+    r->first = -1;
+    r->timeStamp = 0;
+    r++;
+  }
+
+  _spacing = 0.25f;
+  _invSpacing = 1.0f / _spacing;
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxMeshHash::
+~PhysxMeshHash() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::hash_function
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int PhysxMeshHash::
+hash_function(int xi, int yi, int zi) const {
+
+  unsigned int h = (xi * 92837111)^(yi * 689287499)^(zi * 283923481);
+  return h % _hashIndexSize;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::cell_coord_of
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void PhysxMeshHash::
+cell_coord_of(const NxVec3 &v, int &xi, int &yi, int &zi) const {
+
+  xi = (int)(v.x * _invSpacing); if (v.x < 0.0f) xi--;
+  yi = (int)(v.y * _invSpacing); if (v.y < 0.0f) yi--;
+  zi = (int)(v.z * _invSpacing); if (v.z < 0.0f) zi--;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::get_grid_spacing
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE NxF32 PhysxMeshHash::
+get_grid_spacing() const {
+
+  return 1.0f / _invSpacing;
+}
+
+

+ 263 - 0
panda/src/physx/physxMeshHash.cxx

@@ -0,0 +1,263 @@
+// Filename: physxMeshHash.cxx
+// Created by: enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "physxMeshHash.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::quick_sort
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+quick_sort(pvector<int> &itemIndices, int l, int r) {
+
+  int i, j, mi;
+  int k, m;
+
+  i = l; j = r; mi = (l + r)/2;
+  m = itemIndices[mi];
+
+  while (i <= j) {
+    while(itemIndices[i] < m) i++;
+    while(m < itemIndices[j]) j--;
+
+    if (i <= j) {
+      k = itemIndices[i]; itemIndices[i] = itemIndices[j]; itemIndices[j] = k;
+      i++; j--;
+    }
+  }
+
+  if (l < j) quick_sort(itemIndices, l, j);
+  if (i < r) quick_sort(itemIndices, i, r);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::compress_indices
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+compress_indices(pvector<int> &itemIndices) {
+
+  if (itemIndices.size() == 0) return;
+
+  // Sort results
+  quick_sort(itemIndices, 0, itemIndices.size() - 1);
+
+  // Mark duplicates
+  int i = 0;
+  while (i < (int)itemIndices.size()) {
+    int j = i+1;
+    while (j < (int)itemIndices.size() && itemIndices[i] == itemIndices[j]) {
+      itemIndices[j] = -1; j++;
+    }
+    i = j;
+  }
+
+  // Remove duplicates
+  i = 0;
+  while (i < (int)itemIndices.size()) {
+    if (itemIndices[i] < 0) {
+      itemIndices[i] = itemIndices[itemIndices.size()-1];
+      itemIndices.pop_back();
+    }
+    else i++;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::set_grid_spacing
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+set_grid_spacing(float spacing) {
+
+  _spacing = spacing;
+  _invSpacing = 1.0f / spacing;
+
+  reset();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::reset
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+reset() {
+
+  _time++;
+  _entries.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::add
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+add(const NxBounds3 &bounds, int itemIndex) {
+
+  int x1,y1,z1;
+  int x2,y2,z2;
+  int x,y,z;
+
+  cell_coord_of(bounds.min, x1, y1, z1);
+  cell_coord_of(bounds.max, x2, y2, z2);
+
+  MeshHashEntry entry;
+  entry.itemIndex = itemIndex;
+
+  for (x = x1; x <= x2; x++) {
+    for (y = y1; y <= y2; y++) {
+      for (z = z1; z <= z2; z++) {
+
+        int h = hash_function(x, y, z);
+        MeshHashRoot &r = _hashIndex[h];
+        int n = _entries.size();
+
+        if (r.timeStamp != _time || r.first < 0)
+          entry.next = -1;
+        else 
+          entry.next = r.first;
+
+        r.first = n;
+        r.timeStamp = _time;
+
+        _entries.push_back(entry);
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::add
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+add(const NxVec3 &pos, int itemIndex) {
+
+  int x, y, z;
+
+  cell_coord_of(pos, x, y, z);
+
+  MeshHashEntry entry;
+  entry.itemIndex = itemIndex;
+
+  int h = hash_function(x, y, z);
+  MeshHashRoot &r = _hashIndex[h];
+  int n = _entries.size();
+
+  if (r.timeStamp != _time || r.first < 0) 
+    entry.next = -1;
+  else 
+    entry.next = r.first;
+
+  r.first = n;
+  r.timeStamp = _time;
+
+  _entries.push_back(entry);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::query
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+query(const NxBounds3 &bounds, pvector<int> &itemIndices, int maxIndices) {
+
+  int x1, y1, z1;
+  int x2, y2, z2;
+  int x, y, z;
+
+  cell_coord_of(bounds.min, x1, y1, z1);
+  cell_coord_of(bounds.max, x2, y2, z2);
+
+  itemIndices.clear();
+
+  for (x=x1; x<=x2; x++) {
+    for (y=y1; y<=y2; y++) {
+      for (z=z1; z<=z2; z++) {
+
+        int h = hash_function(x, y, z);
+
+        MeshHashRoot &r = _hashIndex[h];
+        if (r.timeStamp != _time) continue;
+        int i = r.first;
+
+        while (i >= 0) {
+          MeshHashEntry &entry = _entries[i];
+          itemIndices.push_back(entry.itemIndex);
+          if (maxIndices >= 0 && (int)itemIndices.size() >= maxIndices) return;
+          i = entry.next;
+        }
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::query_unique
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+query_unique(const NxBounds3 &bounds, pvector<int> &itemIndices, int maxIndices) {
+
+  query(bounds, itemIndices, maxIndices);
+  compress_indices(itemIndices);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::query
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+query(const NxVec3 &pos, pvector<int> &itemIndices, int maxIndices) {
+
+  int x, y, z;
+
+  cell_coord_of(pos, x, y, z);
+
+  itemIndices.clear();
+
+  int h = hash_function(x, y, z);
+  MeshHashRoot &r = _hashIndex[h];
+  if (r.timeStamp != _time) return;
+  int i = r.first;
+
+  while (i >= 0) {
+    MeshHashEntry &entry = _entries[i];
+    itemIndices.push_back(entry.itemIndex);
+    if (maxIndices >= 0 && (int)itemIndices.size() >= maxIndices) return;
+    i = entry.next;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshHash::query_unique
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxMeshHash::
+query_unique(const NxVec3 &pos, pvector<int> &itemIndices, int maxIndices) {
+
+  query(pos, itemIndices, maxIndices);
+  compress_indices(itemIndices);
+}
+

+ 78 - 0
panda/src/physx/physxMeshHash.h

@@ -0,0 +1,78 @@
+// Filename: physMeshHash.h
+// Created by: enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PHYSXMESHHASH_H
+#define PHYSXMESHHASH_H
+
+#include "config_physx.h"
+
+#include "pvector.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PhysxMeshHash
+// Description : Utility class used in building links between a
+//               tetrahedron mesh (soft body) and a triangle mesh
+//               used for rendering the soft body.
+////////////////////////////////////////////////////////////////////
+class PhysxMeshHash {
+
+public:
+  PhysxMeshHash();
+  ~PhysxMeshHash();
+
+  void reset();
+
+  void set_grid_spacing(float spacing);
+  INLINE NxF32 get_grid_spacing() const;
+
+  void add(const NxBounds3 &bounds, int itemIndex);
+  void add(const NxVec3 &pos, int itemIndex);
+
+  void query(const NxBounds3 &bounds, pvector<int> &itemIndices, int maxIndices=-1);
+  void query_unique(const NxBounds3 &bounds, pvector<int> &itemIndices, int maxIndices=-1);
+
+  void query(const NxVec3 &pos, pvector<int> &itemIndices, int maxIndices=-1);
+  void query_unique(const NxVec3 &pos, pvector<int> &itemIndices, int maxIndices=-1);
+
+private:
+  struct MeshHashRoot {
+    int first;
+    int timeStamp;
+  };
+
+  struct MeshHashEntry {
+    int itemIndex;
+    int next;
+  };
+
+  NxI32 _time;
+  NxF32 _spacing;
+  NxF32 _invSpacing;
+
+  static const int _hashIndexSize = 17011;
+  MeshHashRoot _hashIndex[_hashIndexSize];
+
+  pvector<MeshHashEntry> _entries;
+
+  INLINE int hash_function(int xi, int yi, int zi) const;
+  INLINE void cell_coord_of(const NxVec3 &v, int &xi, int &yi, int &zi) const;
+
+  void compress_indices(pvector<int> &itemIndices);
+  void quick_sort(pvector<int> &itemIndices, int l, int r);
+
+};
+
+#include "physxMeshHash.I"
+
+#endif // PHYSXMESHHASH_H

+ 76 - 1
panda/src/physx/physxMeshPool.cxx

@@ -16,6 +16,7 @@
 #include "physxConvexMesh.h"
 #include "physxTriangleMesh.h"
 #include "physxClothMesh.h"
+#include "physxSoftBodyMesh.h"
 
 #include "physxFileStream.h"
 #include "virtualFileSystem.h"
@@ -23,7 +24,7 @@
 PhysxMeshPool::ConvexMeshes PhysxMeshPool::_convex_meshes;
 PhysxMeshPool::TriangleMeshes PhysxMeshPool::_triangle_meshes;
 PhysxMeshPool::ClothMeshes PhysxMeshPool::_cloth_meshes;
-//PhysxMeshPool::SoftbodyMeshes PhysxMeshPool::_softbody_meshes;
+PhysxMeshPool::SoftbodyMeshes PhysxMeshPool::_softbody_meshes;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxMeshPool::check_file
@@ -163,6 +164,45 @@ load_cloth_mesh(const Filename &fn) {
   return mesh;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshPool::load_soft_body_mesh
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+PhysxSoftBodyMesh *PhysxMeshPool::
+load_soft_body_mesh(const Filename &fn) {
+
+  if (!check_filename(fn)) return NULL;
+
+  PhysxSoftBodyMesh *mesh;
+
+  SoftbodyMeshes::iterator it = _softbody_meshes.find(fn);
+  if (it == _softbody_meshes.end()) {
+    // Not found; load mesh.
+    NxSoftBodyMesh *meshPtr;
+    PhysxFileStream stream = PhysxFileStream(fn, true);
+
+    mesh = new PhysxSoftBodyMesh();
+    nassertr_always(mesh, NULL);
+
+    NxPhysicsSDK *sdk = NxGetPhysicsSDK();
+    nassertr_always(sdk, NULL);
+
+    meshPtr = sdk->createSoftBodyMesh(stream);
+    nassertr_always(meshPtr, NULL);
+
+    mesh->link(meshPtr);
+
+    _softbody_meshes.insert(SoftbodyMeshes::value_type(fn, mesh));
+  }
+  else {
+    // Found; return previously loaded mesh.
+    mesh = (*it).second;
+  }
+
+  return mesh;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxMeshPool::release_convex_mesh
 //       Access: Published
@@ -220,6 +260,25 @@ release_cloth_mesh(PhysxClothMesh *mesh) {
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxMeshPool::release_soft_body_mesh
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool PhysxMeshPool::
+release_soft_body_mesh(PhysxSoftBodyMesh *mesh) {
+
+  SoftbodyMeshes::iterator it;
+  for (it=_softbody_meshes.begin(); it != _softbody_meshes.end(); ++it) {
+    if (mesh == (*it).second) {
+      _softbody_meshes.erase(it);
+      return true;
+    }
+  }
+
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxMeshPool::list_content
 //       Access: Published
@@ -279,6 +338,19 @@ list_contents(ostream &out) {
     }
   }
 
+  // Soft body meshes
+  {
+    SoftbodyMeshes::const_iterator it;
+    for (it=_softbody_meshes.begin(); it != _softbody_meshes.end(); ++it) {
+      Filename fn = (*it).first;
+      PhysxSoftBodyMesh *mesh = (*it).second;
+
+      out << "  " << fn.get_fullpath()
+          << " (soft body mesh, " << mesh->ptr()->getReferenceCount() 
+          << " references)\n";
+    }
+  }
+
   // Summary
   NxPhysicsSDK *sdk = NxGetPhysicsSDK();
 
@@ -290,5 +362,8 @@ list_contents(ostream &out) {
 
   out << "  Total number of cloth meshes: " << sdk->getNbClothMeshes() 
       << " created, " << _cloth_meshes.size() << " registred\n";
+
+  out << "  Total number of soft body meshes: " << sdk->getNbSoftBodyMeshes() 
+      << " created, " << _softbody_meshes.size() << " registred\n";
 }
 

+ 5 - 4
panda/src/physx/physxMeshPool.h

@@ -26,6 +26,7 @@
 class PhysxConvexMesh;
 class PhysxTriangleMesh;
 class PhysxClothMesh;
+class PhysxSoftBodyMesh;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PhysxMeshPool
@@ -44,12 +45,12 @@ PUBLISHED:
   static PhysxConvexMesh *load_convex_mesh(const Filename &filename);
   static PhysxTriangleMesh *load_triangle_mesh(const Filename &filename);
   static PhysxClothMesh *load_cloth_mesh(const Filename &filename);
-  //static PhysxSoftBodyMesh *load_softbody_mesh(const Filename &filename);
+  static PhysxSoftBodyMesh *load_soft_body_mesh(const Filename &filename);
 
   static bool release_convex_mesh(PhysxConvexMesh *mesh);
   static bool release_triangle_mesh(PhysxTriangleMesh *mesh);
   static bool release_cloth_mesh(PhysxClothMesh *mesh);
-  //static bool release_softbody_mesh(PhysxSoftBodyMesh *mesh);
+  static bool release_soft_body_mesh(PhysxSoftBodyMesh *mesh);
 
   static void list_contents();
   static void list_contents(ostream &out);
@@ -66,8 +67,8 @@ private:
   typedef pmap<Filename, PT(PhysxClothMesh)> ClothMeshes;
   static ClothMeshes _cloth_meshes;
 
-  //typedef pmap<Filename, PT(PhysxSoftBodyMesh)> SoftbodyMeshes;
-  //static SoftbodyMeshes _softbody_meshes;
+  typedef pmap<Filename, PT(PhysxSoftBodyMesh)> SoftbodyMeshes;
+  static SoftbodyMeshes _softbody_meshes;
 };
 
 #include "physxMeshPool.I"

+ 1 - 1
panda/src/physx/physxScene.I

@@ -66,6 +66,6 @@ ls(ostream &out, int indent_level) const {
   _controllers.ls(out, indent_level);
   _vehicles.ls(out, indent_level);
   _cloths.ls(out, indent_level);
-  //_softbodies.ls(out, indent_level);
+  _softbodies.ls(out, indent_level);
 }
 

+ 67 - 10
panda/src/physx/physxScene.cxx

@@ -24,6 +24,8 @@
 #include "physxVehicleDesc.h"
 #include "physxCloth.h"
 #include "physxClothDesc.h"
+#include "physxSoftBody.h"
+#include "physxSoftBodyDesc.h"
 
 TypeHandle PhysxScene::_type_handle;
 
@@ -32,7 +34,7 @@ PStatCollector PhysxScene::_pcollector_update_transforms("App:PhysX:Update Trans
 PStatCollector PhysxScene::_pcollector_debug_renderer("App:PhysX:Debug Renderer");
 PStatCollector PhysxScene::_pcollector_simulate("App:PhysX:Simulate");
 PStatCollector PhysxScene::_pcollector_cloth("App:PhysX:Cloth");
-//PStatCollector PhysxScene::_pcollector_softbody("App:PhysX:Softbody");
+PStatCollector PhysxScene::_pcollector_softbody("App:PhysX:Softbody");
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxScene::link
@@ -137,15 +139,13 @@ unlink() {
   }
 
   // Unlink softbodies
-/*
-  NxSoftBody **sbs = _ptr->getSoftBodies();
-  NxU32 nSbs = _ptr->getNbSoftBodies();
+  NxSoftBody **softbodies = _ptr->getSoftBodies();
+  NxU32 nSoftbodies = _ptr->getNbSoftBodies();
 
-  for (NxU32 i=0; i < nSbs; i++) {
-    PhysxSoftBody *sb = (PhysxSoftBody *)sb[i]->userData;
-    sb->unlink();
+  for (NxU32 i=0; i < nSoftbodies; i++) {
+    PhysxSoftBody *softbody = (PhysxSoftBody *)softbodies[i]->userData;
+    softbody->unlink();
   }
-*/
 
   // Unlink materials
   NxMaterial *materials[5];
@@ -241,6 +241,12 @@ simulate(float dt) {
 void PhysxScene::
 fetch_results() {
 
+#ifdef NX64
+  cout << "<64bit>";
+#else
+  cout << "<32bit>";
+#endif
+
   nassertv(_error_type == ET_ok);
   nassertv(_ptr != NULL);
 
@@ -288,15 +294,15 @@ fetch_results() {
   _pcollector_cloth.stop();
 
   // Update softbody nodes
-/*
   _pcollector_softbody.start();
+
   NxSoftBody **softbodies = _ptr->getSoftBodies();
   for (NxU32 i=0; i < _ptr->getNbSoftBodies(); i++) {
     PT(PhysxSoftBody) softbody = (PhysxSoftBody *)softbodies[i]->userData;
     softbody->update();
   }
+
   _pcollector_softbody.stop();
-*/
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -951,6 +957,57 @@ get_cloth(unsigned int idx) const {
   return (PhysxCloth *)(clothPtr->userData);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxScene::get_num_soft_bodies
+//       Access: Published
+//  Description: Gets the number of soft bodies in the scene.
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxScene::
+get_num_soft_bodies() const {
+
+  nassertr(_error_type == ET_ok, -1);
+  return _ptr->getNbSoftBodies();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxScene::create_soft_body
+//       Access: Published
+//  Description: Creates a soft body in this scene.
+////////////////////////////////////////////////////////////////////
+PhysxSoftBody *PhysxScene::
+create_soft_body(PhysxSoftBodyDesc &desc) {
+
+  nassertr(_error_type == ET_ok, NULL);
+
+  PhysxSoftBody *softbody = new PhysxSoftBody();
+  nassertr(softbody, NULL);
+
+  NxSoftBody *softbodyPtr = _ptr->createSoftBody(desc._desc);
+  nassertr(softbodyPtr, NULL);
+
+  softbody->link(softbodyPtr);
+
+  return softbody;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxScene::get_soft_body
+//       Access: Published
+//  Description: Returns the n-th soft body from the array of
+//               all the soft bodies in the scene.
+////////////////////////////////////////////////////////////////////
+PhysxSoftBody *PhysxScene::
+get_soft_body(unsigned int idx) const {
+
+  nassertr(_error_type == ET_ok, NULL);
+  nassertr_always(idx < _ptr->getNbSoftBodies(), NULL);
+
+  NxSoftBody **softbodies = _ptr->getSoftBodies();
+  NxSoftBody *softbodyPtr = softbodies[idx];
+
+  return (PhysxSoftBody *)(softbodyPtr->userData);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PhysxScene::get_num_vehicles
 //       Access: Published

+ 10 - 1
panda/src/physx/physxScene.h

@@ -52,6 +52,8 @@ class PhysxVehicle;
 class PhysxVehicleDesc;
 class PhysxCloth;
 class PhysxClothDesc;
+class PhysxSoftBody;
+class PhysxSoftBodyDesc;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PhysxScene
@@ -139,6 +141,12 @@ PUBLISHED:
   PhysxCloth *get_cloth(unsigned int idx) const;
   MAKE_SEQ(get_cloths, get_num_cloths, get_cloth);
 
+  // Soft bodies
+  unsigned int get_num_soft_bodies() const;
+  PhysxSoftBody *create_soft_body(PhysxSoftBodyDesc &desc);
+  PhysxSoftBody *get_soft_body(unsigned int idx) const;
+  MAKE_SEQ(get_soft_bodies, get_num_soft_bodies, get_soft_body);
+
   // Vehicles
   unsigned int get_num_vehicles() const;
   PhysxVehicle *create_vehicle(PhysxVehicleDesc &desc);
@@ -230,6 +238,7 @@ public:
   PhysxObjectCollection<PhysxController> _controllers;
   PhysxObjectCollection<PhysxVehicle> _vehicles;
   PhysxObjectCollection<PhysxCloth> _cloths;
+  PhysxObjectCollection<PhysxSoftBody> _softbodies;
 
   PhysxMaterial *get_wheel_shape_material();
 
@@ -248,7 +257,7 @@ private:
   static PStatCollector _pcollector_debug_renderer;
   static PStatCollector _pcollector_simulate;
   static PStatCollector _pcollector_cloth;
-  //static PStatCollector _pcollector_softbody;
+  static PStatCollector _pcollector_softbody;
 
 ////////////////////////////////////////////////////////////////////
 public:

+ 66 - 0
panda/src/physx/physxSoftBody.I

@@ -0,0 +1,66 @@
+// Filename: physxSoftBody.I
+// Created by:  enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: PhysxSoftBody::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBody::
+PhysxSoftBody() : PhysxObject() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBody::
+~PhysxSoftBody() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::ls
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void PhysxSoftBody::
+ls() const {
+
+  ls(nout);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::ls
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void PhysxSoftBody::
+ls(ostream &out, int indent_level) const {
+
+  indent(out, indent_level) << get_type().get_name()
+                            << " " << _name
+                            << " (at 0x" << this << ")";
+
+  if (_node) {
+    out << " N:0x" << _node;
+  }
+
+  out << "\n";
+}
+

+ 914 - 0
panda/src/physx/physxSoftBody.cxx

@@ -0,0 +1,914 @@
+// Filename: physxSoftBody.cxx
+// Created by:  enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "physxSoftBody.h"
+#include "physxSoftBodyDesc.h"
+#include "physxSoftBodyNode.h"
+#include "physxScene.h"
+#include "physxGroupsMask.h"
+
+#include "boundingBox.h"
+
+TypeHandle PhysxSoftBody::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::link
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+link(NxSoftBody *softbodyPtr) {
+
+  // Link self
+  _ptr = softbodyPtr;
+  _error_type = ET_ok;
+  _ptr->userData = this;
+
+  set_name(softbodyPtr->getName());
+
+  PhysxScene *scene = (PhysxScene *)_ptr->getScene().userData;
+  scene->_softbodies.add(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::unlink
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+unlink() {
+
+  // Unlink self
+  _ptr->userData = NULL;
+  _error_type = ET_released;
+
+  PhysxScene *scene = (PhysxScene *)_ptr->getScene().userData;
+  scene->_softbodies.remove(this);
+
+  _node = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::release
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+release() {
+
+  nassertv(_error_type == ET_ok);
+
+  unlink();
+  _ptr->getScene().releaseSoftBody(*_ptr);
+  _ptr = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::update
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+update() {
+
+  if (_node) {
+
+    // Update node mesh data
+    _node->update();
+
+    // Update node bounding volume
+    NxBounds3 bounds;
+    _ptr->getWorldBounds(bounds);
+
+    BoundingBox bb(PhysxManager::nxVec3_to_point3(bounds.min),
+                   PhysxManager::nxVec3_to_point3(bounds.max));
+    _node->set_bounds(&bb);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_scene
+//       Access: Published
+//  Description: Returns the scene which this soft body belongs to.
+////////////////////////////////////////////////////////////////////
+PhysxScene *PhysxSoftBody::
+get_scene() const {
+
+  nassertr(_error_type == ET_ok, NULL);
+  return (PhysxScene *)_ptr->getScene().userData;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_soft_body_node
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PhysxSoftBodyNode *PhysxSoftBody::
+get_soft_body_node() const {
+
+  nassertr(_error_type == ET_ok, NULL);
+  return _node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::create_soft_body_node
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PhysxSoftBodyNode *PhysxSoftBody::
+create_soft_body_node(const char *name) {
+
+  nassertr(_error_type == ET_ok, NULL);
+
+  _node = new PhysxSoftBodyNode(name);
+  _node->allocate(this);
+
+  return _node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_name
+//       Access: Published
+//  Description: Sets a name string for the object that can be
+//               retrieved with get_name(). 
+//               This is for debugging and is not used by the
+//               engine.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_name(const char *name) {
+
+  nassertv(_error_type == ET_ok);
+
+  _name = name ? name : "";
+  _ptr->setName(_name.c_str());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_name
+//       Access: Published
+//  Description: Retrieves the name string.
+////////////////////////////////////////////////////////////////////
+const char *PhysxSoftBody::
+get_name() const {
+
+  nassertr(_error_type == ET_ok, "");
+  return _ptr->getName();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_group
+//       Access: Published
+//  Description: Sets which collision group this soft body is part
+//               of. Collision group must be between 0 and 31.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_group(unsigned int group) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(group >= 0 && group < 32);
+  _ptr->setGroup(group);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_group
+//       Access: Published
+//  Description: Retrieves the collision group this soft body is
+//               part of.
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxSoftBody::
+get_group() const {
+
+  nassertr(_error_type == ET_ok, 0);
+  return _ptr->getGroup();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_groups_mask
+//       Access: Published
+//  Description: Sets 128-bit mask used for collision filtering.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_groups_mask(const PhysxGroupsMask &mask) {
+
+  nassertv(_error_type == ET_ok);
+
+  NxGroupsMask _mask = mask.get_mask();
+  _ptr->setGroupsMask(_mask);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_groups_mask
+//       Access: Published
+//  Description: Gets the 128-bit groups mask used for collision
+//               filtering.
+////////////////////////////////////////////////////////////////////
+PhysxGroupsMask PhysxSoftBody::
+get_groups_mask() const {
+
+  PhysxGroupsMask mask;
+
+  nassertr(_error_type == ET_ok, mask);
+
+  NxGroupsMask _mask = _ptr->getGroupsMask();
+  mask.set_mask(_mask);
+
+  return mask;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_num_particles
+//       Access: Published
+//  Description: Gets the number of cloth particles.
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxSoftBody::
+get_num_particles() {
+
+  nassertr(_error_type == ET_ok, 0);
+  return _ptr->getNumberOfParticles();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_particle_radius
+//       Access: Published
+//  Description: Sets the soft body particle radius (must be 
+//               positive).
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_particle_radius(float radius) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->setParticleRadius(radius);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_particle_radius
+//       Access: Published
+//  Description: Gets the soft body particle radius.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_particle_radius() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return _ptr->getParticleRadius();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_flag
+//       Access: Published
+//  Description: Sets the value of a single flag.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_flag(PhysxSoftBodyFlag flag, bool value) {
+
+  nassertv(_error_type == ET_ok);
+
+  NxU32 flags = _ptr->getFlags();
+
+  if (value == true) {
+    flags |= flag;
+  } 
+  else {
+    flags &= ~(flag);
+  }
+
+  _ptr->setFlags(flags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_flag
+//       Access: Published
+//  Description: Retrieves the value of a single flag.
+////////////////////////////////////////////////////////////////////
+bool PhysxSoftBody::
+get_flag(PhysxSoftBodyFlag flag) const {
+
+  nassertr(_error_type == ET_ok, false);
+
+  return (_ptr->getFlags() & flag) ? true : false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_density
+//       Access: Published
+//  Description: Gets the soft body density.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_density() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return _ptr->getDensity();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_relative_grid_spacing
+//       Access: Published
+//  Description: Gets the relative grid spacing for the broad
+//               phase. The cloth is represented by a set of
+//               world aligned cubical cells in broad phase. The
+//               size of these cells is determined by multiplying
+//               the length of the diagonal of the AABB of the
+//               initial soft body size with this constant.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_relative_grid_spacing() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return _ptr->getRelativeGridSpacing();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_volume_stiffness
+//       Access: Published
+//  Description: Sets the soft body volume stiffness in the range
+//               from 0 to 1.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_volume_stiffness(float stiffness) {
+
+  nassertv(_error_type == ET_ok);
+  ptr()->setVolumeStiffness(stiffness);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_volume_stiffness
+//       Access: Published
+//  Description: Retrieves the soft body volume stiffness.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_volume_stiffness() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getVolumeStiffness();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_stretching_stiffness
+//       Access: Published
+//  Description: Sets the soft body stretching stiffness in the
+//               range from 0 to 1.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_stretching_stiffness(float stiffness) {
+
+  nassertv(_error_type == ET_ok);
+  ptr()->setStretchingStiffness(stiffness);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_stretching_stiffness
+//       Access: Published
+//  Description: Retrieves the soft body stretching stiffness.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_stretching_stiffness() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getStretchingStiffness();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_damping_coefficient
+//       Access: Published
+//  Description: Sets the damping coefficient in the range from 0
+//               to 1.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_damping_coefficient(float coef) {
+
+  nassertv(_error_type == ET_ok);
+  ptr()->setDampingCoefficient(coef);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_damping_coefficient
+//       Access: Published
+//  Description: Retrieves the damping coefficient.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_damping_coefficient() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getDampingCoefficient();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_friction
+//       Access: Published
+//  Description: Sets the soft body friction coefficient in the
+//               range from 0 to 1.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_friction(float friction) {
+
+  nassertv(_error_type == ET_ok);
+  ptr()->setFriction(friction);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_friction
+//       Access: Published
+//  Description: Retrieves the soft body friction coefficient.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_friction() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getFriction();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_tear_factor
+//       Access: Published
+//  Description: Sets the soft body tear factor (must be larger
+//               than one).
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_tear_factor(float factor) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(factor > 1.0f);
+  ptr()->setTearFactor(factor);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_tear_factor
+//       Access: Published
+//  Description: Retrieves the soft body tear factor.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_tear_factor() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getTearFactor();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_attachment_tear_factor
+//       Access: Published
+//  Description: Sets the soft body attachment tear factor (must be
+//               larger than one).
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_attachment_tear_factor(float factor) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(factor > 1.0f);
+  ptr()->setAttachmentTearFactor(factor);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_attachment_tear_factor
+//       Access: Published
+//  Description: Retrieves the attachment soft body tear factor.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_attachment_tear_factor() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getAttachmentTearFactor();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_solver_iterations
+//       Access: Published
+//  Description: Sets the soft body solver iterations.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_solver_iterations(unsigned int iterations) {
+
+  nassertv(_error_type == ET_ok);
+  ptr()->setSolverIterations(iterations);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_solver_iterations
+//       Access: Published
+//  Description: Retrieves the soft body solver iterations.
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxSoftBody::
+get_solver_iterations() const {
+
+  nassertr(_error_type == ET_ok, 0);
+  return ptr()->getSolverIterations();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::is_sleeping
+//       Access: Published
+//  Description: Returns true if this soft body is sleeping. 
+//
+//               When a soft body does not move for a period of
+//               time, it is no longer simulated in order to save
+//               time. This state is called sleeping. However,
+//               because the object automatically wakes up when it
+//               is either touched by an awake object, or one of its
+//               properties is changed by the user, the entire sleep
+//               mechanism should be transparent to the user.
+////////////////////////////////////////////////////////////////////
+bool PhysxSoftBody::
+is_sleeping() const {
+
+  nassertr(_error_type == ET_ok, false);
+  return _ptr->isSleeping();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::wake_up
+//       Access: Published
+//  Description: Wakes up the soft body if it is sleeping. 
+//
+//               The wakeCounterValue determines how long until the
+//               body is put to sleep, a value of zero means that
+//               the body is sleeping. wake_up(0) is equivalent to
+//               PhysxSoftBody::put_to_sleep().
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+wake_up(float wakeCounterValue) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->wakeUp(wakeCounterValue);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::put_to_sleep
+//       Access: Published
+//  Description: Forces the soft body to sleep. 
+//
+//               The soft body  will stay asleep until the next
+//               call to simulate, and will not wake up until then
+//               even when otherwise it would (for example a force
+//               is applied to it). It can however wake up during
+//               the next do_physics call.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+put_to_sleep() {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->putToSleep();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_sleep_linear_velocity
+//       Access: Published
+//  Description: Sets the linear velocity below which an soft body
+//               may go to sleep. SoftBodys whose linear velocity is
+//               above this threshold will not be put to sleep.
+//
+//               Setting the sleep angular/linear velocity only
+//               makes sense when the BF_energy_sleep_test is not
+//               set.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_sleep_linear_velocity(float threshold) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->setSleepLinearVelocity(threshold);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_sleep_linear_velocity
+//       Access: Published
+//  Description: Returns the linear velocity below which an soft
+//               body may go to sleep. Soft bodies whose linear
+//               velocity is above this threshold will not be put
+//               to sleep.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_sleep_linear_velocity() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return _ptr->getSleepLinearVelocity();
+}
+
+#ifndef PHYSX281
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_self_collision_thickness
+//       Access: Published
+//  Description: Sets the soft body self collision thickness (must
+//               be positive).
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_self_collision_thickness(float thickness) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->setSelfCollisionThickness(thickness);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_self_collision_thickness
+//       Access: Published
+//  Description: Gets the soft body self collision thickness.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_self_collision_thickness() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return _ptr->getSelfCollisionThickness();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_hard_stretch_limitation_factor
+//       Access: Published
+//  Description: Sets the soft body hard stretch elongation limit.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_hard_stretch_limitation_factor(float factor) {
+
+  nassertv(_error_type == ET_ok);
+  ptr()->setHardStretchLimitationFactor(factor);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_hard_stretch_limitation_factor
+//       Access: Published
+//  Description: Retrieves the soft body hard stretch elongation
+//               limit.
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBody::
+get_hard_stretch_limitation_factor() const {
+
+  nassertr(_error_type == ET_ok, 0.0f);
+  return ptr()->getHardStretchLimitationFactor();
+}
+#endif // PHYSX281
+
+
+
+
+
+
+
+
+/*
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::attach_vertex_to_global_pos
+//       Access: Published
+//  Description: Attaches a cloth vertex to a position in world
+//               space.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+attach_vertex_to_global_pos(unsigned int vertexId, LPoint3f const &pos) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(!pos.is_nan());
+
+  _ptr->attachVertexToGlobalPosition(vertexId, PhysxManager::point3_to_nxVec3(pos));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::attach_to_shape
+//       Access: Published
+//  Description: Attaches the cloth to a shape. All cloth points
+//               currently inside the shape are attached.
+//
+//               This method only works with primitive and convex
+//               shapes. Since the inside of a general triangle mesh
+//               is not clearly defined.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+attach_to_shape(PhysxShape *shape) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(shape);
+
+  NxU32 attachmentFlags = 0; // --TODO--
+  _ptr->attachToShape(shape->ptr(), attachmentFlags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::attach_to_colliding_shapes
+//       Access: Published
+//  Description: Attaches the cloth to all shapes, currently
+//               colliding. 
+//
+//               This method only works with primitive and convex
+//               shapes. Since the inside of a general triangle mesh
+//               is not clearly defined.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+attach_to_colliding_shapes() {
+
+  nassertv(_error_type == ET_ok);
+
+  NxU32 attachmentFlags = 0; // --TODO--
+  _ptr->attachToCollidingShapes(attachmentFlags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::detach_from_shape
+//       Access: Published
+//  Description: Detaches the cloth from a shape it has been
+//               attached to before. 
+//
+//               If the cloth has not been attached to the shape
+//               before, the call has no effect.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+detach_from_shape(PhysxShape *shape) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(shape);
+
+  _ptr->detachFromShape(shape->ptr());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::free_vertex
+//       Access: Published
+//  Description: Frees a previously attached cloth point.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+free_vertex(unsigned int vertexId) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->freeVertex(vertexId);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::attach_vertex_to_shape
+//       Access: Published
+//  Description: Attaches a cloth vertex to a local position within
+//               a shape.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+attach_vertex_to_shape(unsigned int vertexId, PhysxShape *shape, LPoint3f const &localPos) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv(!localPos.is_nan());
+  nassertv(shape);
+
+  NxU32 attachmentFlags = 0; // --TODO--
+  _ptr->attachVertexToShape(vertexId, shape->ptr(),
+                            PhysxManager::point3_to_nxVec3(localPos),
+                            attachmentFlags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_vertex_attachment_status
+//       Access: Published
+//  Description: Return the attachment status of the given vertex.
+////////////////////////////////////////////////////////////////////
+PhysxEnums::PhysxVertexAttachmentStatus PhysxSoftBody::
+get_vertex_attachment_status(unsigned int vertexId) const {
+
+  nassertr(_error_type == ET_ok, VAS_none);
+  // --TODO-- nassertr(vertexId < _ptr->getNumberOfParticles(), VAS_none);
+
+  return (PhysxVertexAttachmentStatus) _ptr->getVertexAttachmentStatus(vertexId);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_vertex_attachment_shape
+//       Access: Published
+//  Description: Returns the pointer to an attached shape pointer
+//               of the given vertex. If the vertex is not attached
+//               or attached to a global position, NULL is returned.
+////////////////////////////////////////////////////////////////////
+PhysxShape *PhysxSoftBody::
+get_vertex_attachment_shape(unsigned int vertexId) const {
+
+  nassertr(_error_type == ET_ok, NULL);
+  // --TODO-- nassertr(vertexId < _ptr->getNumberOfParticles(), NULL);
+
+  NxShape *shapePtr = _ptr->getVertexAttachmentShape(vertexId);
+  PhysxShape *shape = shapePtr ? (PhysxShape *)(shapePtr->userData) : NULL;
+
+  return shape;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_vertex_attachment_pos
+//       Access: Published
+//  Description: Returns the attachment position of the given
+//               vertex. If the vertex is attached to shape, the
+//               position local to the shape's pose is returned. If
+//               the vertex is not attached, the return value is
+//               undefined.
+////////////////////////////////////////////////////////////////////
+LPoint3f PhysxSoftBody::
+get_vertex_attachment_pos(unsigned int vertexId) const {
+
+  nassertr(_error_type == ET_ok, LPoint3f::zero());
+  // --TODO-- nassertr(vertexId < _ptr->getNumberOfParticles(), LPoint3f::zero());
+
+  return PhysxManager::nxVec3_to_point3(_ptr->getVertexAttachmentPosition(vertexId));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_external_acceleration
+//       Access: Published
+//  Description: Sets an external acceleration which affects all non
+//               attached particles of the cloth.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_external_acceleration(LVector3f const &acceleration) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv_always(!acceleration.is_nan());
+
+  _ptr->setExternalAcceleration(PhysxManager::vec3_to_nxVec3(acceleration));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::set_wind_acceleration
+//       Access: Published
+//  Description: Sets an acceleration acting normal to the cloth
+//               surface at each vertex.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+set_wind_acceleration(LVector3f const &acceleration) {
+
+  nassertv(_error_type == ET_ok);
+  nassertv_always(!acceleration.is_nan());
+
+  _ptr->setWindAcceleration(PhysxManager::vec3_to_nxVec3(acceleration));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_external_acceleration
+//       Access: Published
+//  Description: Retrieves the external acceleration which affects
+//               all non attached particles of the cloth.
+////////////////////////////////////////////////////////////////////
+LVector3f PhysxSoftBody::
+get_external_acceleration() const {
+
+  nassertr(_error_type == ET_ok, LVector3f::zero());
+  return PhysxManager::nxVec3_to_vec3(_ptr->getExternalAcceleration());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::get_wind_acceleration
+//       Access: Published
+//  Description: Retrieves the acceleration acting normal to the
+//               cloth surface at each vertex
+////////////////////////////////////////////////////////////////////
+LVector3f PhysxSoftBody::
+get_wind_acceleration() const {
+
+  nassertr(_error_type == ET_ok, LVector3f::zero());
+  return PhysxManager::nxVec3_to_vec3(_ptr->getWindAcceleration());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::add_force_at_vertex
+//       Access: Published
+//  Description: Applies a force (or impulse) defined in the 
+//               global coordinate frame, to a particular vertex
+//               of the cloth.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+add_force_at_vertex(LVector3f const &force, int vertexId, PhysxForceMode mode) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->addForceAtVertex(PhysxManager::vec3_to_nxVec3(force),
+                         vertexId,
+                         (NxForceMode) mode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::add_force_at_pos
+//       Access: Published
+//  Description: Applies a radial force (or impulse) at a
+//               particular position. All vertices within radius
+//               will be affected with a quadratic drop-off. 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+add_force_at_pos(LPoint3f const &pos, float magnitude, float radius, PhysxForceMode mode) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->addForceAtPos(PhysxManager::point3_to_nxVec3(pos),
+                      magnitude,
+                      radius,
+                      (NxForceMode) mode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBody::add_directed_force_at_pos
+//       Access: Published
+//  Description: Applies a directed force (or impulse) at a
+//               particular position. All vertices within radius
+//               will be affected with a quadratic drop-off.  
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBody::
+add_directed_force_at_pos(LPoint3f const &pos, LVector3f const &force, float radius, PhysxForceMode mode) {
+
+  nassertv(_error_type == ET_ok);
+  _ptr->addDirectedForceAtPos(PhysxManager::point3_to_nxVec3(pos),
+                              PhysxManager::vec3_to_nxVec3(force),
+                              radius,
+                              (NxForceMode) mode);
+}
+*/
+

+ 218 - 0
panda/src/physx/physxSoftBody.h

@@ -0,0 +1,218 @@
+// Filename: physxSoftBody.h
+// Created by:  enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PHYSXSOFTBODY_H
+#define PHYSXSOFTBODY_H
+
+#include "pandabase.h"
+#include "lvector3.h"
+#include "lpoint3.h"
+
+#include "physxObject.h"
+#include "physxObjectCollection.h"
+#include "physxEnums.h"
+#include "physx_includes.h"
+
+class PhysxScene;
+class PhysxGroupsMask;
+class PhysxSoftBodyNode;
+
+////////////////////////////////////////////////////////////////////
+//       Class : PhysxSoftBody
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAPHYSX PhysxSoftBody : public PhysxObject, public PhysxEnums {
+
+PUBLISHED:
+  INLINE PhysxSoftBody();
+  INLINE ~PhysxSoftBody();
+
+  PhysxScene *get_scene() const;
+  PhysxSoftBodyNode *get_soft_body_node() const;
+  PhysxSoftBodyNode *create_soft_body_node(const char *name);
+
+  void set_name(const char *name);
+  void set_flag(PhysxSoftBodyFlag flag, bool value);
+  void set_groups_mask(const PhysxGroupsMask &mask);
+  void set_group(unsigned int group);
+  void set_solver_iterations(unsigned int iterations);
+  void set_particle_radius(float radius);
+#ifndef PHYSX281
+  void set_self_collision_thickness(float thickness);
+  void set_hard_stretch_limitation_factor(float factor);
+#endif
+  void set_volume_stiffness(float stiffness);
+  void set_stretching_stiffness(float stiffness);
+  void set_damping_coefficient(float coef);
+  void set_friction(float friction);
+  void set_tear_factor(float factor);
+  void set_attachment_tear_factor(float factor);
+
+  const char *get_name() const;
+  bool get_flag(PhysxSoftBodyFlag flag) const;
+  PhysxGroupsMask get_groups_mask() const;
+  unsigned int get_group() const;
+  unsigned int get_num_particles();
+  unsigned int get_solver_iterations() const;
+  float get_particle_radius() const;
+  float get_density() const;
+  float get_relative_grid_spacing() const;
+#ifndef PHYSX281
+  float get_self_collision_thickness() const;
+  float get_hard_stretch_limitation_factor() const;
+#endif
+  float get_volume_stiffness() const;
+  float get_stretching_stiffness() const;
+  float get_damping_coefficient() const;
+  float get_friction() const;
+  float get_tear_factor() const;
+  float get_attachment_tear_factor() const;
+
+/*
+  // Attachment
+  void attach_vertex_to_global_pos(unsigned int vertexId, LPoint3f const &pos);
+  void free_vertex(unsigned int vertexId);
+  void attach_to_shape(PhysxShape *shape);
+  void attach_to_colliding_shapes();
+  void detach_from_shape(PhysxShape *shape);
+  void attach_vertex_to_shape(unsigned int vertexId, PhysxShape *shape, LPoint3f const &localPos);
+  PhysxVertexAttachmentStatus get_vertex_attachment_status(unsigned int vertexId) const;
+  PhysxShape *get_vertex_attachment_shape(unsigned int vertexId) const;
+  LPoint3f get_vertex_attachment_pos(unsigned int vertexId) const;
+*/
+
+  // Sleeping
+  bool is_sleeping() const;
+  void wake_up(float wakeCounterValue=NX_SLEEP_INTERVAL);
+  void put_to_sleep();
+  void set_sleep_linear_velocity(float threshold);
+  float get_sleep_linear_velocity() const;
+
+/*
+  // Forces
+  void set_external_acceleration(LVector3f const &acceleration);
+  LVector3f get_external_acceleration() const;
+
+  void set_wind_acceleration(LVector3f const &acceleration);
+  LVector3f get_wind_acceleration() const;
+
+  void add_force_at_vertex(LVector3f const &force, int vertexId,
+                           PhysxForceMode mode=FM_force);
+  void add_force_at_pos(LPoint3f const &pos, float magnitude, float radius,
+                        PhysxForceMode mode=FM_force);
+  void add_directed_force_at_pos(LPoint3f const &pos, LVector3f const &force, float radius,
+                                 PhysxForceMode mode=FM_force);
+*/
+
+
+/*
+virtual void  getWorldBounds (NxBounds3 &bounds) const =0 
+virtual void  attachToShape (const NxShape *shape, NxU32 attachmentFlags)=0 
+virtual void  attachToCollidingShapes (NxU32 attachmentFlags)=0 
+virtual void  detachFromShape (const NxShape *shape)=0 
+virtual void  attachVertexToShape (NxU32 vertexId, const NxShape *shape, const NxVec3 &localPos, NxU32 attachmentFlags)=0 
+virtual void  attachVertexToGlobalPosition (const NxU32 vertexId, const NxVec3 &pos)=0 
+virtual void  freeVertex (const NxU32 vertexId)=0 
+virtual bool  tearVertex (const NxU32 vertexId, const NxVec3 &normal)=0 
+virtual bool  raycast (const NxRay &worldRay, NxVec3 &hit, NxU32 &vertexId)=0 
+virtual void  setMeshData (NxMeshData &meshData)=0 
+virtual NxMeshData  getMeshData ()=0 
+virtual void  setSplitPairData (NxSoftBodySplitPairData &splitPairData)=0 
+virtual NxSoftBodySplitPairData  getSplitPairData ()=0 
+virtual void  setValidBounds (const NxBounds3 &validBounds)=0 
+virtual void  getValidBounds (NxBounds3 &validBounds) const =0 
+virtual void  setPosition (const NxVec3 &position, NxU32 vertexId)=0 
+virtual void  setPositions (void *buffer, NxU32 byteStride=sizeof(NxVec3))=0 
+virtual NxVec3  getPosition (NxU32 vertexId) const =0 
+virtual void  getPositions (void *buffer, NxU32 byteStride=sizeof(NxVec3))=0 
+virtual void  setVelocity (const NxVec3 &velocity, NxU32 vertexId)=0 
+virtual void  setVelocities (void *buffer, NxU32 byteStride=sizeof(NxVec3))=0 
+virtual NxVec3  getVelocity (NxU32 vertexId) const =0 
+virtual void  getVelocities (void *buffer, NxU32 byteStride=sizeof(NxVec3))=0 
+virtual void  setConstrainPositions (void *buffer, NxU32 byteStride=sizeof(NxVec3))=0 
+virtual void  setConstrainNormals (void *buffer, NxU32 byteStride=sizeof(NxVec3))=0 
+virtual void  setConstrainCoefficients (const NxSoftBodyConstrainCoefficients *coefficients, NxU32 byteStride=sizeof(NxSoftBodyConstrainCoefficients))=0 
+virtual NxU32  queryShapePointers ()=0 
+virtual NxU32  getStateByteSize ()=0 
+virtual void  getShapePointers (NxShape **shapePointers, NxU32 *flags)=0 
+virtual void  setShapePointers (NxShape **shapePointers, unsigned int numShapes)=0 
+virtual void  saveStateToStream (NxStream &stream, bool permute=false)=0 
+virtual void  loadStateFromStream (NxStream &stream)=0 
+virtual void  setCollisionResponseCoefficient (NxReal coefficient)=0 
+virtual NxReal  getCollisionResponseCoefficient () const =0 
+virtual void  setAttachmentResponseCoefficient (NxReal coefficient)=0 
+virtual NxReal  getAttachmentResponseCoefficient () const =0 
+virtual void  setFromFluidResponseCoefficient (NxReal coefficient)=0 
+virtual NxReal  getFromFluidResponseCoefficient () const =0 
+virtual void  setToFluidResponseCoefficient (NxReal coefficient)=0 
+virtual NxReal  getToFluidResponseCoefficient () const =0 
+virtual void  setExternalAcceleration (NxVec3 acceleration)=0 
+virtual NxVec3  getExternalAcceleration () const =0 
+virtual void  setMinAdhereVelocity (NxReal velocity)=0 
+virtual NxReal  getMinAdhereVelocity () const =0 
+virtual void  addForceAtVertex (const NxVec3 &force, NxU32 vertexId, NxForceMode mode=NX_FORCE)=0 
+virtual void  addForceAtPos (const NxVec3 &position, NxReal magnitude, NxReal radius, NxForceMode mode=NX_FORCE)=0 
+virtual void  addDirectedForceAtPos (const NxVec3 &position, const NxVec3 &force, NxReal radius, NxForceMode mode=NX_FORCE)=0 
+virtual bool  overlapAABBTetrahedra (const NxBounds3 &bounds, NxU32 &nb, const NxU32 *&indices) const =0 
+virtual NxCompartment *  getCompartment () const =0 
+virtual NxForceFieldMaterial  getForceFieldMaterial () const =0 
+virtual void  setForceFieldMaterial (NxForceFieldMaterial)=0 
+*/
+
+  INLINE void ls() const;
+  INLINE void ls(ostream &out, int indent_level=0) const;
+
+public:
+  void update();
+
+////////////////////////////////////////////////////////////////////
+PUBLISHED:
+  void release();
+
+public:
+  INLINE NxSoftBody *ptr() const { return _ptr; };
+
+  void link(NxSoftBody *ptr);
+  void unlink();
+
+private:
+  NxSoftBody *_ptr;
+  PT(PhysxSoftBodyNode) _node;
+  string _name;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PhysxObject::init_type();
+    register_type(_type_handle, "PhysxSoftBody", 
+                  PhysxObject::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 "physxSoftBody.I"
+
+#endif // PHYSXSOFTBODY_H

+ 60 - 0
panda/src/physx/physxSoftBodyDesc.I

@@ -0,0 +1,60 @@
+// Filename: physxSoftBodyDesc.I
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: PhysxSoftBodyDesc::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyDesc::
+PhysxSoftBodyDesc() {
+
+  set_to_default();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyDesc::
+~PhysxSoftBodyDesc() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_to_default
+//       Access: Published
+//  Description: (re)sets the structure to the default.
+////////////////////////////////////////////////////////////////////
+INLINE void PhysxSoftBodyDesc::
+set_to_default() {
+
+  _desc.setToDefault();
+  set_name("");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::is_valid
+//       Access: Published
+//  Description: Returns true if the descriptor is valid.
+////////////////////////////////////////////////////////////////////
+INLINE bool PhysxSoftBodyDesc::
+is_valid() const {
+
+  return _desc.isValid();
+}
+

+ 403 - 0
panda/src/physx/physxSoftBodyDesc.cxx

@@ -0,0 +1,403 @@
+// Filename: physxSoftBodyDesc.cxx
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "physxSoftBodyDesc.h"
+#include "physxSoftBodyMesh.h"
+#include "physxManager.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_name
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_name(const char *name) {
+
+  _name = name ? name : "";
+  _desc.name = _name.c_str();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_global_pos
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_global_pos(const LPoint3f &pos) {
+
+  _desc.globalPose.t = PhysxManager::point3_to_nxVec3(pos);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_global_mat
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_global_mat(const LMatrix4f &mat) {
+
+  _desc.globalPose = PhysxManager::mat4_to_nxMat34(mat);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_global_hpr
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_global_hpr(float h, float p, float r) {
+
+  LQuaternionf q;
+  LMatrix3f rot;
+  NxMat34 m;
+
+  q.set_hpr(LVector3f(h, p, r));
+  q.extract_to_matrix(rot);
+
+  _desc.globalPose.M = PhysxManager::mat3_to_nxMat33(rot);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_particle_radius
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_particle_radius(float radius) {
+
+  _desc.particleRadius = radius;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_relative_grid_spacing
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_relative_grid_spacing(float spacing) {
+
+  _desc.relativeGridSpacing = spacing;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_collision_response_coefficient
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_collision_response_coefficient(float coef) {
+
+  _desc.collisionResponseCoefficient = coef;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_attachment_response_coefficient
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_attachment_response_coefficient(float coef) {
+
+  _desc.attachmentResponseCoefficient = coef;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_density
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_density(float density) {
+
+  _desc.density = density;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_volume_stiffness
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_volume_stiffness(float stiffness) {
+
+  _desc.volumeStiffness = stiffness;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_stretching_stiffness
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_stretching_stiffness(float stiffness) {
+
+  _desc.stretchingStiffness = stiffness;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_damping_coefficient
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_damping_coefficient(float damping) {
+
+  _desc.dampingCoefficient = damping;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_friction
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_friction(float friction) {
+
+  _desc.friction = friction;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_tear_factor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_tear_factor(float tearFactor) {
+
+  _desc.tearFactor = tearFactor;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_flag
+//       Access: Published
+//  Description: Raise or lower individual SoftBodyFlag flags.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_flag(PhysxSoftBodyFlag flag, bool value) {
+
+  if (value == true) {
+    _desc.flags |= flag;
+  }
+  else {
+    _desc.flags &= ~(flag);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_solver_iterations
+//       Access: Published
+//  Description: Number of solver iterations.
+//               Small numbers make the simulation faster while 
+//               the soft body gets less stiff.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_solver_iterations(unsigned int iterations) {
+
+  _desc.solverIterations = iterations;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::set_soft_body_mesh
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+set_soft_body_mesh(PhysxSoftBodyMesh *mesh) {
+
+  _desc.softBodyMesh = mesh->ptr();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_name
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const char *PhysxSoftBodyDesc::
+get_name() const {
+
+  return _desc.name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_global_pos
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+LPoint3f PhysxSoftBodyDesc::
+get_global_pos() const {
+
+  return PhysxManager::nxVec3_to_point3(_desc.globalPose.t);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_global_mat
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+LMatrix4f PhysxSoftBodyDesc::
+get_global_mat() const {
+
+  return PhysxManager::nxMat34_to_mat4(_desc.globalPose);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_particle_radius
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_particle_radius() const {
+
+  return _desc.particleRadius;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_relative_grid_spacing
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_relative_grid_spacing() const {
+
+  return _desc.relativeGridSpacing;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_collision_response_coefficient
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_collision_response_coefficient() const {
+
+  return _desc.collisionResponseCoefficient;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_attachment_response_coefficient
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_attachment_response_coefficient() const {
+
+  return _desc.attachmentResponseCoefficient;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_density
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_density() const {
+
+  return _desc.density;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_volume_stiffness
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_volume_stiffness() const {
+
+  return _desc.volumeStiffness;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_stretching_stiffness
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_stretching_stiffness() const {
+
+  return _desc.stretchingStiffness;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_damping_coefficient
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_damping_coefficient() const {
+
+  return _desc.dampingCoefficient;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_friction
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_friction() const {
+
+  return _desc.friction;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_tear_factor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float PhysxSoftBodyDesc::
+get_tear_factor() const {
+
+  return _desc.tearFactor;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_flag
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PhysxSoftBodyDesc::
+get_flag(PhysxSoftBodyFlag flag) const {
+
+  return (_desc.flags & flag) ? true : false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_solver_iterations
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxSoftBodyDesc::
+get_solver_iterations() const {
+
+  return _desc.solverIterations;
+}
+
+/*
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyDesc::get_mesh_numbers
+//       Access: Public
+//  Description: Used by PhysScene to query the sizes of arrays
+//               to allocate for the user buffers in PhysxSoftBodyNode.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyDesc::
+get_mesh_numbers(NxU32 &numVertices, NxU32 &numTriangles) {
+
+  NxSoftBodyMeshDesc meshDesc;
+  _desc.clothMesh->saveToDesc(meshDesc);
+
+  numVertices = meshDesc.numVertices;
+  numTriangles = meshDesc.numTriangles;
+}
+*/
+

+ 84 - 0
panda/src/physx/physxSoftBodyDesc.h

@@ -0,0 +1,84 @@
+// Filename: physxSoftBodyDesc.h
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PHYSXSOFTBODYDESC_H
+#define PHYSXSOFTBODYDESC_H
+
+#include "pandabase.h"
+#include "lpoint3.h"
+#include "lmatrix.h"
+
+#include "physxEnums.h"
+#include "physx_includes.h"
+
+class PhysxSoftBodyMesh;
+
+////////////////////////////////////////////////////////////////////
+//       Class : PhysxSoftBodyDesc
+// Description : Descriptor for PhysxSoftBody.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAPHYSX PhysxSoftBodyDesc : public PhysxEnums {
+
+PUBLISHED:
+  INLINE PhysxSoftBodyDesc();
+  INLINE ~PhysxSoftBodyDesc();
+
+  INLINE void set_to_default();
+  INLINE bool is_valid() const;
+
+  void set_soft_body_mesh(PhysxSoftBodyMesh *mesh);
+
+  void set_name(const char *name);
+  void set_global_pos(const LPoint3f &pos);
+  void set_global_mat(const LMatrix4f &mat);
+  void set_global_hpr(float h, float p, float r);
+  void set_density(float density);
+  void set_volume_stiffness(float stiffness);
+  void set_stretching_stiffness(float stiffness);
+  void set_damping_coefficient(float damping);
+  void set_friction(float friction);
+  void set_tear_factor(float tearFactor);
+  void set_particle_radius(float radius);
+  void set_relative_grid_spacing(float spacing);
+  void set_collision_response_coefficient(float coef);
+  void set_attachment_response_coefficient(float coef);
+  void set_solver_iterations(unsigned int interations);
+  void set_flag(PhysxSoftBodyFlag flag, bool value);
+
+  const char *get_name() const;
+  LPoint3f get_global_pos() const;
+  LMatrix4f get_global_mat() const;
+  float get_density() const;
+  float get_volume_stiffness() const;
+  float get_stretching_stiffness() const;
+  float get_damping_coefficient() const;
+  float get_friction() const;
+  float get_tear_factor() const;
+  float get_particle_radius() const;
+  float get_relative_grid_spacing() const;
+  float get_collision_response_coefficient() const;
+  float get_attachment_response_coefficient() const;
+  unsigned int get_solver_iterations() const;
+  bool get_flag(PhysxSoftBodyFlag flag) const;
+
+public:
+  NxSoftBodyDesc _desc;
+
+private:
+  string _name;  
+};
+
+#include "physxSoftBodyDesc.I"
+
+#endif // PHYSXSOFTBODYDESC_H

+ 59 - 0
panda/src/physx/physxSoftBodyMesh.I

@@ -0,0 +1,59 @@
+// Filename: physxSoftBodyMesh.I
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: PhysxSoftBodyMesh::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyMesh::
+PhysxSoftBodyMesh() : PhysxObject() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyMesh::
+~PhysxSoftBodyMesh() {
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::ls
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void PhysxSoftBodyMesh::
+ls() const {
+
+  ls(nout);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::ls
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void PhysxSoftBodyMesh::
+ls(ostream &out, int indent_level) const {
+
+  indent(out, indent_level) << get_type().get_name()
+                            << " (at 0x" << this << ")\n";
+}
+

+ 76 - 0
panda/src/physx/physxSoftBodyMesh.cxx

@@ -0,0 +1,76 @@
+// Filename: physxSoftBodyMesh.cxx
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "physxSoftBodyMesh.h"
+#include "physxMeshPool.h"
+
+TypeHandle PhysxSoftBodyMesh::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::link
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMesh::
+link(NxSoftBodyMesh *meshPtr) {
+
+  // Link self
+  PhysxManager::get_global_ptr()->_softbody_meshes.add(this);
+  _ptr = meshPtr;
+  _error_type = ET_ok;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::unlink
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMesh::
+unlink() {
+
+  // Unlink self
+  _error_type = ET_released;
+  PhysxManager::get_global_ptr()->_softbody_meshes.remove(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::release
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMesh::
+release() {
+
+  nassertv(_error_type == ET_ok);
+
+  unlink();
+  NxGetPhysicsSDK()->releaseSoftBodyMesh(*_ptr);
+  _ptr = NULL;
+
+  PhysxMeshPool::release_soft_body_mesh(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMesh::get_reference_count
+//       Access: Published
+//  Description: Returns the reference count for shared meshes.
+////////////////////////////////////////////////////////////////////
+unsigned int PhysxSoftBodyMesh::
+get_reference_count() const {
+
+  nassertr(_error_type == ET_ok, 0);
+
+  return _ptr->getReferenceCount();
+}
+

+ 75 - 0
panda/src/physx/physxSoftBodyMesh.h

@@ -0,0 +1,75 @@
+// Filename: physxSoftBodyMesh.h
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PHYSXSOFTBODYMESH_H
+#define PHYSXSOFTBODYMESH_H
+
+#include "pandabase.h"
+
+#include "physxObject.h"
+#include "physx_includes.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PhysxSoftBodyMesh
+// Description : 
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAPHYSX PhysxSoftBodyMesh : public PhysxObject {
+
+PUBLISHED:
+  unsigned int get_reference_count() const;
+
+////////////////////////////////////////////////////////////////////
+PUBLISHED:
+  void release();
+
+  INLINE void ls() const;
+  INLINE void ls(ostream &out, int indent_level=0) const;
+
+public:
+  INLINE PhysxSoftBodyMesh();
+  INLINE ~PhysxSoftBodyMesh();
+
+  INLINE NxSoftBodyMesh *ptr() const { return _ptr; };
+
+  void link(NxSoftBodyMesh *meshPtr);
+  void unlink();
+
+private:
+  NxSoftBodyMesh *_ptr;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PhysxObject::init_type();
+    register_type(_type_handle, "PhysxSoftBodyMesh", 
+                  PhysxObject::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 "physxSoftBodyMesh.I"
+
+#endif // PHYSXSOFTBODYMESH_H

+ 72 - 0
panda/src/physx/physxSoftBodyMeshDesc.I

@@ -0,0 +1,72 @@
+// Filename: physxSoftBodyMeshDesc.I
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: PhysxSoftBodyMeshDesc::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyMeshDesc::
+PhysxSoftBodyMeshDesc() {
+
+  _desc.flags = 0;
+  _desc.vertexStrideBytes = sizeof(NxVec3);
+  _desc.tetrahedronStrideBytes = 4*sizeof(NxU32);
+  _desc.vertices = NULL;
+  _desc.tetrahedra = NULL;
+
+  _vertices = NULL;
+  _tetrahedra = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyMeshDesc::
+~PhysxSoftBodyMeshDesc() {
+
+  if (_vertices) {
+    delete [] _vertices;
+  }
+
+  if (_tetrahedra) {
+    delete [] _tetrahedra;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::is_valid
+//       Access: Published
+//  Description: Returns true if the descriptor is valid.
+////////////////////////////////////////////////////////////////////
+INLINE bool PhysxSoftBodyMeshDesc::
+is_valid() const {
+
+  return _desc.isValid();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::get_desc
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const NxSoftBodyMeshDesc &PhysxSoftBodyMeshDesc::
+get_desc() const {
+
+  return _desc;
+}
+

+ 96 - 0
panda/src/physx/physxSoftBodyMeshDesc.cxx

@@ -0,0 +1,96 @@
+// Filename: physxSoftBodyMeshDesc.cxx
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "physxSoftBodyMeshDesc.h"
+#include "physxManager.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::set_num_vertices
+//       Access: Published
+//  Description: Sets the number of vertices to be stored within
+//               this soft body mesh. The function allocates memory
+//               for the vertices, but it does not set any vertices.
+//
+//               This method must be called before any calls to
+//               set_vertex are done!
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMeshDesc::
+set_num_vertices(unsigned int numVertices) {
+
+  // Vertices
+  if (_desc.vertices) {
+    delete [] _vertices;
+  }
+
+  _vertices = new NxVec3[numVertices];
+
+  _desc.numVertices = numVertices;
+  _desc.vertices = _vertices;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::set_vertex
+//       Access: Published
+//  Description: Sets a single vertex. You have to call the function
+//               set_num_vertices before you can call this function.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMeshDesc::
+set_vertex(unsigned int idx, const LPoint3f &vert) {
+
+  nassertv(_desc.numVertices > idx);
+
+  _vertices[idx] = PhysxManager::point3_to_nxVec3(vert);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::set_num_tetrahedra
+//       Access: Published
+//  Description: Sets the number of tetrahedra to be stored in this
+//               soft body mesh.
+//
+//               This method must be called before any calls to
+//               set_tetrahedron are done!
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMeshDesc::
+set_num_tetrahedra(unsigned int numTetrahedra) {
+
+  if (_desc.tetrahedra) {
+    delete [] _tetrahedra;
+  }
+
+  _tetrahedra = new NxU32[4 * numTetrahedra];
+
+  _desc.numTetrahedra = numTetrahedra;
+  _desc.tetrahedra = _tetrahedra;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyMeshDesc::set_tetrahedron
+//       Access: Published
+//  Description: Sets a single tetrahedron, by providing the three
+//               indices i1, i2, i3, i4.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyMeshDesc::
+set_tetrahedron(unsigned int idx,
+                unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4) {
+
+  nassertv(_desc.numTetrahedra > idx);
+
+  idx = 4 * idx;
+  _tetrahedra[idx]     = i1;
+  _tetrahedra[idx + 1] = i2;
+  _tetrahedra[idx + 2] = i3;
+  _tetrahedra[idx + 3] = i4;
+}
+

+ 57 - 0
panda/src/physx/physxSoftBodyMeshDesc.h

@@ -0,0 +1,57 @@
+// Filename: physxSoftBodyMeshDesc.h
+// Created by:  enn0x (12Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PHYSXSOFTBODYMESHDESC_H
+#define PHYSXSOFTBODYMESHDESC_H
+
+#include "pandabase.h"
+#include "lpoint3.h"
+
+#include "physx_includes.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PhysxSoftBodyMeshDesc
+// Description :
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAPHYSX PhysxSoftBodyMeshDesc {
+
+PUBLISHED:
+  INLINE PhysxSoftBodyMeshDesc();
+  INLINE ~PhysxSoftBodyMeshDesc();
+
+  INLINE bool is_valid() const;
+
+  void set_num_vertices(unsigned int n);
+  void set_vertex(unsigned int idx,
+                  const LPoint3f &vert);
+
+  void set_num_tetrahedra(unsigned int n);
+  void set_tetrahedron(unsigned int idx,
+                       unsigned int i1,
+                       unsigned int i2,
+                       unsigned int i3,
+                       unsigned int i4);
+
+public:
+  INLINE const NxSoftBodyMeshDesc &get_desc() const;
+
+private:
+  NxSoftBodyMeshDesc _desc;
+  NxVec3 *_vertices;
+  NxU32 *_tetrahedra;
+};
+
+#include "physxSoftBodyMeshDesc.I"
+
+#endif // PHYSXSOFTBODYMESHDESC_H

+ 45 - 0
panda/src/physx/physxSoftBodyNode.I

@@ -0,0 +1,45 @@
+// Filename: physxSoftBodyNode.I
+// Created by:  enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: PhysxSoftBodyNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyNode::
+PhysxSoftBodyNode(const char *name) : GeomNode(name) {
+
+  _vdata = new GeomVertexData("", GeomVertexFormat::get_v3n3t2(), Geom::UH_stream);
+
+  _prim = new GeomTriangles(Geom::UH_stream);
+  _prim->set_shade_model(Geom::SM_uniform);
+
+  _geom = new Geom(_vdata);
+  _geom->add_primitive(_prim);
+
+  this->add_geom(_geom);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PhysxSoftBodyNode::
+~PhysxSoftBodyNode() {
+
+}
+

+ 414 - 0
panda/src/physx/physxSoftBodyNode.cxx

@@ -0,0 +1,414 @@
+// Filename: physxSoftBodyNode.cxx
+// Created by:  enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "physxSoftBodyNode.h"
+#include "physxSoftBody.h"
+#include "physxFileStream.h"
+#include "physxManager.h"
+#include "physxMeshHash.h"
+
+#include "geomVertexFormat.h"
+#include "geomVertexWriter.h"
+#include "geomVertexRewriter.h"
+
+TypeHandle PhysxSoftBodyNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::allocate
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+allocate(PhysxSoftBody *softbody) {
+
+  _softbody = softbody;
+
+  // Retrieve number of vertices and triangles the hard way
+  NxSoftBodyMeshDesc meshDesc;
+  _softbody->ptr()->getSoftBodyMesh()->saveToDesc(meshDesc);
+
+  NxU32 numVertices = meshDesc.numVertices;
+  NxU32 numTetrahedra = meshDesc.numTetrahedra;
+
+  float factor = 1.0f; // TODO max(1.0f, factor);
+
+  // Reserve more memory for vertices than the initial mesh takes because
+  // tearing creates new vertices
+  NxU32 maxVertices = factor * numVertices;
+  _mesh.verticesPosBegin = (NxVec3 *)malloc(sizeof(NxVec3) * maxVertices);
+  _mesh.verticesPosByteStride = sizeof(NxVec3);
+  _mesh.maxVertices = maxVertices;
+  _mesh.numVerticesPtr = (NxU32 *)malloc(sizeof(NxU32));
+
+  // The number of tetrahedra is constant, even if the softbody is torn
+  NxU32 maxIndices = 4 * numTetrahedra;
+  _mesh.indicesBegin = (NxU32 *)malloc(sizeof(NxU32) * maxIndices);
+  _mesh.indicesByteStride = sizeof(NxU32);
+  _mesh.maxIndices = maxIndices;
+  _mesh.numIndicesPtr = (NxU32 *)malloc(sizeof(NxU32));
+
+  *(_mesh.numVerticesPtr) = 0;
+  *(_mesh.numIndicesPtr) = 0;
+
+  _softbody->ptr()->setMeshData(_mesh);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::set_from_geom
+//       Access: Published
+//  Description: Reads the vertices and indices from an existing
+//               Geom and makes a decomposed copy of the data.
+//               Then computes links between the owning soft body
+//               tetrahedron mesh in order to render an updated
+//               geometry every simulation frame.
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+set_from_geom(const Geom *geom) {
+
+  _prim->clear_vertices();
+
+  GeomVertexWriter vwriter = GeomVertexWriter(_vdata, InternalName::get_vertex());
+  GeomVertexWriter nwriter = GeomVertexWriter(_vdata, InternalName::get_normal());
+  GeomVertexWriter twriter = GeomVertexWriter(_vdata, InternalName::get_texcoord());
+
+  CPT(GeomVertexData) vdata = geom->get_vertex_data();
+  GeomVertexReader vreader = GeomVertexReader(vdata, InternalName::get_vertex());
+  GeomVertexReader nreader = GeomVertexReader(vdata, InternalName::get_normal());
+  GeomVertexReader treader = GeomVertexReader(vdata, InternalName::get_texcoord());
+
+  while (!vreader.is_at_end()) {
+    LVecBase3f v = vreader.get_data3f();
+    vwriter.add_data3f(v.get_x(), v.get_y(), v.get_z());
+  }
+
+  while (!nreader.is_at_end()) {
+    LVecBase3f n = nreader.get_data3f();
+    nwriter.add_data3f(n.get_x(), n.get_y(), n.get_z());
+  }
+
+  while (!treader.is_at_end()) {
+    LVecBase2f t = treader.get_data2f();
+    twriter.add_data2f(t.get_x(), t.get_y());
+  }
+
+  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 l=s; l<e; l++) {
+        _prim->add_vertex(prim->get_vertex(l));
+      }
+    }
+  }
+
+  _prim->close_primitive();
+
+  update_bounds();
+  build_tetra_links();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::build_tetra_links
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+build_tetra_links() {
+
+  NxSoftBodyMeshDesc meshDesc;
+  _softbody->ptr()->getSoftBodyMesh()->saveToDesc(meshDesc);
+  const NxVec3 *vertices = (const NxVec3 *) meshDesc.vertices;
+  const NxU32 *indices = (const NxU32 *) meshDesc.tetrahedra;
+  const NxU32 numTets = meshDesc.numTetrahedra;
+
+  _tetraLinks.clear();
+
+  PhysxMeshHash* hash = new PhysxMeshHash();
+  hash->set_grid_spacing(_bounds.min.distance(_bounds.max) * 0.1f);
+
+  for (NxU32 i=0; i<numTets; i++) {
+    const NxU32 *ix = &indices[4*i];
+    NxBounds3 tetraBounds;
+    tetraBounds.setEmpty();
+    tetraBounds.include(vertices[*ix++]);
+    tetraBounds.include(vertices[*ix++]);
+    tetraBounds.include(vertices[*ix++]);
+    tetraBounds.include(vertices[*ix++]);
+    hash->add(tetraBounds, i);
+  }
+
+  GeomVertexReader vreader = GeomVertexReader(_vdata, InternalName::get_vertex());
+
+  while (!vreader.is_at_end()) {
+
+    // Prepare datastructure for drained tetras
+    _drainedTriVertices.push_back(false);
+
+    TetraLink tmpLink;
+
+    LVecBase3f v = vreader.get_data3f();
+    NxVec3 triVert = PhysxManager::vec3_to_nxVec3(v);
+    pvector<int> itemIndices;
+    hash->query_unique(triVert, itemIndices);
+
+    NxReal minDist = 0.0f;
+    NxVec3 b;
+    int num, isize;
+    num = isize = itemIndices.size();
+    if (num == 0) {
+        num = numTets;
+    }
+
+    for (int i=0; i<num; i++) {
+      int j = i;
+      if (isize > 0) {
+          j = itemIndices[i];
+      }
+
+      const NxU32 *ix = &indices[j*4];
+      const NxVec3 &p0 = vertices[*ix++];
+      const NxVec3 &p1 = vertices[*ix++];
+      const NxVec3 &p2 = vertices[*ix++];
+      const NxVec3 &p3 = vertices[*ix++];
+
+      NxVec3 b = compute_bary_coords(triVert, p0, p1, p2, p3);
+
+      // Is the vertex inside the tetrahedron? If yes we take it
+      if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) {
+        tmpLink.barycentricCoords = b;
+        tmpLink.tetraNr = j;
+        break;
+      }
+
+      // Otherwise, if we are not in any tetrahedron we take the closest one
+      NxReal dist = 0.0f;
+      if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f;
+      if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x;
+      if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y;
+      if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z;
+
+      if (i == 0 || dist < minDist) {
+        minDist = dist;
+        tmpLink.barycentricCoords = b;
+        tmpLink.tetraNr = j;
+      }
+    }
+
+    _tetraLinks.push_back(tmpLink);
+  }
+
+  delete hash;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::remove_tris_related_to_vertex
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+remove_tris_related_to_vertex(const int vertexIndex) {
+
+  GeomVertexRewriter vrewriter = GeomVertexRewriter(_vdata, InternalName::get_vertex());
+  LVecBase3f v;
+
+  for (int j=0; j<_prim->get_num_primitives(); j++) {
+
+    int s = _prim->get_primitive_start(j);
+    int idx0 = _prim->get_vertex(s);
+    int idx1 = _prim->get_vertex(s+1);
+    int idx2 = _prim->get_vertex(s+2);
+
+    if (vertexIndex == idx0 || vertexIndex == idx1 || vertexIndex == idx2) {
+
+      // Make this triangle degenerated
+      vrewriter.set_row(idx0); v = vrewriter.get_data3f();
+      vrewriter.set_row(idx1); vrewriter.set_data3f(v.get_x(), v.get_y(), v.get_z());
+      vrewriter.set_row(idx2); vrewriter.set_data3f(v.get_x(), v.get_y(), v.get_z());
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::update_bounds
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+update_bounds() {
+
+  _bounds.setEmpty();
+
+  GeomVertexReader vreader = GeomVertexReader(_vdata, InternalName::get_vertex());
+
+  while (!vreader.is_at_end()) {
+    LVecBase3f v = vreader.get_data3f();
+    _bounds.include(PhysxManager::vec3_to_nxVec3(v));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::update_normals
+//       Access: Public
+//  Description:_bounds.include(mVertices[i]);
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+update_normals() {
+
+  _normals.resize(_vdata->get_num_rows());
+
+  int i;
+  for (i=0; i<(int)_normals.size(); i++) { 
+    _normals[i] = LVector3f::zero();
+  }
+
+  LVecBase3f n, v0, v1, v2;
+  GeomVertexReader vreader = GeomVertexReader(_vdata, InternalName::get_vertex());
+
+  for (int j=0; j<_prim->get_num_primitives(); j++) {
+
+    int s = _prim->get_primitive_start(j);
+    int idx0 = _prim->get_vertex(s);
+    int idx1 = _prim->get_vertex(s+1);
+    int idx2 = _prim->get_vertex(s+2);
+
+    vreader.set_row(idx0); v0 = vreader.get_data3f();
+    vreader.set_row(idx1); v1 = vreader.get_data3f();
+    vreader.set_row(idx2); v2 = vreader.get_data3f();
+
+    n = (v1 - v0).cross(v2 - v0);
+
+    _normals[idx0] += n;
+    _normals[idx1] += n;
+    _normals[idx2] += n;
+  }
+
+  for (i=0; i<(int)_normals.size(); i++) { 
+    _normals[i].normalize();
+  }
+
+  GeomVertexWriter nwriter = GeomVertexWriter(_vdata, InternalName::get_normal());
+  for (i=0; i<(int)_normals.size(); i++) { 
+    n = _normals[i];
+    nwriter.add_data3f(n.get_x(), n.get_y(), n.get_z());
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::compute_bary_coords
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+NxVec3 PhysxSoftBodyNode::
+compute_bary_coords(NxVec3 vertex, NxVec3 p0, NxVec3 p1, NxVec3 p2, NxVec3 p3) const {
+
+  NxVec3 baryCoords;
+
+  NxVec3 q  = vertex - p3;
+  NxVec3 q0 = p0 - p3;
+  NxVec3 q1 = p1 - p3;
+  NxVec3 q2 = p2 - p3;
+
+  NxMat33 m;
+  m.setColumn(0, q0);
+  m.setColumn(1, q1);
+  m.setColumn(2, q2);
+
+  NxReal det = m.determinant();
+
+  m.setColumn(0, q);
+  baryCoords.x = m.determinant();
+
+  m.setColumn(0, q0);
+  m.setColumn(1, q);
+  baryCoords.y = m.determinant();
+
+  m.setColumn(1, q1);
+  m.setColumn(2,q);
+  baryCoords.z = m.determinant();
+
+  if (det != 0.0f) {
+    baryCoords /= det;
+  }
+
+  return baryCoords;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::update
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PhysxSoftBodyNode::
+update() {
+
+  update_tetra_links();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PhysxSoftBodyNode::update_tetra_links
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool PhysxSoftBodyNode::
+update_tetra_links() {
+
+  if (_tetraLinks.size() != _vdata->get_num_rows())
+  {
+      return false;
+  }
+
+  NxU32 numVertices = *_mesh.numVerticesPtr;
+  NxU32 numTetrahedra = *_mesh.numIndicesPtr / 4;
+  const NxVec3 *vertices = (NxVec3*)_mesh.verticesPosBegin;
+  NxU32* indices = (NxU32*)_mesh.indicesBegin;
+
+  GeomVertexRewriter vwriter = GeomVertexRewriter(_vdata, InternalName::get_vertex());
+
+  int i = 0;
+  while (!vwriter.is_at_end()) {
+
+    TetraLink &link = _tetraLinks[i];
+
+    if (!_drainedTriVertices[i]) {
+      const NxU32 *ix = &indices[4*link.tetraNr];
+
+      if (*ix == *(ix + 1)) {
+        remove_tris_related_to_vertex(i);
+        _drainedTriVertices[i] = true;
+        continue;
+      }
+
+      const NxVec3 &p0 = vertices[*ix++];
+      const NxVec3 &p1 = vertices[*ix++];
+      const NxVec3 &p2 = vertices[*ix++];
+      const NxVec3 &p3 = vertices[*ix++];
+
+      NxVec3 &b = link.barycentricCoords;
+      NxVec3 tmp = p0 * b.x + p1 * b.y + p2 * b.z + p3 * (1.0f - b.x - b.y - b.z);
+      vwriter.set_data3f(tmp.x, tmp.y, tmp.z);
+    }
+    i++;
+  }
+
+  update_normals();
+
+  return true;
+}
+

+ 99 - 0
panda/src/physx/physxSoftBodyNode.h

@@ -0,0 +1,99 @@
+// Filename: physxSoftBodyNode.h
+// Created by:  enn0x (13Sep10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PHYSXSOFTBODYNODE_H
+#define PHYSXSOFTBODYNODE_H
+
+#include "pandabase.h"
+#include "pointerTo.h"
+#include "geomNode.h"
+#include "transformState.h"
+#include "geom.h"
+#include "geomVertexData.h"
+#include "geomTriangles.h"
+#include "filename.h"
+
+#include "physx_includes.h"
+
+class PhysxSoftBody;
+
+////////////////////////////////////////////////////////////////////
+//       Class : PhysxSoftBodyNode
+// Description : Renderable geometry which represents a soft body
+//               mesh.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAPHYSX PhysxSoftBodyNode : public GeomNode {
+
+PUBLISHED:
+  INLINE PhysxSoftBodyNode(const char *name);
+  INLINE ~PhysxSoftBodyNode();
+
+  void set_from_geom(const Geom *geom);
+
+public:
+  void allocate(PhysxSoftBody *cloth);
+  void update();
+
+private:
+
+  struct TetraLink {
+    int tetraNr;
+    NxVec3 barycentricCoords;
+  };
+
+  void update_bounds();
+  void build_tetra_links();
+  bool update_tetra_links();
+  void update_normals();
+  void remove_tris_related_to_vertex(const int vertexIndex);
+  NxVec3 compute_bary_coords(NxVec3 vertex, NxVec3 p0, NxVec3 p1, NxVec3 p2, NxVec3 p3) const;
+
+  pvector<TetraLink> _tetraLinks;
+  pvector<bool> _drainedTriVertices;
+  pvector<LVecBase3f> _normals;
+
+  NxBounds3 _bounds;
+  NxMeshData _mesh;
+
+  PT(GeomVertexData) _vdata;
+  PT(Geom) _geom;
+  PT(GeomTriangles) _prim;
+
+  PT(PhysxSoftBody) _softbody;
+
+////////////////////////////////////////////////////////////////////
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    GeomNode::init_type();
+    register_type(_type_handle, "PhysxSoftBodyNode", 
+                  GeomNode::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 "physxSoftBodyNode.I"
+
+#endif // PHYSXSOFTBODYNODE_H

+ 1 - 0
panda/src/physx/physxVehicle.h

@@ -23,6 +23,7 @@
 
 class PhysxActor;
 class PhysxWheel;
+class PhysxVehicleDesc;
 class PhysxScene;
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/physx/physxWheelShape.h

@@ -21,6 +21,7 @@
 #include "physx_includes.h"
 
 class PhysxWheelShapeDesc;
+class PhysxSpringDesc;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PhysxWheelShape

+ 6 - 0
panda/src/physx/physx_composite.cxx

@@ -70,6 +70,7 @@
 #include "physxMaterialDesc.cxx"
 #include "physxMemoryReadBuffer.cxx"
 #include "physxMemoryWriteBuffer.cxx"
+#include "physxMeshHash.cxx"
 #include "physxMeshPool.cxx"
 #include "physxMotorDesc.cxx"
 #include "physxObject.cxx"
@@ -97,6 +98,11 @@
 #include "physxSegment.cxx"
 #include "physxShape.cxx"
 #include "physxShapeDesc.cxx"
+#include "physxSoftBody.cxx"
+#include "physxSoftBodyDesc.cxx"
+#include "physxSoftBodyMesh.cxx"
+#include "physxSoftBodyMeshDesc.cxx"
+#include "physxSoftBodyNode.cxx"
 #include "physxSphere.cxx"
 #include "physxSphereForceFieldShape.cxx"
 #include "physxSphereForceFieldShapeDesc.cxx"

+ 5 - 0
panda/src/physx/physx_includes.h

@@ -18,8 +18,12 @@
 
 // Platform-specific defines
 #ifdef WIN32
+#if _WIN64 || __amd64__
+#define NX64 1
+#else
 #define NX32 1
 #endif
+#endif
 
 #ifdef IS_LINUX
 #define LINUX 1
@@ -30,6 +34,7 @@
 #endif
 #define CORELIB 1
 #define NX_DISABLE_FLUIDS 1
+#define NX_DISABLE_HARDWARE 1
 #endif
 
 #ifdef IS_FREEBSD