Bullet triangle mesh scaling/multiple objects

I’m using 414 dev build for windows.
1)
I have made simple model in blender and exported to *.egg file, however when I load it, in debug mode I can see it really rescalled/smaller than the visual model is itself.
Is it how it should be done?

geom = loader.loadModel('media/models/test')\
                 .findAllMatches('**/+GeomNode')\
                 .getPath(0)\
                 .node()\
                 .getGeom(0)
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)
        shape = BulletTriangleMeshShape(mesh, dynamic=False)
    
        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Mesh'))
        np.node().addShape(shape)
        np.setPos(0, 0, 0.1)
        np.setCollideMask(BitMask32.allOn())
    
        self.world.attachRigidBody(np.node())
        
        visual = loader.loadModel('media/models/test')
        visual.reparentTo( np )

When I create 2 different objects in same file in blender and export them, only the first ones bounds are shown.

img638.imageshack.us/img638/5987/ssdads.jpg

Please pay attention to what loader.loadModel() returns. It is a NodePath to a small tree of nodes, usually having a ModelNode as root, and then one or more GeomNodes. You can test this yourself:

np = loader.loadModel('media/models/test')
np.ls()

The PandaNodes and thus the GeomNodes might have transforms relative to the root of the subtree loaded with loader.loadModel!

If you just pick the GeomNodes, fetch the Geoms from them, and feed the Geoms to the BulletTriangleMesh then you will loose information about these transforms, since the Geom itself does not know anything about a transform.

Also if you have more than one GeomNodes or more than one Geom within a GeomNode then you will loose them, since you explicitly fetch the first GeomNode, and from this first GeomNode the first Geom!

So what you might want to do is (pseudocode!):

np = loader.loadModel(path)
loop over all NodePath's to GeomNodes (gnp) within np:
  ts = get transformState of gnp relative to np
  loop over all Geoms (geom) within gnp.node()
    shape = create mesh shape from geom
    body.addShape(shape, ts) # <-- pass TransformState!

I’m having some issues about model mesh to Bullet Triangle Mesh (& -Shape), I tried your pseudocode and I can’t get it work, the following code (in C++) creates shape but apparently unscaled:

NodePath np_model_scene = base->get_window()->load_model(base->get_framework()->get_models(), "map/floor");

    NodePathCollection all_geom = np_model_scene.find_all_matches("**/+GeomNode");
    BulletRigidBodyNode *brbn_floor = new BulletRigidBodyNode("Floor");

    for (int i = 0; i < all_geom.get_num_paths(); i++) {
        BulletTriangleMesh *btm_tmp_floor = new BulletTriangleMesh();
        NodePath np_geom = all_geom.get_path(i);

        GeomNode *gn_all_geoms = DCAST(GeomNode, np_geom.node());
        const TransformState *ts_of_geoms = np_geom.get_transform(np_model_scene);

        for (int j = 0; j < gn_all_geoms->get_num_geoms(); j++) {
            btm_tmp_floor->add_geom(gn_all_geoms->get_geom(j), true);
        }

        BulletTriangleMeshShape *btms_floor = new BulletTriangleMeshShape(btm_tmp_floor, false);
        brbn_floor->add_shape(btms_floor, ts_of_geoms);
    }

    NodePath np_floor = base->get_window()->get_render().attach_new_node(brbn_floor);
    np_model_scene.reparent_to(np_floor);
    //brbn_floor->set_transform(np_model_scene.find("/").get_transform());

    get_physics_world()->attach_rigid_body(brbn_floor);

:arrow_right: Note: If you uncomment the line brbn_floor-> … then you will get an half-well working, but when you reparent model to physics node, the model changes (Transform values are powered, I think).

:arrow_right: Variable base is just a class with WindowFramework * and PandaFramework * pointers.

:arrow_right: Function get_physics_world() is just a static variable allocator:

BulletWorld *get_physics_world() {
    static BulletWorld *physics_world = new BulletWorld();
    return physics_world;
}

:arrow_right: I think it’s .egg stuff, nevertheless it may work with any mesh type.

I’m very overhead with this problem :angry:.
Thanks for reading :smiley: and greetings from Mexico.

Can you PM me a download link for this model (zipped egg), or send it via email? Of course I wont re-use/re-sell/… the model and delete it once the question is ansered.

http://www.4shared.com/zip/0BI6uAUr/2DWorld.html

Here you are … it’s made on Netbeans, all eggs are on map/ folder, sources are compiled with Makefile (linux) some path’s are absolutes :slight_smile:.

Thanks.

sigh Another file hosting service I can not use. Guys, there is Panda3D Projects (p3dp), why do you always use those sign-in-with-your-email-to-download-a-file hosters.

Didn’t Know man … wherever I have to get permissions, so upload to my personal hosting … sorry for mistake.

http://consultoriaconverge.com/p3d/2DWorld.zip

Actually, I’m pretty sure that is egg stuff (exported from blender) :slight_smile:.

Ok, got it. Thank you.

The floor.egg seems weired indeed. Just try this (Python) code:

np = loader.loadModel('floor.egg')
np.ls()
for geomNP in np.findAllMatches('**/+GeomNode'):
  geomNode = geomNP.node()
  print geomNP.getTransform(np)
  for geom in geomNode.getGeoms():
    print geom.getVertexData()

No Bullet stuff in here, just plain Panda3D. Anyway, the output will show vertices at (1,1,1), (-1,1,1) etc. Not what I would expect after looking at the .egg file. I can’t explain what is going on here. In order to get an explanation I think we need rdb or drwr.

But I know what helps: flatten light after loading

