samples: Add Bullet Physics sample programs
Closes #248 [skip ci] Co-authored-by: Sebastian Hoffmann <TheCheapestPixels@gmail.com>
179
samples/bullet-physics/01_basics.py
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#from panda3d.core import load_prc_file_data
|
||||
#load_prc_file_data('', 'bullet-additional-damping true')
|
||||
#load_prc_file_data('', 'bullet-additional-damping-linear-factor 0.005')
|
||||
#load_prc_file_data('', 'bullet-additional-damping-angular-factor 0.01')
|
||||
#load_prc_file_data('', 'bullet-additional-damping-linear-threshold 0.01')
|
||||
#load_prc_file_data('', 'bullet-additional-damping-angular-threshold 0.01')
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
force = render.get_relative_vector(self.boxNP, force)
|
||||
torque = render.get_relative_vector(self.boxNP, torque)
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
#self.world.doPhysics(dt)
|
||||
self.world.do_physics(dt, 5, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world.remove(self.groundNP.node())
|
||||
self.world.remove(self.boxNP.node())
|
||||
self.world = None
|
||||
self.debugNP = None
|
||||
self.groundNP = None
|
||||
self.boxNP = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(True)
|
||||
|
||||
#self.debugNP.show_tight_bounds()
|
||||
#self.debugNP.show_bounds()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity(0, 0, -9.81)
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground (static)
|
||||
shape = BulletPlaneShape((0, 0, 1), 1)
|
||||
|
||||
self.groundNP = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
self.groundNP.node().add_shape(shape)
|
||||
self.groundNP.set_pos(0, 0, -2)
|
||||
self.groundNP.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(self.groundNP.node())
|
||||
|
||||
# Box (dynamic)
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
self.boxNP = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
self.boxNP.node().set_mass(1.0)
|
||||
self.boxNP.node().add_shape(shape)
|
||||
self.boxNP.set_pos(0, 0, 2)
|
||||
#self.boxNP.set_scale(2, 1, 0.5)
|
||||
self.boxNP.set_collide_mask(BitMask32.all_on())
|
||||
#self.boxNP.node().set_deactivation_enabled(False)
|
||||
|
||||
self.world.attach(self.boxNP.node())
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.clear_model_nodes()
|
||||
visualNP.reparent_to(self.boxNP)
|
||||
|
||||
# Bullet nodes should survive a flatten operation!
|
||||
#self.worldNP.flatten_strong()
|
||||
#render.ls()
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
298
samples/bullet-physics/02_shapes.py
Normal file
@@ -0,0 +1,298 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#from panda3d.core import load_prc_file_data
|
||||
#load_prc_file_data('', 'bullet-enable-contact-events true')
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletCapsuleShape
|
||||
from panda3d.bullet import BulletCylinderShape
|
||||
from panda3d.bullet import BulletConeShape
|
||||
from panda3d.bullet import BulletConvexHullShape
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import BulletMultiSphereShape
|
||||
from panda3d.bullet import XUp
|
||||
from panda3d.bullet import YUp
|
||||
from panda3d.bullet import ZUp
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
#pairs = [(mf.getNode0().getName(),
|
||||
# mf.getNode1().getName())
|
||||
# for mf in self.world.getManifolds() if mf.getNumManifoldPoints() > 0]
|
||||
#print pairs
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
#def do_added(self, node1, node2):
|
||||
# print('added:', node1.getName(), node2.getName())
|
||||
|
||||
#def do_destroyed(self, node1, node2):
|
||||
# print('destroyed:', node1.getName(), node2.getName())
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(True)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Plane (static)
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Box (dynamic)
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.boxNP = np # For applying force & torque
|
||||
|
||||
#np.node().notifyCollisions(True)
|
||||
#self.accept('bullet-contact-added', self.do_added)
|
||||
#self.accept('bullet-contact-destroyed', self.do_destroyed)
|
||||
|
||||
# Sphere (dynamic)
|
||||
shape = BulletSphereShape(0.6)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Sphere'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(-4, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Cone (dynamic)
|
||||
shape = BulletConeShape(0.6, 1.2, ZUp)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Cone'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(4, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Capsule (dynamic)
|
||||
shape = BulletCapsuleShape(0.5, 1.0, ZUp)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Capsule'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 4, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Cyliner (dynamic)
|
||||
shape = BulletCylinderShape(0.7, 1.5, ZUp)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Cylinder'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(4, 4, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Convex (dynamic)
|
||||
shape = BulletConvexHullShape()
|
||||
shape.add_point(LPoint3(1, 1, 2))
|
||||
shape.add_point(LPoint3(0, 0, 0))
|
||||
shape.add_point(LPoint3(2, 0, 0))
|
||||
shape.add_point(LPoint3(0, 2, 0))
|
||||
shape.add_point(LPoint3(2, 2, 0))
|
||||
|
||||
# Another way to create the convex hull shape:
|
||||
#shape = BulletConvexHullShape()
|
||||
#shape.add_array([
|
||||
# LPoint3(1, 1, 2),
|
||||
# LPoint3(0, 0, 0),
|
||||
# LPoint3(2, 0, 0),
|
||||
# LPoint3(0, 2, 0),
|
||||
# LPoint3(2, 2, 0),
|
||||
#])
|
||||
|
||||
# Yet another way to create the convex hull shape:
|
||||
#geom = loader.load_model('models/box.egg')\
|
||||
# .find_all_matches('**/+GeomNode')\
|
||||
# .get_path(0)\
|
||||
# .node()\
|
||||
# .get_geom(0)
|
||||
#shape = BulletConvexHullShape()
|
||||
#shape.add_geom(geom)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Convex'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(-4, 4, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Mesh (static)
|
||||
p0 = LPoint3(-10, -10, 0)
|
||||
p1 = LPoint3(-10, 10, 0)
|
||||
p2 = LPoint3(10, -10, 0)
|
||||
p3 = LPoint3(10, 10, 0)
|
||||
mesh = BulletTriangleMesh()
|
||||
mesh.add_triangle(p0, p1, p2)
|
||||
mesh.add_triangle(p1, p2, p3)
|
||||
shape = BulletTriangleMeshShape(mesh, dynamic=False)
|
||||
|
||||
# Another way to create the triangle mesh shape:
|
||||
#geom = loader.load_model('models/box.egg')\
|
||||
# .find_all_matches('**/+GeomNode')\
|
||||
# .get_path(0)\
|
||||
# .node()\
|
||||
# .get_geom(0)
|
||||
#mesh = BulletTriangleMesh()
|
||||
#mesh.add_geom(geom)
|
||||
#shape = BulletTriangleMeshShape(mesh, dynamic=False)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Mesh'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 0.1)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# MultiSphere
|
||||
points = [LPoint3(-1, 0, 0), LPoint3(0, 0, 0), LPoint3(1, 0, 0)]
|
||||
radii = [.4, .8, .6]
|
||||
shape = BulletMultiSphereShape(points, radii)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('MultiSphere'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(8, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
187
samples/bullet-physics/03_heightfield.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import Filename
|
||||
from panda3d.core import PNMImage
|
||||
from panda3d.core import GeoMipTerrain
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletHeightfieldShape
|
||||
from panda3d.bullet import ZUp
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('x', self.toggle_heightfield)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def toggle_heightfield(self):
|
||||
self.hf.set_debug_enabled(not self.hf.is_debug_enabled())
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
self.terrain.update()
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_normals(True)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box (dynamic)
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.boxNP = np # For applying force & torque
|
||||
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.clear_model_nodes()
|
||||
visualNP.reparent_to(self.boxNP)
|
||||
|
||||
# Heightfield (static)
|
||||
height = 8.0
|
||||
|
||||
img = PNMImage(Filename('models/elevation.png'))
|
||||
shape = BulletHeightfieldShape(img, height, ZUp)
|
||||
shape.set_use_diamond_subdivision(True)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Heightfield'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 0)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.hf = np.node() # To enable/disable debug visualisation
|
||||
|
||||
self.terrain = GeoMipTerrain('terrain')
|
||||
self.terrain.set_heightfield(img)
|
||||
|
||||
self.terrain.set_block_size(32)
|
||||
self.terrain.set_near(50)
|
||||
self.terrain.set_far(100)
|
||||
self.terrain.set_focal_point(base.camera)
|
||||
|
||||
rootNP = self.terrain.get_root()
|
||||
rootNP.reparent_to(render)
|
||||
rootNP.set_sz(8.0)
|
||||
|
||||
offset = img.get_x_size() / 2.0 - 0.5
|
||||
rootNP.set_pos(-offset, -offset, -height / 2.0)
|
||||
|
||||
self.terrain.generate()
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
202
samples/bullet-physics/04_filtering.py
Normal file
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), -1)
|
||||
|
||||
mask = BitMask32(0x0f)
|
||||
print('ground: ', mask)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_collide_mask(mask)
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
## Box 1
|
||||
#shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
#mask = BitMask32.allOff()
|
||||
#print('box-1: ', mask)
|
||||
|
||||
#np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-1'))
|
||||
#np.node().set_mass(1.0)
|
||||
#np.node().add_shape(shape)
|
||||
#np.set_pos(-6, 0, 4)
|
||||
#np.set_collide_mask(mask)
|
||||
|
||||
#self.world.attach(np.node())
|
||||
|
||||
## Box 2
|
||||
#shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
#mask = BitMask32.bit(0)
|
||||
#print('box-2: ', mask)
|
||||
|
||||
#np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-2'))
|
||||
#np.node().set_mass(1.0)
|
||||
#np.node().add_shape(shape)
|
||||
#np.set_pos(-2, 0, 4)
|
||||
#np.set_collide_mask(mask)
|
||||
|
||||
#self.world.attach(np.node())
|
||||
|
||||
## Box 3
|
||||
#shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
#mask = BitMask32.bit(2)
|
||||
#print('box-3: ', mask)
|
||||
|
||||
#np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-3'))
|
||||
#np.node().set_mass(1.0)
|
||||
#np.node().add_shape(shape)
|
||||
#np.set_pos(2, 0, 4)
|
||||
#np.set_collide_mask(mask)
|
||||
|
||||
#self.world.attach(np.node())
|
||||
|
||||
# Box 4
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
mask = BitMask32(0x3)
|
||||
print('box-4: ', mask)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-4'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(6, 0, 4)
|
||||
np.set_collide_mask(mask)
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.boxNP = np
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.reparent_to(self.boxNP)
|
||||
|
||||
#self.boxNP.set_collide_mask(BitMask32.allOff())
|
||||
#self.world.remove(self.boxNP.node())
|
||||
#self.world.attach(self.boxNP.node())
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
187
samples/bullet-physics/05_filtering_extended.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from panda3d.core import load_prc_file_data
|
||||
load_prc_file_data('', 'bullet-filter-algorithm groups-mask')
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('1', self.do_select, [0,])
|
||||
self.accept('2', self.do_select, [1,])
|
||||
self.accept('3', self.do_select, [2,])
|
||||
self.accept('4', self.do_select, [3,])
|
||||
self.accept('5', self.do_select, [4,])
|
||||
self.accept('6', self.do_select, [5,])
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_select(self, i):
|
||||
self.boxNP = self.boxes[i]
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), -1)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_collide_mask(BitMask32.bit(0))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Boxes
|
||||
self.boxes = [None,]*6
|
||||
|
||||
for i in range(6):
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-1'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.boxes[i] = np
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.reparent_to(np)
|
||||
|
||||
self.boxes[0].set_pos(-3, -3, 0)
|
||||
self.boxes[1].set_pos( 0, -3, 0)
|
||||
self.boxes[2].set_pos( 3, -3, 0)
|
||||
self.boxes[3].set_pos(-3, 3, 0)
|
||||
self.boxes[4].set_pos( 0, 3, 0)
|
||||
self.boxes[5].set_pos( 3, 3, 0)
|
||||
|
||||
self.boxes[0].set_collide_mask(BitMask32.bit(1))
|
||||
self.boxes[1].set_collide_mask(BitMask32.bit(2))
|
||||
self.boxes[2].set_collide_mask(BitMask32.bit(3))
|
||||
self.boxes[3].set_collide_mask(BitMask32.bit(1))
|
||||
self.boxes[4].set_collide_mask(BitMask32.bit(2))
|
||||
self.boxes[5].set_collide_mask(BitMask32.bit(3))
|
||||
|
||||
self.boxNP = self.boxes[0]
|
||||
|
||||
self.world.set_group_collision_flag(0, 1, True)
|
||||
self.world.set_group_collision_flag(0, 2, True)
|
||||
self.world.set_group_collision_flag(0, 3, True)
|
||||
|
||||
self.world.set_group_collision_flag(1, 1, False)
|
||||
self.world.set_group_collision_flag(1, 2, True)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
167
samples/bullet-physics/06_filtering_python.py
Normal file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from panda3d.core import load_prc_file_data
|
||||
load_prc_file_data('', 'bullet-filter-algorithm callback')
|
||||
|
||||
import sys
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import PythonCallbackObject
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
self.world.set_filter_callback(PythonCallbackObject(self.filter))
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), -1)
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_python_tag('foo', 2)
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Box 1
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-1'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(3, 0, 4)
|
||||
np.set_python_tag('foo', 0)
|
||||
self.world.attach(np.node())
|
||||
self.boxNP = np
|
||||
|
||||
# Box 2
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box-2'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(-3, 0, 4)
|
||||
np.set_python_tag('foo', -1)
|
||||
self.world.attach(np.node())
|
||||
|
||||
def filter(self, cb_data):
|
||||
"""
|
||||
cb_data is of type BulletFilterCallbackData.
|
||||
A rather silly collision filtering algorithm. We assume every node
|
||||
has the Python tag 'foo' set, and that the value of this tag is integer.
|
||||
Then we add the values and if the result is greater than zero we want
|
||||
the nodes to collide.
|
||||
"""
|
||||
x1 = cb_data.get_node_0().get_python_tag('foo')
|
||||
x2 = cb_data.get_node_1().get_python_tag('foo')
|
||||
cb_data.set_collide(x1 + x2 > 0)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
195
samples/bullet-physics/07_raycast.py
Normal file
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletConeShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import ZUp
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
self.raycast()
|
||||
return task.cont
|
||||
|
||||
def raycast(self):
|
||||
pFrom = LPoint3(-4, 0, 0.5)
|
||||
pTo = LPoint3(4, 0, 0.5)
|
||||
#pTo = pFrom + LVector3(1, 0, 0) * 99999
|
||||
|
||||
# Raycast for closest hit
|
||||
result = self.world.ray_test_closest(pFrom, pTo)
|
||||
print(result.has_hit(), \
|
||||
result.get_hit_fraction(), \
|
||||
result.get_node(), \
|
||||
result.get_hit_pos(), \
|
||||
result.get_hit_normal())
|
||||
|
||||
# Raycast for all hits
|
||||
#result = self.world.ray_test_all(pFrom, pTo)
|
||||
#print result.has_hits(), \
|
||||
# result.get_closest_hit_fraction(), \
|
||||
# result.get_num_hits()
|
||||
#print [hit.get_hit_pos() for hit in result.get_hits()]
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 0)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Box
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 4)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.boxNP = np
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.reparent_to(self.boxNP)
|
||||
|
||||
# Sphere
|
||||
shape = BulletSphereShape(0.6)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Sphere'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(3, 0, 4)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Cone
|
||||
shape = BulletConeShape(0.6, 1.0)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Cone'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(6, 0, 4)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
212
samples/bullet-physics/08_contacts.py
Normal file
@@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#from panda3d.core import load_prc_file_data
|
||||
#load_prc_file_data('', 'bullet-enable-contact-events true')
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import NodePath
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
if not self.box:
|
||||
return
|
||||
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.box.set_active(True)
|
||||
self.box.apply_central_force(force)
|
||||
self.box.apply_torque(torque)
|
||||
|
||||
def process_contacts(self):
|
||||
if not self.box or not self.sphere:
|
||||
return
|
||||
|
||||
result = self.world.contact_test_pair(self.box, self.sphere)
|
||||
#result = self.world.contact_test(self.box)
|
||||
|
||||
#print '-->', result.get_num_contacts()
|
||||
for contact in result.get_contacts():
|
||||
cp = contact.get_manifold_point()
|
||||
node0 = contact.get_node0()
|
||||
node1 = contact.get_node1()
|
||||
print(node0.get_name(), node1.get_name(), cp.get_local_point_a())
|
||||
|
||||
#print(contact.get_node0(), cp.get_position_world_on_a())
|
||||
#print(contact.get_idx0(), contact.get_idx1(), \
|
||||
# contact.get_part_id0(), contact.get_part_id1())
|
||||
|
||||
self.remove_node(node1)
|
||||
|
||||
def remove_node(self, node):
|
||||
self.world.remove(node)
|
||||
if node == self.sphere: self.sphere = None
|
||||
if node == self.box: self.box = None
|
||||
np = NodePath(node)
|
||||
np.remove_node()
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
self.process_contacts()
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
#def on_contact_added(self, node1, node2):
|
||||
# print('contact added:', node1, node2)
|
||||
|
||||
#def on_contact_destroyed(self, node1, node2):
|
||||
# print('contact destroyed:', node1, node2)
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Plane
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Box
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.node().set_deactivation_enabled(False)
|
||||
np.set_pos(2, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.reparent_to(np)
|
||||
|
||||
self.box = np.node()
|
||||
|
||||
# Sphere
|
||||
shape = BulletSphereShape(0.6)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Sphere'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(-2, 0, 4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.sphere = np.node()
|
||||
|
||||
## Enable contact reporting
|
||||
#self.accept('bullet-contact-added', self.on_contact_added)
|
||||
#self.accept('bullet-contact-destroyed', self.on_contact_destroyed)
|
||||
#self.box.notify_collisions(True)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
177
samples/bullet-physics/09_ccd.py
Normal file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#from panda3d.core import load_prc_file_data
|
||||
#load_prc_file_data('', 'bullet-solver-iterations 20')
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import get_model_path
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -40, 10)
|
||||
base.cam.look_at(0, 0, 5)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('1', self.do_shoot, [True])
|
||||
self.accept('2', self.do_shoot, [False])
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_shoot(self, ccd):
|
||||
# Get from/to points from mouse click
|
||||
pMouse = base.mouseWatcherNode.get_mouse()
|
||||
pFrom = LPoint3()
|
||||
pTo = LPoint3()
|
||||
base.camLens.extrude(pMouse, pFrom, pTo)
|
||||
|
||||
pFrom = render.get_relative_point(base.cam, pFrom)
|
||||
pTo = render.get_relative_point(base.cam, pTo)
|
||||
|
||||
# Calculate initial velocity
|
||||
v = pTo - pFrom
|
||||
v.normalize()
|
||||
v *= 10000.0
|
||||
|
||||
# Create bullet
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
body = BulletRigidBodyNode('Bullet')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(2.0)
|
||||
bodyNP.node().set_linear_velocity(v)
|
||||
bodyNP.set_pos(pFrom)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
if ccd:
|
||||
bodyNP.node().set_ccd_motion_threshold(1e-7)
|
||||
bodyNP.node().set_ccd_swept_sphere_radius(0.50)
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Remove the bullet again after 1 second
|
||||
taskMgr.do_method_later(1, self.do_remove, 'doRemove',
|
||||
extraArgs=[bodyNP], appendTask=True)
|
||||
|
||||
def do_remove(self, bulletNP, task):
|
||||
self.world.remove(bulletNP.node())
|
||||
return task.done
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
self.worldNP = None
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
body = BulletRigidBodyNode('Ground')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_pos(0, 0, -1)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Some boxes
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
for i in range(10):
|
||||
for j in range(10):
|
||||
x = i - 5.0
|
||||
y = 0.0
|
||||
z = j - 0.5
|
||||
|
||||
body = BulletRigidBodyNode('Box-{}-{}'.format(i, j))
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.set_pos(x, y, z)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
190
samples/bullet-physics/10_hinge_constraint.py
Normal file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletHingeConstraint
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 5)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('enter', self.do_shoot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_shoot(self):
|
||||
# Get from/to points from mouse click
|
||||
pMouse = base.mouseWatcherNode.get_mouse()
|
||||
pFrom = LPoint3()
|
||||
pTo = LPoint3()
|
||||
base.camLens.extrude(pMouse, pFrom, pTo)
|
||||
|
||||
pFrom = render.get_relative_point(base.cam, pFrom)
|
||||
pTo = render.get_relative_point(base.cam, pTo)
|
||||
|
||||
# Calculate initial velocity
|
||||
v = pTo - pFrom
|
||||
v.normalize()
|
||||
v *= 100.0
|
||||
|
||||
# Create bullet
|
||||
shape = BulletSphereShape(0.3)
|
||||
body = BulletRigidBodyNode('Bullet')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_linear_velocity(v)
|
||||
bodyNP.node().set_ccd_motion_threshold(1e-7);
|
||||
bodyNP.node().set_ccd_swept_sphere_radius(0.50);
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(pFrom)
|
||||
|
||||
visNP = loader.load_model('models/ball.egg')
|
||||
visNP.set_scale(0.8)
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Remove the bullet again after 2 seconds
|
||||
taskMgr.do_method_later(2, self.do_remove, 'doRemove',
|
||||
extraArgs=[bodyNP], appendTask=True)
|
||||
|
||||
def do_remove(self, bodyNP, task):
|
||||
self.world.remove(bodyNP.node())
|
||||
bodyNP.remove_node()
|
||||
return task.done
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.worldNP.remove_node()
|
||||
self.worldNP = None
|
||||
self.world = None
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(False)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box A
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyA = BulletRigidBodyNode('Box A')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyA)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(-2, 0, 1)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyA)
|
||||
|
||||
# Box B
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyB = BulletRigidBodyNode('Box B')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyB)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(2, 0, 1)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyB)
|
||||
|
||||
# Hinge
|
||||
pivotA = (2, 0, 0)
|
||||
pivotB = (-4, 0, 0)
|
||||
axisA = (0, 0, 1)
|
||||
axisB = (0, 0, 1)
|
||||
|
||||
hinge = BulletHingeConstraint(bodyA, bodyB, pivotA, pivotB, axisA, axisB, True)
|
||||
hinge.set_debug_draw_size(2.0)
|
||||
hinge.set_limit(-90, 120, softness=0.9, bias=0.3, relaxation=1.0)
|
||||
self.world.attach(hinge)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
191
samples/bullet-physics/11_slider_constraint.py
Normal file
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletSliderConstraint
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 5)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('enter', self.do_shoot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_shoot(self):
|
||||
# Get from/to points from mouse click
|
||||
pMouse = base.mouseWatcherNode.get_mouse()
|
||||
pFrom = LPoint3()
|
||||
pTo = LPoint3()
|
||||
base.camLens.extrude(pMouse, pFrom, pTo)
|
||||
|
||||
pFrom = render.get_relative_point(base.cam, pFrom)
|
||||
pTo = render.get_relative_point(base.cam, pTo)
|
||||
|
||||
# Calculate initial velocity
|
||||
v = pTo - pFrom
|
||||
v.normalize()
|
||||
v *= 100.0
|
||||
|
||||
# Create bullet
|
||||
shape = BulletSphereShape(0.3)
|
||||
body = BulletRigidBodyNode('Bullet')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_linear_velocity(v)
|
||||
bodyNP.node().set_ccd_motion_threshold(1e-7);
|
||||
bodyNP.node().set_ccd_swept_sphere_radius(0.50);
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(pFrom)
|
||||
|
||||
visNP = loader.load_model('models/ball.egg')
|
||||
visNP.set_scale(0.8)
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Remove the bullet again after 2 seconds
|
||||
taskMgr.do_method_later(2, self.do_remove, 'doRemove',
|
||||
extraArgs=[bodyNP], appendTask=True)
|
||||
|
||||
def do_remove(self, bodyNP, task):
|
||||
self.world.remove(bodyNP.node())
|
||||
bodyNP.remove_node()
|
||||
return task.done
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.worldNP.remove_node()
|
||||
self.worldNP = None
|
||||
self.world = None
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(False)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box A
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyA = BulletRigidBodyNode('Box A')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyA)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(-3, 0, 4)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyA)
|
||||
|
||||
# Box B
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyB = BulletRigidBodyNode('Box B')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyB)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(0, 0, 0)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyB)
|
||||
|
||||
# Slider
|
||||
frameA = TransformState.make_pos_hpr((2, 0, 0), (0, 0, 45))
|
||||
frameB = TransformState.make_pos_hpr((0, -3, 0), (0, 0, 0))
|
||||
|
||||
slider = BulletSliderConstraint(bodyA, bodyB, frameA, frameB, True)
|
||||
slider.set_debug_draw_size(2.0)
|
||||
slider.set_lower_linear_limit(0)
|
||||
slider.set_upper_linear_limit(6)
|
||||
slider.set_lower_angular_limit(-60)
|
||||
slider.set_upper_angular_limit(60)
|
||||
self.world.attach(slider)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
189
samples/bullet-physics/12_spherical_constraint.py
Normal file
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletSphericalConstraint
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 5)
|
||||
base.cam.look_at(0, 0, 5)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('enter', self.do_shoot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_shoot(self):
|
||||
# Get from/to points from mouse click
|
||||
pMouse = base.mouseWatcherNode.get_mouse()
|
||||
pFrom = LPoint3()
|
||||
pTo = LPoint3()
|
||||
base.camLens.extrude(pMouse, pFrom, pTo)
|
||||
|
||||
pFrom = render.get_relative_point(base.cam, pFrom)
|
||||
pTo = render.get_relative_point(base.cam, pTo)
|
||||
|
||||
# Calculate initial velocity
|
||||
v = pTo - pFrom
|
||||
v.normalize()
|
||||
v *= 100.0
|
||||
|
||||
# Create bullet
|
||||
shape = BulletSphereShape(0.3)
|
||||
body = BulletRigidBodyNode('Bullet')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_linear_velocity(v)
|
||||
bodyNP.node().set_ccd_motion_threshold(1e-7);
|
||||
bodyNP.node().set_ccd_swept_sphere_radius(0.50);
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(pFrom)
|
||||
|
||||
visNP = loader.load_model('models/ball.egg')
|
||||
visNP.set_scale(0.8)
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Remove the bullet again after 2 seconds
|
||||
taskMgr.do_method_later(2, self.do_remove, 'doRemove',
|
||||
extraArgs=[bodyNP], appendTask=True)
|
||||
|
||||
def do_remove(self, bodyNP, task):
|
||||
self.world.remove(bodyNP.node())
|
||||
bodyNP.remove_node()
|
||||
return task.done
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.worldNP.remove_node()
|
||||
self.worldNP = None
|
||||
self.world = None
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(False)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box A
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyA = BulletRigidBodyNode('Box A')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyA)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(-1, 0, 4)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyA)
|
||||
|
||||
# Box B
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyB = BulletRigidBodyNode('Box B')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyB)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.node().setLinearDamping(0.6)
|
||||
bodyNP.node().setAngularDamping(0.6)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(2, 0, 0)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyB)
|
||||
|
||||
# Spherical Constraint
|
||||
pivotA = (2, 0, 0)
|
||||
pivotB = (0, 0, 4)
|
||||
|
||||
joint = BulletSphericalConstraint(bodyA, bodyB, pivotA, pivotB)
|
||||
joint.set_debug_draw_size(2.0)
|
||||
self.world.attach(joint)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
188
samples/bullet-physics/13_cone_twist_constraint.py
Normal file
@@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletConeTwistConstraint
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 5)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('enter', self.do_shoot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_shoot(self):
|
||||
# Get from/to points from mouse click
|
||||
pMouse = base.mouseWatcherNode.get_mouse()
|
||||
pFrom = LPoint3()
|
||||
pTo = LPoint3()
|
||||
base.camLens.extrude(pMouse, pFrom, pTo)
|
||||
|
||||
pFrom = render.get_relative_point(base.cam, pFrom)
|
||||
pTo = render.get_relative_point(base.cam, pTo)
|
||||
|
||||
# Calculate initial velocity
|
||||
v = pTo - pFrom
|
||||
v.normalize()
|
||||
v *= 100.0
|
||||
|
||||
# Create bullet
|
||||
shape = BulletSphereShape(0.3)
|
||||
body = BulletRigidBodyNode('Bullet')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_linear_velocity(v)
|
||||
bodyNP.node().set_ccd_motion_threshold(1e-7);
|
||||
bodyNP.node().set_ccd_swept_sphere_radius(0.50);
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(pFrom)
|
||||
|
||||
visNP = loader.load_model('models/ball.egg')
|
||||
visNP.set_scale(0.8)
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Remove the bullet again after 2 seconds
|
||||
taskMgr.do_method_later(2, self.do_remove, 'doRemove',
|
||||
extraArgs=[bodyNP], appendTask=True)
|
||||
|
||||
def do_remove(self, bodyNP, task):
|
||||
self.world.remove(bodyNP.node())
|
||||
bodyNP.remove_node()
|
||||
return task.done
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.worldNP.remove_node()
|
||||
self.worldNP = None
|
||||
self.world = None
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(False)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box A
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyA = BulletRigidBodyNode('Box A')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyA)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(-2, 0, 4)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyA)
|
||||
|
||||
# Box B
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyB = BulletRigidBodyNode('Box B')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyB)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(0, 0, 0)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyB)
|
||||
|
||||
# Cone
|
||||
frameA = TransformState.make_pos_hpr((0, 0, -2), (0, 0, 90))
|
||||
frameB = TransformState.make_pos_hpr((-5, 0, 0), (0, 0, 0))
|
||||
|
||||
cone = BulletConeTwistConstraint(bodyA, bodyB, frameA, frameB)
|
||||
cone.set_debug_draw_size(2.0)
|
||||
cone.set_limit(30, 45, 170, softness=1.0, bias=0.3, relaxation=8.0)
|
||||
self.world.attach(cone)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
194
samples/bullet-physics/14_generic_constraint.py
Normal file
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletSphereShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletGenericConstraint
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 5)
|
||||
base.cam.look_at(0, 0, 5)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('enter', self.do_shoot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_shoot(self):
|
||||
# Get from/to points from mouse click
|
||||
pMouse = base.mouseWatcherNode.get_mouse()
|
||||
pFrom = LPoint3()
|
||||
pTo = LPoint3()
|
||||
base.camLens.extrude(pMouse, pFrom, pTo)
|
||||
|
||||
pFrom = render.get_relative_point(base.cam, pFrom)
|
||||
pTo = render.get_relative_point(base.cam, pTo)
|
||||
|
||||
# Calculate initial velocity
|
||||
v = pTo - pFrom
|
||||
v.normalize()
|
||||
v *= 100.0
|
||||
|
||||
# Create bullet
|
||||
shape = BulletSphereShape(0.3)
|
||||
body = BulletRigidBodyNode('Bullet')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_linear_velocity(v)
|
||||
bodyNP.node().set_ccd_motion_threshold(1e-7);
|
||||
bodyNP.node().set_ccd_swept_sphere_radius(0.50);
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(pFrom)
|
||||
|
||||
visNP = loader.load_model('models/ball.egg')
|
||||
visNP.set_scale(0.8)
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Remove the bullet again after 2 seconds
|
||||
taskMgr.do_method_later(2, self.do_remove, 'doRemove',
|
||||
extraArgs=[bodyNP], appendTask=True)
|
||||
|
||||
def do_remove(self, bodyNP, task):
|
||||
self.world.remove(bodyNP.node())
|
||||
bodyNP.remove_node()
|
||||
return task.done
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.worldNP.remove_node()
|
||||
self.worldNP = None
|
||||
self.world = None
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(False)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box A
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyA = BulletRigidBodyNode('Box A')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyA)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(-4, 0, 4)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyA)
|
||||
|
||||
# Box B
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
bodyB = BulletRigidBodyNode('Box B')
|
||||
bodyNP = self.worldNP.attach_new_node(bodyB)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos(1, 0, 0)
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.world.attach(bodyB)
|
||||
|
||||
# Generic
|
||||
frameA = TransformState.make_pos_hpr((4, 0, 0), (0, 0, 0))
|
||||
frameB = TransformState.make_pos_hpr((2, 0, 0), (0, 0, 0))
|
||||
|
||||
generic = BulletGenericConstraint(bodyA, bodyB, frameA, frameB, True)
|
||||
generic.set_debug_draw_size(2.0)
|
||||
generic.set_linear_limit(0, 0, 0)
|
||||
generic.set_linear_limit(1, 0, 3)
|
||||
generic.set_linear_limit(2, 0, 1)
|
||||
generic.set_angular_limit(0, -60, 60)
|
||||
generic.set_angular_limit(1, -30, 30)
|
||||
generic.set_angular_limit(2, -120, 120)
|
||||
|
||||
self.world.attach(generic)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
168
samples/bullet-physics/15_ghost.py
Normal file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletGhostNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().set_active(True)
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
|
||||
# Get nodes overlapping with the ghost object
|
||||
if self.ghostNP.node().get_num_overlapping_nodes() > 0:
|
||||
print(self.ghostNP.node().get_num_overlapping_nodes(),
|
||||
self.ghostNP.node().get_overlapping_nodes())
|
||||
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
node = BulletRigidBodyNode('Ground')
|
||||
np = self.worldNP.attach_new_node(node)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 0)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Box
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
np.node().set_mass(1.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, 4)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.boxNP = np
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.reparent_to(self.boxNP)
|
||||
|
||||
# Trigger
|
||||
shape = BulletBoxShape((1, 1, 2))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletGhostNode('Ghost'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(3, 0, 0)
|
||||
np.set_collide_mask(BitMask32(0x0f))
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
self.ghostNP = np
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
172
samples/bullet-physics/16_ghost_local.py
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
This sample is incomplete; do not expect to gain much insight from this.
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletGhostNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
torque = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('forward'): force.y = 1.0
|
||||
if inputState.isSet('reverse'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
if inputState.isSet('turnLeft'): torque.z = 1.0
|
||||
if inputState.isSet('turnRight'): torque.z = -1.0
|
||||
|
||||
force *= 30.0
|
||||
torque *= 10.0
|
||||
|
||||
self.boxNP.node().apply_central_force(force)
|
||||
self.boxNP.node().apply_torque(torque)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
#self.world.do_physics(dt, 20, 1.0/180.0)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world.remove(self.groundNP.node())
|
||||
self.world.remove(self.boxNP.node())
|
||||
self.world = None
|
||||
|
||||
self.debugNP = None
|
||||
self.groundNP = None
|
||||
self.boxNP = None
|
||||
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(True)
|
||||
|
||||
#self.debugNP.show_tight_bounds()
|
||||
#self.debugNP.show_bounds()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground (static)
|
||||
shape = BulletPlaneShape((0, 0, 1), 1)
|
||||
|
||||
self.groundNP = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
self.groundNP.node().add_shape(shape)
|
||||
self.groundNP.set_pos(0, 0, -2)
|
||||
self.groundNP.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(self.groundNP.node())
|
||||
|
||||
# Box (dynamic)
|
||||
shape = BulletBoxShape((0.5, 0.5, 0.5))
|
||||
|
||||
self.boxNP = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
self.boxNP.node().set_mass(1.0)
|
||||
self.boxNP.node().add_shape(shape)
|
||||
self.boxNP.set_pos(0, 0, 2)
|
||||
self.boxNP.set_collide_mask(BitMask32.all_on())
|
||||
self.boxNP.node().set_deactivation_enabled(False)
|
||||
|
||||
self.world.attach(self.boxNP.node())
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.clear_model_nodes()
|
||||
visualNP.reparent_to(self.boxNP)
|
||||
|
||||
# TODO:
|
||||
# self.ghostNP = self.worldNP.attach_new_node(BulletGhostNode('ghost'))
|
||||
# self.ghostNP.reparent_to(self.boxNP)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
201
samples/bullet-physics/17_character.py
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.actor.Actor import Actor
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import load_prc_file_data
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import Filename
|
||||
from panda3d.core import PNMImage
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletCapsuleShape
|
||||
from panda3d.bullet import BulletCharacterControllerNode
|
||||
from panda3d.bullet import BulletHeightfieldShape
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import ZUp
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
"""
|
||||
Load some configuration variables, it's important for this to happen
|
||||
before the ShowBase is initialized
|
||||
"""
|
||||
load_prc_file_data("", """
|
||||
sync-video #t
|
||||
### add entries below if you are not running from an installation.
|
||||
#model-path /path/to/panda3d
|
||||
""")
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
self.accept('space', self.do_jump)
|
||||
self.accept('c', self.do_crouch)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
inputState.watchWithModifiers('turnLeft', 'q')
|
||||
inputState.watchWithModifiers('turnRight', 'e')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def do_jump(self):
|
||||
self.character.set_max_jump_height(5.0)
|
||||
self.character.set_jump_speed(8.0)
|
||||
self.character.do_jump()
|
||||
self.actorNP.play("jump")
|
||||
|
||||
def do_crouch(self):
|
||||
self.crouching = not self.crouching
|
||||
sz = self.crouching and 0.6 or 1.0
|
||||
self.characterNP.set_scale((1, 1, sz))
|
||||
#self.character.get_shape().set_local_scale(LVector3(1, 1, sz))
|
||||
#self.characterNP.set_scale(LVector3(1, 1, sz) * 0.3048)
|
||||
#self.characterNP.set_pos(0, 0, -1 * sz)
|
||||
|
||||
def process_input(self, dt):
|
||||
speed = LVector3(0, 0, 0)
|
||||
omega = 0.0
|
||||
|
||||
if inputState.isSet('forward'): speed.y = 2.0
|
||||
if inputState.isSet('reverse'): speed.y = -2.0
|
||||
if inputState.isSet('left'): speed.x = -2.0
|
||||
if inputState.isSet('right'): speed.x = 2.0
|
||||
if inputState.isSet('turnLeft'): omega = 120.0
|
||||
if inputState.isSet('turnRight'): omega = -120.0
|
||||
|
||||
self.character.set_angular_movement(omega)
|
||||
self.character.set_linear_movement(speed, True)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt, 4, 1./240.)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
#img = PNMImage(Filename('models/elevation.png'))
|
||||
#shape = BulletHeightfieldShape(img, 1.0, ZUp)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Box
|
||||
shape = BulletBoxShape((1.0, 3.0, 0.3))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
np.node().set_mass(10.0)
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(3, 0, 4)
|
||||
np.setH(20.0)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Character
|
||||
self.crouching = False
|
||||
|
||||
h = 1.75
|
||||
w = 0.4
|
||||
shape = BulletCapsuleShape(w, h - 2 * w, ZUp)
|
||||
self.character = BulletCharacterControllerNode(shape, 0.4, 'Player')
|
||||
self.characterNP = self.worldNP.attach_new_node(self.character)
|
||||
self.characterNP.set_pos(-2, 0, 14)
|
||||
self.characterNP.set_h(45)
|
||||
self.characterNP.set_collide_mask(BitMask32.all_on())
|
||||
self.world.attach(self.character)
|
||||
|
||||
self.actorNP = Actor('../roaming-ralph/models/ralph.egg.pz',
|
||||
{'run' : '../roaming-ralph/models/ralph-run.egg.pz',
|
||||
'walk' : '../roaming-ralph/models/ralph-walk.egg.pz'})
|
||||
self.actorNP.reparent_to(self.characterNP)
|
||||
self.actorNP.set_scale(0.3048) # 1ft = 0.3048m
|
||||
self.actorNP.setH(180)
|
||||
self.actorNP.set_pos(0, 0, -1)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
213
samples/bullet-physics/18_vehicle.py
Normal file
@@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletVehicle
|
||||
from panda3d.bullet import ZUp
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -20, 4)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('forward', 'w')
|
||||
inputState.watchWithModifiers('reverse', 's')
|
||||
inputState.watchWithModifiers('turnLeft', 'a')
|
||||
inputState.watchWithModifiers('turnRight', 'd')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
engineForce = 0.0
|
||||
brakeForce = 0.0
|
||||
|
||||
if inputState.isSet('forward'):
|
||||
engineForce = 1000.0
|
||||
brakeForce = 0.0
|
||||
|
||||
if inputState.isSet('reverse'):
|
||||
engineForce = 0.0
|
||||
brakeForce = 100.0
|
||||
|
||||
if inputState.isSet('turnLeft'):
|
||||
self.steering += dt * self.steeringIncrement
|
||||
self.steering = min(self.steering, self.steeringClamp)
|
||||
|
||||
if inputState.isSet('turnRight'):
|
||||
self.steering -= dt * self.steeringIncrement
|
||||
self.steering = max(self.steering, -self.steeringClamp)
|
||||
|
||||
# Apply steering to front wheels
|
||||
self.vehicle.setSteeringValue(self.steering, 0);
|
||||
self.vehicle.setSteeringValue(self.steering, 1);
|
||||
|
||||
# Apply engine and brake to rear wheels
|
||||
self.vehicle.applyEngineForce(engineForce, 2);
|
||||
self.vehicle.applyEngineForce(engineForce, 3);
|
||||
self.vehicle.setBrake(brakeForce, 2);
|
||||
self.vehicle.setBrake(brakeForce, 3);
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
#print self.vehicle.getWheel(0).getRaycastInfo().isInContact()
|
||||
#print self.vehicle.getWheel(0).getRaycastInfo().getContactPointWs()
|
||||
#print self.vehicle.getChassis().isKinematic()
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Plane
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -1)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Chassis
|
||||
shape = BulletBoxShape((0.6, 1.4, 0.5))
|
||||
ts = TransformState.make_pos((0, 0, 0.5))
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Vehicle'))
|
||||
np.node().add_shape(shape, ts)
|
||||
np.set_pos(0, 0, 1)
|
||||
np.node().set_mass(800.0)
|
||||
np.node().set_deactivation_enabled(False)
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
#np.node().set_ccd_swept_sphere_radius(1.0)
|
||||
#np.node().set_ccd_motion_threshold(1e-7)
|
||||
|
||||
# Vehicle
|
||||
self.vehicle = BulletVehicle(self.world, np.node())
|
||||
self.vehicle.set_coordinate_system(ZUp)
|
||||
self.world.attach(self.vehicle)
|
||||
|
||||
self.yugoNP = loader.load_model('models/yugo/yugo.egg')
|
||||
self.yugoNP.reparent_to(np)
|
||||
|
||||
# Right front wheel
|
||||
np = loader.load_model('models/yugo/yugotireR.egg')
|
||||
np.reparent_to(self.worldNP)
|
||||
self.add_wheel(( 0.70, 1.05, 0.3), True, np)
|
||||
|
||||
# Left front wheel
|
||||
np = loader.load_model('models/yugo/yugotireL.egg')
|
||||
np.reparent_to(self.worldNP)
|
||||
self.add_wheel((-0.70, 1.05, 0.3), True, np)
|
||||
|
||||
# Right rear wheel
|
||||
np = loader.load_model('models/yugo/yugotireR.egg')
|
||||
np.reparent_to(self.worldNP)
|
||||
self.add_wheel(( 0.70, -1.05, 0.3), False, np)
|
||||
|
||||
# Left rear wheel
|
||||
np = loader.load_model('models/yugo/yugotireL.egg')
|
||||
np.reparent_to(self.worldNP)
|
||||
self.add_wheel((-0.70, -1.05, 0.3), False, np)
|
||||
|
||||
# Steering info
|
||||
self.steering = 0.0 # degree
|
||||
self.steeringClamp = 45.0 # degree
|
||||
self.steeringIncrement = 120.0 # degree per second
|
||||
|
||||
def add_wheel(self, pos, front, np):
|
||||
wheel = self.vehicle.create_wheel()
|
||||
|
||||
wheel.set_node(np.node())
|
||||
wheel.set_chassis_connection_point_cs(pos)
|
||||
wheel.set_front_wheel(front)
|
||||
|
||||
wheel.set_wheel_direction_cs((0, 0, -1))
|
||||
wheel.set_wheel_axle_cs((1, 0, 0))
|
||||
wheel.set_wheel_radius(0.25)
|
||||
wheel.set_max_suspension_travel_cm(40.0)
|
||||
|
||||
wheel.set_suspension_stiffness(40.0)
|
||||
wheel.set_wheels_damping_relaxation(2.3)
|
||||
wheel.set_wheels_damping_compression(4.4)
|
||||
wheel.set_friction_slip(100.0);
|
||||
wheel.set_roll_influence(0.1)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
192
samples/bullet-physics/19_ball_in_maze.py
Normal file
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
from direct.interval.MetaInterval import Sequence
|
||||
from direct.interval.MetaInterval import Parallel
|
||||
from direct.interval.LerpInterval import LerpFunc
|
||||
from direct.interval.FunctionInterval import Func
|
||||
from direct.interval.FunctionInterval import Wait
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import Material
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletGhostNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletHelper
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos_hpr(0, 0, 25, 0, -90, 0)
|
||||
base.disable_mouse()
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.exitGame)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Setup scene 1: World
|
||||
self.debugNP = render.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(True)
|
||||
self.debugNP.node().show_normals(True)
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Setup scene 2: Ball
|
||||
#visNP = loader.load_model('models/ball.egg')
|
||||
visNP = loader.load_model('../ball-in-maze/models/ball.egg.pz')
|
||||
visNP.clear_model_nodes()
|
||||
|
||||
bodyNPs = BulletHelper.from_collision_solids(visNP, True)
|
||||
self.ballNP = bodyNPs[0]
|
||||
self.ballNP.reparent_to(render)
|
||||
self.ballNP.node().set_mass(1.0)
|
||||
self.ballNP.set_pos(4, -4, 1)
|
||||
self.ballNP.node().set_deactivation_enabled(False)
|
||||
|
||||
visNP.reparent_to(self.ballNP)
|
||||
|
||||
# Setup scene 3: Maze
|
||||
visNP = loader.load_model('models/maze.egg')
|
||||
#visNP = loader.load_model('samples/ball-in-maze/models/maze.egg.pz')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.reparent_to(render)
|
||||
|
||||
self.holes = []
|
||||
self.maze = []
|
||||
self.mazeNP = visNP
|
||||
|
||||
bodyNPs = BulletHelper.from_collision_solids(visNP, True);
|
||||
for bodyNP in bodyNPs:
|
||||
bodyNP.reparent_to(render)
|
||||
|
||||
if isinstance(bodyNP.node(), BulletRigidBodyNode):
|
||||
bodyNP.node().set_mass(0.0)
|
||||
bodyNP.node().set_kinematic(True)
|
||||
self.maze.append(bodyNP)
|
||||
|
||||
elif isinstance(bodyNP.node(), BulletGhostNode):
|
||||
self.holes.append(bodyNP)
|
||||
|
||||
# Lighting and material for the ball
|
||||
ambientLight = AmbientLight('ambientLight')
|
||||
ambientLight.set_color((0.55, 0.55, 0.55, 1))
|
||||
directionalLight = DirectionalLight('directionalLight')
|
||||
directionalLight.set_direction((0, 0, -1))
|
||||
directionalLight.set_color((0.375, 0.375, 0.375, 1))
|
||||
directionalLight.set_specular_color((1, 1, 1, 1))
|
||||
self.ballNP.set_light(render.attach_new_node(ambientLight))
|
||||
self.ballNP.set_light(render.attach_new_node(directionalLight))
|
||||
|
||||
m = Material()
|
||||
m.set_specular((1,1,1,1))
|
||||
m.set_shininess(96)
|
||||
self.ballNP.set_material(m, 1)
|
||||
|
||||
# Startup
|
||||
self.start_game()
|
||||
|
||||
def exitGame(self):
|
||||
sys.exit()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def start_game(self):
|
||||
self.ballNP.set_pos(4, -4, 1)
|
||||
self.ballNP.node().set_linear_velocity((0, 0, 0))
|
||||
self.ballNP.node().set_angular_velocity((0, 0, 0))
|
||||
|
||||
# Mouse
|
||||
p = base.win.get_properties()
|
||||
base.win.move_pointer(0, int(p.get_x_size()/2), int(p.get_y_size()/2))
|
||||
|
||||
# Add bodies and ghosts
|
||||
self.world.attach(self.ballNP.node())
|
||||
for bodyNP in self.maze:
|
||||
self.world.attach(bodyNP.node())
|
||||
for ghostNP in self.holes:
|
||||
self.world.attach(ghostNP.node())
|
||||
|
||||
# Simulation task
|
||||
taskMgr.add(self.update_game, 'updateGame')
|
||||
|
||||
def stop_game(self):
|
||||
|
||||
# Remove bodies and ghosts
|
||||
self.world.remove(self.ballNP.node())
|
||||
for bodyNP in self.maze:
|
||||
self.world.remove(bodyNP.node())
|
||||
for ghostNP in self.holes:
|
||||
self.world.remove(ghostNP.node())
|
||||
|
||||
# Simulation task
|
||||
taskMgr.remove('updateGame')
|
||||
|
||||
def update_game(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
|
||||
# Get mouse position and tilt maze
|
||||
if base.mouseWatcherNode.hasMouse():
|
||||
mpos = base.mouseWatcherNode.get_mouse()
|
||||
hpr = (0, mpos.y * -10, mpos.x * 10)
|
||||
|
||||
# Maze visual node
|
||||
self.mazeNP.set_hpr(hpr)
|
||||
|
||||
# Maze body nodes
|
||||
for bodyNP in self.maze:
|
||||
bodyNP.set_hpr(hpr)
|
||||
|
||||
# Update simulation
|
||||
self.world.do_physics(dt)
|
||||
|
||||
# Check if ball is touching a hole
|
||||
for holeNP in self.holes:
|
||||
if holeNP.node().get_num_overlapping_nodes() > 2:
|
||||
if self.ballNP.node() in holeNP.node().get_overlapping_nodes():
|
||||
self.lose_game(holeNP)
|
||||
|
||||
return task.cont
|
||||
|
||||
def lose_game(self, holeNP):
|
||||
toPos = holeNP.node().get_shape_pos(0)
|
||||
self.stop_game()
|
||||
|
||||
Sequence(
|
||||
Parallel(
|
||||
LerpFunc(self.ballNP.set_x, fromData = self.ballNP.get_x(),
|
||||
toData = toPos.get_x(), duration = .1),
|
||||
LerpFunc(self.ballNP.set_y, fromData = self.ballNP.get_y(),
|
||||
toData = toPos.get_y(), duration = .1),
|
||||
LerpFunc(self.ballNP.set_z, fromData = self.ballNP.get_z(),
|
||||
toData = self.ballNP.get_z() - .9, duration = .2)),
|
||||
Wait(1),
|
||||
Func(self.start_game)).start()
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
187
samples/bullet-physics/20_bowl_and_eggs.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import random
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletConvexHullShape
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import ZUp
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -10, 5)
|
||||
base.cam.look_at(0, 0, 0.2)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
inputState.watchWithModifiers('up', 'w')
|
||||
inputState.watchWithModifiers('left', 'a')
|
||||
inputState.watchWithModifiers('down', 's')
|
||||
inputState.watchWithModifiers('right', 'd')
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def process_input(self, dt):
|
||||
force = LVector3(0, 0, 0)
|
||||
|
||||
if inputState.isSet('up'): force.y = 1.0
|
||||
if inputState.isSet('down'): force.y = -1.0
|
||||
if inputState.isSet('left'): force.x = -1.0
|
||||
if inputState.isSet('right'): force.x = 1.0
|
||||
|
||||
force *= 300.0
|
||||
|
||||
self.bowlNP.node().set_active(True)
|
||||
self.bowlNP.node().apply_central_force(force)
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.process_input(dt)
|
||||
self.world.do_physics(dt)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
self.debugNP.node().show_wireframe(True)
|
||||
self.debugNP.node().show_constraints(True)
|
||||
self.debugNP.node().show_bounding_boxes(False)
|
||||
self.debugNP.node().show_normals(False)
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
shape = BulletPlaneShape((0, 0, 1), 0)
|
||||
|
||||
body = BulletRigidBodyNode('Ground')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.set_pos(0, 0, 0)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
# Bowl
|
||||
visNP = loader.load_model('models/bowl.egg')
|
||||
|
||||
geom = (visNP.findAllMatches('**/+GeomNode')
|
||||
.get_path(0).node().get_geom(0))
|
||||
mesh = BulletTriangleMesh()
|
||||
mesh.addGeom(geom)
|
||||
shape = BulletTriangleMeshShape(mesh, dynamic=True)
|
||||
|
||||
body = BulletRigidBodyNode('Bowl')
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_mass(10.0)
|
||||
bodyNP.set_pos(0, 0, 0)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.bowlNP = bodyNP
|
||||
self.bowlNP.set_scale(2)
|
||||
|
||||
# Eggs
|
||||
self.eggNPs = []
|
||||
for i in range(5):
|
||||
x = random.gauss(0, 0.1)
|
||||
y = random.gauss(0, 0.1)
|
||||
z = random.gauss(0, 0.1) + 1
|
||||
h = random.random() * 360
|
||||
p = random.random() * 360
|
||||
r = random.random() * 360
|
||||
|
||||
visNP = loader.load_model('models/egg.egg')
|
||||
|
||||
geom = (visNP.find_all_matches('**/+GeomNode')
|
||||
.get_path(0).node().get_geom(0))
|
||||
shape = BulletConvexHullShape()
|
||||
shape.addGeom(geom)
|
||||
|
||||
body = BulletRigidBodyNode('Egg-%i' % i)
|
||||
bodyNP = self.worldNP.attach_new_node(body)
|
||||
bodyNP.node().set_mass(1.0)
|
||||
bodyNP.node().add_shape(shape)
|
||||
bodyNP.node().set_deactivation_enabled(False)
|
||||
bodyNP.set_collide_mask(BitMask32.all_on())
|
||||
bodyNP.set_pos_hpr(x, y, z, h, p, r)
|
||||
#bodyNP.set_scale(1.5)
|
||||
self.world.attach(bodyNP.node())
|
||||
|
||||
visNP.reparent_to(bodyNP)
|
||||
|
||||
self.eggNPs.append(bodyNP)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
172
samples/bullet-physics/21_softbody_rope.py
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import GeomNode
|
||||
from panda3d.core import RopeNode
|
||||
from panda3d.core import NurbsCurveEvaluator
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletSoftBodyNode
|
||||
from panda3d.bullet import BulletSoftBodyConfig
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -40, 10)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((5, 0, -2))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 10, 0.004)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Soft body world information
|
||||
info = self.world.get_world_info()
|
||||
info.set_air_density(1.2)
|
||||
info.set_water_density(0)
|
||||
info.set_water_offset(0)
|
||||
info.set_water_normal((0, 0, 0))
|
||||
|
||||
# Softbody
|
||||
def make(p1):
|
||||
n = 8
|
||||
p2 = p1 + LVector3(10, 0, 0)
|
||||
|
||||
bodyNode = BulletSoftBodyNode.makeRope(info, p1, p2, n, 1)
|
||||
bodyNode.set_total_mass(50.0)
|
||||
bodyNP = self.worldNP.attach_new_node(bodyNode)
|
||||
self.world.attach(bodyNode)
|
||||
|
||||
# Render option 1: Line geom
|
||||
#geom = BulletSoftBodyNode.make_geom_from_links(bodyNode)
|
||||
#bodyNode.link_geom(geom)
|
||||
#visNode = GeomNode('')
|
||||
#visNode.add_geom(geom)
|
||||
#visNP = bodyNP.attach_new_node(visNode)
|
||||
|
||||
# Render option 2: NURBS curve
|
||||
curve = NurbsCurveEvaluator()
|
||||
curve.reset(n + 2)
|
||||
bodyNode.link_curve(curve)
|
||||
|
||||
visNode = RopeNode('')
|
||||
visNode.set_curve(curve)
|
||||
visNode.set_render_mode(RopeNode.RM_tube)
|
||||
visNode.set_uv_mode(RopeNode.UV_parametric)
|
||||
visNode.set_num_subdiv(4)
|
||||
visNode.set_num_slices(8)
|
||||
visNode.set_thickness(0.4)
|
||||
visNP = self.worldNP.attach_new_node(visNode)
|
||||
#visNP = bodyNP.attach_new_node(visNode) # --> renders with offset!!!
|
||||
visNP.set_texture(loader.load_texture('models/maps/color-grid.rgb'))
|
||||
|
||||
#bodyNP.show_bounds()
|
||||
#visNP.show_bounds()
|
||||
|
||||
return bodyNP
|
||||
|
||||
np1 = make(LPoint3(-2, -1, 8))
|
||||
np2 = make(LPoint3(-2, 1, 8))
|
||||
|
||||
# Box
|
||||
shape = BulletBoxShape((2, 2, 6))
|
||||
|
||||
boxNP = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
boxNP.node().set_mass(50.0)
|
||||
boxNP.node().add_shape(shape)
|
||||
boxNP.set_pos(10, 0, 8)
|
||||
boxNP.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(boxNP.node())
|
||||
|
||||
np1.node().append_anchor(np1.node().get_num_nodes() - 1, boxNP.node())
|
||||
np2.node().append_anchor(np1.node().get_num_nodes() - 1, boxNP.node())
|
||||
|
||||
visNP = loader.load_model('models/box.egg')
|
||||
visNP.clear_model_nodes()
|
||||
visNP.set_scale(4, 4, 12)
|
||||
visNP.reparent_to(boxNP)
|
||||
|
||||
#render.ls()
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
179
samples/bullet-physics/22_softbody_cloth.py
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import GeomNode
|
||||
from panda3d.core import GeomVertexFormat
|
||||
from panda3d.core import GeomVertexRewriter
|
||||
from panda3d.core import InternalName
|
||||
from panda3d.core import NurbsSurfaceEvaluator
|
||||
from panda3d.core import SheetNode
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletHelper
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import BulletSoftBodyNode
|
||||
from panda3d.bullet import BulletSoftBodyConfig
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -40, 10)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((5, 0, -2))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 10, 0.004)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Box
|
||||
shape = BulletBoxShape((1.0, 1.0, 1.0))
|
||||
|
||||
boxNP = self.worldNP.attach_new_node(BulletRigidBodyNode('Box'))
|
||||
boxNP.node().set_mass(150.0)
|
||||
boxNP.node().add_shape(shape)
|
||||
boxNP.set_pos(0, 0, 2)
|
||||
boxNP.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(boxNP.node())
|
||||
|
||||
visualNP = loader.load_model('models/box.egg')
|
||||
visualNP.clear_model_nodes()
|
||||
visualNP.set_scale(2.0)
|
||||
visualNP.reparent_to(boxNP)
|
||||
|
||||
# Soft body world information
|
||||
info = self.world.get_world_info()
|
||||
info.set_air_density(1.2)
|
||||
info.set_water_density(0)
|
||||
info.set_water_offset(0)
|
||||
info.set_water_normal((0, 0, 0))
|
||||
|
||||
# Softbody
|
||||
nx = 31
|
||||
ny = 31
|
||||
|
||||
p00 = LPoint3(-8, -8, 0)
|
||||
p10 = LPoint3( 8, -8, 0)
|
||||
p01 = LPoint3(-8, 8, 0)
|
||||
p11 = LPoint3( 8, 8, 0)
|
||||
bodyNode = BulletSoftBodyNode.make_patch(
|
||||
info, p00, p10, p01, p11, nx, ny, 1+2+4+8, True)
|
||||
|
||||
material = bodyNode.append_material()
|
||||
material.set_linear_stiffness(0.4)
|
||||
#material.set_angular_stiffness(2.)
|
||||
bodyNode.generate_bending_constraints(2, material);
|
||||
bodyNode.set_total_mass(50.0)
|
||||
bodyNode.get_shape(0).set_margin(0.5)
|
||||
|
||||
bodyNP = self.worldNP.attach_new_node(bodyNode)
|
||||
self.world.attach(bodyNode)
|
||||
|
||||
# Rendering with Geom:
|
||||
fmt = GeomVertexFormat.get_v3n3t2()
|
||||
geom = BulletHelper.make_geom_from_faces(bodyNode, fmt, True)
|
||||
bodyNode.link_geom(geom)
|
||||
visNode = GeomNode('')
|
||||
visNode.add_geom(geom)
|
||||
visNP = bodyNP.attach_new_node(visNode)
|
||||
|
||||
# Now we want to have a texture and texture coordinates.
|
||||
# The geom's format has already a column for texcoords, so we just need
|
||||
# to write texcoords using a GeomVertexRewriter.
|
||||
tex = loader.load_texture('models/panda.jpg')
|
||||
visNP.set_texture(tex)
|
||||
BulletHelper.make_texcoords_for_patch(geom, nx, ny)
|
||||
|
||||
# Rendering with NURBS (please reduce nx & ny to 12):
|
||||
#surface = NurbsSurfaceEvaluator()
|
||||
#surface.reset(nx, ny)
|
||||
#bodyNode.link_surface(surface)
|
||||
|
||||
#visNode = SheetNode('')
|
||||
#visNode.set_surface(surface)
|
||||
#visNode.set_num_u_subdiv(2)
|
||||
#visNode.set_num_v_subdiv(2)
|
||||
#visNP = self.worldNP.attach_new_node(visNode)
|
||||
#visNP.setTwoSided(True)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
178
samples/bullet-physics/23_softbody_pressure.py
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import GeomNode
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletHelper
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import BulletSoftBodyNode
|
||||
from panda3d.bullet import BulletSoftBodyConfig
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -60, 20)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((1, 1, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
#self.debugNP.show_tight_bounds()
|
||||
#self.debugNP.show_bounds()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
p0 = LPoint3(-20, -20, 0)
|
||||
p1 = LPoint3(-20, 20, 0)
|
||||
p2 = LPoint3(20, -20, 0)
|
||||
p3 = LPoint3(20, 20, 0)
|
||||
mesh = BulletTriangleMesh()
|
||||
mesh.add_triangle(p0, p1, p2)
|
||||
mesh.add_triangle(p1, p2, p3)
|
||||
shape = BulletTriangleMeshShape(mesh, dynamic=False)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Mesh'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -2)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Stair
|
||||
origin = LPoint3(0, 0, 0)
|
||||
size = LVector3(2, 10, 1)
|
||||
shape = BulletBoxShape(size * 0.5)
|
||||
for i in range(10):
|
||||
pos = origin + size * i
|
||||
pos.setY(0)
|
||||
|
||||
np = self.worldNP.attach_new_node(
|
||||
BulletRigidBodyNode('Stair{}'.format(i)))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(pos)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
npV = loader.load_model('models/box.egg')
|
||||
npV.reparent_to(np)
|
||||
npV.set_scale(size)
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Soft body world information
|
||||
info = self.world.get_world_info()
|
||||
info.set_air_density(1.2)
|
||||
info.set_water_density(0)
|
||||
info.set_water_offset(0)
|
||||
info.set_water_normal((0, 0, 0))
|
||||
|
||||
# Softbody
|
||||
center = LPoint3(0, 0, 0)
|
||||
radius = LVector3(1, 1, 1) * 1.5
|
||||
node = BulletSoftBodyNode.make_ellipsoid(info, center, radius, 128)
|
||||
node.set_name('Ellipsoid')
|
||||
node.get_material(0).set_linear_stiffness(0.1)
|
||||
node.get_cfg().set_dynamic_friction_coefficient(1)
|
||||
node.get_cfg().set_damping_coefficient(0.001)
|
||||
node.get_cfg().set_pressure_coefficient(1500)
|
||||
node.set_total_mass(30, True)
|
||||
node.set_pose(True, False)
|
||||
|
||||
np = self.worldNP.attach_new_node(node)
|
||||
np.set_pos(15, 0, 12)
|
||||
#np.setH(90.0)
|
||||
#np.show_bounds()
|
||||
#np.show_tight_bounds()
|
||||
self.world.attach(np.node())
|
||||
|
||||
geom = BulletHelper.make_geom_from_faces(node)
|
||||
node.link_geom(geom)
|
||||
nodeV = GeomNode('EllipsoidVisual')
|
||||
nodeV.add_geom(geom)
|
||||
npV = np.attach_new_node(nodeV)
|
||||
|
||||
#npV.show_bounds()
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
162
samples/bullet-physics/24_softbody_tri.py
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import GeomNode
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import BulletSoftBodyNode
|
||||
from panda3d.bullet import BulletSoftBodyConfig
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -40, 10)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((5, 0, -2))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
#dt *= 0.01
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
p0 = LPoint3(-20, -20, 0)
|
||||
p1 = LPoint3(-20, 20, 0)
|
||||
p2 = LPoint3(20, -20, 0)
|
||||
p3 = LPoint3(20, 20, 0)
|
||||
mesh = BulletTriangleMesh()
|
||||
mesh.add_triangle(p0, p1, p2)
|
||||
mesh.add_triangle(p1, p2, p3)
|
||||
shape = BulletTriangleMeshShape(mesh, dynamic=False)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Mesh'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -2)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Soft body world information
|
||||
info = self.world.get_world_info()
|
||||
info.set_air_density(1.2)
|
||||
info.set_water_density(0)
|
||||
info.set_water_offset(0)
|
||||
info.set_water_normal((0, 0, 0))
|
||||
|
||||
# Softbody
|
||||
def make_SB(pos, hpr):
|
||||
|
||||
#use this to construct a torus geom.
|
||||
#import torus
|
||||
#geom = torus.make_geom()
|
||||
|
||||
geom = (loader.load_model('models/torus.egg')
|
||||
.find_all_matches('**/+GeomNode').get_path(0).node()
|
||||
.modify_geom(0))
|
||||
|
||||
geomNode = GeomNode('')
|
||||
geomNode.add_geom(geom)
|
||||
|
||||
node = BulletSoftBodyNode.make_tri_mesh(info, geom)
|
||||
node.link_geom(geomNode.modify_geom(0))
|
||||
|
||||
node.generate_bending_constraints(2)
|
||||
node.get_cfg().set_positions_solver_iterations(2)
|
||||
node.get_cfg().set_collision_flag(
|
||||
BulletSoftBodyConfig.CF_vertex_face_soft_soft, True)
|
||||
node.randomize_constraints()
|
||||
node.set_total_mass(50, True)
|
||||
|
||||
softNP = self.worldNP.attach_new_node(node)
|
||||
softNP.set_pos(pos)
|
||||
softNP.set_hpr(hpr)
|
||||
self.world.attach(node)
|
||||
|
||||
geomNP = softNP.attach_new_node(geomNode)
|
||||
|
||||
make_SB(LPoint3(-3, 0, 4), (0, 0, 0))
|
||||
make_SB(LPoint3(0, 0, 4), (0, 90, 90))
|
||||
make_SB(LPoint3(3, 0, 4), (0, 0, 0))
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
187
samples/bullet-physics/25_softbody_tetra.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import GeomNode
|
||||
from panda3d.core import GeomVertexFormat
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletHelper
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import BulletSoftBodyNode
|
||||
from panda3d.bullet import BulletSoftBodyConfig
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -40, 10)
|
||||
base.cam.look_at(0, 0, 0)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((5, 0, -2))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
p0 = LPoint3(-20, -20, 0)
|
||||
p1 = LPoint3(-20, 20, 0)
|
||||
p2 = LPoint3(20, -20, 0)
|
||||
p3 = LPoint3(20, 20, 0)
|
||||
mesh = BulletTriangleMesh()
|
||||
mesh.add_triangle(p0, p1, p2)
|
||||
mesh.add_triangle(p1, p2, p3)
|
||||
shape = BulletTriangleMeshShape(mesh, dynamic=False)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Mesh'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -4)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Soft body world information
|
||||
info = self.world.get_world_info()
|
||||
info.set_air_density(1.2)
|
||||
info.set_water_density(0)
|
||||
info.set_water_offset(0)
|
||||
info.set_water_normal((0, 0, 0))
|
||||
|
||||
## Softbody - From points/indices
|
||||
#import cube
|
||||
#points = [LPoint3(x,y,z) * 3 for x,y,z in cube.nodes]
|
||||
#indices = sum([list(x) for x in cube.elements], [])
|
||||
|
||||
#node = BulletSoftBodyNode.make_tet_mesh(info, points, indices, True)
|
||||
#node.set_volume_mass(300);
|
||||
#node.get_shape(0).set_margin(0.01)
|
||||
#node.get_material(0).set_linear_stiffness(0.8)
|
||||
#node.get_cfg().set_positions_solver_iterations(1)
|
||||
#node.get_cfg().clear_all_collision_flags()
|
||||
#node.get_cfg().set_collision_flag(
|
||||
#BulletSoftBodyConfig.CF_cluster_soft_soft, True)
|
||||
#node.get_cfg().set_collision_flag(
|
||||
#BulletSoftBodyConfig.CF_cluster_rigid_soft, True)
|
||||
#node.generate_clusters(16)
|
||||
|
||||
#softNP = self.worldNP.attach_new_node(node)
|
||||
#softNP.set_pos(0, 0, 8)
|
||||
#softNP.set_hpr(0, 0, 45)
|
||||
#self.world.attach(node)
|
||||
|
||||
# Softbody - From tetgen data
|
||||
ele = open('models/cube/cube.1.ele', 'r').read()
|
||||
face = open('models/cube/cube.1.face', 'r').read()
|
||||
node = open('models/cube/cube.1.node', 'r').read()
|
||||
|
||||
node = BulletSoftBodyNode.make_tet_mesh(info, ele, face, node)
|
||||
node.set_name('Tetra')
|
||||
node.set_volume_mass(300)
|
||||
node.get_shape(0).set_margin(0.01)
|
||||
node.get_material(0).set_linear_stiffness(0.1)
|
||||
node.get_cfg().set_positions_solver_iterations(1)
|
||||
node.get_cfg().clear_all_collision_flags()
|
||||
node.get_cfg().set_collision_flag(
|
||||
BulletSoftBodyConfig.CF_cluster_soft_soft, True)
|
||||
node.get_cfg().setCollisionFlag(
|
||||
BulletSoftBodyConfig.CF_cluster_rigid_soft, True)
|
||||
node.generate_clusters(6)
|
||||
|
||||
softNP = self.worldNP.attach_new_node(node)
|
||||
softNP.set_pos(0, 0, 8)
|
||||
softNP.set_hpr(45, 0, 0)
|
||||
self.world.attach(node)
|
||||
|
||||
# Option 1:
|
||||
visNP = loader.load_model('models/cube/cube.egg')
|
||||
visNP.reparent_to(softNP)
|
||||
geom = (visNP.findAllMatches('**/+GeomNode').
|
||||
getPath(0).node().modifyGeom(0))
|
||||
node.link_geom(geom)
|
||||
|
||||
# Option 2:
|
||||
#geom = BulletHelper.make_geom_from_faces(node)
|
||||
#visNode = GeomNode('TetraVisual')
|
||||
#visNode.add_geom(geom)
|
||||
#visNP = softNP.attach_new_node(visNode)
|
||||
#node.link_geom(geom)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
169
samples/bullet-physics/26_softbody_aero.py
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import random
|
||||
import sys
|
||||
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.showbase.InputStateGlobal import inputState
|
||||
|
||||
from panda3d.core import AmbientLight
|
||||
from panda3d.core import DirectionalLight
|
||||
from panda3d.core import LVector3
|
||||
from panda3d.core import LPoint3
|
||||
from panda3d.core import TransformState
|
||||
from panda3d.core import BitMask32
|
||||
from panda3d.core import GeomNode
|
||||
from panda3d.core import GeomVertexFormat
|
||||
|
||||
from panda3d.bullet import BulletWorld
|
||||
from panda3d.bullet import BulletHelper
|
||||
from panda3d.bullet import BulletPlaneShape
|
||||
from panda3d.bullet import BulletBoxShape
|
||||
from panda3d.bullet import BulletRigidBodyNode
|
||||
from panda3d.bullet import BulletDebugNode
|
||||
from panda3d.bullet import BulletTriangleMesh
|
||||
from panda3d.bullet import BulletTriangleMeshShape
|
||||
from panda3d.bullet import BulletSoftBodyNode
|
||||
from panda3d.bullet import BulletSoftBodyConfig
|
||||
|
||||
|
||||
class Game(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
base.set_background_color(0.1, 0.1, 0.8, 1)
|
||||
base.set_frame_rate_meter(True)
|
||||
|
||||
base.cam.set_pos(0, -80, 40)
|
||||
base.cam.look_at(0, 0, 10)
|
||||
|
||||
# Light
|
||||
alight = AmbientLight('ambientLight')
|
||||
alight.set_color((0.5, 0.5, 0.5, 1))
|
||||
alightNP = render.attach_new_node(alight)
|
||||
|
||||
dlight = DirectionalLight('directionalLight')
|
||||
dlight.set_direction((0, 0, -1))
|
||||
dlight.set_color((0.7, 0.7, 0.7, 1))
|
||||
dlightNP = render.attach_new_node(dlight)
|
||||
|
||||
render.clear_light()
|
||||
render.set_light(alightNP)
|
||||
render.set_light(dlightNP)
|
||||
|
||||
# Input
|
||||
self.accept('escape', self.do_exit)
|
||||
self.accept('r', self.do_reset)
|
||||
self.accept('f1', base.toggle_wireframe)
|
||||
self.accept('f2', base.toggle_texture)
|
||||
self.accept('f3', self.toggle_debug)
|
||||
self.accept('f5', self.do_screenshot)
|
||||
|
||||
# Task
|
||||
taskMgr.add(self.update, 'updateWorld')
|
||||
|
||||
# Physics
|
||||
self.setup()
|
||||
|
||||
def do_exit(self):
|
||||
self.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
def do_reset(self):
|
||||
self.cleanup()
|
||||
self.setup()
|
||||
|
||||
def toggle_debug(self):
|
||||
if self.debugNP.is_hidden():
|
||||
self.debugNP.show()
|
||||
else:
|
||||
self.debugNP.hide()
|
||||
|
||||
def do_screenshot(self):
|
||||
base.screenshot('Bullet')
|
||||
|
||||
def update(self, task):
|
||||
dt = globalClock.get_dt()
|
||||
self.world.do_physics(dt, 10, 0.008)
|
||||
return task.cont
|
||||
|
||||
def cleanup(self):
|
||||
self.world = None
|
||||
self.worldNP.remove_node()
|
||||
|
||||
@staticmethod
|
||||
def LVector3_rand():
|
||||
x = 2 * random.random() - 1
|
||||
y = 2 * random.random() - 1
|
||||
z = 2 * random.random() - 1
|
||||
return LVector3(x, y, z)
|
||||
|
||||
def setup(self):
|
||||
self.worldNP = render.attach_new_node('World')
|
||||
|
||||
# World
|
||||
self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug'))
|
||||
self.debugNP.show()
|
||||
|
||||
self.world = BulletWorld()
|
||||
self.world.set_gravity((0, 0, -9.81))
|
||||
self.world.set_debug_node(self.debugNP.node())
|
||||
|
||||
# Ground
|
||||
p0 = LPoint3(-20, -20, 0)
|
||||
p1 = LPoint3(-20, 20, 0)
|
||||
p2 = LPoint3(20, -20, 0)
|
||||
p3 = LPoint3(20, 20, 0)
|
||||
mesh = BulletTriangleMesh()
|
||||
mesh.add_triangle(p0, p1, p2)
|
||||
mesh.add_triangle(p1, p2, p3)
|
||||
shape = BulletTriangleMeshShape(mesh, dynamic=False)
|
||||
|
||||
np = self.worldNP.attach_new_node(BulletRigidBodyNode('Mesh'))
|
||||
np.node().add_shape(shape)
|
||||
np.set_pos(0, 0, -2)
|
||||
np.set_collide_mask(BitMask32.all_on())
|
||||
|
||||
self.world.attach(np.node())
|
||||
|
||||
# Soft body world information
|
||||
info = self.world.get_world_info()
|
||||
info.set_air_density(1.2)
|
||||
info.set_water_density(0)
|
||||
info.set_water_offset(0)
|
||||
info.set_water_normal((0, 0, 0))
|
||||
|
||||
# Softbody
|
||||
for i in range(50):
|
||||
p00 = LPoint3(-2, -2, 0)
|
||||
p10 = LPoint3( 2, -2, 0)
|
||||
p01 = LPoint3(-2, 2, 0)
|
||||
p11 = LPoint3( 2, 2, 0)
|
||||
node = BulletSoftBodyNode.make_patch(
|
||||
info, p00, p10, p01, p11, 6, 6, 0, True)
|
||||
node.generate_bending_constraints(2)
|
||||
node.get_cfg().set_lift_coefficient(0.004)
|
||||
node.get_cfg().set_dynamic_friction_coefficient(0.0003)
|
||||
node.get_cfg().set_aero_model(
|
||||
BulletSoftBodyConfig.AM_vertex_two_sided)
|
||||
node.set_total_mass(0.1)
|
||||
node.add_force((0, 2, 0), 0)
|
||||
|
||||
np = self.worldNP.attach_new_node(node)
|
||||
np.set_pos(self.LVector3_rand() * 10 + LVector3(0, 0, 20))
|
||||
np.set_hpr(self.LVector3_rand() * 16)
|
||||
self.world.attach(node)
|
||||
|
||||
fmt = GeomVertexFormat.get_v3n3t2()
|
||||
geom = BulletHelper.make_geom_from_faces(node, fmt, True)
|
||||
node.link_geom(geom)
|
||||
nodeV = GeomNode('')
|
||||
nodeV.add_geom(geom)
|
||||
npV = np.attach_new_node(nodeV)
|
||||
|
||||
tex = loader.load_texture('models/panda.jpg')
|
||||
npV.set_texture(tex)
|
||||
BulletHelper.make_texcoords_for_patch(geom, 6, 6)
|
||||
|
||||
|
||||
game = Game()
|
||||
game.run()
|
||||
4424
samples/bullet-physics/models/ball.egg
Normal file
3393
samples/bullet-physics/models/bowl.egg
Normal file
BIN
samples/bullet-physics/models/bowl.jpg
Normal file
|
After Width: | Height: | Size: 43 KiB |
137
samples/bullet-physics/models/box.egg
Normal file
@@ -0,0 +1,137 @@
|
||||
<CoordinateSystem> { Z-up }
|
||||
|
||||
<Comment> { "Egg laid by Chicken for Blender v1.0" }
|
||||
|
||||
<Texture> wood.png {
|
||||
"./wood.png"
|
||||
}
|
||||
<Group> Box {
|
||||
<VertexPool> Box {
|
||||
<Vertex> 0 {
|
||||
0.500000 -0.500000 -0.500000
|
||||
<UV> { 1.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 1 {
|
||||
-0.500000 -0.500000 -0.500000
|
||||
<UV> { 0.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 2 {
|
||||
-0.500000 0.500000 -0.500000
|
||||
<UV> { 0.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 3 {
|
||||
0.500000 0.500000 -0.500000
|
||||
<UV> { 1.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 4 {
|
||||
0.500000 -0.500000 0.500000
|
||||
<UV> { 0.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 5 {
|
||||
0.500000 0.500000 0.500000
|
||||
<UV> { 0.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 6 {
|
||||
-0.500000 0.500000 0.500000
|
||||
<UV> { 1.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 7 {
|
||||
-0.500000 -0.500000 0.500000
|
||||
<UV> { 1.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 8 {
|
||||
0.500000 -0.500000 -0.500000
|
||||
<UV> { 0.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 9 {
|
||||
0.500000 -0.500000 0.500000
|
||||
<UV> { 0.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 10 {
|
||||
-0.500000 -0.500000 0.500000
|
||||
<UV> { 1.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 11 {
|
||||
-0.500000 -0.500000 -0.500000
|
||||
<UV> { 1.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 12 {
|
||||
-0.500000 -0.500000 -0.500000
|
||||
<UV> { 1.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 13 {
|
||||
-0.500000 -0.500000 0.500000
|
||||
<UV> { 0.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 14 {
|
||||
-0.500000 0.500000 0.500000
|
||||
<UV> { 0.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 15 {
|
||||
-0.500000 0.500000 -0.500000
|
||||
<UV> { 1.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 16 {
|
||||
-0.500000 0.500000 -0.500000
|
||||
<UV> { 0.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 17 {
|
||||
-0.500000 0.500000 0.500000
|
||||
<UV> { 0.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 18 {
|
||||
0.500000 0.500000 0.500000
|
||||
<UV> { 1.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 19 {
|
||||
0.500000 0.500000 -0.500000
|
||||
<UV> { 1.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 20 {
|
||||
0.500000 -0.500000 0.500000
|
||||
<UV> { 1.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 21 {
|
||||
0.500000 -0.500000 -0.500000
|
||||
<UV> { 0.000000 1.000000 }
|
||||
}
|
||||
<Vertex> 22 {
|
||||
0.500000 0.500000 -0.500000
|
||||
<UV> { -0.000000 0.000000 }
|
||||
}
|
||||
<Vertex> 23 {
|
||||
0.500000 0.500000 0.500000
|
||||
<UV> { 1.000000 -0.000000 }
|
||||
}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<Normal> { 0.000000 0.000000 -1.000000 }
|
||||
<VertexRef> { 0 1 2 3 <Ref> { Box } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<Normal> { 0.000000 0.000000 1.000000 }
|
||||
<VertexRef> { 4 5 6 7 <Ref> { Box } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<Normal> { -0.000000 -1.000000 0.000000 }
|
||||
<VertexRef> { 8 9 10 11 <Ref> { Box } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<Normal> { -1.000000 0.000000 -0.000000 }
|
||||
<VertexRef> { 12 13 14 15 <Ref> { Box } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<Normal> { 0.000000 1.000000 -0.000000 }
|
||||
<VertexRef> { 16 17 18 19 <Ref> { Box } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<Normal> { 1.000000 -0.000000 0.000000 }
|
||||
<VertexRef> { 20 21 22 23 <Ref> { Box } }
|
||||
}
|
||||
}
|
||||
226
samples/bullet-physics/models/cube/cube.1.ele
Normal file
@@ -0,0 +1,226 @@
|
||||
224 4 0
|
||||
0 63 64 60 69
|
||||
1 10 89 12 91
|
||||
2 51 36 50 34
|
||||
3 65 68 67 33
|
||||
4 10 5 57 89
|
||||
5 68 8 55 3
|
||||
6 8 96 91 95
|
||||
7 57 58 53 5
|
||||
8 5 89 10 91
|
||||
9 8 95 13 21
|
||||
10 47 49 46 61
|
||||
11 58 5 57 4
|
||||
12 42 65 45 67
|
||||
13 57 5 10 4
|
||||
14 55 63 60 3
|
||||
15 58 63 55 3
|
||||
16 65 67 42 33
|
||||
17 46 49 48 61
|
||||
18 8 5 13 91
|
||||
19 60 62 59 66
|
||||
20 55 68 66 33
|
||||
21 51 54 37 35
|
||||
22 68 7 8 3
|
||||
23 62 66 60 69
|
||||
24 38 35 54 30
|
||||
25 71 41 77 40
|
||||
26 13 10 14 91
|
||||
27 53 89 5 90
|
||||
28 37 36 51 34
|
||||
29 16 81 82 19
|
||||
30 10 9 57 4
|
||||
31 33 92 8 80
|
||||
32 69 3 63 0
|
||||
33 46 59 47 61
|
||||
34 51 35 37 34
|
||||
35 14 10 12 91
|
||||
36 30 29 35 93
|
||||
37 55 5 8 92
|
||||
38 69 70 66 3
|
||||
39 38 47 46 59
|
||||
40 42 48 45 65
|
||||
41 39 47 38 59
|
||||
42 38 54 39 59
|
||||
43 69 2 3 0
|
||||
44 54 33 38 30
|
||||
45 60 64 62 69
|
||||
46 46 48 42 65
|
||||
47 46 61 48 65
|
||||
48 59 61 46 65
|
||||
49 83 79 84 28
|
||||
50 29 93 30 94
|
||||
51 71 43 44 40
|
||||
52 60 66 55 3
|
||||
53 55 33 54 30
|
||||
54 5 4 58 0
|
||||
55 55 5 58 3
|
||||
56 7 80 82 78
|
||||
57 53 55 51 30
|
||||
58 59 62 61 66
|
||||
59 61 65 59 66
|
||||
60 50 53 51 90
|
||||
61 70 6 7 2
|
||||
62 52 57 53 89
|
||||
63 12 9 11 89
|
||||
64 66 70 68 3
|
||||
65 54 35 51 30
|
||||
66 67 32 68 72
|
||||
67 53 90 5 92
|
||||
68 42 33 67 32
|
||||
69 25 26 83 27
|
||||
70 53 58 55 5
|
||||
71 10 9 12 89
|
||||
72 7 6 70 75
|
||||
73 51 55 54 30
|
||||
74 37 54 39 35
|
||||
75 39 54 38 35
|
||||
76 55 60 54 33
|
||||
77 53 30 51 90
|
||||
78 13 5 10 91
|
||||
79 52 53 50 90
|
||||
80 53 5 55 92
|
||||
81 55 66 60 33
|
||||
82 66 68 65 33
|
||||
83 46 65 42 33
|
||||
84 54 59 38 33
|
||||
85 54 60 59 33
|
||||
86 60 66 59 33
|
||||
87 59 66 65 33
|
||||
88 38 59 46 33
|
||||
89 59 65 46 33
|
||||
90 13 91 14 95
|
||||
91 8 17 87 21
|
||||
92 7 81 82 16
|
||||
93 58 3 5 0
|
||||
94 5 90 89 92
|
||||
95 16 19 82 20
|
||||
96 57 5 53 89
|
||||
97 69 1 2 0
|
||||
98 57 9 10 89
|
||||
99 55 8 33 92
|
||||
100 30 93 90 94
|
||||
101 51 90 30 93
|
||||
102 55 30 53 92
|
||||
103 50 90 51 93
|
||||
104 51 30 35 93
|
||||
105 11 9 56 89
|
||||
106 8 5 55 3
|
||||
107 68 33 55 8
|
||||
108 35 29 34 93
|
||||
109 70 3 69 2
|
||||
110 56 9 57 89
|
||||
111 97 85 96 83
|
||||
112 80 77 78 32
|
||||
113 63 69 60 3
|
||||
114 60 69 66 3
|
||||
115 70 7 68 3
|
||||
116 66 68 55 3
|
||||
117 69 63 64 0
|
||||
118 52 89 53 90
|
||||
119 90 92 30 94
|
||||
120 63 3 58 0
|
||||
121 56 57 52 89
|
||||
122 51 34 50 93
|
||||
123 35 34 51 93
|
||||
124 8 91 13 95
|
||||
125 33 30 55 92
|
||||
126 5 91 8 92
|
||||
127 30 90 53 92
|
||||
128 89 91 5 92
|
||||
129 7 3 70 2
|
||||
130 64 1 69 0
|
||||
131 71 44 67 41
|
||||
132 16 15 81 19
|
||||
133 8 92 91 96
|
||||
134 74 72 78 71
|
||||
135 95 87 88 21
|
||||
136 42 32 67 41
|
||||
137 77 71 32 41
|
||||
138 77 41 31 40
|
||||
139 78 74 81 72
|
||||
140 77 32 31 41
|
||||
141 68 32 78 72
|
||||
142 13 21 95 22
|
||||
143 81 18 15 76
|
||||
144 8 87 95 21
|
||||
145 15 18 81 19
|
||||
146 87 21 17 23
|
||||
147 82 81 7 78
|
||||
148 86 84 96 83
|
||||
149 79 28 27 32
|
||||
150 8 84 87 80
|
||||
151 15 16 81 75
|
||||
152 96 85 86 83
|
||||
153 88 21 87 23
|
||||
154 95 21 88 22
|
||||
155 27 31 79 32
|
||||
156 68 78 7 72
|
||||
157 68 80 7 78
|
||||
158 96 95 8 84
|
||||
159 95 87 8 84
|
||||
160 96 86 95 84
|
||||
161 88 87 95 84
|
||||
162 95 86 88 84
|
||||
163 87 82 8 80
|
||||
164 33 8 68 80
|
||||
165 79 77 80 32
|
||||
166 78 32 77 71
|
||||
167 92 96 8 80
|
||||
168 96 84 8 80
|
||||
169 8 7 68 80
|
||||
170 8 82 7 80
|
||||
171 16 82 17 20
|
||||
172 68 7 70 75
|
||||
173 81 76 15 75
|
||||
174 88 22 21 24
|
||||
175 17 20 87 23
|
||||
176 8 82 87 17
|
||||
177 7 82 8 17
|
||||
178 7 16 82 17
|
||||
179 32 72 67 71
|
||||
180 97 25 83 28
|
||||
181 97 83 96 28
|
||||
182 13 95 14 22
|
||||
183 21 23 88 24
|
||||
184 17 82 87 20
|
||||
185 81 16 7 75
|
||||
186 77 73 78 71
|
||||
187 6 16 15 75
|
||||
188 7 75 68 72
|
||||
189 83 27 79 28
|
||||
190 85 83 25 26
|
||||
191 32 71 67 41
|
||||
192 25 27 83 28
|
||||
193 79 31 77 32
|
||||
194 80 28 79 32
|
||||
195 30 25 94 28
|
||||
196 33 28 80 32
|
||||
197 85 83 97 25
|
||||
198 7 16 6 75
|
||||
199 29 94 30 25
|
||||
200 33 80 68 32
|
||||
201 94 25 97 28
|
||||
202 96 83 84 28
|
||||
203 84 79 80 28
|
||||
204 30 92 33 28
|
||||
205 92 80 33 28
|
||||
206 97 96 92 28
|
||||
207 30 94 92 28
|
||||
208 92 94 97 28
|
||||
209 84 80 96 28
|
||||
210 96 80 92 28
|
||||
211 80 78 68 32
|
||||
212 67 33 68 32
|
||||
213 78 73 74 71
|
||||
214 73 71 77 40
|
||||
215 7 78 81 72
|
||||
216 81 75 7 72
|
||||
217 76 75 81 72
|
||||
218 81 74 76 72
|
||||
219 78 72 32 71
|
||||
220 73 43 71 40
|
||||
221 44 41 71 40
|
||||
222 42 67 45 41
|
||||
223 67 44 45 41
|
||||
# Generated by tetgen -p cube.poly
|
||||
194
samples/bullet-physics/models/cube/cube.1.face
Normal file
@@ -0,0 +1,194 @@
|
||||
192 0
|
||||
0 2 0 3
|
||||
1 1 0 2
|
||||
2 7 2 3
|
||||
3 6 2 7
|
||||
4 7 16 6
|
||||
5 6 16 15
|
||||
6 16 19 15
|
||||
7 15 19 18
|
||||
8 5 0 4
|
||||
9 3 0 5
|
||||
10 8 3 5
|
||||
11 7 3 8
|
||||
12 8 17 7
|
||||
13 7 17 16
|
||||
14 17 20 16
|
||||
15 16 20 19
|
||||
16 10 4 9
|
||||
17 5 4 10
|
||||
18 13 5 10
|
||||
19 8 5 13
|
||||
20 13 21 8
|
||||
21 8 21 17
|
||||
22 21 23 17
|
||||
23 17 23 20
|
||||
24 12 9 11
|
||||
25 10 9 12
|
||||
26 14 10 12
|
||||
27 13 10 14
|
||||
28 14 22 13
|
||||
29 13 22 21
|
||||
30 22 24 21
|
||||
31 21 24 23
|
||||
32 25 27 26
|
||||
33 25 28 27
|
||||
34 28 32 27
|
||||
35 27 32 31
|
||||
36 32 41 31
|
||||
37 41 40 31
|
||||
38 44 40 41
|
||||
39 43 40 44
|
||||
40 30 25 29
|
||||
41 30 28 25
|
||||
42 33 28 30
|
||||
43 33 32 28
|
||||
44 42 32 33
|
||||
45 42 41 32
|
||||
46 45 41 42
|
||||
47 44 41 45
|
||||
48 35 29 34
|
||||
49 30 29 35
|
||||
50 38 30 35
|
||||
51 33 30 38
|
||||
52 46 33 38
|
||||
53 42 33 46
|
||||
54 46 48 42
|
||||
55 42 48 45
|
||||
56 37 34 36
|
||||
57 35 34 37
|
||||
58 39 35 37
|
||||
59 38 35 39
|
||||
60 39 47 38
|
||||
61 38 47 46
|
||||
62 47 49 46
|
||||
63 46 49 48
|
||||
64 56 57 52
|
||||
65 52 57 53
|
||||
66 57 58 53
|
||||
67 53 58 55
|
||||
68 58 63 55
|
||||
69 55 63 60
|
||||
70 63 64 60
|
||||
71 60 64 62
|
||||
72 11 9 56
|
||||
73 56 9 57
|
||||
74 9 4 57
|
||||
75 57 4 58
|
||||
76 4 0 58
|
||||
77 58 0 63
|
||||
78 64 0 1
|
||||
79 63 0 64
|
||||
80 61 65 48
|
||||
81 49 61 48
|
||||
82 65 67 45
|
||||
83 48 65 45
|
||||
84 71 44 67
|
||||
85 67 44 45
|
||||
86 73 43 71
|
||||
87 71 43 44
|
||||
88 62 66 61
|
||||
89 61 66 65
|
||||
90 66 68 65
|
||||
91 65 68 67
|
||||
92 68 72 67
|
||||
93 72 71 67
|
||||
94 74 71 72
|
||||
95 73 71 74
|
||||
96 64 69 62
|
||||
97 62 69 66
|
||||
98 69 70 66
|
||||
99 66 70 68
|
||||
100 70 75 68
|
||||
101 75 72 68
|
||||
102 76 72 75
|
||||
103 74 72 76
|
||||
104 64 1 69
|
||||
105 69 1 2
|
||||
106 69 2 70
|
||||
107 70 2 6
|
||||
108 6 75 70
|
||||
109 15 75 6
|
||||
110 18 76 15
|
||||
111 76 75 15
|
||||
112 73 40 43
|
||||
113 77 40 73
|
||||
114 79 31 77
|
||||
115 31 40 77
|
||||
116 83 27 79
|
||||
117 27 31 79
|
||||
118 85 26 83
|
||||
119 26 27 83
|
||||
120 78 73 74
|
||||
121 77 73 78
|
||||
122 80 77 78
|
||||
123 79 77 80
|
||||
124 84 79 80
|
||||
125 83 79 84
|
||||
126 86 83 84
|
||||
127 85 83 86
|
||||
128 81 74 76
|
||||
129 78 74 81
|
||||
130 82 78 81
|
||||
131 80 78 82
|
||||
132 87 80 82
|
||||
133 84 80 87
|
||||
134 88 84 87
|
||||
135 86 84 88
|
||||
136 81 76 18
|
||||
137 18 19 81
|
||||
138 81 19 82
|
||||
139 19 20 82
|
||||
140 82 20 87
|
||||
141 20 23 87
|
||||
142 87 23 88
|
||||
143 23 24 88
|
||||
144 56 89 11
|
||||
145 11 89 12
|
||||
146 89 91 12
|
||||
147 12 91 14
|
||||
148 91 95 14
|
||||
149 95 22 14
|
||||
150 88 22 95
|
||||
151 88 24 22
|
||||
152 52 89 56
|
||||
153 52 90 89
|
||||
154 50 90 52
|
||||
155 50 93 90
|
||||
156 36 34 50
|
||||
157 34 93 50
|
||||
158 90 92 89
|
||||
159 89 92 91
|
||||
160 92 96 91
|
||||
161 96 95 91
|
||||
162 96 86 95
|
||||
163 95 86 88
|
||||
164 93 94 90
|
||||
165 90 94 92
|
||||
166 92 94 97
|
||||
167 97 96 92
|
||||
168 97 85 96
|
||||
169 96 85 86
|
||||
170 29 93 34
|
||||
171 29 94 93
|
||||
172 29 25 94
|
||||
173 94 25 97
|
||||
174 25 26 85
|
||||
175 97 25 85
|
||||
176 51 36 50
|
||||
177 37 36 51
|
||||
178 51 54 37
|
||||
179 37 54 39
|
||||
180 54 59 39
|
||||
181 39 59 47
|
||||
182 59 61 47
|
||||
183 47 61 49
|
||||
184 52 53 50
|
||||
185 50 53 51
|
||||
186 53 55 51
|
||||
187 51 55 54
|
||||
188 55 60 54
|
||||
189 54 60 59
|
||||
190 60 62 59
|
||||
191 59 62 61
|
||||
# Generated by tetgen.exe -pq cube.poly
|
||||
100
samples/bullet-physics/models/cube/cube.1.node
Normal file
@@ -0,0 +1,100 @@
|
||||
98 3 0 0
|
||||
0 2 -1 -2
|
||||
1 2 -2 -2
|
||||
2 1 -2 -2
|
||||
3 1 -1 -2
|
||||
4 2 0 -2
|
||||
5 1 0 -2
|
||||
6 -0 -2 -2
|
||||
7 0 -1 -2
|
||||
8 0 0 -2
|
||||
9 2 1 -2
|
||||
10 1 1 -2
|
||||
11 2 2 -2
|
||||
12 1 2 -2
|
||||
13 0 1 -2
|
||||
14 0 2 -2
|
||||
15 -1 -2 -2
|
||||
16 -1 -1 -2
|
||||
17 -1 0 -2
|
||||
18 -2 -2 -2
|
||||
19 -2 -1 -2
|
||||
20 -2 0 -2
|
||||
21 -1 1 -2
|
||||
22 -1 2 -2
|
||||
23 -2 1 -2
|
||||
24 -2 2 -2
|
||||
25 -1 2 2
|
||||
26 -2 2 2
|
||||
27 -2 1 2
|
||||
28 -1 1 2
|
||||
29 0 2 2
|
||||
30 0 1 2
|
||||
31 -2 0 2
|
||||
32 -1 0 2
|
||||
33 -0 -0 2
|
||||
34 1 2 2
|
||||
35 1 1 2
|
||||
36 2 2 2
|
||||
37 2 1 2
|
||||
38 1 -0 2
|
||||
39 2 -0 2
|
||||
40 -2 -1 2
|
||||
41 -1 -1 2
|
||||
42 -0 -1 2
|
||||
43 -2 -2 2
|
||||
44 -1 -2 2
|
||||
45 -0 -2 2
|
||||
46 1 -1 2
|
||||
47 2 -1 2
|
||||
48 1 -2 2
|
||||
49 2 -2 2
|
||||
50 2 2 1
|
||||
51 2 1 1
|
||||
52 2 2 0
|
||||
53 2 1 0
|
||||
54 2 -0 1
|
||||
55 2 -0 0
|
||||
56 2 2 -1
|
||||
57 2 1 -1
|
||||
58 2 -0 -1
|
||||
59 2 -1 1
|
||||
60 2 -1 0
|
||||
61 2 -2 1
|
||||
62 2 -2 0
|
||||
63 2 -1 -1
|
||||
64 2 -2 -1
|
||||
65 1 -2 1
|
||||
66 1 -2 0
|
||||
67 -0 -2 1
|
||||
68 -0 -2 0
|
||||
69 1 -2 -1
|
||||
70 -0 -2 -1
|
||||
71 -1 -2 1
|
||||
72 -1 -2 0
|
||||
73 -2 -2 1
|
||||
74 -2 -2 0
|
||||
75 -1 -2 -1
|
||||
76 -2 -2 -1
|
||||
77 -2 -1 1
|
||||
78 -2 -1 0
|
||||
79 -2 0 1
|
||||
80 -2 0 0
|
||||
81 -2 -1 -1
|
||||
82 -2 0 -1
|
||||
83 -2 1 1
|
||||
84 -2 1 0
|
||||
85 -2 2 1
|
||||
86 -2 2 0
|
||||
87 -2 1 -1
|
||||
88 -2 2 -1
|
||||
89 1 2 -1
|
||||
90 1 2 0
|
||||
91 0 2 -1
|
||||
92 0 2 0
|
||||
93 1 2 1
|
||||
94 0 2 1
|
||||
95 -1 2 -1
|
||||
96 -1 2 0
|
||||
97 -1 2 1
|
||||
# Generated by tetgen -p cube.poly
|
||||
3664
samples/bullet-physics/models/cube/cube.egg
Normal file
493
samples/bullet-physics/models/cube/cube.poly
Normal file
@@ -0,0 +1,493 @@
|
||||
# Nodes
|
||||
98 3 0 0
|
||||
0 2.00000 -1.00000 -2.00000
|
||||
1 2.00000 -2.00000 -2.00000
|
||||
2 1.00000 -2.00000 -2.00000
|
||||
3 1.00000 -1.00000 -2.00000
|
||||
4 2.00000 0.00000 -2.00000
|
||||
5 1.00000 0.00000 -2.00000
|
||||
6 -0.00000 -2.00000 -2.00000
|
||||
7 0.00000 -1.00000 -2.00000
|
||||
8 0.00000 0.00000 -2.00000
|
||||
9 2.00000 1.00000 -2.00000
|
||||
10 1.00000 1.00000 -2.00000
|
||||
11 2.00000 2.00000 -2.00000
|
||||
12 1.00000 2.00000 -2.00000
|
||||
13 0.00000 1.00000 -2.00000
|
||||
14 0.00000 2.00000 -2.00000
|
||||
15 -1.00000 -2.00000 -2.00000
|
||||
16 -1.00000 -1.00000 -2.00000
|
||||
17 -1.00000 0.00000 -2.00000
|
||||
18 -2.00000 -2.00000 -2.00000
|
||||
19 -2.00000 -1.00000 -2.00000
|
||||
20 -2.00000 0.00000 -2.00000
|
||||
21 -1.00000 1.00000 -2.00000
|
||||
22 -1.00000 2.00000 -2.00000
|
||||
23 -2.00000 1.00000 -2.00000
|
||||
24 -2.00000 2.00000 -2.00000
|
||||
25 -1.00000 2.00000 2.00000
|
||||
26 -2.00000 2.00000 2.00000
|
||||
27 -2.00000 1.00000 2.00000
|
||||
28 -1.00000 1.00000 2.00000
|
||||
29 0.00000 2.00000 2.00000
|
||||
30 0.00000 1.00000 2.00000
|
||||
31 -2.00000 0.00000 2.00000
|
||||
32 -1.00000 0.00000 2.00000
|
||||
33 -0.00000 -0.00000 2.00000
|
||||
34 1.00000 2.00000 2.00000
|
||||
35 1.00000 1.00000 2.00000
|
||||
36 2.00000 2.00000 2.00000
|
||||
37 2.00000 1.00000 2.00000
|
||||
38 1.00000 -0.00000 2.00000
|
||||
39 2.00000 -0.00000 2.00000
|
||||
40 -2.00000 -1.00000 2.00000
|
||||
41 -1.00000 -1.00000 2.00000
|
||||
42 -0.00000 -1.00000 2.00000
|
||||
43 -2.00000 -2.00000 2.00000
|
||||
44 -1.00000 -2.00000 2.00000
|
||||
45 -0.00000 -2.00000 2.00000
|
||||
46 1.00000 -1.00000 2.00000
|
||||
47 2.00000 -1.00000 2.00000
|
||||
48 1.00000 -2.00000 2.00000
|
||||
49 2.00000 -2.00000 2.00000
|
||||
50 2.00000 2.00000 1.00000
|
||||
51 2.00000 1.00000 1.00000
|
||||
52 2.00000 2.00000 0.00000
|
||||
53 2.00000 1.00000 0.00000
|
||||
54 2.00000 -0.00000 1.00000
|
||||
55 2.00000 -0.00000 0.00000
|
||||
56 2.00000 2.00000 -1.00000
|
||||
57 2.00000 1.00000 -1.00000
|
||||
58 2.00000 -0.00000 -1.00000
|
||||
59 2.00000 -1.00000 1.00000
|
||||
60 2.00000 -1.00000 0.00000
|
||||
61 2.00000 -2.00000 1.00000
|
||||
62 2.00000 -2.00000 0.00000
|
||||
63 2.00000 -1.00000 -1.00000
|
||||
64 2.00000 -2.00000 -1.00000
|
||||
65 1.00000 -2.00000 1.00000
|
||||
66 1.00000 -2.00000 0.00000
|
||||
67 -0.00000 -2.00000 1.00000
|
||||
68 -0.00000 -2.00000 0.00000
|
||||
69 1.00000 -2.00000 -1.00000
|
||||
70 -0.00000 -2.00000 -1.00000
|
||||
71 -1.00000 -2.00000 1.00000
|
||||
72 -1.00000 -2.00000 0.00000
|
||||
73 -2.00000 -2.00000 1.00000
|
||||
74 -2.00000 -2.00000 0.00000
|
||||
75 -1.00000 -2.00000 -1.00000
|
||||
76 -2.00000 -2.00000 -1.00000
|
||||
77 -2.00000 -1.00000 1.00000
|
||||
78 -2.00000 -1.00000 0.00000
|
||||
79 -2.00000 0.00000 1.00000
|
||||
80 -2.00000 0.00000 0.00000
|
||||
81 -2.00000 -1.00000 -1.00000
|
||||
82 -2.00000 0.00000 -1.00000
|
||||
83 -2.00000 1.00000 1.00000
|
||||
84 -2.00000 1.00000 0.00000
|
||||
85 -2.00000 2.00000 1.00000
|
||||
86 -2.00000 2.00000 0.00000
|
||||
87 -2.00000 1.00000 -1.00000
|
||||
88 -2.00000 2.00000 -1.00000
|
||||
89 1.00000 2.00000 -1.00000
|
||||
90 1.00000 2.00000 0.00000
|
||||
91 0.00000 2.00000 -1.00000
|
||||
92 0.00000 2.00000 0.00000
|
||||
93 1.00000 2.00000 1.00000
|
||||
94 0.00000 2.00000 1.00000
|
||||
95 -1.00000 2.00000 -1.00000
|
||||
96 -1.00000 2.00000 0.00000
|
||||
97 -1.00000 2.00000 1.00000
|
||||
|
||||
# Facets
|
||||
192 0
|
||||
1
|
||||
3 0 1 3
|
||||
1
|
||||
3 3 1 2
|
||||
1
|
||||
3 3 2 7
|
||||
1
|
||||
3 7 2 6
|
||||
1
|
||||
3 7 6 16
|
||||
1
|
||||
3 16 6 15
|
||||
1
|
||||
3 16 15 19
|
||||
1
|
||||
3 19 15 18
|
||||
1
|
||||
3 4 0 5
|
||||
1
|
||||
3 5 0 3
|
||||
1
|
||||
3 5 3 8
|
||||
1
|
||||
3 8 3 7
|
||||
1
|
||||
3 8 7 17
|
||||
1
|
||||
3 17 7 16
|
||||
1
|
||||
3 17 16 20
|
||||
1
|
||||
3 20 16 19
|
||||
1
|
||||
3 9 4 10
|
||||
1
|
||||
3 10 4 5
|
||||
1
|
||||
3 10 5 13
|
||||
1
|
||||
3 13 5 8
|
||||
1
|
||||
3 13 8 21
|
||||
1
|
||||
3 21 8 17
|
||||
1
|
||||
3 21 17 23
|
||||
1
|
||||
3 23 17 20
|
||||
1
|
||||
3 11 9 12
|
||||
1
|
||||
3 12 9 10
|
||||
1
|
||||
3 12 10 14
|
||||
1
|
||||
3 14 10 13
|
||||
1
|
||||
3 14 13 22
|
||||
1
|
||||
3 22 13 21
|
||||
1
|
||||
3 22 21 24
|
||||
1
|
||||
3 24 21 23
|
||||
1
|
||||
3 25 26 28
|
||||
1
|
||||
3 28 26 27
|
||||
1
|
||||
3 28 27 32
|
||||
1
|
||||
3 32 27 31
|
||||
1
|
||||
3 32 31 41
|
||||
1
|
||||
3 41 31 40
|
||||
1
|
||||
3 41 40 44
|
||||
1
|
||||
3 44 40 43
|
||||
1
|
||||
3 29 25 30
|
||||
1
|
||||
3 30 25 28
|
||||
1
|
||||
3 30 28 33
|
||||
1
|
||||
3 33 28 32
|
||||
1
|
||||
3 33 32 42
|
||||
1
|
||||
3 42 32 41
|
||||
1
|
||||
3 42 41 45
|
||||
1
|
||||
3 45 41 44
|
||||
1
|
||||
3 34 29 35
|
||||
1
|
||||
3 35 29 30
|
||||
1
|
||||
3 35 30 38
|
||||
1
|
||||
3 38 30 33
|
||||
1
|
||||
3 38 33 46
|
||||
1
|
||||
3 46 33 42
|
||||
1
|
||||
3 46 42 48
|
||||
1
|
||||
3 48 42 45
|
||||
1
|
||||
3 36 34 37
|
||||
1
|
||||
3 37 34 35
|
||||
1
|
||||
3 37 35 39
|
||||
1
|
||||
3 39 35 38
|
||||
1
|
||||
3 39 38 47
|
||||
1
|
||||
3 47 38 46
|
||||
1
|
||||
3 47 46 49
|
||||
1
|
||||
3 49 46 48
|
||||
1
|
||||
3 56 52 57
|
||||
1
|
||||
3 57 52 53
|
||||
1
|
||||
3 57 53 58
|
||||
1
|
||||
3 58 53 55
|
||||
1
|
||||
3 58 55 63
|
||||
1
|
||||
3 63 55 60
|
||||
1
|
||||
3 63 60 64
|
||||
1
|
||||
3 64 60 62
|
||||
1
|
||||
3 11 56 9
|
||||
1
|
||||
3 9 56 57
|
||||
1
|
||||
3 9 57 4
|
||||
1
|
||||
3 4 57 58
|
||||
1
|
||||
3 4 58 0
|
||||
1
|
||||
3 0 58 63
|
||||
1
|
||||
3 0 63 1
|
||||
1
|
||||
3 1 63 64
|
||||
1
|
||||
3 61 49 65
|
||||
1
|
||||
3 65 49 48
|
||||
1
|
||||
3 65 48 67
|
||||
1
|
||||
3 67 48 45
|
||||
1
|
||||
3 67 45 71
|
||||
1
|
||||
3 71 45 44
|
||||
1
|
||||
3 71 44 73
|
||||
1
|
||||
3 73 44 43
|
||||
1
|
||||
3 62 61 66
|
||||
1
|
||||
3 66 61 65
|
||||
1
|
||||
3 66 65 68
|
||||
1
|
||||
3 68 65 67
|
||||
1
|
||||
3 68 67 72
|
||||
1
|
||||
3 72 67 71
|
||||
1
|
||||
3 72 71 74
|
||||
1
|
||||
3 74 71 73
|
||||
1
|
||||
3 64 62 69
|
||||
1
|
||||
3 69 62 66
|
||||
1
|
||||
3 69 66 70
|
||||
1
|
||||
3 70 66 68
|
||||
1
|
||||
3 70 68 75
|
||||
1
|
||||
3 75 68 72
|
||||
1
|
||||
3 75 72 76
|
||||
1
|
||||
3 76 72 74
|
||||
1
|
||||
3 1 64 2
|
||||
1
|
||||
3 2 64 69
|
||||
1
|
||||
3 2 69 6
|
||||
1
|
||||
3 6 69 70
|
||||
1
|
||||
3 6 70 15
|
||||
1
|
||||
3 15 70 75
|
||||
1
|
||||
3 15 75 18
|
||||
1
|
||||
3 18 75 76
|
||||
1
|
||||
3 73 43 77
|
||||
1
|
||||
3 77 43 40
|
||||
1
|
||||
3 77 40 79
|
||||
1
|
||||
3 79 40 31
|
||||
1
|
||||
3 79 31 83
|
||||
1
|
||||
3 83 31 27
|
||||
1
|
||||
3 83 27 85
|
||||
1
|
||||
3 85 27 26
|
||||
1
|
||||
3 74 73 78
|
||||
1
|
||||
3 78 73 77
|
||||
1
|
||||
3 78 77 80
|
||||
1
|
||||
3 80 77 79
|
||||
1
|
||||
3 80 79 84
|
||||
1
|
||||
3 84 79 83
|
||||
1
|
||||
3 84 83 86
|
||||
1
|
||||
3 86 83 85
|
||||
1
|
||||
3 76 74 81
|
||||
1
|
||||
3 81 74 78
|
||||
1
|
||||
3 81 78 82
|
||||
1
|
||||
3 82 78 80
|
||||
1
|
||||
3 82 80 87
|
||||
1
|
||||
3 87 80 84
|
||||
1
|
||||
3 87 84 88
|
||||
1
|
||||
3 88 84 86
|
||||
1
|
||||
3 18 76 19
|
||||
1
|
||||
3 19 76 81
|
||||
1
|
||||
3 19 81 20
|
||||
1
|
||||
3 20 81 82
|
||||
1
|
||||
3 20 82 23
|
||||
1
|
||||
3 23 82 87
|
||||
1
|
||||
3 23 87 24
|
||||
1
|
||||
3 24 87 88
|
||||
1
|
||||
3 56 11 89
|
||||
1
|
||||
3 89 11 12
|
||||
1
|
||||
3 89 12 91
|
||||
1
|
||||
3 91 12 14
|
||||
1
|
||||
3 91 14 95
|
||||
1
|
||||
3 95 14 22
|
||||
1
|
||||
3 95 22 88
|
||||
1
|
||||
3 88 22 24
|
||||
1
|
||||
3 56 89 52
|
||||
1
|
||||
3 52 89 90
|
||||
1
|
||||
3 52 90 50
|
||||
1
|
||||
3 50 90 93
|
||||
1
|
||||
3 50 93 36
|
||||
1
|
||||
3 36 93 34
|
||||
1
|
||||
3 90 89 92
|
||||
1
|
||||
3 92 89 91
|
||||
1
|
||||
3 92 91 96
|
||||
1
|
||||
3 96 91 95
|
||||
1
|
||||
3 96 95 86
|
||||
1
|
||||
3 86 95 88
|
||||
1
|
||||
3 93 90 94
|
||||
1
|
||||
3 94 90 92
|
||||
1
|
||||
3 94 92 97
|
||||
1
|
||||
3 97 92 96
|
||||
1
|
||||
3 97 96 85
|
||||
1
|
||||
3 85 96 86
|
||||
1
|
||||
3 34 93 29
|
||||
1
|
||||
3 29 93 94
|
||||
1
|
||||
3 29 94 25
|
||||
1
|
||||
3 25 94 97
|
||||
1
|
||||
3 25 97 26
|
||||
1
|
||||
3 26 97 85
|
||||
1
|
||||
3 50 36 51
|
||||
1
|
||||
3 51 36 37
|
||||
1
|
||||
3 51 37 54
|
||||
1
|
||||
3 54 37 39
|
||||
1
|
||||
3 54 39 59
|
||||
1
|
||||
3 59 39 47
|
||||
1
|
||||
3 59 47 61
|
||||
1
|
||||
3 61 47 49
|
||||
1
|
||||
3 52 50 53
|
||||
1
|
||||
3 53 50 51
|
||||
1
|
||||
3 53 51 55
|
||||
1
|
||||
3 55 51 54
|
||||
1
|
||||
3 55 54 60
|
||||
1
|
||||
3 60 54 59
|
||||
1
|
||||
3 60 59 62
|
||||
1
|
||||
3 62 59 61
|
||||
|
||||
# Holes
|
||||
0
|
||||
|
||||
# Regions
|
||||
0
|
||||
2345
samples/bullet-physics/models/egg.egg
Normal file
BIN
samples/bullet-physics/models/egg.jpg
Normal file
|
After Width: | Height: | Size: 367 KiB |
BIN
samples/bullet-physics/models/elevation.png
Normal file
|
After Width: | Height: | Size: 695 B |
BIN
samples/bullet-physics/models/iron.jpg
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
samples/bullet-physics/models/limba.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
26316
samples/bullet-physics/models/maze.egg
Normal file
BIN
samples/bullet-physics/models/panda.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
188
samples/bullet-physics/models/pyramid.egg
Normal file
@@ -0,0 +1,188 @@
|
||||
<CoordinateSystem> { Z-up }
|
||||
|
||||
<Comment> { "Egg laid by Chicken for Blender, version R85" }
|
||||
|
||||
<Material> Material {
|
||||
<Scalar> diffr {0.800000011921}
|
||||
<Scalar> diffg {0.800000011921}
|
||||
<Scalar> diffb {0.800000011921}
|
||||
<Scalar> specr {0.25}
|
||||
<Scalar> specg {0.25}
|
||||
<Scalar> specb {0.25}
|
||||
<Scalar> shininess {12.5}
|
||||
}
|
||||
<Texture> wood.png {
|
||||
"./wood.png"
|
||||
<Scalar> saved-result { 1 }
|
||||
<Scalar> envtype { MODULATE }
|
||||
<Scalar> minfilter { LINEAR }
|
||||
<Scalar> magfilter { LINEAR }
|
||||
<Scalar> wrap { REPEAT }
|
||||
}
|
||||
<Group> Cube {
|
||||
<VertexPool> Cube {
|
||||
<Vertex> 0 {
|
||||
1.0 0.999999940395 -1.0
|
||||
<UV> {
|
||||
0.000000 0.000000
|
||||
<Tangent> { 0.182574 0.912871 -0.365148 }
|
||||
<Binormal> { -0.912871 0.182574 -0.000000 }
|
||||
}
|
||||
}
|
||||
<Vertex> 1 {
|
||||
1.0 -1.0 -1.0
|
||||
<UV> {
|
||||
1.000000 0.000000
|
||||
<Tangent> { 0.000000 1.000000 0.000000 }
|
||||
<Binormal> { -1.000000 0.000000 -0.000000 }
|
||||
}
|
||||
}
|
||||
<Vertex> 2 {
|
||||
-1.00000011921 -0.999999821186 -1.0
|
||||
<UV> {
|
||||
1.000000 1.000000
|
||||
<Tangent> { 0.267261 0.801784 -0.534522 }
|
||||
<Binormal> { -0.801784 0.267261 -0.000000 }
|
||||
}
|
||||
}
|
||||
<Vertex> 3 {
|
||||
-0.999999642372 1.00000035763 -1.0
|
||||
<UV> {
|
||||
0.000000 1.000000
|
||||
<Tangent> { 0.000000 1.000000 0.000000 }
|
||||
<Binormal> { -1.000000 0.000000 -0.000000 }
|
||||
}
|
||||
}
|
||||
<Vertex> 4 {
|
||||
1.0 0.999999940395 -1.0
|
||||
<UV> {
|
||||
0.000000 0.000000
|
||||
<Tangent> { 0.182574 0.912871 -0.365148 }
|
||||
<Binormal> { 0.408248 -0.408248 -0.816497 }
|
||||
}
|
||||
}
|
||||
<Vertex> 5 {
|
||||
-1.34110450745e-07 -1.63912773132e-07 1.0
|
||||
<UV> {
|
||||
1.000000 0.000000
|
||||
<Tangent> { 0.162221 -0.162221 -0.973329 }
|
||||
<Binormal> { -0.072548 -0.943119 0.145095 }
|
||||
}
|
||||
}
|
||||
<Vertex> 6 {
|
||||
1.0 -1.0 -1.0
|
||||
<UV> {
|
||||
1.000000 1.000000
|
||||
<Tangent> { 0.408248 0.408248 -0.816497 }
|
||||
<Binormal> { 0.182574 -0.912871 -0.365148 }
|
||||
}
|
||||
}
|
||||
<Vertex> 7 {
|
||||
1.0 -1.0 -1.0
|
||||
<UV> {
|
||||
0.000000 0.000000
|
||||
<Tangent> { 0.408248 -0.408248 -0.816497 }
|
||||
<Binormal> { -0.912871 -0.182574 -0.365148 }
|
||||
}
|
||||
}
|
||||
<Vertex> 8 {
|
||||
-1.34110450745e-07 -1.63912773132e-07 1.0
|
||||
<UV> {
|
||||
1.000000 0.000000
|
||||
<Tangent> { 0.162221 -0.162221 -0.973329 }
|
||||
<Binormal> { -0.943119 -0.072548 -0.145095 }
|
||||
}
|
||||
}
|
||||
<Vertex> 9 {
|
||||
-1.00000011921 -0.999999821186 -1.0
|
||||
<UV> {
|
||||
1.000000 1.000000
|
||||
<Tangent> { 0.267261 0.801784 -0.534522 }
|
||||
<Binormal> { -0.119523 -0.119523 -0.239046 }
|
||||
}
|
||||
}
|
||||
<Vertex> 10 {
|
||||
-1.00000011921 -0.999999821186 -1.0
|
||||
<UV> {
|
||||
0.000000 0.000000
|
||||
<Tangent> { -0.408248 -0.408248 -0.816497 }
|
||||
<Binormal> { -0.182574 0.912871 -0.365148 }
|
||||
}
|
||||
}
|
||||
<Vertex> 11 {
|
||||
-1.34110450745e-07 -1.63912773132e-07 1.0
|
||||
<UV> {
|
||||
1.000000 0.000000
|
||||
<Tangent> { 0.162221 -0.162221 -0.973329 }
|
||||
<Binormal> { -0.072547 0.798024 -0.145095 }
|
||||
}
|
||||
}
|
||||
<Vertex> 12 {
|
||||
-0.999999642372 1.00000035763 -1.0
|
||||
<UV> {
|
||||
1.000000 1.000000
|
||||
<Tangent> { -0.707107 -0.707107 0.000000 }
|
||||
<Binormal> { -0.316228 0.316228 -0.632456 }
|
||||
}
|
||||
}
|
||||
<Vertex> 13 {
|
||||
-1.34110450745e-07 -1.63912773132e-07 1.0
|
||||
<UV> {
|
||||
0.000000 0.000000
|
||||
<Tangent> { -0.408248 -0.408248 0.816497 }
|
||||
<Binormal> { -0.912871 0.182574 -0.365148 }
|
||||
}
|
||||
}
|
||||
<Vertex> 14 {
|
||||
1.0 0.999999940395 -1.0
|
||||
<UV> {
|
||||
1.000000 0.000000
|
||||
<Tangent> { -0.408248 -0.408248 0.816497 }
|
||||
<Binormal> { -0.912871 0.182574 -0.365148 }
|
||||
}
|
||||
}
|
||||
<Vertex> 15 {
|
||||
-0.999999642372 1.00000035763 -1.0
|
||||
<UV> {
|
||||
1.000000 1.000000
|
||||
<Tangent> { -0.707107 -0.707107 0.000000 }
|
||||
<Binormal> { -0.316228 0.316228 -0.632455 }
|
||||
}
|
||||
}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<MRef> { Material }
|
||||
<Normal> { 0.000000 0.000000 -1.000000
|
||||
}
|
||||
<VertexRef> { 0 1 2 3 <Ref> { Cube } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<MRef> { Material }
|
||||
<Normal> { 0.894427 0.000000 0.447214
|
||||
}
|
||||
<VertexRef> { 4 5 6 <Ref> { Cube } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<MRef> { Material }
|
||||
<Normal> { -0.000000 -0.894427 0.447214
|
||||
}
|
||||
<VertexRef> { 7 8 9 <Ref> { Cube } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<MRef> { Material }
|
||||
<Normal> { -0.894427 0.000000 0.447214
|
||||
}
|
||||
<VertexRef> { 10 11 12 <Ref> { Cube } }
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { wood.png }
|
||||
<MRef> { Material }
|
||||
<Normal> { 0.000000 0.894427 0.447214
|
||||
}
|
||||
<VertexRef> { 13 14 15 <Ref> { Cube } }
|
||||
}
|
||||
}
|
||||
3777
samples/bullet-physics/models/softbox.egg
Normal file
3304
samples/bullet-physics/models/torus.egg
Normal file
BIN
samples/bullet-physics/models/wood.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
120376
samples/bullet-physics/models/yugo/yugo.egg
Normal file
BIN
samples/bullet-physics/models/yugo/yugo.png
Normal file
|
After Width: | Height: | Size: 444 KiB |
BIN
samples/bullet-physics/models/yugo/yugotire.png
Normal file
|
After Width: | Height: | Size: 69 KiB |