Hello everyone,
As a beginner in Panda3D, I am facing some issues when trying to use the built-in collision system.
Indeed, I would like to set a mechanism telling me the number of stacked tiles at each point of a map. The map is simply composed by ground tiles (1x1 square model) and at this step the collision system should answer me there is one object at any point. But in practice, Panda3D sees two collision entries both pointing to the same tile present at this point. I probably lack some basic knowledge to find out the problem.
So, first step is to create the map:
self.npMap = base.render.attachNewNode("mapNode")
for i in range(5):
for j in range(5):
npWork = loader.loadModel(self.mapElementModel)
npWork.reparentTo(self.npMap)
npWork.setScale(1, 1, 1)
npWork.setPos(i, j, 0)
npWork.setHpr(0, 0, 0)
npWork.setColor(self.Color0)
Then, to setup the collision mechanism:
def initCollisionSystem(self):
# Create a collision handler
self.collisionHandler = CollisionHandlerQueue()
# Create the collision solid (here, a segment)
self.collisionSeg = CollisionSegment()
self.nCollisionSolid = CollisionNode('segment')
self.nCollisionSolid.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.nCollisionSolid.addSolid(self.collisionSeg)
self.npCollisionSolid = self.npOrigin.attachNewNode(self.nCollisionSolid)
# Create a traverser and link it to the collision solid and the collision handler
self.traverser = CollisionTraverser('traverser')
self.traverser.addCollider(self.npCollisionSolid, self.collisionHandler)
self.shower = self.traverser.showCollisions(base.render)
To get the collisions at one point of the map, the vertical collision segment is relocated at the tile position to study. After clearing all entries of the collision handler and of the collision visualizer, the collisions are requested:
def getCollisions(self, npToObjectPosition):
# Set the segment collision solid to start above the object and to end below it
self.collisionSeg.setPointA(npToObjectPosition.getX(), npToObjectPosition.getY(), -1)
self.collisionSeg.setPointB(npToObjectPosition.getX(), npToObjectPosition.getY(), 1)
# Let the segment collide all "into" solids under render
self.collisionHandler.clearEntries()
self.shower.clear()
self.traverser.traverse(base.render)
Finally, this minimal code tests the number of collisions at each point of the map:
print len(self.npMap.getChildren())
for npChild in self.npMap.getChildren():
self.getCollisions(npChild)
print self.collisionHandler
if self.collisionHandler.getNumEntries() == 1:
npChild.setColor(self.Color1)
elif self.collisionHandler.getNumEntries() == 2:
npChild.setColor(self.Color2)
else:
npChild.setColor(self.Color3)
I tried rays, segments and lines. The result is always that two collisions are detected at each point, where there is only one tile. Visually, the entire map appears in self.Color2 color.
What is crasy for me is if I change the line:
self.collisionSeg.setPointA(npToObjectPosition.getX(), npToObjectPosition.getY(), -1)
by (for example):
self.collisionSeg.setPointA(npToObjectPosition.getX(), npToObjectPosition.getY()+0.5, -1)
setting the segment with a slope instead of being vertical, the “issue” disappears. Only a single collision is detected. It seems that if the segment collides with the center of the tile, the detection is doubled.
How to explain this behavior? Is it an expected output of the collision traverser?
Thanks for helping me to understand this !
Have all a nice day