ovr_sdk

annotate LibOVR/Src/Util/Util_Render_Stereo.h @ 3:f12a8f74fe1f

added the Xcode project
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 21 Jan 2015 11:37:50 +0200
parents
children
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 Filename : Util_Render_Stereo.h
nuclear@0 4 Content : Sample stereo rendering configuration classes.
nuclear@0 5 Created : October 22, 2012
nuclear@0 6 Authors : Michael Antonov, Tom Forsyth
nuclear@0 7
nuclear@0 8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 9
nuclear@0 10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 11 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 12 which is provided at the time of installation or download, or which
nuclear@0 13 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 14
nuclear@0 15 You may obtain a copy of the License at
nuclear@0 16
nuclear@0 17 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 18
nuclear@0 19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 20 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 22 See the License for the specific language governing permissions and
nuclear@0 23 limitations under the License.
nuclear@0 24
nuclear@0 25 *************************************************************************************/
nuclear@0 26
nuclear@0 27 #ifndef OVR_Util_Render_Stereo_h
nuclear@0 28 #define OVR_Util_Render_Stereo_h
nuclear@0 29
nuclear@0 30 #include "../OVR_Stereo.h"
nuclear@0 31 #include "../Tracking/Tracking_SensorStateReader.h"
nuclear@0 32
nuclear@0 33 namespace OVR { namespace Util { namespace Render {
nuclear@0 34
nuclear@0 35
nuclear@0 36
nuclear@0 37 //-----------------------------------------------------------------------------------
nuclear@0 38 // **** Useful debug functions.
nuclear@0 39 //
nuclear@0 40 // Purely for debugging - the results are not very end-user-friendly.
nuclear@0 41 char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType );
nuclear@0 42 char const* GetDebugNameHmdType ( HmdTypeEnum hmdType );
nuclear@0 43
nuclear@0 44
nuclear@0 45
nuclear@0 46 //-----------------------------------------------------------------------------------
nuclear@0 47 // **** Higher-level utility functions.
nuclear@0 48
nuclear@0 49 Sizei CalculateRecommendedTextureSize ( HmdRenderInfo const &hmd,
nuclear@0 50 bool bRendertargetSharedByBothEyes,
nuclear@0 51 float pixelDensityInCenter = 1.0f );
nuclear@0 52
nuclear@0 53 FovPort CalculateRecommendedFov ( HmdRenderInfo const &hmd,
nuclear@0 54 StereoEye eyeType,
nuclear@0 55 bool bMakeFovSymmetrical = false);
nuclear@0 56
nuclear@0 57 StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd,
nuclear@0 58 StereoEye eyeType,
nuclear@0 59 Sizei const &actualRendertargetSurfaceSize,
nuclear@0 60 bool bRendertargetSharedByBothEyes,
nuclear@0 61 bool bRightHanded = true,
nuclear@0 62 float zNear = 0.01f, float zFar = 10000.0f,
nuclear@0 63 Sizei const *pOverrideRenderedPixelSize = NULL,
nuclear@0 64 FovPort const *pOverrideFovport = NULL,
nuclear@0 65 float zoomFactor = 1.0f );
nuclear@0 66
nuclear@0 67 Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd,
nuclear@0 68 StereoEye eyeType, bool bMonoRenderingMode );
nuclear@0 69
nuclear@0 70
nuclear@0 71 // These are two components from StereoEyeParams that can be changed
nuclear@0 72 // very easily without full recomputation of everything.
nuclear@0 73 struct ViewportScaleAndOffset
nuclear@0 74 {
nuclear@0 75 Recti RenderedViewport;
nuclear@0 76 ScaleAndOffset2D EyeToSourceUV;
nuclear@0 77 };
nuclear@0 78
nuclear@0 79 // Three ways to override the size of the render view dynamically.
nuclear@0 80 // None of these require changing the distortion parameters or the regenerating the distortion mesh,
nuclear@0 81 // and can be called every frame if desired.
nuclear@0 82 ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const &params,
nuclear@0 83 Sizei const &actualRendertargetSurfaceSize,
nuclear@0 84 Recti const &renderViewport );
nuclear@0 85
nuclear@0 86 ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const &params,
nuclear@0 87 Sizei const &actualRendertargetSurfaceSize,
nuclear@0 88 Sizei const &requestedRenderSize,
nuclear@0 89 bool bRendertargetSharedByBothEyes = false );
nuclear@0 90
nuclear@0 91 ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const &params,
nuclear@0 92 Sizei const &actualRendertargetSurfaceSize,
nuclear@0 93 float pixelDensity = 1.0f,
nuclear@0 94 bool bRendertargetSharedByBothEyes = false );
nuclear@0 95
nuclear@0 96
nuclear@0 97 //-----------------------------------------------------------------------------------
nuclear@0 98 // ***** StereoConfig
nuclear@0 99
nuclear@0 100 // StereoConfig maintains a scene stereo state and allow switching between different
nuclear@0 101 // stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
nuclear@0 102 // variables such as screen size, eye-to-screen distance and distortion, and computes
nuclear@0 103 // extra data such as FOV and distortion center offsets based on it. Rendering
nuclear@0 104 // parameters are returned though StereoEyeParams for each eye.
nuclear@0 105 //
nuclear@0 106 // Beyond regular 3D projection, this class supports rendering a 2D orthographic
nuclear@0 107 // surface for UI and text. The 2D surface will be defined by CreateOrthoSubProjection().
nuclear@0 108 // The (0,0) coordinate corresponds to eye center location.
nuclear@0 109 //
nuclear@0 110 // Applications are not required to use this class, but they should be doing very
nuclear@0 111 // similar sequences of operations, and it may be useful to start with this class
nuclear@0 112 // and modify it.
nuclear@0 113
nuclear@0 114 struct StereoEyeParamsWithOrtho
nuclear@0 115 {
nuclear@0 116 StereoEyeParams StereoEye;
nuclear@0 117 Matrix4f OrthoProjection;
nuclear@0 118 };
nuclear@0 119
nuclear@0 120 struct ViewportScaleAndOffsetBothEyes
nuclear@0 121 {
nuclear@0 122 ViewportScaleAndOffset Left;
nuclear@0 123 ViewportScaleAndOffset Right;
nuclear@0 124 };
nuclear@0 125
nuclear@0 126 class StereoConfig
nuclear@0 127 {
nuclear@0 128 public:
nuclear@0 129
nuclear@0 130 // StereoMode describes rendering modes that can be used by StereoConfig.
nuclear@0 131 // These modes control whether stereo rendering is used or not (Stereo_None),
nuclear@0 132 // and how it is implemented.
nuclear@0 133 enum StereoMode
nuclear@0 134 {
nuclear@0 135 Stereo_None = 0, // Single eye
nuclear@0 136 Stereo_LeftRight_Multipass = 1, // One frustum per eye
nuclear@0 137 };
nuclear@0 138
nuclear@0 139
nuclear@0 140 StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass);
nuclear@0 141
nuclear@0 142 //---------------------------------------------------------------------------------------------
nuclear@0 143 // *** Core functions - every app MUST call these functions at least once.
nuclear@0 144
nuclear@0 145 // Sets HMD parameters; also initializes distortion coefficients.
nuclear@0 146 void SetHmdRenderInfo(const HmdRenderInfo& hmd);
nuclear@0 147
nuclear@0 148 // Set the physical size of the rendertarget surface the app created,
nuclear@0 149 // and whether one RT is shared by both eyes, or each eye has its own RT:
nuclear@0 150 // true: both eyes are rendered to the same RT. Left eye starts at top-left, right eye starts at top-middle.
nuclear@0 151 // false: each eye is rendered to its own RT. Some GPU architectures prefer this arrangement.
nuclear@0 152 // Typically, the app would call CalculateRecommendedTextureSize() to suggest the choice of RT size.
nuclear@0 153 // This setting must be exactly the size of the actual RT created, or the UVs produced will be incorrect.
nuclear@0 154 // If the app wants to render to a subsection of the RT, it should use SetRenderSize()
nuclear@0 155 void SetRendertargetSize (Size<int> const rendertargetSize,
nuclear@0 156 bool rendertargetIsSharedByBothEyes );
nuclear@0 157
nuclear@0 158 // Returns full set of Stereo rendering parameters for the specified eye.
nuclear@0 159 const StereoEyeParamsWithOrtho& GetEyeRenderParams(StereoEye eye);
nuclear@0 160
nuclear@0 161
nuclear@0 162
nuclear@0 163 //---------------------------------------------------------------------------------------------
nuclear@0 164 // *** Optional functions - an app may call these to override default behaviours.
nuclear@0 165
nuclear@0 166 const HmdRenderInfo& GetHmdRenderInfo() const { return Hmd; }
nuclear@0 167
nuclear@0 168 // Returns the recommended size of rendertargets.
nuclear@0 169 // If rendertargetIsSharedByBothEyes is true, this is the size of the combined buffer.
nuclear@0 170 // If rendertargetIsSharedByBothEyes is false, this is the size of each individual buffer.
nuclear@0 171 // pixelDensityInCenter may be set to any number - by default it will match the HMD resolution in the center of the image.
nuclear@0 172 // After creating the rendertargets, the application MUST call SetRendertargetSize() with the actual size created
nuclear@0 173 // (which can be larger or smaller as the app wishes, but StereoConfig needs to know either way)
nuclear@0 174 Sizei CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes,
nuclear@0 175 float pixelDensityInCenter = 1.0f );
nuclear@0 176
nuclear@0 177 // Sets a stereo rendering mode and updates internal cached
nuclear@0 178 // state (matrices, per-eye view) based on it.
nuclear@0 179 void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; }
nuclear@0 180 StereoMode GetStereoMode() const { return Mode; }
nuclear@0 181
nuclear@0 182 // Sets the fieldOfView that the 2D coordinate area stretches to.
nuclear@0 183 void Set2DAreaFov(float fovRadians);
nuclear@0 184
nuclear@0 185 // Really only for science experiments - no normal app should ever need to override
nuclear@0 186 // the HMD's lens descriptors. Passing NULL removes the override.
nuclear@0 187 // Supply both = set left and right.
nuclear@0 188 // Supply just left = set both to the same.
nuclear@0 189 // Supply neither = remove override.
nuclear@0 190 void SetLensOverride ( LensConfig const *pLensOverrideLeft = NULL,
nuclear@0 191 LensConfig const *pLensOverrideRight = NULL );
nuclear@0 192
nuclear@0 193 // Override the rendered FOV in various ways. All angles in tangent units.
nuclear@0 194 // This is not clamped to the physical FOV of the display - you'll need to do that yourself!
nuclear@0 195 // Supply both = set left and right.
nuclear@0 196 // Supply just left = set both to the same.
nuclear@0 197 // Supply neither = remove override.
nuclear@0 198 void SetFov ( FovPort const *pfovLeft = NULL,
nuclear@0 199 FovPort const *pfovRight = NULL );
nuclear@0 200
nuclear@0 201 void SetFovPortRadians ( float horizontal, float vertical )
nuclear@0 202 {
nuclear@0 203 FovPort fov = FovPort::CreateFromRadians(horizontal, vertical);
nuclear@0 204 SetFov( &fov, &fov );
nuclear@0 205 }
nuclear@0 206
nuclear@0 207
nuclear@0 208 // This forces a "zero IPD" mode where there is just a single render with an FOV that
nuclear@0 209 // is the union of the two calculated FOVs.
nuclear@0 210 // The calculated render is for the left eye. Any size & FOV overrides for the right
nuclear@0 211 // eye will be ignored.
nuclear@0 212 // If you query the right eye's size, you will get the same render
nuclear@0 213 // size & position as the left eye - you should not actually do the render of course!
nuclear@0 214 // The distortion values will be different, because it goes to a different place on the framebuffer.
nuclear@0 215 // Note that if you do this, the rendertarget does not need to be twice the width of
nuclear@0 216 // the render size any more.
nuclear@0 217 void SetZeroVirtualIpdOverride ( bool enableOverride );
nuclear@0 218
nuclear@0 219 // Allows the app to specify near and far clip planes and the right/left-handedness of the projection matrix.
nuclear@0 220 void SetZClipPlanesAndHandedness ( float zNear = 0.01f, float zFar = 10000.0f,
nuclear@0 221 bool rightHandedProjection = true );
nuclear@0 222
nuclear@0 223 // Allows the app to specify how much extra eye rotation to allow when determining the visible FOV.
nuclear@0 224 void SetExtraEyeRotation ( float extraEyeRotationInRadians = 0.0f );
nuclear@0 225
nuclear@0 226 // The dirty flag is set by any of the above calls. Just handy for the app to know
nuclear@0 227 // if e.g. the distortion mesh needs regeneration.
nuclear@0 228 void SetDirty() { DirtyFlag = true; }
nuclear@0 229 bool IsDirty() { return DirtyFlag; }
nuclear@0 230
nuclear@0 231 // An app never needs to call this - GetEyeRenderParams will call it internally if
nuclear@0 232 // the state is dirty. However apps can call this explicitly to control when and where
nuclear@0 233 // computation is performed (e.g. not inside critical loops)
nuclear@0 234 void UpdateComputedState();
nuclear@0 235
nuclear@0 236 // This returns the projection matrix with a "zoom". Does not modify any internal state.
nuclear@0 237 Matrix4f GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const;
nuclear@0 238
nuclear@0 239
nuclear@0 240 //---------------------------------------------------------------------------------------------
nuclear@0 241 // The SetRender* functions are special.
nuclear@0 242 //
nuclear@0 243 // They do not require a full recalculation of state, and they do not change anything but the
nuclear@0 244 // ViewportScaleAndOffset data for the eyes (which they return), and do not set the dirty flag!
nuclear@0 245 // This means they can be called without regenerating the distortion mesh, and thus
nuclear@0 246 // can happily be called every frame without causing performance problems. Dynamic rescaling
nuclear@0 247 // of the rendertarget can help keep framerate up in demanding VR applications.
nuclear@0 248 // See the documentation for more details on their use.
nuclear@0 249
nuclear@0 250 // Specify a pixel density - how many rendered pixels per pixel in the physical display.
nuclear@0 251 ViewportScaleAndOffsetBothEyes SetRenderDensity ( float pixelsPerDisplayPixel );
nuclear@0 252
nuclear@0 253 // Supply the size directly. Will be clamped to the physical rendertarget size.
nuclear@0 254 ViewportScaleAndOffsetBothEyes SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight );
nuclear@0 255
nuclear@0 256 // Supply the viewport directly. This is not clamped to the physical rendertarget - careful now!
nuclear@0 257 ViewportScaleAndOffsetBothEyes SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight );
nuclear@0 258
nuclear@0 259 private:
nuclear@0 260
nuclear@0 261 // *** Modifiable State
nuclear@0 262
nuclear@0 263 StereoMode Mode;
nuclear@0 264 HmdRenderInfo Hmd;
nuclear@0 265
nuclear@0 266 float Area2DFov; // FOV range mapping to the 2D area.
nuclear@0 267
nuclear@0 268 // Only one of these three overrides can be true!
nuclear@0 269 enum SetViewportModeEnum
nuclear@0 270 {
nuclear@0 271 SVPM_Density,
nuclear@0 272 SVPM_Size,
nuclear@0 273 SVPM_Viewport,
nuclear@0 274 } SetViewportMode;
nuclear@0 275 // ...and depending which it is, one of the following are used.
nuclear@0 276 float SetViewportPixelsPerDisplayPixel;
nuclear@0 277 Sizei SetViewportSize[2];
nuclear@0 278 Recti SetViewport[2];
nuclear@0 279
nuclear@0 280 // Other overrides.
nuclear@0 281 bool OverrideLens;
nuclear@0 282 LensConfig LensOverrideLeft;
nuclear@0 283 LensConfig LensOverrideRight;
nuclear@0 284 Sizei RendertargetSize;
nuclear@0 285 bool OverrideTanHalfFov;
nuclear@0 286 FovPort FovOverrideLeft;
nuclear@0 287 FovPort FovOverrideRight;
nuclear@0 288 bool OverrideZeroIpd;
nuclear@0 289 float ZNear;
nuclear@0 290 float ZFar;
nuclear@0 291 float ExtraEyeRotationInRadians;
nuclear@0 292 bool IsRendertargetSharedByBothEyes;
nuclear@0 293 bool RightHandedProjection;
nuclear@0 294
nuclear@0 295 bool DirtyFlag; // Set when any if the modifiable state changed. Does NOT get set by SetRender*()
nuclear@0 296
nuclear@0 297 // Utility function.
nuclear@0 298 ViewportScaleAndOffsetBothEyes setupViewportScaleAndOffsets();
nuclear@0 299
nuclear@0 300 // *** Computed State
nuclear@0 301
nuclear@0 302 public: // Small hack for the config tool. Normal code should never read EyeRenderParams directly - use GetEyeRenderParams() instead.
nuclear@0 303 // 0/1 = left/right main views.
nuclear@0 304 StereoEyeParamsWithOrtho EyeRenderParams[2];
nuclear@0 305 };
nuclear@0 306
nuclear@0 307
nuclear@0 308 //-----------------------------------------------------------------------------------
nuclear@0 309 // ***** Distortion Mesh Rendering
nuclear@0 310 //
nuclear@0 311
nuclear@0 312 // Stores both texture UV coords, or tan(angle) values.
nuclear@0 313 // Use whichever set of data the specific distortion algorithm requires.
nuclear@0 314 // This struct *must* be binary compatible with CAPI ovrDistortionVertex.
nuclear@0 315 struct DistortionMeshVertexData
nuclear@0 316 {
nuclear@0 317 // [-1,+1],[-1,+1] over the entire framebuffer.
nuclear@0 318 Vector2f ScreenPosNDC;
nuclear@0 319 // [0.0-1.0] interpolation value for timewarping - see documentation for details.
nuclear@0 320 float TimewarpLerp;
nuclear@0 321 // [0.0-1.0] fade-to-black at the edges to reduce peripheral vision noise.
nuclear@0 322 float Shade;
nuclear@0 323 // The red, green, and blue vectors in tan(angle) space.
nuclear@0 324 // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
nuclear@0 325 // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
nuclear@0 326 Vector2f TanEyeAnglesR;
nuclear@0 327 Vector2f TanEyeAnglesG;
nuclear@0 328 Vector2f TanEyeAnglesB;
nuclear@0 329 };
nuclear@0 330
nuclear@0 331 // If you just want a single point on the screen transformed.
nuclear@0 332 DistortionMeshVertexData DistortionMeshMakeVertex ( Vector2f screenNDC,
nuclear@0 333 bool rightEye,
nuclear@0 334 const HmdRenderInfo &hmdRenderInfo,
nuclear@0 335 const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
nuclear@0 336
nuclear@0 337 void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
nuclear@0 338 int *pNumVertices, int *pNumTriangles,
nuclear@0 339 const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
nuclear@0 340
nuclear@0 341 // Generate distortion mesh for a eye.
nuclear@0 342 // This version requires less data then stereoParms, supporting dynamic change in render target viewport.
nuclear@0 343 void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
nuclear@0 344 int *pNumVertices, int *pNumTriangles,
nuclear@0 345 bool rightEye,
nuclear@0 346 const HmdRenderInfo &hmdRenderInfo,
nuclear@0 347 const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
nuclear@0 348
nuclear@0 349 void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices );
nuclear@0 350
nuclear@0 351
nuclear@0 352 //-----------------------------------------------------------------------------------
nuclear@0 353 // ***** Heightmap Mesh Rendering
nuclear@0 354 //
nuclear@0 355
nuclear@0 356 // Stores both texture UV coords, or tan(angle) values.
nuclear@0 357 // This struct *must* be binary compatible with CAPI ovrHeightmapVertex.
nuclear@0 358 struct HeightmapMeshVertexData
nuclear@0 359 {
nuclear@0 360 // [-1,+1],[-1,+1] over the entire framebuffer.
nuclear@0 361 Vector2f ScreenPosNDC;
nuclear@0 362 // [0.0-1.0] interpolation value for timewarping - see documentation for details.
nuclear@0 363 float TimewarpLerp;
nuclear@0 364 // The vectors in tan(angle) space.
nuclear@0 365 // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
nuclear@0 366 // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
nuclear@0 367 Vector2f TanEyeAngles;
nuclear@0 368 };
nuclear@0 369
nuclear@0 370
nuclear@0 371 void HeightmapMeshCreate ( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
nuclear@0 372 int *pNumVertices, int *pNumTriangles,
nuclear@0 373 const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
nuclear@0 374
nuclear@0 375 // Generate heightmap mesh for a eye. This version requires less data then stereoParms, supporting
nuclear@0 376 // dynamic change in render target viewport.
nuclear@0 377 void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
nuclear@0 378 int *pNumVertices, int *pNumTriangles, bool rightEye,
nuclear@0 379 const HmdRenderInfo &hmdRenderInfo, const ScaleAndOffset2D &eyeToSourceNDC );
nuclear@0 380
nuclear@0 381 void HeightmapMeshDestroy ( HeightmapMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices );
nuclear@0 382
nuclear@0 383
nuclear@0 384
nuclear@0 385 //-----------------------------------------------------------------------------------
nuclear@0 386 // ***** Prediction and timewarp.
nuclear@0 387 //
nuclear@0 388
nuclear@0 389 struct PredictionValues
nuclear@0 390 {
nuclear@0 391 // All values in seconds.
nuclear@0 392 // These are the times in seconds from a present+flush to the relevant display element.
nuclear@0 393 // The time is measured to the middle of that element's visibility window,
nuclear@0 394 // e.g. if the device is a full-persistence display, the element will be visible for
nuclear@0 395 // an entire frame, so the time measures to the middle of that period, i.e. half the frame time.
nuclear@0 396 float PresentFlushToRenderedScene; // To the overall rendered 3D scene being visible.
nuclear@0 397 float PresentFlushToTimewarpStart; // To when the first timewarped scanline will be visible.
nuclear@0 398 float PresentFlushToTimewarpEnd; // To when the last timewarped scanline will be visible.
nuclear@0 399 float PresentFlushToPresentFlush; // To the next present+flush, i.e. the ideal framerate.
nuclear@0 400
nuclear@0 401 bool WithTimewarp;
nuclear@0 402 bool WithVsync;
nuclear@0 403 };
nuclear@0 404
nuclear@0 405 // Calculates the values from the HMD info.
nuclear@0 406 PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo,
nuclear@0 407 bool withTimewarp = true,
nuclear@0 408 bool withVsync = true );
nuclear@0 409
nuclear@0 410 // Pass in an orientation used to render the scene, and then the predicted orientation
nuclear@0 411 // (which may have been computed later on, and thus is more accurate), and this
nuclear@0 412 // will return the matrix to pass to the timewarp distortion shader.
nuclear@0 413 // TODO: deal with different handedness?
nuclear@0 414 Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset );
nuclear@0 415 Matrix4f TimewarpComputePoseDeltaPosition ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset );
nuclear@0 416
nuclear@0 417
nuclear@0 418
nuclear@0 419 // TimewarpMachine helps keep track of rendered frame timing and
nuclear@0 420 // handles predictions for time-warp rendering.
nuclear@0 421 class TimewarpMachine
nuclear@0 422 {
nuclear@0 423 public:
nuclear@0 424 TimewarpMachine();
nuclear@0 425
nuclear@0 426 // Call this on and every time something about the setup changes.
nuclear@0 427 void Reset ( HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow );
nuclear@0 428
nuclear@0 429 // The only reliable time in most engines is directly after the frame-present and GPU flush-and-wait.
nuclear@0 430 // This call should be done right after that to give this system the timing info it needs.
nuclear@0 431 void AfterPresentAndFlush(double timeNow);
nuclear@0 432 // But some engines queue up the frame-present and only later find out when it actually happened.
nuclear@0 433 // They should call these two at those times.
nuclear@0 434 void AfterPresentWithoutFlush();
nuclear@0 435 void AfterPresentFinishes(double timeNow);
nuclear@0 436
nuclear@0 437 // The "average" time the rendered frame will show up,
nuclear@0 438 // and the predicted pose of the HMD at that time.
nuclear@0 439 // You usually only need to call one of these functions.
nuclear@0 440 double GetViewRenderPredictionTime();
nuclear@0 441 bool GetViewRenderPredictionPose(Tracking::SensorStateReader* reader, Posef& transform);
nuclear@0 442
nuclear@0 443
nuclear@0 444 // Timewarp prediction functions. You usually only need to call one of these three sets of functions.
nuclear@0 445
nuclear@0 446 // The predicted times that the first and last pixel will be visible on-screen.
nuclear@0 447 double GetVisiblePixelTimeStart();
nuclear@0 448 double GetVisiblePixelTimeEnd();
nuclear@0 449 // Predicted poses of the HMD at those first and last pixels.
nuclear@0 450 bool GetPredictedVisiblePixelPoseStart(Tracking::SensorStateReader* reader, Posef& transform);
nuclear@0 451 bool GetPredictedVisiblePixelPoseEnd(Tracking::SensorStateReader* reader, Posef& transform);
nuclear@0 452 // The delta matrices to feed to the timewarp distortion code,
nuclear@0 453 // given the pose that was used for rendering.
nuclear@0 454 // (usually the one returned by GetViewRenderPredictionPose() earlier)
nuclear@0 455 bool GetTimewarpDeltaStart(Tracking::SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform);
nuclear@0 456 bool GetTimewarpDeltaEnd(Tracking::SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform);
nuclear@0 457
nuclear@0 458 // Just-In-Time distortion aims to delay the second sensor reading & distortion
nuclear@0 459 // until the very last moment to improve prediction. However, it is a little scary,
nuclear@0 460 // since the delay might wait too long and miss the vsync completely!
nuclear@0 461 // Use of the JustInTime_* functions is entirely optional, and we advise allowing
nuclear@0 462 // users to turn it off in their video options to cope with odd machine configurations.
nuclear@0 463
nuclear@0 464 // What time should the app wait until before starting distortion?
nuclear@0 465 double JustInTime_GetDistortionWaitUntilTime();
nuclear@0 466
nuclear@0 467 // Used to time the distortion rendering
nuclear@0 468 bool JustInTime_NeedDistortionTimeMeasurement() const;
nuclear@0 469 void JustInTime_BeforeDistortionTimeMeasurement(double timeNow);
nuclear@0 470 void JustInTime_AfterDistortionTimeMeasurement(double timeNow);
nuclear@0 471 double JustInTime_AverageDistortionTime(); // Just for profiling - use JustInTime_GetDistortionWaitUntilTime() for functionality.
nuclear@0 472
nuclear@0 473 private:
nuclear@0 474 bool VsyncEnabled;
nuclear@0 475 HmdRenderInfo RenderInfo;
nuclear@0 476 PredictionValues CurrentPredictionValues;
nuclear@0 477
nuclear@0 478 enum { NumDistortionTimes = 100 };
nuclear@0 479 int DistortionTimeCount;
nuclear@0 480 double DistortionTimeCurrentStart;
nuclear@0 481 float DistortionTimes[NumDistortionTimes];
nuclear@0 482 float DistortionTimeAverage;
nuclear@0 483
nuclear@0 484 // Pose at which last time the eye was rendered.
nuclear@0 485 Posef EyeRenderPoses[2];
nuclear@0 486
nuclear@0 487 // Absolute time of the last present+flush
nuclear@0 488 double LastFramePresentFlushTime;
nuclear@0 489 // Seconds between present+flushes
nuclear@0 490 float PresentFlushToPresentFlushSeconds;
nuclear@0 491 // Predicted absolute time of the next present+flush
nuclear@0 492 double NextFramePresentFlushTime;
nuclear@0 493
nuclear@0 494 };
nuclear@0 495
nuclear@0 496
nuclear@0 497
nuclear@0 498 }}} // OVR::Util::Render
nuclear@0 499
nuclear@0 500 #endif