This is a small example program for clicking on 3D objects. A panda, a teapot, and a cube will be on screen. When you click on the screen the console will tell you the nodePath of what you have clicked on. Its basically a watered down version the tutorial included with Panda 3D 1.0.4. However, all the functionality for picking 3D objects is encapsulated into the Picker class which you may feel free to use in your own 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):
#setup collision stuff
self.picker= CollisionTraverser()
self.queue=CollisionHandlerQueue()
self.pickerNode=CollisionNode('mouseRay')
self.pickerNP=camera.attachNewNode(self.pickerNode)
self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.pickerRay=CollisionRay()
self.pickerNode.addSolid(self.pickerRay)
self.picker.addCollider(self.pickerNode, 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 thest models
panda=loader.loadModel('panda')
teapot=loader.loadModel('teapot')
box=loader.loadModel('box')
#put them in the world
panda.reparentTo(render)
panda.setPos(camera, 0, 100,0)
teapot.reparentTo(render)
teapot.setPos(panda, -30, 0, 0)
box.reparentTo(render)
box.setPos(panda, 30,0,0)
mousePicker.makePickable(panda)
mousePicker.makePickable(teapot)
mousePicker.makePickable(box)
run()
|
If you are running this example on Panda 1.1, replace line 24 with
self.picker.addCollider(self.pickerNP, self.queue)
|
Note: If you switch to another window, the mouse picker may not work when you are back to the panda window. If that happens, just select the perform some window action.If it still doesn't work still, replace printMe method with this:
def printMe(self):
if base.mouseWatcherNode.hasMouse():
self.getObjectHit( base.mouseWatcherNode.getMouse())
print self.pickedObj
|
|