Problem with Bullet Vehicle and collisions

Hi, I’ve a problem with Bullet Vehicle and collisions. It happens on Panda3D 1.9.2.

As you can see in this video, the vehicle “enters” into the hills on Windows and OSX: the same code works perfectly on Linux (the car goes “over” the hill), but it doesn’t work on Windows and on OSX (I use 1.9.2 on these three systems).

I attach a minimal example which shows the issue to this post.

Here is how the physics is initialized:

...
self.world_phys = BulletWorld()
self.world_phys.setGravity((0, 0, -9.81))
...

Here is how the physics is processed:

...
    def __update(self, task):
        ...
        self.world_phys.doPhysics(globalClock.getDt(), 5, 1/60.0)
...

Here is how the collision for the track is generated (it is a BulletTriangleMesh):

geom_geom = geom.node().getGeom(0)
mesh = BulletTriangleMesh()
mesh.addGeom(geom_geom)
shape = BulletTriangleMeshShape(mesh, dynamic=False)
np = base.world_np.attachNewNode(BulletRigidBodyNode(geom.get_name()))
np.node().addShape(shape)
base.world_phys.attachRigidBody(np.node())

Here is how the vehicle is created:

...
chassis_shape = BulletBoxShape(LVecBase3f(*self.collision_box_shape))
transform_state = TransformState.makePos(LVecBase3f(*self.collision_box_pos))
mdt.gfx.nodepath.node().addShape(chassis_shape, transform_state)
mdt.gfx.nodepath.node().setMass(self.mass)
mdt.gfx.nodepath.node().setDeactivationEnabled(False)

base.world_phys.attachRigidBody(mdt.gfx.nodepath.node())

self.vehicle = BulletVehicle(base.world_phys, mdt.gfx.nodepath.node())
self.vehicle.setCoordinateSystem(ZUp)
...
base.world_phys.attachVehicle(self.vehicle)

Why doesn’t it work on Windows and OSX? What am I missing here? Thank you!
collision.zip (7.58 MB)

Hi, I’ve made a smaller example, maybe it could help to spot the problem more easily. Here is the complete code; in the attachment there is the file and the assets. Thank you!

from direct.gui.OnscreenText import OnscreenText
from direct.showbase.ShowBase import ShowBase
from panda3d.bullet import BulletWorld, BulletDebugNode, BulletBoxShape, \
    BulletRigidBodyNode, BulletTriangleMesh, BulletTriangleMeshShape, \
    BulletVehicle
from panda3d.core import TransformState


