Panda Bullet

Oh no, I was wrong, my previous issue isn’t solved.
I made an example snippet.

from pandac.PandaModules import *
import direct.directbase.DirectStart
from direct.task import Task
from panda3d.bullet import *

#----------------------------------------
dlight = DirectionalLight('my dlight')
dlnp = render.attachNewNode(dlight)
dlnp.setHpr(0,-20,0)
render.setLight(dlnp)

alight = AmbientLight('my alight')
alight.setColor(VBase4(0.5,0.5,0.5,1))
alnp = render.attachNewNode(alight)
render.setLight(alnp)

scene = loader.loadModel('environment')
scene.reparentTo(render)
scene.setPos(0,200,-10)
#----------------------------------------

bulletworld = BulletWorld()
bulletworld.setGravity(Vec3(0, 0, -9.81))
# render bullet nodes
debugNode = BulletDebugNode('Debug')
debugNode.setVerbose(False)
debugNP = render.attachNewNode(debugNode)
debugNP.show()
debugNP.setShaderOff()
bulletworld.setDebugNode(debugNP.node())
# bullet task
def bulletTask(task):
	global bulletworld
	dt = globalClock.getDt()
	bulletworld.doPhysics(dt)
	return task.cont
taskMgr.add(bulletTask, 'bulletTask')


def createBulletMesh(nodepath, name = ''):
	mesh = BulletTriangleMesh()
	
	# create collision solids from the model geometry
	geomNodeCollection = nodepath.findAllMatches('**/+GeomNode')
	for nodePath in geomNodeCollection:
		geomNode = nodePath.node()
		for i in range(geomNode.getNumGeoms()):
			geom = geomNode.getGeom(i)
			mesh.addGeom(geom)
	shape = BulletTriangleMeshShape(mesh, dynamic = False)
	node = BulletRigidBodyNode(name)
	node.addShape(shape)
	
	return node

bulletscene = createBulletMesh(scene)
bulletsceneNP = render.attachNewNode(bulletscene)
bulletsceneNP.setPos(0,200,-10)
bulletworld.attachRigidBody(bulletscene)

def addBox(positionx, positiony, positionz, relative = render):
	boxshape = BulletBoxShape(Vec3(1, 1, 1))
 
	boxnode = BulletRigidBodyNode('Box')
	boxnode.setMass(1.0)
	boxnode.addShape(boxshape)
	#boxnode.setDisableDeactivation(True)
	 
	boxnp = render.attachNewNode(boxnode)
	boxnp.setPos(base.cam, positionx, positiony, positionz)
	
	visiblebox = loader.loadModel('box')
	visiblebox.setPos(-1,-1,-1)
	visiblebox.setScale(2)
	visiblebox.reparentTo(boxnp)
	 
	bulletworld.attachRigidBody(boxnode)
	return boxnode, visiblebox
base.accept('enter', addBox, extraArgs = [0, 30, 2, base.cam])

def shoot():
	sphereshape = BulletSphereShape(10)
 
	spherenode = BulletRigidBodyNode('Sphere')
	spherenode.setMass(0)
	spherenode.addShape(sphereshape)
	spherenode.setKinematic(True)
	 
	spherenp = render.attachNewNode(spherenode)
	spherenp.setPos(base.cam, 0,0,0)
	 
	bulletworld.attachRigidBody(spherenode)
	
	spherenp.setPos(base.camera.getPos())
	spherenp.setHpr(base.camera.getHpr())
	spherenp.reparentTo(render)
	
	def shootTask(bullet, task):
		if task.frame < 24:
			bullet.setY(bullet, 1)
			return task.cont
		else:
			spherenp.removeNode()
			bulletworld.removeRigidBody(spherenode)
			return task.done
	taskMgr.add(shootTask, 'shootTask', extraArgs = [spherenp], appendTask = True)

base.accept('mouse1', shoot)


run()

