Object colliding twice

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

Welcome to the forums!

It might help if you shared your .egg file.

Thank you !

You are right, it could be linked with the model. The file is in the .zip attached.
map_element1x1.zip (341 Bytes)

I still have no idea on what could be the root cause of this behavior.
Can anybody help me?

A shot in the dark, but maybe your collision mesh is not one quad but two triangles?

Hmm, I can’t spot anything wrong. On the off-chance that this is a bug with collision-with-geometry, perhaps you could instead of using GeomNode.getDefaultCollideMask() to collide with the visible geometry, add a {Polyset keep descend} to your .egg file so that Panda generates a special CollisionPolygon for it? This is generally more advisable anyway, and perhaps a CollisionPolygon is more reliable than colliding with the visible geometry directly as you’re doing.

Hello guys,

I come back to you as, after some progress on other projects, I just restarted with this one. Ten months ago I complained about the issue explained in this topic and used a temporary workaround.

Thank you, wezu and rdb, to have answered to me at that time and excuse me for the long silence.

To recap and rephrase a bit, a vertical collision solid (ray/segment/line tested) hits apparently twice a simple horizontal flat quad.

wezu pointed that in reality the “from” solid collides with the two triangles composing the quad. Indeed, I get the expected result if the collision test is performed at a position shifted from the diagonals of the quad. Panda3d splits the model into triangles for rendering purposes.

Next I considered the rdb’s advice and created a CollisionNode for the quad. This way it works fine, whatever the position of the “from” solid onto the quad.

This is to officially close this topic, even if I am not sure the collision with geometry should have the behaviour described here.