示例#1
0
    def __init__(self):
        ShowBase.__init__(self)

        dlight = DirectionalLight('dlight')
        dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        self.render.setLight(dlnp)

        self.balls = [Ball(self) for x in range(NUMBALLS)]

        # Setup our physics world and the body
        self.world = OdeWorld()
        self.world.setGravity(0, 0, -9.81)
        if 0:
            self.body = OdeBody(self.world)
            M = OdeMass()
            M.setSphere(7874, 1.0)
            self.body.setMass(M)
            self.body.setPosition(self.sphere.getPos(self.render))
            self.body.setQuaternion(self.sphere.getQuat(self.render))

        ## Set the camera position
        self.disableMouse()
        self.angle = 0.0
        self.camera.setPos(1000, 1000, 1000)
        self.camera.lookAt(0, 0, 0)
        #self.enableMouse()
        # Create an accumulator to track the time since the sim
        # has been running
        self.deltaTimeAccumulator = 0.0
        # This stepSize makes the simulation run at 60 frames per second
        self.stepSize = 1.0 / 60.0

        taskMgr.doMethodLater(1.0, self.simulationTask, "Physics Simulation")
示例#2
0
class Element:
    def __init__(self, app, nom, modele, texture_chemin=None):
        self.app = app
        self.nom = nom

        self.corps = OdeBody(self.app.monde)

        # Chargement du modele
        self.modele = modele

        if texture_chemin is not None:
            tex = app.loader.loadTexture(texture_chemin)

            # Association de la texture au modele
            self.modele.setTexture(tex)

        # Ajout de l'objet a la scene
        self.modele.reparentTo(self.app.render)

    def set_position(self, x, y, z):
        if self.modele is not None:
            self.modele.setPos(x, y, z)

    def get_position(self):
        return self.modele.getPos()

    def set_rotation(self, x, y, z):
        if self.modele is not None:
            self.modele.setHpr(x, y, z)

    def set_taille(self, x, y, z):
        taille = self.get_taille()
        echelle_modele = self.modele.getScale()

        if taille is not None and echelle_modele is not None:
            self.modele.setScale(
                x * echelle_modele.x / (taille.x if taille.x > 0 else 1),
                y * echelle_modele.y / (taille.z if taille.z > 0 else 1),
                z * echelle_modele.z / (taille.y if taille.y > 0 else 1))

    def get_taille(self):
        bounds = self.modele.getTightBounds()

        if bounds is not None:
            bound_min, bound_max = bounds
            return LPoint3f(abs(bound_max.x - bound_min.x),
                            abs(bound_max.y - bound_min.y),
                            abs(bound_max.z - bound_min.z))

        return bounds

    def maj_physique(self):
        self.modele.setPosQuat(self.app.render, self.corps.getPosition(),
                               Quat(self.corps.getQuaternion()))
示例#3
0
def createBonded():
    global world
    electrons.append(
        electron(random.randint(-10, 10), random.randint(-10, 10),
                 random.randint(-10, 10), True))
    body = OdeBody(world)
    M = OdeMass()
    M.setSphere(7874, 1.0)
    body.setMass(M)
    bodies.append(body)
    button4.setText(("Remove Bonded Pair", "Destroy", "Destroy", "disabled"))
示例#4
0
    def __init__(self):
        ShowBase.__init__(self)

        dlight = DirectionalLight("dlight")
        dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        self.render.setLight(dlnp)

        self.balls = [Ball(self) for x in range(NUMBALLS)]

        # Setup our physics world and the body
        self.world = OdeWorld()
        self.world.setGravity(0, 0, -9.81)
        if 0:
            self.body = OdeBody(self.world)
            M = OdeMass()
            M.setSphere(7874, 1.0)
            self.body.setMass(M)
            self.body.setPosition(self.sphere.getPos(self.render))
            self.body.setQuaternion(self.sphere.getQuat(self.render))

        ## Set the camera position
        self.disableMouse()
        self.angle = 0.0
        self.camera.setPos(1000, 1000, 1000)
        self.camera.lookAt(0, 0, 0)
        # self.enableMouse()
        # Create an accumulator to track the time since the sim
        # has been running
        self.deltaTimeAccumulator = 0.0
        # This stepSize makes the simulation run at 60 frames per second
        self.stepSize = 1.0 / 60.0

        taskMgr.doMethodLater(1.0, self.simulationTask, "Physics Simulation")
