#!/usr/bin/env python #/* # * This application is open source and may be redistributed and/or modified # * freely and without restriction, both in commericial and non commericial # * applications,as long as this copyright notice is maintained. # * # * This application is distributed in the hope that it will be useful, # * but WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. #*/ import sys from PyOSG import * from OpenGL.GL import * # create text drawable at 'pos' def createText(string, pos): # text drawable text = osgText.Text() text.setFont("fonts/arial.ttf") text.setPosition(pos) text.setText(string) # geode geode = osg.Geode() geode.addDrawable(text) return geode def createTextGroup(text): group = osg.Group() pos = osg.Vec3(120.0, 800.0, 0.0) delta = osg.Vec3(0.0, -60.0, 0.0) # header group.addChild(createText(text[0], pos)) pos += delta # remainder of text under sequence seq = osg.Sequence() group.addChild(seq) for t in text[1:]: seq.addChild(createText(t, pos)) seq.setTime(seq.getNumChildren()-1, 2.0) pos += delta # loop through all children seq.setInterval(osg.Sequence.LOOP, 0,-1) # real-time playback, repeat indefinitively seq.setDuration(1.0, -1) # must be started explicitly seq.setMode(osg.Sequence.START) return group def createHUD(node): # absolute transform modelview_abs = osg.MatrixTransform() modelview_abs.setReferenceFrame(osg.Transform.ABSOLUTE_RF) modelview_abs.setMatrix(osg.Matrix.identity()) modelview_abs.addChild(node) # 2D projection node projection = osg.Projection() projection.setMatrix(osg.Matrix.ortho2D(0,1280,0,1024)) projection.addChild(modelview_abs) # turn off lighting and depth test state = modelview_abs.getOrCreateStateSet() state.setMode(GL_LIGHTING, osg.StateAttribute.OFF) state.setMode(GL_DEPTH_TEST, osg.StateAttribute.OFF) return projection def createScaledNode(node, targetScale): # create scale matrix transform = osg.MatrixTransform() bsphere = node.getBound() scale = targetScale / bsphere._radius transform.setMatrix(osg.Matrix.scale(scale,scale,scale)) transform.setDataVariance(osg.Object.STATIC) transform.addChild(node) # rescale normals state = transform.getOrCreateStateSet() state.setMode(GL_NORMALIZE, osg.StateAttribute.ON) return transform def createSequence(arguments): # assumes any remaining parameters are models seq = osg.Sequence() for i in range(1, arguments.argc()): # load model node = osgDB.readNodeFile(arguments[i]) if not node: continue seq.addChild(createScaledNode(node, 100.0)) seq.setTime(seq.getNumChildren()-1, 1.0) # loop through all children seq.setInterval(osg.Sequence.LOOP, 0,-1) # real-time playback, repeat indefinitively seq.setDuration(1.0, -1) return seq # event handler to control sequence class SequenceEventHandler( osgGA.GUIEventHandler): def __init__(self, seq): osgGA.GUIEventHandler.__init__(self) self._seq = seq self._self = self # handle keydown events def handle(self, ea, aa): if (ea.getEventType() == osgGA.GUIEventAdapter.KEYDOWN): if ea.getKey() == ord('S'): mode = self._seq.getMode() if mode == osg.Sequence.STOP: mode = osg.Sequence.START # std.cerr << "Start" << std.endl elif mode == osg.Sequence.PAUSE: mode = osg.Sequence.RESUME # std.cerr << "Resume" << std.endl else: mode = osg.Sequence.PAUSE #std.cerr << "Pause" << std.endl self._seq.setMode(mode) elif ea.getKey() == ord('L'): mode = osg.Sequence.LoopMode() (mode, begin, end) = self._seq.getInterval() if mode == osg.Sequence.LOOP: mode = osg.Sequence.SWING # std.cerr << "Swing" << std.endl else: mode = osg.Sequence.LOOP # std.cerr << "Loop" << std.endl self._seq.setInterval(mode, begin, end) return False # accept visits def accept(self, v): pass def main(argv ): # use an ArgumentParser object to manage the program arguments. arguments = osg.ArgumentParser(argv) # set up the usage document, in case we need to print out how to use this program. arguments.getApplicationUsage().setDescription(arguments.getApplicationName()+" is the example which demonstrates use of osg.Sequence.") arguments.getApplicationUsage().setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...") arguments.getApplicationUsage().addCommandLineOption("-h or --help","Display this information") # construct the viewer. viewer = osgProducer.Viewer(arguments) # set up the value with sensible default event handlers. viewer.setUpViewer(osgProducer.Viewer.STANDARD_SETTINGS) # get details on keyboard and mouse bindings used by the viewer. viewer.getUsage(arguments.getApplicationUsage()) # if user request help write it out to cout. if arguments.read("-h") or arguments.read("--help"): arguments.getApplicationUsage().write(sys.stdout) return 1 # any option left unread are converted into errors to write out later. arguments.reportRemainingOptionsAsUnrecognized() # report any errors if they have occured when parsing the program aguments. if arguments.errors(): arguments.writeErrorMessages(sys.stdout) return 1 if arguments.argc()<=1: arguments.getApplicationUsage().write(sys.stdout,osg.ApplicationUsage.COMMAND_LINE_OPTION) return 1 # root rootNode = osg.Group() # create info display text = [ "osg.Sequence Mini-Howto", "- can be used for simple flip-book-style animation", "- is subclassed from osg.Switch", "- assigns a display duration to each child", "- can loop or swing through an interval of it's children", "- can repeat the interval a number of times or indefinitively", "- press 'Shift-S' to start/pause/resume", "- press 'Shift-L' to toggle loop/swing mode" ] rootNode.addChild(createHUD(createTextGroup(text))) # add sequence of models from command line seq = createSequence(arguments) rootNode.addChild(seq) # add model to viewer. viewer.setSceneData(rootNode) # add event handler to control sequence viewer.getEventHandlerList().push_front(SequenceEventHandler(seq)) # create the windows and run the threads. viewer.realize() while not viewer.done(): # wait for all cull and draw threads to complete. viewer.sync() # update the scene by traversing it with the the update visitor which will # call all node update callbacks and animations. viewer.update() # fire off the cull and draw traversals of the scene. viewer.frame() # wait for all cull and draw threads to complete before exit. viewer.sync() return 0 if __name__ == "__main__": sys.exit(main(sys.argv))