Collisions camera

I’m a beginner on panda, and I’ve started a simulation that would allow me to move the camera only with the keyboard keys. I’d like to implement a function that would return a text if the camera collides with an actor. I’d like to detect collisions between camera and actors if possible.
thanks for reading, Arthur

Have you looked at the manual pages regarding collision detection? If not, see here:
https://docs.panda3d.org/1.10/python/programming/collision-detection/index

(There’s also my Panda3D Beginner’s Tutorial, part of which covers simple collision detection.)

In this case, the short version would be something like this:

  • Assign a collider or set of colliders to both the camera and the actor
  • Have a CollisionHandlerEvent (or CollisionHandlerPusher, if you also want to prevent their moving through each other) respond to collisions
  • Call for and respond to a collision-event

Now there is a question: how precise do you want your collisions to be?

A fairly general collision may be fairly straightforward: assign a roughly-appropriate collision-shape to your actor.

A somewhat-precise collision might not be too hard: for each relevant joint in the actor, assign an appropriate collision shape.

More precise still than that, however, gets harder; there are likely ways, but I won’t delve into that here, I think–in part because I’m not familiar with attempting collision of that degree of precision.

thank you very much, your tutorial is awesome !
I needn’t very precise collisions, I’m an engineering student and I’m just trying to develop a little project for the school.

1 Like

It’s my pleasure, and thank you very much, respectively! :smiley: I hope that it proves helpful. :slight_smile:

In that case, the sort of collision demonstrated in the manual or my tutorial may well be enough.

Yes, I’ve started using them and it fits perfectly with what I want to do. so I followed your great tutorial, can I come back to you if I have more questions ?

1 Like

You can! :slight_smile:

I would recommend posting your questions on the forum, if applicable: you may get a broader range of respondents, with a broader range of knowledge, after all.

okay, thanks for the advice, I have another question, I’ve coded the collision between my camera and my actor, but I don’t understand how to detect it to show an end game screen.

# actors setting
        self.fish = loader.loadModel("poisson")
        self.fish.setScale(0.2, 0.2, 0.2)
        self.fish.setPos(0, -150, 20)
        self.fish.reparentTo(self.render)

        # collisions
        self.cTrav = CollisionTraverser()
        self.pusher = CollisionHandlerPusher()
        colliderNode = CollisionNode("fish")
        colliderNode2 = CollisionNode("camera")
        # Add a collision box for the fish
        colliderNode.addSolid(CollisionBox(0, 50, 20, 30))
        collider = self.fish.attachNewNode(colliderNode)
        # add a second collision box for the camera
        colliderNode2.addSolid(CollisionSphere(0, 0, 0, 1))
        collider2 = self.camera.attachNewNode(colliderNode2)

        base.pusher.addCollider(collider, base.camera)
        base.cTrav.addCollider(collider, self.pusher)

        self.pusher.add_in_pattern("%fn-into-%in")
        self.accept("camera-into-fish", self.death)

I’ve done that but it isn’t working, could you correct me ?

(I presume that you have a method named “death”.) It looks like you have the names in your call to “accept” the wrong way around:

In “add_in_pattern”, you’ve specified the event-pattern <from-node>-into-<into node>, I believe. However, when “accepting” the resultant event, you seem to have given the associated names the other way around: since “collider” seems to be the “from-node”–the node that “does the colliding”, so to speak–and since “collider” is associated with the name “fish”, I would expect “fish” to be your “from-node”, and “camera” to be your “into-node”.

in my code, I assigned keyboard entry to move the camera, and I want to create a pathfinding for fishes to simulate an aquarium, the camera is like the eyes of a fish and if he hit an other fish he die, so I create a method “death” which do “sys.exit”, and so I want to detect when the camera is hitting the fish, so I have to use “from-node” into “into-node” with the fish as into node and the camera as from node ? but I think I misunderstood the way to program that and so it’s not working

This should help you.

https://docs.panda3d.org/1.10/python/programming/collision-detection/event-example#event-example

oh yes it’s interesting for me, but I want to detect collision between an actor and base.camera, so I’m a little bit lost (I’m so sorry for my noobism)

Delete this entry and it will be what you wanted.

s.setPos(0, 25, 0)
from direct.showbase.ShowBase import ShowBase
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import Sequence, Func, Wait
from panda3d.core import CollisionTraverser, CollisionHandlerEvent
from panda3d.core import CollisionNode, CollisionSphere
import sys

class World(DirectObject):

    def __init__(self):
        # Initialize the traverser.
        base.cTrav = CollisionTraverser()

        # Initialize the handler.
        self.collHandEvent = CollisionHandlerEvent()
        self.collHandEvent.addInPattern('into-%in')
        self.collHandEvent.addOutPattern('outof-%in')

        # Make a variable to store the unique collision string count.
        self.collCount = 0

        # Load a model. Reparent it to the camera so we can move it.
        s = base.loader.loadModel('smiley')
        s.reparentTo(base.camera)

        # Setup a collision solid for this model.
        sColl = self.initCollisionSphere(s, True)

        # Add this object to the traverser.
        base.cTrav.addCollider(sColl[0], self.collHandEvent)

        # Load another model.
        t = base.loader.loadModel('smiley')
        t.reparentTo(base.render)
        t.setPos(5, 25, 0)

        # Setup a collision solid for this model.
        tColl = self.initCollisionSphere(t, True)

        # Add this object to the traverser.
        base.cTrav.addCollider(tColl[0], self.collHandEvent)

        # Accept the events sent by the collisions.
        self.accept('into-' + tColl[1], self.collide)

    def collide(self, collEntry):
        sys.exit()

    def initCollisionSphere(self, obj, show=False):
        # Get the size of the object for the collision sphere.
        bounds = obj.getChild(0).getBounds()
        center = bounds.getCenter()
        radius = bounds.getRadius() * 1.1

        # Create a collision sphere and name it something understandable.
        collSphereStr = 'CollisionHull{0}_{1}'.format(self.collCount, obj.name)
        self.collCount += 1
        cNode = CollisionNode(collSphereStr)
        cNode.addSolid(CollisionSphere(center, radius))

        cNodepath = obj.attachNewNode(cNode)
        if show:
            cNodepath.show()

        # Return a tuple with the collision node and its corrsponding string so
        # that the bitmask can be set.
        return (cNodepath, collSphereStr)


base = ShowBase()
# Run the world. Move around with the mouse to create collisions.
w = World()
base.run()

Try ramming a smiley face with your camera.

You don’t have to–you could just swap the names in the call to “accept” in which you reference “self.death”.

That said, it might not be a bad idea to have the camera be the “from-node”, instead of the fish: I imagine that you may have multiple fish, but only one camera, and it can be more efficient to keep the number of “from-nodes” to a minimum, I believe.

oh it’s working thank you very much :grinning:

1 Like