Possible to use multiple bullet worlds?


#1

I’m building an environment where I nest render’s within each other. A sort of world within world functionality. I recently started using bullet physics to detect mouseovers, and have created BulletWorld instances that correspond with each render/nodepath of each world entered. This sort of works, but, i am getting segfaults now when I switch back to using my first BulletWorld instance. Is using multiple bulletworld instances on the same window causing issues? Is there some BulletWorld or Engine level method needed to be called prior to switching which BulletWorld is in use?


#2

And how is the type of error classified? or is it a secret. :slight_smile:


#3

Could you give some example code to demonstrate the segfault? It may be a bug in Panda3D, or at the very least something we should give a better error message about.


#4

I’ll see if I can build a simple implementation that replicates it… the error I get is:

2019-01-12T13:32:52.979117 [debug] < -- > - [0.001397848129272461s]⭅⇦⇦⇦⇦⇦ event:wrapper( args = (<event.EventInstance object at 0x7fb5d4156278>,) ) returned: None
2019-01-12T13:32:52.979143 [debug] < -- > - [0.0031614303588867188s]⭅⇦⇦⇦⇦ statemanager:wrapped( args = (<<MenuItem:['Cool Squished Curtain' i(exitcontainer)]>>, LPoint3f(0.150721, 1, 0.0271298)) ) returned: None
2019-01-12T13:32:52.979167 [debug] < -- > - [0.010904312133789062s]⭅⇦⇦⇦ mousehandler:screen_touch( self = <mousehandler.MouseHandler object at 0x7fb5e0c77588>, tag = 'clickable' ) returned: None
:EventManager(debug): received C++ event named: time-mouse1-up parameters: [14.890185]
:Messenger(debug): sent event: time-mouse1-up sentArgs = [14.890185], taskChain = None
Segmentation fault (core dumped)

So, as you can see not very informative… I don’t have a debug build, this is just installed with pip3. I believe the segfault is happening in this loop:

       while True:
            dt = globalClock.getDt()  # noqa: F821

            cm.cur_world().doPhysics(dt)
           
            taskMgr.step()  # noqa: F821
            time.sleep(1.0 / DEFAULTFPS)

Where cm.cur_world() returns the current working BulletWorld() instance. Each “world” in my app is a tuple of root nodepath, bulletworld and 2d root nodepath. I basically add models to to the various root nodepaths and associated BulletRigidBodyNodes to the associated BulletWorld. I’m trying to then show tooltips on the associated 2d nodepath for each of my “worlds”. I move the camera’s between my worlds when I enter or exit them. Unfortunately, it is the exit to the topmost level that then causes the crash mentioned… I’ll get some code up here later today, but have to run out now.


#5

The reason I think the error occurs in the doPhysics call is because when I comment that line out, the program doesn’t crash. I suspect the isssue is with how I am using Bullet, but will provide code, later on.


#6

Well, I fixed the problem… It seems the problem was tied to model’s being in one root nodepath, and their associated BulletRigidBodyNodes being in a BulletWorld not associated with the root nodepath. This all turned out to be an artifact of my spaghetti code path to create a model and put it in the “world”…


#7

@nate.byrnes can you reproduce the issue with a simple example? Even if you did “something wrong,” Panda should not segfault. If nothing else, Panda should recognize that bad stuff is happening and throw an appropriate error.


#8

Sure, it seems this does the trick (crashing that is):

from direct.showbase.ShowBase import ShowBase
from panda3d.bullet import BulletSphereShape, BulletRigidBodyNode, BulletWorld
from panda3d.core import NodePath
from direct.actor.Actor import Actor


class app(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        model = Actor('models/unknown.egg')
        physics = BulletRigidBodyNode('unknown')
        shape = BulletSphereShape(2.0)
        data = render.attachNewNode(physics)
        model.reparentTo(data)
        world = BulletWorld()
        world.attach(physics)
        world2 = BulletWorld()
        render2 = NodePath('render2')
        camera.reparentTo(render2)
        model.reparentTo(render2)
        world2.attachRigidBody(physics)



if __name__ == '__main__':
    a = app()
    a.run()