ovr_sdk

view LibOVR/Src/CAPI/CAPI_HMDState.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
line source
1 /************************************************************************************
3 Filename : CAPI_HMDState.cpp
4 Content : State associated with a single HMD
5 Created : January 24, 2014
6 Authors : Michael Antonov
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (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.
15 You may obtain a copy of the License at
17 http://www.oculusvr.com/licenses/LICENSE-3.2
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.
25 ************************************************************************************/
27 #include "CAPI_HMDState.h"
28 #include "../OVR_Profile.h"
29 #include "../Service/Service_NetClient.h"
30 #ifdef OVR_OS_WIN32
31 #include "../Displays/OVR_Win32_ShimFunctions.h"
32 #endif
35 namespace OVR { namespace CAPI {
38 // Accessed via HMDState::GetHMDStateList()
39 static OVR::List<HMDState> hmdStateList; // List of all created HMDStates.
42 //-------------------------------------------------------------------------------------
43 // ***** HMDState
45 HMDState::HMDState(const OVR::Service::HMDNetworkInfo& netInfo,
46 const OVR::HMDInfo& hmdInfo,
47 Profile* profile,
48 Service::NetClient* client) :
49 pProfile(profile),
50 pHmdDesc(0),
51 pWindow(0),
52 pClient(client),
53 NetId(netInfo.NetId),
54 NetInfo(netInfo),
55 OurHMDInfo(hmdInfo),
56 pLastError(NULL),
57 EnabledHmdCaps(0),
58 EnabledServiceHmdCaps(0),
59 SharedStateReader(),
60 TheSensorStateReader(),
61 TheLatencyTestStateReader(),
62 LatencyTestActive(false),
63 //LatencyTestDrawColor(),
64 LatencyTest2Active(false),
65 //LatencyTest2DrawColor(),
66 TimeManager(true),
67 RenderState(),
68 pRenderer(),
69 pHSWDisplay(),
70 LastFrameTimeSeconds(0.),
71 LastGetFrameTimeSeconds(0.),
72 //LastGetStringValue(),
73 RenderingConfigured(false),
74 BeginFrameCalled(false),
75 BeginFrameThreadId(),
76 RenderAPIThreadChecker(),
77 BeginFrameTimingCalled(false)
78 {
79 sharedInit(profile);
80 hmdStateList.PushBack(this);
81 }
84 HMDState::HMDState(const OVR::HMDInfo& hmdInfo, Profile* profile) :
85 pProfile(profile),
86 pHmdDesc(0),
87 pWindow(0),
88 pClient(0),
89 NetId(InvalidVirtualHmdId),
90 NetInfo(),
91 OurHMDInfo(hmdInfo),
92 pLastError(NULL),
93 EnabledHmdCaps(0),
94 EnabledServiceHmdCaps(0),
95 SharedStateReader(),
96 TheSensorStateReader(),
97 TheLatencyTestStateReader(),
98 LatencyTestActive(false),
99 //LatencyTestDrawColor(),
100 LatencyTest2Active(false),
101 //LatencyTest2DrawColor(),
102 TimeManager(true),
103 RenderState(),
104 pRenderer(),
105 pHSWDisplay(),
106 LastFrameTimeSeconds(0.),
107 LastGetFrameTimeSeconds(0.),
108 //LastGetStringValue(),
109 RenderingConfigured(false),
110 BeginFrameCalled(false),
111 BeginFrameThreadId(),
112 RenderAPIThreadChecker(),
113 BeginFrameTimingCalled(false)
114 {
115 sharedInit(profile);
116 hmdStateList.PushBack(this);
117 }
119 HMDState::~HMDState()
120 {
121 hmdStateList.Remove(this);
123 if (pClient)
124 {
125 pClient->Hmd_Release(NetId);
126 pClient = 0;
127 }
129 ConfigureRendering(0,0,0,0);
131 if (pHmdDesc)
132 {
133 OVR_FREE(pHmdDesc);
134 pHmdDesc = NULL;
135 }
136 }
138 void HMDState::sharedInit(Profile* profile)
139 {
140 // TBD: We should probably be looking up the default profile for the given
141 // device type + user if profile == 0.
142 pLastError = 0;
144 RenderState.OurHMDInfo = OurHMDInfo;
146 UpdateRenderProfile(profile);
148 OVR_ASSERT(!pHmdDesc);
149 pHmdDesc = (ovrHmdDesc*)OVR_ALLOC(sizeof(ovrHmdDesc));
150 *pHmdDesc = RenderState.GetDesc();
151 pHmdDesc->Handle = this;
153 RenderState.ClearColor[0] = 0.0f;
154 RenderState.ClearColor[1] = 0.0f;
155 RenderState.ClearColor[2] = 0.0f;
156 RenderState.ClearColor[3] = 0.0f;
158 RenderState.EnabledHmdCaps = 0;
160 TimeManager.Init(RenderState.RenderInfo);
162 /*
163 LatencyTestDrawColor[0] = 0;
164 LatencyTestDrawColor[1] = 0;
165 LatencyTestDrawColor[2] = 0;
166 */
168 RenderingConfigured = false;
169 BeginFrameCalled = false;
170 BeginFrameThreadId = 0;
171 BeginFrameTimingCalled = false;
173 // Construct the HSWDisplay. We will later reconstruct it with a specific ovrRenderAPI type if the application starts using SDK-based rendering.
174 if(!pHSWDisplay)
175 {
176 pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(ovrRenderAPI_None, pHmdDesc, RenderState);
177 pHSWDisplay->Enable(pProfile->GetBoolValue("HSW", true));
178 }
179 }
181 static Vector3f GetNeckModelFromProfile(Profile* profile)
182 {
183 OVR_ASSERT(profile);
185 float neckeye[2] = { OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL };
186 profile->GetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
188 // Make sure these are vaguely sensible values.
189 //OVR_ASSERT((neckeye[0] > 0.05f) && (neckeye[0] < 0.5f));
190 //OVR_ASSERT((neckeye[1] > 0.05f) && (neckeye[1] < 0.5f));
192 // Named for clarity
193 float NeckToEyeHorizontal = neckeye[0];
194 float NeckToEyeVertical = neckeye[1];
196 // Store the neck model
197 return Vector3f(0.0, NeckToEyeVertical, -NeckToEyeHorizontal);
198 }
200 static float GetCenterPupilDepthFromRenderInfo(HmdRenderInfo* hmdRenderInfo)
201 {
202 OVR_ASSERT(hmdRenderInfo);
204 // Find the distance from the center of the screen to the "center eye"
205 // This center eye is used by systems like rendering & audio to represent the player,
206 // and they will handle the offsets needed from there to each actual eye.
208 // HACK HACK HACK
209 // We know for DK1 the screen->lens surface distance is roughly 0.049f, and that the faceplate->lens is 0.02357f.
210 // We're going to assume(!!!!) that all HMDs have the same screen->faceplate distance.
211 // Crystal Cove was measured to be roughly 0.025 screen->faceplate which agrees with this assumption.
212 // TODO: do this properly! Update: Measured this at 0.02733 with a CC prototype, CES era (PT7), on 2/19/14 -Steve
213 float screenCenterToMidplate = 0.02733f;
214 float centerEyeRelief = hmdRenderInfo->GetEyeCenter().ReliefInMeters;
215 float CenterPupilDepth = screenCenterToMidplate + hmdRenderInfo->LensSurfaceToMidplateInMeters + centerEyeRelief;
217 return CenterPupilDepth;
218 }
220 void HMDState::UpdateRenderProfile(Profile* profile)
221 {
222 // Apply the given profile to generate a render context
223 RenderState.RenderInfo = GenerateHmdRenderInfoFromHmdInfo(RenderState.OurHMDInfo, profile);
224 RenderState.Distortion[0] = CalculateDistortionRenderDesc(StereoEye_Left, RenderState.RenderInfo, 0);
225 RenderState.Distortion[1] = CalculateDistortionRenderDesc(StereoEye_Right, RenderState.RenderInfo, 0);
227 if (pClient)
228 {
229 // Center pupil depth
230 float centerPupilDepth = GetCenterPupilDepthFromRenderInfo(&RenderState.RenderInfo);
231 pClient->SetNumberValue(GetNetId(), "CenterPupilDepth", centerPupilDepth);
233 // Neck model
234 Vector3f neckModel = GetNeckModelFromProfile(profile);
235 double neckModelArray[3] = {
236 neckModel.x,
237 neckModel.y,
238 neckModel.z
239 };
240 pClient->SetNumberValues(GetNetId(), "NeckModelVector3f", neckModelArray, 3);
242 double camerastate[7];
243 if (profile->GetDoubleValues(OVR_KEY_CAMERA_POSITION, camerastate, 7) == 0)
244 {
245 //there is no value, so we load the default
246 for (int i = 0; i < 7; i++) camerastate[i] = 0;
247 camerastate[3] = 1;//no offset. by default, give the quaternion w component value 1
248 }
249 else
251 TheSensorStateReader.setCenteredFromWorld(OVR::Posed::FromArray(camerastate));
252 }
255 }
257 HMDState* HMDState::CreateHMDState(NetClient* client, const HMDNetworkInfo& netInfo)
258 {
259 // HMDState works through a handle to service HMD....
260 HMDInfo hinfo;
261 if (!client->Hmd_GetHmdInfo(netInfo.NetId, &hinfo))
262 {
263 OVR_DEBUG_LOG(("[HMDState] Unable to get HMD info"));
264 return NULL;
265 }
267 #ifdef OVR_OS_WIN32
268 OVR_DEBUG_LOG(("Setting up display shim"));
270 // Initialize the display shim before reporting the display to the user code
271 // so that this will happen before the D3D display object is created.
272 Win32::DisplayShim::GetInstance().Update(&hinfo.ShimInfo);
273 #endif
275 Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultUserProfile(&hinfo);
276 OVR_DEBUG_LOG(("Using profile %s", pDefaultProfile->GetValue(OVR_KEY_USER)));
278 HMDState* hmds = new HMDState(netInfo, hinfo, pDefaultProfile, client);
280 if (!hmds->SharedStateReader.Open(netInfo.SharedMemoryName.ToCStr()))
281 {
282 delete hmds;
283 return NULL;
284 }
286 hmds->TheSensorStateReader.SetUpdater(hmds->SharedStateReader.Get());
287 hmds->TheLatencyTestStateReader.SetUpdater(hmds->SharedStateReader.Get());
289 return hmds;
290 }
292 HMDState* HMDState::CreateHMDState(ovrHmdType hmdType)
293 {
294 HmdTypeEnum t = HmdType_None;
295 if (hmdType == ovrHmd_DK1)
296 t = HmdType_DK1;
297 else if (hmdType == ovrHmd_DK2)
298 t = HmdType_DK2;
300 // FIXME: This does not actually grab the right user..
301 Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultProfile(t);
303 return new HMDState(CreateDebugHMDInfo(t), pDefaultProfile);
304 }
307 const OVR::List<HMDState>& HMDState::GetHMDStateList()
308 {
309 return hmdStateList;
310 }
313 //-------------------------------------------------------------------------------------
314 // *** Sensor
316 bool HMDState::ConfigureTracking(unsigned supportedCaps, unsigned requiredCaps)
317 {
318 return pClient ? pClient->Hmd_ConfigureTracking(NetId, supportedCaps, requiredCaps) : true;
319 }
321 void HMDState::ResetTracking()
322 {
323 if (pClient) pClient->Hmd_ResetTracking(NetId);
324 }
326 // Re-center the orientation.
327 void HMDState::RecenterPose()
328 {
329 TheSensorStateReader.RecenterPose();
330 }
332 // Returns prediction for time.
333 ovrTrackingState HMDState::PredictedTrackingState(double absTime)
334 {
335 Tracking::TrackingState ss;
336 TheSensorStateReader.GetSensorStateAtTime(absTime, ss);
338 // Zero out the status flags
339 if (!pClient || !pClient->IsConnected(false, false))
340 {
341 ss.StatusFlags = 0;
342 }
344 return ss;
345 }
347 void HMDState::SetEnabledHmdCaps(unsigned hmdCaps)
348 {
349 if (OurHMDInfo.HmdType < HmdType_DK2)
350 {
351 // disable low persistence and pentile.
352 hmdCaps &= ~ovrHmdCap_LowPersistence;
353 hmdCaps &= ~ovrHmdCap_DirectPentile;
355 // disable dynamic prediction using the internal latency tester
356 hmdCaps &= ~ovrHmdCap_DynamicPrediction;
357 }
359 if (OurHMDInfo.HmdType >= HmdType_DK2)
360 {
361 if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_DynamicPrediction)
362 {
363 // DynamicPrediction change
364 TimeManager.ResetFrameTiming(TimeManager.GetFrameTiming().FrameIndex,
365 (hmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
366 RenderingConfigured);
367 }
368 }
370 // Pentile unsupported on everything right now.
371 hmdCaps &= ~ovrHmdCap_DirectPentile;
373 if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoVSync)
374 {
375 TimeManager.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true);
376 }
378 if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoMirrorToWindow)
379 {
380 #ifdef OVR_OS_WIN32
381 Win32::DisplayShim::GetInstance().UseMirroring = (hmdCaps & ovrHmdCap_NoMirrorToWindow) ?
382 false : true;
383 if (pWindow)
384 { // Force window repaint so that stale mirrored image doesn't persist.
385 ::InvalidateRect((HWND)pWindow, 0, true);
386 }
387 #endif
388 }
390 // TBD: Should this include be only the rendering flags? Otherwise, bits that failed
391 // modification in Hmd_SetEnabledCaps may mis-match...
392 EnabledHmdCaps = hmdCaps & ovrHmdCap_Writable_Mask;
393 RenderState.EnabledHmdCaps = EnabledHmdCaps;
396 // If any of the modifiable service caps changed, call on the service.
397 unsigned prevServiceCaps = EnabledServiceHmdCaps & ovrHmdCap_Writable_Mask;
398 unsigned newServiceCaps = hmdCaps & ovrHmdCap_Writable_Mask & ovrHmdCap_Service_Mask;
400 if (prevServiceCaps ^ newServiceCaps)
401 {
402 EnabledServiceHmdCaps = pClient ? pClient->Hmd_SetEnabledCaps(NetId, newServiceCaps)
403 : newServiceCaps;
404 }
405 }
408 unsigned HMDState::SetEnabledHmdCaps()
409 {
410 unsigned serviceCaps = pClient ? pClient->Hmd_GetEnabledCaps(NetId) :
411 EnabledServiceHmdCaps;
413 return serviceCaps & ((~ovrHmdCap_Service_Mask) | EnabledHmdCaps);
414 }
417 //-------------------------------------------------------------------------------------
418 // ***** Property Access
420 // FIXME: Remove the EGetBoolValue stuff and do it with a "Server:" prefix, so we do not
421 // need to keep a white-list of keys. This is also way cool because it allows us to add
422 // new settings keys from outside CAPI that can modify internal server data.
424 bool HMDState::getBoolValue(const char* propertyName, bool defaultVal)
425 {
426 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetBoolValue, propertyName))
427 {
428 return NetClient::GetInstance()->GetBoolValue(GetNetId(), propertyName, defaultVal);
429 }
430 else if (pProfile)
431 {
432 return pProfile->GetBoolValue(propertyName, defaultVal);
433 }
434 return defaultVal;
435 }
437 bool HMDState::setBoolValue(const char* propertyName, bool value)
438 {
439 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetBoolValue, propertyName))
440 {
441 return NetClient::GetInstance()->SetBoolValue(GetNetId(), propertyName, value);
442 }
444 return false;
445 }
447 int HMDState::getIntValue(const char* propertyName, int defaultVal)
448 {
449 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetIntValue, propertyName))
450 {
451 return NetClient::GetInstance()->GetIntValue(GetNetId(), propertyName, defaultVal);
452 }
453 else if (pProfile)
454 {
455 return pProfile->GetIntValue(propertyName, defaultVal);
456 }
457 return defaultVal;
458 }
460 bool HMDState::setIntValue(const char* propertyName, int value)
461 {
462 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetIntValue, propertyName))
463 {
464 return NetClient::GetInstance()->SetIntValue(GetNetId(), propertyName, value);
465 }
467 return false;
468 }
470 float HMDState::getFloatValue(const char* propertyName, float defaultVal)
471 {
472 if (OVR_strcmp(propertyName, "LensSeparation") == 0)
473 {
474 return OurHMDInfo.LensSeparationInMeters;
475 }
476 else if (OVR_strcmp(propertyName, "VsyncToNextVsync") == 0)
477 {
478 return OurHMDInfo.Shutter.VsyncToNextVsync;
479 }
480 else if (OVR_strcmp(propertyName, "PixelPersistence") == 0)
481 {
482 return OurHMDInfo.Shutter.PixelPersistence;
483 }
484 else if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetNumberValue, propertyName))
485 {
486 return (float)NetClient::GetInstance()->GetNumberValue(GetNetId(), propertyName, defaultVal);
487 }
488 else if (pProfile)
489 {
490 return pProfile->GetFloatValue(propertyName, defaultVal);
491 }
493 return defaultVal;
494 }
496 bool HMDState::setFloatValue(const char* propertyName, float value)
497 {
498 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetNumberValue, propertyName))
499 {
500 return NetClient::GetInstance()->SetNumberValue(GetNetId(), propertyName, value);
501 }
503 return false;
504 }
506 static unsigned CopyFloatArrayWithLimit(float dest[], unsigned destSize,
507 float source[], unsigned sourceSize)
508 {
509 unsigned count = Alg::Min(destSize, sourceSize);
510 for (unsigned i = 0; i < count; i++)
511 dest[i] = source[i];
512 return count;
513 }
515 unsigned HMDState::getFloatArray(const char* propertyName, float values[], unsigned arraySize)
516 {
517 if (arraySize)
518 {
519 if (OVR_strcmp(propertyName, "ScreenSize") == 0)
520 {
521 float data[2] = { OurHMDInfo.ScreenSizeInMeters.w, OurHMDInfo.ScreenSizeInMeters.h };
523 return CopyFloatArrayWithLimit(values, arraySize, data, 2);
524 }
525 else if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
526 {
527 return CopyFloatArrayWithLimit(values, arraySize, RenderState.ClearColor, 4);
528 }
529 else if (OVR_strcmp(propertyName, "DK2Latency") == 0)
530 {
531 if (OurHMDInfo.HmdType != HmdType_DK2)
532 {
533 return 0;
534 }
536 union {
537 struct X {
538 float latencyRender, latencyTimewarp, latencyPostPresent;
539 } x;
540 float data[3];
541 } m;
543 static_assert(sizeof(m.x)==sizeof(m.data), "sizeof(struct X) failure");
545 TimeManager.GetLatencyTimings(m.x.latencyRender, m.x.latencyTimewarp, m.x.latencyPostPresent);
547 return CopyFloatArrayWithLimit(values, arraySize, m.data, 3);
548 }
549 else if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetNumberValues, propertyName))
550 {
551 // Convert floats to doubles
552 double* da = new double[arraySize];
553 for (int i = 0; i < (int)arraySize; ++i)
554 {
555 da[i] = values[i];
556 }
558 int count = NetClient::GetInstance()->GetNumberValues(GetNetId(), propertyName, da, (int)arraySize);
560 for (int i = 0; i < count; ++i)
561 {
562 values[i] = (float)da[i];
563 }
565 delete[] da;
567 return count;
568 }
569 else if (pProfile)
570 {
571 // TBD: Not quite right. Should update profile interface, so that
572 // we can return 0 in all conditions if property doesn't exist.
574 return pProfile->GetFloatValues(propertyName, values, arraySize);
575 }
576 }
578 return 0;
579 }
581 bool HMDState::setFloatArray(const char* propertyName, float values[], unsigned arraySize)
582 {
583 if (!arraySize)
584 {
585 return false;
586 }
588 if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
589 {
590 CopyFloatArrayWithLimit(RenderState.ClearColor, 4, values, arraySize);
591 return true;
592 }
594 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetNumberValues, propertyName))
595 {
596 double* da = new double[arraySize];
597 for (int i = 0; i < (int)arraySize; ++i)
598 {
599 da[i] = values[i];
600 }
602 bool result = NetClient::GetInstance()->SetNumberValues(GetNetId(), propertyName, da, arraySize);
604 delete[] da;
606 return result;
607 }
609 return false;
610 }
612 const char* HMDState::getString(const char* propertyName, const char* defaultVal)
613 {
614 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetStringValue, propertyName))
615 {
616 return NetClient::GetInstance()->GetStringValue(GetNetId(), propertyName, defaultVal);
617 }
619 if (pProfile)
620 {
621 LastGetStringValue[0] = 0;
622 if (pProfile->GetValue(propertyName, LastGetStringValue, sizeof(LastGetStringValue)))
623 {
624 return LastGetStringValue;
625 }
626 }
628 return defaultVal;
629 }
631 bool HMDState::setString(const char* propertyName, const char* value)
632 {
633 if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetStringValue, propertyName))
634 {
635 return NetClient::GetInstance()->SetStringValue(GetNetId(), propertyName, value);
636 }
638 return false;
639 }
642 //-------------------------------------------------------------------------------------
643 // *** Latency Test
645 bool HMDState::ProcessLatencyTest(unsigned char rgbColorOut[3])
646 {
647 return NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut);
648 }
650 //-------------------------------------------------------------------------------------
651 // *** Rendering
653 bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
654 const ovrFovPort eyeFovIn[2],
655 const ovrRenderAPIConfig* apiConfig,
656 unsigned distortionCaps)
657 {
658 ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_ConfigureRendering");
660 // null -> shut down.
661 if (!apiConfig)
662 {
663 if (pHSWDisplay)
664 {
665 pHSWDisplay->Shutdown();
666 pHSWDisplay.Clear();
667 }
669 if (pRenderer)
670 pRenderer.Clear();
671 RenderingConfigured = false;
672 return true;
673 }
675 if (pRenderer &&
676 (apiConfig->Header.API != pRenderer->GetRenderAPI()))
677 {
678 // Shutdown old renderer.
679 if (pHSWDisplay)
680 {
681 pHSWDisplay->Shutdown();
682 pHSWDisplay.Clear();
683 }
685 if (pRenderer)
686 pRenderer.Clear();
687 }
689 distortionCaps = distortionCaps & pHmdDesc->DistortionCaps;
691 // Step 1: do basic setup configuration
692 RenderState.EnabledHmdCaps = EnabledHmdCaps; // This is a copy... Any cleaner way?
693 RenderState.DistortionCaps = distortionCaps;
694 RenderState.EyeRenderDesc[0] = RenderState.CalcRenderDesc(ovrEye_Left, eyeFovIn[0]);
695 RenderState.EyeRenderDesc[1] = RenderState.CalcRenderDesc(ovrEye_Right, eyeFovIn[1]);
696 eyeRenderDescOut[0] = RenderState.EyeRenderDesc[0];
697 eyeRenderDescOut[1] = RenderState.EyeRenderDesc[1];
699 TimeManager.ResetFrameTiming(0,
700 (EnabledHmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
701 true);
703 LastFrameTimeSeconds = 0.0f;
705 // Set RenderingConfigured early to avoid ASSERTs in renderer initialization.
706 RenderingConfigured = true;
708 if (!pRenderer)
709 {
710 pRenderer = *DistortionRenderer::APICreateRegistry
711 [apiConfig->Header.API](pHmdDesc, TimeManager, RenderState);
712 }
714 if (!pRenderer ||
715 !pRenderer->Initialize(apiConfig))
716 {
717 RenderingConfigured = false;
718 return false;
719 }
721 // Setup the Health and Safety Warning display system.
722 if(pHSWDisplay && (pHSWDisplay->GetRenderAPIType() != apiConfig->Header.API)) // If we need to reconstruct the HSWDisplay for a different graphics API type, delete the existing display.
723 {
724 pHSWDisplay->Shutdown();
725 pHSWDisplay.Clear();
726 }
728 if(!pHSWDisplay) // Use * below because that for of operator= causes it to inherit the refcount the factory gave the object.
729 {
730 pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(apiConfig->Header.API, pHmdDesc, RenderState);
731 pHSWDisplay->Enable(pProfile->GetBoolValue("HSW", true));
732 }
734 if (pHSWDisplay)
735 pHSWDisplay->Initialize(apiConfig); // This is potentially re-initializing it with a new config.
737 return true;
738 }
741 void HMDState::SubmitEyeTextures(const ovrPosef renderPose[2],
742 const ovrTexture eyeTexture[2])
743 {
744 RenderState.EyeRenderPoses[0] = renderPose[0];
745 RenderState.EyeRenderPoses[1] = renderPose[1];
747 if (pRenderer)
748 {
749 pRenderer->SubmitEye(0, &eyeTexture[0]);
750 pRenderer->SubmitEye(1, &eyeTexture[1]);
751 }
752 }
755 // I appreciate this is not an idea place for this function, but it didn't seem to be
756 // being linked properly when in OVR_CAPI.cpp.
757 // Please relocate if you know of a better place
758 ovrBool ovrHmd_CreateDistortionMeshInternal( ovrHmdStruct * hmd,
759 ovrEyeType eyeType, ovrFovPort fov,
760 unsigned int distortionCaps,
761 ovrDistortionMesh *meshData,
762 float overrideEyeReliefIfNonZero )
763 {
764 if (!meshData)
765 return 0;
766 HMDState* hmds = (HMDState*)hmd;
768 // Not used now, but Chromatic flag or others could possibly be checked for in the future.
769 OVR_UNUSED1(distortionCaps);
771 #if defined (OVR_CC_MSVC)
772 static_assert(sizeof(DistortionMeshVertexData) == sizeof(ovrDistortionVertex), "DistortionMeshVertexData size mismatch");
773 #endif
775 // *** Calculate a part of "StereoParams" needed for mesh generation
777 // Note that mesh distortion generation is invariant of RenderTarget UVs, allowing
778 // render target size and location to be changed after the fact dynamically.
779 // eyeToSourceUV is computed here for convenience, so that users don't need
780 // to call ovrHmd_GetRenderScaleAndOffset unless changing RT dynamically.
782 const HmdRenderInfo& hmdri = hmds->RenderState.RenderInfo;
783 StereoEye stereoEye = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
785 DistortionRenderDesc& distortion = hmds->RenderState.Distortion[eyeType];
786 if (overrideEyeReliefIfNonZero)
787 {
788 distortion.Lens = GenerateLensConfigFromEyeRelief(overrideEyeReliefIfNonZero,hmdri);
789 }
791 // Find the mapping from TanAngle space to target NDC space.
792 ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
794 int triangleCount = 0;
795 int vertexCount = 0;
797 DistortionMeshCreate((DistortionMeshVertexData**)&meshData->pVertexData,
798 (uint16_t**)&meshData->pIndexData,
799 &vertexCount, &triangleCount,
800 (stereoEye == StereoEye_Right),
801 hmdri, distortion, eyeToSourceNDC);
803 if (meshData->pVertexData)
804 {
805 // Convert to index
806 meshData->IndexCount = triangleCount * 3;
807 meshData->VertexCount = vertexCount;
808 return 1;
809 }
811 return 0;
812 }
816 }} // namespace OVR::CAPI