def pick(self, x, y, viewer): if viewer.getSceneData(): if self.usePolytopeIntersector(): picker = osgUtil.PolytopeIntersector(osgUtil.Intersector.WINDOW, x - 2.0, y - 2.0, x + 2.0, y + 2.0) else: picker = osgUtil.LineSegmentIntersector(osgUtil.Intersector.WINDOW, x, y) intersectionVisitor = osgUtil.IntersectionVisitor(picker) viewer.getCamera().accept(intersectionVisitor) if picker.containsIntersections(): intersections = picker.getIntersections() # The PolytopeIntersector mis-calculates the eye distance for geometry nested under a transform, which is true for all UnitShapes. (See the thread at http://www.mail-archive.com/[email protected]/msg29195.html for some discussion.) # Calculate the correct distance and re-sort. # This will probably still work correctly after that bug is fixed but will be inefficient. visibleHits = [] eye, center, up = (osg.Vec3(), osg.Vec3(), osg.Vec3()) viewer.getCamera().getViewMatrixAsLookAt(eye, center, up) eye = (eye.x(), eye.y(), eye.z()) for i in range(0, len(intersections)): intersection = intersections[i] for j in range(0, len(intersection.nodePath)): node = intersection.nodePath[j] geode = osg.NodeToGeode(node) if geode != None: visibleID = int(geode.getName()) visible = self._display.visibleWithId(visibleID) if geode.getOrCreateStateSet().getAttribute(osg.StateAttribute.DEPTH): # If a geode has this attribute set then (currently) it is being rendered in front of all other nodes. Simulate this here by placing the geode right at the eye. # If depths other than the default or osg.Depth.ALWAYS are used in the future then this check will need to be modified. eyeDistance = 0.0 else: intersectionPoint = intersection.localIntersectionPoint if isinstance(visible.shape(), UnitShape): position = visible.worldPosition() size = visible.worldSize() intersectionPoint = (position[0] + size[0] * intersectionPoint.x(), position[1] + size[1] * intersectionPoint.y(), position[2] + size[2] * intersectionPoint.z()) eyeDistance = (intersectionPoint[0] - eye[0]) ** 2 + (intersectionPoint[1] - eye[1]) ** 2 + (intersectionPoint[2] - eye[2]) ** 2 visibleHits += [(eyeDistance, visible)] visibleHits.sort() # Loop through all of the hits to find the "deepest" one in the sense of the visible hierarchy. For example, a neuron in a region will be picked instead of the region even though the region hit is closer. if self._display.useGhosts(): # Make a first pass only picking non-ghosted items. # TODO: this could be done with node masks... deepestVisible = None for distance_, visible in visibleHits: if (visible in self._display.highlightedVisibles or visible in self._display.animatedVisibles) and (deepestVisible is None or deepestVisible in visible.ancestors()): deepestVisible = visible if deepestVisible is not None: self._display.selectVisibles([deepestVisible], self._display.selectionShouldExtend, self._display.findShortestPath, fromclick=True) return True deepestVisible = None for distance_, visible in visibleHits: if deepestVisible is None or deepestVisible in visible.ancestors(): deepestVisible = visible self._display.selectVisibles([deepestVisible], self._display.selectionShouldExtend, self._display.findShortestPath, fromclick=True) else: self._display.selectVisibles([]) return True
def startDragPanOrPick(self, eventAdaptor, viewer): eventWasHandled = False if viewer.getSceneData(): # TODO: This is a major hack. The intersection code below always picks the composite dragger, even if it isn't being rendered. So we remove the inactive dragger while picking. # TODO: Figure out how to make the intersection code honor the LOD and get rid of the DraggerCullCallback class. if self._display.draggerLOD is not None: if self._display.activeDragger == self._display.simpleDragger: self._display.draggerLOD.removeChild( self._display.compositeDragger) if self._display.activeDragger == self._display.compositeDragger: self._display.draggerLOD.removeChild( self._display.simpleDragger) x, y = eventAdaptor.getX(), eventAdaptor.getY() if self.usePolytopeIntersector(): picker = osgUtil.PolytopeIntersector( osgUtil.Intersector.WINDOW, x - 2.0, y - 2.0, x + 2.0, y + 2.0) else: picker = osgUtil.LineSegmentIntersector( osgUtil.Intersector.WINDOW, x, y) intersectionVisitor = osgUtil.IntersectionVisitor(picker) intersectionVisitor.setTraversalMode( osg.NodeVisitor.TRAVERSE_ACTIVE_CHILDREN) viewer.getCamera().accept(intersectionVisitor) if picker.containsIntersections(): # Add all intersections from the first dragger hit onward to the pointer info. This allows dragging of nested regions. self.pointerInfo.setCamera(viewer.getCamera()) self.pointerInfo.setMousePosition(eventAdaptor.getX(), eventAdaptor.getY()) intersections = picker.getIntersections() for i in range(0, len(intersections)): intersection = intersections[i] for j in range(0, len(intersection.nodePath)): node = intersection.nodePath[j] if self.dragger is None: self.dragger = osgManipulator.NodeToDragger(node) if self.dragger is not None: localPoint = intersection.localIntersectionPoint # have to do stupid conversion from Vec3d to Vec3 if self.usePolytopeIntersector(): self.pointerInfo.addIntersection( intersection.nodePath, osg.Vec3(localPoint.x(), localPoint.y(), localPoint.z())) else: self.pointerInfo.addIntersection( intersection.nodePath, osg.Vec3d(localPoint.x(), localPoint.y(), localPoint.z())) if self.dragger is not None: self.dragger.handle(self.pointerInfo, eventAdaptor, viewer) eventWasHandled = True if self._display.draggerLOD is not None: if self._display.activeDragger == self._display.simpleDragger: self._display.draggerLOD.addChild( self._display.compositeDragger) if self._display.activeDragger == self._display.compositeDragger: self._display.draggerLOD.addChild( self._display.simpleDragger) return eventWasHandled
def pick(self, x, y, viewer): print "Picking" if not viewer.getSceneData(): return False #create an intersector picker = osgUtil.LineSegmentIntersector(osgUtil.Intersector.PROJECTION, x, y) #create an intersectionVisitor iv = osgUtil.IntersectionVisitor(picker) #visit the sceneGraph viewer.getCamera().accept(iv) #check for intersections if picker.containsIntersections(): print "Intersection Found" intersection = picker.getFirstIntersection() #find the first Transform node and make it the selected node for node in intersection.nodePath: mt = osg.NodeToMatrixTransform(node) if mt: #if there is a previous selected node, 'deselect' it if self._selectedNode: self._selectedNode.setUpdateCallback( osg.NodeCallback()) #remove the wirebox of the previous selection if self.wb: self._selectedNode.removeChild(self.wb) self._selectedNode = mt #show that the node is selected mt.setUpdateCallback(RotateCB().__disown__()) else: pot = osg.NodeToPositionAttitudeTransform(node) if pot: #if there is a previous selected node, 'deselect' it if self._selectedNode: self._selectedNode.setUpdateCallback(None) #remove the wirebox of the previous selection if self.wb: self._selectedNode.removeChild(self.wb) self._selectedNode = pot #show that the node is selected pot.setUpdateCallback(RotateCB().__disown__()) else: geode = osg.NodeToGeode(node) if geode: #create a wirebox and safe it, the wire box #will be attached to the parental transform node self.wb = createWireBox(geode) self._selectedNode.addChild(self.wb) self.wb.thisown = False return True return False else: print "No Intersection Found" return False