Here’s a code snippet, I create a CollisionHandlerFloor to let the car move on uneven terrain without any force. But the result is odd. Although the intersection point is detected, the car is not been set to that point. I print out the ‘Z’ of the car when I move it by arrow keys. The car’s ‘z’ is always 0, but I can see its change in Z axis during running the code.
# Space to hold the car.
self.box = loader.loadModel("Models/Box")
self.box.reparentTo(render)
# The wall
self.walls = self.box.find("**/wall_Coll")
self.walls.node().setIntoCollideMask(BitMask32(0x3))
# The ground
self.boxGround = self.box.find("**/ground_Coll")
self.boxGround.node().setIntoCollideMask(BitMask32(0x1))
# Load the car and create a collision sphere and a collision ray for it.
self.car = loader.loadModel("Models/Car")
self.car.reparentTo(render)
bounds = self.car.getChild(0).getBounds()
center = bounds.getCenter()
radius = bounds.getRadius()
cSphere = CollisionSphere(center,radius)
cNode = CollisionNode("Car")
cNode.addSolid(cSphere)
cNode.setFromCollideMask(BitMask32(0x3))
cNode.setIntoCollideMask(BitMask32(0x1))
self.carCollNodePath = self.car.attachNewNode(cNode)
# Collision ray for the car.
cRay = CollisionRay(0, 0, 0, 0, 0, -1)
cNode = CollisionNode("Car_Ray_Down")
cNode.addSolid(cRay)
cNode.setFromCollideMask(BitMask32(0x1))
self.carCollRayNodePath = self.car.attachNewNode(cNode)
self.cTrav = CollisionTraverser()
self.pusher_car = PhysicsCollisionHandler()
self.lifter= CollisionHandlerFloor()
self.lifter.addCollider(self.carCollRayNodePath, self.car)
self.cTrav.addCollider(self.carCollRayNodePath, self.lifter)
I’ve been careful about the Collision Handler and bitmask. Anybody can point out what’s wrong here? Thanks
You set sphere’s into-mask to 0x1, while the ray also has the same from-mask.
That’s the source of your problem. CollisionHandlerFloor adjust your car’s Z based on collision of the ray into it’s own sphere. That’s why it’s Z never changed.
You’d better shut it down, unless you need it for something else (you should use other bit for that).
cNode.setIntoCollideMask(BitMask32.allOff())
You print your car’s Z, but the node actually moves around is not self.car. It stays on Z=0 all the time. The node which moves around is the physical node, self.carANP.
angle = self.car.getH()*math.pi/180.0
You convert degrees to radians by yourself. Python’s math module has radians method as well as degrees.
Hi ynjh_jo, I know how the crazy jitter come.
The Collision Sphere around the car collides with the ground, also does the Collision ray of the car. Every time CollisionHandlerFloor try to move the car’s center to the intersection point, however, the Collision Sphere prevents the car move under the ground. So it jitters that way!
I add this
Now, there’s a new problem.
It seems that two different CollisionHandlers cannot be associated with the same object. I use PhsicsCollisionHandler to prevent the stones falling through the ground. The result is good. However, when I add a CollisionHandlerEvent to the stone, the PhsicsCollisionHandler does not work. Surprise, the CollisionHandlerEvent works.
( I need to detect when the falling stones collide into the car. So I use CollisionHandlerEvent to send a message when the collision is detected. )
Sinppet:
# The wall
self.walls = self.box.find("**/wall_Coll")
self.walls.node().setIntoCollideMask(BitMask32(0x1))
self.walls.show()
# The ground
self.boxGround = self.box.find("**/ground_Coll")
self.boxGround.node().setIntoCollideMask(BitMask32(0x9))
self.boxGround.show()
# Load the car and its collision sphere
self.car = loader.loadModel("Models/Car")
self.car.reparentTo(render)
self.car.setScale(0.8)
self.car.setPos(0, 0, 0)
self.car.setHpr(90, 0, 0)
# add a sphere around the car to be collide with the walls
# get the bounding sphere of the car
bounds = self.car.getChild(0).getBounds()
center = bounds.getCenter()
radius = bounds.getRadius()
cSphere = CollisionSphere(center,radius)
cNode = CollisionNode("Car")
cNode.addSolid(cSphere)
cNode.setFromCollideMask(BitMask32(0x11))
cNode.setIntoCollideMask(BitMask32(0x8))
self.carCollNodePath = self.car.attachNewNode(cNode)
# Collision ray for the car.
cRay = CollisionRay(0, 0, 0, 0, 0, -1)
cNode = CollisionNode("Car_Ray_Down")
cNode.addSolid(cRay)
cNode.setFromCollideMask(BitMask32(0x1))
cNode.setIntoCollideMask(BitMask32.allOff())
self.carCollRayNodePath = self.car.attachNewNode(cNode)
# Load stones and their collision solids and rays.
self.stones = []
for i in range(5):
stone = loader.loadModelCopy("Models/stone")
stone.reparentTo(render)
stone.setScale(0.7)
stone.setPos( Vec3( random.uniform(-5, 5), random.uniform(-5, 5), random.uniform(5, 15) ) )
self.stones.append(stone)
self.cTrav = CollisionTraverser()
self.pusher_stone = PhysicsCollisionHandler()
self.stoneAN = []
# Use a Collision Handler Event to deal with the explosion when
# stone collides into the car.
self.cHandler = CollisionHandlerEvent()
self.cHandler.addInPattern("%fn-crash-%in")
# self.cTrav.addCollider(self.carCollNodePath, self.cHandler)
self.accept("Stone-crash-Car", self.accident)
for stone in self.stones:
# Create a sphere solid around each stone
cSphere = CollisionSphere(stone.getChild(0).getBounds().getCenter(), stone.getChild(0).getBounds().getRadius())
cNode = CollisionNode("Stone")
cNode.addSolid(cSphere)
cNode.setFromCollideMask(BitMask32(0x9))
cNode.setIntoCollideMask(BitMask32(0x8))
stoneCollNP = stone.attachNewNode(cNode)
stoneCollNP.show()
i = self.stones.index(stone)
stoneAN = ActorNode("stone-physics"+str(i))
self.stoneAN.append(stoneAN)
stoneANP = render.attachNewNode(stoneAN)
base.physicsMgr.attachPhysicalNode(stoneAN)
stone.reparentTo(stoneANP)
self.pusher_stone.addCollider(stoneCollNP, stoneANP)
self.cTrav.addCollider(stoneCollNP, self.pusher_stone)
# Comment the next, the world looks fine except cannot detect "Stone-crash-Car"
self.cTrav.addCollider(stoneCollNP, self.cHandler)