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,center,lcorner) # 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, lcorner, ucorner) left_back = Vec3(lcorner, ucorner, ucorner) right_front = Vec3(ucorner, lcorner, ucorner) 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/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!