#!/usr/bin/env python # Copyright (C) 2002-2003 Gideon May (gideon@computer.org) # # Permission to copy, use, sell and distribute this software is granted # provided this copyright notice appears in all copies. # Permission to modify the code and to distribute modified code is granted # provided this copyright notice appears in all copies, and a notice # that the code was modified is included with the copyright notice. # # This software is provided "as is" without express or implied warranty, # and with no claim as to its suitability for any purpose. #/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield # * # * This library is open source and may be redistributed and/or modified under # * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or # * (at your option) any later version. The full license is in LICENSE file # * included with this distribution, and on the openscenegraph.org website. # * # * This library 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. See the # * OpenSceneGraph Public License for more details. #*/ import sys import math from PyOSG import Producer from PyOSG import osg from PyOSG import osgDB from PyOSG import osgGA from PyOSG import osgUtil from PyOSG import osgProducer from PyOSG import osgText from OpenGL.GL import * def createHUDText(): rootNode = osg.Group() font = osgText.readFontFile("fonts/arial.ttf") geode = osg.Geode() rootNode.addChild(geode) windowHeight = 1024.0 windowWidth = 1280.0 margin = 50.0 #################################################### # # Examples of how to set up different text layout # layoutColor = osg.Vec4(1.0,1.0,0.0,1.0) layoutCharacterSize = 20.0 if 1: text = osgText.Text() text.setFont(font) text.setColor(layoutColor) text.setCharacterSize(layoutCharacterSize) text.setPosition(osg.Vec3(margin,windowHeight-margin,0.0)) # the default layout is left to right, typically used in languages # originating from europe such as English, French, German, Spanish etc.. text.setLayout(osgText.Text.LEFT_TO_RIGHT) text.setText("text.setLayout(osgText.Text.LEFT_TO_RIGHT);") geode.addDrawable(text) if 1: text = osgText.Text() text.setFont(font) text.setColor(layoutColor) text.setCharacterSize(layoutCharacterSize) text.setPosition(osg.Vec3(windowWidth-margin,windowHeight-margin,0.0)) # right to left layouts would be used for hebrew or arabic fonts. text.setLayout(osgText.Text.RIGHT_TO_LEFT) text.setText("text.setLayout(osgText.Text.RIGHT_TO_LEFT);") geode.addDrawable(text) if 1: text = osgText.Text() text.setFont(font) text.setColor(layoutColor) text.setPosition(osg.Vec3(margin,windowHeight-margin,0.0)) text.setCharacterSize(layoutCharacterSize) # vertical font layout would be used for asian fonts. text.setLayout(osgText.Text.VERTICAL) text.setText("text.setLayout(osgText.Text.VERTICAL);") geode.addDrawable(text) #################################################### # # Examples of how to set up different font resolution # fontSizeColor = osg.Vec4(0.0,1.0,1.0,1.0) fontSizeCharacterSize = 30 cursor = osg.Vec3(margin*2,windowHeight-margin*2,0.0) if 1: text = osgText.Text() text.setFont(font) text.setColor(fontSizeColor) text.setCharacterSize(fontSizeCharacterSize) text.setPosition(cursor) # use text that uses 10 by 10 texels as a target resolution for fonts. text.setFontResolution(10,10); # blocky but small texture memory usage text.setText("text.setFontResolution(10,10); # blocky but small texture memory usage") geode.addDrawable(text) cursor._y -= fontSizeCharacterSize if 1: text = osgText.Text() text.setFont(font) text.setColor(fontSizeColor) text.setCharacterSize(fontSizeCharacterSize) text.setPosition(cursor) # use text that uses 10 by 10 texels as a target resolution for fonts. text.setFontResolution(20,20); # smoother but higher texture memory usage (but still quite low). text.setText("text.setFontResolution(20,20); # smoother but higher texture memory usage (but still quite low).") geode.addDrawable(text) cursor._y -= fontSizeCharacterSize if 1: text = osgText.Text() text.setFont(font) text.setColor(fontSizeColor) text.setCharacterSize(fontSizeCharacterSize) text.setPosition(cursor) # use text that uses 10 by 10 texels as a target resolution for fonts. text.setFontResolution(40,40); # even smoother but again higher texture memory usage. text.setText("text.setFontResolution(40,40); # even smoother but again higher texture memory usage.") geode.addDrawable(text) #################################################### # # Examples of how to set up different sized text # characterSizeColor = osg.Vec4(1.0,0.0,1.0,1.0) cursor._y -= fontSizeCharacterSize*2.0 if 1: text = osgText.Text() text.setFont(font) text.setColor(characterSizeColor) text.setFontResolution(20,20) text.setPosition(cursor) # use text that 20 units high. text.setCharacterSize(20); # small text.setText("text.setCharacterSize(15.0); # small") geode.addDrawable(text) cursor._y -= 30.0 if 1: text = osgText.Text() text.setFont(font) text.setColor(characterSizeColor) text.setFontResolution(30,30) text.setPosition(cursor) # use text that 20 units high. text.setCharacterSize(30.0) # medium text.setText("text.setCharacterSize(30.0); # medium") geode.addDrawable(text) cursor._y -= 50.0 if 1: text = osgText.Text() text.setFont(font) text.setColor(characterSizeColor) text.setFontResolution(40,40) text.setPosition(cursor) # use text that uses 10 by 10 texels as a target resolution for fonts. text.setCharacterSize(60.0); # large text.setText("text.setCharacterSize(60.0); # large") geode.addDrawable(text) #################################################### # # Examples of how to set up different alignments # alignmentSizeColor = osg.Vec4(0.0,1.0,0.0,1.0) alignmentCharacterSize = 25.0 cursor._x = 640 cursor._y = margin*4.0 alignmentList = {} alignmentList[osgText.Text.LEFT_TOP] = "text.setAlignment(osgText.Text.LEFT_TOP);" alignmentList[osgText.Text.LEFT_CENTER] = "text.setAlignment(osgText.Text.LEFT_CENTER);" alignmentList[osgText.Text.LEFT_BOTTOM] = "text.setAlignment(osgText.Text.LEFT_BOTTOM);" alignmentList[osgText.Text.CENTER_TOP] = "text.setAlignment(osgText.Text.CENTER_TOP);" alignmentList[osgText.Text.CENTER_CENTER] = "text.setAlignment(osgText.Text.CENTER_CENTER);" alignmentList[osgText.Text.CENTER_BOTTOM] = "text.setAlignment(osgText.Text.CENTER_BOTTOM);" alignmentList[osgText.Text.RIGHT_TOP] = "text.setAlignment(osgText.Text.RIGHT_TOP);" alignmentList[osgText.Text.RIGHT_CENTER] = "text.setAlignment(osgText.Text.RIGHT_CENTER);" alignmentList[osgText.Text.RIGHT_BOTTOM] = "text.setAlignment(osgText.Text.RIGHT_BOTTOM);" alignmentList[osgText.Text.LEFT_BASE_LINE] = "text.setAlignment(osgText.Text.BASE_LINE);" alignmentList[osgText.Text.CENTER_BASE_LINE] = "text.setAlignment(osgText.Text.CENTER_BASE_LINE);" alignmentList[osgText.Text.RIGHT_BASE_LINE] = "text.setAlignment(osgText.Text.RIGHT_BASE_LINE);" sequence = osg.Sequence() for key in alignmentList: alignmentGeode = osg.Geode() sequence.addChild(alignmentGeode) sequence.setTime(sequence.getNumChildren(), 1.0) text = osgText.Text() text.setFont(font) text.setColor(alignmentSizeColor) text.setCharacterSize(alignmentCharacterSize) text.setPosition(cursor) text.setDrawMode(osgText.Text.TEXT|osgText.Text.ALIGNMENT|osgText.Text.BOUNDINGBOX) text.setAlignment(key) text.setText(alignmentList[key]) alignmentGeode.addDrawable(text) sequence.setMode(osg.Sequence.START) sequence.setInterval(osg.Sequence.LOOP, 0, -1) sequence.setDuration(1.0, -1) rootNode.addChild(sequence) #################################################### # # Examples of how to set up different fonts... # cursor._x = margin*2.0 cursor._y = margin*2.0 fontColor = osg.Vec4(1.0,0.5,0.0,1.0) fontCharacterSize = 20.0 spacing = 40.0 if 1: text = osgText.Text() text.setColor(fontColor) text.setPosition(cursor) text.setCharacterSize(fontCharacterSize) text.setFont(None) text.setText("text.setFont(0); # inbuilt font.") geode.addDrawable(text) cursor._x = text.getBound().xMax() + spacing if 1: arial = osgText.readFontFile("fonts/arial.ttf") text = osgText.Text() text.setColor(fontColor) text.setPosition(cursor) text.setCharacterSize(fontCharacterSize) text.setFont(arial) if arial: text.setText("text.setFont(\"fonts/arial.ttf\");") else: text.setText("unable to load \"fonts/arial.ttf\"") geode.addDrawable(text) cursor._x = text.getBound().xMax() + spacing if 1: times = osgText.readFontFile("fonts/times.ttf") text = osgText.Text() text.setColor(fontColor) text.setPosition(cursor) text.setCharacterSize(fontCharacterSize) geode.addDrawable(text) text.setFont(times) if times: text.setText("text.setFont(\"fonts/times.ttf\");") else: text.setText("unable to load \"fonts/times.ttf\"") cursor._x = text.getBound().xMax() + spacing cursor._x = margin*2.0 cursor._y = margin if 1: dirtydoz = osgText.readFontFile("fonts/dirtydoz.ttf") text = osgText.Text() text.setColor(fontColor) text.setPosition(cursor) text.setCharacterSize(fontCharacterSize) text.setFont(dirtydoz) if dirtydoz: text.setText("text.setFont(\"fonts/dirtydoz.ttf\");") else: text.setText("unable to load \"fonts/dirtydoz.ttf\"") geode.addDrawable(text) cursor._x = text.getBound().xMax() + spacing if 1: fudd = osgText.readFontFile("fonts/fudd.ttf") text = osgText.Text() text.setColor(fontColor) text.setPosition(cursor) text.setCharacterSize(fontCharacterSize) text.setFont(fudd) if fudd: text.setText("text.setFont(\"fonts/fudd.ttf\");") else: text.setText("unable to load \"fonts/fudd.ttf\"") geode.addDrawable(text) cursor._x = text.getBound().xMax() + spacing return rootNode def create3DText(center, radius): """ create text which sits in 3D space such as would be inserted into a normal model""" geode = osg.Geode() #################################################### # # Examples of how to set up axis/orientation alignments # characterSize=radius*0.2 pos = osg.Vec3(center._x-radius*.5,center._y-radius*.5,center._z-radius*.5) text1 = osgText.Text() text1.setFont("fonts/times.ttf") text1.setCharacterSize(characterSize) text1.setPosition(pos) text1.setAxisAlignment(osgText.Text.XY_PLANE) text1.setText("XY_PLANE") geode.addDrawable(text1) text2 = osgText.Text() text2.setFont("fonts/times.ttf") text2.setCharacterSize(characterSize) text2.setPosition(pos) text2.setAxisAlignment(osgText.Text.YZ_PLANE) text2.setText("YZ_PLANE") geode.addDrawable(text2) text3 = osgText.Text() text3.setFont("fonts/times.ttf") text3.setCharacterSize(characterSize) text3.setPosition(pos) text3.setAxisAlignment(osgText.Text.XZ_PLANE) text3.setText("XZ_PLANE") geode.addDrawable(text3) text4 = osgText.Text() text4.setFont("fonts/times.ttf") text4.setCharacterSize(characterSize) text4.setPosition(center) text4.setAxisAlignment(osgText.Text.SCREEN) text4.setText("SCREEN") geode.addDrawable(text4) shape = osg.ShapeDrawable(osg.Sphere(center,characterSize*0.2)) shape.getOrCreateStateSet().setMode(GL_LIGHTING,osg.StateAttribute.ON) geode.addDrawable(shape) rootNode = osg.Group() rootNode.addChild(geode) return rootNode 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 text.") 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() 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() return 1 # read the scene from the list of file specified commandline args. rootNode = osgDB.readNodeFiles(arguments) # prepare scene. if 1: center = osg.Vec3(0.0,0.0,0.0) radius = 1.0 if rootNode: # optimize the scene graph, remove rendundent nodes and state etc. optimizer = osgUtil.Optimizer() optimizer.optimize(rootNode) bs = rootNode.getBound() center = bs.center() radius = bs.radius() # make sure the root node is group so we can add extra nodes to it. group = rootNode.asGroup() else: group = None if not group: group = osg.Group() if rootNode: group.addChild(rootNode) rootNode = group if 1: # create the hud. projection = osg.Projection() projection.setMatrix(osg.Matrix.ortho2D(0,1280,0,1024)) modelview_abs = osg.MatrixTransform() modelview_abs.setReferenceFrame(osg.Transform.ABSOLUTE_RF) modelview_abs.setMatrix(osg.Matrix.identity()) modelview_abs.addChild(createHUDText()) projection.addChild(modelview_abs) group.addChild(projection) group.addChild(create3DText(center,radius)) # set the scene to render viewer.setSceneData(rootNode) # create the windows and run the threads. viewer.realize() # #if 0 # # this optional compile block is done as a test against graphics # # drivers that claim support for generate mip map, but the actual # # implementation is flacky. It is not compiled by default. # # # go through each graphics context and switch off the generate mip map extension. # # note, this must be done after the realize so that init of texture state and as # # result extension structures have been iniatilized. # for(unsigned int contextID = 0; # contextID