By the way, you don’t need a new shape for each geom. And if you are not using the Panda3D internal collision system you probably have no use for the contained Panda3D collision solids. You could try to export without the " { Polyset keep descend }". Maybe this way you can get rid of the in the .egg file (which causes this effect).

This is the code I used for loading. It’s Python, but I guess you can translate to C++:

np = loader.loadModel('floor.egg')
np.reparentTo(render)
np.flattenLight()

mesh = BulletTriangleMesh()
for geomNP in np.findAllMatches('**/+GeomNode'):
  geomNode = geomNP.node()
  ts = geomNP.getTransform(np)
  for geom in geomNode.getGeoms():
    mesh.addGeom(geom, ts)

shape = BulletTriangleMeshShape(mesh, False)
floor = BulletRigidBodyNode('floor')
floor.addShape(shape)
floorNP = render.attachNewNode(floor)
floorNP.setPos(0, 0, 0)
floorNP.setCollideMask(BitMask32.allOn())
world.attachRigidBody(floor)

Thanks.

Actually, I modified YABEE plugin for automatic adding of " { Polyset keep descend }" and I forgot it :unamused:. Anyway I couldn’t get it work, so I rebuilded entire land from scratch without resizing and did mesh transforms only. After exporting without “…”, it worked!.

I’ll look for more stylish solution, but for now it’s ok.
Thanks again :smiley:.

Hey enn0x I tried your code to automatically create a mesh of my model (the box.egg that comes with panda) but for some reason when I create it using the triangle mesh it does not collide with my BulletPlaneShape anymore, it just goes straight through it. Any idea why? If I used a boxshape for the same model it works fine.

Which code are you refering to?

This one. But instead of floor.egg I used box.egg and I also added a planeShape and made it so that the box would fall into the plane.

np = loader.loadModel('floor.egg') 
 np.reparentTo(render) 
 np.flattenLight() 
 mesh = BulletTriangleMesh() 
 for geomNP in np.findAllMatches('**/+GeomNode'): 
   geomNode = geomNP.node() 
   ts = geomNP.getTransform(np) 
   for geom in geomNode.getGeoms(): 
     mesh.addGeom(geom, ts) 

 shape = BulletTriangleMeshShape(mesh, False) 
 floor = BulletRigidBodyNode('floor') 
 floor.addShape(shape) 
 floorNP = render.attachNewNode(floor) 
 floorNP.setPos(0, 0, 0) 
 floorNP.setCollideMask(BitMask32.allOn()) 
 world.attachRigidBody(floor)

Try this:

shape = BulletTriangleMeshShape(mesh, dynamic=True)

Just for the record: using a triangle mesh for anything but a static environment is highly discouraged. Either use primitives (box!) or a convex hull shape.

Please read the manual page about collison shapes. The page explains when to use which shape type: panda3d.org/manual/index.ph … ion_Shapes

Hm, when I was reading the manual in the entry of Convex Hull Shapes I read “elastic membrane” and I thought it was refering to the kind of membrane of a drum and it was used to simulate vibrations and I skiped to the Triangle Meshes.

So I’m now trying to use Convex Hull Shapes. But it’s not working as I expected. I think when I create the shape it’s not getting all the geoms of my model.

I tried using the following code:

geomNodes = box.findAllMatches('**/+GeomNode')
geomNode = geomNodes.getPath(0).node()
geom = geomNode.getGeom(0)

And

geomNodes = box.findAllMatches('**/+GeomNode')
geomNode = geomNodes.getPath(0).node()
geom = geomNode.getGeom(0)
shape = BulletConvexHullShape()
shape.addGeom(geom)

Both seem to not be getting all the geoms.

You see the “(0)” twice in the code you have cited? This is where you access the first elements of something. Now look at your own post of 07 Apr. There you will see how to pick up all geoms. Also have a look at the manual section on the Panda3D scene graph and how Panda3D stores geometry - it won’t be time wasted if you want to code with Panda3D.

shape = BulletConvexHullShape()
for geomNP in model.findAllMatches('**/+GeomNode'): 
    geomNode = geomNP.node() 
    for geom in geomNode.getGeoms(): 
        shape.addGeom(geom)

I actually tried this too before. This seems to be working on simpler models, but anything more complex and it doesn’t get all the geometry. In the teapot.egg model included in panda it doesn’t get the handle, the funnel and the lid of the model. On the panda.egg it only gets the glasses and part of one hand as can be seen in the screenshots below:

s15.postimage.org/jmmf2dtrv/panda.png

s15.postimage.org/ra9bkosfv/panda.png

(in the teapot screeshot there is a plane shape in the background, ignore the line behind the teapot)

I don’t see anything wrong while looking at the debug wire-frames of the box.egg model but it behaves very oddly when colliding with a plane which leads me to think that the rigid body in this model is also not being made properly.

Using
findAllMatches(’**/+GeomNode;+h+s+i’):
doesn’t help either.

Yes, there are upper limits on the number of vertices for convex hulls. PhysX has 256 vertices for example. No idea what the Bullet limit is.

You could simply use several convex hull shapes:

    model = loader.loadModel('teapot.egg')

    np = self.worldNP.attachNewNode(BulletRigidBodyNode('Teapot'))

    for geomNP in model.findAllMatches('**/+GeomNode'):
      geomNode = geomNP.node()
      ts = geomNP.getTransform(model)
      for geom in geomNode.getGeoms():
        shape = BulletConvexHullShape()
        shape.addGeom(geom)
        np.node().addShape(shape, ts)

    np.node().setMass(1.0)
    np.setPos(4, 0, 2)
    np.setCollideMask(BitMask32.allOn())
    self.world.attachRigidBody(np.node())

However, it is highly recommended that the mesh used for collision is simplified first.