├── .gitignore ├── LICENSE.txt ├── LibOVR ├── Include │ ├── Extras │ │ ├── OVR_CAPI_Util.h │ │ ├── OVR_Math.h │ │ └── OVR_StereoProjection.h │ ├── OVR_CAPI.h │ ├── OVR_CAPI_Audio.h │ ├── OVR_CAPI_D3D.h │ ├── OVR_CAPI_GL.h │ ├── OVR_CAPI_Keys.h │ ├── OVR_ErrorCode.h │ └── OVR_Version.h ├── Lib │ └── Windows │ │ ├── Win32 │ │ └── Release │ │ │ └── VS2013 │ │ │ └── LibOVR.lib │ │ └── x64 │ │ └── Release │ │ └── VS2013 │ │ └── LibOVR.lib └── Src │ ├── OVR_CAPIShim.c │ ├── OVR_CAPI_Util.cpp │ ├── OVR_StereoProjection.cpp │ └── Resources │ └── Windows │ ├── LibOVR.rc │ ├── Oculus.ico │ └── resource.h ├── README.md ├── cinderblock.png ├── cinderblock.xml ├── include ├── CinderOculus.cpp └── CinderOculus.h └── samples ├── BasicSample ├── assets │ ├── phong.frag │ └── phong.vert ├── include │ └── Resources.h ├── resources │ ├── CinderApp.icns │ └── cinder_app_icon.ico ├── src │ └── BasicSampleApp.cpp └── vc2013 │ ├── BasicSample.sln │ ├── BasicSample.vcxproj │ ├── BasicSample.vcxproj.filters │ └── Resources.rc ├── InstancedStereo ├── assets │ ├── phong.frag │ └── phong.vert ├── include │ └── Resources.h ├── resources │ ├── CinderApp.icns │ └── cinder_app_icon.ico ├── src │ └── InstancedStereoApp.cpp └── vc2013 │ ├── InstancedStereo.sln │ ├── InstancedStereo.vcxproj │ ├── InstancedStereo.vcxproj.filters │ └── Resources.rc └── SphericalStereo ├── assets ├── arnold_LR.jpg ├── stereo.frag └── stereo.vert ├── include └── Resources.h ├── resources ├── CinderApp.icns └── cinder_app_icon.ico ├── src └── SphericalStereoApp.cpp └── vc2013 ├── Resources.rc ├── SphericalStereo.sln ├── SphericalStereo.vcxproj └── SphericalStereo.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows cruft 2 | *.suo 3 | *.ncb 4 | *.sdf 5 | *.opensdf 6 | Debug/ 7 | Release/ 8 | ipch/ 9 | *.VC.opendb 10 | 11 | # Finder 12 | .DS_Store 13 | 14 | # Xcode 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | *.user 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Oculus VR Rift SDK Software License 2 | 3 | Oculus VR, LLC Software Development Kit License Agreement 4 | 5 | Copyright © 2014 Oculus VR, LLC. All rights reserved. 6 | 7 | The text of this may be found at: http://www.oculusvr.com/licenses/LICENSE-3.2 8 | 9 | Human-Readable Summary*: 10 | 11 | You are Free to: 12 | 13 | Use, modify, and distribute the Oculus VR Rift SDK in source and binary 14 | form with your applications/software. 15 | 16 | With the Following Restrictions: 17 | 18 | You can only distribute or re-distribute the source code to LibOVR in 19 | whole, not in part. 20 | 21 | Modifications to the Oculus VR Rift SDK in source or binary form must 22 | be shared with Oculus VR. 23 | 24 | If your applications cause health and safety issues, you may lose your 25 | right to use the Oculus VR Rift SDK, including LibOVR. 26 | 27 | The Oculus VR Rift SDK may not be used to interface with unapproved commercial 28 | virtual reality mobile or non-mobile products or hardware. 29 | 30 | * - This human-readable Summary is not a license. It is simply a convenient 31 | reference for understanding the full Oculus VR Rift SDK License Agreement. 32 | The Summary is written as a user-friendly interface to the full Oculus VR Rift 33 | SDK License below. This Summary itself has no legal value, and its contents do 34 | not appear in the actual license. 35 | 36 | Full-length Legal Copy: 37 | 38 | 1. Subject to the terms and conditions of this License Agreement (the "License"), 39 | Oculus VR, LLC ("Oculus VR") hereby grants to you a perpetual, worldwide, 40 | non-exclusive, no-charge, royalty-free, sublicenseable copyright license to use, 41 | reproduce, redistribute (subject to restrictions below), modify, and improve the 42 | software contained in this Oculus VR Rift Software Development Kit ("RIFT SDK"), 43 | including, but not limited to, the samples, headers, LibOVR headers, and LibOVR 44 | source. This license is subject to the following terms and conditions: 45 | 46 | 1.1. This license includes the non-exclusive license and right to use (i) the RIFT 47 | SDK to make applications, content, games and demos (collectively and generally 48 | referred to as "Developer Content") that run on the Oculus VR approved mobile hardware 49 | and software products ("Oculus Approved Rift Products") and which may incorporate 50 | the RIFT SDK in whole or in part in binary or object code; and (ii) to use the 51 | RIFT SDK to create derivative works of the RIFT SDK itself ("RIFT SDK Derivatives"), 52 | whether in source, binary, or object form, in whole or in part, including third 53 | party software unless otherwise noted. 54 | 55 | 1.2. RIFT SDK Derivatives are further defined as source, binary or object code 56 | derived exclusively from the RIFT SDK by you; provided, however, that RIFT SDK 57 | Derivatives do not include the Developer Content (engines, utilities, applications, 58 | content, games or demos) which may be developed using the RIFT SDK. By way of example 59 | a mobile application or game or demo that is developed using the RIFT SDK would not 60 | be a RIFT SDK Derivative , nor would a utility or tool set in a pre-existing game 61 | engine that is adapted to work with the RIFT SDK be a RIFT SDK Derivative. 62 | By way of example, but not limitation, a RIFT SDK Derivative is or would be: either (i) 63 | an adaptation of a utility or piece of code from the RIFT SDK to improve efficiency; 64 | or (ii) an addition of code or improvement to the RIFT SDK that adds functionality. 65 | 66 | 1.3 For the sake of clarification when you use the RIFT SDK (including RIFT SDK 67 | Derivatives) in or with Developer Content, you retain all rights to your Developer 68 | Content, and you have no obligations to share or license Developer Content (including 69 | your source and object code) to Oculus VR or any third parties; provided, however, 70 | Oculus VR retains all rights to the RIFT SDK and the RIFT SDK Derivatives that may 71 | be incorporated into your Developer Content. 72 | 73 | 1.4 You agree to and you will use the Flash Screen Warning and the Health and 74 | Safety Warnings (collectively the "Oculus Warnings") and the Oculus VR health and 75 | safety protocols found in the Oculus Best Practices Guide ("Oculus H&S Protocols"), 76 | and your use of the Oculus Warnings and the Oculus end user license agreement 77 | ("Oculus EULA") with your Developer Content as provided for in the Oculus Developer 78 | Center, all of which can be found at the following link: 79 | https://developer.oculusvr.com/?action=doc. 80 | 81 | 2. You, the recipient and user of the RIFT SDK, hereby agree and accept that that 82 | Oculus VR shall own all right, title and interest to the intellectual property 83 | rights, including, but limited to copyright, trademark and patent rights, to any 84 | RIFT SDK Derivatives that you may create, and you hereby assign any and all such 85 | rights to such RIFT SDK Derivatives to Oculus VR, subject to the following. 86 | 87 | 2.1 We hereby grant to you the a fully paid up, no-charge, royalty-free, 88 | world-wide, in perpetuity, non-exclusive right and license back to use these RIFT 89 | SDK Derivatives solely in conjunction with the RIFT SDK (or any components of the 90 | RIFT SDK) and/or Developer Content on Oculus Rift Products as set forth herein. 91 | 92 | 2.2 Furthermore, for the sake of clarification, Oculus VR and its assignees and 93 | licensees shall be free to use such RIFT SDK Derivatives without any approval 94 | from you and without compensation or attribution to you. 95 | 96 | 2.3 You also agree upon Oculus VR's request to provide the source and binary code 97 | of any RIFT SDK Derivatives to Oculus VR. FAILURE TO COMPLY WITH THIS REQUEST 98 | IS THE BASIS FOR AUTOMATIC TERMINATION OF THIS LICENSE BY OCULUS VR. 99 | 100 | 3. Subject to the terms and conditions of this License, your license to redistribute 101 | and sublicense the RIFT SDK and RIFT SDK Derivatives is also expressly made 102 | subject to the following conditions: 103 | 104 | 3.1. You may sublicense and redistribute the source, binary, or object code of 105 | the RIFT SDK in whole or in part by itself for no charge or as part of a for charge 106 | piece of Developer Content; provided, however, you may only license, sublicense 107 | or redistribute the source, binary or object code of LibOVR in whole, and you may 108 | not license, sublicense or redistribute any portion or element of LibOVR separately 109 | or in part (in either source, binary or object form). If you license, sublicense 110 | or redistribute RIFT SDK Derivatives in and of themselves (not as a part of a 111 | piece of Developer Content) then you may only do that solely with and in conjunction 112 | with either the RIFT SDK or LibOVR. The RIFT SDK (including, but not limited to 113 | LibOVR), any RIFT SDK Derivatives, and any Developer Content may only be used 114 | with Oculus Approved Rift Products and may not be used, licensed, or sublicensed 115 | to interface with mobile software or hardware or other commercial headsets, 116 | mobile tablets or phones that are not authorized and approved by Oculus VR; 117 | 118 | 3.2. You must include with all such redistributed or sublicensed RIFT SDK 119 | or RIFT SDK Derivatives code the following copyright notice: 120 | "Copyright © 2014 Oculus VR, LLC. All rights reserved," and include the 121 | list of conditions contained in this Section 3, including the full text of 122 | the disclaimer in Section 3.6 below; 123 | 124 | 3.3. Neither the name of Oculus VR, LLC nor the names of Oculus VR, LLC's 125 | contributors, licensors, employees, or contractors, may be used to endorse or promote 126 | products derived from this RIFT SDK without specific prior written permission 127 | of Oculus VR, LLC; 128 | 129 | 3.4. You must give any other recipients of the RIFT SDK or any elements thereof, 130 | including LibOVR or RIFT SDK Derivatives, a copy of this License as such recipients, 131 | licensees or sublicensees may only use the RIFT SDK or any RIFT SDK Derivatives 132 | or any elements thereof subject to the terms of this Licence and such recipients, 133 | licensees or sublicensees agreement and acceptance of this License with Oculus VR 134 | (which will convey all rights to the recipients’ or licensees’ or sublicensees’ 135 | RIFT SDK Derivatives to Oculus VR), and you must cause any modified files to 136 | carry prominent notices stating that you changed the files; 137 | 138 | 3.5. If the RIFT SDK or a specific element thereof such as LibOVR includes a 139 | "LICENSE" text file as part of its distribution (the "License Notice"), then 140 | any RIFT SDK Derivatives that you distribute with the RIFT SDK in whole or in 141 | part must include a readable copy of such attribution notices as are contained 142 | within the applicable License Notice file (excluding those notices that do not 143 | pertain to any part of the RIFT SDK Derivatives), in at least one of the following 144 | places: within a License Notice text file distributed as part of the RIFT SDK 145 | Derivatives; within the source form or documentation, if provided along with 146 | the RIFT SDK Derivatives; or, within a display generated by the RIFT SDK Derivatives, 147 | if and wherever such third-party notices normally appear. You must also include 148 | in the License Notice file for all RIFT SDK Derivatives a copy of all notices 149 | (including any product liability or health and safety notices). The contents 150 | of the License Notice file are for informational purposes only and do not modify 151 | the License. You may add your own attribution notices within RIFT SDK Derivatives 152 | that you distribute, alongside or as an addendum to the License Notice text from 153 | the RIFT SDK or any part thereof, provided that such additional attribution notices 154 | cannot be construed as modifying the License. 155 | 156 | 3.6. THIS RIFT SDK AND ANY COMPONENT THEREOF IS PROVIDED BY OCULUS VR AND 157 | ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 158 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 159 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OCULUS VR AS THE 160 | COPYRIGHT OWNER OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 161 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 162 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 163 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 164 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 165 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS RIFT 166 | SDK OR THE RIFT SDK DERIVATIVES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 167 | 168 | 4. This License does not grant permission to use the trade names, trademarks, 169 | service marks, or product names of Oculus VR, except as required for reasonable 170 | and customary use in describing the origin of the RIFT SDK, LibOVR, or any 171 | element thereof, and reproducing the content of the License Notice file. 172 | Oculus VR reserves all rights not expressly granted to you under this License. 173 | 174 | 5. In no event and under no legal theory, whether in tort (including negligence), 175 | contract, or otherwise, unless required by applicable law (such as 176 | deliberate and grossly negligent acts) or agreed to in writing, shall Oculus VR 177 | or any contributor be liable to you or your licensees or sublicensees for 178 | damages, including any direct, indirect, special, incidental, or consequential 179 | damages of any character arising as a result of this License or out of the use 180 | or inability to use the RIFT SDK, LibOVR, any element thereof or any RIFT SDK 181 | Derivatives (including but not limited to damages for loss of goodwill, work 182 | stoppage, computer failure or malfunction, or any and all other commercial 183 | damages or losses), even if you or such contributor has been advised of the 184 | possibility of such damages. 185 | 186 | 6. Your acceptance of the terms and conditions of this License in and of 187 | itself and for all Developer Content created as of March 1, 2014, may be 188 | evidenced by any of the following: your usage of the RIFT SDK or any element 189 | thereof, acceptance of the click-through agreement, or opening the packaging 190 | of the CD-ROM containing the RIFT SDK or any element thereof, including LibOVR. 191 | As this License is updated for future releases of the RIFT SDK and/or LibOVR, 192 | you agree to abide by and meet all requirements of future updates of this 193 | License for those future RIFT SDK releases as evidenced by the same usage of 194 | the RIFT SDK or any element thereof and the future updates of this License 195 | will apply for that future Developer Content that may developed for or with 196 | that future RIFT SDK or any element thereof (i.e., you cannot sidestep out 197 | of the requirements of future updates of the License by developing against 198 | an older release of the RIFT SDK or License). 199 | 200 | 7. Oculus VR reserves the right to terminate this License and all your 201 | rights hereunder in the event you materially breach this License and fail 202 | to cure such breach within ten (10) business days after notice of breach 203 | from Oculus VR. 204 | 205 | 8. Furthermore, Oculus VR also reserves the right to cancel or terminate 206 | this License for any of the following reasons upon notice to you, subject 207 | to the appeal process set forth in Section 14 for a wrongful termination: 208 | 209 | a) Intellectual property infringement by you with Developer Content 210 | or RIFT SDK Derivatives created by you that is used with or by the 211 | RIFT SDK or any part thereof, or any of the RIFT SDK Derivatives; 212 | 213 | b) Developer Content that violates or infringes upon applicable law; 214 | 215 | c) Health and safety issues associated with your Developer Content; 216 | 217 | d) Failure to comply with or use properly the Oculus Warnings, 218 | Oculus H&S Protocols, or Oculus EULA; 219 | 220 | e) Use of the RIFT SDK, RIFT SDK Derivatives or LibOVR with a 221 | commercial product other than an Oculus Approved Product; and 222 | 223 | f) Failure to provide required notices or deliver source code 224 | and/or binary of RIFT SDK Derivatives as set forth above. 225 | 226 | If you believe that you have been wrongfully terminated under this Section 8 227 | with respect to material breach or with respect to these above conditions, 228 | you have the right to appeal the termination of this License under Section 14. 229 | 230 | 9. This License may be amended by Oculus VR on a prospective basis, and your 231 | usage of the License after such amendments or changes signifies your consent 232 | to and acceptance of any such amendments or changes on a going forward basis. 233 | 234 | 10. In the event any provision of this License is determined to be invalid, 235 | prohibited or unenforceable by a court or other body of competent jurisdiction, 236 | this License shall be construed as if such invalid, prohibited or unenforceable 237 | provision has been more narrowly drawn so as not to be invalid, prohibited or 238 | unenforceable. 239 | 240 | 11. You may not assign any rights or obligations under this License without 241 | the advance written consent of Oculus VR, which may be withheld in its sole 242 | discretion. Oculus VR may assign its rights or obligations under this License 243 | in its sole discretion. 244 | 245 | 12. Failure of either party at any time to enforce any of the provisions of 246 | this License will not be construed as a waiver of such provisions or in any way 247 | affect the validity of this License or parts thereof. 248 | 249 | 13. Your remedies under this License shall be limited to the right to collect 250 | money damages, if any, and you hereby waive your right to injunctive or other 251 | equitable relief. 252 | 253 | 14. This License shall be governed by the laws of the State of California, 254 | without giving effect to choice of law principles. All disputes relating to 255 | this License shall be resolved by binding non-appearance-based arbitration 256 | before a neutral arbitrator in Orange County, California. If your License 257 | has been terminated hereunder by Oculus, you may appeal your termination 258 | through this arbitration process on an expedited basis with an arbitration 259 | within thirty days of your giving Oculus VR notice of the appeal. The 260 | arbitration shall be conducted in accordance with the rules and procedures 261 | of JAMS then in effect, and the judgment of the arbitrator shall be final 262 | and capable of entry in any court of competent jurisdiction. You agree 263 | to submit to the personal jurisdiction of the courts located within Orange 264 | County, California in connection with any entrance of an arbitrator’s judgment 265 | or decision or any dispute with respect to the arbitration process or procedure 266 | or Oculus VR’s exercise of its equitable rights or remedies. 267 | -------------------------------------------------------------------------------- /LibOVR/Include/Extras/OVR_CAPI_Util.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************//** 2 | \file OVR_CAPI_Util.h 3 | \brief This header provides LibOVR utility function declarations 4 | \copyright Copyright 2015-2016 Oculus VR, LLC All Rights reserved. 5 | *************************************************************************************/ 6 | 7 | #ifndef OVR_CAPI_Util_h 8 | #define OVR_CAPI_Util_h 9 | 10 | 11 | #include "OVR_CAPI.h" 12 | 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | 19 | /// Enumerates modifications to the projection matrix based on the application's needs. 20 | /// 21 | /// \see ovrMatrix4f_Projection 22 | /// 23 | typedef enum ovrProjectionModifier_ 24 | { 25 | /// Use for generating a default projection matrix that is: 26 | /// * Right-handed. 27 | /// * Near depth values stored in the depth buffer are smaller than far depth values. 28 | /// * Both near and far are explicitly defined. 29 | /// * With a clipping range that is (0 to w). 30 | ovrProjection_None = 0x00, 31 | 32 | /// Enable if using left-handed transformations in your application. 33 | ovrProjection_LeftHanded = 0x01, 34 | 35 | /// After the projection transform is applied, far values stored in the depth buffer will be less than closer depth values. 36 | /// NOTE: Enable only if the application is using a floating-point depth buffer for proper precision. 37 | ovrProjection_FarLessThanNear = 0x02, 38 | 39 | /// When this flag is used, the zfar value pushed into ovrMatrix4f_Projection() will be ignored 40 | /// NOTE: Enable only if ovrProjection_FarLessThanNear is also enabled where the far clipping plane will be pushed to infinity. 41 | ovrProjection_FarClipAtInfinity = 0x04, 42 | 43 | /// Enable if the application is rendering with OpenGL and expects a projection matrix with a clipping range of (-w to w). 44 | /// Ignore this flag if your application already handles the conversion from D3D range (0 to w) to OpenGL. 45 | ovrProjection_ClipRangeOpenGL = 0x08, 46 | } ovrProjectionModifier; 47 | 48 | 49 | /// Return values for ovr_Detect. 50 | /// 51 | /// \see ovr_Detect 52 | /// 53 | typedef struct OVR_ALIGNAS(8) ovrDetectResult_ 54 | { 55 | /// Is ovrFalse when the Oculus Service is not running. 56 | /// This means that the Oculus Service is either uninstalled or stopped. 57 | /// IsOculusHMDConnected will be ovrFalse in this case. 58 | /// Is ovrTrue when the Oculus Service is running. 59 | /// This means that the Oculus Service is installed and running. 60 | /// IsOculusHMDConnected will reflect the state of the HMD. 61 | ovrBool IsOculusServiceRunning; 62 | 63 | /// Is ovrFalse when an Oculus HMD is not detected. 64 | /// If the Oculus Service is not running, this will be ovrFalse. 65 | /// Is ovrTrue when an Oculus HMD is detected. 66 | /// This implies that the Oculus Service is also installed and running. 67 | ovrBool IsOculusHMDConnected; 68 | 69 | OVR_UNUSED_STRUCT_PAD(pad0, 6) ///< \internal struct padding 70 | 71 | } ovrDetectResult; 72 | 73 | OVR_STATIC_ASSERT(sizeof(ovrDetectResult) == 8, "ovrDetectResult size mismatch"); 74 | 75 | 76 | /// Detects Oculus Runtime and Device Status 77 | /// 78 | /// Checks for Oculus Runtime and Oculus HMD device status without loading the LibOVRRT 79 | /// shared library. This may be called before ovr_Initialize() to help decide whether or 80 | /// not to initialize LibOVR. 81 | /// 82 | /// \param[in] timeoutMilliseconds Specifies a timeout to wait for HMD to be attached or 0 to poll. 83 | /// 84 | /// \return Returns an ovrDetectResult object indicating the result of detection. 85 | /// 86 | /// \see ovrDetectResult 87 | /// 88 | OVR_PUBLIC_FUNCTION(ovrDetectResult) ovr_Detect(int timeoutMilliseconds); 89 | 90 | // On the Windows platform, 91 | #ifdef _WIN32 92 | /// This is the Windows Named Event name that is used to check for HMD connected state. 93 | #define OVR_HMD_CONNECTED_EVENT_NAME L"OculusHMDConnected" 94 | #endif // _WIN32 95 | 96 | 97 | /// Used to generate projection from ovrEyeDesc::Fov. 98 | /// 99 | /// \param[in] fov Specifies the ovrFovPort to use. 100 | /// \param[in] znear Distance to near Z limit. 101 | /// \param[in] zfar Distance to far Z limit. 102 | /// \param[in] projectionModFlags A combination of the ovrProjectionModifier flags. 103 | /// 104 | /// \return Returns the calculated projection matrix. 105 | /// 106 | /// \see ovrProjectionModifier 107 | /// 108 | OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, unsigned int projectionModFlags); 109 | 110 | 111 | /// Extracts the required data from the result of ovrMatrix4f_Projection. 112 | /// 113 | /// \param[in] projection Specifies the project matrix from which to extract ovrTimewarpProjectionDesc. 114 | /// \param[in] projectionModFlags A combination of the ovrProjectionModifier flags. 115 | /// \return Returns the extracted ovrTimewarpProjectionDesc. 116 | /// \see ovrTimewarpProjectionDesc 117 | /// 118 | OVR_PUBLIC_FUNCTION(ovrTimewarpProjectionDesc) ovrTimewarpProjectionDesc_FromProjection(ovrMatrix4f projection, unsigned int projectionModFlags); 119 | 120 | 121 | /// Generates an orthographic sub-projection. 122 | /// 123 | /// Used for 2D rendering, Y is down. 124 | /// 125 | /// \param[in] projection The perspective matrix that the orthographic matrix is derived from. 126 | /// \param[in] orthoScale Equal to 1.0f / pixelsPerTanAngleAtCenter. 127 | /// \param[in] orthoDistance Equal to the distance from the camera in meters, such as 0.8m. 128 | /// \param[in] HmdToEyeOffsetX Specifies the offset of the eye from the center. 129 | /// 130 | /// \return Returns the calculated projection matrix. 131 | /// 132 | OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale, 133 | float orthoDistance, float HmdToEyeOffsetX); 134 | 135 | 136 | 137 | /// Computes offset eye poses based on headPose returned by ovrTrackingState. 138 | /// 139 | /// \param[in] headPose Indicates the HMD position and orientation to use for the calculation. 140 | /// \param[in] hmdToEyeOffset Can be ovrEyeRenderDesc.HmdToEyeOffset returned from 141 | /// ovr_GetRenderDesc. For monoscopic rendering, use a vector that is the average 142 | /// of the two vectors for both eyes. 143 | /// \param[out] outEyePoses If outEyePoses are used for rendering, they should be passed to 144 | /// ovr_SubmitFrame in ovrLayerEyeFov::RenderPose or ovrLayerEyeFovDepth::RenderPose. 145 | /// 146 | OVR_PUBLIC_FUNCTION(void) ovr_CalcEyePoses(ovrPosef headPose, 147 | const ovrVector3f hmdToEyeOffset[2], 148 | ovrPosef outEyePoses[2]); 149 | 150 | 151 | /// Returns the predicted head pose in outHmdTrackingState and offset eye poses in outEyePoses. 152 | /// 153 | /// This is a thread-safe function where caller should increment frameIndex with every frame 154 | /// and pass that index where applicable to functions called on the rendering thread. 155 | /// Assuming outEyePoses are used for rendering, it should be passed as a part of ovrLayerEyeFov. 156 | /// The caller does not need to worry about applying HmdToEyeOffset to the returned outEyePoses variables. 157 | /// 158 | /// \param[in] hmd Specifies an ovrSession previously returned by ovr_Create. 159 | /// \param[in] frameIndex Specifies the targeted frame index, or 0 to refer to one frame after 160 | /// the last time ovr_SubmitFrame was called. 161 | /// \param[in] latencyMarker Specifies that this call is the point in time where 162 | /// the "App-to-Mid-Photon" latency timer starts from. If a given ovrLayer 163 | /// provides "SensorSampleTimestamp", that will override the value stored here. 164 | /// \param[in] hmdToEyeOffset Can be ovrEyeRenderDesc.HmdToEyeOffset returned from 165 | /// ovr_GetRenderDesc. For monoscopic rendering, use a vector that is the average 166 | /// of the two vectors for both eyes. 167 | /// \param[out] outEyePoses The predicted eye poses. 168 | /// \param[out] outSensorSampleTime The time when this function was called. May be NULL, in which case it is ignored. 169 | /// 170 | OVR_PUBLIC_FUNCTION(void) ovr_GetEyePoses(ovrSession session, long long frameIndex, ovrBool latencyMarker, 171 | const ovrVector3f hmdToEyeOffset[2], 172 | ovrPosef outEyePoses[2], 173 | double* outSensorSampleTime); 174 | 175 | 176 | 177 | /// Tracking poses provided by the SDK come in a right-handed coordinate system. If an application 178 | /// is passing in ovrProjection_LeftHanded into ovrMatrix4f_Projection, then it should also use 179 | /// this function to flip the HMD tracking poses to be left-handed. 180 | /// 181 | /// While this utility function is intended to convert a left-handed ovrPosef into a right-handed 182 | /// coordinate system, it will also work for converting right-handed to left-handed since the 183 | /// flip operation is the same for both cases. 184 | /// 185 | /// \param[in] inPose that is right-handed 186 | /// \param[out] outPose that is requested to be left-handed (can be the same pointer to inPose) 187 | /// 188 | OVR_PUBLIC_FUNCTION(void) ovrPosef_FlipHandedness(const ovrPosef* inPose, ovrPosef* outPose); 189 | 190 | 191 | #ifdef __cplusplus 192 | } /* extern "C" */ 193 | #endif 194 | 195 | 196 | #endif // Header include guard 197 | -------------------------------------------------------------------------------- /LibOVR/Include/Extras/OVR_StereoProjection.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************ 2 | 3 | Filename : OVR_StereoProjection.h 4 | Content : Stereo projection functions 5 | Created : November 30, 2013 6 | Authors : Tom Fosyth 7 | 8 | Copyright : Copyright 2014-2016 Oculus VR, LLC All Rights reserved. 9 | 10 | Licensed under the Oculus VR Rift SDK License Version 3.3 (the "License"); 11 | you may not use the Oculus VR Rift SDK except in compliance with the License, 12 | which is provided at the time of installation or download, or which 13 | otherwise accompanies this software in either electronic or hard copy form. 14 | 15 | You may obtain a copy of the License at 16 | 17 | http://www.oculusvr.com/licenses/LICENSE-3.3 18 | 19 | Unless required by applicable law or agreed to in writing, the Oculus VR SDK 20 | distributed under the License is distributed on an "AS IS" BASIS, 21 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | See the License for the specific language governing permissions and 23 | limitations under the License. 24 | 25 | *************************************************************************************/ 26 | 27 | #ifndef OVR_StereoProjection_h 28 | #define OVR_StereoProjection_h 29 | 30 | 31 | #include "Extras/OVR_Math.h" 32 | 33 | 34 | namespace OVR { 35 | 36 | 37 | //----------------------------------------------------------------------------------- 38 | // ***** Stereo Enumerations 39 | 40 | // StereoEye specifies which eye we are rendering for; it is used to 41 | // retrieve StereoEyeParams. 42 | enum StereoEye 43 | { 44 | StereoEye_Left, 45 | StereoEye_Right, 46 | StereoEye_Center 47 | }; 48 | 49 | 50 | 51 | //----------------------------------------------------------------------------------- 52 | // ***** Propjection functions 53 | 54 | Matrix4f CreateProjection ( bool rightHanded, bool isOpenGL, FovPort fov, StereoEye eye, 55 | float zNear = 0.01f, float zFar = 10000.0f, 56 | bool flipZ = false, bool farAtInfinity = false); 57 | 58 | Matrix4f CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType, 59 | float tanHalfFovX, float tanHalfFovY, 60 | float unitsX, float unitsY, float distanceFromCamera, 61 | float interpupillaryDistance, Matrix4f const &projection, 62 | float zNear = 0.0f, float zFar = 0.0f, 63 | bool flipZ = false, bool farAtInfinity = false); 64 | 65 | ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort fov ); 66 | 67 | 68 | } //namespace OVR 69 | 70 | #endif // OVR_StereoProjection_h 71 | -------------------------------------------------------------------------------- /LibOVR/Include/OVR_CAPI_Audio.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************//** 2 | \file OVR_CAPI_Audio.h 3 | \brief CAPI audio functions. 4 | \copyright Copyright 2015 Oculus VR, LLC. All Rights reserved. 5 | ************************************************************************************/ 6 | 7 | 8 | #ifndef OVR_CAPI_Audio_h 9 | #define OVR_CAPI_Audio_h 10 | 11 | #ifdef _WIN32 12 | #include 13 | #include "OVR_CAPI.h" 14 | #define OVR_AUDIO_MAX_DEVICE_STR_SIZE 128 15 | 16 | /// Gets the ID of the preferred VR audio output device. 17 | /// 18 | /// \param[out] deviceOutId The ID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be WAVE_MAPPER. 19 | /// 20 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 21 | /// ovr_GetLastErrorInfo to get more information. 22 | /// 23 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutWaveId(UINT* deviceOutId); 24 | 25 | /// Gets the ID of the preferred VR audio input device. 26 | /// 27 | /// \param[out] deviceInId The ID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be WAVE_MAPPER. 28 | /// 29 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 30 | /// ovr_GetLastErrorInfo to get more information. 31 | /// 32 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInWaveId(UINT* deviceInId); 33 | 34 | 35 | /// Gets the GUID of the preferred VR audio device as a string. 36 | /// 37 | /// \param[out] deviceOutStrBuffer A buffer where the GUID string for the device will copied to. 38 | /// 39 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 40 | /// ovr_GetLastErrorInfo to get more information. 41 | /// 42 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutGuidStr(WCHAR deviceOutStrBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]); 43 | 44 | 45 | /// Gets the GUID of the preferred VR audio device. 46 | /// 47 | /// \param[out] deviceOutGuid The GUID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be NULL. 48 | /// 49 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 50 | /// ovr_GetLastErrorInfo to get more information. 51 | /// 52 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutGuid(GUID* deviceOutGuid); 53 | 54 | 55 | /// Gets the GUID of the preferred VR microphone device as a string. 56 | /// 57 | /// \param[out] deviceInStrBuffer A buffer where the GUID string for the device will copied to. 58 | /// 59 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 60 | /// ovr_GetLastErrorInfo to get more information. 61 | /// 62 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInGuidStr(WCHAR deviceInStrBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]); 63 | 64 | 65 | /// Gets the GUID of the preferred VR microphone device. 66 | /// 67 | /// \param[out] deviceInGuid The GUID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be NULL. 68 | /// 69 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 70 | /// ovr_GetLastErrorInfo to get more information. 71 | /// 72 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInGuid(GUID* deviceInGuid); 73 | 74 | #endif //OVR_OS_MS 75 | 76 | #endif // OVR_CAPI_Audio_h 77 | -------------------------------------------------------------------------------- /LibOVR/Include/OVR_CAPI_D3D.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************//** 2 | \file OVR_CAPI_D3D.h 3 | \brief D3D specific structures used by the CAPI interface. 4 | \copyright Copyright 2014-2016 Oculus VR, LLC All Rights reserved. 5 | ************************************************************************************/ 6 | 7 | #ifndef OVR_CAPI_D3D_h 8 | #define OVR_CAPI_D3D_h 9 | 10 | #include "OVR_CAPI.h" 11 | #include "OVR_Version.h" 12 | 13 | 14 | #if defined (_WIN32) 15 | #include 16 | 17 | //----------------------------------------------------------------------------------- 18 | // ***** Direct3D Specific 19 | 20 | /// Create Texture Swap Chain suitable for use with Direct3D 11 and 12. 21 | /// 22 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 23 | /// \param[in] d3dPtr Specifies the application's D3D11Device to create resources with or the D3D12CommandQueue 24 | /// which must be the same one the application renders to the eye textures with. 25 | /// \param[in] desc Specifies requested texture properties. See notes for more info about texture format. 26 | /// \param[in] bindFlags Specifies what ovrTextureBindFlags the application requires for this texture chain. 27 | /// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon a successful return value, else it will be NULL. 28 | /// This texture chain must be eventually destroyed via ovr_DestroyTextureSwapChain before destroying the HMD with ovr_Destroy. 29 | /// 30 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 31 | /// ovr_GetLastErrorInfo to get more information. 32 | /// 33 | /// \note The texture format provided in \a desc should be thought of as the format the distortion-compositor will use for the 34 | /// ShaderResourceView when reading the contents of the texture. To that end, it is highly recommended that the application 35 | /// requests texture swapchain formats that are in sRGB-space (e.g. OVR_FORMAT_R8G8B8A8_UNORM_SRGB) as the compositor 36 | /// does sRGB-correct rendering. As such, the compositor relies on the GPU's hardware sampler to do the sRGB-to-linear 37 | /// conversion. If the application still prefers to render to a linear format (e.g. OVR_FORMAT_R8G8B8A8_UNORM) while handling the 38 | /// linear-to-gamma conversion via HLSL code, then the application must still request the corresponding sRGB format and also use 39 | /// the \a ovrTextureMisc_DX_Typeless flag in the ovrTextureSwapChainDesc's Flag field. This will allow the application to create 40 | /// a RenderTargetView that is the desired linear format while the compositor continues to treat it as sRGB. Failure to do so 41 | /// will cause the compositor to apply unexpected gamma conversions leading to gamma-curve artifacts. The \a ovrTextureMisc_DX_Typeless 42 | /// flag for depth buffer formats (e.g. OVR_FORMAT_D32_FLOAT) is ignored as they are always converted to be typeless. 43 | /// 44 | /// \see ovr_GetTextureSwapChainLength 45 | /// \see ovr_GetTextureSwapChainCurrentIndex 46 | /// \see ovr_GetTextureSwapChainDesc 47 | /// \see ovr_GetTextureSwapChainBufferDX 48 | /// \see ovr_DestroyTextureSwapChain 49 | /// 50 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateTextureSwapChainDX(ovrSession session, 51 | IUnknown* d3dPtr, 52 | const ovrTextureSwapChainDesc* desc, 53 | ovrTextureSwapChain* out_TextureSwapChain); 54 | 55 | 56 | /// Get a specific buffer within the chain as any compatible COM interface (similar to QueryInterface) 57 | /// 58 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 59 | /// \param[in] chain Specifies an ovrTextureSwapChain previously returned by ovr_CreateTextureSwapChainDX 60 | /// \param[in] index Specifies the index within the chain to retrieve. Must be between 0 and length (see ovr_GetTextureSwapChainLength), 61 | /// or may pass -1 to get the buffer at the CurrentIndex location. (Saving a call to GetTextureSwapChainCurrentIndex) 62 | /// \param[in] iid Specifies the interface ID of the interface pointer to query the buffer for. 63 | /// \param[out] out_Buffer Returns the COM interface pointer retrieved. 64 | /// 65 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 66 | /// ovr_GetLastErrorInfo to get more information. 67 | /// 68 | /// Example code 69 | /// \code{.cpp} 70 | /// ovr_GetTextureSwapChainBufferDX(session, chain, 0, IID_ID3D11Texture2D, &d3d11Texture); 71 | /// ovr_GetTextureSwapChainBufferDX(session, chain, 1, IID_PPV_ARGS(&dxgiResource)); 72 | /// \endcode 73 | /// 74 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainBufferDX(ovrSession session, 75 | ovrTextureSwapChain chain, 76 | int index, 77 | IID iid, 78 | void** out_Buffer); 79 | 80 | 81 | /// Create Mirror Texture which is auto-refreshed to mirror Rift contents produced by this application. 82 | /// 83 | /// A second call to ovr_CreateMirrorTextureDX for a given ovrSession before destroying the first one 84 | /// is not supported and will result in an error return. 85 | /// 86 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 87 | /// \param[in] d3dPtr Specifies the application's D3D11Device to create resources with or the D3D12CommandQueue 88 | /// which must be the same one the application renders to the textures with. 89 | /// \param[in] desc Specifies requested texture properties. See notes for more info about texture format. 90 | /// \param[out] out_MirrorTexture Returns the created ovrMirrorTexture, which will be valid upon a successful return value, else it will be NULL. 91 | /// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the HMD with ovr_Destroy. 92 | /// 93 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 94 | /// ovr_GetLastErrorInfo to get more information. 95 | /// 96 | /// \note The texture format provided in \a desc should be thought of as the format the compositor will use for the RenderTargetView when 97 | /// writing into mirror texture. To that end, it is highly recommended that the application requests a mirror texture format that is 98 | /// in sRGB-space (e.g. OVR_FORMAT_R8G8B8A8_UNORM_SRGB) as the compositor does sRGB-correct rendering. If however the application wants 99 | /// to still read the mirror texture as a linear format (e.g. OVR_FORMAT_R8G8B8A8_UNORM) and handle the sRGB-to-linear conversion in 100 | /// HLSL code, then it is recommended the application still requests an sRGB format and also use the \a ovrTextureMisc_DX_Typeless flag in the 101 | /// ovrMirrorTextureDesc's Flags field. This will allow the application to bind a ShaderResourceView that is a linear format while the 102 | /// compositor continues to treat is as sRGB. Failure to do so will cause the compositor to apply unexpected gamma conversions leading to 103 | /// gamma-curve artifacts. 104 | /// 105 | /// 106 | /// Example code 107 | /// \code{.cpp} 108 | /// ovrMirrorTexture mirrorTexture = nullptr; 109 | /// ovrMirrorTextureDesc mirrorDesc = {}; 110 | /// mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; 111 | /// mirrorDesc.Width = mirrorWindowWidth; 112 | /// mirrorDesc.Height = mirrorWindowHeight; 113 | /// ovrResult result = ovr_CreateMirrorTextureDX(session, d3d11Device, &mirrorDesc, &mirrorTexture); 114 | /// [...] 115 | /// // Destroy the texture when done with it. 116 | /// ovr_DestroyMirrorTexture(session, mirrorTexture); 117 | /// mirrorTexture = nullptr; 118 | /// \endcode 119 | /// 120 | /// \see ovr_GetMirrorTextureBufferDX 121 | /// \see ovr_DestroyMirrorTexture 122 | /// 123 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateMirrorTextureDX(ovrSession session, 124 | IUnknown* d3dPtr, 125 | const ovrMirrorTextureDesc* desc, 126 | ovrMirrorTexture* out_MirrorTexture); 127 | 128 | /// Get a the underlying buffer as any compatible COM interface (similar to QueryInterface) 129 | /// 130 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 131 | /// \param[in] mirrorTexture Specifies an ovrMirrorTexture previously returned by ovr_CreateMirrorTextureDX 132 | /// \param[in] iid Specifies the interface ID of the interface pointer to query the buffer for. 133 | /// \param[out] out_Buffer Returns the COM interface pointer retrieved. 134 | /// 135 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 136 | /// ovr_GetLastErrorInfo to get more information. 137 | /// 138 | /// Example code 139 | /// \code{.cpp} 140 | /// ID3D11Texture2D* d3d11Texture = nullptr; 141 | /// ovr_GetMirrorTextureBufferDX(session, mirrorTexture, IID_PPV_ARGS(&d3d11Texture)); 142 | /// d3d11DeviceContext->CopyResource(d3d11TextureBackBuffer, d3d11Texture); 143 | /// d3d11Texture->Release(); 144 | /// dxgiSwapChain->Present(0, 0); 145 | /// \endcode 146 | /// 147 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetMirrorTextureBufferDX(ovrSession session, 148 | ovrMirrorTexture mirrorTexture, 149 | IID iid, 150 | void** out_Buffer); 151 | 152 | 153 | #endif // _WIN32 154 | 155 | #endif // OVR_CAPI_D3D_h 156 | -------------------------------------------------------------------------------- /LibOVR/Include/OVR_CAPI_GL.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************//** 2 | \file OVR_CAPI_GL.h 3 | \brief OpenGL-specific structures used by the CAPI interface. 4 | \copyright Copyright 2015 Oculus VR, LLC. All Rights reserved. 5 | ************************************************************************************/ 6 | 7 | #ifndef OVR_CAPI_GL_h 8 | #define OVR_CAPI_GL_h 9 | 10 | #include "OVR_CAPI.h" 11 | 12 | /// Creates a TextureSwapChain suitable for use with OpenGL. 13 | /// 14 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 15 | /// \param[in] desc Specifies the requested texture properties. See notes for more info about texture format. 16 | /// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon 17 | /// a successful return value, else it will be NULL. This texture swap chain must be eventually 18 | /// destroyed via ovr_DestroyTextureSwapChain before destroying the HMD with ovr_Destroy. 19 | /// 20 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 21 | /// ovr_GetLastErrorInfo to get more information. 22 | /// 23 | /// \note The \a format provided should be thought of as the format the distortion compositor will use when reading 24 | /// the contents of the texture. To that end, it is highly recommended that the application requests texture swap chain 25 | /// formats that are in sRGB-space (e.g. OVR_FORMAT_R8G8B8A8_UNORM_SRGB) as the distortion compositor does sRGB-correct 26 | /// rendering. Furthermore, the app should then make sure "glEnable(GL_FRAMEBUFFER_SRGB);" is called before rendering 27 | /// into these textures. Even though it is not recommended, if the application would like to treat the texture as a linear 28 | /// format and do linear-to-gamma conversion in GLSL, then the application can avoid calling "glEnable(GL_FRAMEBUFFER_SRGB);", 29 | /// but should still pass in an sRGB variant for the \a format. Failure to do so will cause the distortion compositor 30 | /// to apply incorrect gamma conversions leading to gamma-curve artifacts. 31 | /// 32 | /// \see ovr_GetTextureSwapChainLength 33 | /// \see ovr_GetTextureSwapChainCurrentIndex 34 | /// \see ovr_GetTextureSwapChainDesc 35 | /// \see ovr_GetTextureSwapChainBufferGL 36 | /// \see ovr_DestroyTextureSwapChain 37 | /// 38 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateTextureSwapChainGL(ovrSession session, 39 | const ovrTextureSwapChainDesc* desc, 40 | ovrTextureSwapChain* out_TextureSwapChain); 41 | 42 | /// Get a specific buffer within the chain as a GL texture name 43 | /// 44 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 45 | /// \param[in] chain Specifies an ovrTextureSwapChain previously returned by ovr_CreateTextureSwapChainGL 46 | /// \param[in] index Specifies the index within the chain to retrieve. Must be between 0 and length (see ovr_GetTextureSwapChainLength) 47 | /// or may pass -1 to get the buffer at the CurrentIndex location. (Saving a call to GetTextureSwapChainCurrentIndex) 48 | /// \param[out] out_TexId Returns the GL texture object name associated with the specific index requested 49 | /// 50 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 51 | /// ovr_GetLastErrorInfo to get more information. 52 | /// 53 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainBufferGL(ovrSession session, 54 | ovrTextureSwapChain chain, 55 | int index, 56 | unsigned int* out_TexId); 57 | 58 | 59 | /// Creates a Mirror Texture which is auto-refreshed to mirror Rift contents produced by this application. 60 | /// 61 | /// A second call to ovr_CreateMirrorTextureGL for a given ovrSession before destroying the first one 62 | /// is not supported and will result in an error return. 63 | /// 64 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 65 | /// \param[in] desc Specifies the requested mirror texture description. 66 | /// \param[out] out_MirrorTexture Specifies the created ovrMirrorTexture, which will be valid upon a successful return value, else it will be NULL. 67 | /// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the HMD with ovr_Destroy. 68 | /// 69 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 70 | /// ovr_GetLastErrorInfo to get more information. 71 | /// 72 | /// \note The \a format provided should be thought of as the format the distortion compositor will use when writing into the mirror 73 | /// texture. It is highly recommended that mirror textures are requested as sRGB formats because the distortion compositor 74 | /// does sRGB-correct rendering. If the application requests a non-sRGB format (e.g. R8G8B8A8_UNORM) as the mirror texture, 75 | /// then the application might have to apply a manual linear-to-gamma conversion when reading from the mirror texture. 76 | /// Failure to do so can result in incorrect gamma conversions leading to gamma-curve artifacts and color banding. 77 | /// 78 | /// \see ovr_GetMirrorTextureBufferGL 79 | /// \see ovr_DestroyMirrorTexture 80 | /// 81 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateMirrorTextureGL(ovrSession session, 82 | const ovrMirrorTextureDesc* desc, 83 | ovrMirrorTexture* out_MirrorTexture); 84 | 85 | /// Get a the underlying buffer as a GL texture name 86 | /// 87 | /// \param[in] session Specifies an ovrSession previously returned by ovr_Create. 88 | /// \param[in] mirrorTexture Specifies an ovrMirrorTexture previously returned by ovr_CreateMirrorTextureGL 89 | /// \param[out] out_TexId Specifies the GL texture object name associated with the mirror texture 90 | /// 91 | /// \return Returns an ovrResult indicating success or failure. In the case of failure, use 92 | /// ovr_GetLastErrorInfo to get more information. 93 | /// 94 | OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetMirrorTextureBufferGL(ovrSession session, 95 | ovrMirrorTexture mirrorTexture, 96 | unsigned int* out_TexId); 97 | 98 | 99 | #endif // OVR_CAPI_GL_h 100 | -------------------------------------------------------------------------------- /LibOVR/Include/OVR_CAPI_Keys.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************//** 2 | \file OVR_CAPI.h 3 | \brief Keys for CAPI proprty function calls 4 | \copyright Copyright 2015 Oculus VR, LLC All Rights reserved. 5 | ************************************************************************************/ 6 | 7 | #ifndef OVR_CAPI_Keys_h 8 | #define OVR_CAPI_Keys_h 9 | 10 | #include "OVR_Version.h" 11 | 12 | 13 | 14 | #define OVR_KEY_USER "User" // string 15 | 16 | #define OVR_KEY_NAME "Name" // string 17 | 18 | #define OVR_KEY_GENDER "Gender" // string "Male", "Female", or "Unknown" 19 | #define OVR_DEFAULT_GENDER "Unknown" 20 | 21 | #define OVR_KEY_PLAYER_HEIGHT "PlayerHeight" // float meters 22 | #define OVR_DEFAULT_PLAYER_HEIGHT 1.778f 23 | 24 | #define OVR_KEY_EYE_HEIGHT "EyeHeight" // float meters 25 | #define OVR_DEFAULT_EYE_HEIGHT 1.675f 26 | 27 | #define OVR_KEY_NECK_TO_EYE_DISTANCE "NeckEyeDistance" // float[2] meters 28 | #define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL 0.0805f 29 | #define OVR_DEFAULT_NECK_TO_EYE_VERTICAL 0.075f 30 | 31 | 32 | #define OVR_KEY_EYE_TO_NOSE_DISTANCE "EyeToNoseDist" // float[2] meters 33 | 34 | 35 | 36 | 37 | 38 | #define OVR_PERF_HUD_MODE "PerfHudMode" // int, allowed values are defined in enum ovrPerfHudMode 39 | 40 | #define OVR_LAYER_HUD_MODE "LayerHudMode" // int, allowed values are defined in enum ovrLayerHudMode 41 | #define OVR_LAYER_HUD_CURRENT_LAYER "LayerHudCurrentLayer" // int, The layer to show 42 | #define OVR_LAYER_HUD_SHOW_ALL_LAYERS "LayerHudShowAll" // bool, Hide other layers when the hud is enabled 43 | 44 | #define OVR_DEBUG_HUD_STEREO_MODE "DebugHudStereoMode" // int, allowed values are defined in enum ovrDebugHudStereoMode 45 | #define OVR_DEBUG_HUD_STEREO_GUIDE_INFO_ENABLE "DebugHudStereoGuideInfoEnable" // bool 46 | #define OVR_DEBUG_HUD_STEREO_GUIDE_SIZE "DebugHudStereoGuideSize2f" // float[2] 47 | #define OVR_DEBUG_HUD_STEREO_GUIDE_POSITION "DebugHudStereoGuidePosition3f" // float[3] 48 | #define OVR_DEBUG_HUD_STEREO_GUIDE_YAWPITCHROLL "DebugHudStereoGuideYawPitchRoll3f" // float[3] 49 | #define OVR_DEBUG_HUD_STEREO_GUIDE_COLOR "DebugHudStereoGuideColor4f" // float[4] 50 | 51 | 52 | 53 | #endif // OVR_CAPI_Keys_h 54 | -------------------------------------------------------------------------------- /LibOVR/Include/OVR_ErrorCode.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************//** 2 | \file OVR_ErrorCode.h 3 | \brief This header provides LibOVR error code declarations. 4 | \copyright Copyright 2015-2016 Oculus VR, LLC All Rights reserved. 5 | *************************************************************************************/ 6 | 7 | #ifndef OVR_ErrorCode_h 8 | #define OVR_ErrorCode_h 9 | 10 | 11 | #include "OVR_Version.h" 12 | #include 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | #ifndef OVR_RESULT_DEFINED 21 | #define OVR_RESULT_DEFINED ///< Allows ovrResult to be independently defined. 22 | /// API call results are represented at the highest level by a single ovrResult. 23 | typedef int32_t ovrResult; 24 | #endif 25 | 26 | 27 | /// \brief Indicates if an ovrResult indicates success. 28 | /// 29 | /// Some functions return additional successful values other than ovrSucces and 30 | /// require usage of this macro to indicate successs. 31 | /// 32 | #if !defined(OVR_SUCCESS) 33 | #define OVR_SUCCESS(result) (result >= 0) 34 | #endif 35 | 36 | 37 | /// \brief Indicates if an ovrResult indicates an unqualified success. 38 | /// 39 | /// This is useful for indicating that the code intentionally wants to 40 | /// check for result == ovrSuccess as opposed to OVR_SUCCESS(), which 41 | /// checks for result >= ovrSuccess. 42 | /// 43 | #if !defined(OVR_UNQUALIFIED_SUCCESS) 44 | #define OVR_UNQUALIFIED_SUCCESS(result) (result == ovrSuccess) 45 | #endif 46 | 47 | 48 | /// \brief Indicates if an ovrResult indicates failure. 49 | /// 50 | #if !defined(OVR_FAILURE) 51 | #define OVR_FAILURE(result) (!OVR_SUCCESS(result)) 52 | #endif 53 | 54 | 55 | // Success is a value greater or equal to 0, while all error types are negative values. 56 | #ifndef OVR_SUCCESS_DEFINED 57 | #define OVR_SUCCESS_DEFINED ///< Allows ovrResult to be independently defined. 58 | typedef enum ovrSuccessType_ 59 | { 60 | /// This is a general success result. Use OVR_SUCCESS to test for success. 61 | ovrSuccess = 0, 62 | 63 | /// Returned from a call to SubmitFrame. The call succeeded, but what the app 64 | /// rendered will not be visible on the HMD. Ideally the app should continue 65 | /// calling SubmitFrame, but not do any rendering. When the result becomes 66 | /// ovrSuccess, rendering should continue as usual. 67 | ovrSuccess_NotVisible = 1000, 68 | 69 | ovrSuccess_HMDFirmwareMismatch = 4100, ///< The HMD Firmware is out of date but is acceptable. 70 | ovrSuccess_TrackerFirmwareMismatch = 4101, ///< The Tracker Firmware is out of date but is acceptable. 71 | ovrSuccess_ControllerFirmwareMismatch = 4104, ///< The controller firmware is out of date but is acceptable. 72 | ovrSuccess_TrackerDriverNotFound = 4105, ///< The tracker driver interface was not found. Can be a temporary error 73 | 74 | } ovrSuccessType; 75 | #endif 76 | 77 | 78 | typedef enum ovrErrorType_ 79 | { 80 | /* General errors */ 81 | ovrError_MemoryAllocationFailure = -1000, ///< Failure to allocate memory. 82 | ovrError_SocketCreationFailure = -1001, ///< Failure to create a socket. 83 | ovrError_InvalidSession = -1002, ///< Invalid ovrSession parameter provided. 84 | ovrError_Timeout = -1003, ///< The operation timed out. 85 | ovrError_NotInitialized = -1004, ///< The system or component has not been initialized. 86 | ovrError_InvalidParameter = -1005, ///< Invalid parameter provided. See error info or log for details. 87 | ovrError_ServiceError = -1006, ///< Generic service error. See error info or log for details. 88 | ovrError_NoHmd = -1007, ///< The given HMD doesn't exist. 89 | ovrError_Unsupported = -1009, ///< Function call is not supported on this hardware/software 90 | ovrError_DeviceUnavailable = -1010, ///< Specified device type isn't available. 91 | ovrError_InvalidHeadsetOrientation = -1011, ///< The headset was in an invalid orientation for the requested operation (e.g. vertically oriented during ovr_RecenterPose). 92 | ovrError_ClientSkippedDestroy = -1012, ///< The client failed to call ovr_Destroy on an active session before calling ovr_Shutdown. Or the client crashed. 93 | ovrError_ClientSkippedShutdown = -1013, ///< The client failed to call ovr_Shutdown or the client crashed. 94 | ovrError_ServiceDeadlockDetected = -1014, ///< The service watchdog discovered a deadlock. 95 | 96 | /* Audio error range, reserved for Audio errors. */ 97 | ovrError_AudioReservedBegin = -2000, ///< First Audio error. 98 | ovrError_AudioDeviceNotFound = -2001, ///< Failure to find the specified audio device. 99 | ovrError_AudioComError = -2002, ///< Generic COM error. 100 | ovrError_AudioReservedEnd = -2999, ///< Last Audio error. 101 | 102 | /* Initialization errors. */ 103 | ovrError_Initialize = -3000, ///< Generic initialization error. 104 | ovrError_LibLoad = -3001, ///< Couldn't load LibOVRRT. 105 | ovrError_LibVersion = -3002, ///< LibOVRRT version incompatibility. 106 | ovrError_ServiceConnection = -3003, ///< Couldn't connect to the OVR Service. 107 | ovrError_ServiceVersion = -3004, ///< OVR Service version incompatibility. 108 | ovrError_IncompatibleOS = -3005, ///< The operating system version is incompatible. 109 | ovrError_DisplayInit = -3006, ///< Unable to initialize the HMD display. 110 | ovrError_ServerStart = -3007, ///< Unable to start the server. Is it already running? 111 | ovrError_Reinitialization = -3008, ///< Attempting to re-initialize with a different version. 112 | ovrError_MismatchedAdapters = -3009, ///< Chosen rendering adapters between client and service do not match 113 | ovrError_LeakingResources = -3010, ///< Calling application has leaked resources 114 | ovrError_ClientVersion = -3011, ///< Client version too old to connect to service 115 | ovrError_OutOfDateOS = -3012, ///< The operating system is out of date. 116 | ovrError_OutOfDateGfxDriver = -3013, ///< The graphics driver is out of date. 117 | ovrError_IncompatibleGPU = -3014, ///< The graphics hardware is not supported 118 | ovrError_NoValidVRDisplaySystem = -3015, ///< No valid VR display system found. 119 | ovrError_Obsolete = -3016, ///< Feature or API is obsolete and no longer supported. 120 | ovrError_DisabledOrDefaultAdapter = -3017, ///< No supported VR display system found, but disabled or driverless adapter found. 121 | ovrError_HybridGraphicsNotSupported = -3018, ///< The system is using hybrid graphics (Optimus, etc...), which is not support. 122 | ovrError_DisplayManagerInit = -3019, ///< Initialization of the DisplayManager failed. 123 | ovrError_TrackerDriverInit = -3020, ///< Failed to get the interface for an attached tracker 124 | 125 | /* Hardware errors */ 126 | ovrError_InvalidBundleAdjustment = -4000, ///< Headset has no bundle adjustment data. 127 | ovrError_USBBandwidth = -4001, ///< The USB hub cannot handle the camera frame bandwidth. 128 | ovrError_USBEnumeratedSpeed = -4002, ///< The USB camera is not enumerating at the correct device speed. 129 | ovrError_ImageSensorCommError = -4003, ///< Unable to communicate with the image sensor. 130 | ovrError_GeneralTrackerFailure = -4004, ///< We use this to report various sensor issues that don't fit in an easily classifiable bucket. 131 | ovrError_ExcessiveFrameTruncation = -4005, ///< A more than acceptable number of frames are coming back truncated. 132 | ovrError_ExcessiveFrameSkipping = -4006, ///< A more than acceptable number of frames have been skipped. 133 | ovrError_SyncDisconnected = -4007, ///< The sensor is not receiving the sync signal (cable disconnected?). 134 | ovrError_TrackerMemoryReadFailure = -4008, ///< Failed to read memory from the sensor. 135 | ovrError_TrackerMemoryWriteFailure = -4009, ///< Failed to write memory from the sensor. 136 | ovrError_TrackerFrameTimeout = -4010, ///< Timed out waiting for a camera frame. 137 | ovrError_TrackerTruncatedFrame = -4011, ///< Truncated frame returned from sensor. 138 | ovrError_TrackerDriverFailure = -4012, ///< The sensor driver has encountered a problem. 139 | ovrError_TrackerNRFFailure = -4013, ///< The sensor wireless subsystem has encountered a problem. 140 | ovrError_HardwareGone = -4014, ///< The hardware has been unplugged 141 | ovrError_NordicEnabledNoSync = -4015, ///< The nordic indicates that sync is enabled but it is not sending sync pulses 142 | ovrError_NordicSyncNoFrames = -4016, ///< It looks like we're getting a sync signal, but no camera frames have been received 143 | ovrError_CatastrophicFailure = -4017, ///< A catastrophic failure has occurred. We will attempt to recover by resetting the device 144 | ovrError_CatastrophicTimeout = -4018, ///< The catastrophic recovery has timed out. 145 | ovrError_RepeatCatastrophicFail = -4019, ///< Catastrophic failure has repeated too many times. 146 | ovrError_USBOpenDeviceFailure = -4020, ///< Could not open handle for Rift device (likely already in use by another process). 147 | ovrError_HMDGeneralFailure = -4021, ///< Unexpected HMD issues that don't fit a specific bucket. 148 | 149 | ovrError_HMDFirmwareMismatch = -4100, ///< The HMD Firmware is out of date and is unacceptable. 150 | ovrError_TrackerFirmwareMismatch = -4101, ///< The sensor Firmware is out of date and is unacceptable. 151 | ovrError_BootloaderDeviceDetected = -4102, ///< A bootloader HMD is detected by the service. 152 | ovrError_TrackerCalibrationError = -4103, ///< The sensor calibration is missing or incorrect. 153 | ovrError_ControllerFirmwareMismatch = -4104, ///< The controller firmware is out of date and is unacceptable. 154 | ovrError_DevManDeviceDetected = -4105, ///< A DeviceManagement mode HMD is detected by the service. 155 | ovrError_RebootedBootloaderDevice = -4106, ///< Had to reboot bootloader device, which succeeded. 156 | ovrError_FailedRebootBootloaderDev = -4107, ///< Had to reboot bootloader device, which failed. Device is stuck in bootloader mode. 157 | 158 | ovrError_IMUTooManyLostSamples = -4200, ///< Too many lost IMU samples. 159 | ovrError_IMURateError = -4201, ///< IMU rate is outside of the expected range. 160 | ovrError_FeatureReportFailure = -4202, ///< A feature report has failed. 161 | ovrError_HMDWirelessTimeout = -4203, ///< HMD wireless interface never returned from busy state. 162 | 163 | ovrError_BootloaderAssertLog = -4300, ///< HMD Bootloader Assert Log was not empty. 164 | ovrError_AppAssertLog = -4301, ///< HMD App Assert Log was not empty. 165 | 166 | /* Synchronization errors */ 167 | ovrError_Incomplete = -5000, ///< Requested async work not yet complete. 168 | ovrError_Abandoned = -5001, ///< Requested async work was abandoned and result is incomplete. 169 | 170 | /* Rendering errors */ 171 | ovrError_DisplayLost = -6000, ///< In the event of a system-wide graphics reset or cable unplug this is returned to the app. 172 | ovrError_TextureSwapChainFull = -6001, ///< ovr_CommitTextureSwapChain was called too many times on a texture swapchain without calling submit to use the chain. 173 | ovrError_TextureSwapChainInvalid = -6002, ///< The ovrTextureSwapChain is in an incomplete or inconsistent state. Ensure ovr_CommitTextureSwapChain was called at least once first. 174 | ovrError_GraphicsDeviceReset = -6003, ///< Graphics device has been reset (TDR, etc...) 175 | ovrError_DisplayRemoved = -6004, ///< HMD removed from the display adapter 176 | ovrError_ContentProtectionNotAvailable = -6005,/// 25 | #include 26 | 27 | 28 | #if defined(_MSC_VER) 29 | #include 30 | #pragma intrinsic(_mm_pause) 31 | #endif 32 | 33 | #if defined(_WIN32) 34 | #include 35 | #endif 36 | 37 | 38 | 39 | // Used to generate projection from ovrEyeDesc::Fov 40 | OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_Projection( 41 | ovrFovPort fov, float znear, float zfar, unsigned int projectionModFlags) 42 | { 43 | bool leftHanded = (projectionModFlags & ovrProjection_LeftHanded) > 0; 44 | bool flipZ = (projectionModFlags & ovrProjection_FarLessThanNear) > 0; 45 | bool farAtInfinity = (projectionModFlags & ovrProjection_FarClipAtInfinity) > 0; 46 | bool isOpenGL = (projectionModFlags & ovrProjection_ClipRangeOpenGL) > 0; 47 | 48 | // TODO: Pass in correct eye to CreateProjection if we want to support canted displays from CAPI 49 | return OVR::CreateProjection(leftHanded , isOpenGL, fov, OVR::StereoEye_Center, znear, zfar, flipZ, farAtInfinity); 50 | } 51 | 52 | OVR_PUBLIC_FUNCTION(ovrTimewarpProjectionDesc) ovrTimewarpProjectionDesc_FromProjection( 53 | ovrMatrix4f Projection, unsigned int projectionModFlags) 54 | { 55 | ovrTimewarpProjectionDesc res; 56 | res.Projection22 = Projection.M[2][2]; 57 | res.Projection23 = Projection.M[2][3]; 58 | res.Projection32 = Projection.M[3][2]; 59 | 60 | if ((res.Projection32 != 1.0f) && (res.Projection32 != -1.0f)) 61 | { 62 | // This is a very strange projection matrix, and probably won't work. 63 | // If you need it to work, please contact Oculus and let us know your usage scenario. 64 | } 65 | 66 | if ( ( projectionModFlags & ovrProjection_ClipRangeOpenGL ) != 0 ) 67 | { 68 | // Internally we use the D3D range of [0,+w] not the OGL one of [-w,+w], so we need to convert one to the other. 69 | // Note that the values in the depth buffer, and the actual linear depth we want is the same for both APIs, 70 | // the difference is purely in the values inside the projection matrix. 71 | 72 | // D3D does this: 73 | // depthBuffer = ( ProjD3D.M[2][2] * linearDepth + ProjD3D.M[2][3] ) / ( linearDepth * ProjD3D.M[3][2] ); 74 | // OGL does this: 75 | // depthBuffer = 0.5 + 0.5 * ( ProjOGL.M[2][2] * linearDepth + ProjOGL.M[2][3] ) / ( linearDepth * ProjOGL.M[3][2] ); 76 | 77 | // Therefore: 78 | // ProjD3D.M[2][2] = 0.5 * ( ProjOGL.M[2][2] + ProjOGL.M[3][2] ); 79 | // ProjD3D.M[2][3] = 0.5 * ProjOGL.M[2][3]; 80 | // ProjD3D.M[3][2] = ProjOGL.M[3][2]; 81 | 82 | res.Projection22 = 0.5f * ( Projection.M[2][2] + Projection.M[3][2] ); 83 | res.Projection23 = 0.5f * Projection.M[2][3]; 84 | res.Projection32 = Projection.M[3][2]; 85 | } 86 | return res; 87 | } 88 | 89 | OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_OrthoSubProjection( 90 | ovrMatrix4f projection, ovrVector2f orthoScale, 91 | float orthoDistance, float hmdToEyeOffsetX) 92 | { 93 | ovrMatrix4f ortho; 94 | // Negative sign is correct! 95 | // If the eye is offset to the left, then the ortho view needs to be offset to the right relative to the camera. 96 | float orthoHorizontalOffset = -hmdToEyeOffsetX / orthoDistance; 97 | 98 | /* 99 | // Current projection maps real-world vector (x,y,1) to the RT. 100 | // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to 101 | // the physical [-orthoHalfFov,orthoHalfFov] 102 | // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means 103 | // we don't have to feed in Z=1 all the time. 104 | // The horizontal offset math is a little hinky because the destination is 105 | // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset] 106 | // So we need to first map [-FovPixels/2,FovPixels/2] to 107 | // [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]: 108 | // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset; 109 | // = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset; 110 | // But then we need the same mapping as the existing projection matrix, i.e. 111 | // x2 = x1 * Projection.M[0][0] + Projection.M[0][2]; 112 | // = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2]; 113 | // = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels + 114 | // orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2]; 115 | // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and 116 | // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2]. 117 | */ 118 | 119 | ortho.M[0][0] = projection.M[0][0] * orthoScale.x; 120 | ortho.M[0][1] = 0.0f; 121 | ortho.M[0][2] = 0.0f; 122 | ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] ); 123 | 124 | ortho.M[1][0] = 0.0f; 125 | ortho.M[1][1] = -projection.M[1][1] * orthoScale.y; /* Note sign flip (text rendering uses Y=down). */ 126 | ortho.M[1][2] = 0.0f; 127 | ortho.M[1][3] = -projection.M[1][2]; 128 | 129 | ortho.M[2][0] = 0.0f; 130 | ortho.M[2][1] = 0.0f; 131 | ortho.M[2][2] = 0.0f; 132 | ortho.M[2][3] = 0.0f; 133 | 134 | /* No perspective correction for ortho. */ 135 | ortho.M[3][0] = 0.0f; 136 | ortho.M[3][1] = 0.0f; 137 | ortho.M[3][2] = 0.0f; 138 | ortho.M[3][3] = 1.0f; 139 | 140 | return ortho; 141 | } 142 | 143 | 144 | OVR_PUBLIC_FUNCTION(void) ovr_CalcEyePoses(ovrPosef headPose, 145 | const ovrVector3f hmdToEyeOffset[2], 146 | ovrPosef outEyePoses[2]) 147 | { 148 | if (!hmdToEyeOffset || !outEyePoses) 149 | { 150 | return; 151 | } 152 | 153 | using OVR::Posef; 154 | using OVR::Vector3f; 155 | 156 | // Currently hmdToEyeOffset is only a 3D vector 157 | outEyePoses[0] = Posef(headPose.Orientation, ((Posef)headPose).Apply((Vector3f)hmdToEyeOffset[0])); 158 | outEyePoses[1] = Posef(headPose.Orientation, ((Posef)headPose).Apply((Vector3f)hmdToEyeOffset[1])); 159 | } 160 | 161 | 162 | OVR_PUBLIC_FUNCTION(void) ovr_GetEyePoses(ovrSession session, long long frameIndex, ovrBool latencyMarker, 163 | const ovrVector3f hmdToEyeOffset[2], 164 | ovrPosef outEyePoses[2], 165 | double* outSensorSampleTime) 166 | { 167 | double frameTime = ovr_GetPredictedDisplayTime(session, frameIndex); 168 | ovrTrackingState trackingState = ovr_GetTrackingState(session, frameTime, latencyMarker); 169 | ovr_CalcEyePoses(trackingState.HeadPose.ThePose, hmdToEyeOffset, outEyePoses); 170 | 171 | if (outSensorSampleTime != nullptr) 172 | { 173 | *outSensorSampleTime = ovr_GetTimeInSeconds(); 174 | } 175 | } 176 | 177 | OVR_PUBLIC_FUNCTION(ovrDetectResult) ovr_Detect(int timeoutMilliseconds) 178 | { 179 | // Initially we assume everything is not running. 180 | ovrDetectResult result; 181 | result.IsOculusHMDConnected = ovrFalse; 182 | result.IsOculusServiceRunning = ovrFalse; 183 | 184 | #if defined(_WIN32) 185 | // Attempt to open the named event. 186 | HANDLE hServiceEvent = ::OpenEventW(SYNCHRONIZE, FALSE, OVR_HMD_CONNECTED_EVENT_NAME); 187 | 188 | // If event exists, 189 | if (hServiceEvent != nullptr) 190 | { 191 | // This indicates that the Oculus Runtime is installed and running. 192 | result.IsOculusServiceRunning = ovrTrue; 193 | 194 | // Poll for event state. 195 | DWORD objectResult = ::WaitForSingleObject(hServiceEvent, timeoutMilliseconds); 196 | 197 | // If the event is signaled, 198 | if (objectResult == WAIT_OBJECT_0) 199 | { 200 | // This indicates that the Oculus HMD is connected. 201 | result.IsOculusHMDConnected = ovrTrue; 202 | } 203 | 204 | ::CloseHandle(hServiceEvent); 205 | } 206 | #endif // _WIN32 207 | 208 | 209 | return result; 210 | } 211 | 212 | OVR_PUBLIC_FUNCTION(void) ovrPosef_FlipHandedness(const ovrPosef* inPose, ovrPosef* outPose) 213 | { 214 | outPose->Orientation.x = -inPose->Orientation.x; 215 | outPose->Orientation.y = inPose->Orientation.y; 216 | outPose->Orientation.z = inPose->Orientation.z; 217 | outPose->Orientation.w = -inPose->Orientation.w; 218 | 219 | outPose->Position.x = -inPose->Position.x; 220 | outPose->Position.y = inPose->Position.y; 221 | outPose->Position.z = inPose->Position.z; 222 | } 223 | -------------------------------------------------------------------------------- /LibOVR/Src/OVR_StereoProjection.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************************ 2 | 3 | Filename : OVR_StereoProjection.cpp 4 | Content : Stereo rendering functions 5 | Created : November 30, 2013 6 | Authors : Tom Fosyth 7 | 8 | Copyright : Copyright 2014-2016 Oculus VR, LLC All Rights reserved. 9 | 10 | Licensed under the Oculus VR Rift SDK License Version 3.3 (the "License"); 11 | you may not use the Oculus VR Rift SDK except in compliance with the License, 12 | which is provided at the time of installation or download, or which 13 | otherwise accompanies this software in either electronic or hard copy form. 14 | 15 | You may obtain a copy of the License at 16 | 17 | http://www.oculusvr.com/licenses/LICENSE-3.3 18 | 19 | Unless required by applicable law or agreed to in writing, the Oculus VR SDK 20 | distributed under the License is distributed on an "AS IS" BASIS, 21 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | See the License for the specific language governing permissions and 23 | limitations under the License. 24 | 25 | *************************************************************************************/ 26 | 27 | #include 28 | 29 | 30 | namespace OVR { 31 | 32 | 33 | ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort tanHalfFov ) 34 | { 35 | float projXScale = 2.0f / ( tanHalfFov.LeftTan + tanHalfFov.RightTan ); 36 | float projXOffset = ( tanHalfFov.LeftTan - tanHalfFov.RightTan ) * projXScale * 0.5f; 37 | float projYScale = 2.0f / ( tanHalfFov.UpTan + tanHalfFov.DownTan ); 38 | float projYOffset = ( tanHalfFov.UpTan - tanHalfFov.DownTan ) * projYScale * 0.5f; 39 | 40 | ScaleAndOffset2D result; 41 | result.Scale = Vector2f(projXScale, projYScale); 42 | result.Offset = Vector2f(projXOffset, projYOffset); 43 | // Hey - why is that Y.Offset negated? 44 | // It's because a projection matrix transforms from world coords with Y=up, 45 | // whereas this is from NDC which is Y=down. 46 | 47 | return result; 48 | } 49 | 50 | 51 | 52 | Matrix4f CreateProjection( bool leftHanded, bool isOpenGL, FovPort tanHalfFov, StereoEye /*eye*/, 53 | float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/, 54 | bool flipZ /*= false*/, bool farAtInfinity /*= false*/) 55 | { 56 | if(!flipZ && farAtInfinity) 57 | { 58 | //OVR_ASSERT_M(false, "Cannot push Far Clip to Infinity when Z-order is not flipped"); Assertion disabled because this code no longer has access to LibOVRKernel assertion functionality. 59 | farAtInfinity = false; 60 | } 61 | 62 | // A projection matrix is very like a scaling from NDC, so we can start with that. 63 | ScaleAndOffset2D scaleAndOffset = CreateNDCScaleAndOffsetFromFov ( tanHalfFov ); 64 | 65 | float handednessScale = leftHanded ? 1.0f : -1.0f; 66 | 67 | Matrix4f projection; 68 | // Produces X result, mapping clip edges to [-w,+w] 69 | projection.M[0][0] = scaleAndOffset.Scale.x; 70 | projection.M[0][1] = 0.0f; 71 | projection.M[0][2] = handednessScale * scaleAndOffset.Offset.x; 72 | projection.M[0][3] = 0.0f; 73 | 74 | // Produces Y result, mapping clip edges to [-w,+w] 75 | // Hey - why is that YOffset negated? 76 | // It's because a projection matrix transforms from world coords with Y=up, 77 | // whereas this is derived from an NDC scaling, which is Y=down. 78 | projection.M[1][0] = 0.0f; 79 | projection.M[1][1] = scaleAndOffset.Scale.y; 80 | projection.M[1][2] = handednessScale * -scaleAndOffset.Offset.y; 81 | projection.M[1][3] = 0.0f; 82 | 83 | // Produces Z-buffer result - app needs to fill this in with whatever Z range it wants. 84 | // We'll just use some defaults for now. 85 | projection.M[2][0] = 0.0f; 86 | projection.M[2][1] = 0.0f; 87 | 88 | if (farAtInfinity) 89 | { 90 | if (isOpenGL) 91 | { 92 | // It's not clear this makes sense for OpenGL - you don't get the same precision benefits you do in D3D. 93 | projection.M[2][2] = -handednessScale; 94 | projection.M[2][3] = 2.0f * zNear; 95 | } 96 | else 97 | { 98 | projection.M[2][2] = 0.0f; 99 | projection.M[2][3] = zNear; 100 | } 101 | } 102 | else 103 | { 104 | if (isOpenGL) 105 | { 106 | // Clip range is [-w,+w], so 0 is at the middle of the range. 107 | projection.M[2][2] = -handednessScale * (flipZ ? -1.0f : 1.0f) * (zNear + zFar) / (zNear - zFar); 108 | projection.M[2][3] = 2.0f * ((flipZ ? -zFar : zFar) * zNear) / (zNear - zFar); 109 | } 110 | else 111 | { 112 | // Clip range is [0,+w], so 0 is at the start of the range. 113 | projection.M[2][2] = -handednessScale * (flipZ ? -zNear : zFar) / (zNear - zFar); 114 | projection.M[2][3] = ((flipZ ? -zFar : zFar) * zNear) / (zNear - zFar); 115 | } 116 | } 117 | 118 | // Produces W result (= Z in) 119 | projection.M[3][0] = 0.0f; 120 | projection.M[3][1] = 0.0f; 121 | projection.M[3][2] = handednessScale; 122 | projection.M[3][3] = 0.0f; 123 | 124 | return projection; 125 | } 126 | 127 | 128 | Matrix4f CreateOrthoSubProjection ( bool /*rightHanded*/, StereoEye eyeType, 129 | float tanHalfFovX, float tanHalfFovY, 130 | float unitsX, float unitsY, 131 | float distanceFromCamera, float interpupillaryDistance, 132 | Matrix4f const &projection, 133 | float zNear /*= 0.0f*/, float zFar /*= 0.0f*/, 134 | bool flipZ /*= false*/, bool farAtInfinity /*= false*/) 135 | { 136 | if(!flipZ && farAtInfinity) 137 | { 138 | //OVR_ASSERT_M(false, "Cannot push Far Clip to Infinity when Z-order is not flipped"); Assertion disabled because this code no longer has access to LibOVRKernel assertion functionality. 139 | farAtInfinity = false; 140 | } 141 | 142 | float orthoHorizontalOffset = interpupillaryDistance * 0.5f / distanceFromCamera; 143 | switch ( eyeType ) 144 | { 145 | case StereoEye_Left: 146 | break; 147 | case StereoEye_Right: 148 | orthoHorizontalOffset = -orthoHorizontalOffset; 149 | break; 150 | case StereoEye_Center: 151 | orthoHorizontalOffset = 0.0f; 152 | break; 153 | default: 154 | break; 155 | } 156 | 157 | // Current projection maps real-world vector (x,y,1) to the RT. 158 | // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to 159 | // the physical [-orthoHalfFov,orthoHalfFov] 160 | // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means 161 | // we don't have to feed in Z=1 all the time. 162 | // The horizontal offset math is a little hinky because the destination is 163 | // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset] 164 | // So we need to first map [-FovPixels/2,FovPixels/2] to 165 | // [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]: 166 | // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset; 167 | // = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset; 168 | // But then we need the sam mapping as the existing projection matrix, i.e. 169 | // x2 = x1 * Projection.M[0][0] + Projection.M[0][2]; 170 | // = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2]; 171 | // = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels + 172 | // orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2]; 173 | // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and 174 | // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2]. 175 | 176 | float orthoScaleX = 2.0f * tanHalfFovX / unitsX; 177 | float orthoScaleY = 2.0f * tanHalfFovY / unitsY; 178 | Matrix4f ortho; 179 | ortho.M[0][0] = projection.M[0][0] * orthoScaleX; 180 | ortho.M[0][1] = 0.0f; 181 | ortho.M[0][2] = 0.0f; 182 | ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] ); 183 | 184 | ortho.M[1][0] = 0.0f; 185 | ortho.M[1][1] = -projection.M[1][1] * orthoScaleY; // Note sign flip (text rendering uses Y=down). 186 | ortho.M[1][2] = 0.0f; 187 | ortho.M[1][3] = -projection.M[1][2]; 188 | 189 | const float zDiff = zNear - zFar; 190 | if (fabsf(zDiff) < 0.001f) 191 | { 192 | ortho.M[2][0] = 0.0f; 193 | ortho.M[2][1] = 0.0f; 194 | ortho.M[2][2] = 0.0f; 195 | ortho.M[2][3] = flipZ ? zNear : zFar; 196 | } 197 | else 198 | { 199 | ortho.M[2][0] = 0.0f; 200 | ortho.M[2][1] = 0.0f; 201 | 202 | if(farAtInfinity) 203 | { 204 | ortho.M[2][2] = 0.0f; 205 | ortho.M[2][3] = zNear; 206 | } 207 | else if (zDiff != 0.0f) 208 | { 209 | ortho.M[2][2] = (flipZ ? zNear : zFar) / zDiff; 210 | ortho.M[2][3] = ((flipZ ? -zFar : zFar) * zNear) / zDiff; 211 | } 212 | } 213 | 214 | // No perspective correction for ortho. 215 | ortho.M[3][0] = 0.0f; 216 | ortho.M[3][1] = 0.0f; 217 | ortho.M[3][2] = 0.0f; 218 | ortho.M[3][3] = 1.0f; 219 | 220 | return ortho; 221 | } 222 | 223 | 224 | 225 | } //namespace OVR 226 | 227 | 228 | -------------------------------------------------------------------------------- /LibOVR/Src/Resources/Windows/LibOVR.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/LibOVR/Src/Resources/Windows/LibOVR.rc -------------------------------------------------------------------------------- /LibOVR/Src/Resources/Windows/Oculus.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/LibOVR/Src/Resources/Windows/Oculus.ico -------------------------------------------------------------------------------- /LibOVR/Src/Resources/Windows/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/LibOVR/Src/Resources/Windows/resource.h -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Cinder-OculusRift 2 | ================== 3 | 4 | This is yet another Oculus Rift block for Cinder, and a collaboration between [Paul Houx](https://github.com/paulhoux) & myself. *Thanks Paul for all the initial work!* 5 | 6 | Samples 7 | ----------------- 8 | * Basic Sample: Features the standard use case scenario, with all the most common functionalities. 9 | ![BasicSample](https://dl.dropboxusercontent.com/u/29102565/oculus/basicsample.png) 10 | 11 | * Spherical Stereo: Maps a sample Arnold 360 texture to a sphere, in stereo. Useful for both live-action & pre-rendered CG content. 12 | ![SphericalStereo](https://dl.dropboxusercontent.com/u/29102565/oculus/sphericalstereo.png) 13 | 14 | * Instanced Stereo: Similar to the Basic Sample, only it uses instanced stereo rendering as described [here](https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/edit). 15 | 16 | Usage 17 | ----------------- 18 | First, initialize the rift manager in prepareSettings. 19 | 20 | ``` 21 | hmd::RiftManager::initialize(); 22 | ``` 23 | 24 | Create an Oculus Rift instance: 25 | ``` 26 | hmd::OculusRiftRef mRift; 27 | ... 28 | mRift = hmd::OculusRift::create(); 29 | ``` 30 | 31 | The OculusRift class has two cameras: a convenience host camera controlling the overall head position & orientation, and an active eye camera which is updated by the SDK according to the tracked position & orientation. Their transformations are composed and can be queried via the `hmd::OculusRift` interface. 32 | 33 | 34 | In the draw() loop, call bind to render the scene to the rift's framebuffers. Iterate over each eye, drawing your scene as follows: 35 | ``` 36 | hmd::ScopedRiftBuffer bind{ mRift }; 37 | ... 38 | for( auto eye : mRift.getEyes() ) { 39 | mRift.enableEye( eye ); 40 | drawScene(); 41 | } 42 | ``` 43 | 44 | To avoid judder, make sure you hit **90fps** for the CV1 and **75fps** for the DK2! 45 | 46 | 47 | -------------------------------------------------------------------------------- /cinderblock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/cinderblock.png -------------------------------------------------------------------------------- /cinderblock.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | include 15 | LibOVR/Include 16 | 17 |
include/CinderOculus.h
18 | include/CinderOculus.cpp 19 | 20 | 21 | LibOVR/Lib/Windows/$(Platform)/$(Configuration)/VS2013/LibOVR.lib 22 | 23 | 24 | LibOVR/Lib/Mac/Release/LibOVR.framework 25 | 26 |
27 |
28 | -------------------------------------------------------------------------------- /include/CinderOculus.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2015 4 | * Paul Houx - The Barbarian Group 5 | * Eric Renaud-Houde - Moving Picture Company / The Mill 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or 9 | * without modification, are permitted provided that the following 10 | * conditions are met: 11 | * 12 | * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in 16 | * the documentation and/or other materials provided with the 17 | * distribution. 18 | * 19 | * Neither the name of the Paul Houx/Eric Renaud-Houde nor the names of its 20 | * contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | */ 38 | 39 | #include "CinderOculus.h" 40 | #include "cinder/Log.h" 41 | #include "cinder/app/App.h" 42 | #include "cinder/Utilities.h" 43 | #include "cinder/Breakpoint.h" 44 | 45 | using namespace ci; 46 | using namespace ci::app; 47 | using namespace hmd; 48 | 49 | PoseState::PoseState( const ovrPoseStatef& ps ) 50 | : position{ fromOvr( ps.ThePose.Position ) } 51 | , orientation{ fromOvr( ps.ThePose.Orientation ) } 52 | , angularVelocity{ fromOvr( ps.AngularVelocity ) } 53 | , angularAcceleration{ fromOvr( ps.AngularAcceleration ) } 54 | , linearVelocity{ fromOvr( ps.LinearVelocity ) } 55 | , linearAcceleration{ fromOvr( ps.LinearAcceleration ) } 56 | , timeInSeconds{ ps.TimeInSeconds } 57 | { 58 | 59 | } 60 | 61 | std::unique_ptr RiftManager::mInstance = nullptr; 62 | std::once_flag RiftManager::mOnceFlag; 63 | 64 | void OVR_VERIFY( const ovrResult& result ) 65 | { 66 | if( ! OVR_SUCCESS( result ) ) { 67 | ovrErrorInfo errorInfo; 68 | ovr_GetLastErrorInfo( &errorInfo ); 69 | throw RiftExeption( errorInfo.ErrorString ); 70 | } 71 | } 72 | 73 | void RiftManager::initialize() 74 | { 75 | std::call_once( mOnceFlag, 76 | [] { 77 | mInstance.reset( new RiftManager ); 78 | } ); 79 | } 80 | 81 | RiftManager::RiftManager() 82 | { 83 | OVR_VERIFY( ovr_Initialize( nullptr ) ); 84 | } 85 | 86 | RiftManager::~RiftManager() 87 | { 88 | ovr_Shutdown(); 89 | } 90 | 91 | OculusRift::Params::Params() 92 | : mHostCam{ false, ci::CameraPersp{} } 93 | , mClipDistance{ false, vec2(-1) } 94 | { 95 | 96 | } 97 | 98 | OculusRiftRef OculusRift::create( const Params& params ) 99 | { 100 | return OculusRiftRef( new OculusRift{ params } ); 101 | } 102 | 103 | OculusRift::OculusRift( const Params& params ) 104 | : mScreenPercentage( params.mScreenPercentage ) 105 | , mIsMirrrored( params.mIsMirrrored ) 106 | , mIsMonoscopic( params.mIsMonoscopic ) 107 | , mUsePositionalTracking( params.mUsePositionalTracking ) 108 | , mFrameIndex( 0 ) 109 | , mSession( nullptr ) 110 | , mMirrorFBO( 0 ) 111 | , mMirrorTexture( nullptr ) 112 | , mIsVisible( true ) 113 | , mPerfHudMode( 0 ) 114 | , mSensorSampleTime( 0 ) 115 | { 116 | if( params.mHostCam.first ) { 117 | mHostCamera = params.mHostCam.second; 118 | } 119 | else { 120 | mHostCamera.setEyePoint( vec3( 0 ) ); 121 | mHostCamera.setViewDirection( vec3( 0, 0, -1 ) ); 122 | } 123 | 124 | if( params.mClipDistance.first ) { 125 | mEyeCamera.setNearClip( params.mClipDistance.second.x ); 126 | mEyeCamera.setFarClip( params.mClipDistance.second.y ); 127 | } 128 | 129 | ovrGraphicsLuid luid; //can't use in opengl 130 | OVR_VERIFY( ovr_Create( &mSession, &luid ) ); 131 | mHmdDesc = ovr_GetHmdDesc( mSession ); 132 | 133 | for( int i = 0; i < ovrEye_Count; ++i ) { 134 | mEyeRenderDesc[i] = ovr_GetRenderDesc( mSession, (ovrEyeType)i, mHmdDesc.DefaultEyeFov[i] ); 135 | } 136 | 137 | initializeFrameBuffer(); 138 | updateEyeOffset(); 139 | app::getWindow()->getSignalResize().connect( [this](){ 140 | initializeMirrorTexture( app::getWindowSize() ); 141 | } ); 142 | 143 | //ovr_SetTrackingOriginType( mSession, ovrTrackingOrigin_EyeLevel ); 144 | 145 | if( app::App::get()->isFrameRateEnabled() ) { 146 | CI_LOG_I( "Disabled framerate for better performance." ); 147 | app::App::get()->disableFrameRate(); 148 | } 149 | 150 | if( gl::isVerticalSyncEnabled() ) { 151 | CI_LOG_I( "Disabled vertical sync: handled by compositor service." ); 152 | gl::enableVerticalSync( false ); 153 | } 154 | } 155 | 156 | OculusRift::~OculusRift() 157 | { 158 | //To prevent SDK bug(?) where perf hud state is maintained by the runtime 159 | cyclePerfHudModes( false ); 160 | 161 | if( mMirrorTexture ) 162 | destroyMirrorTexture(); 163 | 164 | mRenderBuffer.reset(); 165 | mDepthBuffer.reset(); 166 | 167 | if( mSession ) 168 | ovr_Destroy( mSession ); 169 | 170 | mSession = nullptr; 171 | } 172 | 173 | void OculusRift::initializeMirrorTexture( const glm::ivec2& size ) 174 | { 175 | if( mMirrorTexture ) 176 | destroyMirrorTexture(); 177 | 178 | ovrMirrorTextureDesc desc; 179 | memset( &desc, 0, sizeof( desc ) ); 180 | desc.Width = size.x; 181 | desc.Height = size.y; 182 | desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; 183 | 184 | // Create mirror texture and an FBO used to copy mirror texture to back buffer 185 | ovrResult result = ovr_CreateMirrorTextureGL( mSession, &desc, &mMirrorTexture ); 186 | if( ! OVR_SUCCESS( result ) ) { 187 | CI_LOG_E( "Failed to create mirror texture." ); 188 | } 189 | 190 | // Configure the mirror read buffer 191 | GLuint texId; 192 | ovr_GetMirrorTextureBufferGL( mSession, mMirrorTexture, &texId ); 193 | 194 | glGenFramebuffers( 1, &mMirrorFBO ); 195 | glBindFramebuffer( GL_READ_FRAMEBUFFER, mMirrorFBO ); 196 | glFramebufferTexture2D( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0 ); 197 | glFramebufferRenderbuffer( GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0 ); 198 | glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); 199 | } 200 | 201 | void OculusRift::destroyMirrorTexture() 202 | { 203 | if( mMirrorFBO ) 204 | glDeleteFramebuffers( 1, &mMirrorFBO ); 205 | if( mMirrorTexture ) 206 | ovr_DestroyMirrorTexture( mSession, mMirrorTexture ); 207 | } 208 | 209 | void OculusRift::initializeFrameBuffer() 210 | { 211 | auto size = mScreenPercentage * vec2( fromOvr( mHmdDesc.Resolution ) ); 212 | mRenderBuffer = std::unique_ptr( new TextureBuffer( mSession, size, 1, 1 ) ); 213 | mDepthBuffer = std::unique_ptr( new DepthBuffer( size, 0 ) ); 214 | 215 | if( ! mRenderBuffer->mTextureChain ) { 216 | CI_LOG_E( "Failed to create texture." ); 217 | } 218 | } 219 | 220 | void OculusRift::bind() 221 | { 222 | ovr_GetEyePoses( mSession, mFrameIndex, ovrTrue, mEyeViewOffset, mEyeRenderPose, &mSensorSampleTime ); 223 | 224 | if( mRenderBuffer && mIsVisible ) { 225 | mRenderBuffer->setAndClearRenderSurface( mDepthBuffer.get() ); 226 | } 227 | } 228 | 229 | void OculusRift::enableEye( int eyeIndex, bool applyMatrices ) 230 | { 231 | mEye = static_cast( eyeIndex ); 232 | 233 | if( isPositionalTrackingEnabled() ) { 234 | mEyeCamera.setEyePoint( fromOvr( mEyeRenderPose[mEye].Position ) ); 235 | } 236 | else { 237 | mEyeCamera.setEyePoint( vec3(0.0) ); 238 | } 239 | mEyeCamera.setOrientation( fromOvr( mEyeRenderPose[mEye].Orientation ) ); 240 | mEyeCamera.mOvrProjection = fromOvr( ovrMatrix4f_Projection( mEyeRenderDesc[mEye].Fov, mEyeCamera.getNearClip(), mEyeCamera.getFarClip(), ovrProjection_None ) ); 241 | 242 | if( applyMatrices ) { 243 | auto area = getEyeViewport( eyeIndex ); 244 | gl::viewport( area.getUL(), area.getSize() ); 245 | gl::setModelMatrix( getModelMatrix() ); 246 | gl::setViewMatrix( getViewMatrix() ); 247 | gl::setProjectionMatrix( mEyeCamera.mOvrProjection ); 248 | } 249 | } 250 | 251 | void OculusRift::unbind() 252 | { 253 | if( mRenderBuffer && mIsVisible ) { 254 | mRenderBuffer->unsetRenderSurface(); 255 | mRenderBuffer->commit(); 256 | } 257 | 258 | submitFrame(); 259 | } 260 | 261 | void OculusRift::submitFrame() 262 | { 263 | // Set up positional data. 264 | ovrViewScaleDesc viewScaleDesc; 265 | viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; 266 | 267 | mBaseLayer.Header.Type = ovrLayerType_EyeFov; 268 | mBaseLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; 269 | mBaseLayer.SensorSampleTime = mSensorSampleTime; 270 | for( auto eye : getEyes() ) { 271 | viewScaleDesc.HmdToEyeOffset[eye] = mEyeViewOffset[eye]; 272 | mBaseLayer.Fov[eye] = mEyeRenderDesc[eye].Fov; 273 | mBaseLayer.RenderPose[eye] = mEyeRenderPose[eye]; 274 | auto area = getEyeViewport( eye ); 275 | auto sz = area.getSize(); 276 | mBaseLayer.Viewport[eye] = { { area.x1, area.y1 }, { sz.x, sz.y } }; 277 | } 278 | mBaseLayer.ColorTexture[0] = mRenderBuffer->mTextureChain; 279 | mBaseLayer.ColorTexture[1] = NULL; 280 | 281 | 282 | ovrLayerHeader* layers = &mBaseLayer.Header; 283 | auto result = ovr_SubmitFrame( mSession, mFrameIndex, &viewScaleDesc, &layers, 1 ); 284 | mIsVisible = (result == ovrSuccess); 285 | 286 | if( mMirrorTexture && isMirrored() ) { 287 | // Blit mirror texture to back buffer 288 | glBindFramebuffer( GL_READ_FRAMEBUFFER, mMirrorFBO ); 289 | glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); 290 | GLint w = app::getWindowWidth(); 291 | GLint h = app::getWindowHeight(); 292 | glBlitFramebuffer( 0, h, w, 0, 293 | 0, 0, w, h, 294 | GL_COLOR_BUFFER_BIT, GL_NEAREST ); 295 | glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); 296 | } 297 | 298 | ++mFrameIndex; 299 | } 300 | 301 | 302 | std::list OculusRift::getEyes() const 303 | { 304 | if( mSession && mIsVisible ) 305 | return { ovrEye_Left, ovrEye_Right }; 306 | 307 | return {}; 308 | } 309 | 310 | Area OculusRift::getEyeViewport( int eyeIndex ) const 311 | { 312 | auto size = mRenderBuffer->getSize(); 313 | if( eyeIndex == 0 ) { 314 | return Area{ 0, 0, size.x / 2, size.y }; 315 | } 316 | return Area{ ( size.x + 1) / 2, 0, size.x, size.y }; 317 | } 318 | 319 | glm::mat4 OculusRift::getModelMatrix() const 320 | { 321 | return mHostCamera.getViewMatrix(); 322 | } 323 | 324 | glm::mat4 OculusRift::getViewMatrix() const 325 | { 326 | return mEyeCamera.getViewMatrix(); 327 | } 328 | 329 | glm::mat4 OculusRift::getProjectionMatrix() const 330 | { 331 | return mEyeCamera.mOvrProjection; 332 | } 333 | 334 | void OculusRift::enableMonoscopic( bool enabled ) 335 | { 336 | mIsMonoscopic = enabled; 337 | updateEyeOffset(); 338 | } 339 | 340 | void OculusRift::updateEyeOffset() 341 | { 342 | if( isMonoscopic() ) { 343 | auto centerEyeOffset = 0.5f * ( fromOvr( mEyeRenderDesc[0].HmdToEyeOffset ) + fromOvr( mEyeRenderDesc[1].HmdToEyeOffset ) ); 344 | mEyeViewOffset[0] = toOvr( centerEyeOffset ); 345 | mEyeViewOffset[1] = toOvr( centerEyeOffset ); 346 | } 347 | else { 348 | mEyeViewOffset[0] = mEyeRenderDesc[0].HmdToEyeOffset; 349 | mEyeViewOffset[1] = mEyeRenderDesc[1].HmdToEyeOffset; 350 | } 351 | } 352 | 353 | void OculusRift::recenterPose() 354 | { 355 | ovr_RecenterTrackingOrigin( mSession ); 356 | } 357 | 358 | bool OculusRift::getPositionalTrackingCamera( CameraPersp* positional ) const 359 | { 360 | ovrTrackingState ts = ovr_GetTrackingState( mSession, 0.0f, ovrFalse ); 361 | if( isTracked( ts ) ) { 362 | 363 | ovrTrackerDesc td = ovr_GetTrackerDesc( mSession, 0 ); 364 | ovrTrackerPose tp = ovr_GetTrackerPose( mSession, 0 ); 365 | 366 | float aspectRatio = abs( tan( 0.5f * td.FrustumHFovInRadians ) / tan( 0.5f * td.FrustumVFovInRadians ) ); 367 | positional->setPerspective( toDegrees( td.FrustumVFovInRadians ), 368 | aspectRatio, 369 | - td.FrustumFarZInMeters, 370 | - td.FrustumFarZInMeters ); 371 | positional->setOrientation( fromOvr( tp.Pose.Orientation ) ); 372 | positional->setEyePoint( fromOvr( tp.Pose.Position ) ); 373 | return true; 374 | } 375 | return false; 376 | } 377 | 378 | bool OculusRift::getHandPose( int handIndex, PoseState* ps ) const 379 | { 380 | ovrTrackingState ts = ovr_GetTrackingState( mSession, 0.0f, ovrFalse ); 381 | ovrHandType hi = static_cast( handIndex ); 382 | if( (ts.HandStatusFlags[hi] & ovrStatus_OrientationTracked) && (ts.HandStatusFlags[hi] & ovrStatus_PositionTracked) ) { 383 | *ps = PoseState{ ts.HandPoses[hi] }; 384 | return true; 385 | } 386 | return false; 387 | } 388 | 389 | glm::vec3 OculusRift::getLatencies() const 390 | { 391 | float latencies[3] = { 0.0f, 0.0f, 0.0f }; 392 | if( ovr_GetFloatArray( mSession, "DK2Latency", latencies, 3 ) == 3 ) { 393 | return 1000.0f * glm::vec3( latencies[0], latencies[1], latencies[2] ); 394 | } 395 | return glm::vec3( 0 ); 396 | } 397 | 398 | void OculusRift::setScreenPercentage( float sp ) 399 | { 400 | CI_ASSERT( sp > 0.0f ); 401 | mScreenPercentage = sp; 402 | } 403 | 404 | bool OculusRift::isTracked() const 405 | { 406 | ovrTrackingState ts = ovr_GetTrackingState( mSession, 0.0f, ovrFalse ); 407 | return isTracked( ts ); 408 | } 409 | 410 | bool OculusRift::isTracked( const ovrTrackingState& ts ) const 411 | { 412 | bool tracked = ts.StatusFlags & ovrStatus_PositionTracked; 413 | return tracked && isPositionalTrackingEnabled(); 414 | } 415 | 416 | void OculusRift::cyclePerfHudModes( bool enabled ) 417 | { 418 | mPerfHudMode = ( enabled ) ? (++mPerfHudMode) % int(ovrPerfHud_Count) : 0; 419 | ovr_SetInt( mSession, OVR_PERF_HUD_MODE, mPerfHudMode ); 420 | } 421 | 422 | bool OculusRift::isMirrored() const 423 | { 424 | return mIsMirrrored; 425 | } 426 | 427 | void OculusRift::enableMirrored( bool enabled ) 428 | { 429 | if( mIsMirrrored != enabled ) { 430 | mIsMirrrored = enabled; 431 | } 432 | } 433 | 434 | ScopedRiftBuffer::ScopedRiftBuffer( const OculusRiftRef& rift ) 435 | : mRift( rift.get() ) 436 | { 437 | mRift->bind(); 438 | } 439 | 440 | ScopedRiftBuffer::~ScopedRiftBuffer() 441 | { 442 | mRift->unbind(); 443 | } 444 | 445 | 446 | -------------------------------------------------------------------------------- /include/CinderOculus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2015 4 | * Paul Houx - The Barbarian Group 5 | * Eric Renaud-Houde - Moving Picture Company / The Mill 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or 9 | * without modification, are permitted provided that the following 10 | * conditions are met: 11 | * 12 | * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in 16 | * the documentation and/or other materials provided with the 17 | * distribution. 18 | * 19 | * Neither the name of the Paul Houx/Eric Renaud-Houde nor the names of its 20 | * contributors may be used to endorse or promote products 21 | * derived from this software without specific prior written 22 | * permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | */ 38 | 39 | #pragma once 40 | 41 | #include "cinder/app/RendererGl.h" 42 | #include "cinder/app/Window.h" 43 | #include "cinder/gl/gl.h" 44 | #include "cinder/Camera.h" 45 | #include "cinder/Exception.h" 46 | #include "cinder/Noncopyable.h" 47 | 48 | #include "OVR_CAPI.h" 49 | #include "OVR_CAPI_GL.h" 50 | 51 | #include 52 | #include 53 | #include 54 | 55 | namespace hmd { 56 | 57 | struct PoseState 58 | { 59 | PoseState( const ovrPoseStatef& ps ); 60 | 61 | glm::vec3 position; 62 | glm::quat orientation; 63 | glm::vec3 angularVelocity; 64 | glm::vec3 linearVelocity; 65 | glm::vec3 angularAcceleration; 66 | glm::vec3 linearAcceleration; 67 | double timeInSeconds; 68 | }; 69 | 70 | ///////////////////// CONVERSIONS /////////////////////////// 71 | 72 | inline glm::ivec2 fromOvr( const ovrSizei& v ) 73 | { 74 | // faster than glm::make_* 75 | return glm::ivec2( v.w, v.h ); 76 | } 77 | 78 | inline glm::ivec2 fromOvr( const ovrVector2i& v ) 79 | { 80 | // faster than glm::make_* 81 | return glm::ivec2( v.x, v.y ); 82 | } 83 | 84 | inline glm::vec2 fromOvr( const ovrVector2f& v ) 85 | { 86 | // faster than glm::make_* 87 | return glm::vec2( v.x, v.y ); 88 | } 89 | 90 | inline glm::vec3 fromOvr( const ovrVector3f& v ) 91 | { 92 | // faster than glm::make_* 93 | return glm::vec3( v.x, v.y, v.z ); 94 | } 95 | 96 | inline glm::mat4 fromOvr( const ovrMatrix4f& m ) 97 | { 98 | return glm::transpose( glm::make_mat4( &m.M[0][0] ) ); 99 | } 100 | 101 | inline glm::quat fromOvr( const ovrQuatf& q ) 102 | { 103 | return glm::quat( q.w, q.x, q.y, q.z ); 104 | } 105 | 106 | inline glm::mat4 fromOvr( const ovrPosef& p ) 107 | { 108 | return glm::toMat4( fromOvr( p.Orientation ) ) * glm::translate( fromOvr( p.Position ) ); 109 | } 110 | 111 | inline std::pair fromOvr( const ovrRecti& r ) 112 | { 113 | return std::pair( fromOvr( r.Pos ), fromOvr( r.Size ) ); 114 | } 115 | 116 | inline ovrMatrix4f toOvr( const glm::mat4& m ) 117 | { 118 | ovrMatrix4f result; 119 | glm::mat4 mat = glm::transpose( m ); 120 | memcpy( result.M, &mat, sizeof( glm::mat4 ) ); 121 | return result; 122 | } 123 | 124 | inline ovrVector3f toOvr( const glm::vec3& v ) 125 | { 126 | ovrVector3f result; 127 | result.x = v.x; 128 | result.y = v.y; 129 | result.z = v.z; 130 | return result; 131 | } 132 | 133 | inline ovrVector2f toOvr( const glm::vec2& v ) 134 | { 135 | ovrVector2f result; 136 | result.x = v.x; 137 | result.y = v.y; 138 | return result; 139 | } 140 | 141 | inline ovrSizei toOvr( const glm::ivec2& v ) 142 | { 143 | ovrSizei result; 144 | result.w = v.x; 145 | result.h = v.y; 146 | return result; 147 | } 148 | 149 | inline ovrQuatf toOvr( const glm::quat& q ) 150 | { 151 | ovrQuatf result; 152 | result.x = q.x; 153 | result.y = q.y; 154 | result.z = q.z; 155 | result.w = q.w; 156 | return result; 157 | } 158 | 159 | static const float kLeapToRiftScale = 0.01f; 160 | static const glm::vec3 kLeapToRiftEuler = glm::vec3( -0.5f * (float)M_PI, 0, (float)M_PI ); 161 | 162 | //////////////////////////////////////////////////////////////////////// 163 | 164 | 165 | // TODO: Cinder gl::Fbos currently don't allow for changing the texture attachments at every frame. 166 | // We thus use the provided sample implementation by Oculus. 167 | 168 | //--------------------------------------------------------------------------------------- 169 | struct DepthBuffer 170 | { 171 | GLuint texId; 172 | 173 | DepthBuffer( glm::ivec2 size, int sampleCount ) 174 | { 175 | CI_ASSERT( sampleCount <= 1 ); // The code doesn't currently handle MSAA textures. 176 | 177 | glGenTextures( 1, &texId ); 178 | glBindTexture( GL_TEXTURE_2D, texId ); 179 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 180 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 181 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); 182 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); 183 | glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, size.x, size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL ); 184 | } 185 | 186 | ~DepthBuffer() { 187 | glDeleteTextures( 1, &texId ); 188 | } 189 | }; 190 | 191 | //-------------------------------------------------------------------------- 192 | struct TextureBuffer 193 | { 194 | ovrSession mSession; 195 | ovrTextureSwapChain mTextureChain; 196 | GLuint mTexId; 197 | GLuint mFboId; 198 | glm::ivec2 mSize; 199 | 200 | TextureBuffer( ovrSession session, glm::ivec2 size, int mipLevels, int sampleCount ) 201 | : mSession( session ) 202 | { 203 | CI_ASSERT( sampleCount <= 1 ); // The code doesn't currently handle MSAA textures. 204 | mSize = size; 205 | 206 | // This texture isn't necessarily going to be a rendertarget, but it usually is. 207 | CI_ASSERT( session ); 208 | CI_ASSERT( sampleCount == 1 ); // ovrHmd_CreateSwapTextureSetD3D11 doesn't support MSAA. 209 | 210 | ovrTextureSwapChainDesc desc = {}; 211 | desc.Type = ovrTexture_2D; 212 | desc.ArraySize = 1; 213 | desc.Width = mSize.x; 214 | desc.Height = mSize.y; 215 | desc.MipLevels = 1; 216 | desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; 217 | desc.SampleCount = 1; 218 | desc.StaticImage = ovrFalse; 219 | 220 | ovrResult result = ovr_CreateTextureSwapChainGL( mSession, &desc, &mTextureChain ); 221 | 222 | int length = 0; 223 | ovr_GetTextureSwapChainLength( mSession, mTextureChain, &length ); 224 | CI_ASSERT( result == ovrSuccess ); 225 | 226 | for( int i = 0; i < length; ++i ) { 227 | GLuint chainTexId; 228 | ovr_GetTextureSwapChainBufferGL( mSession, mTextureChain, i, &chainTexId ); 229 | glBindTexture( GL_TEXTURE_2D, chainTexId ); 230 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 231 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 232 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); 233 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); 234 | } 235 | 236 | if( mipLevels > 1 ) { 237 | glGenerateMipmap( GL_TEXTURE_2D ); 238 | } 239 | 240 | glGenFramebuffers( 1, &mFboId ); 241 | } 242 | 243 | ~TextureBuffer() { 244 | if( mTextureChain ) { 245 | ovr_DestroyTextureSwapChain( mSession, mTextureChain ); 246 | mTextureChain = nullptr; 247 | } 248 | if( mTexId ) { 249 | glDeleteTextures( 1, &mTexId ); 250 | mTexId = 0; 251 | } 252 | if( mFboId ) { 253 | glDeleteFramebuffers( 1, &mFboId ); 254 | mFboId = 0; 255 | } 256 | } 257 | 258 | glm::ivec2 getSize() const 259 | { 260 | return mSize; 261 | } 262 | 263 | void setAndClearRenderSurface( DepthBuffer * dbuffer ) 264 | { 265 | GLuint curTexId; 266 | if( mTextureChain ) { 267 | int curIndex; 268 | ovr_GetTextureSwapChainCurrentIndex( mSession, mTextureChain, &curIndex ); 269 | ovr_GetTextureSwapChainBufferGL( mSession, mTextureChain, curIndex, &curTexId ); 270 | } else { 271 | curTexId = mTexId; 272 | } 273 | 274 | glBindFramebuffer( GL_FRAMEBUFFER, mFboId ); 275 | glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0 ); 276 | glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dbuffer->texId, 0 ); 277 | 278 | glViewport( 0, 0, mSize.x, mSize.y ); 279 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 280 | 281 | //glEnable( GL_FRAMEBUFFER_SRGB ); 282 | } 283 | 284 | void unsetRenderSurface() 285 | { 286 | glBindFramebuffer( GL_FRAMEBUFFER, mFboId ); 287 | glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 ); 288 | glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0 ); 289 | } 290 | 291 | void commit() { 292 | if( mTextureChain ) { 293 | ovr_CommitTextureSwapChain( mSession, mTextureChain ); 294 | } 295 | } 296 | }; 297 | 298 | 299 | class OculusRift; 300 | 301 | class RiftManager : public ci::Noncopyable 302 | { 303 | public: 304 | ~RiftManager(); 305 | static void initialize(); 306 | private: 307 | RiftManager(); 308 | static std::once_flag mOnceFlag; 309 | static std::unique_ptr mInstance; 310 | 311 | friend OculusRift; 312 | }; 313 | 314 | typedef std::shared_ptr OculusRiftRef; 315 | 316 | class OculusRift : ci::Noncopyable 317 | { 318 | public: 319 | struct Params { 320 | Params(); 321 | Params& screenPercentage( float sp ) { mScreenPercentage = sp; return *this; } 322 | Params& hostCamera( const ci::CameraPersp& host ) { mHostCam = { true, host }; return *this; } 323 | Params& monoscopic( bool mono ) { mIsMonoscopic = mono; return *this; } 324 | Params& mirrored( bool mirror ) { mIsMirrrored = mirror; return *this; } 325 | Params& clipDistance(float nearClip, float farClip) { mClipDistance = { true, glm::vec2(nearClip, farClip) }; return *this; } 326 | Params& positional( bool tracked ) { mUsePositionalTracking = tracked; return *this; } 327 | private: 328 | std::pair mHostCam; 329 | std::pair mClipDistance; 330 | float mScreenPercentage = 1.3f; 331 | bool mIsMonoscopic = false; 332 | bool mIsMirrrored = true; 333 | bool mUsePositionalTracking = true; 334 | friend OculusRift; 335 | }; 336 | 337 | 338 | static OculusRiftRef create( const Params& params = Params{} ); 339 | ~OculusRift(); 340 | //! Binds the final framebuffer used by the OVR runtime. 341 | void bind(); 342 | //! Unbinds the framebuffer. 343 | void unbind(); 344 | 345 | //! Returns the convenience host camera (base viewpoint position and orientation). 346 | const ci::CameraPersp& getHostCamera() const { return mHostCamera; } 347 | //! Set the base viewpoint position and orientation through the host camera. (Affects the model matrix.) 348 | void setHostCamera( const ci::CameraPersp& camera ) { mHostCamera = camera; } 349 | 350 | //! Enable the current rendered eye, applies the viewport and mvp matrices directly (optionally disabled). 351 | void enableEye( int eyeIndex, bool applyMatrices = true ); 352 | //! Returns the array of eyes indices, in the order dictated by the SDK. 353 | std::list getEyes() const; 354 | 355 | //! Returns the active eye camera. 356 | const ci::CameraPersp& getEyeCamera() const { return mEyeCamera; } 357 | 358 | /*! Re-centers the sensor orientation. 359 | * Normally this will recenter the (x,y,z) translational components and the yaw 360 | * component of orientation. */ 361 | void recenterPose(); 362 | 363 | //! Get DK2 positional tracking camera 364 | bool getPositionalTrackingCamera( ci::CameraPersp* positional ) const; 365 | 366 | //! Get hand pose information if tracked. 367 | bool getHandPose( int handIndex, PoseState* ps ) const; 368 | 369 | //! Get DK2 latencies (render, timewarp, post-present). 370 | glm::vec3 getLatencies() const; 371 | 372 | //! Get frame buffer screen percentage 373 | float getScreenPercentage() const { return mScreenPercentage; } 374 | /* Set frame buffer screen percentage (fbo size / device screen size). 375 | * It is best to use a value >1: downscaling a higher resolution 376 | * render helps minimize aliasing and increases detail. */ 377 | void setScreenPercentage( float sp ); 378 | 379 | //! Returns true if the render is also mirrored on screen. 380 | bool isMirrored() const; 381 | //! Enable mirroring to screen. 382 | void enableMirrored( bool enabled ); 383 | 384 | //! Returns true if monoscopic (no offset between eyes). 385 | bool isMonoscopic() const { return mIsMonoscopic; } 386 | /*! Enabling monoscopic will eliminate offsets between each eye, 387 | * thus eliminating any 3d stereoscopic effect. */ 388 | void enableMonoscopic( bool enabled ); 389 | 390 | //! Updates horizontal offset between the eyes depending on mono vs stereo rendering. 391 | void updateEyeOffset(); 392 | 393 | //! Returns true if the positional tracking translations are applied. 394 | bool isTracked() const; 395 | bool isTracked( const ovrTrackingState& ts ) const; 396 | //! Returns if positional tracking is enabled. 397 | bool isPositionalTrackingEnabled() const { return mUsePositionalTracking; } 398 | //! Enabling the use of positional tracking translations. 399 | void enablePositionalTracking( bool enabled ) { mUsePositionalTracking = enabled; } 400 | //! Cycles through the performance compositor huds. 401 | void cyclePerfHudModes( bool enabled = true ); 402 | 403 | //! Returns the native resolution of the HMD. 404 | glm::ivec2 getNativeHmdResolution() const { return fromOvr( mHmdDesc.Resolution ); } 405 | //! Returns the size of the render target fbo (used by both eyes). 406 | glm::ivec2 getFboSize() const { return mRenderBuffer->getSize(); } 407 | 408 | //! Returns the host camera view matrix, which acts as the rift model matrix. 409 | inline glm::mat4 getModelMatrix() const; 410 | //! Returns the active eye's view matrix. 411 | inline glm::mat4 getViewMatrix() const; 412 | //! Returns the composed host and (active) eye projection matrix. 413 | glm::mat4 getProjectionMatrix() const; 414 | //! Returns the eye viewport. 415 | ci::Area getEyeViewport( int eyeIndex ) const; 416 | 417 | private: 418 | explicit OculusRift( const Params& params ); 419 | 420 | class EyeCamera : public ci::CameraPersp 421 | { 422 | protected: 423 | void calcProjection() const override 424 | { 425 | mProjectionMatrix = mOvrProjection; 426 | mProjectionCached = true; 427 | } 428 | private: 429 | glm::mat4 mOvrProjection; 430 | 431 | friend class OculusRift; 432 | }; 433 | 434 | void initializeFrameBuffer(); 435 | void initializeMirrorTexture( const glm::ivec2& size ); 436 | void destroyMirrorTexture(); 437 | void submitFrame(); 438 | 439 | EyeCamera mEyeCamera; 440 | ci::CameraPersp mHostCamera; 441 | 442 | float mScreenPercentage; 443 | bool mIsMirrrored; 444 | bool mIsMonoscopic; 445 | bool mUsePositionalTracking; 446 | 447 | bool mIsVisible; 448 | 449 | // Oculus Rift SDK 450 | long long mFrameIndex; 451 | ovrSession mSession; 452 | ovrHmdDesc mHmdDesc; 453 | ovrEyeType mEye; 454 | ovrEyeRenderDesc mEyeRenderDesc[ovrEye_Count]; 455 | ovrPosef mEyeRenderPose[ovrEye_Count]; 456 | ovrVector3f mEyeViewOffset[ovrEye_Count]; 457 | ovrLayerEyeFov mBaseLayer; 458 | 459 | std::unique_ptr mRenderBuffer; 460 | std::unique_ptr mDepthBuffer; 461 | 462 | ovrMirrorTexture mMirrorTexture; 463 | GLuint mMirrorFBO; 464 | 465 | double mSensorSampleTime; 466 | 467 | int mPerfHudMode; 468 | }; 469 | 470 | struct ScopedRiftBuffer 471 | { 472 | ScopedRiftBuffer( const OculusRiftRef& rift ); 473 | ~ScopedRiftBuffer(); 474 | private: 475 | OculusRift* mRift; 476 | }; 477 | 478 | class RiftExeption : public ci::Exception { 479 | public: 480 | RiftExeption() { } 481 | RiftExeption( const std::string &description ) : Exception( description ) { } 482 | }; 483 | 484 | } // namespace hmd 485 | -------------------------------------------------------------------------------- /samples/BasicSample/assets/phong.frag: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform vec4 uLightViewPosition; 4 | uniform vec4 uSkyDirection; 5 | 6 | in vec4 vViewPosition; 7 | in vec3 vNormal; 8 | 9 | out vec4 oColor; 10 | 11 | void main( void ) 12 | { 13 | const vec3 matDiffuse = vec3( 1 ); 14 | const vec3 lightDiffuse = vec3( 1 ); 15 | 16 | vec3 V = vViewPosition.xyz; 17 | vec3 N = normalize( vNormal ); 18 | vec3 L = normalize( uLightViewPosition.xyz - V ); 19 | vec3 R = normalize( -reflect( L, N ) ); 20 | 21 | // hemispherical ambient lighting 22 | float hemi = dot( N, uSkyDirection.xyz ) * 0.5 + 0.5; 23 | oColor.rgb = mix( vec3(0), vec3(0.1), hemi ); 24 | 25 | // diffuse lighting 26 | float lambert = max( 0, dot( N, L ) ); 27 | oColor.rgb += lambert * matDiffuse * lightDiffuse; 28 | 29 | // output gamma corrected color 30 | oColor.rgb = sqrt( oColor.rgb ); 31 | oColor.a = 1; 32 | } -------------------------------------------------------------------------------- /samples/BasicSample/assets/phong.vert: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform mat4 ciModelViewProjection; 4 | uniform mat4 ciModelView; 5 | uniform mat3 ciNormalMatrix; 6 | 7 | in vec4 ciPosition; 8 | in vec3 ciNormal; 9 | 10 | out vec4 vViewPosition; 11 | out vec3 vNormal; 12 | 13 | void main( void ) 14 | { 15 | vViewPosition = ciModelView * ciPosition; 16 | vNormal = ciNormalMatrix * ciNormal; 17 | gl_Position = ciModelViewProjection * ciPosition; 18 | } -------------------------------------------------------------------------------- /samples/BasicSample/include/Resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/CinderResources.h" 3 | 4 | //#define RES_MY_RES CINDER_RESOURCE( ../resources/, image_name.png, 128, IMAGE ) 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /samples/BasicSample/resources/CinderApp.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/BasicSample/resources/CinderApp.icns -------------------------------------------------------------------------------- /samples/BasicSample/resources/cinder_app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/BasicSample/resources/cinder_app_icon.ico -------------------------------------------------------------------------------- /samples/BasicSample/src/BasicSampleApp.cpp: -------------------------------------------------------------------------------- 1 | #include "cinder/app/App.h" 2 | #include "cinder/app/RendererGl.h" 3 | #include "cinder/gl/gl.h" 4 | #include "cinder/gl/Batch.h" 5 | #include "cinder/gl/Context.h" 6 | #include "cinder/Log.h" 7 | #include "cinder/CameraUi.h" 8 | #include "cinder/Utilities.h" 9 | 10 | #include "CinderOculus.h" 11 | 12 | using namespace ci; 13 | using namespace ci::app; 14 | using namespace std; 15 | using namespace hmd; 16 | 17 | class BasicSampleApp : public App { 18 | public: 19 | BasicSampleApp(); 20 | 21 | void update() override; 22 | void draw() override; 23 | void resize() override; 24 | 25 | void keyDown( KeyEvent event ) override; 26 | private: 27 | void drawScene(); 28 | double mTime; 29 | 30 | CameraPersp mCamera; 31 | CameraUi mCameraUi; 32 | OculusRiftRef mRift; 33 | 34 | gl::GlslProgRef mShader; 35 | gl::BatchRef mTeapot; 36 | 37 | vec3 mViewerPosition; 38 | vec4 mLightWorldPosition; 39 | }; 40 | 41 | BasicSampleApp::BasicSampleApp() 42 | : mViewerPosition{ vec3( 0, 0, 1 ) } 43 | , mCameraUi( &mCamera, app::getWindow() ) 44 | { 45 | mShader = gl::GlslProg::create( gl::GlslProg::Format().vertex( loadAsset( "phong.vert" ) ).fragment( loadAsset( "phong.frag" ) ) ); 46 | mTeapot = gl::Batch::create( geom::Teapot().subdivisions( 12 ), mShader ); 47 | 48 | // Setup camera for the debug (main) window. 49 | mCamera.setEyePoint( vec3( 0, 2, 5 ) ); 50 | mCamera.lookAt( vec3( 0 ) ); 51 | mCamera.setFov( 45.0f ); 52 | 53 | gl::disableAlphaBlending(); 54 | gl::enableDepthRead(); 55 | gl::enableDepthWrite(); 56 | gl::color( Color::white() ); 57 | 58 | try { 59 | mRift = OculusRift::create(); 60 | } 61 | catch( const RiftExeption& exc ) { 62 | CI_LOG_EXCEPTION( "Failed rift initialization.", exc ); 63 | } 64 | } 65 | 66 | void BasicSampleApp::update() 67 | { 68 | // Animate light position. 69 | mTime = getElapsedSeconds(); 70 | float t = float( mTime ) * 0.4f; 71 | mLightWorldPosition = vec4( math::sin( t ), math::sin( t * 4.0f ), math::cos( t ), 1 ); 72 | 73 | // Move head location 74 | if( mRift ) { 75 | auto host = mRift->getHostCamera(); 76 | host.setEyePoint( mViewerPosition + vec3( 0.5f * sin( app::getElapsedSeconds() ), 0, 0 ) ); 77 | host.lookAt( vec3( 0 ) ); 78 | mRift->setHostCamera( host ); 79 | } 80 | } 81 | 82 | void BasicSampleApp::drawScene() 83 | { 84 | { 85 | gl::ScopedModelMatrix push; 86 | gl::rotate( (float)mTime, vec3( -0.3f, -1.0f, 0.2f ) ); 87 | gl::scale( vec3( 0.5f ) ); 88 | gl::translate( 0.0f, -0.5f, 0.0f ); 89 | mTeapot->draw(); 90 | } 91 | 92 | gl::lineWidth( 3.0f ); 93 | gl::drawCoordinateFrame( 2 ); 94 | gl::drawSphere( vec3( mLightWorldPosition ), 0.05f, 36 ); 95 | } 96 | 97 | void BasicSampleApp::draw() 98 | { 99 | gl::clear( Color( 0.02, 0.02, 0.1 ) ); 100 | if( mRift ) { 101 | ScopedRiftBuffer bind{ mRift }; 102 | 103 | for( auto eye : mRift->getEyes() ) { 104 | mRift->enableEye( eye ); 105 | mShader->uniform( "uLightViewPosition", mRift->getViewMatrix() * mLightWorldPosition ); 106 | mShader->uniform( "uSkyDirection", mRift->getViewMatrix() * vec4( 0, 1, 0, 0 ) ); 107 | 108 | drawScene(); 109 | 110 | // Draw positional tracking camera frustum 111 | CameraPersp positional; 112 | if( mRift->getPositionalTrackingCamera( &positional ) ) { 113 | gl::setModelMatrix( mat4() ); 114 | gl::lineWidth( 1.0f ); 115 | gl::drawFrustum( positional ); 116 | } 117 | } 118 | } 119 | else if( ! mRift ) { 120 | gl::viewport( getWindowSize() ); 121 | gl::setMatrices( mCamera ); 122 | 123 | const mat4& view = mCamera.getViewMatrix(); 124 | mShader->uniform( "uLightViewPosition", view * mLightWorldPosition ); 125 | mShader->uniform( "uSkyDirection", view * vec4( 0, 1, 0, 0 ) ); 126 | 127 | drawScene(); 128 | } 129 | } 130 | 131 | void BasicSampleApp::resize() 132 | { 133 | mCamera.setAspectRatio( getWindowAspectRatio() ); 134 | } 135 | 136 | void BasicSampleApp::keyDown( KeyEvent event ) 137 | { 138 | switch( event.getCode() ) { 139 | case KeyEvent::KEY_ESCAPE: 140 | quit(); 141 | break; 142 | case KeyEvent::KEY_r: 143 | mRift->recenterPose(); 144 | break; 145 | case KeyEvent::KEY_m: 146 | mRift->enableMirrored( ! mRift->isMirrored() ); 147 | break; 148 | case KeyEvent::KEY_s: 149 | mRift->enableMonoscopic( ! mRift->isMonoscopic() ); 150 | break; 151 | case KeyEvent::KEY_t: 152 | mRift->enablePositionalTracking( ! mRift->isPositionalTrackingEnabled() ); 153 | break; 154 | case KeyEvent::KEY_p: 155 | mRift->cyclePerfHudModes(); 156 | break; 157 | } 158 | } 159 | 160 | void prepareSettings( App::Settings *settings ) 161 | { 162 | try { 163 | RiftManager::initialize(); 164 | } 165 | catch( const RiftExeption& exc ) { 166 | CI_LOG_EXCEPTION( "Failed ovr initialization", exc ); 167 | } 168 | settings->setTitle( "Oculus Rift Sample" ); 169 | settings->setWindowSize( 1920/2, 1080/2 ); 170 | } 171 | 172 | CINDER_APP( BasicSampleApp, RendererGl( RendererGl::Options().msaa(0) ), prepareSettings ); -------------------------------------------------------------------------------- /samples/BasicSample/vc2013/BasicSample.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2013 3 | VisualStudioVersion = 12.0.30110.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicSample", "BasicSample.vcxproj", "{63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Win32 = Debug|Win32 10 | Debug|x64 = Debug|x64 11 | Release|Win32 = Release|Win32 12 | Release|x64 = Release|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Debug|Win32.ActiveCfg = Debug|Win32 16 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Debug|Win32.Build.0 = Debug|Win32 17 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Debug|x64.ActiveCfg = Debug|x64 18 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Debug|x64.Build.0 = Debug|x64 19 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Release|Win32.ActiveCfg = Release|Win32 20 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Release|Win32.Build.0 = Release|Win32 21 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Release|x64.ActiveCfg = Release|x64 22 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E}.Release|x64.Build.0 = Release|x64 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /samples/BasicSample/vc2013/BasicSample.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {63B11ADE-4F4B-47B7-A92C-4DD98C805E0E} 23 | BasicSample 24 | Win32Proj 25 | 26 | 27 | 28 | Application 29 | false 30 | v120 31 | Unicode 32 | true 33 | 34 | 35 | Application 36 | false 37 | v120 38 | Unicode 39 | true 40 | 41 | 42 | Application 43 | true 44 | v120 45 | Unicode 46 | 47 | 48 | Application 49 | true 50 | v120 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | <_ProjectFileVersion>10.0.30319.1 70 | $(SolutionDir)$(Configuration)\ 71 | $(Configuration)\ 72 | true 73 | true 74 | $(SolutionDir)$(Configuration)\ 75 | $(Configuration)\ 76 | false 77 | false 78 | 79 | 80 | 81 | Disabled 82 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 83 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 84 | true 85 | EnableFastChecks 86 | MultiThreadedDebug 87 | 88 | Level3 89 | EditAndContinue 90 | true 91 | 92 | 93 | "..\..\..\..\..\\include";..\include 94 | 95 | 96 | cinder-$(PlatformToolset)_d.lib;..\..\..\LibOVR\Lib\Windows\$(Platform)\Release\VS2013\LibOVR.lib;%(AdditionalDependencies) 97 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 98 | true 99 | Windows 100 | false 101 | 102 | MachineX86 103 | LIBCMT;LIBCPMT 104 | 105 | 106 | 107 | 108 | Disabled 109 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 110 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 111 | EnableFastChecks 112 | MultiThreadedDebug 113 | 114 | 115 | Level3 116 | ProgramDatabase 117 | true 118 | 119 | 120 | "..\..\..\..\..\\include";..\include 121 | 122 | 123 | cinder-$(PlatformToolset)_d.lib;..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\Release\VS2013\LibOVR.lib;%(AdditionalDependencies) 124 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 125 | true 126 | Windows 127 | false 128 | 129 | 130 | LIBCMT;LIBCPMT 131 | 132 | 133 | 134 | 135 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 136 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 137 | MultiThreaded 138 | 139 | Level3 140 | ProgramDatabase 141 | true 142 | 143 | 144 | true 145 | 146 | 147 | "..\..\..\..\..\\include";..\include 148 | 149 | 150 | cinder-$(PlatformToolset).lib;..\..\..\LibOVR\Lib\Windows\$(Platform)\$(Configuration)\VS2013\LibOVR.lib;%(AdditionalDependencies) 151 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 152 | false 153 | true 154 | Windows 155 | true 156 | 157 | false 158 | 159 | MachineX86 160 | 161 | 162 | 163 | 164 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 165 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 166 | MultiThreaded 167 | 168 | 169 | Level3 170 | ProgramDatabase 171 | true 172 | 173 | 174 | true 175 | 176 | 177 | "..\..\..\..\..\\include";..\include 178 | 179 | 180 | cinder-$(PlatformToolset).lib;..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\$(Configuration)\VS2013\LibOVR.lib;%(AdditionalDependencies) 181 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 182 | false 183 | true 184 | Windows 185 | true 186 | 187 | 188 | false 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /samples/BasicSample/vc2013/BasicSample.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 6 | 7 | 8 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | 11 | 12 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 14 | 15 | 16 | {45D1A1DE-B1D4-4F87-836C-2B909D23FD02} 17 | 18 | 19 | {437C7516-2E0D-422D-B43C-AB0315E711A4} 20 | 21 | 22 | {C36A065F-0D91-4AB4-AFCE-A77925A403EA} 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Blocks\OculusRift\include 37 | 38 | 39 | Blocks\OculusRift\include 40 | 41 | 42 | 43 | 44 | Header Files 45 | 46 | 47 | 48 | 49 | Resource Files 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /samples/BasicSample/vc2013/Resources.rc: -------------------------------------------------------------------------------- 1 | #include "../include/Resources.h" 2 | 3 | 1 ICON "..\\resources\\cinder_app_icon.ico" 4 | -------------------------------------------------------------------------------- /samples/InstancedStereo/assets/phong.frag: -------------------------------------------------------------------------------- 1 | #version 410 2 | 3 | uniform vec4 uLightPosition; 4 | 5 | in vec4 vViewPosition; 6 | in vec3 vNormal; 7 | in mat4 vEyeViewMatrix; 8 | 9 | out vec4 oColor; 10 | 11 | void main( void ) 12 | { 13 | const vec3 matDiffuse = vec3( 1 ); 14 | const vec3 lightDiffuse = vec3( 1 ); 15 | 16 | vec3 N = normalize( vNormal ); 17 | vec3 L = normalize( vec3( vEyeViewMatrix * uLightPosition - vViewPosition ) ); 18 | 19 | // hemispherical ambient lighting 20 | float hemi = dot( N, vec3(0,1,0) ) * 0.5 + 0.5; 21 | oColor.rgb = mix( vec3(0), vec3(0.1), hemi ); 22 | 23 | // diffuse lighting 24 | float lambert = max( 0, dot( N, L ) ); 25 | oColor.rgb += lambert * matDiffuse * lightDiffuse; 26 | 27 | // output gamma corrected color 28 | oColor.rgb = sqrt( oColor.rgb ); 29 | oColor.a = 1; 30 | } -------------------------------------------------------------------------------- /samples/InstancedStereo/assets/phong.vert: -------------------------------------------------------------------------------- 1 | #version 410 2 | 3 | uniform mat4 ciModelMatrix; 4 | uniform mat4 uWorldToEyeClipMatrices[6]; 5 | 6 | in vec4 ciPosition; 7 | in vec3 ciNormal; 8 | 9 | out vec4 vViewPosition; 10 | out vec3 vNormal; 11 | out mat4 vEyeViewMatrix; 12 | out float gl_ClipDistance[1]; 13 | 14 | vec4 eyeClipEdge[2] = vec4[2]( vec4(-1,0,0,0), vec4(1,0,0,0) ); 15 | float eyeOffsetScale[2] = float[2]( -0.5, 0.5 ); 16 | 17 | void main( void ) 18 | { 19 | uint eyeIndex = gl_InstanceID; 20 | vEyeViewMatrix = uWorldToEyeClipMatrices[ 3 * eyeIndex ]; 21 | mat4 eyeProjectionMatrix = uWorldToEyeClipMatrices[ 3 * eyeIndex + 1 ]; 22 | mat3 eyeNormalMatrix = mat3( uWorldToEyeClipMatrices[ 3 * eyeIndex + 2 ] ); 23 | 24 | vec4 clipPos; 25 | vViewPosition = vEyeViewMatrix * ciModelMatrix * ciPosition; 26 | vNormal = mat3(vEyeViewMatrix) * eyeNormalMatrix * ciNormal; 27 | clipPos = eyeProjectionMatrix * vViewPosition; 28 | clipPos.x *= 0.5; // shrink to half of the screen 29 | clipPos.x += eyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. 30 | 31 | gl_Position = clipPos; 32 | gl_ClipDistance[0] = dot( eyeClipEdge[eyeIndex], clipPos ); 33 | } -------------------------------------------------------------------------------- /samples/InstancedStereo/include/Resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/CinderResources.h" 3 | 4 | //#define RES_MY_RES CINDER_RESOURCE( ../resources/, image_name.png, 128, IMAGE ) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/InstancedStereo/resources/CinderApp.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/InstancedStereo/resources/CinderApp.icns -------------------------------------------------------------------------------- /samples/InstancedStereo/resources/cinder_app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/InstancedStereo/resources/cinder_app_icon.ico -------------------------------------------------------------------------------- /samples/InstancedStereo/src/InstancedStereoApp.cpp: -------------------------------------------------------------------------------- 1 | #include "cinder/app/App.h" 2 | #include "cinder/app/RendererGl.h" 3 | #include "cinder/gl/gl.h" 4 | #include "cinder/Log.h" 5 | #include "cinder/Utilities.h" 6 | 7 | #include "CinderOculus.h" 8 | 9 | using namespace ci; 10 | using namespace ci::app; 11 | using namespace std; 12 | 13 | class InstancedStereoApp : public App { 14 | public: 15 | InstancedStereoApp(); 16 | 17 | void update() override; 18 | void draw() override; 19 | void keyDown( KeyEvent event ) override; 20 | private: 21 | void drawPositionalTrackingCamera() const; 22 | double mTime; 23 | 24 | hmd::OculusRiftRef mRift; 25 | 26 | gl::GlslProgRef mShader; 27 | gl::BatchRef mTeapot; 28 | 29 | vec4 mLightWorldPosition; 30 | }; 31 | 32 | InstancedStereoApp::InstancedStereoApp() 33 | : mLightWorldPosition( vec4( 1, 1, 1, 1 ) ) 34 | { 35 | CameraPersp host; 36 | host.setEyePoint( vec3( 0, 0, 1 ) ); 37 | host.lookAt( vec3( 0 ) ); 38 | mRift = hmd::OculusRift::create( hmd::OculusRift::Params().hostCamera( host ).screenPercentage( 1.25f ) ); 39 | 40 | try { 41 | mShader = gl::GlslProg::create( gl::GlslProg::Format().vertex( loadAsset( "phong.vert" ) ).fragment( loadAsset( "phong.frag" ) ) ); 42 | } 43 | catch( const std::exception& e ) { 44 | console() << e.what() << std::endl; 45 | quit(); 46 | } 47 | mTeapot = gl::Batch::create( geom::Teapot().subdivisions( 12 ), mShader ); 48 | 49 | gl::enableVerticalSync( false ); 50 | gl::disableAlphaBlending(); 51 | gl::enableDepthRead(); 52 | gl::enableDepthWrite(); 53 | gl::enable( GL_CLIP_DISTANCE0, true ); 54 | } 55 | 56 | void InstancedStereoApp::update() 57 | { 58 | mTime = getElapsedSeconds(); 59 | } 60 | 61 | void InstancedStereoApp::draw() 62 | { 63 | gl::clear(); 64 | 65 | hmd::ScopedRiftBuffer bind{ mRift }; 66 | std::array worldToEyeClipMatrices; 67 | 68 | // Calc clip space conversion matrices for both eyes 69 | for( auto eye : mRift->getEyes() ) { 70 | gl::ScopedMatrices push; 71 | mRift->enableEye( eye ); 72 | auto idx = 3 * static_cast(eye); 73 | worldToEyeClipMatrices.at( idx ) = mRift->getViewMatrix() * mRift->getModelMatrix(); 74 | worldToEyeClipMatrices.at( idx + 1 ) = mRift->getProjectionMatrix(); 75 | 76 | // non-instanced scene 77 | gl::lineWidth( 3.0f ); 78 | gl::drawCoordinateFrame( 2 ); 79 | gl::drawSphere( vec3( mLightWorldPosition ), 0.05f, 36 ); 80 | } 81 | 82 | { 83 | gl::ScopedViewport port{ vec2( 0 ), mRift->getFboSize() }; 84 | gl::ScopedModelMatrix push; 85 | gl::rotate( (float)mTime, vec3( -0.3f, -1.0f, 0.2f ) ); 86 | gl::scale( vec3( 0.5f ) ); 87 | gl::translate( 0.0f, -0.5f, 0.0f ); 88 | 89 | auto normalMatrix = glm::transpose( glm::inverse( gl::getModelMatrix() ) ); 90 | worldToEyeClipMatrices.at( 2 ) = worldToEyeClipMatrices.at( 5 ) = normalMatrix; 91 | mShader->uniform( "uLightPosition", mLightWorldPosition ); 92 | mShader->uniform( "uWorldToEyeClipMatrices", worldToEyeClipMatrices.data(), 6 ); 93 | mTeapot->drawInstanced( 2 ); 94 | } 95 | } 96 | 97 | void InstancedStereoApp::keyDown( KeyEvent event ) 98 | { 99 | hideCursor(); 100 | switch( event.getCode() ) { 101 | case KeyEvent::KEY_ESCAPE: 102 | quit(); 103 | break; 104 | case KeyEvent::KEY_r: 105 | mRift->recenterPose(); 106 | break; 107 | case KeyEvent::KEY_m: 108 | mRift->enableMirrored( ! mRift->isMirrored() ); 109 | break; 110 | case KeyEvent::KEY_s: 111 | mRift->enableMonoscopic( ! mRift->isMonoscopic() ); 112 | break; 113 | case KeyEvent::KEY_t: 114 | mRift->enablePositionalTracking( ! mRift->isTracked() ); 115 | break; 116 | } 117 | } 118 | 119 | void prepareSettings( App::Settings *settings ) 120 | { 121 | hmd::RiftManager::initialize(); 122 | 123 | settings->disableFrameRate(); 124 | settings->setTitle( "Oculus Rift Sample" ); 125 | settings->setWindowSize( 1920/2, 1080/2 ); 126 | } 127 | 128 | CINDER_APP( InstancedStereoApp, RendererGl( RendererGl::Options().msaa( 0 ) ), prepareSettings ); -------------------------------------------------------------------------------- /samples/InstancedStereo/vc2013/InstancedStereo.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InstancedStereo", "InstancedStereo.vcxproj", "{1A0DC129-7D5B-450D-A0BF-654A5902C1A9}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {1A0DC129-7D5B-450D-A0BF-654A5902C1A9}.Debug|x64.ActiveCfg = Debug|x64 13 | {1A0DC129-7D5B-450D-A0BF-654A5902C1A9}.Debug|x64.Build.0 = Debug|x64 14 | {1A0DC129-7D5B-450D-A0BF-654A5902C1A9}.Release|x64.ActiveCfg = Release|x64 15 | {1A0DC129-7D5B-450D-A0BF-654A5902C1A9}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /samples/InstancedStereo/vc2013/InstancedStereo.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {1A0DC129-7D5B-450D-A0BF-654A5902C1A9} 15 | InstancedStereo 16 | Win32Proj 17 | 18 | 19 | 20 | Application 21 | false 22 | v120 23 | Unicode 24 | true 25 | 26 | 27 | Application 28 | true 29 | v120 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>10.0.30319.1 43 | true 44 | false 45 | 46 | 47 | 48 | Disabled 49 | ..\include;"..\..\..\..\..\include";"..\..\..\..\..\boost";..\..\..\include;..\..\..\LibOVR\Include; 50 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 51 | EnableFastChecks 52 | MultiThreadedDebug 53 | 54 | Level3 55 | ProgramDatabase 56 | true 57 | 58 | 59 | "..\..\..\..\..\include";..\include 60 | 61 | 62 | cinder-$(PlatformToolset)_d.lib;OpenGL32.lib;%(AdditionalDependencies);..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\$(Configuration)\VS2013\LibOVR.lib; 63 | "..\..\..\..\..\lib\msw\$(PlatformTarget)" 64 | true 65 | Windows 66 | false 67 | 68 | LIBCMT;LIBCPMT 69 | 70 | 71 | 72 | 73 | ..\include;"..\..\..\..\..\include";"..\..\..\..\..\boost";..\..\..\include;..\..\..\LibOVR\Include; 74 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 75 | MultiThreaded 76 | 77 | Level3 78 | ProgramDatabase 79 | true 80 | 81 | 82 | true 83 | 84 | 85 | "..\..\..\..\..\include";..\include 86 | 87 | 88 | cinder-$(PlatformToolset).lib;OpenGL32.lib;%(AdditionalDependencies);..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\$(Configuration)\VS2013\LibOVR.lib; 89 | "..\..\..\..\..\lib\msw\$(PlatformTarget)" 90 | false 91 | true 92 | Windows 93 | true 94 | 95 | false 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /samples/InstancedStereo/vc2013/InstancedStereo.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 6 | 7 | 8 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | 11 | 12 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 14 | 15 | 16 | {C7BE831B-0335-4129-AABC-2C74EA5B9D65} 17 | 18 | 19 | {C6340460-AFB2-41D9-A046-0A1FAE12CBB7} 20 | 21 | 22 | {067D48B1-75A8-405B-AD37-8709FC8ED692} 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Blocks\OculusRift\include 37 | 38 | 39 | Blocks\OculusRift\include 40 | 41 | 42 | 43 | 44 | Header Files 45 | 46 | 47 | 48 | 49 | Resource Files 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /samples/InstancedStereo/vc2013/Resources.rc: -------------------------------------------------------------------------------- 1 | #include "../include/Resources.h" 2 | 3 | 1 ICON "..\\resources\\cinder_app_icon.ico" 4 | -------------------------------------------------------------------------------- /samples/SphericalStereo/assets/arnold_LR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/SphericalStereo/assets/arnold_LR.jpg -------------------------------------------------------------------------------- /samples/SphericalStereo/assets/stereo.frag: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform sampler2D uTex0; 4 | uniform ivec2 uDisplayMode; // LR, RL, TB, BT 5 | uniform int uRightEye; 6 | 7 | in vec3 vModelNormal; 8 | out vec4 fragColor; 9 | 10 | const float ONE_OVER_PI = 1.0 / 3.14159265; 11 | 12 | void main() { 13 | vec3 N = normalize( vModelNormal ); 14 | // spherical projection based on the surface normal 15 | vec2 coord = vec2( 0.5 + 0.5 * atan( N.x, -N.z ) * ONE_OVER_PI, 1.0 - acos( N.y ) * ONE_OVER_PI ); 16 | if( bool( uDisplayMode.x ) ) { 17 | coord.y = 0.5 * coord.y + float( uRightEye != uDisplayMode.y ) * 0.5; 18 | } else { 19 | coord.x = 0.5 * coord.x + float( uRightEye == uDisplayMode.y ) * 0.5; 20 | } 21 | fragColor = texture( uTex0, coord ); 22 | } -------------------------------------------------------------------------------- /samples/SphericalStereo/assets/stereo.vert: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform mat4 ciModelViewProjection; 4 | uniform mat3 ciNormalMatrix; 5 | in vec4 ciPosition; 6 | in vec3 ciNormal; 7 | 8 | out vec3 vModelNormal; 9 | 10 | void main( void ) 11 | { 12 | vModelNormal = ciNormal; 13 | gl_Position = ciModelViewProjection * ciPosition; 14 | } 15 | -------------------------------------------------------------------------------- /samples/SphericalStereo/include/Resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/CinderResources.h" 3 | 4 | //#define RES_MY_RES CINDER_RESOURCE( ../resources/, image_name.png, 128, IMAGE ) 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /samples/SphericalStereo/resources/CinderApp.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/SphericalStereo/resources/CinderApp.icns -------------------------------------------------------------------------------- /samples/SphericalStereo/resources/cinder_app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/num3ric/Cinder-OculusRift/02f59a3362ec102db6fe843fbaacb391866f4f87/samples/SphericalStereo/resources/cinder_app_icon.ico -------------------------------------------------------------------------------- /samples/SphericalStereo/src/SphericalStereoApp.cpp: -------------------------------------------------------------------------------- 1 | #include "cinder/app/App.h" 2 | #include "cinder/app/RendererGl.h" 3 | #include "cinder/gl/gl.h" 4 | #include "cinder/Log.h" 5 | #include "cinder/gl/VboMesh.h" 6 | #include "cinder/Utilities.h" 7 | #include "cinder/GeomIo.h" 8 | #include "cinder/gl/Shader.h" 9 | #include "cinder/Text.h" 10 | 11 | #include "CinderOculus.h" 12 | 13 | #include 14 | 15 | using namespace ci; 16 | using namespace ci::app; 17 | using namespace std; 18 | 19 | // Spherical latlong file names should follow the Gear VR convention: _LR, _RL, _TB, _BT. 20 | struct Pano { 21 | Pano() { } 22 | Pano( const fs::path& path ) 23 | : mDisplayMode{ ivec2(0,0) }, mName( path.filename().string() ) 24 | { 25 | std::string stem = path.stem().string(); 26 | std::transform( stem.begin(), stem.end(), stem.begin(), ::toupper ); 27 | switch( stem.back() ) { 28 | case 'L': mDisplayMode = ivec2( 0, 0 ); break; 29 | case 'R': mDisplayMode = ivec2( 0, 1 ); break; 30 | case 'T': mDisplayMode = ivec2( 1, 0 ); break; 31 | case 'B': mDisplayMode = ivec2( 1, 1 ); break; 32 | default: break; 33 | } 34 | 35 | mLatLong = gl::Texture2d::create( loadImage( path ), gl::Texture2d::Format().wrap( GL_REPEAT ) ); 36 | } 37 | gl::Texture2dRef mLatLong; 38 | std::string mName; 39 | ivec2 mDisplayMode; 40 | }; 41 | 42 | class SphericalStereoApp : public App { 43 | public: 44 | SphericalStereoApp(); 45 | void update() override; 46 | void draw() override; 47 | 48 | void fileDrop( FileDropEvent event ) override; 49 | void keyDown( KeyEvent event ) override; 50 | 51 | hmd::OculusRiftRef mRift; 52 | private: 53 | 54 | size_t mPanoIndex = 0; 55 | std::vector mPanos; 56 | gl::BatchRef mSphere; 57 | gl::GlslProgRef mStereoGlsl; 58 | }; 59 | 60 | SphericalStereoApp::SphericalStereoApp() 61 | { 62 | mRift = hmd::OculusRift::create( hmd::OculusRift::Params() 63 | .monoscopic( true ) 64 | .positional( false ) ); 65 | 66 | try{ 67 | mStereoGlsl = gl::GlslProg::create( loadAsset( "stereo.vert" ), loadAsset( "stereo.frag" ) ); 68 | } 69 | catch( const ci::Exception& exc ) { 70 | CI_LOG_EXCEPTION( "GLSL", exc ); 71 | } 72 | mPanos.push_back( Pano{ getAssetPath( "arnold_LR.jpg" ) } ); 73 | mSphere = gl::Batch::create( geom::Icosphere().subdivisions( 2 ), mStereoGlsl ); 74 | 75 | // Generally preferable to enable vsync to prevent tearing in the headset display 76 | gl::enableVerticalSync( false ); 77 | gl::color( Color::white() ); 78 | } 79 | 80 | void SphericalStereoApp::update() 81 | { 82 | 83 | } 84 | 85 | void SphericalStereoApp::draw() 86 | { 87 | if( mRift ) { 88 | hmd::ScopedRiftBuffer bind{ mRift }; 89 | gl::clear(); 90 | for( auto eye : mRift->getEyes() ) { 91 | mRift->enableEye( eye ); 92 | const auto& pano = mPanos.at( mPanoIndex ); 93 | mStereoGlsl->uniform( "uDisplayMode", pano.mDisplayMode ); 94 | mStereoGlsl->uniform( "uRightEye", static_cast(eye) ); 95 | gl::ScopedTextureBind tex0( pano.mLatLong ); 96 | mSphere->draw(); 97 | 98 | { 99 | auto size = mRift->getFboSize(); 100 | gl::ScopedMatrices push; 101 | gl::setMatricesWindow( size.x / 2, size.y ); 102 | vec3 latencies = mRift->getLatencies(); 103 | 104 | stringstream ss; 105 | ss << mPanos.at( mPanoIndex ).mName << std::endl; 106 | ss << " " << std::endl; 107 | ss << "App fps: " << toString( getAverageFps() ) << std::endl; 108 | ss << "Ren: " << latencies.x << std::endl; 109 | ss << "TWrp: " << latencies.y << std::endl; 110 | ss << "PostPresent: " << latencies.z << std::endl; 111 | 112 | auto tbox = TextBox().text( ss.str() ).font( Font( "Arial", 20.0f ) ).color( Color::white() ).backgroundColor( Color::black() ); 113 | gl::draw( gl::Texture2d::create( tbox.render() ), vec2( size.x / 3, size.y / 2 ) ); 114 | } 115 | } 116 | } 117 | } 118 | 119 | void SphericalStereoApp::fileDrop( FileDropEvent event ) 120 | { 121 | mPanos.insert( mPanos.begin() + mPanoIndex, Pano{ event.getFile( 0 ) } ); 122 | } 123 | 124 | void SphericalStereoApp::keyDown( KeyEvent event ) 125 | { 126 | hideCursor(); 127 | switch( event.getCode() ) { 128 | case KeyEvent::KEY_SPACE: 129 | mPanoIndex = ( mPanoIndex + 1 ) % mPanos.size(); 130 | break; 131 | case KeyEvent::KEY_ESCAPE: 132 | quit(); 133 | break; 134 | case KeyEvent::KEY_r: 135 | mRift->recenterPose(); 136 | break; 137 | case KeyEvent::KEY_m: 138 | mRift->enableMirrored( ! mRift->isMirrored() ); 139 | break; 140 | case KeyEvent::KEY_s: 141 | mRift->enableMonoscopic( ! mRift->isMonoscopic() ); 142 | break; 143 | case KeyEvent::KEY_p: 144 | mRift->enablePositionalTracking( ! mRift->isPositionalTrackingEnabled() ); 145 | break; 146 | } 147 | } 148 | 149 | void prepareSettings( App::Settings *settings ) 150 | { 151 | hmd::RiftManager::initialize(); 152 | settings->disableFrameRate(); 153 | settings->setTitle( "Oculus Rift Sample" ); 154 | settings->setWindowSize( 1920 / 2, 1080 / 2 ); 155 | } 156 | 157 | CINDER_APP( SphericalStereoApp, RendererGl( RendererGl::Options().msaa( 0 ) ), prepareSettings) 158 | -------------------------------------------------------------------------------- /samples/SphericalStereo/vc2013/Resources.rc: -------------------------------------------------------------------------------- 1 | #include "../include/Resources.h" 2 | 3 | 1 ICON "..\\resources\\cinder_app_icon.ico" 4 | -------------------------------------------------------------------------------- /samples/SphericalStereo/vc2013/SphericalStereo.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2013 3 | VisualStudioVersion = 12.0.30110.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SphericalStereo", "SphericalStereo.vcxproj", "{A4DB40A2-9C92-41CA-9723-EC629842AF6F}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Win32 = Debug|Win32 10 | Debug|x64 = Debug|x64 11 | Release|Win32 = Release|Win32 12 | Release|x64 = Release|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Debug|Win32.ActiveCfg = Debug|Win32 16 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Debug|Win32.Build.0 = Debug|Win32 17 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Debug|x64.ActiveCfg = Debug|x64 18 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Debug|x64.Build.0 = Debug|x64 19 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Release|Win32.ActiveCfg = Release|Win32 20 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Release|Win32.Build.0 = Release|Win32 21 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Release|x64.ActiveCfg = Release|x64 22 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F}.Release|x64.Build.0 = Release|x64 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /samples/SphericalStereo/vc2013/SphericalStereo.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {A4DB40A2-9C92-41CA-9723-EC629842AF6F} 23 | SphericalStereo 24 | Win32Proj 25 | 26 | 27 | 28 | Application 29 | false 30 | v120 31 | Unicode 32 | true 33 | 34 | 35 | Application 36 | false 37 | v120 38 | Unicode 39 | true 40 | 41 | 42 | Application 43 | true 44 | v120 45 | Unicode 46 | 47 | 48 | Application 49 | true 50 | v120 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | <_ProjectFileVersion>10.0.30319.1 70 | $(SolutionDir)$(Configuration)\ 71 | $(Configuration)\ 72 | true 73 | true 74 | $(SolutionDir)$(Configuration)\ 75 | $(Configuration)\ 76 | false 77 | false 78 | 79 | 80 | 81 | Disabled 82 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 83 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 84 | true 85 | EnableFastChecks 86 | MultiThreadedDebug 87 | 88 | Level3 89 | EditAndContinue 90 | true 91 | 92 | 93 | "..\..\..\..\..\\include";..\include 94 | 95 | 96 | cinder-$(PlatformToolset)_d.lib;%(AdditionalDependencies);..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\Release\VS2013\LibOVR.lib; 97 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 98 | true 99 | Windows 100 | false 101 | 102 | MachineX86 103 | LIBCMT;LIBCPMT 104 | 105 | 106 | 107 | 108 | Disabled 109 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 110 | WIN32;_DEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 111 | EnableFastChecks 112 | MultiThreadedDebug 113 | 114 | 115 | Level3 116 | ProgramDatabase 117 | true 118 | 119 | 120 | "..\..\..\..\..\\include";..\include 121 | 122 | 123 | cinder-$(PlatformToolset)_d.lib;%(AdditionalDependencies);..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\Release\VS2013\LibOVR.lib; 124 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 125 | true 126 | Windows 127 | false 128 | 129 | 130 | LIBCMT;LIBCPMT 131 | 132 | 133 | 134 | 135 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 136 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 137 | MultiThreaded 138 | 139 | Level3 140 | ProgramDatabase 141 | true 142 | 143 | 144 | true 145 | 146 | 147 | "..\..\..\..\..\\include";..\include 148 | 149 | 150 | cinder-$(PlatformToolset).lib;%(AdditionalDependencies);..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\$(Configuration)\VS2013\LibOVR.lib; 151 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 152 | false 153 | true 154 | Windows 155 | true 156 | 157 | false 158 | 159 | MachineX86 160 | 161 | 162 | 163 | 164 | ..\include;"..\..\..\..\..\\include";"..\..\..\..\..\\boost";..\..\..\include;..\..\..\LibOVR\Include; 165 | WIN32;NDEBUG;_WINDOWS;NOMINMAX;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) 166 | MultiThreaded 167 | 168 | 169 | Level3 170 | ProgramDatabase 171 | true 172 | 173 | 174 | true 175 | 176 | 177 | "..\..\..\..\..\\include";..\include 178 | 179 | 180 | cinder-$(PlatformToolset).lib;%(AdditionalDependencies);..\..\..\LibOVR\Lib\Windows\$(PlatformTarget)\$(Configuration)\VS2013\LibOVR.lib; 181 | "..\..\..\..\..\\lib\msw\$(PlatformTarget)" 182 | false 183 | true 184 | Windows 185 | true 186 | 187 | 188 | false 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /samples/SphericalStereo/vc2013/SphericalStereo.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 6 | 7 | 8 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | 11 | 12 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 14 | 15 | 16 | {9B9FE89E-3F0C-43FC-84DA-27C7F5D62A66} 17 | 18 | 19 | {8810564C-1440-4EB6-829E-AC1EB2493601} 20 | 21 | 22 | {0601D31A-176E-44E8-A245-EFEF799A1754} 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Blocks\OculusRift\include 37 | 38 | 39 | Blocks\OculusRift\include 40 | 41 | 42 | 43 | 44 | Header Files 45 | 46 | 47 | 48 | 49 | Resource Files 50 | 51 | 52 | 53 | --------------------------------------------------------------------------------