示例#5
0
    def add_smiley(self, x, y, z):
        sm = render.attachNewNode("smiley-instance")
        sm.setPos(x, y, z)
        self.smiley.instanceTo(sm)

        body = OdeBody(self.world)
        mass = OdeMass()
        mass.setSphereTotal(10, 1)
        body.setMass(mass)
        body.setPosition(sm.getPos())
        geom = OdeSphereGeom(self.space, 1)
        geom.setBody(body)

        sm.setPythonTag("body", body)

        return body
示例#6
0
    def __init__(self, app, nom, modele, texture_chemin=None):
        self.app = app
        self.nom = nom

        self.corps = OdeBody(self.app.monde)

        # Chargement du modele
        self.modele = modele

        if texture_chemin is not None:
            tex = app.loader.loadTexture(texture_chemin)

            # Association de la texture au modele
            self.modele.setTexture(tex)

        # Ajout de l'objet a la scene
        self.modele.reparentTo(self.app.render)
示例#7
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        dlight = DirectionalLight('dlight')
        dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        self.render.setLight(dlnp)

        self.balls = [Ball(self) for x in range(NUMBALLS)]

        # Setup our physics world and the body
        self.world = OdeWorld()
        self.world.setGravity(0, 0, -9.81)
        if 0:
            self.body = OdeBody(self.world)
            M = OdeMass()
            M.setSphere(7874, 1.0)
            self.body.setMass(M)
            self.body.setPosition(self.sphere.getPos(self.render))
            self.body.setQuaternion(self.sphere.getQuat(self.render))

        ## Set the camera position
        self.disableMouse()
        self.angle = 0.0
        self.camera.setPos(1000, 1000, 1000)
        self.camera.lookAt(0, 0, 0)
        #self.enableMouse()
        # Create an accumulator to track the time since the sim
        # has been running
        self.deltaTimeAccumulator = 0.0
        # This stepSize makes the simulation run at 60 frames per second
        self.stepSize = 1.0 / 60.0

        taskMgr.doMethodLater(1.0, self.simulationTask, "Physics Simulation")

    def simulationTask(self, task):
        if 0:
            # Add the deltaTime for the task to the accumulator
            self.deltaTimeAccumulator += globalClock.getDt()
            while self.deltaTimeAccumulator > self.stepSize:
                # Remove a stepSize from the accumulator until
                # the accumulated time is less than the stepsize
                self.deltaTimeAccumulator -= self.stepSize
                # Step the simulation
                self.world.quickStep(self.stepSize)
        for ball in self.balls:
            ball.evolve()
        deltas = [ball.getdelta(self.balls) for ball in self.balls]
        for i, ball in enumerate(self.balls):
            dx, dy, dz = deltas[i]
            ball.move(dx, dy, dz)
            ball.update()
        #print "moved"
        self.camera.setPos(CX + 2500 * math.sin(self.angle),
                           CY + 2500 * math.cos(self.angle), CZ)
        self.camera.lookAt(CX, CY, CZ)
        self.angle += 0.01
        return task.cont
