Advertisement
fistsofthenorthstar

Oculus + OpenGL + SDL 2 minimal demo. (With distortion filte

Sep 16th, 2013
2,484
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.53 KB | None | 0 0
  1. //----------------------------------------------
  2. // Oculus + OpenGL + SDL 2 minimal demo. (With distortion filter).
  3. //
  4. // Author : Olivier Renault.
  5. //----------------------------------------------
  6. #include <windows.h>
  7. #include <GL/glew.h>
  8. #include <GL/gl.h>
  9. #include <GL/glu.h>
  10. #include <stdio.h>
  11. #include <limits>
  12. #include <string>
  13. #include <vector>
  14. #include <iostream>
  15. #include <fstream>
  16. #include <algorithm>
  17. #include "sdl.h"
  18. #include "OVR.h"
  19.  
  20. #pragma comment(lib, "Winmm.lib")
  21. #pragma comment(lib, "opengl32.lib")
  22. #pragma comment(lib, "glu32.lib")
  23. #pragma comment(lib, "glew32.lib")
  24. #pragma comment(lib, "libovr.lib")
  25. #pragma comment (lib, "sdl2.lib")
  26. #pragma comment (lib, "sdl2main.lib")
  27.  
  28. void trace(const char* format, ...)
  29. {
  30.     char temp[1024];
  31.     va_list args;
  32.     va_start(args, format);
  33.     vsprintf_s(temp, sizeof(temp), format, args);
  34.     va_end(args);
  35.     OutputDebugString(temp);
  36.     OutputDebugString("\n");
  37.     printf("%s\n", temp);
  38. }
  39.  
  40. void debug_break()
  41. {
  42.     __asm int 3;
  43. }
  44.  
  45. #define TRACE(A, ...)  { trace("[TRACE] %s", A, __VA_ARGS__); }
  46. #define WARN(A, ...)   { trace("[WARN]  %s", A, __VA_ARGS__); }
  47. #define FATAL(A, ...)  { trace("[FATAL] %s", A, __VA_ARGS__); debug_break(); }
  48. #define ASSERT(A)      { if(!(A)) { trace("[ASSERT] %s", #A); debug_break(); } }
  49.  
  50. float clamp(float x, float min, float max)
  51. {
  52.     if(x < min) return min; else if (x > max) return max; else return x;
  53. }
  54.  
  55. void apply_gl_matrix(const OVR::Matrix4f& matrix)
  56. {
  57.     glMultMatrixf(&(matrix.Transposed().M[0][0]));
  58. }
  59.  
  60. void APIENTRY gl_debug_callback(    GLenum source,
  61.                                     GLenum type,
  62.                                     GLuint id,
  63.                                     GLenum severity,
  64.                                     GLsizei length,
  65.                                     const GLchar* message,
  66.                                     void* userParam)
  67. {
  68.     TRACE("[OPENGL ERROR] source(%s) type(%s) id(%d) severity(%s) '%s'", glewGetString(source), glewGetString(type), id, glewGetString(severity), message);
  69.     if(severity == GL_DEBUG_SEVERITY_HIGH)
  70.         debug_break();
  71. }
  72.  
  73. class Oculus : public OVR::MessageHandler
  74. {
  75. public:
  76.     Oculus()
  77.     {}
  78.  
  79.     ~Oculus()
  80.     {
  81.         OVR::MessageHandler::RemoveHandlerFromDevices();
  82.         m_sensor.Clear();
  83.         m_HMD.Clear();
  84.         m_device_manager.Clear();
  85.        
  86.         OVR::System::Destroy();
  87.         OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
  88.     }
  89.  
  90.     void start()
  91.     {
  92.         OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
  93.        
  94.         m_device_manager = *OVR::DeviceManager::Create();
  95.        
  96.         // We'll handle it's messages in this case.
  97.         m_device_manager->SetMessageHandler(this);
  98.  
  99.         // Release Sensor/HMD in case this is a retry.
  100.         m_sensor.Clear();
  101.         m_HMD.Clear();
  102.        
  103.         m_HMD = *m_device_manager->EnumerateDevices<OVR::HMDDevice>().CreateDevice();
  104.         if (m_HMD)
  105.         {
  106.             m_sensor = *m_HMD->GetSensor();
  107.  
  108.             // This will initialize HMDInfo with information about configured IPD,
  109.             // screen size and other variables needed for correct projection.
  110.             // We pass HMD DisplayDeviceName into the renderer to select the
  111.             // correct monitor in full-screen mode.
  112.             m_HMD->GetDeviceInfo(&m_HMD_info);
  113.  
  114.             m_stereo_config.SetHMDInfo(m_HMD_info);
  115.             m_stereo_config.SetFullViewport(OVR::Util::Render::Viewport(0,0, m_HMD_info.HResolution, m_HMD_info.VResolution));
  116.             m_stereo_config.SetStereoMode(OVR::Util::Render::Stereo_LeftRight_Multipass);
  117.            
  118.             if (m_HMD_info.HScreenSize > 0.140f) // 7"
  119.                 m_stereo_config.SetDistortionFitPointVP(-1.0f, 0.0f);
  120.             else
  121.                 m_stereo_config.SetDistortionFitPointVP(0.0f, 1.0f);
  122.         }
  123.         else
  124.         {            
  125.             // If we didn't detect an HMD, try to create the sensor directly.
  126.             // This is useful for debugging sensor interaction; it is not needed in
  127.             // a shipping app.
  128.             m_sensor = m_device_manager->EnumerateDevices<OVR::SensorDevice>().CreateDevice();
  129.         }
  130.  
  131.         const char* detectionMessage=0;
  132.         if (!m_HMD && !m_sensor)
  133.             detectionMessage = "Oculus Rift not detected.";
  134.         else if (!m_HMD)
  135.             detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
  136.         else if (!m_sensor)
  137.             detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
  138.         else if (m_HMD_info.DisplayDeviceName[0] == '\0')
  139.             detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
  140.         else
  141.             detectionMessage = 0;
  142.  
  143.         if (detectionMessage)
  144.         {
  145.             ::MessageBoxA(0, detectionMessage, "Oculus Rift ERROR", MB_OK);
  146.         }
  147.        
  148.         if (m_sensor)
  149.         {
  150.             // We need to attach sensor to SensorFusion object for it to receive
  151.             // body frame messages and update orientation. SFusion.GetOrientation()
  152.             // is used in OnIdle() to orient the view.
  153.             m_sensor_fusion.AttachToSensor(m_sensor);
  154.             m_sensor_fusion.SetPredictionEnabled(true);
  155.             m_sensor_fusion.SetDelegateMessageHandler(this);           
  156.         }
  157.     }
  158.  
  159.     bool get_sensor_position(float& x, float& y, float& z) const
  160.     {
  161.         // TODO. Some form of positional tracking.
  162.         x = 0.0f;
  163.         y = 0.0f;
  164.         z = 0.0f;
  165.         return false;
  166.     }
  167.  
  168.     bool get_sensor_orientation(float& yaw, float& pitch, float& roll) const
  169.     {
  170.         yaw = 0.0f;
  171.         pitch = 0.0f;
  172.         roll = 0.0f;
  173.    
  174.         if(!m_sensor_fusion.IsAttachedToSensor())
  175.             return false;
  176.  
  177.         OVR::Quatf hmdOrient = m_sensor_fusion.GetOrientation();
  178.         hmdOrient.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&yaw, &pitch, &roll);
  179.         return true;
  180.     }
  181.  
  182.     const OVR::HMDInfo& get_HMD_info() const
  183.     {
  184.         return m_HMD_info;
  185.     }
  186.  
  187.     OVR::Util::Render::StereoConfig get_stereo_config() const
  188.     {
  189.         return m_stereo_config;
  190.     }
  191.  
  192.     virtual void OnMessage(const OVR::Message& msg)
  193.     {
  194.         if(msg.pDevice == m_sensor)
  195.         {
  196.             if (msg.Type == OVR::Message_BodyFrame)
  197.             {
  198.             }
  199.         }
  200.         else if(msg.pDevice == m_device_manager)
  201.         {
  202.             if (msg.Type == OVR::Message_DeviceAdded)
  203.             {
  204.                 trace("DeviceManager reported device added.");
  205.             }
  206.             else if (msg.Type == OVR::Message_DeviceRemoved)
  207.             {
  208.                 trace("DeviceManager reported device removed.");
  209.             }
  210.             else if (msg.Type == OVR::Message_DeviceAdded)
  211.             {
  212.                 trace("Sensor reported device added.");
  213.             }
  214.             else if (msg.Type == OVR::Message_DeviceRemoved)
  215.             {
  216.                 trace("Sensor reported device removed.");
  217.             }
  218.         }
  219.     }
  220.  
  221. private:
  222.     OVR::Ptr<OVR::DeviceManager>            m_device_manager;
  223.     OVR::Ptr<OVR::SensorDevice>             m_sensor;
  224.     OVR::Ptr<OVR::HMDDevice>                m_HMD;
  225.     OVR::HMDInfo                            m_HMD_info;
  226.     OVR::SensorFusion                       m_sensor_fusion;
  227.     OVR::Util::Render::StereoConfig         m_stereo_config;
  228. };
  229.  
  230. // handles basic movement in the scene.
  231. class Avatar
  232. {
  233. public:
  234.     Avatar()
  235.     {
  236.         m_oculus = NULL;
  237.     }
  238.  
  239.     void start(const Oculus* oculus)
  240.     {
  241.         m_oculus = oculus;
  242.         m_speed = 10.0f;
  243.     }
  244.  
  245.     void on_key_down(int key)
  246.     {
  247.         switch(key)
  248.         {
  249.         case SDLK_UP:
  250.             {
  251.                 m_velocity.z = -m_speed;
  252.                 break;
  253.             }
  254.         case SDLK_DOWN:
  255.             {
  256.                 m_velocity.z = m_speed;
  257.                 break;
  258.             }
  259.         case SDLK_LEFT:
  260.             {
  261.                 m_velocity.x = -m_speed;
  262.                 break;
  263.             }
  264.         case SDLK_RIGHT:
  265.             {
  266.                 m_velocity.x = m_speed;
  267.                 break;
  268.             }
  269.         }
  270.     }
  271.  
  272.     void on_key_up(int key)
  273.     {
  274.         switch(key)
  275.         {
  276.         case SDLK_UP:
  277.             {
  278.                 m_velocity.z = 0.0f;
  279.                 break;
  280.             }
  281.         case SDLK_DOWN:
  282.             {
  283.                 m_velocity.z = 0.0f;
  284.                 break;
  285.             }
  286.         case SDLK_LEFT:
  287.             {
  288.                 m_velocity.x = 0.0f;
  289.                 break;
  290.             }
  291.         case SDLK_RIGHT:
  292.             {
  293.                 m_velocity.x = 0.0f;
  294.                 break;
  295.             }
  296.         }
  297.     }
  298.  
  299.     const OVR::Vector3f& get_position() const
  300.     {
  301.         return m_position;
  302.     }
  303.  
  304.     void set_position(const OVR::Vector3f& position)
  305.     {
  306.         m_position = position;
  307.     }
  308.  
  309.     void update(float dt)
  310.     {
  311.         m_position += m_velocity * dt;
  312.     }
  313.  
  314.     void setup_camera(OVR::Util::Render::StereoEye eye)
  315.     {
  316.         const OVR::HMDInfo& hmd = m_oculus->get_HMD_info();
  317.         const OVR::Util::Render::StereoEyeParams& params = m_oculus->get_stereo_config().GetEyeRenderParams(eye);
  318.         glViewport(params.VP.x, params.VP.y, params.VP.w, params.VP.h);
  319.        
  320.         glMatrixMode(GL_PROJECTION);
  321.         glLoadIdentity();
  322.         apply_gl_matrix(params.ViewAdjust);
  323.         apply_gl_matrix(params.Projection);
  324.  
  325.         glMatrixMode(GL_MODELVIEW);
  326.         glLoadIdentity();
  327.        
  328.         OVR::Matrix4f eye_view = get_eye_view(eye);
  329.         apply_gl_matrix(eye_view);
  330.     }
  331.  
  332.     OVR::Matrix4f get_eye_view(OVR::Util::Render::StereoEye eye)
  333.     {
  334.         static const OVR::Vector3f UpVector(0.0f, 1.0f, 0.0f);
  335.         static const OVR::Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
  336.         static const OVR::Vector3f RightVector(1.0f, 0.0f, 0.0f);
  337.  
  338.         float yaw, pitch, roll;
  339.         m_oculus->get_sensor_orientation(yaw, pitch, roll);
  340.         OVR::Matrix4f eye_rpy = OVR::Matrix4f::RotationY(yaw) * OVR::Matrix4f::RotationX(pitch) * OVR::Matrix4f::RotationZ(roll);
  341.  
  342.         OVR::Vector3f eye_pos = m_position;
  343.         OVR::Vector3f eye_forward = eye_rpy.Transform(ForwardVector);
  344.         OVR::Vector3f eye_up = eye_rpy.Transform(UpVector);
  345.         OVR::Vector3f eye_right = eye_rpy.Transform(RightVector);
  346.         OVR::Matrix4f eye_view = OVR::Matrix4f::LookAtRH(eye_pos, eye_pos + eye_forward, eye_up);
  347.         return eye_view;
  348.     }
  349.  
  350.     float m_speed;
  351.     OVR::Vector3f m_position;
  352.     OVR::Vector3f m_velocity;
  353.     const Oculus* m_oculus;
  354. };
  355.  
  356. // A bunch of 3D-rendered stuff
  357. struct Scene
  358. {
  359.     int spherelist;
  360.  
  361.     Scene()
  362.     {
  363.         spherelist = -1;
  364.     }
  365.     ~Scene()
  366.     {
  367.         if(glIsList(spherelist))
  368.         {
  369.             glDeleteLists(spherelist, 1);
  370.         }
  371.     }
  372.  
  373.     void draw_sphere()
  374.     {
  375.         if(!glIsList(spherelist))
  376.         {
  377.             spherelist = glGenLists(1);
  378.             glNewList(spherelist,GL_COMPILE);
  379.             GLUquadricObj* sphere=gluNewQuadric();
  380.             gluQuadricNormals(sphere, GLU_SMOOTH);
  381.             gluQuadricTexture(sphere, GL_TRUE);
  382.             gluSphere(sphere,0.5,20,20);
  383.             gluDeleteQuadric(sphere);      
  384.             glEndList();
  385.         }
  386.  
  387.         if(glIsList(spherelist))
  388.         {
  389.             glCallList(spherelist);
  390.         }
  391.     }
  392.  
  393.     // draw a bunch of spheres
  394.     void draw(const OVR::Vector3f position)
  395.     {
  396.         float scale = 10.0f;
  397.         float step = scale * 2.0f;
  398.         int nx = 10;
  399.         int ny = 1;
  400.         int nz = 10;
  401.        
  402.         float cx = (int)(position.x / step) * step;
  403.         float cy = (int)(position.y / step) * step;
  404.         float cz = (int)(position.z / step) * step;
  405.        
  406.         for(int ix = 0; ix < nx; ix++)
  407.         {
  408.             for(int iz = 0; iz < nz; iz++)
  409.             {
  410.                 for(int iy = 0; iy < ny; iy++)
  411.                 {
  412.                     glPushMatrix();
  413.                     float x = cx + (ix - nx * 0.5f)* (step);
  414.                     float y = cy + (iy - ny * 0.5f)* (step);
  415.                     float z = cz + (iz - nz * 0.5f)* (step);
  416.                     glTranslatef(x, y, z);
  417.                     glScalef(scale, scale, scale);
  418.                     draw_sphere();
  419.                     glPopMatrix();
  420.                 }
  421.             }
  422.         }
  423.     }
  424. };
  425.  
  426. // render frame buffer to a portion of the screen,
  427. // so we can apply the distortion shader.
  428. struct EyePatch
  429. {
  430.     // various patches for eyes.
  431.     void setup(OVR::Util::Render::StereoEye eye)
  432.     {
  433.         static float g_vertex_buffer_data[3][4][3]=
  434.         {  
  435.             // centre eye
  436.             {   { -1.0f, -1.0f, 0.0f, },
  437.                 {  1.0f, -1.0f, 0.0f, },
  438.                 {  1.0f,  1.0f, 0.0f, },
  439.                 { -1.0f,  1.0f, 0.0f, }, },
  440.  
  441.             // left eye
  442.             {   { -1.0f, -1.0f, 0.0f, },
  443.                 {  0.0f, -1.0f, 0.0f, },
  444.                 {  0.0f,  1.0f, 0.0f, },
  445.                 { -1.0f,  1.0f, 0.0f, }, },
  446.  
  447.             // right eye
  448.             {   {  0.0f, -1.0f, 0.0f, },
  449.                 {  1.0f, -1.0f, 0.0f, },
  450.                 {  1.0f,  1.0f, 0.0f, },
  451.                 {  0.0f,  1.0f, 0.0f, }, },
  452.         };
  453.  
  454.         static float g_uv_buffer_data[3][4][2] =
  455.         {
  456.             // center eye
  457.             {   { 0.0f, 0.0f, },
  458.                 { 1.0f, 0.0f, },
  459.                 { 1.0f, 1.0f, },
  460.                 { 0.0f, 1.0f, }, },
  461.  
  462.             // left eye
  463.             {   { 0.0f, 0.0f, },
  464.                 { 0.5f, 0.0f, },
  465.                 { 0.5f, 1.0f, },
  466.                 { 0.0f, 1.0f, }, },
  467.  
  468.             // right eye
  469.             {   { 0.5f, 0.0f, },
  470.                 { 1.0f, 0.0f, },
  471.                 { 1.0f, 1.0f, },
  472.                 { 0.5f, 1.0f, }, }
  473.         };
  474.  
  475.         // load up the eye quad.
  476.         glGenVertexArrays(1, &m_vertex_arrays);
  477.         glBindVertexArray(m_vertex_arrays);
  478.  
  479.         glGenBuffers(1, &m_vertex_buffer);
  480.         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
  481.         glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data[eye]), &g_vertex_buffer_data[eye][0][0], GL_STATIC_DRAW);
  482.  
  483.         glGenBuffers(1, &m_uv_buffer);
  484.         glBindBuffer(GL_ARRAY_BUFFER, m_uv_buffer);
  485.         glBufferData(GL_ARRAY_BUFFER, sizeof(g_uv_buffer_data[eye]), &g_uv_buffer_data[eye][0][0], GL_STATIC_DRAW);
  486.     }
  487.  
  488.     void render()
  489.     {
  490.         // render the quad for the eye patch on Oculus display.
  491.         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
  492.         glEnableVertexAttribArray(0);
  493.         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
  494.        
  495.         glBindBuffer(GL_ARRAY_BUFFER, m_uv_buffer);
  496.         glEnableVertexAttribArray(1);
  497.         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);  
  498.  
  499.         glDrawArrays(GL_QUADS, 0, 4);
  500.  
  501.         glBindBuffer(GL_ARRAY_BUFFER, 0);
  502.         glEnableVertexAttribArray(0);
  503.         glEnableVertexAttribArray(1);
  504.     }
  505.  
  506.     void cleanup()
  507.     {
  508.         glDeleteBuffers(1, &m_vertex_buffer);
  509.         glDeleteBuffers(1, &m_uv_buffer);
  510.         glDeleteVertexArrays(1, &m_vertex_arrays);
  511.     }
  512.  
  513.     GLuint m_vertex_arrays;
  514.     GLuint m_vertex_buffer;
  515.     GLuint m_uv_buffer;
  516. };
  517.  
  518. // SDL maintenance stuff
  519. bool sdl_use_vertex_shaders=true;
  520. bool sdl_debug = false;
  521. bool sdl_quit = false;
  522. SDL_Window *sdl_window=NULL;
  523. SDL_GLContext sdl_opengl_context;
  524. unsigned int sdl_frame_timestamp = 0;
  525. unsigned int sdl_frame_timestep = 16;
  526.  
  527. // frame buffer maintenance.
  528. GLuint gl_frame_buffer = 0;
  529. GLuint gl_frame_buffer_texture = 0;
  530. GLuint gl_frame_buffer_depth=0;
  531. GLuint gl_draw_buffers[1];
  532.        
  533. // shader maintenance.
  534. GLuint gl_fragment_shader_program = 0;
  535.  
  536. const char* gl_vertex_shader_code =
  537. "#version 330 core\n"
  538. "\n"
  539. "layout(location = 0) in vec3 Position;\n"
  540. "layout(location = 1) in vec2 TexCoord;\n"
  541. "out vec2 oTexCoord;\n"
  542. "\n"
  543. "void main()\n"
  544. "{\n"
  545. "   gl_Position = vec4(Position, 1);\n"
  546. "   oTexCoord = TexCoord;\n"
  547. "};\n";
  548.  
  549. const char* gl_fragment_shader_code =
  550. "#version 330\n"
  551. "\n"
  552. "uniform vec2 LensCenter;\n"
  553. "uniform vec2 ScreenCenter;\n"
  554. "uniform vec2 Scale;\n"
  555. "uniform vec2 ScaleIn;\n"
  556. "uniform vec4 HmdWarpParam;\n"
  557. "uniform sampler2D texture0;\n"
  558. "varying vec2 oTexCoord;\n"
  559. "out vec4 outcolor;\n"
  560. "\n"
  561. "vec2 HmdWarp(vec2 in01)\n"
  562. "{\n"
  563. "   vec2  theta = (in01 - LensCenter) * ScaleIn; // Scales to [-1, 1]\n"
  564. "   float rSq = theta.x * theta.x + theta.y * theta.y;\n"
  565. "   vec2  theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + \n"
  566. "                           HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
  567. "   return LensCenter + Scale * theta1;\n"
  568. "}\n"
  569. "void main()\n"
  570. "{\n"
  571. "   vec2 tc = HmdWarp(oTexCoord);\n"
  572. "   if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))\n"
  573. "       outcolor = vec4(0);\n"
  574. "   else\n"
  575. "      outcolor = texture2D(texture0, tc);\n"
  576. "};\n";
  577.  
  578. void gl_uniform_2f   (const char* varname, float a, float b) { GLuint varid = glGetUniformLocation(gl_fragment_shader_program, varname); glUniform2f(varid, a, b); }
  579. void gl_uniform_4f   (const char* varname, float a, float b, float c, float d) { GLuint varid = glGetUniformLocation(gl_fragment_shader_program, varname); glUniform4f(varid, a, b, c, d); }
  580. void gl_uniform_1i   (const char* varname, int value) { GLuint varid = glGetUniformLocation(gl_fragment_shader_program, varname); glUniform1i(varid, value); }
  581.  
  582. // main object encapsulation.
  583. Avatar m_avatar;
  584. Oculus m_oculus;
  585. Scene m_scene;
  586. EyePatch m_eye_patch[3];
  587.  
  588. // render the 3D scene for each eye.
  589. void render_scene_to_framebuffer(void)
  590. {
  591.     glPushAttrib( GL_TEXTURE_BIT | GL_DEPTH_TEST | GL_LIGHTING );
  592.  
  593.     glEnable(GL_DEPTH_TEST);
  594.     glEnable(GL_LIGHTING);
  595.     glEnable(GL_CULL_FACE);
  596.  
  597.     // Render to our framebuffer
  598.     glBindFramebuffer(GL_FRAMEBUFFER, gl_frame_buffer);
  599.  
  600.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  601.  
  602.     // draw left viewpoint
  603.     m_avatar.setup_camera(OVR::Util::Render::StereoEye_Left);
  604.     m_scene.draw(m_avatar.get_position());
  605.  
  606.     // draw right viewpoint
  607.     m_avatar.setup_camera(OVR::Util::Render::StereoEye_Right);
  608.     m_scene.draw(m_avatar.get_position());
  609.  
  610.     glPopAttrib();
  611. }
  612.  
  613. // output each viewpoint to the display screen.
  614. void render_eye_patch(OVR::Util::Render::StereoEye eye)
  615. {
  616.     // apply distortion for each eye.
  617.     const OVR::Util::Render::StereoEyeParams& params = m_oculus.get_stereo_config().GetEyeRenderParams(eye);
  618.     if(params.pDistortion)
  619.     {
  620.         GLsizei width = m_oculus.get_HMD_info().HResolution;
  621.         GLsizei height = m_oculus.get_HMD_info().VResolution;
  622.         const OVR::Util::Render::DistortionConfig& distortion = *params.pDistortion;
  623.  
  624.         float w  = float(params.VP.w) / float(width),
  625.               h  = float(params.VP.h) / float(height),
  626.               x  = float(params.VP.x) / float(width),
  627.               y  = float(params.VP.y) / float(height);
  628.         float as = float(params.VP.w) / float(params.VP.h);
  629.  
  630.         // We are using 1/4 of DistortionCenter offset value here, since it is
  631.         // relative to [-1,1] range that gets mapped to [0, 0.5].
  632.         float HmdWarpParam[4]   = { distortion.K[0], distortion.K[1], distortion.K[2], distortion.K[3] };
  633.         float ChromAbParam[4]   = { distortion.ChromaticAberration[0], distortion.ChromaticAberration[1], distortion.ChromaticAberration[2], distortion.ChromaticAberration[3] };
  634.         float scaleFactor       = 1.0f / distortion.Scale;
  635.         OVR::Vector2f LensCenter    (x + (w + distortion.XCenterOffset * 0.5f)*0.5f,    y + h*0.5f);
  636.         OVR::Vector2f ScreenCenter  (x + w*0.5f,                                        y + h*0.5f);
  637.         OVR::Vector2f Scale         ((w/2) * scaleFactor,                               (h/2) * scaleFactor * as);
  638.         OVR::Vector2f ScaleIn       ((2/w),                                             (2/h) / as);
  639.        
  640.         // fragment shader.
  641.         gl_uniform_2f("LensCenter",     LensCenter.x,    LensCenter.y);
  642.         gl_uniform_2f("ScreenCenter",   ScreenCenter.x,  ScreenCenter.y);
  643.         gl_uniform_2f("Scale",          Scale.x,         Scale.y);
  644.         gl_uniform_2f("ScaleIn",        ScaleIn.x,       ScaleIn.y);
  645.         gl_uniform_4f("HmdWarpParam",   HmdWarpParam[0], HmdWarpParam[1], HmdWarpParam[2], HmdWarpParam[3]);
  646.         gl_uniform_4f("ChromAbParam",   ChromAbParam[0], ChromAbParam[1], ChromAbParam[2], ChromAbParam[3]);
  647.     }
  648.    
  649.     // render the quad on display.
  650.     m_eye_patch[eye].render();
  651. }
  652.  
  653. // send 3D screen render to the display.
  654. // apply the post process shaders.
  655. void postprocess_framebuffer(void)
  656. {
  657.     // dumb way to display the frame buffer as a full screen quad, but hey...
  658.     glPushAttrib(GL_TEXTURE_BIT | GL_DEPTH_TEST | GL_LIGHTING );
  659.    
  660.     glDisable(GL_CULL_FACE);
  661.     glDisable(GL_DEPTH_TEST);
  662.     glDisable(GL_LIGHTING);
  663.     glEnable(GL_TEXTURE_2D);
  664.    
  665.     // Render to the screen
  666.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  667.  
  668.     // reset the screen params.
  669.     glViewport(0, 0, m_oculus.get_HMD_info().HResolution, m_oculus.get_HMD_info().VResolution);
  670.     glMatrixMode(GL_PROJECTION);
  671.     glLoadIdentity();
  672.     glMatrixMode(GL_MODELVIEW);
  673.     glLoadIdentity();
  674.    
  675.     // clear the screen.
  676.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  677.  
  678.     // setup the post process shader.
  679.     glUseProgram(gl_fragment_shader_program);
  680.     glActiveTexture(GL_TEXTURE0);
  681.     glBindTexture(GL_TEXTURE_2D, gl_frame_buffer_texture);
  682.     gl_uniform_1i("texture0", 0);
  683.  
  684.     // render left eye with distortion shader
  685.     render_eye_patch(OVR::Util::Render::StereoEye_Left);
  686.  
  687.     // render right eye with distortion shader
  688.     render_eye_patch(OVR::Util::Render::StereoEye_Right);
  689.  
  690.     // clean up.
  691.     glBindTexture(GL_TEXTURE_2D, 0);
  692.     glUseProgram(0);   
  693.     glPopAttrib();
  694.  
  695.     SDL_GL_SwapWindow(sdl_window);
  696. }
  697.  
  698. void update_tick()
  699. {
  700.     // limit framerate in a ham-fisted way.
  701.     unsigned int sdl_frame_time = SDL_GetTicks() - sdl_frame_timestamp;
  702.     if(sdl_frame_time < sdl_frame_timestep) SDL_Delay(sdl_frame_timestep - sdl_frame_time);
  703.     sdl_frame_timestamp = SDL_GetTicks();
  704. }
  705.  
  706. void update_sdl_events()
  707. {
  708.     SDL_Event event;   
  709.     while( SDL_PollEvent( &event ) )
  710.     {
  711.         if( event.type == SDL_KEYDOWN )
  712.         {
  713.             if(event.key.keysym.sym == SDLK_ESCAPE)
  714.             {
  715.                 sdl_quit = true;
  716.             }
  717.             else
  718.             {
  719.                 m_avatar.on_key_down(event.key.keysym.sym);
  720.             }
  721.         }
  722.         else if( event.type == SDL_KEYUP )
  723.         {
  724.             m_avatar.on_key_up(event.key.keysym.sym);
  725.         }
  726.         else if( event.type == SDL_QUIT )
  727.         {
  728.             sdl_quit = true;
  729.         }
  730.     }
  731. }
  732.  
  733. void update_avatar()
  734. {
  735.     // move the viewpoint, update camera orientations.
  736.     m_avatar.update(sdl_frame_timestep / 1000.0f);
  737. }
  738.  
  739. // main loop. Do various bits till we want to quit.
  740. void sdl_main_loop()
  741. {
  742.     while(!sdl_quit)
  743.     {
  744.         update_tick();
  745.         update_sdl_events();
  746.         update_avatar();
  747.         render_scene_to_framebuffer();
  748.         postprocess_framebuffer();
  749.     }
  750. }
  751.  
  752. // create frame buffer where we render the scene.
  753. void setup_frame_buffer()
  754. {
  755.     // setup frame buffer. Resolution can be set to anything, preferably higher than oculus resolution.
  756.     GLsizei width = m_oculus.get_HMD_info().HResolution;
  757.     GLsizei height = m_oculus.get_HMD_info().VResolution;
  758.    
  759.     glGenFramebuffers(1, &gl_frame_buffer);
  760.     glBindFramebuffer(GL_FRAMEBUFFER, gl_frame_buffer);
  761.  
  762.     // The texture we're going to render to
  763.     glGenTextures(1, &gl_frame_buffer_texture);
  764.      
  765.     // "Bind" the newly created texture : all future texture functions will modify this texture
  766.     glBindTexture(GL_TEXTURE_2D, gl_frame_buffer_texture);
  767.      
  768.     // Give an empty image to OpenGL ( the last "0" )
  769.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
  770.      
  771.     // linear filtering.
  772.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  773.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  774.  
  775.     // The depth buffer
  776.     glGenRenderbuffers(1, &gl_frame_buffer_depth);
  777.     glBindRenderbuffer(GL_RENDERBUFFER, gl_frame_buffer_depth);
  778.     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
  779.     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gl_frame_buffer_depth);
  780.  
  781.     // Set "renderedTexture" as our colour attachement #0
  782.     glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gl_frame_buffer_texture, 0);
  783.      
  784.     // Set the list of draw buffers.
  785.     GLenum gl_draw_buffers[1] = { GL_COLOR_ATTACHMENT0 };
  786.     glDrawBuffers(1, gl_draw_buffers); // "1" is the size of DrawBuffers
  787.  
  788.     // Always check that our framebuffer is ok
  789.     if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  790.     {
  791.         ASSERT("[FRAMEBUFFER] error.");
  792.     }
  793. }
  794.  
  795. void setup_oculus()
  796. {
  797.     m_oculus.start();
  798.     m_avatar.start(&m_oculus);
  799. }
  800.  
  801. void setup_sdl()
  802. {
  803.     // initialise out rendering context.
  804.     if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
  805.         return;    
  806.    
  807.     const OVR::HMDInfo& hmd_info = m_oculus.get_HMD_info();
  808.     sdl_window = SDL_CreateWindow("Oculus!", 100, 100, hmd_info.HResolution, hmd_info.VResolution, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS | SDL_WINDOW_MAXIMIZED);
  809.     sdl_opengl_context = SDL_GL_CreateContext(sdl_window);
  810.  
  811.     if(!sdl_debug)
  812.     {
  813.         // set window bounds into oculus display.
  814.         SDL_SetWindowPosition(sdl_window, hmd_info.DesktopX, hmd_info.DesktopY);
  815.         SDL_SetWindowSize(sdl_window, hmd_info.HResolution, hmd_info.VResolution);
  816.         //SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN);
  817.     }
  818. }
  819.  
  820. void setup_material()
  821. {  
  822.     // basic material for the scene.
  823.     float mat_specular[4]={1.0f,1.0f,1.0f,1.0f};
  824.     float mat_diffuse[4] ={0.5f,0.0f,0.0f,1.0f};
  825.     float mat_ambient[4] ={0.2f,0.1f,0.1f,1.0f};
  826.     float mat_shininess=50.0;
  827.  
  828.     glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,mat_shininess);
  829.     glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
  830.     glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
  831.     glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,mat_ambient);
  832. }
  833.  
  834. void setup_lighting()
  835. {
  836.     // basic lighting for the scene.
  837.     GLfloat global_ambient[]={.3f,.3f,.3f,1.0f};
  838.     GLfloat ambient[]={1.0f,0.0f,0.0f,1.0f};
  839.     glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
  840.     glLightfv(GL_LIGHT0,GL_LIGHT_MODEL_AMBIENT,global_ambient);
  841.  
  842.     GLfloat diffuse[]= { 0.5,0.5,0.5,1.0 };
  843.     glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
  844.  
  845.     GLfloat specular[] = { 1.0,1.0,1.0,1.0 };
  846.     glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
  847.  
  848.     GLfloat light_position[]={ 100.0,1000.0,100.0,1.0};
  849.     glLightfv(GL_LIGHT0,GL_POSITION,light_position);
  850.  
  851.     glEnable(GL_LIGHT0);
  852.     glEnable(GL_LIGHTING);
  853. }
  854.  
  855. void setup_opengl()
  856. {
  857.     // debugging
  858.     if(glDebugMessageControl)   glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, NULL, true);
  859.     if(glDebugMessageCallback)  glDebugMessageCallback(gl_debug_callback, NULL);
  860.    
  861.     // shading
  862.     glClearColor    (0.1f, 0.1f, 0.1f, 1.0f);
  863.     glShadeModel    (GL_SMOOTH);
  864.     glEnable        (GL_NORMALIZE);
  865.  
  866.     // culling
  867.     glPolygonMode   (GL_FRONT_AND_BACK,GL_FILL);
  868.     glEnable        (GL_CULL_FACE);
  869.     glFrontFace     (GL_CW);
  870.     glCullFace      (GL_BACK);
  871.     glEnable        (GL_DEPTH_TEST);
  872.     glDepthMask     (GL_TRUE);
  873.     glDepthFunc     (GL_LEQUAL);
  874.    
  875.     // blending
  876.     glEnable        (GL_BLEND);
  877.     glBlendFunc     (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  878.  
  879.     setup_lighting();
  880.     setup_material();
  881. }
  882.  
  883. void setup_shaders()
  884. {
  885.     // initialise glew API.
  886.     glewInit();
  887.  
  888.     // setup eye quads.
  889.     for(int i = 0; i < 3; ++i)
  890.         m_eye_patch[i].setup((OVR::Util::Render::StereoEye) i);
  891.    
  892.     // Now create the shaders
  893.     GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
  894.     GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
  895.  
  896.     GLint Result = GL_FALSE;
  897.     int InfoLogLength;
  898.    
  899.     // Compile Vertex Shader
  900.     trace("Compiling vertex shader");
  901.     glShaderSource(VertexShaderID, 1, &gl_vertex_shader_code , NULL);
  902.     glCompileShader(VertexShaderID);
  903.  
  904.     // Check Vertex Shader
  905.     glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
  906.     glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
  907.     if ( InfoLogLength > 0 ){
  908.             std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
  909.             glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
  910.             trace("%s", &VertexShaderErrorMessage[0]);
  911.     }
  912.  
  913.     // Compile Fragment Shader
  914.     trace("Compiling fragment shader");
  915.     glShaderSource(FragmentShaderID, 1, &gl_fragment_shader_code , NULL);
  916.     glCompileShader(FragmentShaderID);
  917.  
  918.     // Check Fragment Shader
  919.     glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
  920.     glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
  921.     if ( InfoLogLength > 0 ){
  922.             std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
  923.             glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
  924.             trace("%s", &FragmentShaderErrorMessage[0]);
  925.     }
  926.  
  927.     // Link the program
  928.     trace("Linking program");
  929.     gl_fragment_shader_program = glCreateProgram();
  930.     glAttachShader(gl_fragment_shader_program, VertexShaderID);
  931.     glAttachShader(gl_fragment_shader_program, FragmentShaderID);
  932.     glLinkProgram(gl_fragment_shader_program);
  933.  
  934.     // Check the program
  935.     glGetProgramiv(gl_fragment_shader_program, GL_LINK_STATUS, &Result);
  936.     glGetProgramiv(gl_fragment_shader_program, GL_INFO_LOG_LENGTH, &InfoLogLength);
  937.     if ( InfoLogLength > 0 ){
  938.             std::vector<char> ProgramErrorMessage(InfoLogLength+1);
  939.             glGetProgramInfoLog(gl_fragment_shader_program, InfoLogLength, NULL, &ProgramErrorMessage[0]);
  940.             trace("%s", &ProgramErrorMessage[0]);
  941.     }
  942.  
  943.     glDeleteShader(VertexShaderID);
  944.     glDeleteShader(FragmentShaderID);
  945. }
  946.  
  947. void cleanup_frame_buffer()
  948. {
  949.     // [TODO] stop being lazy.
  950. }
  951.  
  952. void cleanup_opengl()
  953. {
  954.     // [TODO] stop being lazy.
  955.  
  956. }
  957.  
  958. void cleanup_sdl()
  959. {
  960.     SDL_GL_DeleteContext(sdl_opengl_context);
  961.    
  962.     SDL_DestroyWindow(sdl_window);
  963.  
  964.     SDL_Quit();
  965. }
  966.  
  967. void cleanup_shader()
  968. {
  969.     for(int i = 0; i < 3; ++i)
  970.         m_eye_patch[i].cleanup();
  971.  
  972.     glDeleteProgram(gl_fragment_shader_program);
  973. }
  974.  
  975. int SDL_main(int argc, char * argv[])
  976. {  
  977.     setup_oculus();
  978.     setup_sdl();
  979.     setup_opengl();
  980.     setup_shaders();
  981.     setup_frame_buffer();
  982.  
  983.     sdl_main_loop();
  984.  
  985.     cleanup_shader();
  986.     cleanup_frame_buffer();
  987.     cleanup_opengl();
  988.     cleanup_sdl();
  989.  
  990.     return 0;
  991. }
  992.  
  993. /*
  994. void set_oculus_display_mode()
  995. {
  996.     int num_displays = SDL_GetNumVideoDisplays();
  997.  
  998.     for(int display_index = 0; display_index < num_displays; display_index++)
  999.     {
  1000.         int num_modes = SDL_GetNumDisplayModes(display_index);
  1001.  
  1002.         const char * display_name = SDL_GetDisplayName(display_index);
  1003.  
  1004.         SDL_Rect display_bounds;
  1005.         SDL_GetDisplayBounds(display_index, &display_bounds);
  1006.  
  1007.         trace("---- Display[%d] '%s'. %d modes, (%dx%d)", display_index, display_name, num_modes, display_bounds.w, display_bounds.h);
  1008.        
  1009.         for (int display_mode = 0; display_mode < num_modes; ++display_mode)
  1010.         {
  1011.             SDL_DisplayMode mode;
  1012.             SDL_GetDisplayMode(display_index, display_mode, &mode);
  1013.             trace("\t   Mode %d:  %dx%d %dHz %d bpp", display_mode, mode.w, mode.h, mode.refresh_rate, SDL_BITSPERPIXEL(mode.format));
  1014.  
  1015.             // find mode that matches the display.
  1016.             // [TODO] arbitrary display index.
  1017.             if(m_oculus.get_display_index() == display_index)
  1018.             {
  1019.                 // [TODO] arbitrary refresh rate and BPP.
  1020.                 const OVR::HMDInfo& hmd_info = m_oculus.get_HMD_info();
  1021.                 if( mode.w == hmd_info.HResolution &&
  1022.                     mode.h == hmd_info.VResolution &&
  1023.                     mode.refresh_rate == 60 &&
  1024.                     SDL_BITSPERPIXEL(mode.format) == 24)
  1025.                 {
  1026.                     SDL_SetWindowDisplayMode(sdl_window, &mode);
  1027.                     SDL_SetWindowPosition(sdl_window, display_bounds.x, display_bounds.y);
  1028.                     SDL_SetWindowSize(sdl_window, display_bounds.w, display_bounds.h);
  1029.                     //SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN);
  1030.                     trace("Window bound to Oculus display mode.");
  1031.                     break;
  1032.                 }
  1033.             }
  1034.         }
  1035.     }
  1036. }
  1037. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement