2013-06-26 00:45:49 +00:00
/**
* \ file stereo_ovr . cpp
* \ brief CStereoOVR
* \ date 2013 - 06 - 25 22 : 22 GMT
* \ author Jan Boon ( Kaetemi )
* CStereoOVR
*/
/*
* Copyright ( C ) 2013 by authors
*
* This file is part of NL3D .
* NL3D is free software : you can redistribute it and / or modify it
* under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* NL3D 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 GNU Affero General
* Public License for more details .
*
* You should have received a copy of the GNU Affero General Public
* License along with NL3D . If not , see
* < http : //www.gnu.org/licenses/>.
*
* Linking this library statically or dynamically with other modules
* is making a combined work based on this library . Thus , the terms
* and conditions of the GNU General Public License cover the whole
* combination .
*
* As a special exception , the copyright holders of this library give
* you permission to link this library with the Oculus SDK to produce
* an executable , regardless of the license terms of the Oculus SDK ,
* and distribute linked combinations including the two , provided that
* you also meet the terms and conditions of the license of the Oculus
* SDK . You must obey the GNU General Public License in all respects
* for all of the code used other than the Oculus SDK . If you modify
* this file , you may extend this exception to your version of the
* file , but you are not obligated to do so . If you do not wish to do
* so , delete this exception statement from your version .
*/
2013-07-06 18:40:42 +00:00
# ifdef HAVE_LIBOVR
2013-07-06 18:05:19 +00:00
2013-06-26 00:45:49 +00:00
# include <nel/misc/types_nl.h>
# include <nel/3d/stereo_ovr.h>
// STL includes
2013-06-28 21:19:32 +00:00
# include <sstream>
2013-06-26 00:45:49 +00:00
// External includes
# include <OVR.h>
// NeL includes
// #include <nel/misc/debug.h>
2013-06-26 06:00:19 +00:00
# include <nel/3d/u_camera.h>
2013-07-01 21:23:54 +00:00
# include <nel/3d/u_driver.h>
# include <nel/3d/material.h>
# include <nel/3d/texture_bloom.h>
# include <nel/3d/texture_user.h>
# include <nel/3d/driver_user.h>
# include <nel/3d/u_texture.h>
2013-06-26 00:45:49 +00:00
// Project includes
using namespace std ;
// using namespace NLMISC;
namespace NL3D {
2013-07-02 17:39:05 +00:00
extern const char * g_StereoOVR_fp40 ;
2013-07-01 21:23:54 +00:00
extern const char * g_StereoOVR_arbfp1 ;
2013-07-02 00:40:27 +00:00
extern const char * g_StereoOVR_ps_2_0 ;
2013-09-09 18:49:59 +00:00
extern const char * g_StereoOVR_glsl330f ;
2013-07-01 21:23:54 +00:00
2013-06-26 00:45:49 +00:00
namespace {
class CStereoOVRLog : public OVR : : Log
{
public :
CStereoOVRLog ( unsigned logMask = OVR : : LogMask_All ) : OVR : : Log ( logMask )
{
}
virtual void LogMessageVarg ( OVR : : LogMessageType messageType , const char * fmt , va_list argList )
{
if ( NLMISC : : INelContext : : isContextInitialised ( ) )
{
char buffer [ MaxLogBufferMessageSize ] ;
FormatLog ( buffer , MaxLogBufferMessageSize , messageType , fmt , argList ) ;
if ( IsDebugMessage ( messageType ) )
NLMISC : : INelContext : : getInstance ( ) . getDebugLog ( ) - > displayNL ( " OVR: %s " , buffer ) ;
else
NLMISC : : INelContext : : getInstance ( ) . getInfoLog ( ) - > displayNL ( " OVR: %s " , buffer ) ;
}
}
} ;
CStereoOVRLog * s_StereoOVRLog = NULL ;
OVR : : Ptr < OVR : : DeviceManager > s_DeviceManager ;
class CStereoOVRSystem
{
public :
~ CStereoOVRSystem ( )
{
Release ( ) ;
}
void Init ( )
{
if ( ! s_StereoOVRLog )
{
nldebug ( " Initialize OVR " ) ;
s_StereoOVRLog = new CStereoOVRLog ( ) ;
}
if ( ! OVR : : System : : IsInitialized ( ) )
OVR : : System : : Init ( s_StereoOVRLog ) ;
if ( ! s_DeviceManager )
s_DeviceManager = OVR : : DeviceManager : : Create ( ) ;
}
void Release ( )
{
if ( s_DeviceManager )
{
nldebug ( " Release OVR " ) ;
s_DeviceManager - > Release ( ) ;
}
s_DeviceManager . Clear ( ) ;
if ( OVR : : System : : IsInitialized ( ) )
OVR : : System : : Destroy ( ) ;
if ( s_StereoOVRLog )
nldebug ( " Release OVR Ok " ) ;
delete s_StereoOVRLog ;
s_StereoOVRLog = NULL ;
}
} ;
CStereoOVRSystem s_StereoOVRSystem ;
2013-06-28 21:19:32 +00:00
sint s_DeviceCounter = 0 ;
}
class CStereoOVRDeviceHandle : public IStereoDeviceFactory
2013-06-26 00:45:49 +00:00
{
public :
2013-07-03 22:09:10 +00:00
// fixme: virtual destructor???
2013-06-26 02:57:58 +00:00
OVR : : DeviceEnumerator < OVR : : HMDDevice > DeviceHandle ;
2013-06-28 21:19:32 +00:00
IStereoDisplay * createDevice ( ) const
{
CStereoOVR * stereo = new CStereoOVR ( this ) ;
if ( stereo - > isDeviceCreated ( ) )
return stereo ;
delete stereo ;
return NULL ;
}
2013-06-26 00:45:49 +00:00
} ;
class CStereoOVRDevicePtr
{
public :
OVR : : Ptr < OVR : : HMDDevice > HMDDevice ;
2013-06-26 02:57:58 +00:00
OVR : : Ptr < OVR : : SensorDevice > SensorDevice ;
OVR : : SensorFusion SensorFusion ;
2013-06-26 06:00:19 +00:00
OVR : : HMDInfo HMDInfo ;
2013-06-26 00:45:49 +00:00
} ;
2013-07-03 03:21:32 +00:00
CStereoOVR : : CStereoOVR ( const CStereoOVRDeviceHandle * handle ) : m_Stage ( 0 ) , m_SubStage ( 0 ) , m_OrientationCached ( false ) , m_Driver ( NULL ) , m_BarrelTexU ( NULL ) , m_PixelProgram ( NULL ) , m_EyePosition ( 0.0f , 0.09f , 0.15f ) , m_Scale ( 1.0f )
2013-06-26 00:45:49 +00:00
{
+ + s_DeviceCounter ;
m_DevicePtr = new CStereoOVRDevicePtr ( ) ;
2013-06-26 02:57:58 +00:00
OVR : : DeviceEnumerator < OVR : : HMDDevice > dh = handle - > DeviceHandle ;
m_DevicePtr - > HMDDevice = dh . CreateDevice ( ) ;
if ( m_DevicePtr - > HMDDevice )
{
2013-06-26 06:00:19 +00:00
m_DevicePtr - > HMDDevice - > GetDeviceInfo ( & m_DevicePtr - > HMDInfo ) ;
nldebug ( " OVR: HScreenSize: %f, VScreenSize: %f " , m_DevicePtr - > HMDInfo . HScreenSize , m_DevicePtr - > HMDInfo . VScreenSize ) ;
nldebug ( " OVR: VScreenCenter: %f " , m_DevicePtr - > HMDInfo . VScreenCenter ) ;
nldebug ( " OVR: EyeToScreenDistance: %f " , m_DevicePtr - > HMDInfo . EyeToScreenDistance ) ;
nldebug ( " OVR: LensSeparationDistance: %f " , m_DevicePtr - > HMDInfo . LensSeparationDistance ) ;
nldebug ( " OVR: InterpupillaryDistance: %f " , m_DevicePtr - > HMDInfo . InterpupillaryDistance ) ;
nldebug ( " OVR: HResolution: %i, VResolution: %i " , m_DevicePtr - > HMDInfo . HResolution , m_DevicePtr - > HMDInfo . VResolution ) ;
nldebug ( " OVR: DistortionK[0]: %f, DistortionK[1]: %f " , m_DevicePtr - > HMDInfo . DistortionK [ 0 ] , m_DevicePtr - > HMDInfo . DistortionK [ 1 ] ) ;
nldebug ( " OVR: DistortionK[2]: %f, DistortionK[3]: %f " , m_DevicePtr - > HMDInfo . DistortionK [ 2 ] , m_DevicePtr - > HMDInfo . DistortionK [ 3 ] ) ;
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 160 NL3D::CStereoOVR::CStereoOVR : OVR: HScreenSize: 0.149760, VScreenSize: 0.093600
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 161 NL3D::CStereoOVR::CStereoOVR : OVR: VScreenCenter: 0.046800
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 162 NL3D::CStereoOVR::CStereoOVR : OVR: EyeToScreenDistance: 0.041000
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 163 NL3D::CStereoOVR::CStereoOVR : OVR: LensSeparationDistance: 0.063500
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 164 NL3D::CStereoOVR::CStereoOVR : OVR: InterpupillaryDistance: 0.064000
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 165 NL3D::CStereoOVR::CStereoOVR : OVR: HResolution: 1280, VResolution: 800
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 166 NL3D::CStereoOVR::CStereoOVR : OVR: DistortionK[0]: 1.000000, DistortionK[1]: 0.220000
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 167 NL3D::CStereoOVR::CStereoOVR : OVR: DistortionK[2]: 0.240000, DistortionK[3]: 0.000000
2013-06-26 02:57:58 +00:00
m_DevicePtr - > SensorDevice = m_DevicePtr - > HMDDevice - > GetSensor ( ) ;
m_DevicePtr - > SensorFusion . AttachToSensor ( m_DevicePtr - > SensorDevice ) ;
m_DevicePtr - > SensorFusion . SetGravityEnabled ( true ) ;
m_DevicePtr - > SensorFusion . SetPredictionEnabled ( true ) ;
m_DevicePtr - > SensorFusion . SetYawCorrectionEnabled ( true ) ;
2013-06-26 06:00:19 +00:00
m_LeftViewport . init ( 0.f , 0.f , 0.5f , 1.0f ) ;
m_RightViewport . init ( 0.5f , 0.f , 0.5f , 1.0f ) ;
2013-06-26 02:57:58 +00:00
}
2013-06-26 00:45:49 +00:00
}
CStereoOVR : : ~ CStereoOVR ( )
{
2013-07-01 21:23:54 +00:00
if ( ! m_BarrelMat . empty ( ) )
{
m_BarrelMat . getObjectPtr ( ) - > setTexture ( 0 , NULL ) ;
m_Driver - > deleteMaterial ( m_BarrelMat ) ;
}
delete m_BarrelTexU ;
m_BarrelTexU = NULL ;
m_BarrelTex = NULL ; // CSmartPtr
2013-07-02 00:40:27 +00:00
delete m_PixelProgram ;
m_PixelProgram = NULL ;
2013-07-01 21:23:54 +00:00
m_Driver = NULL ;
2013-06-26 02:57:58 +00:00
if ( m_DevicePtr - > SensorDevice )
m_DevicePtr - > SensorDevice - > Release ( ) ;
m_DevicePtr - > SensorDevice . Clear ( ) ;
if ( m_DevicePtr - > HMDDevice )
m_DevicePtr - > HMDDevice - > Release ( ) ;
m_DevicePtr - > HMDDevice . Clear ( ) ;
2013-06-26 00:45:49 +00:00
delete m_DevicePtr ;
m_DevicePtr = NULL ;
- - s_DeviceCounter ;
}
2013-09-09 18:49:59 +00:00
class CPixelProgramOVR : public CPixelProgram
2013-07-01 19:23:47 +00:00
{
2013-09-09 18:49:59 +00:00
public :
struct COVRIndices
{
uint LensCenter ;
uint ScreenCenter ;
uint Scale ;
uint ScaleIn ;
uint HmdWarpParam ;
} ;
2013-09-07 18:41:07 +00:00
2013-09-09 18:49:59 +00:00
CPixelProgramOVR ( )
2013-07-02 17:39:05 +00:00
{
2013-09-09 18:49:59 +00:00
{
CSource * source = new CSource ( ) ;
source - > Profile = glsl330f ;
2013-09-13 22:46:10 +00:00
source - > Features . MaterialFlags = CProgramFeatures : : TextureStages ;
2013-09-09 18:49:59 +00:00
source - > setSourcePtr ( g_StereoOVR_glsl330f ) ;
addSource ( source ) ;
}
{
CSource * source = new CSource ( ) ;
source - > Profile = fp40 ;
2013-09-13 22:46:10 +00:00
source - > Features . MaterialFlags = CProgramFeatures : : TextureStages ;
2013-09-09 18:49:59 +00:00
source - > setSourcePtr ( g_StereoOVR_fp40 ) ;
source - > ParamIndices [ " cLensCenter " ] = 0 ;
source - > ParamIndices [ " cScreenCenter " ] = 1 ;
source - > ParamIndices [ " cScale " ] = 2 ;
source - > ParamIndices [ " cScaleIn " ] = 3 ;
source - > ParamIndices [ " cHmdWarpParam " ] = 4 ;
addSource ( source ) ;
}
{
CSource * source = new CSource ( ) ;
source - > Profile = arbfp1 ;
2013-09-13 22:46:10 +00:00
source - > Features . MaterialFlags = CProgramFeatures : : TextureStages ;
2013-09-09 18:49:59 +00:00
source - > setSourcePtr ( g_StereoOVR_arbfp1 ) ;
source - > ParamIndices [ " cLensCenter " ] = 0 ;
source - > ParamIndices [ " cScreenCenter " ] = 1 ;
source - > ParamIndices [ " cScale " ] = 2 ;
source - > ParamIndices [ " cScaleIn " ] = 3 ;
source - > ParamIndices [ " cHmdWarpParam " ] = 4 ;
addSource ( source ) ;
}
{
CSource * source = new CSource ( ) ;
source - > Profile = ps_2_0 ;
2013-09-13 22:46:10 +00:00
source - > Features . MaterialFlags = CProgramFeatures : : TextureStages ;
2013-09-09 18:49:59 +00:00
source - > setSourcePtr ( g_StereoOVR_ps_2_0 ) ;
source - > ParamIndices [ " cLensCenter " ] = 0 ;
source - > ParamIndices [ " cScreenCenter " ] = 1 ;
source - > ParamIndices [ " cScale " ] = 2 ;
source - > ParamIndices [ " cScaleIn " ] = 3 ;
source - > ParamIndices [ " cHmdWarpParam " ] = 4 ;
addSource ( source ) ;
}
2013-07-02 17:39:05 +00:00
}
2013-09-09 18:49:59 +00:00
virtual ~ CPixelProgramOVR ( )
2013-07-02 00:40:27 +00:00
{
2013-09-09 18:49:59 +00:00
2013-07-02 00:40:27 +00:00
}
2013-09-09 18:49:59 +00:00
virtual void buildInfo ( )
2013-07-02 00:40:27 +00:00
{
2013-09-09 18:49:59 +00:00
CPixelProgram : : buildInfo ( ) ;
m_OVRIndices . LensCenter = getUniformIndex ( " cLensCenter " ) ;
nlassert ( m_OVRIndices . LensCenter ! = ~ 0 ) ;
m_OVRIndices . ScreenCenter = getUniformIndex ( " cScreenCenter " ) ;
nlassert ( m_OVRIndices . ScreenCenter ! = ~ 0 ) ;
m_OVRIndices . Scale = getUniformIndex ( " cScale " ) ;
nlassert ( m_OVRIndices . Scale ! = ~ 0 ) ;
m_OVRIndices . ScaleIn = getUniformIndex ( " cScaleIn " ) ;
nlassert ( m_OVRIndices . ScaleIn ! = ~ 0 ) ;
m_OVRIndices . HmdWarpParam = getUniformIndex ( " cHmdWarpParam " ) ;
nlassert ( m_OVRIndices . HmdWarpParam ! = ~ 0 ) ;
2013-09-09 16:33:38 +00:00
}
2013-09-09 18:49:59 +00:00
inline const COVRIndices & ovrIndices ( ) { return m_OVRIndices ; }
private :
COVRIndices m_OVRIndices ;
} ;
void CStereoOVR : : setDriver ( NL3D : : UDriver * driver )
{
nlassert ( ! m_PixelProgram ) ;
NL3D : : IDriver * drvInternal = ( static_cast < CDriverUser * > ( driver ) ) - > getDriver ( ) ;
if ( drvInternal - > supportBloomEffect ( ) & & drvInternal - > supportNonPowerOfTwoTextures ( ) )
2013-09-09 16:33:38 +00:00
{
2013-09-09 18:49:59 +00:00
m_PixelProgram = new CPixelProgramOVR ( ) ;
if ( ! drvInternal - > compilePixelProgram ( m_PixelProgram ) )
{
m_PixelProgram . kill ( ) ;
}
2013-07-02 00:40:27 +00:00
}
2013-07-01 21:23:54 +00:00
2013-07-02 00:40:27 +00:00
if ( m_PixelProgram )
{
m_Driver = driver ;
m_BarrelTex = new CTextureBloom ( ) ; // lol bloom
2013-07-02 16:48:29 +00:00
m_BarrelTex - > setRenderTarget ( true ) ;
2013-07-02 00:40:27 +00:00
m_BarrelTex - > setReleasable ( false ) ;
2013-07-05 00:04:34 +00:00
m_BarrelTex - > resize ( m_DevicePtr - > HMDInfo . HResolution , m_DevicePtr - > HMDInfo . VResolution ) ;
2013-07-02 00:40:27 +00:00
m_BarrelTex - > setFilterMode ( ITexture : : Linear , ITexture : : LinearMipMapOff ) ;
m_BarrelTex - > setWrapS ( ITexture : : Clamp ) ;
m_BarrelTex - > setWrapT ( ITexture : : Clamp ) ;
drvInternal - > setupTexture ( * m_BarrelTex ) ;
m_BarrelTexU = new CTextureUser ( m_BarrelTex ) ;
m_BarrelMat = m_Driver - > createMaterial ( ) ;
m_BarrelMat . initUnlit ( ) ;
m_BarrelMat . setColor ( CRGBA : : White ) ;
m_BarrelMat . setBlend ( false ) ;
m_BarrelMat . setAlphaTest ( false ) ;
NL3D : : CMaterial * barrelMat = m_BarrelMat . getObjectPtr ( ) ;
2013-09-09 19:44:14 +00:00
barrelMat - > setShader ( NL3D : : CMaterial : : Normal ) ;
2013-07-02 00:40:27 +00:00
barrelMat - > setBlendFunc ( CMaterial : : one , CMaterial : : zero ) ;
barrelMat - > setZWrite ( false ) ;
barrelMat - > setZFunc ( CMaterial : : always ) ;
barrelMat - > setDoubleSided ( true ) ;
barrelMat - > setTexture ( 0 , m_BarrelTex ) ;
2013-07-02 01:34:49 +00:00
m_BarrelQuadLeft . V0 = CVector ( 0.f , 0.f , 0.5f ) ;
m_BarrelQuadLeft . V1 = CVector ( 0.5f , 0.f , 0.5f ) ;
m_BarrelQuadLeft . V2 = CVector ( 0.5f , 1.f , 0.5f ) ;
m_BarrelQuadLeft . V3 = CVector ( 0.f , 1.f , 0.5f ) ;
m_BarrelQuadRight . V0 = CVector ( 0.5f , 0.f , 0.5f ) ;
m_BarrelQuadRight . V1 = CVector ( 1.f , 0.f , 0.5f ) ;
m_BarrelQuadRight . V2 = CVector ( 1.f , 1.f , 0.5f ) ;
m_BarrelQuadRight . V3 = CVector ( 0.5f , 1.f , 0.5f ) ;
2013-07-02 00:40:27 +00:00
2013-07-02 16:48:29 +00:00
nlassert ( ! drvInternal - > isTextureRectangle ( m_BarrelTex ) ) ; // not allowed
2013-07-02 00:40:27 +00:00
2013-07-02 01:34:49 +00:00
m_BarrelQuadLeft . Uv0 = CUV ( 0.f , 0.f ) ;
2013-07-02 16:48:29 +00:00
m_BarrelQuadLeft . Uv1 = CUV ( 0.5f , 0.f ) ;
m_BarrelQuadLeft . Uv2 = CUV ( 0.5f , 1.f ) ;
m_BarrelQuadLeft . Uv3 = CUV ( 0.f , 1.f ) ;
m_BarrelQuadRight . Uv0 = CUV ( 0.5f , 0.f ) ;
m_BarrelQuadRight . Uv1 = CUV ( 1.f , 0.f ) ;
m_BarrelQuadRight . Uv2 = CUV ( 1.f , 1.f ) ;
m_BarrelQuadRight . Uv3 = CUV ( 0.5f , 1.f ) ;
2013-07-02 00:40:27 +00:00
}
else
{
nlwarning ( " VR: No pixel program support " ) ;
}
2013-07-01 19:23:47 +00:00
}
2013-07-03 22:09:10 +00:00
bool CStereoOVR : : getScreenResolution ( uint & width , uint & height )
2013-06-26 06:00:19 +00:00
{
width = m_DevicePtr - > HMDInfo . HResolution ;
height = m_DevicePtr - > HMDInfo . VResolution ;
2013-07-03 22:09:10 +00:00
return true ;
2013-06-26 06:00:19 +00:00
}
2013-06-26 18:57:37 +00:00
void CStereoOVR : : initCamera ( uint cid , const NL3D : : UCamera * camera )
2013-06-26 06:00:19 +00:00
{
float ar = ( float ) m_DevicePtr - > HMDInfo . HResolution / ( ( float ) m_DevicePtr - > HMDInfo . VResolution * 2.0f ) ;
2013-07-03 04:04:37 +00:00
float fov = 2.0f * atanf ( ( m_DevicePtr - > HMDInfo . HScreenSize * 0.5f * 0.5f ) / ( m_DevicePtr - > HMDInfo . EyeToScreenDistance ) ) ; //(float)NLMISC::Pi/2.f; // 2.0f * atanf(m_DevicePtr->HMDInfo.VScreenSize / 2.0f * m_DevicePtr->HMDInfo.EyeToScreenDistance);
2013-06-26 18:57:37 +00:00
m_LeftFrustum [ cid ] . initPerspective ( fov , ar , camera - > getFrustum ( ) . Near , camera - > getFrustum ( ) . Far ) ;
m_RightFrustum [ cid ] = m_LeftFrustum [ cid ] ;
2013-07-01 18:15:55 +00:00
2013-06-26 06:00:19 +00:00
float viewCenter = m_DevicePtr - > HMDInfo . HScreenSize * 0.25f ;
2013-07-01 19:23:47 +00:00
float eyeProjectionShift = viewCenter - m_DevicePtr - > HMDInfo . LensSeparationDistance * 0.5f ; // docs say LensSeparationDistance, why not InterpupillaryDistance? related to how the lenses work?
2013-07-01 18:15:55 +00:00
float projectionCenterOffset = ( eyeProjectionShift / ( m_DevicePtr - > HMDInfo . HScreenSize * 0.5f ) ) * ( m_LeftFrustum [ cid ] . Right - m_LeftFrustum [ cid ] . Left ) ; // used logic for this one, but it ends up being the same as the one i made up
2013-06-26 06:00:19 +00:00
nldebug ( " OVR: projectionCenterOffset = %f " , projectionCenterOffset ) ;
2013-07-01 18:15:55 +00:00
m_LeftFrustum [ cid ] . Left - = projectionCenterOffset ;
m_LeftFrustum [ cid ] . Right - = projectionCenterOffset ;
m_RightFrustum [ cid ] . Left + = projectionCenterOffset ;
m_RightFrustum [ cid ] . Right + = projectionCenterOffset ;
2013-06-26 19:35:36 +00:00
// TODO: Clipping frustum should also take into account the IPD
m_ClippingFrustum [ cid ] = m_LeftFrustum [ cid ] ;
m_ClippingFrustum [ cid ] . Left = min ( m_LeftFrustum [ cid ] . Left , m_RightFrustum [ cid ] . Left ) ;
m_ClippingFrustum [ cid ] . Right = max ( m_LeftFrustum [ cid ] . Right , m_RightFrustum [ cid ] . Right ) ;
}
/// Get the frustum to use for clipping
void CStereoOVR : : getClippingFrustum ( uint cid , NL3D : : UCamera * camera ) const
{
camera - > setFrustum ( m_ClippingFrustum [ cid ] ) ;
2013-06-26 06:00:19 +00:00
}
2013-06-26 18:57:37 +00:00
void CStereoOVR : : updateCamera ( uint cid , const NL3D : : UCamera * camera )
2013-06-26 06:00:19 +00:00
{
2013-06-26 18:57:37 +00:00
if ( camera - > getFrustum ( ) . Near ! = m_LeftFrustum [ cid ] . Near
| | camera - > getFrustum ( ) . Far ! = m_LeftFrustum [ cid ] . Far )
CStereoOVR : : initCamera ( cid , camera ) ;
m_CameraMatrix [ cid ] = camera - > getMatrix ( ) ;
2013-06-26 06:00:19 +00:00
}
bool CStereoOVR : : nextPass ( )
{
2013-07-05 00:04:34 +00:00
// Do not allow weird stuff.
uint32 width , height ;
m_Driver - > getWindowSize ( width , height ) ;
nlassert ( width = = m_DevicePtr - > HMDInfo . HResolution ) ;
nlassert ( height = = m_DevicePtr - > HMDInfo . VResolution ) ;
2013-07-05 01:42:38 +00:00
if ( m_Driver - > getPolygonMode ( ) = = UDriver : : Filled )
2013-06-26 06:00:19 +00:00
{
2013-07-05 01:42:38 +00:00
switch ( m_Stage )
{
case 0 :
+ + m_Stage ;
m_SubStage = 0 ;
// stage 1:
// (initBloom)
// clear buffer
// draw scene left
return true ;
case 1 :
+ + m_Stage ;
m_SubStage = 0 ;
// stage 2:
// draw scene right
return true ;
case 2 :
+ + m_Stage ;
m_SubStage = 0 ;
// stage 3:
// (endBloom)
// draw interface 3d left
return true ;
case 3 :
+ + m_Stage ;
m_SubStage = 0 ;
// stage 4:
// draw interface 3d right
return true ;
case 4 :
+ + m_Stage ;
m_SubStage = 0 ;
// stage 5:
// (endInterfacesDisplayBloom)
// draw interface 2d left
return true ;
case 5 :
+ + m_Stage ;
m_SubStage = 0 ;
// stage 6:
// draw interface 2d right
return true ;
case 6 :
m_Stage = 0 ;
m_SubStage = 0 ;
// present
m_OrientationCached = false ;
return false ;
}
}
else
{
switch ( m_Stage )
{
case 0 :
+ + m_Stage ;
m_SubStage = 0 ;
return true ;
case 1 :
m_Stage = 0 ;
m_SubStage = 0 ;
return false ;
}
2013-06-26 06:00:19 +00:00
}
2013-07-01 19:23:47 +00:00
nlerror ( " Invalid stage " ) ;
2013-06-26 18:10:30 +00:00
m_Stage = 0 ;
2013-07-01 19:23:47 +00:00
m_SubStage = 0 ;
2013-06-26 18:10:30 +00:00
m_OrientationCached = false ;
return false ;
2013-06-26 06:00:19 +00:00
}
2013-06-26 13:49:31 +00:00
const NL3D : : CViewport & CStereoOVR : : getCurrentViewport ( ) const
2013-06-26 06:00:19 +00:00
{
2013-06-26 13:49:31 +00:00
if ( m_Stage % 2 ) return m_LeftViewport ;
else return m_RightViewport ;
2013-06-26 06:00:19 +00:00
}
2013-06-26 18:57:37 +00:00
const NL3D : : CFrustum & CStereoOVR : : getCurrentFrustum ( uint cid ) const
2013-06-26 14:59:08 +00:00
{
2013-06-26 18:57:37 +00:00
if ( m_Stage % 2 ) return m_LeftFrustum [ cid ] ;
else return m_RightFrustum [ cid ] ;
2013-06-26 14:59:08 +00:00
}
2013-06-26 18:57:37 +00:00
void CStereoOVR : : getCurrentFrustum ( uint cid , NL3D : : UCamera * camera ) const
2013-06-26 06:00:19 +00:00
{
2013-06-26 18:57:37 +00:00
if ( m_Stage % 2 ) camera - > setFrustum ( m_LeftFrustum [ cid ] ) ;
else camera - > setFrustum ( m_RightFrustum [ cid ] ) ;
2013-06-26 06:00:19 +00:00
}
2013-06-26 18:57:37 +00:00
void CStereoOVR : : getCurrentMatrix ( uint cid , NL3D : : UCamera * camera ) const
2013-06-26 06:00:19 +00:00
{
CMatrix translate ;
2013-07-03 03:21:32 +00:00
if ( m_Stage % 2 ) translate . translate ( CVector ( ( m_DevicePtr - > HMDInfo . InterpupillaryDistance * m_Scale ) * - 0.5f , 0.f , 0.f ) ) ;
else translate . translate ( CVector ( ( m_DevicePtr - > HMDInfo . InterpupillaryDistance * m_Scale ) * 0.5f , 0.f , 0.f ) ) ;
2013-07-05 00:38:56 +00:00
CMatrix mat = m_CameraMatrix [ cid ] * translate ;
if ( camera - > getTransformMode ( ) = = NL3D : : UTransformable : : RotQuat )
{
camera - > setPos ( mat . getPos ( ) ) ;
camera - > setRotQuat ( mat . getRot ( ) ) ;
}
else
{
// camera->setTransformMode(NL3D::UTransformable::DirectMatrix);
camera - > setMatrix ( mat ) ;
}
2013-06-26 13:49:31 +00:00
}
2013-07-01 19:23:47 +00:00
bool CStereoOVR : : wantClear ( )
2013-06-26 13:49:31 +00:00
{
switch ( m_Stage )
{
case 1 :
2013-07-01 19:23:47 +00:00
m_SubStage = 1 ;
2013-06-26 13:49:31 +00:00
return true ;
}
2013-07-05 01:42:38 +00:00
return m_Driver - > getPolygonMode ( ) ! = UDriver : : Filled ;
2013-06-26 13:49:31 +00:00
}
2013-07-01 19:23:47 +00:00
bool CStereoOVR : : wantScene ( )
2013-06-26 13:49:31 +00:00
{
switch ( m_Stage )
{
case 1 :
case 2 :
2013-07-01 19:23:47 +00:00
m_SubStage = 2 ;
2013-06-26 13:49:31 +00:00
return true ;
}
2013-07-05 01:42:38 +00:00
return m_Driver - > getPolygonMode ( ) ! = UDriver : : Filled ;
2013-06-26 13:49:31 +00:00
}
2013-07-01 19:23:47 +00:00
bool CStereoOVR : : wantInterface3D ( )
2013-06-26 13:49:31 +00:00
{
switch ( m_Stage )
{
case 3 :
case 4 :
2013-07-01 19:23:47 +00:00
m_SubStage = 3 ;
2013-06-26 13:49:31 +00:00
return true ;
}
2013-07-05 01:42:38 +00:00
return m_Driver - > getPolygonMode ( ) ! = UDriver : : Filled ;
2013-06-26 13:49:31 +00:00
}
2013-07-01 19:23:47 +00:00
bool CStereoOVR : : wantInterface2D ( )
2013-06-26 13:49:31 +00:00
{
switch ( m_Stage )
{
case 5 :
case 6 :
2013-07-01 19:23:47 +00:00
m_SubStage = 4 ;
2013-06-26 13:49:31 +00:00
return true ;
}
2013-07-05 01:42:38 +00:00
return m_Driver - > getPolygonMode ( ) ! = UDriver : : Filled ;
2013-06-26 13:49:31 +00:00
}
2013-07-01 19:23:47 +00:00
/// Returns non-NULL if a new render target was set
2013-07-03 01:53:32 +00:00
bool CStereoOVR : : beginRenderTarget ( )
2013-06-26 13:49:31 +00:00
{
2013-07-01 19:23:47 +00:00
// render target always set before driver clear
2013-07-01 21:23:54 +00:00
// nlassert(m_SubStage <= 1);
2013-07-05 01:42:38 +00:00
if ( m_Driver & & m_Stage = = 1 & & ( m_Driver - > getPolygonMode ( ) = = UDriver : : Filled ) )
2013-07-01 21:23:54 +00:00
{
2013-07-03 01:53:32 +00:00
static_cast < CDriverUser * > ( m_Driver ) - > setRenderTarget ( * m_BarrelTexU , 0 , 0 , 0 , 0 ) ;
return true ;
2013-07-01 21:23:54 +00:00
}
2013-07-03 01:53:32 +00:00
return false ;
2013-07-01 19:23:47 +00:00
}
2013-06-26 13:49:31 +00:00
2013-07-01 19:23:47 +00:00
/// Returns true if a render target was fully drawn
2013-07-01 22:55:13 +00:00
bool CStereoOVR : : endRenderTarget ( )
2013-07-01 19:23:47 +00:00
{
// after rendering of course
2013-07-01 21:23:54 +00:00
// nlassert(m_SubStage > 1);
2013-07-05 01:42:38 +00:00
if ( m_Driver & & m_Stage = = 6 & & ( m_Driver - > getPolygonMode ( ) = = UDriver : : Filled ) ) // set to 4 to turn off distortion of 2d gui
2013-07-01 21:23:54 +00:00
{
2013-07-01 22:55:13 +00:00
CTextureUser cu ;
( static_cast < CDriverUser * > ( m_Driver ) ) - > setRenderTarget ( cu ) ;
2013-07-02 00:40:27 +00:00
bool fogEnabled = m_Driver - > fogEnabled ( ) ;
m_Driver - > enableFog ( false ) ;
2013-07-01 22:55:13 +00:00
m_Driver - > setMatrixMode2D11 ( ) ;
2013-07-02 00:40:27 +00:00
CViewport vp = CViewport ( ) ;
m_Driver - > setViewport ( vp ) ;
uint32 width , height ;
m_Driver - > getWindowSize ( width , height ) ;
NL3D : : IDriver * drvInternal = ( static_cast < CDriverUser * > ( m_Driver ) ) - > getDriver ( ) ;
NL3D : : CMaterial * barrelMat = m_BarrelMat . getObjectPtr ( ) ;
barrelMat - > setTexture ( 0 , m_BarrelTex ) ;
2013-09-08 19:57:27 +00:00
2013-07-02 00:40:27 +00:00
drvInternal - > activePixelProgram ( m_PixelProgram ) ;
2013-07-02 01:34:49 +00:00
float w = float ( m_BarrelQuadLeft . V1 . x ) , // / float(width),
h = float ( m_BarrelQuadLeft . V2 . y ) , // / float(height),
x = float ( m_BarrelQuadLeft . V0 . x ) , /// / float(width),
y = float ( m_BarrelQuadLeft . V0 . y ) ; // / float(height);
2013-07-02 00:40:27 +00:00
float lensOffset = m_DevicePtr - > HMDInfo . LensSeparationDistance * 0.5f ;
float lensShift = m_DevicePtr - > HMDInfo . HScreenSize * 0.25f - lensOffset ;
float lensViewportShift = 4.0f * lensShift / m_DevicePtr - > HMDInfo . HScreenSize ;
float lensCenterX = x + ( w + lensViewportShift * 0.5f ) * 0.5f ;
float lensCenterY = y + h * 0.5f ;
float screenCenterX = x + w * 0.5f ;
float screenCenterY = y + h * 0.5f ;
float scaleX = ( w / 2 ) ;
float scaleY = ( h / 2 ) ;
float scaleInX = ( 2 / w ) ;
float scaleInY = ( 2 / h ) ;
2013-09-08 19:57:27 +00:00
2013-09-09 18:49:59 +00:00
drvInternal - > setUniform2f ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . LensCenter ,
lensCenterX , lensCenterY ) ;
drvInternal - > setUniform2f ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . ScreenCenter ,
screenCenterX , screenCenterY ) ;
drvInternal - > setUniform2f ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . Scale ,
scaleX , scaleY ) ;
drvInternal - > setUniform2f ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . ScaleIn ,
scaleInX , scaleInY ) ;
drvInternal - > setUniform4fv ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . HmdWarpParam ,
1 , m_DevicePtr - > HMDInfo . DistortionK ) ;
2013-07-02 00:40:27 +00:00
2013-07-02 01:34:49 +00:00
m_Driver - > drawQuad ( m_BarrelQuadLeft , m_BarrelMat ) ;
x = w ;
lensCenterX = x + ( w - lensViewportShift * 0.5f ) * 0.5f ;
screenCenterX = x + w * 0.5f ;
2013-09-08 19:57:27 +00:00
2013-09-09 18:49:59 +00:00
drvInternal - > setUniform2f ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . LensCenter ,
lensCenterX , lensCenterY ) ;
drvInternal - > setUniform2f ( IDriver : : PixelProgram ,
m_PixelProgram - > ovrIndices ( ) . ScreenCenter ,
screenCenterX , screenCenterY ) ;
2013-07-02 01:34:49 +00:00
m_Driver - > drawQuad ( m_BarrelQuadRight , m_BarrelMat ) ;
2013-07-02 00:40:27 +00:00
drvInternal - > activePixelProgram ( NULL ) ;
m_Driver - > enableFog ( fogEnabled ) ;
2013-07-01 22:55:13 +00:00
2013-07-01 21:23:54 +00:00
return true ;
}
2013-07-01 19:23:47 +00:00
return false ;
2013-06-26 06:00:19 +00:00
}
2013-06-26 13:49:31 +00:00
NLMISC : : CQuat CStereoOVR : : getOrientation ( ) const
2013-06-26 02:57:58 +00:00
{
2013-06-26 14:59:08 +00:00
if ( m_OrientationCached )
return m_OrientationCache ;
2013-06-26 02:57:58 +00:00
OVR : : Quatf quatovr = m_DevicePtr - > SensorFusion . GetPredictedOrientation ( ) ;
NLMISC : : CMatrix coordsys ;
float csys [ ] = {
1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 0.0f , - 1.0f , 0.0f ,
0.0f , 1.0f , 0.0f , 0.0f ,
0.0f , 0.0f , 0.0f , 1.0f ,
} ;
coordsys . set ( csys ) ;
NLMISC : : CMatrix matovr ;
matovr . setRot ( NLMISC : : CQuat ( quatovr . x , quatovr . y , quatovr . z , quatovr . w ) ) ;
NLMISC : : CMatrix matr ;
matr . rotateX ( NLMISC : : Pi * 0.5f ) ; // fix this properly... :) (note: removing this allows you to use rift while lying down)
NLMISC : : CMatrix matnel = matr * matovr * coordsys ;
2013-06-26 14:59:08 +00:00
NLMISC : : CQuat finalquat = matnel . getRot ( ) ;
m_OrientationCache = finalquat ;
m_OrientationCached = true ;
return finalquat ;
}
2013-06-26 15:24:23 +00:00
/// Get GUI shift
2013-06-28 21:19:32 +00:00
void CStereoOVR : : getInterface2DShift ( uint cid , float & x , float & y , float distance ) const
2013-06-26 14:59:08 +00:00
{
2013-06-26 17:58:27 +00:00
#if 0
2013-07-03 03:21:32 +00:00
// todo: take into account m_EyePosition
2013-06-26 14:59:08 +00:00
NLMISC : : CVector vector = CVector ( 0.f , - distance , 0.f ) ;
NLMISC : : CQuat rot = getOrientation ( ) ;
rot . invert ( ) ;
NLMISC : : CMatrix mat ;
mat . rotate ( rot ) ;
2013-06-26 17:58:27 +00:00
//if (m_Stage % 2) mat.translate(CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * -0.5f, 0.f, 0.f));
//else mat.translate(CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * 0.5f, 0.f, 0.f));
2013-06-26 14:59:08 +00:00
mat . translate ( vector ) ;
2013-07-04 19:12:11 +00:00
CVector proj = CStereoOVR : : getCurrentFrustum ( cid ) . project ( mat . getPos ( ) ) ;
2013-06-26 17:58:27 +00:00
NLMISC : : CVector ipd ;
if ( m_Stage % 2 ) ipd = CVector ( m_DevicePtr - > HMDInfo . InterpupillaryDistance * - 0.5f , 0.f , 0.f ) ;
else ipd = CVector ( m_DevicePtr - > HMDInfo . InterpupillaryDistance * 0.5f , 0.f , 0.f ) ;
2013-07-04 19:12:11 +00:00
CVector projipd = CStereoOVR : : getCurrentFrustum ( cid ) . project ( vector + ipd ) ;
CVector projvec = CStereoOVR : : getCurrentFrustum ( cid ) . project ( vector ) ;
2013-06-26 17:58:27 +00:00
x = ( proj . x + projipd . x - projvec . x - 0.5f ) ;
y = ( proj . y + projipd . y - projvec . y - 0.5f ) ;
# elif 1
// Alternative method
2013-07-03 03:21:32 +00:00
// todo: take into account m_EyePosition
2013-06-26 17:58:27 +00:00
NLMISC : : CVector vec = CVector ( 0.f , - distance , 0.f ) ;
NLMISC : : CVector ipd ;
2013-07-03 03:21:32 +00:00
if ( m_Stage % 2 ) ipd = CVector ( ( m_DevicePtr - > HMDInfo . InterpupillaryDistance * m_Scale ) * - 0.5f , 0.f , 0.f ) ;
else ipd = CVector ( ( m_DevicePtr - > HMDInfo . InterpupillaryDistance * m_Scale ) * 0.5f , 0.f , 0.f ) ;
2013-06-26 17:58:27 +00:00
NLMISC : : CQuat rot = getOrientation ( ) ;
NLMISC : : CQuat modrot = NLMISC : : CQuat ( CVector ( 0.f , 1.f , 0.f ) , NLMISC : : Pi ) ;
rot = rot * modrot ;
float p = NLMISC : : Pi + atan2f ( 2.0f * ( ( rot . x * rot . y ) + ( rot . z * rot . w ) ) , 1.0f - 2.0f * ( ( rot . y * rot . y ) + ( rot . w * rot . w ) ) ) ;
if ( p > NLMISC : : Pi ) p - = NLMISC : : Pi * 2.0f ;
float t = - atan2f ( 2.0f * ( ( rot . x * rot . w ) + ( rot . y * rot . z ) ) , 1.0f - 2.0f * ( ( rot . z * rot . z ) + ( rot . w * rot . w ) ) ) ; // // asinf(2.0f * ((rot.x * rot.z) - (rot.w * rot.y)));
CVector rotshift = CVector ( p , 0.f , t ) * - distance ;
2013-06-26 18:57:37 +00:00
CVector proj = CStereoOVR : : getCurrentFrustum ( cid ) . project ( vec + ipd + rotshift ) ;
2013-06-26 17:58:27 +00:00
x = ( proj . x - 0.5f ) ;
y = ( proj . y - 0.5f ) ;
# endif
2013-06-26 02:57:58 +00:00
}
2013-07-03 03:21:32 +00:00
void CStereoOVR : : setEyePosition ( const NLMISC : : CVector & v )
{
m_EyePosition = v ;
}
const NLMISC : : CVector & CStereoOVR : : getEyePosition ( ) const
{
return m_EyePosition ;
}
void CStereoOVR : : setScale ( float s )
{
m_EyePosition = m_EyePosition * ( s / m_Scale ) ;
m_Scale = s ;
}
2013-06-26 00:45:49 +00:00
void CStereoOVR : : listDevices ( std : : vector < CStereoDeviceInfo > & devicesOut )
{
s_StereoOVRSystem . Init ( ) ;
OVR : : DeviceEnumerator < OVR : : HMDDevice > devices = s_DeviceManager - > EnumerateDevices < OVR : : HMDDevice > ( ) ;
2013-06-28 21:19:32 +00:00
uint id = 1 ;
2013-06-26 00:45:49 +00:00
do
{
CStereoDeviceInfo deviceInfoOut ;
OVR : : DeviceInfo deviceInfo ;
if ( devices . IsAvailable ( ) )
{
devices . GetDeviceInfo ( & deviceInfo ) ;
CStereoOVRDeviceHandle * handle = new CStereoOVRDeviceHandle ( ) ;
2013-06-28 21:19:32 +00:00
deviceInfoOut . Factory = static_cast < IStereoDeviceFactory * > ( handle ) ;
2013-06-26 00:45:49 +00:00
handle - > DeviceHandle = devices ;
2013-06-28 21:19:32 +00:00
deviceInfoOut . Class = CStereoDeviceInfo : : StereoHMD ; // 1; // OVR::HMDDevice
deviceInfoOut . Library = CStereoDeviceInfo : : OVR ; // "Oculus SDK";
2013-06-26 00:45:49 +00:00
deviceInfoOut . Manufacturer = deviceInfo . Manufacturer ;
deviceInfoOut . ProductName = deviceInfo . ProductName ;
2014-02-04 19:52:15 +00:00
deviceInfoOut . AllowAuto = true ;
2013-06-28 21:19:32 +00:00
stringstream ser ;
ser < < id ;
deviceInfoOut . Serial = ser . str ( ) ; // can't get the real serial from the sdk...
2013-06-26 00:45:49 +00:00
devicesOut . push_back ( deviceInfoOut ) ;
+ + id ;
}
} while ( devices . Next ( ) ) ;
}
bool CStereoOVR : : isLibraryInUse ( )
{
nlassert ( s_DeviceCounter > = 0 ) ;
return s_DeviceCounter > 0 ;
}
void CStereoOVR : : releaseLibrary ( )
{
nlassert ( s_DeviceCounter = = 0 ) ;
s_StereoOVRSystem . Release ( ) ;
}
2013-06-26 02:57:58 +00:00
bool CStereoOVR : : isDeviceCreated ( )
{
return m_DevicePtr - > HMDDevice ! = NULL ;
}
2013-06-26 00:45:49 +00:00
} /* namespace NL3D */
2013-07-06 18:40:42 +00:00
# endif /* HAVE_LIBOVR */
2013-07-06 18:05:19 +00:00
2013-06-26 00:45:49 +00:00
/* end of file */