示例#8
0
def zapolnenie(world, n, mi, ma):
    for i in range(n):
        sphere = loader.loadModel("smiley.egg")
        sphere.reparentTo(render)
        r = randint(mi, ma)
        sphere.setPos(
            sin(i * 2 * pi / n) * r,
            cos(i * 2 * pi / n) * r, r // 1.5)

        sphereBody = OdeBody(world.myWorld)
        sphereModel = OdeMass()
        sphereModel.setSphere(1, 2)
        sphereBody.setMass(sphereModel)
        sphereBody.setPosition(
            sin(i * 2 * pi / n) * r,
            cos(i * 2 * pi / n) * r, r // 1.5)
        world.spheres.append(sphereBody)
        world.objs.append(sphere)

    for i in range(n - 1):
        sphereJoint = OdeBallJoint(world.myWorld)
        sphereJoint.attach(world.spheres[i], world.spheres[i + 1])
        sphereJoint.setAnchor(world.spheres[i].getPosition())
        world.joints.append(sphereJoint)
    sphereJoint = OdeBallJoint(world.myWorld)
    sphereJoint.attach(world.spheres[-1], world.spheres[0])
    sphereJoint.setAnchor(world.spheres[-1].getPosition())
    world.joints.append(sphereJoint)
示例#9
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        dlight = DirectionalLight("dlight")
        dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        self.render.setLight(dlnp)

        self.balls = [Ball(self) for x in range(NUMBALLS)]

        # Setup our physics world and the body
        self.world = OdeWorld()
        self.world.setGravity(0, 0, -9.81)
        if 0:
            self.body = OdeBody(self.world)
            M = OdeMass()
            M.setSphere(7874, 1.0)
            self.body.setMass(M)
            self.body.setPosition(self.sphere.getPos(self.render))
            self.body.setQuaternion(self.sphere.getQuat(self.render))

        ## Set the camera position
        self.disableMouse()
        self.angle = 0.0
        self.camera.setPos(1000, 1000, 1000)
        self.camera.lookAt(0, 0, 0)
        # self.enableMouse()
        # Create an accumulator to track the time since the sim
        # has been running
        self.deltaTimeAccumulator = 0.0
        # This stepSize makes the simulation run at 60 frames per second
        self.stepSize = 1.0 / 60.0

        taskMgr.doMethodLater(1.0, self.simulationTask, "Physics Simulation")

    def simulationTask(self, task):
        if 0:
            # Add the deltaTime for the task to the accumulator
            self.deltaTimeAccumulator += globalClock.getDt()
            while self.deltaTimeAccumulator > self.stepSize:
                # Remove a stepSize from the accumulator until
                # the accumulated time is less than the stepsize
                self.deltaTimeAccumulator -= self.stepSize
                # Step the simulation
                self.world.quickStep(self.stepSize)
        for ball in self.balls:
            ball.evolve()
        deltas = [ball.getdelta(self.balls) for ball in self.balls]
        for i, ball in enumerate(self.balls):
            dx, dy, dz = deltas[i]
            ball.move(dx, dy, dz)
            ball.update()
        # print "moved"
        self.camera.setPos(CX + 2500 * math.sin(self.angle), CY + 2500 * math.cos(self.angle), CZ)
        self.camera.lookAt(CX, CY, CZ)
        self.angle += 0.01
        return task.cont
示例#10
0
 def createTire(self, tireIndex):
     if tireIndex < 0 or tireIndex >= len(self.tireMasks):
         self.notify.error('invalid tireIndex %s' % tireIndex)
     self.notify.debug('create tireindex %s' % tireIndex)
     zOffset = 0
     body = OdeBody(self.world)
     mass = OdeMass()
     mass.setSphere(self.tireDensity, IceGameGlobals.TireRadius)
     body.setMass(mass)
     body.setPosition(IceGameGlobals.StartingPositions[tireIndex][0],
                      IceGameGlobals.StartingPositions[tireIndex][1],
                      IceGameGlobals.StartingPositions[tireIndex][2])
     body.setAutoDisableDefaults()
     geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius)
     self.space.setSurfaceType(geom, self.tireSurfaceType)
     self.space.setCollideId(geom, self.tireCollideIds[tireIndex])
     self.massList.append(mass)
     self.geomList.append(geom)
     geom.setCollideBits(self.allTiresMask | self.wallMask | self.floorMask
                         | self.obstacleMask)
     geom.setCategoryBits(self.tireMasks[tireIndex])
     geom.setBody(body)
     if self.notify.getDebug():
         self.notify.debug('tire geom id')
         geom.write()
         self.notify.debug(' -')
     if self.canRender:
         testTire = render.attachNewNode('tire holder %d' % tireIndex)
         smileyModel = NodePath()
         if not smileyModel.isEmpty():
             smileyModel.setScale(IceGameGlobals.TireRadius)
             smileyModel.reparentTo(testTire)
             smileyModel.setAlphaScale(0.5)
             smileyModel.setTransparency(1)
         testTire.setPos(IceGameGlobals.StartingPositions[tireIndex])
         tireModel = loader.loadModel(
             'phase_4/models/minigames/ice_game_tire')
         tireHeight = 1
         tireModel.setZ(-IceGameGlobals.TireRadius + 0.01)
         tireModel.reparentTo(testTire)
         self.odePandaRelationList.append((testTire, body))
     else:
         testTire = None
         self.bodyList.append((None, body))
     return (testTire, body, geom)
示例#11
0
 def createRays(self):
     self.notify.debug('createRays')
     body = OdeBody(self.world)
     self.ballRay = OdeRayGeom(self.space, 50.0)
     self.ballRay.setBody(body)
     self.ballRay.setOffsetRotation(Mat3(1, 0, 0, 0, -1, 0, 0, 0, -1))
     self.ballRay.setOffsetPosition(0, 0, 0.0)
     self.ballRay.setCollideBits(BitMask32(16773375))
     self.ballRay.setCategoryBits(BitMask32(4278190080L))
     self.ballRayBody = body
     self.space.setCollideId(self.ballRay, GolfGlobals.OOB_RAY_COLLIDE_ID)
     self.rayList.append(self.ballRay)
     self.rayList.append(self.ballRayBody)
     self.skyRay = OdeRayGeom(self.space, 100.0)
     self.skyRay.setCollideBits(BitMask32(240))
     self.skyRay.setCategoryBits(BitMask32(0))
     self.skyRay.setRotation(Mat3(1, 0, 0, 0, -1, 0, 0, 0, -1))
     self.space.setCollideId(self.skyRay, GolfGlobals.SKY_RAY_COLLIDE_ID)
     self.rayList.append(self.skyRay)
示例#12
0
    def add_smiley(self, x, y, z):
        sm = render.attachNewNode("smiley-instance")
        sm.setPos(x, y, z)
        self.smiley.instanceTo(sm)

        body = OdeBody(self.world)
        mass = OdeMass()
        mass.setSphereTotal(10, 1)
        body.setMass(mass)
        body.setPosition(sm.getPos())
        geom = OdeSphereGeom(self.space, 1)
        geom.setBody(body)

        sm.setPythonTag("body", body)

        return body
示例#13
0
 def createTire(self, tireIndex):
     if tireIndex < 0 or tireIndex >= len(self.tireMasks):
         self.notify.error('invalid tireIndex %s' % tireIndex)
     self.notify.debug('create tireindex %s' % tireIndex)
     zOffset = 0
     body = OdeBody(self.world)
     mass = OdeMass()
     mass.setSphere(self.tireDensity, IceGameGlobals.TireRadius)
     body.setMass(mass)
     body.setPosition(IceGameGlobals.StartingPositions[tireIndex][0], IceGameGlobals.StartingPositions[tireIndex][1], IceGameGlobals.StartingPositions[tireIndex][2])
     body.setAutoDisableDefaults()
     geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius)
     self.space.setSurfaceType(geom, self.tireSurfaceType)
     self.space.setCollideId(geom, self.tireCollideIds[tireIndex])
     self.massList.append(mass)
     self.geomList.append(geom)
     geom.setCollideBits(self.allTiresMask | self.wallMask | self.floorMask | self.obstacleMask)
     geom.setCategoryBits(self.tireMasks[tireIndex])
     geom.setBody(body)
     if self.notify.getDebug():
         self.notify.debug('tire geom id')
         geom.write()
         self.notify.debug(' -')
     if self.canRender:
         testTire = render.attachNewNode('tire holder %d' % tireIndex)
         smileyModel = NodePath()
         if not smileyModel.isEmpty():
             smileyModel.setScale(IceGameGlobals.TireRadius)
             smileyModel.reparentTo(testTire)
             smileyModel.setAlphaScale(0.5)
             smileyModel.setTransparency(1)
         testTire.setPos(IceGameGlobals.StartingPositions[tireIndex])
         tireModel = loader.loadModel('phase_4/models/minigames/ice_game_tire')
         tireHeight = 1
         tireModel.setZ(-IceGameGlobals.TireRadius + 0.01)
         tireModel.reparentTo(testTire)
         self.odePandaRelationList.append((testTire, body))
     else:
         testTire = None
         self.bodyList.append((None, body))
     return (testTire, body, geom)
