View Single Post
  #4  
Old 02-15-2012, 02:12 PM
AySz88 AySz88 is offline
Member
 
Join Date: Aug 2011
Posts: 13
(The bulk of the file is mostly due to documentation, which I'm keeping intact in case it's useful.)

Part 1 of sunyhardware.py:

Code:
"""
This module provides functions and classes related to the utilization of
virtual reality hardware with Vizard in the lab of _______ at SUNY Optometry.

Variables: None.
Functions: getValue, loadCave, linkView,
	isHiBallAvailable, getTracker, getAllSensors.
Classes: Keyboard, HiBall.

For additional information about a particular function or class, please see
the documentation string for that attribute.

Usage examples:
>>> (headTrkr, stylusTrkr, stylusBtn) = sunyhardware.getAllSensors()
>>> tracker = HiBall()
>>> screenWidth = getValue('screenWidth')
>>> print loadCave.__doc__

<removed>
August 4, 2008
	edited by:
	<removed>
	July 29, 2011
"""

from __future__ import division #implements "/" as division without truncation regardless of its operands
import viz #standard Vizard module
import vizcave #Vizard virtual reality cave module

#private variables (measurements taken by hand [AEY 8/11/2011] in meters)
	#1024x768, projector settings: 'size' = 1.060, 'vertical stretch' = 1.000
	#most are a rough average of two measurements
_screenHeight = 1.779
_screenWidth = 2.396
_screenHeightOffset = (
	0.448	#floor-to-frame
	+ 0.034	#plus frame width
	+ 0.030	#plus frame-to-image
	)
_screenWidthOffset = (
	-0.060	#origin-to-right-wall
	+ 0.270	#plus wall-to-big-frame
	+ 0.034	#plus frame width
	+ 0.030	#plus frame-to-image
	)
_screenDepthOffset = (
	0.573	#origin-to-wall
	+ 0.083	#plus wall-to-frame
	+ 0.023	#plus frame width
	+ 0.008	#plus glass-to-image (glass thickness)
	)
_eyesHeightOffset = 0.140 #approx dist of eyes below HiBall (MAR+SJH 1/23/2009, RBM subject)
_eyesDepthOffset = 0.110 #approx dist of eyes in front of HiBall (MAR+SJH 1/23/2009, RBM subject)

_stylusOffset = [-0.00175, -0.1050, -0.1693] #TODO from HiBall stylus calibration procedure, currently 2003 numbers
	# intended for link.preTrans(); see Help (Reference > Linking > Operators on Links)

def getValue(parameter):
	"""
	Returns the read-only value of the named private attribute.
	
	Currently accepted parameter names include: 'screenHeight', 'screenWidth',
	'screenHeightOffset', 'screenWidthOffset', 'screenDepthOffset',
	'eyesHeightOffset', 'eyesDepthOffset'.
	
	Definition:
	getValue(parameter)
	
	Usage:
	>>> screenWidth = getValue('screenWidth')
	"""
	
	if parameter=='screenWidth':
		return _screenWidth
	elif parameter=='screenHeight':
		return _screenHeight
	elif parameter=='screenHeightOffset':
		return _screenHeightOffset
	elif parameter=='screenWidthOffset':
		return _screenWidthOffset
	elif parameter=='screenDepthOffset':
		return _screenDepthOffset
	elif parameter=='eyesHeightOffset':
		return _eyesHeightOffset
	elif parameter=='eyesDepthOffset':
		return _eyesDepthOffset
	elif parameter=='xZero':
		return -_screenWidthOffset - _screenWidth/2
	elif parameter=='yZero':
		return _screenHeightOffset + _screenHeight/2
	elif parameter=='zZero':
		return _screenDepthOffset
	elif parameter=='stylusOffset':
		return _stylusOffset
	elif isinstance(parameter,tuple): # must use tuples since strings are lists
		return [getValue(x) for x in parameter]

def getVisualBounds(origin):
	# Given HiBall coordinates of a viewpoint, return elevations and azimuths of each edge of screen (l,r,t,b)
	from math import atan2, degrees
	(x0, y0, z0) = getValue(('xZero', 'yZero', 'zZero'))
	(w, h) = getValue(('screenWidth', 'screenHeight'))
	[x,y,z] = origin
	lrtb = (x0-w/2-x, x0+w/2-x, y0+h/2-y, y0-h/2-y)
	angles = map(lambda opposite: atan2(opposite,z), lrtb)
	print "bounds at", origin
	print "... are", map(degrees, angles)
	return angles

