I’ve been struggling on this problem for a couple of hours. I have a world with a ground model with collision bitmask FLOORMASK, players/agents with AGENTMASK, and “static” objects with OBJMASK.
Using CollisionHandlerGravity, all three types of things land on the floor. But, I would also like objects to land on top of other objects. Can this be done with the CollisionHandlerGravity?
My code for setting up the handlers (called once in the main program):
# Initialize the collision traverser.
base.cTrav = CollisionTraverser()
base.cTrav.setRespectPrevTransform(True)
base.cTrav.showCollisions( render )
# initialize 3 handlers: wall, gravity, and other events
# the CollisionHandlerPusher for keeping items from going through walls
base.cWall = CollisionHandlerPusher()
# tracks the velocity of moving objects; CollisionHandlerFloor doesnt
base.cFloor = CollisionHandlerGravity()
# gravity should be -9.81m/s, but that doesn't quite work
base.cFloor.setGravity(25)
base.cFloor.setMaxVelocity(100)
# Initialize the handler.
base.cEvent = CollisionHandlerEvent()
base.cEvent.addInPattern('%fn-into-%in')
base.cEvent.addOutPattern('%fn-outof-%in')
# initialize listeners
base.accept('object-into-object', self._objCollisionHandlerIn)
base.accept('object-outof-object', self._objCollisionHandlerOut)
base.accept('agent-into-object', self._agentCollisionHandlerIn)
base.accept('agent-into-agent', self._agentsCollisionIn)
I’m representing the objects as their top surfaces, since most of them are box-like. Here is the method, part of the class for the OBJMASK members, for determining their top surfaces and initializing their collision geometries.
def _setupPhysics(self, model, collisionGeom='surface'):
self.setCollideMask(OBJMASK)
# when models are scaled down dramatically
# collision handling is buggy. flattenLight() circumvents this.
model.flattenLight()
# setup floor collision ray for gravity
cRay = CollisionRay()
# set origin of ray slightly below obj
lcorner, ucorner =model.getTightBounds()
center = model.getBounds().getCenter()
cRay.setOrigin(center[0],center[1],lcorner[2])
# face it downward
cRay.setDirection(0,0,-1)
cRayNode = self.attachNewNode(CollisionNode('avatarRay'))
cRayNode.node().addSolid(cRay)
# nothing can collide INTO the ray
cRayNode.node().setIntoCollideMask(BitMask32.allOff())
# but the ray can collide INTO the FLOOR and other objects
cRayNode.node().setFromCollideMask(FLOORMASK | OBJMASK)
if collisionGeom == 'surface':
# find the surface of the model
lcorner, ucorner =model.getTightBounds()
center = model.getBounds().getCenter()
left_front = Vec3(lcorner[0], lcorner[1], ucorner[2])
left_back = Vec3(lcorner[0], ucorner[1], ucorner[2])
right_front = Vec3(ucorner[0], lcorner[1], ucorner[2])
right_back = ucorner
# and make a Collision Polygon (ordering important)
cGeom = CollisionPolygon(right_back, left_back, left_front, right_front)
elif collisionGeom == 'sphere':
# set up a collision sphere
bounds, offset = getOrientedBoundedBox(model)
radius = bounds[0]/2.0
cGeom = CollisionSphere(0.0, 0.0, 0.0, radius)
# set so that is just considered a sensor.
cGeom.setTangible(0)
cNode.addSolid(cGeom)
# it cannot collide into other objects
cNode.setFromCollideMask(BitMask32.allOff())
# but other objects and agents can collide INTO it
cNode.setIntoCollideMask(OBJMASK | AGENTMASK)
# attach to current node path
cNodePath = self.attachNewNode(cNode)
# register RayNode in GravityHandler and Traverser
base.cFloor.addCollider(cRayNode,self)
base.cTrav.addCollider(cRayNode, base.cFloor)
# add this to the base collider, accessible through DirectStart
base.cTrav.addCollider(cNodePath, base.cEvent)
If i set an object’s Z-pos/height several units above another object at the start of the simulator, it falls through other objects to the ground. In more words: the visible CollisionRay is a white line that goes through the lower objects (to the ground) and the object falls right through it – slowing down [but not stopping, as if it were actually being pushed back] as it approaches the other object and going through the ground.
I’ve tried the immediate options I could think of: tweaking velocity/gravity parameters, setting every combination of bitmasks, even turning on GravityHandler’s legacy mode! I’m really stuck - please help!
Thanks,
Dustin