示例#14
0
    def __init__(self, world, mass, geom, model, loc = Point3(), rot = True):
        super(Physical, self).__init__(world, geom, model, loc)

        self.toRevert['rot'] = self.setRot
        self.toSave['rot'] = self.getRot

        self.toRevert['vel'] = self.setVel
        self.toSave['vel'] = self.getVel
        self.toRevert['angVel'] = self.setAngVel
        self.toSave['angVel'] = self.getAngVel

        self.setRevertable(True)

        self.body = OdeBody(world.world)
        self.mass = mass
        self.body.setMass(self.mass)

        self.body.setPosition(self.model.getPos())
        self.body.setQuaternion(self.model.getQuat())

        self.geom.setBody(self.body)

        self.rot = rot
box.setTextureOff()




# Add a random amount of boxes
boxes = []

# Setup the geometry
boxNP = box.copyTo(render)
boxNP.setPos(randint(-10, 10), randint(-10, 10), 10 + random())
boxNP.setColor(random(), random(), random(), 1)
boxNP.setHpr(0, 45, 0)

# Create the body and set the mass
boxBody = OdeBody(world)
M = OdeMass()
M.setBox(20, 1, 1, 1)
boxBody.setMass(M)
boxBody.setPosition(boxNP.getPos(render))
boxBody.setQuaternion(boxNP.getQuat(render))
# Create a BoxGeom
boxGeom = OdeBoxGeom(space, 4, 4, 1)
boxGeom.setCollideBits(BitMask32(0x00000002))
boxGeom.setCategoryBits(BitMask32(0x00000001))
boxGeom.setBody(boxBody)
boxes.append((boxNP, boxBody))