class VehicleTest(ShowBase, object):

    def __init__(self, configuration=None, domain=''):
        ShowBase.__init__(self)
        self.setup_physics()
        self.setup_track()
        self.setup_car()
        self.set_debug()
        self.taskMgr.add(self.update, 'Engine::update')

    def setup_physics(self):
        self.world_phys = BulletWorld()
        self.world_phys.setGravity((0, 0, -9.81))

    def setup_track(self):
        self.track_model = loader.loadModel('assets/track/track')
        self.track_model.reparentTo(render)
        self.track_model.flattenLight()

        collision_models = self.track_model.findAllMatches('**/Road*')
        map(lambda mod: mod.hide(), collision_models)

        for geom in self.find_geoms(self.track_model, 'Road'):
            mesh = BulletTriangleMesh()
            mesh.addGeom(geom.node().getGeom(0))
            np = render.attachNewNode(BulletRigidBodyNode())
            np.node().addShape(BulletTriangleMeshShape(mesh, dynamic=False))
            self.world_phys.attachRigidBody(np.node())

    def setup_car(self):
        self.car_np = render.attachNewNode(BulletRigidBodyNode())
        self.car_np.set_pos(-100, -20, 2)
        self.chassis_np = self.loader.loadModel('assets/car/car')
        self.chassis_np.reparentTo(self.car_np)
        self.wheels_np = []
        for _ in range(4):
            self.wheels_np += [self.loader.loadModel('assets/car/wheel')]
            self.wheels_np[-1].reparentTo(render)

        chassis_shape = BulletBoxShape((.8, 1.4, .4))
        transform_state = TransformState.makePos((0, .05, .5))
        self.car_np.node().addShape(chassis_shape, transform_state)
        self.car_np.node().setMass(1400)
        self.world_phys.attachRigidBody(self.car_np.node())
        self.vehicle = BulletVehicle(self.world_phys, self.car_np.node())
        self.world_phys.attachVehicle(self.vehicle)

        wheels_info = [
            ((.75, .9, .3), True, 0),
            ((-0.75, .9, .3), True, 1),
            ((.75, -0.9, .3), False, 2),
            ((-0.75, -0.9, .3), False, 3)]
        def add_wheel(pos, front, idx):
            wheel = self.vehicle.createWheel()
            wheel.setNode(self.wheels_np[idx].node())
            wheel.setChassisConnectionPointCs(pos)
            wheel.setFrontWheel(front)
            wheel.setWheelDirectionCs((0, 0, -1))
            wheel.setWheelRadius(.3)
            wheel.setSuspensionStiffness(10)
        map(lambda (pos, front, idx): add_wheel(pos, front, idx), wheels_info)

    def update(self, task):
        car_pos = self.car_np.get_pos()
        self.cam.set_pos(car_pos.x - 15, car_pos.y - 15, car_pos.z + 5)
        self.cam.look_at(car_pos.x, car_pos.y, car_pos.z)
        map(lambda idx: self.vehicle.applyEngineForce(2000, idx), [2, 3])
        self.world_phys.doPhysics(globalClock.getDt(), 10, 1 / 60.0)
        return task.cont

    def set_debug(self):
        def toggle_debug():
            is_hidden = self.debug_np.isHidden()
            (self.debug_np.show if is_hidden else self.debug_np.hide)()
        OnscreenText('press F9 for physics debug', pos=(0, -.9))
        self.accept('f9', toggle_debug)
        self.debug_np = self.render.attachNewNode(BulletDebugNode('Debug'))
        self.world_phys.setDebugNode(self.debug_np.node())

    def find_geoms(self, model, name):
        def sibling_names(node):
            siblings = node.getParent().getChildren()
            return [child.getName() for child in siblings]

        named_geoms = [
            geom for geom in model.findAllMatches('**/+GeomNode')
            if any([s.startswith(name) for s in sibling_names(geom)])]
        in_vec = [name in named_geom.getName() for named_geom in named_geoms]
        indexes = [i for i, el in enumerate(in_vec) if el]
        return [named_geoms[i] for i in indexes]

VehicleTest().run()

collision_issue.zip (7.56 MB)

I’m unable to test it right now (on vacation), but might it be that different Bullet versions were used on Windows vs Linux? Which exact builds did you test?

Hi rdb! I’m using the latest SDK (and the latest deployment tools), so it is Panda3D 1.9.2. I checked Bullet’s libraries deployed by pdeploy (but the same issue happens with Panda3D’s SDK), it looks like Panda3D ships Bullet 2.81 for Linux and Bullet 2.82 for Windows and OSX. Actually, it works on Linux and it doesn’t work on Windows and OSX, so it may be Bullet’s version. Is there a “simple” way to change Bullet’s version? Thank you, enjoy your vacation! :slight_smile:

I’ve run the demo on windows (10) and all I can say is that the car falls through the hill.

From my experience Bullet is not so keen on triangle strips, and some polygons could be flipped (bad normal) or something else wrong with the geometry. I noticed you only use the first geom so I changed that to look for all the geoms (and decompose the geoms just in case):

mesh = BulletTriangleMesh()
for i in range(geom.node().getNumGeoms()):
    decomposed=geom.node().getGeom(i).decompose()
    mesh.addGeom(decomposed)

But that’s not it. I also run “egg-trans -F -C -np” but no luck there, the car still falls down.
I took the model into my modelling software and tessellated the track mesh - the car didn’t fall in the same place as it used to… but it fell a bit further up the hill.

This is very strange for me, because not so long ago I made a game-prototype that used the same setup -a Bullet vehicle driving over a bullet tri mesh and I had no such problems. The only times I managed to drive (fall) through the terrain where after making some 5 flips in the air and hitting the ground at strange angles and velocities. The code for that project is here: github.com/wezu/pyweek21 but I see no difference in the way I setup the car and terrain there.

Hi wezu, thank you very much! I have analyzed your code, actually it works. Some meshes (like yours) work (I did other working meshes), but some don’t work, with no apparent reason.

I did a lot of experiments based on your posts, and the situation is the one I described at first: some meshes don’t work on Windows and OSX, which are using Bullet 2.82, but they do work on Linux. Do the current runtime-dev packages ship Bullet 2.83? If not, is there any chance to update Bullet’s version that Panda is using? Thank you very much! :slight_smile: