Просмотр исходного кода

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

enn0x 15 лет назад
Родитель
Сommit
e2093b1c2d
37 измененных файлов с 3499 добавлено и 32 удалено
  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