boxNP2 = box.copyTo(render)
boxNP2.reparentTo(boxNP)
示例#16
0
sphere_a.set_rgba([1, .2, .3, 1])
sphere_a.attach_to(base)

sphere_b = cm.gen_sphere(radius=radius)
sphere_b.set_pos([0, 1.25, -.7])
sphere_b.set_rgba([.3, .2, 1, 1])
sphere_b.attach_to(base)

gm.gen_linesegs([[np.zeros(3), sphere_a.get_pos()]], thickness=.05, rgba=[0, 1, 0, 1]).attach_to(base)
gm.gen_linesegs([[sphere_a.get_pos(), sphere_b.get_pos()]], thickness=.05, rgba=[0, 0, 1, 1]).attach_to(base)

# Setup our physics world and the body
world = OdeWorld()
world.setGravity(0, 0, -9.81)

body_sphere_a = OdeBody(world)
M = OdeMass()
M.setSphere(7874, radius)
body_sphere_a.setMass(M)
body_sphere_a.setPosition(da.npv3_to_pdv3(sphere_a.get_pos()))

body_sphere_b = OdeBody(world)
M = OdeMass()
M.setSphere(7874, radius)
body_sphere_b.setMass(M)
body_sphere_b.setPosition(da.npv3_to_pdv3(sphere_b.get_pos()))

# Create the joints
earth_a_jnt = OdeBallJoint(world)
earth_a_jnt.attach(body_sphere_a, None)  # Attach it to the environment
earth_a_jnt.setAnchor(0, 0, 0)
示例#17
0
# Add a random amount of boxes
boxes = []
for i in range(randint(5, 10)):
    # Setup the geometry
    new_box = box.copy()
    new_box.set_pos(
        np.array([random() * 10 - 5,
                  random() * 10 - 5, 1 + random()]))
    new_box.set_rgba([random(), random(), random(), 1])
    new_box.set_rotmat(
        rm.rotmat_from_euler(random() * math.pi / 4,
                             random() * math.pi / 4,
                             random() * math.pi / 4))
    new_box.attach_to(base)
    # Create the body and set the mass
    boxBody = OdeBody(world)
    M = OdeMass()
    M.setBox(3, .3, .3, .3)
    boxBody.setMass(M)
    boxBody.setPosition(da.npv3_to_pdv3(new_box.get_pos()))
    boxBody.setQuaternion(da.npmat3_to_pdquat(new_box.get_rotmat()))
    # Create a BoxGeom
    boxGeom = OdeBoxGeom(space, .3, .3, .3)
    # boxGeom = OdeTriMeshGeom(space, OdeTriMeshData(new_box.objpdnp, True))
    boxGeom.setCollideBits(BitMask32(0x00000002))
    boxGeom.setCategoryBits(BitMask32(0x00000001))
    boxGeom.setBody(boxBody)
    boxes.append((new_box, boxBody))

