Collision detection: interaction between from and into?

Hello,
I m attempting to learn collision detection and want to perform a basic operation where i click on Ralph’s right eye and a text is displayed.

I have added the following line: loseTrigger { Sphere descend } in Ralph’s egg file and prepared the necessary stuff for the from and into objects interaction. I cannot figure out what to do next.

Also, i m getting this error: Any ideas why??? self.hit.node().setIntoCollideMask(BitMask32.bit(0))
AssertionError: !is_empty() at line 273 of c:\temp\mkpr\panda3d-1.3.2\panda\src
pgraph\nodePath.I

Here’s the code:

import direct.directbase.DirectStart
from direct.task import Task
from direct.actor import Actor
from pandac.PandaModules import*
from direct.showbase.DirectObject import DirectObject 
from pandac.PandaModules import CollisionTraverser,CollisionNode
from pandac.PandaModules import CollisionHandlerQueue,CollisionRay
import math
import sys
from direct.gui.OnscreenText import OnscreenText 

class World(DirectObject):
    
    def __init__(self):
        # disable default mouse controls 
         base.disableMouse()
         
    # set camera position     
         base.camera.setPos(-20, -10, 5 )
         base.camera.lookAt( 0, 0, 0 ) 
                  
    # Load environment
         environ = loader.loadModel("models/environment")   
         environ.reparentTo(render)
         
    # Load model
         self.smile = loader.loadModel( 'models/ralph/ralph' )
         self.smile.reparentTo(render)
         self.smile.setPos( 0, 0, 0 )

         self.hit = self.smile.find("**/RightEye")
            # have added the following line on line 24708 to Ralph.egg file:
            # <Group> RightEye {
            # Line 24708: <Collide> loseTrigger { Sphere descend }
         self.hit.node().setIntoCollideMask(BitMask32.bit(0))
         self.hit.node().setFromCollideMask(BitMask32.allOff()) 
         self.hit.show()

    
         self.pickerNode = CollisionNode('mouseRay')
         self.cTrav = CollisionTraverser()
         self.cHandler = CollisionHandlerQueue()
         self.pickerNP = camera.attachNewNode(self.pickerNode)
         self.pickerNode.setFromCollideMask(BitMask32.bit(0))
         self.pickerRay = CollisionRay()               
         self.pickerNode.addSolid(self.pickerRay) 
         self.pickerNode.show()


         #Start the task that handles the 
         self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        
        
    def mouseTask(self, task):
        #Check to see if we can access the mouse. We need it to do anything else
        if base.mouseWatcherNode.hasMouse():
        #get the mouse position
            mpos = base.mouseWatcherNode.getMouse()
        #Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
        
        #HOW TO CHECK FOR COLLISION on Ralph's right eye???????????     
        
        
        # want to display this when mouse click is done on ralphs right eye    
            mouse1Event = OnscreenText(
            text="U've clicked Ralph's right eye",
            style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
            align=TextNode.ALeft, scale = .05) 

world = World()

run()
     

Hi all!
Well, i tried the other approach and am having a tough time getting this to work.
My aim: To take any character(I have taken Ralph.egg) and make its eye collision detectable by adding statement in its egg file. On clicking on a character’s eye, a simple text message shud be displayed.
If anybody knows how to do this pl. give your inputs.
I tried performing this by using “Example for Clicking on 3D Objects” code by modifying it besides my previous example. I have tried to make the eye pickable towards the end of the code but am not sure abt. my approach.
Here’s the code:

import direct.directbase.DirectStart
#for the events
from direct.showbase import DirectObject
#for collision stuff
from pandac.PandaModules import *


class Picker(DirectObject.DirectObject):
   def __init__(self):

      # disable default mouse controls 
      base.disableMouse()
                  
      #setup collision stuff                        SECTION 1                   
      self.picker= CollisionTraverser()
      self.queue=CollisionHandlerQueue()

      self.pickerNode=CollisionNode('mouseRay')
      self.pickerNP=camera.attachNewNode(self.pickerNode)

      self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
      #reference: self.hit.node().setIntoCollideMask(BitMask32.bit(20))


      self.pickerRay=CollisionRay()

      self.pickerNode.addSolid(self.pickerRay)

      #self.picker.addCollider(self.pickerNode, self.queue)
      self.picker.addCollider(self.pickerNP, self.queue)

      #this holds the object that has been picked
      self.pickedObj=None

      self.accept('mouse1', self.printMe)


   #this function is meant to flag an object as being somthing we can pick
   def makePickable(self,newObj):
      newObj.setTag('pickable','true')

   #this function finds the closest object to the camera that has been hit by our ray
   def getObjectHit(self, mpos): #mpos is the position of the mouse on the screen
      self.pickedObj=None #be sure to reset this
      self.pickerRay.setFromLens(base.camNode, mpos.getX(),mpos.getY())
      self.picker.traverse(render)
      if self.queue.getNumEntries() > 0:
         self.queue.sortEntries()
         self.pickedObj=self.queue.getEntry(0).getIntoNodePath()

         parent=self.pickedObj.getParent()
         self.pickedObj=None

         while parent != render:
            if parent.getTag('pickable')=='true':
               self.pickedObj=parent
               return parent
            else:
               parent=parent.getParent()
      return None

   def getPickedObj(self):
         return self.pickedObj

   def printMe(self):
         self.getObjectHit( base.mouseWatcherNode.getMouse())
         print self.pickedObj

mousePicker=Picker()

#load these models
#environ = loader.loadModel("models/environment")   

teapot=loader.loadModel('teapot')
box=loader.loadModel('box')
ralph = loader.loadModel('ralph')
hit = ralph.find("**/RightEye")

#put them in the world

#environ.reparentTo(render)
#camera.setPos(-20, -10, 5 )

#ralph.reparentTo(render)
#ralph.setPos(camera, 0,100,0)

ralph.reparentTo(render)
ralph.setPos(camera, 0,100,0)

teapot.reparentTo(render)
teapot.setPos(ralph, -30, 0, 0)

box.reparentTo(render)
box.setPos(ralph, 30,0,0)



mousePicker.makePickable(teapot)
mousePicker.makePickable(box)
mousePicker.makePickable(hit)

run()
self.hit.node().setIntoCollideMask(BitMask32.bit(0))
AssertionError: !is_empty() at line 273 of c:\temp\mkpr\panda3d-1.3.2\panda\src\
pgraph\nodePath.I 

Mohak, that just means self.hit is empty. In other words, it can’t find the right eye. Have you specified it in the egg-optchar call?

  1. You can’t search for Ralph’s right eye since Ralph is an animated character. Basically, anything under tag can not be search for.
  2. Take a deep look at this part :
      if self.queue.getNumEntries() > 0:
         self.queue.sortEntries()
         self.pickedObj=self.queue.getEntry(0).getIntoNodePath()

         parent=self.pickedObj.getParent()
         self.pickedObj=None

         while parent != render:
            if parent.getTag('pickable')=='true':
               self.pickedObj=parent
               return parent
            else:
               parent=parent.getParent()

In case your self.pickedObj (entry[0]) is already a pickable node, you would miss it silently. So first you have to check if it’s already a pickable one.

      if self.queue.getNumEntries() > 0:
         self.queue.sortEntries()
         self.pickedObj=self.queue.getEntry(0).getIntoNodePath()

         if self.pickedObj.getTag('pickable')=='true':
            return self.pickedObj

         parent=self.pickedObj.getParent()
         self.pickedObj=None

         while parent != render:
            if parent.getTag('pickable')=='true':
               self.pickedObj=parent
               return parent
            else:
               parent=parent.getParent()