Guest User

Untitled

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