Thanks for that link Yellow. Yep, every little bit helps . I think that I may have found another example of the picker.py code in the Panda manual itself, called ‘Example for Clicking On 3D Objects’.
I think it’s a new addition to the manual, cause I never noticed it before .
# 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 of 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 these 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()
Anyway, I’m going to try loading an environment model, instead of the panda, teapot…etc. With luck, when I click on the environment, the console should tell me the nodePath of the model I clicked on (ie: environment).
If that works, then I’m going to try making the console tell me the world ‘coordinates’ of the position clicked on by the mouse. For example, if I click a point on the environment, then I want the console to print out (0, 0, 0) or something, which will give me the X, Y, Z world coordinates of the point I clicked on.
If I click on the sky or somewhere else that is not part of the environment model, then nothing at all should happen, because only the environment model is designated as ‘pickable’.
I don’t know if this makes sense, or even if it’s possible, but I’ll play around with it and see what happens.
So now I need to figure out some way to tell the code to return the ‘world position’ of the mouse click, instead of the nodePath of the model and then print that info to the console.
At the moment though, I’m not really sure how to do this, so if anybody is willing to help me out by telling me which lines of code I need to change, I’d be really grateful.
Thanks