# Add a plane to collide with
ground = cm.gen_box(extent=[20, 20, 1], rgba=[.3, .3, .3, 1])
示例#18
0
# Load the cube where the ball will fall from
cube = loader.loadModel("box.egg")
cube.reparentTo(render)
cube.setColor(0.2, 0, 0.7)
cube.setScale(20)
 
# Load the smiley model which will act as our iron ball
sphere = loader.loadModel("smiley.egg")
sphere.reparentTo(render)
sphere.setPos(10, 1, 21)
sphere.setColor(0.7, 0.4, 0.4)
 
# Setup our physics world and the body
world = OdeWorld()
world.setGravity(0, 0, -9.81)
body = OdeBody(world)
M = OdeMass()
M.setSphere(7874, 1.0)
body.setMass(M)
body.setPosition(sphere.getPos())
body.setQuaternion(sphere.getQuat())
 
# Set the camera position
base.disableMouse()
base.camera.setPos(80, -20, 40)
base.camera.lookAt(0, 0, 10)
 
# Create an accumulator to track the time since the sim
# has been running
deltaTimeAccumulator = 0.0
# This stepSize makes the simulation run at 90 frames per second
示例#19
0
class Physical(Touchable):
    """ 
    The Physical class is the base class for anything that responds to physics
    """

    def __init__(self, world, mass, geom, model, loc = Point3(), rot = True):
        super(Physical, self).__init__(world, geom, model, loc)

        self.toRevert['rot'] = self.setRot
        self.toSave['rot'] = self.getRot

        self.toRevert['vel'] = self.setVel
        self.toSave['vel'] = self.getVel
        self.toRevert['angVel'] = self.setAngVel
        self.toSave['angVel'] = self.getAngVel

        self.setRevertable(True)

        self.body = OdeBody(world.world)
        self.mass = mass
        self.body.setMass(self.mass)

        self.body.setPosition(self.model.getPos())
        self.body.setQuaternion(self.model.getQuat())

        self.geom.setBody(self.body)

        self.rot = rot

    def constrainQuat(self):
        """keep the object rotating in the correct plane"""

        #FIXME is there a better way than fixing at every instant?
        if not self.rot:
            self.body.setQuaternion(Quat.identQuat())
        return

        q = self.body.getQuaternion()
        q[1] = 0
        q[2] = 0
        q.normalize()
        self.body.setQuaternion(Quat(q))

    def getPos(self):
        return self.body.getPosition()

    def setPos(self, pos):
        return self.body.setPosition(pos)

    def setRot(self, rot):
        self.body.setQuaternion(Quat(rot))

    def getRot(self):
        return self.body.getQuaternion()

    def setVel(self, vel):
        self.body.setLinearVel(vel)

    def getVel(self):
        return self.body.getLinearVel()

    def setAngVel(self, angVel):
        self.body.setAngularVel(angVel)

    def getAngVel(self):
        return self.body.getAngularVel()
示例#20
0
# Make sure its center is at 0, 0, 0 like OdeBoxGeom
box.setPos(-.5, -.5, -.5)
box.flattenLight()  # Apply transform
box.setTextureOff()

# Add a random amount of boxes
boxes = []
for i in range(randint(5, 10)):
    # Setup the geometry
    boxNP = box.copyTo(render)
    # boxNP.setPos(randint(-10, 10), randint(-10, 10), 10 + random())
    boxNP.setPos(random() * 10, random() * 10, 10 + random())
    boxNP.setColor(random(), random(), random(), 1)
    boxNP.setHpr(randint(-45, 45), randint(-45, 45), randint(-45, 45))
    # Create the body and set the mass
    boxBody = OdeBody(world)
    M = OdeMass()
    M.setBox(5, 1, 1, 1)
    boxBody.setMass(M)
    boxBody.setPosition(boxNP.getPos(render))
    boxBody.setQuaternion(boxNP.getQuat(render))
    # Create a BoxGeom
    boxGeom = OdeBoxGeom(space, 1, 1, 1)
    # boxGeom = OdeTriMeshGeom(space, OdeTriMeshData(boxNP, True))
    boxGeom.setCollideBits(BitMask32(0x00000002))
    boxGeom.setCategoryBits(BitMask32(0x00000001))
    boxGeom.setBody(boxBody)
    boxes.append((boxNP, boxBody))

# Add a plane to collide with
cm = CardMaker("ground")