# Copyright (c) 2001, Stanford University # All rights reserved # # See the file LICENSE.txt for information on redistributing this software. # Test running a quad-buffered stereo-aware program in a passive stereo # configuration. Basically, instead of quad-color buffers, we use a tilesort # config with two servers, one for the left eye, one for the right. # This demo runs in two modes: # 1. Native stereo (the default): # The stereocube demo will be run with the -s option which causes it # explicitly render left/right views with glDrawBuffer. # 2. Forced stereo (pass in "force" parameter) # The stereocube demo runs as a normal, non-stereo program. # The config file here specifies special viewing and projection # matrices to produce a stereo effect. # # Two server windows will open, one for the left eye, one for the right. # By either "defocusing" or crossing your eyes you can see the stere effect. # The default window arrangement is for defocused stereo. # You'll have to swap the default window positions to get cross-eyed stereo. # # You may also have to tune the EyeSep (interocular distance) and # default tile/window size. import sys sys.path.append( "../server" ) from mothership import * import crmatrix FORCE_STEREO = 0 DEMO = "stereocube" for arg in sys.argv[1:]: if arg == "-force": FORCE_STEREO = 1 elif arg[0] != "-": DEMO = arg print "--> Note: you may have to tweak the projection parameters!" else: print "Unknown option %s" % arg sys.exit(1) if FORCE_STEREO: print "--> Forcing %s into stereo mode via config file." % DEMO else: print "--> Running %s in conventional stereo mode." % DEMO if DEMO == "stereocube": # Parameters copied from sterecube.c demo if FORCE_STEREO == 0: DEMO += " -s" else: EyeSep = 0.3 Width = 12.0 Hither = 1.0 Yon = 25.0 FocalDist = 5.0 elif DEMO == "city": EyeSep = 0.3 Width = 12.0 Hither = 1.0 Yon = 250.0 FocalDist = 5.0 elif DEMO == "atlantis": # atlantis uses some really big numbers! # not a great demo for stereo, either. EyeSep = 0.3 Width = 2000.0 Hither = 10000.0 Yon = 400000.0 FocalDist = Hither * 2.0 elif DEMO == "paraview": # Note: seems to work with "blow.vtk" dataset EyeSep = 2.0 Width = 40.0 Hither = 120.0 Yon = 180.0 FocalDist = 150 else: # some default values that seem to work for some Mesa demos EyeSep = 0.3 # half of interocular distance Width = 2.0 # frustum width at FocalDist Hither = 1.0 # near clip plane distance from eye Yon = 250.0 # far clip plane distance from eye FocalDist = 4.0 # focal distance for stereo imaging cr = CR() cr.MTU( 1024*1024 ) TileWidth = 250 TileHeight = 250 tilesortspu = SPU("tilesort") tilesortspu.Conf('bucket_mode', 'Test All Tiles') tilesortspu.Conf('stereo_mode', 'Passive') tilesortspu.Conf('scale_images', 1) clientnode = CRApplicationNode( ) clientnode.StartDir( crbindir ) clientnode.SetApplication( DEMO ) clientnode.AddSPU( tilesortspu ) EyeNames = [ "left", "right" ] # Loop over two eye views for eye in range(2): renderspu = SPU( 'render' ) renderspu.Conf( 'window_geometry', [eye*(TileWidth+10), 0, TileWidth, TileHeight] ) renderspu.Conf( 'title', "%s view" % EyeNames[eye] ) node = CRNetworkNode( ) # Note: same tile bounds for both views/servers! node.AddTile( 0, 0, TileWidth, TileHeight ) if FORCE_STEREO: # Set up left/right eye viewing transforms to impose upon a non-stereo # application: # 1. Specify a viewing matrix to achieve interocular translation. # 2. Specify a skewed projection frustum for each eye. # Arithmetic same as in sterecube.c demo aspect = float(TileWidth) / float(TileHeight) s = Hither / FocalDist halfWidth = 0.5 * Width top = s * halfWidth bottom = -top # View matrix v = crmatrix.CRMatrix() if eye == 0: v.Translate(+EyeSep, 0, 0) else: v.Translate(-EyeSep, 0, 0) node.Conf('view_matrix', v.ToList()) # Projection matrix p = crmatrix.CRMatrix() if eye == 0: left = s * ((halfWidth * -aspect) - EyeSep); right = s * ((halfWidth * aspect) - EyeSep); else: left = s * (halfWidth * -aspect + EyeSep); right = s * (halfWidth * aspect + EyeSep); p.Frustum(left, right, bottom, top, Hither, Yon) node.Conf('projection_matrix', p.ToList()) node.Conf('optimize_bucket', 0) # just to be safe node.Conf('stereo_view', EyeNames[eye]) node.AddSPU( renderspu ) cr.AddNode( node ) # Add the server, indicating whether it's for the left or right eye. # Actually, lefv vs. right doesn't matter if FORCE_STEREO is non-zero. tilesortspu.AddServer( node, protocol='tcpip', port=7000 + eye) cr.AddNode( clientnode ) cr.Go()