Bullet Softbody with tetgen problem

Hello.

I has read this tutorial.
http://www.panda3d.org/manual/index.php/Bullet_Softbody_Tetrahedron

And I loaded a sample from enn0x’s forum.
[url]Panda Bullet]

The sample is great. So I tried to load my own model to be softbody.
I load tetgen source from tetgen website and build it into .exe file by Visual C++ 6.0.
I export my own model (standard cube) from 3DsMax 2010 to .stl file.
Then I use tetgen.exe generate the .ele , .face and .node file from .stl file and everything work find.

But when I ran Panda3D App. I got runtime-error when run at these code

    node = BulletSoftBodyNode.makeTetMesh(info, ele, face, node)
    node.setName('Tetra')
    node.setVolumeMass(300)
   
    node.getShape(0).setMargin(0.01)
    node.getMaterial(0).setLinearStiffness(0.1)
    node.getCfg().setPositionsSolverIterations(1)
    node.getCfg().clearAllCollisionFlags()
    node.getCfg().setCollisionFlag(BulletSoftBodyConfig.CFClusterSoftSoft, True)
    node.getCfg().setCollisionFlag(BulletSoftBodyConfig.CFClusterRigidSoft, True)
    node.generateClusters(6)

Does this issue relavant to 3DsMax version? Or I should use export file .poly not .stl.
(As I know 3DsMax can export only .stl to support tetgen)
Please help me.

(Panda3D 1.7.2)

Regards,
Ola

Hmmm, in order to find out what is causing the runtime crash I would need the .elem/.face/.node files which cause the crash. Can you upload them somewhere?

I wild guess would be that something with the generated files is wrong, or I am making asumptions about these files which are not met in your case.

I don’t have 3DsMax, just Blender. This is what I have done:
1.) Create a mesh in Blender (a surface mesh!)
2.) Export the surface mesh to .egg format
3.) Use a self-written script to translate .egg --> .poly (still surface mesh!)
4.) Use tetgen to create the volume-mesh from the .poly file.

Here is the “egg2poly.py” script:

from direct.showbase.Loader import Loader

from panda3d.core import Filename
from panda3d.core import Point3
from panda3d.core import GeomVertexReader

def processNP(modelNP):
  points = []
  triangles = []

  for geomNP in modelNP.findAllMatches('**/+GeomNode'):
    geomNode = geomNP.node()
    ts = geomNode.getTransform()
    for geom in geomNode.getGeoms():
      processVertices(geom, points, ts)
      processIndices(geom, triangles)

  return points, triangles

def processVertices(geom, points, ts):
  m = ts.getMat().getUpper3()
  p = ts.getMat().getRow3(3)

  vdata = geom.getVertexData()
  reader = GeomVertexReader(vdata, 'vertex')
  while not reader.isAtEnd():
    v = reader.getData3f()
    v = m.xform(v) + p
    points.append(Point3(v))

def processIndices(geom, triangles):
  for prim in geom.getPrimitives():
    prim = prim.decompose()
    for p in range(prim.getNumPrimitives()):
      s = prim.getPrimitiveStart(p)
      e = prim.getPrimitiveEnd(p)

      assert ((e - s) % 3 == 0)

      triangle = []
      for i in range(s, e):
        vi = prim.getVertex(i)
        triangle.append(vi)
      triangles.append(triangle)

def getPointIndex(p, points):
  eps = 1e-6

  for idx, p0 in enumerate(points):
    if p.almostEqual(p0):
      return idx

  return -1

def processDuplicates(points, triangles):
  new_points = []
  new_triangles = []

  mapping = {}

  # Points
  for idx, p in enumerate(points):
    new_idx = getPointIndex(p, new_points)
    if new_idx < 0:
      new_idx = len(new_points)
      new_points.append(p)

    mapping[idx] = new_idx

  # Triangles
  for triangle in triangles:
    i0 = mapping[triangle[0]]
    i1 = mapping[triangle[1]]
    i2 = mapping[triangle[2]]
    new_triangles.append((i0, i1, i2))

  return new_points, new_triangles

def processFile(fname):
  loader = Loader(None)
  np = loader.loadModel(fname)
  points, triangles = processNP(np)

  points, triangles = processDuplicates(points, triangles)

  # Nodes
  lines = []
  lines.append('# Nodes')
  lines.append('%i 3 0 0' % len(points))

  for idx, p in enumerate(points):
    lines.append('%i %0.5f %0.5f %0.5f' % (idx, p.getX(), p.getY(), p.getZ()))

  lines.append('')

  # Facets
  lines.append('# Facets')
  lines.append('%i 0' % len(triangles))

  for triangle in triangles:
    lines.append('1')
    lines.append('3 %i %i %i' % tuple(triangle))

  lines.append('')

  # Holes
  lines.append('# Holes')
  lines.append('0')
  lines.append('')

  # Regions
  lines.append('# Regions')
  lines.append('0')
  lines.append('')

  fname = fname.replace('.egg', '.poly')
  file(fname, 'w').write('\n'.join(lines))

if __name__ == '__main__':
  processFile('cube.egg')

Hello.

Thank you very much Enn0x.
Your script work for me. :astonished:

I thinks maybe my 3dsmax version not support tetgen.
I will try the lower version.

Thank you.
Regards,
Ola