Graphics.OculusRiftIntegration - lordmundi/wikidoctest GitHub Wiki
These instructions are incomplete and is an active work in progress. Feel free to update it with correct or more complete information.
This writeup was provided by Matthew Benson. Contact him with questions.
Current State:
- Stereoscopic flat display only.
- No head tracking, yet.
- Distortion is not correct. This will look funky and probably hurt your eyes until its fixed.
These were steps gathered through experimentation and frustration to get an early development version of the Oculus Rift integrated with EDGE. The Oculus Rift is a consumer grade Virtual Reality headset with stereoscopic display and head tracking for $350. The current release only tracks head rotation but the next release will include head translation as well.
Assumptions
- Windows 7
- Oculus Rift Dev Kit 1 (2013)
- EDGE Version 2.3
- Oculus Rift calibrated using SDK included utilities.
- <DOUG_HOME> refers to the directory where EDGE is installed.
- Best viewed at 1600×1000.
First, we need to calculate some parameters. Normally, a native Oculus Rift application would query the device driver for some of this data. We're going to do as much as we can without writing code, for now. Here are some default values we'll start with:
Variable | Default Value |
---|---|
HResolution | 1280 |
VResolution | 800 |
HScreenSize | 0.14976 |
VScreenSize | 0.09356 |
VScreenCenter | 0.0468 |
EyeToScreenDistance | 0.041 |
LensSeparationDistance | 0.0635 |
InterpupillaryDistance | 0.064 |
DistortionK[0] | 1.0 |
DistortionK1 | 0.22 |
DistortionK2 | 0.24 |
DistortionK3 | 0.0 |
ChromAbCorrection[0] | 0.996 |
ChromAbCorrection1 | −0.004 |
ChromAbCorrection2 | 1.014 |
ChromAbCorrection3 | 0.0 |
Taken from the Oculus SDK Overview
- Set the viewport to cover the left eye screen area.
- Determine the aspect ratio a and \phi_{fov} based on the reported HMDInfo values.
- Calculate the center projection matrix \mathbf{P} based on a and \phi_{fov} .
- Adjust the projection matrix \mathbf{P} based on the lens separation distance.
- Adjust the view matrix \mathbf{V} to match eye location.
a=\frac{HResolution}{2\times VResolution}
\phi _{fov}=2\times \arctan \left ( \frac{VScreenSize}{2\times EyeToScreenDistance} \right )
\mathbf{P}=\begin{vmatrix} \frac{1}{a\times \tan \left ( \frac{\phi _{fov}}{2} \right )} & 0 & 0 & 0 \ 0 & \frac{1}{\tan \left ( \frac{\phi _{fov}}{2} \right )} & 0 & 0 \ 0 & 0 & \frac{z_{far}}{z_{near}-z_{far}} & \frac{z_{far} z_{near}}{z_{near}-z_{far}} \ 0 & 0 & -1 & 0 \end{vmatrix}
d_{lens}=LensSeparationDistance
h_{meters}=\frac{HScreenSize}{4}-\frac{d_{lens}}{2}
h=\frac{4\times h_{meters}}{HScreenSize}
\mathbf{H} = \begin{bmatrix} 1 & 0 & 0 & \pm h \ 0 & 1 & 0 & 0 \ 0 & 0 & 1 & 0 \ 0 & 0 & 0 & 1\end{bmatrix}
d_{ip} = InterpupillaryDistance
\mathbf{{V}'} = \begin{bmatrix} 1 & 0 & 0 & \pm \frac{d_{ip}}{2} \ 0 & 1 & 0 & 0 \ 0 & 0 & 1 & 0 \ 0 & 0 & 0 & 1\end{bmatrix} \mathbf{V}
LensCenter = 1 - 2\times LensSeparationDistance/HScreenSize
Make a new userdata directory from the template delivered with EDGE and call it "userdata.oculus_rift". In Windows Explorer, make a copy of <DOUG_HOME>/userdata and rename it to <DOUG_HOME>/userdata.oculus_rift.
In the <DOUG_HOME>/userdata.oculus_rift/user.cfg file, add the following right after the ENG_GRAPHICS section:
OCULUS_RIFT
{
DOUG
{
TCL
{
cev_plume_init "${GUI_HOME}/cev_plume_init.tcl"
cev_plume_drive "${GUI_HOME}/cev_plume_drive.tcl"
}
GUI
{
lightsoff "${GUI_HOME}/lightsoff.tcl"
#disp "${GUI_HOME}/multidisp.tcl"
#camtargets "${GUI_HOME}/cam_targets_rel.tcl"
animate "${GUI_HOME}/animate.tcl"
#simdata "${GUI_HOME}/simdatadlg.tcl"
keycuecard "${GUI_HOME}/keycuecard_cev.tcl"
#dyn_ov "${GUI_HOME}/dynamic_overlays.tcl"
#cev_ovl "${GUI_HOME}/cev_overlay_comm.tcl"
#cev_ovl_menu "${GUI_HOME}/cev_overlay_menu.tcl"
#trails "${GUI_HOME}/trails.tcl"
speedfly "${GUI_HOME}/speedfly.tcl"
fix_ideal_light "${GUI_HOME}/fix_ideal_light.tcl"
camdata "${GUI_HOME}/camera_data_overlay.tcl"
#doug_config "${GUI_HOME}/doug_config.tcl"
eyesep "${USERDATA}/gui/change_eye_separation.tcl"
blipper ""
camdata_toggle "${USERDATA}/gui/camera_overlay_toggle.tcl"
}
}
command_line
{
-plugin cctv '-nofocusdraw -nofocus'
-plugin canvas '-dir "${DOUG_HOME}/fonts" -default arial'
-plugin dcanvas '-image_objs 1'
-plugin ideal '-node IDEAL_LIGHTING'
-plugin script '-input "${RECONFIG_FILE}"'
}
plugins
{
#flycam dsp_flycam
cctv dsp_cctv
ideal dsp_ideal
canvas dsp_canvas
dcanvas dsp_drawcanvas
simdata dsp_simdata
jpeg dsp_jpegsave
#timer dsp_timeit
record dsp_record
trail dsp_trail
#noise dsp_noise
}
channel1
{
view.TOP LeftEye perspective( 97.5346, 0.8, 4.0, 1000000000000.0 ); xywh( 0, 0, 800, 1000 ); attribs(CAMINFO);
view.BOTTOM RightEye perspective( 97.5346, 0.8, 4.0, 1000000000000.0 ); xywh( 800, 0, 640, 1000 ); attribs(CAMINFO);
}
}
This new section includes two views which will become our left and right eyes. This is similar to the 3DTV tutorial, but the views are side by side and with the correct aspect ratio.
In the <DOUG_HOME>/userdata.oculus_rift/configs/user_models.cfg file, add in the following to the top CAMERAS block (i.e., "DSP_CONFIG→DATA→SCENE_LOAD→CAMERAS"):
...
node(LeftEye); xyz(-2613.4251 -997.3266 -11.3556); pyr(2.0899 -2.4377 -0.1274); parent( JimboCam );
node(RightEye); xyz(0, 2.3622, 0); parent( LeftEye );
...
This positions the LeftEye camera in some random position, and then puts the RightEye camera 6 cm (2.3622 inches) to the right of it. This is the average separation of most adults. The average range is 5.4 to 6.8 cm, with the average male at 6.5 cm and female at 5.5 cm. Feel free to adjust this eye separation to suit your needs. We will add a script later to make it configurable at runtime.
NOTE: This separation is one of the factors that can cause "simulation sickness", particularly once head tracking is added. When a good value is found, this will be updated.
Now that we have a display context and cameras for the viewports, let's make a script to run it. Inside the <DOUG_HOME> directory, create the following startup script called "run_oculus_rift.bat":
@ECHO OFF
SETLOCAL
IF NOT DEFINED USERDATA set USERDATA=userdata.oculus_rift
IF NOT DEFINED MISSION set MISSION=CEV
set VR_HOST_CPU=Win32
SET VERSION=EDGE_v2.3
set DOUG_HOST_CPU=Win32
set LD_LIBRARY_PATH=bin_Win32
set doug_exec=bin_%DOUG_HOST_CPU%\doug.exe
set doug_comm_mode=standalone
set doug_display=OCULUS_RIFT
set doug_config_file=cev.cfg
set Path=lib_Win32;%PATH%
set HOST=%USERDOMAIN%
set DOUG_TITLE=EDGE
set USER=%USERNAME%
%doug_exec% -double -mode %doug_comm_mode% -display %doug_display% -config %doug_config_file% -DEDGE_SETTINGS_FILE="edge_settings.cfg" -quiet %1 %2 %3 %4 %5 %6 %7 %8
The Oculus Rift displays cuts off the top, bottom, and side borders so there is no need to remove the borders for a full screen display.
As it is, you can't fly the camera around with the usual controls. This is because the instance running in the background doesn't know what the "current" camera is, since it doesn't have a viewport. To workaround this, we trick the scripts and manually set the camera.
Edit the user.cfg, and add a script into the OCULUS_RIFT display context GUI block called "getcam_override":
...
getcam_override "${USERDATA}/gui/getcam_override.tcl"
...
And then in the <DOUG_HOME>/userdata.oculus_rift/gui directory, create a file called "getcam_override.tcl" with the following contents:
proc getcam {args} {
global curcam
set curcam LeftEye
}
Next we're going to make the eye separation adjustable at run time. This will make it easier to configure. To do this, create a script called "change_eye_separation.tcl" in <DOUG_HOME>/userdata.oculus_rift/gui with the following contents:
global dougmain
bind $dougmain <KeyRelease-bracketleft> {
set sep [doug.node RightEye get -y]
doug.node RightEye set -y [expr $sep - 0.1]
puts "Eye Sep is now [expr $sep - 0.1] inches"
}
bind $dougmain <KeyRelease-bracketright> {
set sep [doug.node RightEye get -y]
doug.node RightEye set -y [expr $sep + 0.1]
puts "Eye Sep is now [expr $sep + 0.1] inches"
}
set my_fullscr_win [doug.display get -main_window]
focus -force $my_fullscr_win
update
That will let the bracket keys ("[" and "]") adjust the eye separation in one inch increments. To use it, add it to the GUI block of the OCULUS_RIFT display context as you did with the other scripts.
Comment from Mat Hart:
This worked pretty well for the HTC Vive too. Only delta was the left and right eyes being way too far from aligned. Not sure what the proper way to correct for this would be, but I did it this way, by adding a −4 yaw to the leftEye relative to RightEye:
node(LeftEye); xyz(-2613.4251 -997.3266 -11.3556); pyr(2.0899 -2.4377 -0.1274); parent( JimboCam );
node(RightEye); xyz(0, 2.3622, 0); pyr(0,-4,0); parent( LeftEye );