You should look at lines 67 and 87. 87 is where I set the spheres (bullets) to kinematic, which doesn’t change anything. setDisableDeactivation() (line 67) works, but it might be a performance issue later. You said that other nodes which collide with “sleeping” ones will wake them up, that’s why I think setDisableDeactivation() isn’t the best solution.

Didn’t have a closer look at your code, but you don’t want to use a kinematic body for bullets, especially not the way you do it (the bullet’s speed will be dependent on the framerate). Use plain dynamic rigid bodies, and give them an initial velocity, and maybe enable CCD on the bullet. Have a look at the CCD sample.

Eh, just found out that bullet can already load collada physics data, so it should not be too hard to link incoming collada loader with bullet :slight_smile:

collada.org/mediawiki/index. … et_physics

The COLLADA loader built-in with Bullet is of no use to us. We need to create Panda3D scene graph nodes, not standalone Bullet objects! Also Bullet is not the only physics module provided by Panda3D, it is merely an optional addon. The Panda3D COLLADA loader should not be dependent on the Panda3D Bullet module!

We will wait until the main COLLADA loader and Bullet are halfway stable (1.8.0), then make up our minds on how to create plugable addon loaders for physics. I think rdb already has some ideas here, maybe an interface provided by the addon module (i.e. Panda3D Bullet) which registers with the main COLLADA loader and has interfaces for certain COLLADA nodes. This way the addon module is dependent on the COLLADA loader and not the other way round. Anyway, one step after the other.

A small API change in CVS HEAD: The method “BulletDebugNode.setVerbose(bool)” is replaced by some methods to turn on and off individual components of the debug visualisation

    #self.debugNP.node()setVerbose(True) # removed.
    self.debugNP.node().showWireframe(True) # added
    self.debugNP.node().showConstraints(True) # added
    self.debugNP.node().showBoundingBoxes(False) # added
    self.debugNP.node().showNormals(True) # added

I found a hack to disable the drawing of normals for triangle meshes. It works by filtering lines with color (1,1,0), so everything yellow is not drawn when setting showNormals(True). It’s a hack, but there is no other way to disable drawing the triangle normals (besides modifying the Bullet source code).

I just thought I’d toss this in here, because it seems that enn0x has to repeat some things that are already nicely laid out in the bullet section of the manual.

http://www.panda3d.org/manual/index.php/Using_Bullet_with_Panda3D

It’s not in the manual table of contents yet, but he’s put a lot of really good information and example code in there. You guys should take a look if you haven’t already.

I just checked in another small API change, regarding linear and angular limits for BulletGenericSonstraints. I also updated the samples. For example there is a separate sample for each constraint now.

http://enn0x.p3dp.com/samples.zip

I made some illustrations of constraints, I think it would be nice to have such illustrations in the manual.



Thanks enn0x for your work on this. I am really enjoying getting to grips with Bullet.

I am trying to measure how hard an impact is in order to determine whether damage should be done to the player’s vehicle. From my reading on the web I understand I need to use the “getAppliedImpulse” method on a contact point.

I have a task that checks for collisions with the vehicle’s chassis shape. Collisions are detected correctly, but the impulse is always zero (except as the simulation begins, where the impulse is 1.54142831076e-44 for while, but that is essentially zero).

In writing this I realise that it may be a mistake to check for collisions in a task, since the physics simulation runs faster than panda3d’s update task, I would still expect to get some non-zero impulses though.

Can anybody give any suggestions?

Sorry, but can you help me with something, following code wont update model position to with bullet’s node position (it just sits in place, and bullet node is flying around).

def addModelToBulletNode(btNode,modelPath):
    model = loader.loadModel(modelPath)
    NP = render.attachNewNode(btNode)
    model.reparentTo(NP)
    return NP

Example call is

self.NP = addModelToBulletNode("smiley",self.btNode)

in this case, btNode is BulletRigidBodyNode.

