Failed to call BulletSoftBodyNode.makeTetMesh

I want to create myself soft body by makeTetMesh.

Firstly, I use pygmsh to generate a tetrahedron:

with pygmsh.occ.Geometry() as geom:
    disk = geom.add_disk([0, 0, 0], 0.2, 0.2)
    geom.extrude(disk, [0, 0, 3])
    msh = geom.generate_mesh()

print('generation finish')
points = msh.points
tri = msh.cells_dict['triangle']
tet = msh.cells_dict['tetra']

I find there are two way to call makeTetMesh:

make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices, bool tetralinks)
make_tet_mesh(BulletSoftBodyWorldInfo info, str ele, str face, str node)

For the above points/tri/tet, I can sucessfully call make_tet_mesh(BulletSoftBodyWorldInfo info, str ele, str face, str node) but failed to call make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices, bool tetralinks).

The complete code to test is:


from panda3d.core import Vec3, Point3
from panda3d.bullet import BulletWorld
from panda3d.bullet import BulletSoftBodyNode

import pygmsh

world = BulletWorld()

info = world.getWorldInfo()
with pygmsh.occ.Geometry() as geom:
    disk = geom.add_disk([0, 0, 0], 0.2, 0.2)
    geom.extrude(disk, [0, 0, 3])
    msh = geom.generate_mesh()

print('generation finish')
points = msh.points
tri = msh.cells_dict['triangle']
tet = msh.cells_dict['tetra']

fixIds = []
node = '%d 3 0 0\n'%len(points)
for idx, p in enumerate(points):
    node += '%d %f %f %f\n'%(idx, p[0], p[1], p[2])
    if p[2] == 0:
        fixIds.append(idx)
ele = '%d 4 0\n'%(len(tet))
for idx, e in enumerate(tet):
    ele += '%d %d %d %d %d\n'%(idx, e[0], e[1], e[2], e[3])
face = '%d 0\n'%len(tri)
for idx, f in enumerate(tri):
    face += '%d %d %d %d\n'%(idx, f[0], f[1], f[2])


node = BulletSoftBodyNode.makeTetMesh(info, ele, face, node)
print('success: make_tet_mesh(BulletSoftBodyWorldInfo info, str ele, str face, str node)')

points = [Point3(p[0], p[1], p[2])*3 for p in points]
elements = [(t[0], t[1], t[2], t[3]) for t in tet]
indices = sum([list(x) for x in elements], [])
node = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)
print('success: make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices, bool tetralinks)')

Well, you haven’t specified what you mean by “failed”, so I’m taking a bit of a stab in the dark here.

That said, looking at the API (and indeed, at the method-signature that you posted), it seems that “make_tet_mesh” takes not a list (as you’re passing in) but rather a “PointerToArray”–which I believe is this class.

.However, I myself don’t know how the method expects that class to be used, so perhaps someone more familiar will answer further!

@Thaumaturge Thanks for reply.

For “failed”, the reported information is:

Traceback (most recent call last):
  File "C:\Users\qiang_zhang\Desktop\panda3d\samples\bullet-physics\test3.py", line 41, in <module>
    node = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)
TypeError: Arguments must match:
make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices)
make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices, bool tetralinks)
make_tet_mesh(BulletSoftBodyWorldInfo info, str ele, str face, str node)

I have noticed the inpute PointerToArray, but the tutorial is:

points = [(x1, y1, z1), (x2, y2, z2), ...]
elements = [(i0, i1, i2, i3), (i4, i5, i6, i7), ...]

points = [Point3(x,y,z) * 3 for x,y,z in nodes]
indices = sum([list(x) for x in elements], [])

bodyNode = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)

The tutorial input a list. If the input is incorrect, the tutorial may should be revised.

The tutorial is written correctly. Note that two constructors are specified.

@serega-kkz

points = [Point3(p[0], p[1], p[2])*3 for p in points]
elements = [(t[0], t[1], t[2], t[3]) for t in tet]
indices = sum([list(x) for x in elements], [])
node = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)
print('success: make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices, bool tetralinks)')

Why the above code reported:

Traceback (most recent call last):
  File "C:\Users\qiang_zhang\Desktop\panda3d\samples\bullet-physics\test3.py", line 41, in <module>
    node = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)
TypeError: Arguments must match:
make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices)
make_tet_mesh(BulletSoftBodyWorldInfo info, PointerToArray points, PointerToArray indices, bool tetralinks)
make_tet_mesh(BulletSoftBodyWorldInfo info, str ele, str face, str node)

The bug say the arguments are note match.

But I have used makeTetMesh as the tutorial. Is there anything wrong with my code?

I think you passed variables that don’t match the type.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import Vec3, Point3
from panda3d.bullet import BulletSoftBodyNode, BulletWorld
import cube

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)
        
        world = BulletWorld()
        world.setGravity(Vec3(0, 0, -9.81))

        info = world.getWorldInfo()

        points = [Point3(1, 1, -1), Point3(1, -1, -1), Point3(-1, -1, -1), Point3(1, 1, 1)]
        indices = [0, 1, 2, 3]

        print(points)
        print(indices)

        node = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)


app = MyApp()
app.run()

It works, you just need to pass the correct parameters.