Weird collision behaviour

This is odd. I’ve written some code to test a CollisionSphere colliding with a CollisionPlane (below). The code as shown works fine. But if you increase the “scale” variable, the ball sinks further into the plane before the collision is noticed. It seems to max at out the radius of the ball.


import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.gui.DirectGui import *

class World(DirectObject):  

  def __init__(self):

    scale = 1.0;

    # make a plane and a ball

    collisionMask = BitMask32.bit(0);

    self.bottom = render.attachNewNode("bottom");
    self.bottom.setPos(0, 0.0, -10);    
    self.bottom.setScale(scale, 1.0, 1.0)

    plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
    self.cBottom = self.bottom.attachNewNode(CollisionNode('cBottom'))
    self.cBottom.node().addSolid(plane)
    self.cBottom.node().setIntoCollideMask(collisionMask)
    self.cBottom.show()

    self.ball = render.attachNewNode("bottom");
    self.ball.reparentTo(render);

    sphere = CollisionSphere(0, 0, 0, 1.0);
    self.cBall = self.ball.attachNewNode(CollisionNode('cBall'))
    self.cBall.node().addSolid(sphere);
    self.cBall.node().setFromCollideMask(collisionMask)
    self.cBall.node().setIntoCollideMask(BitMask32.allOff())
    self.cBall.show();
    
    self.cTrav = CollisionTraverser()
    self.cHandler = CollisionHandlerQueue()
    self.cTrav.addCollider(self.cBall, self.cHandler)
    base.cTrav = self.cTrav;

    taskMgr.remove("moveBall")
    self.mainLoop = taskMgr.add(self.moveBall, "moveBall")
    self.mainLoop.last = 0

  def moveBall(self, task):
    print "ball: ", self.ball.getPos()
    
    for i in range(self.cHandler.getNumEntries()):
      entry = self.cHandler.getEntry(i)
      name = entry.getIntoNode().getName()
      print "Collision: ", name
      return Task.done;
   
    pos = self.ball.getPos();
    pos += Vec3(0,0,-0.1)
    self.ball.setPos(pos)
      
    return Task.cont;

w = World()
run()    

This is a known limitation with the collision system: non-uniform scales don’t work well with it. If you were to scale your plane by the same amount in all three dimensions, it would work fine.

The reason for this is because the collision is tested in the coordinate space of the plane. But under a non-uniform-scale coordinate space, a sphere is no longer a sphere. So ia center and a radius is no longer a sufficient representation of a sphere under the non-uniform scale. In order to solve this, we would have to implement fully general ellipsoid-plane intersection tests, which would be much more expensive. We figure it’s better just to avoid non-uniform scales on your collision geometry.

If you find you do occasionally need to use a non-uniform scale, you can always use nodePath.flattenLight() to bake the scale in to the vertices, which will also solve the problem.

David