I want to write wrappers, and i keep looking at old non-wrapped code and cant figure why with this wrapped it wont work…

note, using “old” version of API

note2. following works if i call it from same position
as from where i call addModelToBulletNode

self.model = loader.loadModel("smiley")
self.NP = render.attachNewNode(self.btNode)
self.model.reparentTo(self.NP)

You are calling your method with:

self.NP = addModelToBulletNode("smiley",self.btNode)

Effectively passing a string as btNode and therefore the method does

NP = render.attachNewNode("smiley")

Shouldn’t that be something like attachNewNode(BulletRigidBodyNode(“smiley”))?

Yes, thank you very much, so stupid of me, i was passing arguments in wrong order…
Sorry… I should really start testing arguments for types.

Thank you very much. I will rewrite the maunal page about Bullet constraints, and use this images for the page. Just to make sure: You have created the images, and there is no copyright which limits usage for the Panda3D manual?

Out of the box I have no explanation for this. I did a quick google and found that others (not related to Panda3D) had similar effects. I have to investigate, but this might take a few days.

Yes

I can upload the project file if needed.
I didn’t make the rest mainly because I don’t understand how they work myself. Let me know if I can make other illustrations like this.

BTW, in my previous posts I didn’t want to make bullets, but a wind blow effect. My question is, kinematic bodies can’t collide with sleeping dynamic bodies? I think you said that they will be “awaken” before, but I wasn’t able to achieve this in my snippet.

Kinematic bodies do collide with sleeping bodies of any type. But kinematic bodies can be deactivated too (“put to sleep”) if they don’t move for some time. And two sleeping bodies won’t collide.

You can go two ways:

  1. Disable deactivation for the kinematic body
    bodyNP.node().setKinematic(True)
    bodyNP.node().setDeactivationEnabled(False)

2.) Wake up the kinematic body each time it moves:

  def processInput(self, dt):
    delta = Vec3(0, 0, 0)

    if inputState.isSet('forward'): delta.setY( 1.0)
    if inputState.isSet('reverse'): delta.setY(-1.0)
    if inputState.isSet('left'):    delta.setX(-1.0)
    if inputState.isSet('right'):   delta.setX( 1.0)

    self.kinematicNP.setPos(self.kinematicNP, delta * dt)

    if delta != Vec3.zero():
      self.kinematicNP.node().setActive(True, True)

We could add code which automatically wakes up a sleeping body if the transform is changed.

I had no idea kinematic bodies could be deactivated as well, thanks.
BTW, I think it would be a good idea to mention about the automatic deactivation of bodies somewhere in the manual.

Enn0x, or rdb/etc

Will the panda3d sdk include the bullet sample programs?
I feel that they would add a lot to end users downloading the sdk, and that they probably belong there, as apposed to somewhere else.

Otherwise, enn0x if you would be okay updating your original post on the first page, with the download link to the latest revision of the sample programs?

I find it very difficult to keep track of them inside this thread, is all :smiley:

I love you work,
thank you again,
kind sir,
~powerpup118

I’ve just got to say Thank You again, enn0x and all the folks that build Panda. A few minutes ago, I got the dumper part of a dumper truck (almost*) working. Technically, I really need to work for math exams in september, but developing with Panda Bullet is so much fun - implementing one feature after another without hitting major obstacles.
So, a big thumbs up to you!

Now for the giving-back-part: What would be best? Can I simply go ahead and write something up for BulletVehicle (in bulletVehicle.I) and then diff the file and send it somewhere?

[*] The dumper lifts on keypress, but falls down since the HingeConstraint’s angular motor is turned off. Need to invent some hydraulics there.
[1] panda3d.org/reference/devel … ce1bcbdedf

Can anyone explain me the cone twist constraint? I read the manual page, the info in Bullet user manual and also ran the sample code, but I don’t understand what it does. I used to think the cone apex was one of the nodes and the other node would rotate inside the cone shape.