I think the use of RBC with multithreaded rendering enabled has a threshold of usefulness. Under some circumstances, it is practically useless and has a bug(Some of the geometry is not rendered due to the viewing angle.).
I started coming up with other tests, here’s a test: where the cubes fall vertically, then disappear (you need to turn the camera).
from panda3d.core import loadPrcFileData, NodePath, Vec3, TransformState, RigidBodyCombiner, DirectionalLight, AmbientLight
from panda3d.bullet import BulletWorld, BulletPlaneShape, BulletRigidBodyNode, BulletBoxShape
loadPrcFileData("", "show-frame-rate-meter #t")
loadPrcFileData("", "threading-model Cull/Draw")
loadPrcFileData("", "sync-video 0")
from direct.showbase.ShowBase import ShowBase
import threading, time
class MyApp(ShowBase):
def __init__(self):
ShowBase.__init__(self)
lens = base.cam.node().getLens()
lens.setNearFar(0.02, 5000000)
alight = AmbientLight('ambientLight')
alight.set_color((0.5, 0.5, 0.5, 1))
ambient_light = NodePath(alight)
ambient_light.reparent_to(render)
render.set_light(ambient_light)
dlight = DirectionalLight('directionalLight')
dlight.set_direction(Vec3(1, 1, -1))
dlight.set_color((0.7, 0.7, 0.7, 1))
directional_light = NodePath(dlight)
directional_light.reparent_to(render)
render.set_light(directional_light)
self.bullet_world = BulletWorld()
self.bullet_world.setGravity((0, 0, -9.81))
shape = BulletPlaneShape((0, 0, 1), 1)
node = BulletRigidBodyNode('Ground')
node.addShape(shape)
self.bullet_world.attachRigidBody(node)
rbc = RigidBodyCombiner("rbc")
rbcnp = NodePath(rbc)
rbcnp.reparentTo(render)
model = loader.loadModel("box.bam")
model.flattenLight()
offset = 0.5
for i in range(4000):
pos = Vec3(0, 0, i+offset)
shape_box = BulletBoxShape((0.5, 0.5, 0.5))
node_box = BulletRigidBodyNode('Box')
node_box.set_transform(TransformState.make_pos(pos))
node_box.setMass(1.0)
node_box.addShape(shape_box)
np = NodePath(node_box)
model.copyTo(np)
np.reparentTo(rbcnp)
self.bullet_world.attachRigidBody(node_box)
offset += 0.5
rbc.collect()
threading.Thread(target = self.update_physics_fix).start()
def update_physics_fix(self):
while True:
framerate = 1/60
self.bullet_world.doPhysics(framerate)
time.sleep(framerate)
app = MyApp()
app.run()
Another test without using RBC, the performance is almost better, there is also no disappearance of cubes.
from panda3d.core import loadPrcFileData, NodePath, Vec3, TransformState, DirectionalLight, AmbientLight
from panda3d.bullet import BulletWorld, BulletPlaneShape, BulletRigidBodyNode, BulletBoxShape
loadPrcFileData("", "show-frame-rate-meter #t")
loadPrcFileData("", "threading-model Cull/Draw")
loadPrcFileData("", "sync-video 0")
from direct.showbase.ShowBase import ShowBase
import threading, time
class MyApp(ShowBase):
def __init__(self):
ShowBase.__init__(self)
lens = base.cam.node().getLens()
lens.setNearFar(0.02, 5000000)
alight = AmbientLight('ambientLight')
alight.set_color((0.5, 0.5, 0.5, 1))
ambient_light = NodePath(alight)
ambient_light.reparent_to(render)
render.set_light(ambient_light)
dlight = DirectionalLight('directionalLight')
dlight.set_direction(Vec3(1, 1, -1))
dlight.set_color((0.7, 0.7, 0.7, 1))
directional_light = NodePath(dlight)
directional_light.reparent_to(render)
render.set_light(directional_light)
self.bullet_world = BulletWorld()
self.bullet_world.setGravity((0, 0, -9.81))
shape = BulletPlaneShape((0, 0, 1), 1)
node = BulletRigidBodyNode('Ground')
node.addShape(shape)
self.bullet_world.attachRigidBody(node)
model = loader.loadModel("box.bam")
model.flattenLight()
offset = 0.5
for i in range(4000):
pos = Vec3(0, 0, i+offset)
shape_box = BulletBoxShape((0.5, 0.5, 0.5))
node_box = BulletRigidBodyNode('Box')
node_box.set_transform(TransformState.make_pos(pos))
node_box.setMass(1.0)
node_box.addShape(shape_box)
np = NodePath(node_box)
model.copyTo(np)
np.reparentTo(render)
self.bullet_world.attachRigidBody(node_box)
offset += 0.5
threading.Thread(target = self.update_physics_fix).start()
def update_physics_fix(self):
while True:
framerate = 1/60
self.bullet_world.doPhysics(framerate)
time.sleep(framerate)
app = MyApp()
app.run()
Another problem with RBC is that it is impossible to add geometry incrementally, it will be expensive because it requires a call to collect()
. In this regard, I came up with such a test, by analogy with the video on YouTube - where they test the physics of Godot. In this case, the cubes do not fly apart, and maximum interaction is obtained.
from panda3d.core import loadPrcFileData, NodePath, Vec3, TransformState, RigidBodyCombiner, DirectionalLight, AmbientLight, TextNode
from panda3d.bullet import BulletWorld, BulletPlaneShape, BulletRigidBodyNode, BulletBoxShape
loadPrcFileData("", "show-frame-rate-meter #t")
loadPrcFileData("", "threading-model Cull/Draw")
loadPrcFileData("", "sync-video 0")
from direct.showbase.ShowBase import ShowBase
import threading, random, time
class MyApp(ShowBase):
def __init__(self):
ShowBase.__init__(self)
alight = AmbientLight('ambientLight')
alight.set_color((0.5, 0.5, 0.5, 1))
ambient_light = NodePath(alight)
ambient_light.reparent_to(render)
render.set_light(ambient_light)
dlight = DirectionalLight('directionalLight')
dlight.set_direction(Vec3(1, 1, -1))
dlight.set_color((0.7, 0.7, 0.7, 1))
directional_light = NodePath(dlight)
directional_light.reparent_to(render)
render.set_light(directional_light)
self.bullet_world = BulletWorld()
self.bullet_world.setGravity((0, 0, -15))
shape = BulletPlaneShape((0, 0, 1), 1)
node = BulletRigidBodyNode('Ground')
node.addShape(shape)
self.bullet_world.attachRigidBody(node)
self.model = loader.loadModel("box.bam")
self.model.flattenLight()
self.body_node_count = 0
self.run_create = True
self.label = TextNode('label')
self.label.set_align(2)
label = NodePath(self.label)
label.set_scale(0.07)
label.setPos(0, 0, 0.8)
label.reparentTo(aspect2d)
self.shape_box = BulletBoxShape((0.5, 0.5, 0.5))
threading.Thread(target = self.create_body_node).start()
threading.Thread(target = self.update_physics_fix).start()
def create_body_node(self):
while self.run_create:
if self.body_node_count < 1000:
node_box = BulletRigidBodyNode('Box')
node_box.set_transform(TransformState.make_pos(Vec3(0, 0, 30)))
node_box.setMass(0.1)
node_box.addShape(self.shape_box)
np = NodePath(node_box)
self.model.copyTo(np)
np.reparentTo(render)
self.bullet_world.attachRigidBody(node_box)
self.body_node_count += 1
self.label.set_text("Count bodies: " + str(self.body_node_count))
else:
self.run_create = False
time.sleep(0.2)
def update_physics_fix(self):
while True:
framerate = 1/60
self.bullet_world.doPhysics(framerate)
time.sleep(framerate)
app = MyApp()
app.run()
@Alexander_krack As an optimization path, you can check hardware instantiation.
I have not experimented with this.
box.bam (1.8 KB)