summaryrefslogtreecommitdiffhomepage
path: root/src/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core.c')
-rw-r--r--src/core.c155
1 files changed, 154 insertions, 1 deletions
diff --git a/src/core.c b/src/core.c
index 664bac02..9be1dc06 100644
--- a/src/core.c
+++ b/src/core.c
@@ -80,7 +80,10 @@
* for linkage
*
* #define SUPPORT_DATA_STORAGE
-* Support saving binary data automatically to a generated storage.data file. This file is managed internally.
+* Support saving binary data automatically to a generated storage.data file. This file is managed internally
+*
+* #define SUPPORT_VR_SIMULATOR
+* Support VR simulation functionality (stereo rendering)
*
* DEPENDENCIES:
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
@@ -473,6 +476,15 @@ typedef struct CoreData {
unsigned long long base; // Base time measure for hi-res timer
#endif
} Time;
+#if defined(SUPPORT_VR_SIMULATOR)
+ struct {
+ VrStereoConfig config; // VR stereo configuration for simulator
+ unsigned int stereoFboId; // VR stereo rendering framebuffer id
+ unsigned int stereoTexId; // VR stereo color texture (attached to framebuffer)
+ bool simulatorReady; // VR simulator ready flag
+ bool stereoRender; // VR stereo rendering enabled/disabled flag
+ } Vr; // VR simulator data
+#endif // SUPPORT_VR_SIMULATOR
} CoreData;
//----------------------------------------------------------------------------------
@@ -2000,6 +2012,147 @@ void EndTextureMode(void)
CORE.Window.currentFbo.height = CORE.Window.screen.height;
}
+
+#if defined(SUPPORT_VR_SIMULATOR)
+// Init VR simulator for selected device parameters
+void InitVrSimulator(VrDeviceInfo device)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ // Reset CORE.Vr.config for a new values assignment
+ memset(&CORE.Vr.config, 0, sizeof(VrStereoConfig));
+
+ // Compute aspect ratio
+ float aspect = ((float)device.hResolution*0.5f)/(float)device.vResolution;
+
+ // Compute lens parameters
+ float lensShift = (device.hScreenSize*0.25f - device.lensSeparationDistance*0.5f)/device.hScreenSize;
+ CORE.Vr.config.leftLensCenter[0] = 0.25f + lensShift;
+ CORE.Vr.config.leftLensCenter[1] = 0.5f;
+ CORE.Vr.config.rightLensCenter[0] = 0.75f - lensShift;
+ CORE.Vr.config.rightLensCenter[1] = 0.5f;
+ CORE.Vr.config.leftScreenCenter[0] = 0.25f;
+ CORE.Vr.config.leftScreenCenter[1] = 0.5f;
+ CORE.Vr.config.rightScreenCenter[0] = 0.75f;
+ CORE.Vr.config.rightScreenCenter[1] = 0.5f;
+
+ // Compute distortion scale parameters
+ // NOTE: To get lens max radius, lensShift must be normalized to [-1..1]
+ float lensRadius = fabsf(-1.0f - 4.0f*lensShift);
+ float lensRadiusSq = lensRadius*lensRadius;
+ float distortionScale = device.lensDistortionValues[0] +
+ device.lensDistortionValues[1]*lensRadiusSq +
+ device.lensDistortionValues[2]*lensRadiusSq*lensRadiusSq +
+ device.lensDistortionValues[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq;
+
+ float normScreenWidth = 0.5f;
+ float normScreenHeight = 1.0f;
+ CORE.Vr.config.scaleIn[0] = 2.0f/normScreenWidth;
+ CORE.Vr.config.scaleIn[1] = 2.0f/normScreenHeight/aspect;
+ CORE.Vr.config.scale[0] = normScreenWidth*0.5f/distortionScale;
+ CORE.Vr.config.scale[1] = normScreenHeight*0.5f*aspect/distortionScale;
+
+ // Fovy is normally computed with: 2*atan2f(device.vScreenSize, 2*device.eyeToScreenDistance)
+ // ...but with lens distortion it is increased (see Oculus SDK Documentation)
+ //float fovy = 2.0f*atan2f(device.vScreenSize*0.5f*distortionScale, device.eyeToScreenDistance); // Really need distortionScale?
+ float fovy = 2.0f*(float)atan2f(device.vScreenSize*0.5f, device.eyeToScreenDistance);
+
+ // Compute camera projection matrices
+ float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1]
+ Matrix proj = MatrixPerspective(fovy, aspect, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);
+ rlSetMatrixProjectionStereo(MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)), MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)));
+
+ // Compute camera transformation matrices
+ // NOTE: Camera movement might seem more natural if we model the head.
+ // Our axis of rotation is the base of our head, so we might want to add
+ // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions.
+ rlSetMatrixViewOffsetStereo(MatrixTranslate(-device.interpupillaryDistance*0.5f, 0.075f, 0.045f), MatrixTranslate(device.interpupillaryDistance*0.5f, 0.075f, 0.045f));
+
+ // Compute eyes Viewports
+ /*
+ CORE.Vr.config.eyeViewportRight[0] = 0;
+ CORE.Vr.config.eyeViewportRight[1] = 0;
+ CORE.Vr.config.eyeViewportRight[2] = device.hResolution/2;
+ CORE.Vr.config.eyeViewportRight[3] = device.vResolution;
+
+ CORE.Vr.config.eyeViewportLeft[0] = device.hResolution/2;
+ CORE.Vr.config.eyeViewportLeft[1] = 0;
+ CORE.Vr.config.eyeViewportLeft[2] = device.hResolution/2;
+ CORE.Vr.config.eyeViewportLeft[3] = device.vResolution;
+ */
+
+ CORE.Vr.simulatorReady = true;
+#else
+ TRACELOG(LOG_WARNING, "RLGL: VR Simulator not supported on OpenGL 1.1");
+#endif
+}
+
+// Update VR tracking (position and orientation) and camera
+// NOTE: Camera (position, target, up) gets update with head tracking information
+void UpdateVrTracking(Camera *camera)
+{
+ // TODO: Simulate 1st person camera system
+}
+
+// Close VR simulator for current device
+void CloseVrSimulator(void)
+{
+ CORE.Vr.simulatorReady = false;
+}
+
+// Get stereo rendering configuration parameters
+VrStereoConfig GetVrConfig(VrDeviceInfo device)
+{
+ VrStereoConfig config = { 0 };
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ config = CORE.Vr.config;
+#endif
+ return config;
+}
+
+// Detect if VR simulator is running
+bool IsVrSimulatorReady(void)
+{
+ return CORE.Vr.simulatorReady;
+}
+
+// Begin VR drawing configuration
+void BeginVrDrawing(RenderTexture2D target)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ if (CORE.Vr.simulatorReady)
+ {
+ rlEnableFramebuffer(target.id); // Setup framebuffer for stereo rendering
+ //glEnable(GL_FRAMEBUFFER_SRGB); // Enable SRGB framebuffer (only if required)
+
+ //rlViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
+ rlClearScreenBuffers(); // Clear current framebuffer
+
+ rlEnableStereoRender();
+ }
+#endif
+}
+
+// End VR drawing process (and desktop mirror)
+void EndVrDrawing(void)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ if (CORE.Vr.simulatorReady)
+ {
+ rlDisableStereoRender();
+
+ rlDisableFramebuffer(); // Unbind current framebuffer
+
+ // Reset viewport and default projection-modelview matrices
+ rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
+ SetMatrixProjection(MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0));
+ SetMatrixModelview(MatrixIdentity());
+
+ rlDisableDepthTest();
+ }
+#endif
+}
+#endif // SUPPORT_VR_SIMULATOR
+
// Begin scissor mode (define screen area for following drawing)
// NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
void BeginScissorMode(int x, int y, int width, int height)