SensorBoxTest.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   SensorBoxTest.h
00004 Content     :   Visual orientaion sensor test app; renders a rotating box over axes.
00005 Created     :   October 1, 2012
00006 Authors     :   Michael Antonov
00007 
00008 Copyright   :   Copyright 2012 Oculus, Inc. All Rights reserved.
00009 
00010 Licensed under the Apache License, Version 2.0 (the "License");
00011 you may not use this file except in compliance with the License.
00012 You may obtain a copy of the License at
00013 
00014 http://www.apache.org/licenses/LICENSE-2.0
00015 
00016 Unless required by applicable law or agreed to in writing, software
00017 distributed under the License is distributed on an "AS IS" BASIS,
00018 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 See the License for the specific language governing permissions and
00020 limitations under the License.
00021 
00022 *************************************************************************************/
00023 
00024 #include "OVR.h"
00025 #include "Kernel/OVR_String.h"
00026 
00027 #include "../CommonSrc/Platform/Platform_Default.h"
00028 #include "../CommonSrc/Render/Render_Device.h"
00029 #include "../CommonSrc/Platform/Gamepad.h"
00030 
00031 using namespace OVR;
00032 using namespace OVR::Platform;
00033 using namespace OVR::Render;
00034 
00035 //-------------------------------------------------------------------------------------
00036 // ***** SensorBoxTest Description
00037 
00038 // This application renders an axes-colored box that rotates with sensor input. App allows
00039 // user to toggle views for debugging purposes by pressing F1, F2, F3 keys.
00040 // Application further allows running multiple sensors at once to compare sensor quality.
00041 //
00042 // The Right-handed coordinate system is defines as follows (as seen in perspective view):
00043 //  Y - Up    (colored red)
00044 //  Z - Back  (Out from screen, colored blue)
00045 //  X - Right (green)
00046 //  All cameras are looking at the origin.  
00047 
00048 // Camera view types.
00049 enum ViewType
00050 {
00051     View_Perspective,
00052     View_XZ_UpY,
00053     View_XY_DownZ,
00054     View_Count
00055 };
00056 
00057 
00058 //-------------------------------------------------------------------------------------
00059 
00060 class InputTestApp : public Application
00061 {
00062     RenderDevice*      pRender;
00063 
00064     Ptr<DeviceManager> pManager;
00065     Ptr<HMDDevice>     pHMD;
00066     Ptr<SensorDevice>  pSensor;
00067     Ptr<SensorDevice>  pSensor2;    
00068 
00069     SensorFusion       SFusion;
00070     SensorFusion       SFusion2;
00071     
00072     double          LastUpdate;
00073     ViewType        CurrentView;
00074 
00075     double          LastTitleUpdate;
00076 
00077     Matrix4f        Proj;
00078     Matrix4f        View;
00079     Scene           Sc;
00080     Ptr<Model>      pAxes;   // Model of the coordinate system
00081     Ptr<Container>  pBox;    // Rendered box
00082     Ptr<Container>  pBox2;   // Second model (right now just lines)
00083 
00084     // Applies specified projection/lookAt direction to the scene.
00085     void            SetView(ViewType view);
00086 
00087 public:
00088 
00089     InputTestApp();
00090     ~InputTestApp();
00091 
00092     virtual int  OnStartup(int argc, const char** argv);
00093     virtual void OnIdle();
00094 
00095     virtual void OnMouseMove(int x, int y, int modifiers);
00096     virtual void OnKey(KeyCode key, int chr, bool down, int modifiers);
00097 };
00098 
00099 InputTestApp::InputTestApp()
00100     : pRender(0), CurrentView(View_Perspective),
00101       LastUpdate(0), LastTitleUpdate(0), pAxes(0), pBox(0)
00102 {
00103 
00104 }
00105 
00106 
00107 /*
00108 void UseCase()
00109 {
00110     using namespace OVR;
00111 
00112     OVR::System::Init();
00113 
00114     Ptr<DeviceManager> pManager = 0;
00115     Ptr<HMDDevice>     pHMD = 0;
00116     Ptr<SensorDevice>  pSensor = 0;
00117     SensorFusion       FusionResult;
00118 
00119      
00120     // *** Initialization - Create the first available HMD Device
00121     pManager = *DeviceManager::Create();
00122     pHMD     = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
00123     if (!pHMD)
00124         return;
00125     pSensor  = *pHMD->GetSensor();
00126 
00127     // Get DisplayDeviceName, ScreenWidth/Height, etc..
00128     HMDInfo hmdInfo;
00129     pHMD->GetDeviceInfo(&hmdInfo);
00130     
00131     if (pSensor)
00132         FusionResult.AttachToSensor(pSensor);
00133 
00134     // *** Per Frame
00135     // Get orientation quaternion to control view
00136     Quatf q = FusionResult.GetOrientation();
00137 
00138     // Create a matrix from quaternion,
00139     // where elements [0][0] through [3][3] contain rotation.
00140     Matrix4f bodyFrameMatrix(q); 
00141 
00142     // Get Euler angles from quaternion, in specified axis rotation order.
00143     float yaw, pitch, roll;
00144     q.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &pitch, &roll);
00145 
00146     // *** Shutdown
00147     pSensor.Clear();
00148     pHMD.Clear();
00149     pManager.Clear();
00150 
00151     OVR::System::Destroy();
00152 }
00153 */
00154 
00155 InputTestApp::~InputTestApp()
00156 {
00157     pSensor.Clear();
00158     pManager.Clear();
00159     
00160 }
00161 
00162 
00163 int InputTestApp::OnStartup(int argc, const char** argv)
00164 {
00165     if (!pPlatform->SetupWindow(1200,800))
00166         return 1;
00167     
00168 
00169     pManager = *DeviceManager::Create();
00170     
00171     // This initialization logic supports running two sensors at the same time.
00172    
00173     DeviceEnumerator<SensorDevice> isensor = pManager->EnumerateDevices<SensorDevice>();
00174     DeviceEnumerator<SensorDevice> oculusSensor;
00175     DeviceEnumerator<SensorDevice> oculusSensor2;
00176     
00177     while(isensor)
00178     {
00179         DeviceInfo di;
00180         if (isensor.GetDeviceInfo(&di))
00181         {
00182             if (strstr(di.ProductName, "Tracker"))
00183             {
00184                 if (!oculusSensor)
00185                     oculusSensor = isensor;
00186                 else if (!oculusSensor2)
00187                     oculusSensor2 = isensor;
00188             }
00189         }
00190 
00191         isensor.Next();
00192     }
00193 
00194     if (oculusSensor)
00195     {
00196         pSensor = *oculusSensor.CreateDevice();
00197 
00198         if (pSensor)
00199             pSensor->SetRange(SensorRange(4 * 9.81f, 8 * Math<float>::Pi, 1.0f), true);
00200 
00201         if (oculusSensor2)
00202         {
00203             // Second Oculus sensor, useful for comparing firmware behavior & settings.
00204             pSensor2 = *oculusSensor2.CreateDevice();
00205 
00206             if (pSensor2)
00207                 pSensor2->SetRange(SensorRange(4 * 9.81f, 8 * Math<float>::Pi, 1.0f), true);
00208         }
00209     }
00210 
00211     oculusSensor.Clear();
00212     oculusSensor2.Clear();
00213        
00214     
00215     /*
00216     DeviceHandle hHMD = pManager->EnumerateDevices<HMDDevice>();
00217     HMDInfo      hmdInfo;
00218     if (hHMD)
00219     {        
00220         hHMD.GetDeviceInfo(&hmdInfo);
00221     }
00222     */
00223 
00224     if (pSensor)
00225         SFusion.AttachToSensor(pSensor);
00226     if (pSensor2)
00227         SFusion2.AttachToSensor(pSensor2);
00228 
00229     /*
00230     // Test rotation: This give rotations clockwise (CW) while looking from
00231     // origin in the direction of the axis.
00232 
00233     Vector3f xV(1,0,0);
00234     Vector3f zV(0,0,1);
00235 
00236     Vector3f rxV = Matrix4f::RotationZ(DegreeToRad(10.0f)).Transform(xV);
00237     Vector3f ryV = Matrix4f::RotationY(DegreeToRad(10.0f)).Transform(xV);
00238     Vector3f rzV = Matrix4f::RotationX(DegreeToRad(10.0f)).Transform(zV);
00239     */
00240 
00241     // Report relative mouse motion (not absolute position)
00242    // pPlatform->SetMouseMode(Mouse_Relative);
00243 
00244     const char* graphics = "d3d10";
00245     for (int i = 1; i < argc; i++)
00246         if (!strcmp(argv[i], "-r") && i < argc-1)
00247             graphics = argv[i+1];
00248 
00249     pRender = pPlatform->SetupGraphics(OVR_DEFAULT_RENDER_DEVICE_SET, graphics,
00250                                        RendererParams());
00251   
00252     //WireframeFill = pRender->CreateSimpleFill(Fill::F_Wireframe);
00253 
00254 
00255     
00256     // *** Rotating Box
00257     
00258     pBox = *new Container;
00259     pBox->Add(Ptr<Model>(        
00260        *Model::CreateAxisFaceColorBox(-2.0f, 2.0f, Color(0,   0xAA, 0),        // x = green
00261                                       -1.0f, 1.0f, Color(0xAA,0,    0),        // y = red
00262                                       -1.0f, 1.0f, Color(0,   0,    0xAA)) )); // z = blue 
00263     // Drop-down line from box, to make it easier to see differences in angle.
00264     Ptr<Model> downLine = *new Model(Prim_Lines);
00265     downLine->AddLine(Vertex(0.0f,-4.5f, 0.0f, 0xFFE0B0B0),
00266                       Vertex(0.0f, 0.0f, 0.0f, 0xFFE0B0B0));
00267     pBox->Add(downLine);
00268     Sc.World.Add(pBox);
00269 
00270     
00271     // Secondary rotating coordinate object, if we have two values.
00272     if (pSensor2)
00273     {
00274         pBox2 = *new Container;
00275 
00276         // Drop-down line from box, to make it easier to see differences in angle.
00277         Ptr<Model> lines = *new Model(Prim_Lines);
00278         lines->AddLine(Vertex( 0.0f,-4.0f, 0.0f, 0xFFA07070),  // -Y
00279                        Vertex( 0.0f, 0.0f, 0.0f, 0xFFA07070));
00280         lines->AddLine(Vertex(-4.0f, 0.0f, 0.0f, 0xFF70A070),  // -X
00281                        Vertex( 0.0f, 0.0f, 0.0f, 0xFF70A070));
00282         lines->AddLine(Vertex( 0.0f, 0.0f,-4.0f, 0xFF7070A0),  // -Z
00283                        Vertex( 0.0f, 0.0f, 0.0f, 0xFF7070A0));
00284         pBox2->Add(lines);
00285         Sc.World.Add(pBox2);
00286     }
00287 
00288 
00289     // *** World axis X,Y,Z rendering.
00290 
00291     pAxes = *new Model(Prim_Lines);
00292     pAxes->AddLine(Vertex(-8.0f, 0.0f, 0.0f, 0xFF40FF40),
00293                    Vertex( 8.0f, 0.0f, 0.0f, 0xFF40FF40)); // X
00294     pAxes->AddLine(Vertex( 7.6f, 0.4f, 0.4f, 0xFF40FF40),
00295                    Vertex( 8.0f, 0.0f, 0.0f, 0xFF40FF40)); // X - arrow
00296     pAxes->AddLine(Vertex( 7.6f,-0.4f,-0.4f, 0xFF40FF40),
00297                    Vertex( 8.0f, 0.0f, 0.0f, 0xFF40FF40)); // X - arrow
00298 
00299     pAxes->AddLine(Vertex( 0.0f,-8.0f, 0.0f, 0xFFFF4040),
00300                    Vertex( 0.0f, 8.0f, 0.0f, 0xFFFF4040)); // Y
00301     pAxes->AddLine(Vertex( 0.4f, 7.6f, 0.0f, 0xFFFF4040),
00302                    Vertex( 0.0f, 8.0f, 0.0f, 0xFFFF4040)); // Y - arrow
00303     pAxes->AddLine(Vertex(-0.4f, 7.6f, 0.0f, 0xFFFF4040),
00304                    Vertex( 0.0f, 8.0f, 0.0f, 0xFFFF4040)); // Y
00305     
00306     pAxes->AddLine(Vertex( 0.0f, 0.0f,-8.0f, 0xFF4040FF),
00307                    Vertex( 0.0f, 0.0f, 8.0f, 0xFF4040FF)); // Z
00308     pAxes->AddLine(Vertex( 0.4f, 0.0f, 7.6f, 0xFF4040FF),
00309                    Vertex( 0.0f, 0.0f, 8.0f, 0xFF4040FF)); // Z - arrow
00310     pAxes->AddLine(Vertex(-0.4f, 0.0f, 7.6f, 0xFF4040FF),
00311                    Vertex( 0.0f, 0.0f, 8.0f, 0xFF4040FF)); // Z - arrow
00312     Sc.World.Add(pAxes);
00313    
00314 
00315     SetView(CurrentView);
00316 
00317 
00318     LastUpdate = pPlatform->GetAppTime();
00319     return 0;
00320 }
00321 
00322 void InputTestApp::SetView(ViewType type)
00323 {
00324     switch(type)
00325     {
00326     case View_Perspective:
00327         View = Matrix4f::LookAtRH(Vector3f(5.0f, 4.0f, 10.0f), // eye
00328                                   Vector3f(0.0f, 1.5f, 0.0f),   // at
00329                                   Vector3f(0.0f, 1.0f, 0.0f));
00330         break;
00331 
00332     case View_XY_DownZ: // F2
00333         View = Matrix4f::LookAtRH(Vector3f(0.0f, 0.0f, 10.0f),  // eye
00334                                   Vector3f(0.0f, 0.0f, 0.0f),   // at
00335                                   Vector3f(0.0f, 1.0f, 0.0f));
00336         break;
00337 
00338      case View_XZ_UpY:
00339         View = Matrix4f::LookAtRH(Vector3f(0.0f,-10.0f, 0.0f),   // eye
00340                                   Vector3f(0.0f,  0.0f, 0.0f),   // at
00341                                   Vector3f(0.0f,  0.0f, 1.0f));
00342         
00343         break;
00344         default:
00345             break;
00346     }
00347 
00348     Proj = Matrix4f::PerspectiveRH(DegreeToRad(70.0f), 1280 / (float)800,
00349                                    0.3f, 1000.0f);  // LH
00350 }
00351 
00352 
00353 void InputTestApp::OnMouseMove(int x, int y, int modifiers)
00354 {
00355     OVR_UNUSED3(x, y, modifiers);
00356 }
00357 
00358 
00359 static float CalcDownAngleDegrees(Quatf q)
00360 {
00361     Vector3f downVector(0.0f, -1.0f, 0.0f);    
00362     Vector3f val= q.Rotate(downVector);
00363     return RadToDegree(downVector.Angle(val));
00364 }
00365 
00366 void InputTestApp::OnKey(KeyCode key, int chr, bool down, int modifiers)
00367 {
00368     OVR_UNUSED2(chr, modifiers);
00369 
00370     switch (key)
00371     {
00372     case Key_Q:
00373         if (!down)
00374             pPlatform->Exit(0);
00375         break;
00376 
00377     case Key_F1:
00378         CurrentView = View_Perspective;
00379         SetView(CurrentView);
00380         //UpdateWindowTitle();
00381         break;
00382     case Key_F2:
00383         CurrentView = View_XY_DownZ;
00384         SetView(CurrentView);
00385         break;
00386     case Key_F3:
00387         CurrentView = View_XZ_UpY;
00388         SetView(CurrentView);
00389         break;
00390 
00391     case Key_R:
00392         if (down)
00393         {
00394             SFusion.Reset();
00395             SFusion2.Reset();
00396         }
00397         break;
00398 
00399     case Key_H:
00400         if (down && pSensor)
00401         {
00402             SensorDevice::CoordinateFrame coord = pSensor->GetCoordinateFrame();
00403             pSensor->SetCoordinateFrame(
00404                 (coord == SensorDevice::Coord_Sensor) ?
00405                 SensorDevice::Coord_HMD : SensorDevice::Coord_Sensor);
00406             SFusion.Reset();
00407             SFusion2.Reset();
00408         }
00409         break;
00410 
00411     case Key_G:
00412         if (down)
00413         {
00414             SFusion.SetGravityEnabled(!SFusion.IsGravityEnabled());
00415             SFusion2.SetGravityEnabled(SFusion.IsGravityEnabled());
00416         }
00417         break;
00418 
00419     case Key_A:
00420 
00421         if (down)
00422         {
00423             if (!pSensor2)
00424             {
00425                 LogText("Angle: %2.3f\n", CalcDownAngleDegrees(SFusion.GetOrientation()));
00426             }
00427             else
00428             {
00429                 LogText("Angle: %2.3f Secondary Sensor Angle: %2.3f\n",
00430                         CalcDownAngleDegrees(SFusion.GetOrientation()),
00431                         CalcDownAngleDegrees(SFusion2.GetOrientation()));
00432             }                        
00433         }
00434         break;
00435 
00436         /*
00437     case Key_End:
00438         if (!down)
00439         {
00440             OriAdjust = OriSensor.Conj();
00441             Sc.ViewPoint.SetOrientation(Quatf());
00442         }
00443         break; */
00444         default:
00445             break;
00446     }
00447 }
00448 
00449 void InputTestApp::OnIdle()
00450 {
00451     double curtime = pPlatform->GetAppTime();
00452  //   float  dt      = float(LastUpdate - curtime);
00453     LastUpdate     = curtime;
00454     
00455     if (pBox)
00456     {
00457         Quatf q = SFusion.GetOrientation();
00458         pBox->SetOrientation(q);
00459 
00460    // Test Euler conversion, alternative to the above:
00461    //     Vector3f euler;
00462    //     SFusion.GetOrientation().GetEulerABC<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&euler.y, &euler.x, &euler.z);
00463    //     Matrix4f mat = Matrix4f::RotationY(euler.y) * Matrix4f::RotationX(euler.x) * Matrix4f::RotationZ(euler.z);
00464    //  pBox->SetMatrix(mat);    
00465 
00466         // Update titlebar every 20th of a second.
00467         if ((curtime - LastTitleUpdate) > 0.05f)
00468         {
00469             char                          titleBuffer[512];
00470             SensorDevice::CoordinateFrame coord = SensorDevice::Coord_Sensor;
00471             if (pSensor)
00472                 coord = pSensor->GetCoordinateFrame();
00473 
00474             OVR_sprintf(titleBuffer, 512, "OVR SensorBox %s %s  Ang: %0.3f",
00475                         (SFusion.IsGravityEnabled() ?  "" : "[Grav Off]"),
00476                         (coord == SensorDevice::Coord_HMD) ? "[HMD Coord]" : "",
00477                         CalcDownAngleDegrees(q));
00478             pPlatform->SetWindowTitle(titleBuffer);
00479             LastTitleUpdate = curtime;
00480         }
00481     }
00482 
00483     if (pBox2)
00484     {
00485         pBox2->SetOrientation(SFusion2.GetOrientation());
00486     }
00487 
00488     // Render
00489     int w, h;
00490     pPlatform->GetWindowSize(&w, &h);
00491 
00492     pRender->SetViewport(0, 0, w, h);
00493 
00494     pRender->Clear();
00495     pRender->BeginScene();
00496 
00497     pRender->SetProjection(Proj);
00498     pRender->SetDepthMode(1,1);
00499     
00500     Sc.Render(pRender, View);
00501 
00502     pRender->Present();
00503 
00504 }
00505 
00506 OVR_PLATFORM_APP(InputTestApp);


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19