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?
You can’t search for Ralph’s right eye since Ralph is an animated character. Basically, anything under tag can not be search for.
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()