def loadCave(tracker=None,orthographic=False):
	"""
	Returns a Vizard cave optionally driven by tracker coordinates.
	
	Creates a vizcave wall based on coordinates for the Christie Mirage S+4K
	projection screen. Creates a stereo vizcave cave to which the wall and
	optionally provided tracker are added. The cave can optionally be placed
	in orthographic projection (defaults to perspective). The tracker, if
	provided, sends position and orientation information to the cave, which
	is used in the calculation of the viewing frustum. Note that the active
	viewport is not updated with the tracking position; please use linkView
	to do so.
	
	Definition:
	loadCave(tracker=None,orthographic=False)
	
	Usage:
	>>> cave = loadCave(tracker)
	"""
	
	#save default inter-pupilary distance (IPD)
	ipd = viz.MainWindow.getIPD()
	if not isinstance(tracker,viz.VizView):
		ipd = -ipd #KLUDGE - this solves eye-swap problem, but still not sure where this problem comes from
	
	def makeOrthographic():
		# TODO Doesn't change IPD based on orientation of eyes with head
		# Requires the wall to be in the X-Y plane
		# to set up tracker so that stereo IPD will be correct?
		
		# NOTE this is the "intended" way of doing this, but has drawbacks
		viz.MainView.eyeheight(0)
		viz.MainView.reset(viz.RESET_POS)
		viz.MainWindow.ortho(
			-_screenWidthOffset - _screenWidth,
			-_screenWidthOffset,
			_screenHeightOffset,
			_screenHeightOffset + _screenHeight,
			-1, -1, # automatic near and far clip
			eye = viz.BOTH_EYE)
		viz.MainWindow.screenDistance(_screenDepthOffset)
		
		return None
	
	cave = vizcave.Cave()
	
	def makePerspective():
		#setup wall using world coordinates
		upperLeft = [-_screenWidthOffset-_screenWidth, _screenHeightOffset+_screenHeight, _screenDepthOffset]
		upperRight = [-_screenWidthOffset, _screenHeightOffset+_screenHeight, _screenDepthOffset]
		lowerLeft = [-_screenWidthOffset-_screenWidth, _screenHeightOffset, _screenDepthOffset]
		lowerRight = [-_screenWidthOffset, _screenHeightOffset, _screenDepthOffset]
		wall = vizcave.Wall('wall',upperLeft,upperRight,lowerLeft,lowerRight)
		
		#setup cave with wall and tracker (optional)
		cave.setIPD(ipd)
		cave.addWall(wall)
		if tracker:
			cave.setTracker(pos=tracker, ori=tracker)
	
	tracker.makeOrthographic = makeOrthographic
	tracker.makePerspective = makePerspective
	
	if orthographic:
		tracker.makeOrthographic()
	else:
		tracker.makePerspective()
	
	return cave
	
	# FAILED METHOD
	# Below code **messes up stereo** when giving orthographic-like projection
	"""
	#setup wall using world coordinates
	upperLeft = [-_screenWidthOffset-_screenWidth, _screenHeightOffset+_screenHeight, _screenDepthOffset]
	upperRight = [-_screenWidthOffset, _screenHeightOffset+_screenHeight, _screenDepthOffset]
	lowerLeft = [-_screenWidthOffset-_screenWidth, _screenHeightOffset, _screenDepthOffset]
	lowerRight = [-_screenWidthOffset, _screenHeightOffset, _screenDepthOffset]
	wall = vizcave.Wall('wall',upperLeft,upperRight,lowerLeft,lowerRight)
	
	#setup cave with wall and tracker (optional)
	cave = vizcave.Cave()
	cave.setIPD(ipd)
	cave.addWall(wall)
	if tracker:
		# HACK if orthographic, shift viewpoint as if view is from far away (image as through a telescope)
		cave.orthoTracker = viz.link(tracker, viz.NullLinkable)
		cave.orthoTracker.postTrans([0,0,-100])
		
		def makeOrthographic():
			cave.setTracker(pos=cave.orthoTracker, ori=tracker)
		def makePerspective():
			cave.setTracker(pos=tracker, ori=tracker) #named arguments used for clarity (ori required for stereo)
		
		cave.makeOrthographic = makeOrthographic
		cave.makePerspective = makePerspective
		
		if orthographic:
			cave.makeOrthographic()
		else:
			cave.makePerspective()
	return cave
	"""

def linkView(tracker,withCave=False):
	"""
	Returns a view based on tracker coordinates.
	
	Links the provided tracker to the Vizard main viewpoint. If
	withCave=True, links the tracker to main view through the cave
	view, otherwise links directly to the main view (default).
	
	Definition:
	linkView(tracker,withCave=False)
	
	Usage:
	>>> view = linkView(tracker,True)
	"""
	
	# HACK CaveView doesn't require a cave...at the moment
	return vizcave.CaveView(tracker)
	"""
	if withCave:
		#link tracker to CaveView
		view = vizcave.CaveView(tracker) #added flexibility to change viewpoint manually
	else:
		#link tracker directly to viz.MainView
		view = viz.link(tracker,viz.MainView)
		view.setDstFlag(viz.LINK_POS_RAW) #use the raw tracker position coordinates
	return view
	"""

def orthoUpdateCaveAndView(tracker, cave, view, ortho):
	if ortho:
		tracker.makeOrthographic()
		cave.setTracker(pos=None, ori=None)
		view.setView(viz.NullLinkable) # disassociate CaveView and tracker
		viz.cam.reset()
	else:
		tracker.makePerspective()
		cave.setTracker(pos=tracker,ori=tracker)
		view.setView(viz.MainView)

Last edited by AySz88; 02-15-2012 at 02:14 PM. Reason: take out names; not intended for distribution (yet)
Reply With Quote