You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

507 lines
21 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [core] example - Oculus Rift CV1
  4. *
  5. * Compile example using:
  6. * gcc -o $(NAME_PART).exe $(FILE_NAME) -I..\src\external -I..\src\external\OculusSDK\LibOVR\Include /
  7. * -L. -L..\src\external\OculusSDK\LibOVR -lLibOVRRT32_1 -lraylib -lglfw3 -lopengl32 -lgdi32 -std=c99 /
  8. * -Wl,-allow-multiple-definition
  9. *
  10. * #define SUPPORT_OCULUS_RIFT_CV1 / RLGL_OCULUS_SUPPORT
  11. * Enable Oculus Rift CV1 functionality
  12. *
  13. * This example has been created using raylib 1.5 (www.raylib.com)
  14. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  15. *
  16. * Copyright (c) 2016 Ramon Santamaria (@raysan5)
  17. *
  18. ********************************************************************************************/
  19. #include "raylib.h"
  20. #include "glad.h" // Required for: OpenGL types and functions declarations
  21. #include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality
  22. #include <string.h> // Required for: memset()
  23. #include <stdlib.h> // Required for: exit()
  24. #include <stdio.h> // required for: vfprintf()
  25. #include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
  26. #define RLGL_OCULUS_SUPPORT // Enable Oculus Rift code
  27. #if defined(RLGL_OCULUS_SUPPORT)
  28. #include "OVR_CAPI_GL.h" // Oculus SDK for OpenGL
  29. #endif
  30. //----------------------------------------------------------------------------------
  31. // Defines and Macros
  32. //----------------------------------------------------------------------------------
  33. // ...
  34. //----------------------------------------------------------------------------------
  35. // Types and Structures Definition
  36. //----------------------------------------------------------------------------------
  37. #if defined(RLGL_OCULUS_SUPPORT)
  38. // Oculus buffer type
  39. typedef struct OculusBuffer {
  40. ovrTextureSwapChain textureChain;
  41. GLuint depthId;
  42. GLuint fboId;
  43. int width;
  44. int height;
  45. } OculusBuffer;
  46. // Oculus mirror texture type
  47. typedef struct OculusMirror {
  48. ovrMirrorTexture texture;
  49. GLuint fboId;
  50. int width;
  51. int height;
  52. } OculusMirror;
  53. // Oculus layer type
  54. typedef struct OculusLayer {
  55. ovrViewScaleDesc viewScaleDesc;
  56. ovrLayerEyeFov eyeLayer; // layer 0
  57. //ovrLayerQuad quadLayer; // TODO: layer 1: '2D' quad for GUI
  58. Matrix eyeProjections[2];
  59. int width;
  60. int height;
  61. } OculusLayer;
  62. #endif
  63. //----------------------------------------------------------------------------------
  64. // Global Variables Definition
  65. //----------------------------------------------------------------------------------
  66. #if defined(RLGL_OCULUS_SUPPORT)
  67. // OVR device variables
  68. static ovrSession session; // Oculus session (pointer to ovrHmdStruct)
  69. static ovrHmdDesc hmdDesc; // Oculus device descriptor parameters
  70. static ovrGraphicsLuid luid; // Oculus locally unique identifier for the program (64 bit)
  71. static OculusLayer layer; // Oculus drawing layer (similar to photoshop)
  72. static OculusBuffer buffer; // Oculus internal buffers (texture chain and fbo)
  73. static OculusMirror mirror; // Oculus mirror texture and fbo
  74. static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain
  75. #endif
  76. //----------------------------------------------------------------------------------
  77. // Module specific Functions Declaration
  78. //----------------------------------------------------------------------------------
  79. #if defined(RLGL_OCULUS_SUPPORT)
  80. static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
  81. static void CloseOculusDevice(void); // Close Oculus device
  82. static void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking
  83. static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
  84. static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
  85. static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers
  86. static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); // Unload texture required buffers
  87. static OculusMirror LoadOculusMirror(ovrSession session, int width, int height); // Load Oculus mirror buffers
  88. static void UnloadOculusMirror(ovrSession session, OculusMirror mirror); // Unload Oculus mirror buffers
  89. static void BlitOculusMirror(ovrSession session, OculusMirror mirror); // Copy Oculus screen buffer to mirror texture
  90. static OculusLayer InitOculusLayer(ovrSession session); // Init Oculus layer (similar to photoshop)
  91. static Matrix FromOvrMatrix(ovrMatrix4f ovrM); // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct
  92. #endif
  93. int main()
  94. {
  95. // Initialization
  96. //--------------------------------------------------------------------------------------
  97. int screenWidth = 1080;
  98. int screenHeight = 600;
  99. // NOTE: screenWidth/screenHeight should match VR device aspect ratio
  100. InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift");
  101. bool vrDeviceReady = InitOculusDevice(); // Init VR device Oculus Rift CV1
  102. if (!vrDeviceReady) InitVrSimulator(HMD_OCULUS_RIFT_CV1); // Init VR simulator if device fails
  103. // Define the camera to look into our 3d world
  104. Camera camera;
  105. camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position
  106. camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
  107. camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
  108. camera.fovy = 60.0f; // Camera field-of-view Y
  109. Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
  110. SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode
  111. SetTargetFPS(90); // Set our game to run at 90 frames-per-second
  112. //--------------------------------------------------------------------------------------
  113. // Main game loop
  114. while (!WindowShouldClose()) // Detect window close button or ESC key
  115. {
  116. // Update
  117. //----------------------------------------------------------------------------------
  118. if (!vrDeviceReady) UpdateCamera(&camera); // Update camera (simulator mode)
  119. else UpdateOculusTracking(&camera); // Update camera with device tracking data
  120. if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); // Toggle VR mode
  121. //----------------------------------------------------------------------------------
  122. // Draw
  123. //----------------------------------------------------------------------------------
  124. BeginDrawing();
  125. ClearBackground(RAYWHITE);
  126. if (vrDeviceReady) BeginOculusDrawing();
  127. else BeginVrDrawing();
  128. Begin3dMode(camera);
  129. DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
  130. DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
  131. DrawGrid(40, 1.0f);
  132. End3dMode();
  133. if (vrDeviceReady) EndOculusDrawing();
  134. else EndVrDrawing();
  135. DrawFPS(10, 10);
  136. EndDrawing();
  137. //----------------------------------------------------------------------------------
  138. }
  139. // De-Initialization
  140. //--------------------------------------------------------------------------------------
  141. if (vrDeviceReady) CloseOculusDevice();
  142. else CloseVrSimulator();
  143. CloseWindow(); // Close window and OpenGL context
  144. //--------------------------------------------------------------------------------------
  145. return 0;
  146. }
  147. //----------------------------------------------------------------------------------
  148. // Module specific Functions Definition
  149. //----------------------------------------------------------------------------------
  150. #if defined(RLGL_OCULUS_SUPPORT)
  151. // Set internal projection and modelview matrix depending on eyes tracking data
  152. static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView)
  153. {
  154. Matrix eyeProjection = matProjection;
  155. Matrix eyeModelView = matModelView;
  156. glViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y,
  157. layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h);
  158. Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x,
  159. layer.eyeLayer.RenderPose[eye].Orientation.y,
  160. layer.eyeLayer.RenderPose[eye].Orientation.z,
  161. layer.eyeLayer.RenderPose[eye].Orientation.w };
  162. QuaternionInvert(&eyeRenderPose);
  163. Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose);
  164. Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x,
  165. -layer.eyeLayer.RenderPose[eye].Position.y,
  166. -layer.eyeLayer.RenderPose[eye].Position.z);
  167. Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement
  168. eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement
  169. eyeProjection = layer.eyeProjections[eye];
  170. }
  171. // Initialize Oculus device (returns true if success)
  172. static bool InitOculusDevice(void)
  173. {
  174. bool oculusReady = false;
  175. ovrResult result = ovr_Initialize(NULL);
  176. if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device");
  177. else
  178. {
  179. result = ovr_Create(&session, &luid);
  180. if (OVR_FAILURE(result))
  181. {
  182. TraceLog(LOG_WARNING, "OVR: Could not create Oculus session");
  183. ovr_Shutdown();
  184. }
  185. else
  186. {
  187. hmdDesc = ovr_GetHmdDesc(session);
  188. TraceLog(LOG_INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
  189. TraceLog(LOG_INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
  190. TraceLog(LOG_INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
  191. TraceLog(LOG_INFO, "OVR: Product Type: %i", hmdDesc.Type);
  192. //TraceLog(LOG_INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber);
  193. TraceLog(LOG_INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
  194. // NOTE: Oculus mirror is set to defined screenWidth and screenHeight...
  195. // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2)
  196. // Initialize Oculus Buffers
  197. layer = InitOculusLayer(session);
  198. buffer = LoadOculusBuffer(session, layer.width, layer.height);
  199. mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); // NOTE: hardcoded...
  200. layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
  201. // Recenter OVR tracking origin
  202. ovr_RecenterTrackingOrigin(session);
  203. oculusReady = true;
  204. }
  205. }
  206. return oculusReady;
  207. }
  208. // Close Oculus device (and unload buffers)
  209. static void CloseOculusDevice(void)
  210. {
  211. UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer
  212. UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers
  213. ovr_Destroy(session); // Free Oculus session data
  214. ovr_Shutdown(); // Close Oculus device connection
  215. }
  216. // Update Oculus head position-orientation tracking
  217. static void UpdateOculusTracking(Camera *camera)
  218. {
  219. frameIndex++;
  220. ovrPosef eyePoses[2];
  221. ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
  222. layer.eyeLayer.RenderPose[0] = eyePoses[0];
  223. layer.eyeLayer.RenderPose[1] = eyePoses[1];
  224. // TODO: Update external camera with eyePoses data (position, orientation)
  225. // NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later
  226. // it will be useful for the user to draw, lets say, billboards oriented to camera
  227. // Get session status information
  228. ovrSessionStatus sessionStatus;
  229. ovr_GetSessionStatus(session, &sessionStatus);
  230. if (sessionStatus.ShouldQuit) TraceLog(LOG_WARNING, "OVR: Session should quit...");
  231. if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session);
  232. //if (sessionStatus.HmdPresent) // HMD is present.
  233. //if (sessionStatus.DisplayLost) // HMD was unplugged or the display driver was manually disabled or encountered a TDR.
  234. //if (sessionStatus.HmdMounted) // HMD is on the user's head.
  235. //if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD.
  236. }
  237. // Setup Oculus buffers for drawing
  238. static void BeginOculusDrawing(void)
  239. {
  240. GLuint currentTexId;
  241. int currentIndex;
  242. ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, &currentIndex);
  243. ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, &currentTexId);
  244. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
  245. glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0);
  246. //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded
  247. }
  248. // Finish Oculus drawing and blit framebuffer to mirror
  249. static void EndOculusDrawing(void)
  250. {
  251. // Unbind current framebuffer (Oculus buffer)
  252. glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
  253. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  254. ovr_CommitTextureSwapChain(session, buffer.textureChain);
  255. ovrLayerHeader *layers = &layer.eyeLayer.Header;
  256. ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1);
  257. // Blit mirror texture to back buffer
  258. BlitOculusMirror(session, mirror);
  259. }
  260. // Load Oculus required buffers: texture-swap-chain, fbo, texture-depth
  261. static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height)
  262. {
  263. OculusBuffer buffer;
  264. buffer.width = width;
  265. buffer.height = height;
  266. // Create OVR texture chain
  267. ovrTextureSwapChainDesc desc = {};
  268. desc.Type = ovrTexture_2D;
  269. desc.ArraySize = 1;
  270. desc.Width = width;
  271. desc.Height = height;
  272. desc.MipLevels = 1;
  273. desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; // Requires glEnable(GL_FRAMEBUFFER_SRGB);
  274. desc.SampleCount = 1;
  275. desc.StaticImage = ovrFalse;
  276. ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain);
  277. if (!OVR_SUCCESS(result)) TraceLog(LOG_WARNING, "OVR: Failed to create swap textures buffer");
  278. int textureCount = 0;
  279. ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount);
  280. if (!OVR_SUCCESS(result) || !textureCount) TraceLog(LOG_WARNING, "OVR: Unable to count swap chain textures");
  281. for (int i = 0; i < textureCount; ++i)
  282. {
  283. GLuint chainTexId;
  284. ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, i, &chainTexId);
  285. glBindTexture(GL_TEXTURE_2D, chainTexId);
  286. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  287. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  288. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  289. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  290. }
  291. glBindTexture(GL_TEXTURE_2D, 0);
  292. /*
  293. // Setup framebuffer object (using depth texture)
  294. glGenFramebuffers(1, &buffer.fboId);
  295. glGenTextures(1, &buffer.depthId);
  296. glBindTexture(GL_TEXTURE_2D, buffer.depthId);
  297. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  298. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  299. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  300. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  301. glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
  302. */
  303. // Setup framebuffer object (using depth renderbuffer)
  304. glGenFramebuffers(1, &buffer.fboId);
  305. glGenRenderbuffers(1, &buffer.depthId);
  306. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
  307. glBindRenderbuffer(GL_RENDERBUFFER, buffer.depthId);
  308. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, buffer.width, buffer.height);
  309. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  310. glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer.depthId);
  311. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  312. return buffer;
  313. }
  314. // Unload texture required buffers
  315. static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer)
  316. {
  317. if (buffer.textureChain)
  318. {
  319. ovr_DestroyTextureSwapChain(session, buffer.textureChain);
  320. buffer.textureChain = NULL;
  321. }
  322. if (buffer.depthId != 0) glDeleteTextures(1, &buffer.depthId);
  323. if (buffer.fboId != 0) glDeleteFramebuffers(1, &buffer.fboId);
  324. }
  325. // Load Oculus mirror buffers
  326. static OculusMirror LoadOculusMirror(ovrSession session, int width, int height)
  327. {
  328. OculusMirror mirror;
  329. mirror.width = width;
  330. mirror.height = height;
  331. ovrMirrorTextureDesc mirrorDesc;
  332. memset(&mirrorDesc, 0, sizeof(mirrorDesc));
  333. mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
  334. mirrorDesc.Width = mirror.width;
  335. mirrorDesc.Height = mirror.height;
  336. if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(LOG_WARNING, "Could not create mirror texture");
  337. glGenFramebuffers(1, &mirror.fboId);
  338. return mirror;
  339. }
  340. // Unload Oculus mirror buffers
  341. static void UnloadOculusMirror(ovrSession session, OculusMirror mirror)
  342. {
  343. if (mirror.fboId != 0) glDeleteFramebuffers(1, &mirror.fboId);
  344. if (mirror.texture) ovr_DestroyMirrorTexture(session, mirror.texture);
  345. }
  346. // Copy Oculus screen buffer to mirror texture
  347. static void BlitOculusMirror(ovrSession session, OculusMirror mirror)
  348. {
  349. GLuint mirrorTextureId;
  350. ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId);
  351. glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId);
  352. glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0);
  353. #if defined(GRAPHICS_API_OPENGL_33)
  354. // NOTE: glBlitFramebuffer() requires extension: GL_EXT_framebuffer_blit (not available in OpenGL ES 2.0)
  355. glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
  356. #endif
  357. glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
  358. }
  359. // Init Oculus layer (similar to photoshop)
  360. static OculusLayer InitOculusLayer(ovrSession session)
  361. {
  362. OculusLayer layer = { 0 };
  363. layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
  364. memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov));
  365. layer.eyeLayer.Header.Type = ovrLayerType_EyeFov;
  366. layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
  367. ovrEyeRenderDesc eyeRenderDescs[2];
  368. for (int eye = 0; eye < 2; eye++)
  369. {
  370. eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]);
  371. ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 10000.0f, ovrProjection_None); //ovrProjection_ClipRangeOpenGL);
  372. layer.eyeProjections[eye] = FromOvrMatrix(ovrPerspectiveProjection); // NOTE: struct ovrMatrix4f { float M[4][4] } --> struct Matrix
  373. layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset;
  374. layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov;
  375. ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f);
  376. layer.eyeLayer.Viewport[eye].Size = eyeSize;
  377. layer.eyeLayer.Viewport[eye].Pos.x = layer.width;
  378. layer.eyeLayer.Viewport[eye].Pos.y = 0;
  379. layer.height = eyeSize.h; //std::max(renderTargetSize.y, (uint32_t)eyeSize.h);
  380. layer.width += eyeSize.w;
  381. }
  382. return layer;
  383. }
  384. // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct
  385. static Matrix FromOvrMatrix(ovrMatrix4f ovrmat)
  386. {
  387. Matrix rmat;
  388. rmat.m0 = ovrmat.M[0][0];
  389. rmat.m1 = ovrmat.M[1][0];
  390. rmat.m2 = ovrmat.M[2][0];
  391. rmat.m3 = ovrmat.M[3][0];
  392. rmat.m4 = ovrmat.M[0][1];
  393. rmat.m5 = ovrmat.M[1][1];
  394. rmat.m6 = ovrmat.M[2][1];
  395. rmat.m7 = ovrmat.M[3][1];
  396. rmat.m8 = ovrmat.M[0][2];
  397. rmat.m9 = ovrmat.M[1][2];
  398. rmat.m10 = ovrmat.M[2][2];
  399. rmat.m11 = ovrmat.M[3][2];
  400. rmat.m12 = ovrmat.M[0][3];
  401. rmat.m13 = ovrmat.M[1][3];
  402. rmat.m14 = ovrmat.M[2][3];
  403. rmat.m15 = ovrmat.M[3][3];
  404. MatrixTranspose(&rmat);
  405. return rmat;
  406. }
  407. #endif