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 createWireBox(node): """create a bounding box for the node """ #create an empty bounding box bb = osg.BoundingBox() #if we have a geode, expand by the drawables bounding box, else use the bounding sphere geode = osg.NodeToGeode(node) if geode: print "geode found" for i in range(geode.getNumDrawables()): dwb = geode.getDrawable(0) bb.expandBy(dwb.getBound()) else: bb.expandBy(node.getBound()) center = node.getBound().center() #create a geode for the wirebox wbgeode = osg.Geode() wbgeode.setName("ExtentsGeode") #create a stateset for the wirebox stateset = osg.StateSet() wbgeode.setStateSet(stateset) # stateset.thisown = 0 #create a polygonmode state attribute polyModeObj = osg.PolygonMode() polyModeObj.setMode(osg.PolygonMode.FRONT_AND_BACK, osg.PolygonMode.LINE) stateset.setAttribute(polyModeObj) #create a linewidth state attribute lw = osg.LineWidth() lw.setWidth(2.0) stateset.setAttribute(lw) stateset.setAttribute(selmat) #create a drawablw box with the right position and size lx = bb._max.x() - bb._min.x() ly = bb._max.y() - bb._min.y() lz = bb._max.z() - bb._min.z() box = osg.Box(center, lx, ly, lz) shape = osg.ShapeDrawable(box) #shape.setColor(osg.Vec4(1.0, 0.0, 0.0, 1.0)) #add the drawable to the wirebox geode wbgeode.addDrawable(shape) for pointer in [stateset, box, polyModeObj, lw, shape]: pointer.thisown = False #return the wirebox geode print "returning geode" return wbgeode
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