You are able to get the picked coordiates when you click on an object. All what is needed is to look up what vertex is close to it. pickedPoint in getCollision() should interest you.
class Picker(DirectObject.DirectObject):
def __init__(self, show=False):
self.accept('makePickable', self.makePickable)
#create traverser
#base.cTrav = CollisionTraverser()
self.cTrav = CollisionTraverser()
#create collision ray
self.createRay(self,base.camera,name="mouseRay",show=show)
def getMouseCell(self):
"""Returns terrain cell coordinates (x,y) at mouse pointer"""
#get mouse coords
if base.mouseWatcherNode.hasMouse()==False: return
mpos=base.mouseWatcherNode.getMouse()
#locate ray from camera lens to mouse coords
self.ray.setFromLens(base.camNode, mpos.getX(),mpos.getY())
#get collision: picked obj and point
pickedObj,pickedPoint=self.getCollision(self.queue)
#call appropiate mouse function (left or right)
if pickedObj==None: return
cell=(int(math.floor(pickedPoint[0])),int(math.floor(pickedPoint[1])))
return cell
def getCenterCoords(self, nodePath = render):
'''Returns terrain cell coordinates (x,y) that is at center of camera'''
self.ray.setFromLens(base.camNode, 0, 0)
#get collision: picked obj and point
pickedObj,pickedPoint=self.getCollision(self.queue, nodePath)
return pickedPoint
def getCoords(self):
#get mouse coords
if base.mouseWatcherNode.hasMouse()==False: return
mpos=base.mouseWatcherNode.getMouse()
#locate ray from camera lens to mouse coords
self.ray.setFromLens(base.camNode, mpos.getX(),mpos.getY())
#get collision: picked obj and point
pickedObj,pickedPoint=self.getCollision(self.queue)
return pickedPoint
def getCollision(self, queue, nodePath = render):
"""Returns the picked nodepath and the picked 3d point.
This function not inteded to be called directly, use a get*() function instead.
"""
#do the traverse
#base.cTrav.traverse(render)
self.cTrav.traverse(nodePath)
#process collision entries in queue
if queue.getNumEntries() > 0:
queue.sortEntries()
for i in range(queue.getNumEntries()):
collisionEntry=queue.getEntry(i)
pickedObj=collisionEntry.getIntoNodePath()
#iterate up in model hierarchy to found a pickable tag
parent=pickedObj.getParent()
for n in range(1):
if parent.getTag('pickable')!="" or parent==render: break
parent=parent.getParent()
#return appropiate picked object
if parent.getTag('pickable')!="":
pickedObj=parent
pickedPoint = collisionEntry.getSurfacePoint(pickedObj)
return pickedObj,pickedPoint
return None,None
def makePickable(self,newObj,tag='true'):
"""sets nodepath pickable state"""
newObj.setTag('pickable',tag)
#print "Pickable: ",newObj,"as",tag
"""creates a ray for detecting collisions"""
def createRay(self,obj,ent,name,show=False,x=0,y=0,z=0,dx=0,dy=0,dz=-1):
#create queue
obj.queue=CollisionHandlerQueue()
#create ray
obj.rayNP=ent.attachNewNode(CollisionNode(name))
obj.ray=CollisionRay(x,y,z,dx,dy,dz)
obj.rayNP.node().addSolid(obj.ray)
obj.rayNP.node().setFromCollideMask(GeomNode.getDefaultCollideMask())
#base.cTrav.addCollider(obj.rayNP, obj.queue)
self.cTrav.addCollider(obj.rayNP, obj.queue)
if show: obj.rayNP.show()