Advertisement
fistsofthenorthstar

Oculus + OpenGL + SDL 2 minimal demo on (Visual Studio 9).

Sep 13th, 2013
2,048
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.63 KB | None | 0 0
  1. //----------------------------------------------
  2. // Oculus + OpenGL + SDL 2 minimal demo.
  3. //
  4. // Author : Olivier Renault.
  5. //----------------------------------------------
  6. #include <windows.h>
  7. #include <GL/gl.h>
  8. #include <GL/glu.h>
  9. #include <stdio.h>
  10. #include <limits>
  11. #include "sdl.h"
  12. #include "OVR.h"
  13.  
  14. #pragma comment(lib, "Winmm.lib")
  15. #pragma comment(lib, "opengl32.lib")
  16. #pragma comment(lib, "glu32.lib")
  17. #pragma comment(lib, "libovr.lib")
  18. #pragma comment (lib, "sdl2.lib")
  19. #pragma comment (lib, "sdl2main.lib")
  20.  
  21. void trace(const char* format, ...)
  22. {
  23.     char temp[1024];
  24.     va_list args;
  25.     va_start(args, format);
  26.     vsprintf_s(temp, sizeof(temp), format, args);
  27.     va_end(args);
  28.     OutputDebugString(temp);
  29.     OutputDebugString("\n");
  30. }
  31.  
  32. void debug_break()
  33. {
  34.     __asm int 3;
  35. }
  36.  
  37. #define TRACE(A, ...)  { trace("[TRACE] %s", A, __VA_ARGS__); }
  38. #define WARN(A, ...)   { trace("[WARN]  %s", A, __VA_ARGS__); }
  39. #define FATAL(A, ...)  { trace("[FATAL] %s", A, __VA_ARGS__); debug_break(); }
  40. #define ASSERT(A)      { if(!(A)) { trace("[ASSERT] %s", #A); debug_break(); } }
  41.  
  42. class Oculus : public OVR::MessageHandler
  43. {
  44. public:
  45.     Oculus()
  46.     {}
  47.  
  48.     ~Oculus()
  49.     {
  50.         OVR::MessageHandler::RemoveHandlerFromDevices();
  51.         m_sensor.Clear();
  52.         m_HMD.Clear();
  53.         m_device_manager.Clear();
  54.        
  55.         OVR::System::Destroy();
  56.         OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
  57.     }
  58.  
  59.     void start()
  60.     {
  61.         OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
  62.        
  63.         m_device_manager = *OVR::DeviceManager::Create();
  64.        
  65.         // We'll handle it's messages in this case.
  66.         m_device_manager->SetMessageHandler(this);
  67.  
  68.         // Release Sensor/HMD in case this is a retry.
  69.         m_sensor.Clear();
  70.         m_HMD.Clear();
  71.        
  72.         m_HMD = *m_device_manager->EnumerateDevices<OVR::HMDDevice>().CreateDevice();
  73.         if (m_HMD)
  74.         {
  75.             m_sensor = *m_HMD->GetSensor();
  76.  
  77.             // This will initialize HMDInfo with information about configured IPD,
  78.             // screen size and other variables needed for correct projection.
  79.             // We pass HMD DisplayDeviceName into the renderer to select the
  80.             // correct monitor in full-screen mode.
  81.             m_HMD->GetDeviceInfo(&m_HMD_info);
  82.  
  83.             m_stereo_config.SetHMDInfo(m_HMD_info);
  84.             m_stereo_config.SetFullViewport(OVR::Util::Render::Viewport(0,0, m_HMD_info.HResolution, m_HMD_info.VResolution));
  85.             m_stereo_config.SetStereoMode(OVR::Util::Render::Stereo_LeftRight_Multipass);
  86.             if (m_HMD_info.HScreenSize > 0.140f) // 7"
  87.                 m_stereo_config.SetDistortionFitPointVP(-1.0f, 0.0f);
  88.             else
  89.                 m_stereo_config.SetDistortionFitPointVP(0.0f, 1.0f);
  90.         }
  91.         else
  92.         {            
  93.             // If we didn't detect an HMD, try to create the sensor directly.
  94.             // This is useful for debugging sensor interaction; it is not needed in
  95.             // a shipping app.
  96.             m_sensor = m_device_manager->EnumerateDevices<OVR::SensorDevice>().CreateDevice();
  97.         }
  98.  
  99.         const char* detectionMessage=0;
  100.         if (!m_HMD && !m_sensor)
  101.             detectionMessage = "Oculus Rift not detected.";
  102.         else if (!m_HMD)
  103.             detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
  104.         else if (!m_sensor)
  105.             detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
  106.         else if (m_HMD_info.DisplayDeviceName[0] == '\0')
  107.             detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
  108.         else
  109.             detectionMessage = 0;
  110.  
  111.         if (detectionMessage)
  112.         {
  113.             ::MessageBoxA(0, detectionMessage, "Oculus Rift ERROR", MB_OK);
  114.         }
  115.        
  116.         if (m_sensor)
  117.         {
  118.             // We need to attach sensor to SensorFusion object for it to receive
  119.             // body frame messages and update orientation. SFusion.GetOrientation()
  120.             // is used in OnIdle() to orient the view.
  121.             m_sensor_fusion.AttachToSensor(m_sensor);
  122.             m_sensor_fusion.SetPredictionEnabled(true);
  123.             m_sensor_fusion.SetDelegateMessageHandler(this);           
  124.         }
  125.     }
  126.  
  127.     bool get_sensor_position(float& x, float& y, float& z) const
  128.     {
  129.         x = 0.0f;
  130.         y = 0.0f;
  131.         z = 0.0f;
  132.         return false;
  133.     }
  134.  
  135.     bool get_sensor_orientation(float& yaw, float& pitch, float& roll) const
  136.     {
  137.         yaw = 0.0f;
  138.         pitch = 0.0f;
  139.         roll = 0.0f;
  140.    
  141.         if(!m_sensor_fusion.IsAttachedToSensor())
  142.             return false;
  143.  
  144.         OVR::Quatf hmdOrient = m_sensor_fusion.GetOrientation();
  145.         hmdOrient.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&yaw, &pitch, &roll);
  146.         return true;
  147.     }
  148.  
  149.     const OVR::HMDInfo& get_HMD_info() const
  150.     {
  151.         return m_HMD_info;
  152.     }
  153.  
  154.     OVR::Util::Render::StereoConfig get_stereo_config() const
  155.     {
  156.         return m_stereo_config;
  157.     }
  158.  
  159.     virtual void OnMessage(const OVR::Message& msg)
  160.     {
  161.         if(msg.pDevice == m_sensor)
  162.         {
  163.             if (msg.Type == OVR::Message_BodyFrame)
  164.             {
  165.             }
  166.         }
  167.         else if(msg.pDevice == m_device_manager)
  168.         {
  169.             if (msg.Type == OVR::Message_DeviceAdded)
  170.             {
  171.                 trace("DeviceManager reported device added.");
  172.             }
  173.             else if (msg.Type == OVR::Message_DeviceRemoved)
  174.             {
  175.                 trace("DeviceManager reported device removed.");
  176.             }
  177.             else if (msg.Type == OVR::Message_DeviceAdded)
  178.             {
  179.                 trace("Sensor reported device added.");
  180.             }
  181.             else if (msg.Type == OVR::Message_DeviceRemoved)
  182.             {
  183.                 trace("Sensor reported device removed.");
  184.             }
  185.         }
  186.     }
  187.  
  188. private:
  189.     OVR::Ptr<OVR::DeviceManager>            m_device_manager;
  190.     OVR::Ptr<OVR::SensorDevice>             m_sensor;
  191.     OVR::Ptr<OVR::HMDDevice>                m_HMD;
  192.     OVR::HMDInfo                            m_HMD_info;
  193.     OVR::SensorFusion                       m_sensor_fusion;
  194.     OVR::Util::Render::StereoConfig         m_stereo_config;
  195. };
  196.  
  197. class Avatar
  198. {
  199. public:
  200.     Avatar()
  201.     {
  202.         m_oculus = NULL;
  203.     }
  204.  
  205.     void start(const Oculus* oculus)
  206.     {
  207.         m_oculus = oculus;
  208.         m_speed = 10.0f;
  209.     }
  210.  
  211.     void on_key_down(int key)
  212.     {
  213.         switch(key)
  214.         {
  215.         case SDLK_UP:
  216.             {
  217.                 m_velocity.z = -m_speed;
  218.                 break;
  219.             }
  220.         case SDLK_DOWN:
  221.             {
  222.                 m_velocity.z = m_speed;
  223.                 break;
  224.             }
  225.         case SDLK_LEFT:
  226.             {
  227.                 m_velocity.x = -m_speed;
  228.                 break;
  229.             }
  230.         case SDLK_RIGHT:
  231.             {
  232.                 m_velocity.x = m_speed;
  233.                 break;
  234.             }
  235.         }
  236.     }
  237.  
  238.     void on_key_up(int key)
  239.     {
  240.         switch(key)
  241.         {
  242.         case SDLK_UP:
  243.             {
  244.                 m_velocity.z = 0.0f;
  245.                 break;
  246.             }
  247.         case SDLK_DOWN:
  248.             {
  249.                 m_velocity.z = 0.0f;
  250.                 break;
  251.             }
  252.         case SDLK_LEFT:
  253.             {
  254.                 m_velocity.x = 0.0f;
  255.                 break;
  256.             }
  257.         case SDLK_RIGHT:
  258.             {
  259.                 m_velocity.x = 0.0f;
  260.                 break;
  261.             }
  262.         }
  263.     }
  264.  
  265.     const OVR::Vector3f& get_position() const
  266.     {
  267.         return m_position;
  268.     }
  269.  
  270.     void set_position(const OVR::Vector3f& position)
  271.     {
  272.         m_position = position;
  273.     }
  274.  
  275.     void update(float dt)
  276.     {
  277.         m_position += m_velocity * dt;
  278.     }
  279.  
  280.     void apply_gl_matrix(const OVR::Matrix4f& matrix)
  281.     {
  282.         glMultMatrixf(&(matrix.Transposed().M[0][0]));
  283.     }
  284.  
  285.     void begin_render(OVR::Util::Render::StereoEye eye)
  286.     {
  287.         const OVR::Util::Render::StereoEyeParams& params = m_oculus->get_stereo_config().GetEyeRenderParams(eye);
  288.         glViewport(params.VP.x, params.VP.y, params.VP.w, params.VP.h);
  289.         glMatrixMode(GL_PROJECTION);
  290.         glLoadIdentity();
  291.         apply_gl_matrix(params.ViewAdjust);
  292.         apply_gl_matrix(params.Projection);
  293.  
  294.         glMatrixMode(GL_MODELVIEW);
  295.         glLoadIdentity();
  296.        
  297.         OVR::Matrix4f eye_view = get_eye_view(eye);
  298.         apply_gl_matrix(eye_view);
  299.     }
  300.  
  301.     OVR::Matrix4f get_eye_view(OVR::Util::Render::StereoEye eye)
  302.     {
  303.         static const OVR::Vector3f UpVector(0.0f, 1.0f, 0.0f);
  304.         static const OVR::Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
  305.         static const OVR::Vector3f RightVector(1.0f, 0.0f, 0.0f);
  306.  
  307.         float yaw, pitch, roll;
  308.         m_oculus->get_sensor_orientation(yaw, pitch, roll);
  309.         OVR::Matrix4f eye_rpy = OVR::Matrix4f::RotationY(yaw) * OVR::Matrix4f::RotationX(pitch) * OVR::Matrix4f::RotationZ(roll);
  310.  
  311.         OVR::Vector3f eye_pos = m_position;
  312.         OVR::Vector3f eye_forward = eye_rpy.Transform(ForwardVector);
  313.         OVR::Vector3f eye_up = eye_rpy.Transform(UpVector);
  314.         OVR::Vector3f eye_right = eye_rpy.Transform(RightVector);
  315.         OVR::Matrix4f eye_view = OVR::Matrix4f::LookAtRH(eye_pos, eye_pos + eye_forward, eye_up);
  316.         return eye_view;
  317.     }
  318.  
  319.     float m_speed;
  320.     OVR::Vector3f m_position;
  321.     OVR::Vector3f m_velocity;
  322.     const Oculus* m_oculus;
  323. };
  324.  
  325. struct Scene
  326. {
  327.     int spherelist;
  328.  
  329.     Scene()
  330.     {
  331.         spherelist = -1;
  332.     }
  333.     ~Scene()
  334.     {
  335.         if(glIsList(spherelist))
  336.         {
  337.             glDeleteLists(spherelist, 1);
  338.         }
  339.     }
  340.  
  341.     void draw_sphere()
  342.     {
  343.         if(!glIsList(spherelist))
  344.         {
  345.             spherelist = glGenLists(1);
  346.             glNewList(spherelist,GL_COMPILE);
  347.             GLUquadricObj* sphere=gluNewQuadric();
  348.             gluQuadricNormals(sphere, GLU_SMOOTH);
  349.             gluQuadricTexture(sphere, GL_TRUE);
  350.             gluSphere(sphere,0.5,20,20);
  351.             gluDeleteQuadric(sphere);      
  352.             glEndList();
  353.         }
  354.  
  355.         if(glIsList(spherelist))
  356.         {
  357.             glCallList(spherelist);
  358.         }
  359.     }
  360.  
  361.     // draw a bunch of spheres
  362.     void draw(const OVR::Vector3f position)
  363.     {
  364.         float scale = 10.0f;
  365.         float step = scale * 2.0f;
  366.         int nx = 10;
  367.         int ny = 1;
  368.         int nz = 10;
  369.        
  370.         float cx = (int)(position.x / step) * step;
  371.         float cy = (int)(position.y / step) * step;
  372.         float cz = (int)(position.z / step) * step;
  373.        
  374.         for(int ix = 0; ix < nx; ix++)
  375.         {
  376.             for(int iz = 0; iz < nz; iz++)
  377.             {
  378.                 for(int iy = 0; iy < ny; iy++)
  379.                 {
  380.                     glPushMatrix();
  381.                     float x = cx + (ix - nx * 0.5f)* (step);
  382.                     float y = cy + (iy - ny * 0.5f)* (step);
  383.                     float z = cz + (iz - nz * 0.5f)* (step);
  384.                     glTranslatef(x, y, z);
  385.                     glScalef(scale, scale, scale);
  386.                     draw_sphere();
  387.                     glPopMatrix();
  388.                 }
  389.             }
  390.         }
  391.     }
  392. };
  393.  
  394. // SDL stuff
  395. bool sdl_debug = false;
  396. bool sdl_quit = false;
  397. SDL_Window *sdl_window=NULL;
  398. SDL_GLContext sdl_opengl_context;
  399. unsigned int sdl_frame_timestamp = 0;
  400. unsigned int sdl_frame_timestep = 16;
  401.  
  402. // object encapsulation.
  403. Avatar m_avatar;
  404. Oculus m_oculus;
  405. Scene m_scene;
  406.  
  407. void update_render(void)
  408. {
  409.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  410.  
  411.     m_avatar.begin_render(OVR::Util::Render::StereoEye_Left);
  412.     m_scene.draw(m_avatar.get_position());
  413.  
  414.     m_avatar.begin_render(OVR::Util::Render::StereoEye_Right);
  415.     m_scene.draw(m_avatar.get_position());
  416.  
  417.     SDL_GL_SwapWindow(sdl_window);
  418. }
  419.  
  420. void update_tick()
  421. {
  422.     unsigned int sdl_frame_time = SDL_GetTicks() - sdl_frame_timestamp;
  423.     if(sdl_frame_time < sdl_frame_timestep) SDL_Delay(sdl_frame_timestep - sdl_frame_time);
  424.     sdl_frame_timestamp = SDL_GetTicks();
  425. }
  426.  
  427. void update_sdl_events()
  428. {
  429.     SDL_Event event;   
  430.     while( SDL_PollEvent( &event ) )
  431.     {
  432.         if( event.type == SDL_KEYDOWN )
  433.         {
  434.             if(event.key.keysym.sym == SDLK_ESCAPE)
  435.             {
  436.                 sdl_quit = true;
  437.             }
  438.             else
  439.             {
  440.                 m_avatar.on_key_down(event.key.keysym.sym);
  441.             }
  442.         }
  443.         else if( event.type == SDL_KEYUP )
  444.         {
  445.             m_avatar.on_key_up(event.key.keysym.sym);
  446.         }
  447.         else if( event.type == SDL_QUIT )
  448.         {
  449.             sdl_quit = true;
  450.         }
  451.     }
  452. }
  453.  
  454. void setup_oculus()
  455. {
  456.     m_oculus.start();
  457.     m_avatar.start(&m_oculus);
  458. }
  459.  
  460. void setup_sdl()
  461. {
  462.     if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
  463.         return;    
  464.    
  465.     const OVR::HMDInfo& hmd_info = m_oculus.get_HMD_info();
  466.     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);
  467.     sdl_opengl_context = SDL_GL_CreateContext(sdl_window);
  468.  
  469.     if(!sdl_debug)
  470.     {
  471.         // set window bounds into oculus display.
  472.         SDL_SetWindowPosition(sdl_window, hmd_info.DesktopX, hmd_info.DesktopY);
  473.         SDL_SetWindowSize(sdl_window, hmd_info.HResolution, hmd_info.VResolution);
  474.         //SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN);
  475.     }
  476. }
  477.  
  478. void setup_material()
  479. {  
  480.     float mat_specular[4]={1.0f,1.0f,1.0f,1.0f};
  481.     float mat_diffuse[4] ={0.5f,0.0f,0.0f,1.0f};
  482.     float mat_ambient[4] ={0.2f,0.1f,0.1f,1.0f};
  483.     float mat_shininess=50.0;
  484.  
  485.     glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,mat_shininess);
  486.     glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
  487.     glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
  488.     glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,mat_ambient);
  489. }
  490.  
  491. void setup_lighting()
  492. {
  493.     GLfloat global_ambient[]={.3f,.3f,.3f,1.0f};
  494.     GLfloat ambient[]={1.0f,0.0f,0.0f,1.0f};
  495.     glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
  496.     glLightfv(GL_LIGHT0,GL_LIGHT_MODEL_AMBIENT,global_ambient);
  497.  
  498.     GLfloat diffuse[]= { 0.5,0.5,0.5,1.0 };
  499.     glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
  500.  
  501.     GLfloat specular[] = { 1.0,1.0,1.0,1.0 };
  502.     glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
  503.  
  504.     GLfloat light_position[]={ 100.0,1000.0,100.0,1.0};
  505.     glLightfv(GL_LIGHT0,GL_POSITION,light_position);
  506.  
  507.     glEnable(GL_LIGHT0);
  508.     glEnable(GL_LIGHTING);
  509. }
  510.  
  511. void setup_opengl()
  512. {
  513.     // shading
  514.     glClearColor    (0.1f, 0.1f, 0.1f, 1.0f);
  515.     glShadeModel    (GL_SMOOTH);
  516.     glEnable        (GL_NORMALIZE);
  517.  
  518.     // culling
  519.     glPolygonMode   (GL_FRONT_AND_BACK,GL_FILL);
  520.     glEnable        (GL_CULL_FACE);
  521.     glFrontFace     (GL_CW);
  522.     glCullFace      (GL_BACK);
  523.     glEnable        (GL_DEPTH_TEST);
  524.     glDepthMask     (GL_TRUE);
  525.     glDepthFunc     (GL_LEQUAL);
  526.    
  527.     // blending
  528.     glEnable        (GL_BLEND);
  529.     glBlendFunc     (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  530.  
  531.     setup_lighting();
  532.     setup_material();
  533. }
  534.  
  535. void sdl_main_loop()
  536. {
  537.     while(!sdl_quit)
  538.     {
  539.         update_tick();
  540.         update_sdl_events();
  541.         m_avatar.update(sdl_frame_timestep / 1000.0f);
  542.         update_render();
  543.     }
  544. }
  545.  
  546. void destroy_sdl()
  547. {
  548.     SDL_GL_DeleteContext(sdl_opengl_context);
  549.    
  550.     SDL_DestroyWindow(sdl_window);
  551.  
  552.     SDL_Quit();
  553. }
  554.  
  555. int SDL_main(int argc, char * argv[])
  556. {  
  557.     setup_oculus();
  558.     setup_sdl();
  559.     setup_opengl();
  560.     sdl_main_loop();
  561.     destroy_sdl();
  562.     return 0;
  563. }
  564.  
  565. /*
  566. void set_oculus_display_mode()
  567. {
  568.     int num_displays = SDL_GetNumVideoDisplays();
  569.  
  570.     for(int display_index = 0; display_index < num_displays; display_index++)
  571.     {
  572.         int num_modes = SDL_GetNumDisplayModes(display_index);
  573.  
  574.         const char * display_name = SDL_GetDisplayName(display_index);
  575.  
  576.         SDL_Rect display_bounds;
  577.         SDL_GetDisplayBounds(display_index, &display_bounds);
  578.  
  579.         trace("---- Display[%d] '%s'. %d modes, (%dx%d)", display_index, display_name, num_modes, display_bounds.w, display_bounds.h);
  580.        
  581.         for (int display_mode = 0; display_mode < num_modes; ++display_mode)
  582.         {
  583.             SDL_DisplayMode mode;
  584.             SDL_GetDisplayMode(display_index, display_mode, &mode);
  585.             trace("\t   Mode %d:  %dx%d %dHz %d bpp", display_mode, mode.w, mode.h, mode.refresh_rate, SDL_BITSPERPIXEL(mode.format));
  586.  
  587.             // find mode that matches the display.
  588.             // [TODO] arbitrary display index.
  589.             if(m_oculus.get_display_index() == display_index)
  590.             {
  591.                 // [TODO] arbitrary refresh rate and BPP.
  592.                 const OVR::HMDInfo& hmd_info = m_oculus.get_HMD_info();
  593.                 if( mode.w == hmd_info.HResolution &&
  594.                     mode.h == hmd_info.VResolution &&
  595.                     mode.refresh_rate == 60 &&
  596.                     SDL_BITSPERPIXEL(mode.format) == 24)
  597.                 {
  598.                     SDL_SetWindowDisplayMode(sdl_window, &mode);
  599.                     SDL_SetWindowPosition(sdl_window, display_bounds.x, display_bounds.y);
  600.                     SDL_SetWindowSize(sdl_window, display_bounds.w, display_bounds.h);
  601.                     //SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN);
  602.                     trace("Window bound to Oculus display mode.");
  603.                     break;
  604.                 }
  605.             }
  606.         }
  607.     }
  608. }
  609. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement