;=======================================================================================================
; GeoWall Stereo Library for Blitz3D
; (C) 2004 Jason Leigh, Electronic Visualization Laboratory
; Created: 5/15/2004
; Version: 8/15/2004
;
; This is a set of APIs to enable GeoWall-style (ie twinview side-by-side) stereo for Blitz3D.
; Note that in this implementation the LEFT eye is assumed to be the lead camera. The RIGHT eye view
; is created by offseting from the lead camera.
 
; If you have comments, questions, improvements please post a message on: www.evl.uic.edu/cavern/forum
; For further information about the GeoWall see www.geowall.org
; This code is fully freeware. By using this you take sole responsibility for any damages
; that may result from its use, misuse Or abuse.

; Version: 7/3/2004
; Added SL_SwitchToMono and SL_SwitchToStereo to allow an application to switch on the fly.
;
; Version: 8/15/2004
; Added eye separation as a parameter that the library stores for itself. Also added accessor functions and
; eliminated the need to specify eye separation in SL_Update()
;
;10/15/2004 -- Chris Turek
;added the camera_pivot as a parent to the 2 cameras
;
; ======================================================================================================

Global g_slCameraL, g_slCameraR, g_slEyeSeparation#=0

; Use this to automatically create 2 cameras.
; If you already create your own cameras you should call:
;		SL_SetLeftCamera(); SL_RightCamera() and then SL_SetUpCamera()
Function SL_CreateStereoCameras()
	SL_CreateLeftCamera()
	SL_CreateRightCamera()
	Return g_slCameraL
End Function

; Accessor Functions --------------------
Function SL_SetLeftCamera(camera)
	g_slCameraL=camera
End Function

Function SL_SetRightCamera(camera)
	g_slCameraR=camera
End Function

Function SL_CreateLeftCamera()
	g_slCameraL=CreateCamera()
	Return g_slCameraL
End Function

Function SL_CreateRightCamera()
	g_slCameraR=CreateCamera()
	Return g_slCameraR
End Function

Function SL_GetRightCamera()
	Return g_slCameraR
End Function

Function SL_GetLeftCamera()
	Return g_slCameraL
End Function

Function SL_SetEyeSeparation(eye#)
	g_slEyeSeparation# = eye#
End Function

Function SL_GetEyeSeparation()
	Return g_slEyeSeparation#
End Function

;----------------------------------------

; Set up stereo cameras (ie their viewports)
Function SL_SetUpCameras()
	CameraViewport g_slCameraR,GraphicsWidth()/2,0,GraphicsWidth()/2,GraphicsHeight()
	CameraViewport g_slCameraL,0,0,GraphicsWidth()/2,GraphicsHeight()
End Function

; Switch to monoscopic display mode
Function SL_SwitchToMono()
	CameraViewport g_slCameraL,0,0,GraphicsWidth(), GraphicsHeight()
	CameraViewport g_slCameraR,0,0,0,0
	
End Function

; Switch to stereoscopic display mode
Function SL_SwitchToStereo()
	SL_SetUpCameras()
	
End Function

; Update stereo cameras.
; Stereo eye separation is +ve For transverse viewing, And -ve For crosseye viewing.
Function SL_Update()

	pitch#=EntityPitch#(g_slCameraL)
	roll#=EntityRoll#(g_slCameraL)
	yaw#=EntityYaw#(g_slCameraL)
	x#=EntityX#(g_slCameraL)
	y#=EntityY#(g_slCameraL)
	z#=EntityZ#(g_slCameraL)
	PositionEntity g_slCameraR,x#,y#,z#
	RotateEntity g_slCameraR,pitch#,yaw#,roll#
	TurnEntity g_slCameraR,0,-90,0 : MoveEntity g_slCameraR,0,0,g_slEyeSeparation# : TurnEntity g_slCameraR,0,90,0
End Function

; Set up the field of view to produce "accurate" stereo given the physical screen dimensions
; and the distance of the viewer to the screen.
; 
; This function is really only useful if all your objects in the world conform to a scaling
; convention that is the same as the real world- ie. 1 unit of distance = 1 foot (or 1 meter).
; If you do follow this convention then a 1 foot square will measure to be 1 foot when projected
; at the plane of the screen, and all you need to do is to use the actual eye separation of the
; viewer in the SL_Update() function.
; As I said this is only really useful if you conform to a uniform scaling convention. If you
; are trying to put stereo into an existing game, I recommend you ignore this function and just
; play with different eye separation values until you get a comfortable display.
;
; Final Note for the stereo techies: this is NOT perfectly accurate stereo because
; I cannot create an off-axis projected view frustrum with Blitz3D. But this is pretty close.
Function SL_SetUpCorrectScaleStereo(screenWidth#, screenHeight#, distanceToScreen#)
	stereofov# = 2.0*ATan(screenWidth#/(2.0*distanceToScreen#))
	
	; Set camera fov
	CameraZoom g_slCameraL,1.0/Tan(stereofov#/2.0)
	CameraZoom g_slCameraR,1.0/Tan(stereofov#/2.0)
	
	; Ignore the code below. They belong to the DarkBASIC version of this code.
	
;	set camera fov leftCam,stereofov#*2.0
;	set camera fov rightCam, stereofov#*2.0
	
;	` Set the screen's correct aspect ratio so that a square looks like a square.
;	sx#=screenMaxX
;	sy#=screenMaxY
;	stereoaspect# = (sx#/2.0)/sy#
	
;	set camera aspect leftCam, stereoaspect#
;set camera aspect rightCam, stereoaspect#
End Function