KINECT STATS GENERATOR FOR SPORTS VISUALISATION  1.0
StatsVisualization.cpp
Go to the documentation of this file.
00001 #include "StatsVisualization.h"
00002 #include "KinectInterface.h"
00003 
00004 
00005 #include <iostream>
00006 #include <ngl/Camera.h>
00007 #include <ngl/Light.h>
00008 #include <ngl/Transformation.h>
00009 #include <ngl/TransformStack.h>
00010 #include <ngl/Material.h>
00011 #include <ngl/NGLInit.h>
00012 #include <ngl/VAOPrimitives.h>
00013 
00014 #include <ngl/Random.h>
00015 #include <ngl/Util.h>
00016 #include <ngl/Texture.h>
00017 
00018 //#include <boost/foreach.hpp>
00019 
00020 /*
00021   LICENSING: You are free to use any part of this project provided I am informed about it via email
00022   at santoshwins@hotmail.com and referenced appropriately in your works
00023   */
00024 
00025 //----------------------------------------------------------------------------------------------------------------------
00027 //----------------------------------------------------------------------------------------------------------------------
00028 const static float INCREMENT=0.01;
00029 //----------------------------------------------------------------------------------------------------------------------
00031 //----------------------------------------------------------------------------------------------------------------------
00032 const static float ZOOM=0.3;
00033 //----------------------------------------------------------------------------------------------------------------------
00034 
00035 const GLubyte indices[]=  {
00036                             3,2,7,2,6,7, // back
00037                             0,4,1,1,4,5, // front
00038                             3,0,2,2,0,1, // top
00039                             6,4,7,5,4,6, // bottom
00040                             3,7,4,3,4,0, // left
00041                             1,5,2,2,5,6  //right
00042                           };
00043 
00044 const ngl::Vec3 normals[] = {
00045                                 ngl::Vec3(0.0f,0.0f,-1.0f), //back
00046                                 ngl::Vec3(0.0f,0.0f,1.0f),  // front
00047                                 ngl::Vec3(0.0f,1.0f,0.0f),  // top
00048                                 ngl::Vec3(0.0f,-1.0f,0.0f), // bottom
00049                                 ngl::Vec3(-1.0f,0.0f,0.0f), // left
00050                                 ngl::Vec3(1.0f,0.0f,0.0f)  // right
00051                             };
00052 
00053 StatsVisualization::StatsVisualization()
00054 {
00055    m_importFlag = false;
00056    m_vao = 0;
00057    m_text = 0;
00058 }
00059 
00060 StatsVisualization::StatsVisualization(
00061                    QWidget *_parent,PlayerData *_playerA, PlayerData *_playerB
00062         ) : QGLWidget( new CreateCoreGLContext(QGLFormat::defaultFormat()), _parent ),
00063         m_playerA(_playerA),m_playerB(_playerB)
00064 {
00065 
00066 
00067   // set this widget to have the initial keyboard focus
00068   //setFocus();
00069   // re-size the widget to that of the parent (in this case the GLFrame passed in on construction)
00070   this->resize(_parent->size());
00071 
00072   m_importFlag = false;
00073   // Now set the initial StatsVisualization attributes to default values
00074   // Roate is false
00075   m_rotate=false;
00076   // mouse rotation values set to 0
00077   m_spinXFace=0;
00078   m_spinYFace=0;
00079   m_origX=0;
00080   m_origY=0;
00081 
00082  // m_depthObject = _inputDepthWindow;
00083 
00084   m_impactPtsFilled = false;
00085 
00086   // by default when process stats is clicked, the first stat displayed is the impact point
00087   // of both the players
00088 
00089   m_whichPlayer = BOTH;
00090   m_whichStat = IMPACT_POINTS_VIEW;
00091   m_whichQuad = ALL;
00092 
00093   m_width = m_height = m_midTopX = m_midTopY = m_midBottomX = m_midBottomY = m_midLeftX = 0;
00094   m_midLeftY= m_midRightX = m_midRightY = 0;
00095 
00096   m_percentageABL = m_percentageATL = m_percentageATR = m_percentageABR = -1.0;
00097   m_percentageBBL = m_percentageBTL = m_percentageBTR = m_percentageBBR = -1.0;
00098 
00099   m_playerAImpactData.clear();
00100   m_playerBImpactData.clear();
00101   m_quadSpecABL.clear();
00102   m_quadSpecATL.clear();
00103   m_quadSpecATR.clear();
00104   m_quadSpecABR.clear();
00105   m_quadSpecBBL.clear();
00106   m_quadSpecBTL.clear();
00107   m_quadSpecBTR.clear();
00108   m_quadSpecBBR.clear();
00109   m_dataVertsA.clear();
00110   m_dataVertsB.clear();
00111 
00112   m_playerAInterpPtsMappedToRallies.clear();
00113   m_playerBInterpPtsMappedToRallies.clear();
00114   m_playerATrajectoryFromFile.clear();
00115   m_playerBTrajectoryFromFile.clear();
00116 
00117   m_speedAData.clear();
00118   m_speedBData.clear();
00119   m_playerAImpactPtsAllRalliesIn3D.clear();
00120   m_playerBImpactPtsAllRalliesIn3D.clear();
00121   m_playerARPM.clear();
00122   m_playerBRPM.clear();
00123 
00124   m_vao = 0;
00125   m_text = 0;
00126 
00127   m_3dFlag = false;
00128   m_speedMapBuilt = false;
00129   m_rpmDataBuilt = false;
00130   m_quadMapBuilt = false;
00131   m_trajectoryBuilt = false;
00132   // this is the exacct distance in meters as measured by the kinect
00133   // to the playing tt table
00134   m_kinectToPlayAreaInMeters = 0.76;
00135   m_diameterOfBAllInMeters = 0.044;
00136   m_finalCourtWidthWorld = m_finalCourtDepthWorld = 0.0;
00137 
00138   m_lightPos.set(0,2,0);
00139 }
00140 
00141 StatsVisualization::StatsVisualization(
00142                    QWidget *_parent,bool _importFlag
00143         ) : QGLWidget( new CreateCoreGLContext(QGLFormat::defaultFormat()), _parent ),m_importFlag(_importFlag)
00144 
00145 {
00146 
00147   // set this widget to have the initial keyboard focus
00148   //setFocus();
00149   // re-size the widget to that of the parent (in this case the GLFrame passed in on construction)
00150   this->resize(_parent->size());
00151   // Now set the initial StatsVisualization attributes to default values
00152   // Roate is false
00153   m_rotate=false;
00154   // mouse rotation values set to 0
00155   m_spinXFace=0;
00156   m_spinYFace=0;
00157   m_origX=0;
00158   m_origY=0;
00159 
00160  // m_depthObject = _inputDepthWindow;
00161 
00162   m_impactPtsFilled = false;
00163 
00164   // by default when process stats is clicked, the first stat displayed is the impact point
00165   // of both the players
00166 
00167   m_whichPlayer = BOTH;
00168   m_whichStat = IMPACT_POINTS_VIEW;
00169   m_whichQuad = ALL;
00170   m_3dFlag = false;
00171 
00172   m_width = m_height = m_midTopX = m_midTopY = m_midBottomX = m_midBottomY = m_midLeftX = 0;
00173   m_midLeftY= m_midRightX = m_midRightY = 0;
00174 
00175   m_percentageABL = m_percentageATL = m_percentageATR = m_percentageABR = -1.0;
00176   m_percentageBBL = m_percentageBTL = m_percentageBTR = m_percentageBBR = -1.0;
00177 
00178   m_playerAImpactData.clear();
00179   m_playerBImpactData.clear();
00180   m_quadSpecABL.clear();
00181   m_quadSpecATL.clear();
00182   m_quadSpecATR.clear();
00183   m_quadSpecABR.clear();
00184   m_quadSpecBBL.clear();
00185   m_quadSpecBTL.clear();
00186   m_quadSpecBTR.clear();
00187   m_quadSpecBBR.clear();
00188   m_dataVertsA.clear();
00189   m_dataVertsB.clear();
00190   m_playerAInterpPtsMappedToRallies.clear();
00191   m_playerBInterpPtsMappedToRallies.clear();
00192   m_speedAData.clear();
00193   m_speedBData.clear();
00194   m_playerAImpactPtsAllRalliesIn3D.clear();
00195   m_playerBImpactPtsAllRalliesIn3D.clear();
00196   m_playerARPM.clear();
00197   m_playerBRPM.clear();
00198 
00199   m_vao = 0;
00200   m_text = 0;
00201 
00202   m_speedMapBuilt = false;
00203   m_rpmDataBuilt = false;
00204   m_quadMapBuilt = false;
00205   m_trajectoryBuilt = false;
00206   // this is the exacct distance in meters as measured by the kinect
00207   // to the playing tt table
00208   m_kinectToPlayAreaInMeters = 0.76;
00209   m_diameterOfBAllInMeters = 0.044;
00210   m_finalCourtWidthWorld = m_finalCourtDepthWorld = 0.0;
00211 
00212   m_lightPos.set(0,2,0);
00213 
00214   //m_text->setScreenSize(640,480);
00215 }
00216 
00217 StatsVisualization::~StatsVisualization()
00218 {
00219 //  ngl::NGLInit *Init = ngl::NGLInit::instance();
00220 //  std::cout<<"Shutting down NGL, removing VAO's and Shaders\n";
00221 //  Init->NGLQuit();
00222 
00223     if(m_2DScreen)
00224     {
00225         delete m_2DScreen;
00226     }
00227 
00228     if(m_vao)
00229     {
00230         m_vao->removeVOA();
00231         //delete m_vao;
00232 
00233     }
00234 
00235     if(m_text)
00236     {
00237         delete m_text;
00238         m_text = 0;
00239     }
00240 //    if(m_text1)
00241 //    {
00242 //        delete m_text1;
00243 //    }
00244 }
00245 
00246 
00247 // This virtual function is called once before the first call to paintGL() or resizeGL(),
00248 //and then once whenever the widget has been assigned a new QGLContext.
00249 // This function should set up any required OpenGL context rendering flags, defining display lists, etc.
00250 
00251 //----------------------------------------------------------------------------------------------------------------------
00252 void StatsVisualization::initializeGL()
00253 {
00254 
00255    glClearColor(0.4f, 0.4f, 0.4f, 1.0f);         // Grey Background
00256    // enable depth testing for drawing
00257    glEnable(GL_DEPTH_TEST);
00258 
00259    glEnable(GL_MULTISAMPLE);
00260 
00261    // Now we will create a basic Camera from the graphics library
00262    // This is a static camera so it only needs to be set once
00263    // First create Values for the camera position
00264 
00265    ngl::Vec3 from(0,0.2,50);
00266    ngl::Vec3 to(0,0,0);
00267    ngl::Vec3 up(0,1,0);
00268 
00269    m_cam= new ngl::Camera(from,to,up,ngl::PERSPECTIVE);
00270    // set the shape using FOV 45 Aspect Ratio based on Width and Height
00271    // The final two are near and far clipping planes of 0.5 and 10
00272    m_cam->setShape(45,(float)640/480,0.001,150,ngl::PERSPECTIVE);
00273 
00274 
00275 
00276 
00277 
00278    ngl::NGLInit *Init = ngl::NGLInit::instance();
00279    #ifdef WIN32
00280     glewInit();
00281    #endif
00282    Init->initGlew();
00283 
00284    // we create 2 shaders, one for 3D rendering, another one for 2D quad pasting
00285 
00286    //PER FRAGMENT ASD SHADER FOR 3D RENDER
00287 
00288    // now to load the shader and set the values
00289    // grab an instance of shader manager
00290 
00291    ngl::ShaderLib *shader = ngl::ShaderLib::instance();
00292    //shader = ngl::ShaderLib::instance();
00293    // we are creating a shader called PerFragADS
00294    shader->createShaderProgram("PerFragADS");
00295    // now we are going to create empty shaders for Frag and Vert
00296    shader->attachShader("PerFragADSVertex",ngl::VERTEX);
00297    shader->attachShader("PerFragADSFragment",ngl::FRAGMENT);
00298    // attach the source
00299    shader->loadShaderSource("PerFragADSVertex","shaders/PerFragASDVert.glsl");
00300    shader->loadShaderSource("PerFragADSFragment","shaders/PerFragASDFrag.glsl");
00301    // compile the shaders
00302    shader->compileShader("PerFragADSVertex");
00303    shader->compileShader("PerFragADSFragment");
00304    // add them to the program
00305    shader->attachShaderToProgram("PerFragADS","PerFragADSVertex");
00306    shader->attachShaderToProgram("PerFragADS","PerFragADSFragment");
00307 
00308    // now we have associated this data we can link the shader
00309    shader->linkProgramObject("PerFragADS");
00310    // and make it active ready to load values
00311    (*shader)["PerFragADS"]->use();
00312    // now we need to set the material and light values
00313    /*
00314     *struct MaterialInfo
00315     {
00316          // Ambient reflectivity
00317          vec3 Ka;
00318          // Diffuse reflectivity
00319          vec3 Kd;
00320          // Specular reflectivity
00321          vec3 Ks;
00322          // Specular shininess factor
00323          float shininess;
00324    };*/
00325    shader->setShaderParam3f("material.Ka",0.1,0.1,0.1);
00326    // green diffuse
00327    shader->setShaderParam3f("material.Kd",0.0,0.8,0.0);
00328    // white spec
00329    shader->setShaderParam3f("material.Ks",1.0,1.0,1.0);
00330    shader->setShaderParam1f("material.shininess",100);
00331    // now for  the lights values (all set to white)
00332    /*struct LightInfo
00333    {
00334    // Light position in eye coords.
00335    vec4 position;
00336    // Ambient light intensity
00337    vec3 La;
00338    // Diffuse light intensity
00339    vec3 Ld;
00340    // Specular light intensity
00341    vec3 Ls;
00342    };*/
00343    shader->setUniform("light.position",m_lightPos);
00344    shader->setShaderParam3f("light.La",0.1,0.1,0.1);
00345    shader->setShaderParam3f("light.Ld",1.0,1.0,1.0);
00346    shader->setShaderParam3f("light.Ls",0.9,0.9,0.9);
00347 
00348 
00349 
00350    // TEXTURE SHADER INSTANCE FOR 2D
00351 
00352      // now shader for Texture Pasting used for 2D viz.
00353      shader = ngl::ShaderLib::instance();
00354      shader->createShaderProgram("TextureShaderStats");
00355 
00356      shader->attachShader("TextureVertex",ngl::VERTEX);
00357      shader->attachShader("TextureFragment",ngl::FRAGMENT);
00358      shader->loadShaderSource("TextureVertex","shaders/TextureVert.glsl");
00359      shader->loadShaderSource("TextureFragment","shaders/TextureFrag.glsl");
00360 
00361      shader->compileShader("TextureVertex");
00362      shader->compileShader("TextureFragment");
00363      shader->attachShaderToProgram("TextureShaderStats","TextureVertex");
00364      shader->attachShaderToProgram("TextureShaderStats","TextureFragment");
00365 
00366      shader->linkProgramObject("TextureShaderStats");
00367      (*shader)["TextureShaderStats"]->use();
00368      shader->setShaderParam1i("tex",0);
00369 
00370      m_2DScreen = new ScreenQuad(640,480,"TextureShaderStats");
00371 
00372      ngl::Texture crowdTexture("textures/crowd.png");
00373      ngl::Texture tableTexture("textures/blue_ultramarine.png");
00374 
00375      ngl::Texture speedLegendTexture("textures/speedlegendbold.png");
00376      ngl::Texture rpmLegendTexture("textures/rpslegend.png");
00377      ngl::Texture trajectoryLegendTexture("textures/traj_map.png");
00378      ngl::Texture htMapLegendTexture("textures/height_map.png");
00379      ngl::Texture htGridMapLegendTexture("textures/grid.png");
00380 
00381      m_crowdTextureName = crowdTexture.setTextureGL();
00382      m_tableTextureName = tableTexture.setTextureGL();
00383 
00384      m_speedLegend = speedLegendTexture.setTextureGL();
00385      m_rpmLegend = rpmLegendTexture.setTextureGL();
00386      m_trajectoryLegend = trajectoryLegendTexture.setTextureGL();
00387      m_heightMapLegend = htMapLegendTexture.setTextureGL();
00388      m_gridXYHtMap = htGridMapLegendTexture.setTextureGL();
00389 
00390      //frame rate GUNDU
00391      m_text=new ngl::Text(QFont("Arial",25));
00392      m_text->setColour(1,1,1);
00393      //m_text->setScreenSize(640,480);
00394 
00395      //     m_text1=new ngl::Text(QFont("Arial",25));
00396      //     m_text1->setColour(1,1,1);
00397      //     m_text1->setScreenSize(640,480);
00398 
00399      m_updateTimer = startTimer(3);
00400 
00401 }
00402 
00403 //----------------------------------------------------------------------------------------------------------------------
00404 //This virtual function is called whenever the widget has been resized.
00405 // The new size is passed in width and height.
00406 void StatsVisualization::resizeGL(
00407                         int _w,
00408                         int _h
00409                        )
00410 {
00411     //glViewport(0,0,_w,_h);
00412 
00413     m_legendWidth = _w * (200/640.0);
00414     m_legendHeight = _h * (200/480.0);
00415     //m_cam->setShape(45,(float)_w/_h,0.001,150,ngl::PERSPECTIVE);
00416 }
00417 
00418 // change this name to ads shader
00419 void StatsVisualization::loadMatricesToADSShader()
00420 {
00421   ngl::ShaderLib *shader=ngl::ShaderLib::instance();
00422   //(*shader)["PerFragADS"]->use();
00423 
00424   ngl::Mat4 MV;
00425   ngl::Mat4 MVP;
00426   ngl::Mat3 normalMatrix;
00427   ngl::Mat4 M;
00428   M=m_transformStack.getCurrentTransform().getMatrix();
00429   MV= m_transformStack.getCurrAndGlobal().getMatrix()*m_cam->getViewMatrix();
00430   MVP=MV*m_cam->getProjectionMatrix() ;
00431   normalMatrix=MV;
00432   normalMatrix.inverse();
00433   shader->setUniform("MVP",MVP);
00434   shader->setUniform("MV",MV);
00435   shader->setUniform("normalMatrix",normalMatrix);
00436   shader->setUniform("light.position",m_lightPos);
00437 
00438 }
00439 
00440 void StatsVisualization::loadMatricesToTextureShader()
00441 {
00442   ngl::ShaderLib *shader=ngl::ShaderLib::instance();
00443   //(*shader)["TextureShaderStats"]->use();
00444 
00445   ngl::Mat4 MVP=m_transformStack.getCurrAndGlobal().getMatrix()*m_cam->getVPMatrix();
00446 
00447   shader->setShaderParamFromMat4("MVP",MVP);
00448   shader->setUniform("textureFlag",true);
00449 
00450 
00451 
00452 }
00453 
00454 //----------------------------------------------------------------------------------------------------------------------
00455 //This virtual function is called whenever the widget needs to be painted.
00456 // this is our main drawing routine
00457 void StatsVisualization::paintGL()
00458 {
00459 
00460 
00461   //UPDATETIMER does not call PAINTGL
00462   //JUST CALLS ONCE finally WHEN FIELD VALUES ARE COMPUTED and kills the timer
00463 
00464   // clear the screen and depth buffer
00465   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00466 
00467   //glViewport(0,0,640,480);
00468 
00469   // only when 3D data is requested..
00470   if(m_3dFlag)
00471   {
00472     // Rotation based on the mouse position for our global transform
00473     ngl::Transformation trans;
00474     ngl::Mat4 rotX;
00475     ngl::Mat4 rotY;
00476     // create the rotation matrices
00477     rotX.rotateX(m_spinXFace);
00478     rotY.rotateY(m_spinYFace);
00479     // multiply the rotations
00480     ngl::Mat4 final=rotY*rotX;
00481     // add the translations
00482     final.m_m[3][0] = m_modelPos.m_x;
00483     final.m_m[3][1] = m_modelPos.m_y;
00484     final.m_m[3][2] = m_modelPos.m_z;
00485     // set this in the TX stack
00486     trans.setMatrix(final);
00487     m_transformStack.setGlobal(trans);
00488     //loadMatricesToADSShader();
00489 
00490     // if we were previously seeing a 2D stats
00491     // window it would have been restricted to 640*480
00492     // so we need to resize our opengl window
00493     // to render to the current window size for 3D stats
00494     glViewport(0,0,this->size().width(),this->size().height());
00495     // this resize is called to resize the ratio of the legend window
00496     // which will be displayed in 3d stats
00497     resizeGL(this->size().width(),this->size().height());
00498 
00499   }
00500   else
00501   {
00502     // for 2D stats the gl window can only be 640*480
00503     glViewport(0,0,640,480);
00504     m_text->setScreenSize(640,480);
00505     resizeGL(640,480);
00506 
00507   }
00508 
00509 
00510   drawEntireScene();
00511 
00512 }
00513 
00514 void StatsVisualization::drawEntireScene()
00515 {
00516 
00517     cv::Mat drawing = cv::Mat::zeros(480,640,CV_8UC3 );
00518 
00519     if((m_width != 0) && (m_height != 0))
00520     {
00521 
00522         cv::rectangle(drawing,m_fieldOfPlay,cv::Scalar(92,163,69),-1);
00523 
00524         cv::line(drawing,cv::Point(m_midTopX,m_midTopY),cv::Point(m_midBottomX,m_midBottomY),cv::Scalar(255,0,0),1);
00525 
00526         cv::line(drawing,cv::Point(m_midLeftX,m_midLeftY),cv::Point(m_midRightX,m_midRightY),cv::Scalar(233,235,226),3);
00527 
00528 
00529         // Note for All following Switch cases and Statistics:
00530 
00531         // if data has been processed by the processing utility
00532         // then call a local function which will call playerallrallies function
00533         // store in player specific array and draw it if not empty
00534 
00535         // if impact pts have already been filled, then this will avoid
00536         // further calling of functions..saves time and calculations
00537         // same logic applies for all statistics
00538 
00539         switch (m_whichStat)
00540         {
00541           case IMPACT_POINTS_VIEW:
00542           {
00543             //m_3dFlag = 0;
00544 
00545             if(!(m_impactPtsFilled))
00546             {
00547               if(m_playerA->checkDataProcessed() && m_playerB->checkDataProcessed())
00548               {
00549                   fillAllImpactPointsBothPlayers();
00550               }
00551             }
00552 
00553             switch(m_whichPlayer)
00554             {
00555               case PLAYERA:
00556               {
00557                 if(m_playerAImpactData.size() != 0)
00558                 {
00559                     for(int i=0;i<m_playerAImpactData.size();i++)
00560                     {
00561                         cv::circle(drawing,m_playerAImpactData[i],8,cv::Scalar(255,255,255),-1);
00562                     }
00563                 }
00564                 break;
00565               }
00566 
00567               case PLAYERB:
00568               {
00569                 if(m_playerBImpactData.size() != 0)
00570                 {
00571                     for(int i=0;i<m_playerBImpactData.size();i++)
00572                     {
00573                         cv::circle(drawing,m_playerBImpactData[i],8,cv::Scalar(255,0,0),-1);
00574                     }
00575                 }
00576                 break;
00577               }
00578               case BOTH:
00579               {
00580                 if(m_playerAImpactData.size() != 0)
00581                 {
00582                     for(int i=0;i<m_playerAImpactData.size();i++)
00583                     {
00584                         cv::circle(drawing,m_playerAImpactData[i],8,cv::Scalar(255,255,255),-1);
00585                     }
00586                 }
00587 
00588                 if(m_playerBImpactData.size() != 0)
00589                 {
00590                     for(int i=0;i<m_playerBImpactData.size();i++)
00591                     {
00592                         cv::circle(drawing,m_playerBImpactData[i],8,cv::Scalar(255,0,0),-1);
00593                     }
00594                 }
00595 
00596                 break;
00597               }
00598 
00599             }
00600             break;
00601           }
00602 
00603           case IMPACT_PERCENTAGE_DISTRIBUTION_VIEW:
00604           {
00605             // pecentage distrbn
00606             // to stop recalculating in every paintgl, we check against -1
00607 
00608             // THESE SWITCH CASES MIGHT ONLY BE USEFUL WHEN IT IS RENDERED APO-APO
00609             //  LIKE THE IMPACT DRAWING BUFFER...WE NEED TO FIND A WAY FOR THIS
00610 
00611             //threeDFlag = 0;
00612 
00613             if(!(m_impactPtsFilled))
00614             {
00615               if(m_playerA->checkDataProcessed() && m_playerB->checkDataProcessed())
00616               {
00617                   fillAllImpactPointsBothPlayers();
00618               }
00619             }
00620 
00621             switch(m_whichPlayer)
00622             {
00623               case PLAYERA:
00624               {
00625 
00626                 if(!(m_quadMapBuilt) && (m_impactPtsFilled == true))
00627                 {
00628                     buildQuadSpecificData();
00629                 }
00630 
00631                 switch(m_whichQuad)
00632                 {
00633                   case BOTTOM_LEFT:
00634                   {
00635 
00636                     if(m_quadSpecABL.size() != 0)
00637                     {
00638                         for(int i=0;i<m_quadSpecABL.size();i++)
00639                         {
00640                             cv::circle(drawing,m_quadSpecABL[i],8,cv::Scalar(255,255,255),-1);
00641                         }
00642 
00643 
00644                     }
00645                     break;
00646                   }
00647                   case TOP_LEFT:
00648                   {
00649 
00650                     if(m_quadSpecATL.size() != 0)
00651                     {
00652                         for(int i=0;i<m_quadSpecATL.size();i++)
00653                         {
00654                             cv::circle(drawing,m_quadSpecATL[i],8,cv::Scalar(255,255,255),-1);
00655                         }
00656 
00657                     }
00658 
00659                     break;
00660                   }
00661                   case TOP_RIGHT:
00662                   {
00663 
00664 
00665                     if(m_quadSpecATR.size() != 0)
00666                     {
00667                         for(int i=0;i<m_quadSpecATR.size();i++)
00668                         {
00669                             cv::circle(drawing,m_quadSpecATR[i],8,cv::Scalar(255,255,255),-1);
00670                         }
00671 
00672                     }
00673 
00674                     break;
00675                   }
00676                   case BOTTOM_RIGHT:
00677                   {
00678 
00679                     if(m_quadSpecABR.size() != 0)
00680                     {
00681                         for(int i=0;i<m_quadSpecABR.size();i++)
00682                         {
00683                             cv::circle(drawing,m_quadSpecABR[i],8,cv::Scalar(255,255,255),-1);
00684                         }
00685 
00686                     }
00687 
00688                     break;
00689                   }
00690                 case ALL: // draw A pts
00691                   {
00692                     if(m_playerAImpactData.size() != 0)
00693                     {
00694                         for(int i=0;i<m_playerAImpactData.size();i++)
00695                         {
00696                             cv::circle(drawing,m_playerAImpactData[i],8,cv::Scalar(255,255,255),-1);
00697                         }
00698 
00699                     }
00700                     break;
00701                   }
00702                 }
00703 
00704                 break;
00705               }
00706 
00707               case PLAYERB:
00708               {
00709                 if(!(m_quadMapBuilt) && (m_impactPtsFilled == true))
00710                 {
00711                     buildQuadSpecificData();
00712                 }
00713 
00714                 switch(m_whichQuad)
00715                 {
00716                   case BOTTOM_LEFT:
00717                   {
00718 
00719                     if(m_quadSpecBBL.size() != 0)
00720                     {
00721                         for(int i=0;i<m_quadSpecBBL.size();i++)
00722                         {
00723                             cv::circle(drawing,m_quadSpecBBL[i],8,cv::Scalar(255,0,0),-1);
00724                         }
00725                     }
00726 
00727                     break;
00728                   }
00729                   case TOP_LEFT:
00730                   {
00731 
00732                     if(m_quadSpecBTL.size() != 0)
00733                     {
00734                         for(int i=0;i<m_quadSpecBTL.size();i++)
00735                         {
00736                             cv::circle(drawing,m_quadSpecBTL[i],8,cv::Scalar(255,0,0),-1);
00737                         }
00738                     }
00739 
00740                     break;
00741                   }
00742                   case TOP_RIGHT:
00743                   {
00744 
00745                     if(m_quadSpecBTR.size() != 0)
00746                     {
00747                         for(int i=0;i<m_quadSpecBTR.size();i++)
00748                         {
00749                             cv::circle(drawing,m_quadSpecBTR[i],8,cv::Scalar(255,0,0),-1);
00750                         }
00751                     }
00752 
00753                     break;
00754                   }
00755                   case BOTTOM_RIGHT:
00756                   {
00757 
00758                     if(m_quadSpecBBR.size() != 0)
00759                     {
00760                         for(int i=0;i<m_quadSpecBBR.size();i++)
00761                         {
00762                             cv::circle(drawing,m_quadSpecBBR[i],8,cv::Scalar(255,0,0),-1);
00763                         }
00764                     }
00765 
00766                     break;
00767                   }
00768 
00769                 case ALL: //tbd // draw B pts
00770                   {
00771                     if(m_playerBImpactData.size() != 0)
00772                     {
00773                         for(int i=0;i<m_playerBImpactData.size();i++)
00774                         {
00775                             cv::circle(drawing,m_playerBImpactData[i],8,cv::Scalar(255,0,0),-1);
00776                         }
00777                     }
00778                     break;
00779                   }
00780                 }
00781 
00782                 break;
00783               }
00784               case BOTH:
00785               {
00786                 if(!(m_quadMapBuilt) && (m_impactPtsFilled == true))
00787                 {
00788                     buildQuadSpecificData();
00789                 }
00790 
00791                 switch(m_whichQuad)
00792                 {
00793                   case BOTTOM_LEFT:
00794                   {
00795 
00796                     if(m_quadSpecABL.size() != 0)
00797                     {
00798                         for(int i=0;i<m_quadSpecABL.size();i++)
00799                         {
00800                             cv::circle(drawing,m_quadSpecABL[i],8,cv::Scalar(255,255,255),-1);
00801                         }
00802                     }
00803 
00804                     if(m_quadSpecBBL.size() != 0)
00805                     {
00806                         for(int i=0;i<m_quadSpecBBL.size();i++)
00807                         {
00808                             cv::circle(drawing,m_quadSpecBBL[i],8,cv::Scalar(255,0,0),-1);
00809                         }
00810                     }
00811                     break;
00812                   }
00813                   case TOP_LEFT:
00814                   {
00815 
00816                     if(m_quadSpecATL.size() != 0)
00817                     {
00818                         for(int i=0;i<m_quadSpecATL.size();i++)
00819                         {
00820                             cv::circle(drawing,m_quadSpecATL[i],8,cv::Scalar(255,255,255),-1);
00821                         }
00822                     }
00823 
00824                     if(m_quadSpecBTL.size() != 0)
00825                     {
00826                         for(int i=0;i<m_quadSpecBTL.size();i++)
00827                         {
00828                             cv::circle(drawing,m_quadSpecBTL[i],8,cv::Scalar(255,0,0),-1);
00829                         }
00830                     }
00831 
00832                     break;
00833                   }
00834                   case TOP_RIGHT:
00835                   {
00836 
00837                     if(m_quadSpecATR.size() != 0)
00838                     {
00839                         for(int i=0;i<m_quadSpecATR.size();i++)
00840                         {
00841                             cv::circle(drawing,m_quadSpecATR[i],8,cv::Scalar(255,255,255),-1);
00842                         }
00843                     }
00844 
00845                     if(m_quadSpecBTR.size() != 0)
00846                     {
00847                         for(int i=0;i<m_quadSpecBTR.size();i++)
00848                         {
00849                             cv::circle(drawing,m_quadSpecBTR[i],8,cv::Scalar(255,0,0),-1);
00850                         }
00851                     }
00852 
00853                     break;
00854                   }
00855                   case BOTTOM_RIGHT:
00856                   {
00857 
00858                     if(m_quadSpecABR.size() != 0)
00859                     {
00860                         for(int i=0;i<m_quadSpecABR.size();i++)
00861                         {
00862                             cv::circle(drawing,m_quadSpecABR[i],8,cv::Scalar(255,255,255),-1);
00863                         }
00864                     }
00865 
00866                     if(m_quadSpecBBR.size() != 0)
00867                     {
00868                         for(int i=0;i<m_quadSpecBBR.size();i++)
00869                         {
00870                             cv::circle(drawing,m_quadSpecBBR[i],8,cv::Scalar(255,0,0),-1);
00871                         }
00872                     }
00873 
00874                     break;
00875                   }
00876 
00877                   case ALL: // TBD
00878                   {
00879                     // if ALL quads and BOTH players selected in % view, its the same as full impact points
00880                     if(m_playerAImpactData.size() != 0)
00881                     {
00882                         for(int i=0;i<m_playerAImpactData.size();i++)
00883                         {
00884                             cv::circle(drawing,m_playerAImpactData[i],8,cv::Scalar(255,255,255),-1);
00885                         }
00886                     }
00887 
00888                     if(m_playerBImpactData.size() != 0)
00889                     {
00890                         for(int i=0;i<m_playerBImpactData.size();i++)
00891                         {
00892                             cv::circle(drawing,m_playerBImpactData[i],8,cv::Scalar(255,0,0),-1);
00893                         }
00894                     }
00895                     break;
00896                   }
00897                 }
00898                 break;
00899               }
00900 
00901             }
00902             break;
00903           }
00904           case IMPACT_HEIGHT_MAP_VIEW:
00905           {
00906 
00907 
00908             //hegith map
00909             m_cam->setEye(ngl::Vec4(0,3.0,55,1));
00910 
00911             if(!(m_impactPtsFilled))
00912             {
00913               if(m_playerA->checkDataProcessed() && m_playerB->checkDataProcessed())
00914               {
00915                   fillAllImpactPointsBothPlayers();
00916               }
00917             }
00918 
00919             if(!(m_vao) && (m_impactPtsFilled == true))
00920             {
00921                 buildPointGraphBars();
00922             }
00923 
00924 
00925             ngl::ShaderLib *shader=ngl::ShaderLib::instance();
00926             switch(m_whichPlayer)
00927             {
00928 
00929               case PLAYERA:
00930               {
00931                   // in this case we are going to set our data as the vertices above
00932 
00933                   if(m_vao)
00934                   {
00935 
00936                       drawCrowd("heightMapPlane");
00937                       drawTable("heightMapPlane");
00938 
00939                       // draw the bounding graph planes
00940                       drawContainingGridScaleXY();
00941 
00942                       (*shader)["PerFragADS"]->use();
00943                       shader->setShaderParam3f("material.Kd",0.5,0.5,0.5);
00944 
00945                       m_transformStack.pushTransform();
00946                       {
00947                         // next we bind it so it's active for setting data
00948                         m_vao->bind();
00949                         m_vao->setData(m_dataVertsA.size()*sizeof(VertData),m_dataVertsA[0].nx);
00950 
00951                         //sizeof(vertData) and the offset into the data structure for the first x component is 3 (nx,ny,nz)..x
00952                         m_vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(VertData),3);
00953                         // uv same as above but starts at 0 and is attrib 1 and only u,v so 2
00954                         // normal same as vertex only starts at position 0
00955                         m_vao->setVertexAttributePointer(2,3,GL_FLOAT,sizeof(VertData),0);
00956                         m_vao->setNumIndices(m_dataVertsA.size());
00957 
00958                         loadMatricesToADSShader();
00959 
00960                         m_vao->draw();
00961                         // finally we have finished for now so time to unbind the VAO
00962                         m_vao->unbind();
00963                        }
00964                       m_transformStack.popTransform();
00965                    }
00966                   break;
00967                 }
00968 
00969               case PLAYERB:
00970               {
00971                       // in this case we are going to set our data as the vertices above
00972                   if(m_vao)
00973                   {
00974                       drawCrowd("heightMapPlane");
00975                       drawTable("heightMapPlane");
00976                       // draw the bounding graph planes
00977                       drawContainingGridScaleXY();
00978 
00979                       (*shader)["PerFragADS"]->use();
00980                       shader->setShaderParam3f("material.Kd",0.8,0.0,0.0);
00981 
00982                       m_transformStack.pushTransform();
00983                       {
00984                         // next we bind it so it's active for setting data
00985                         m_vao->bind();
00986 
00987                         m_vao->setData(m_dataVertsB.size()*sizeof(VertData),m_dataVertsB[0].nx);
00988                         m_vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(VertData),3);
00989                         // normal same as vertex only starts at position 0
00990                         m_vao->setVertexAttributePointer(2,3,GL_FLOAT,sizeof(VertData),0);
00991                         m_vao->setNumIndices(m_dataVertsB.size());
00992                         loadMatricesToADSShader();
00993                         m_vao->draw();
00994                         // finally we have finished for now so time to unbind the VAO
00995                         m_vao->unbind();
00996                       }
00997                       m_transformStack.popTransform();
00998                    }
00999 
01000                     break;
01001                 }
01002                 case BOTH:
01003                 {
01004                     // cannot view 3d stats for both players at a time
01005                     break;
01006                 }
01007               }
01008               break;
01009           }
01010           case TRAJECTORY_VIEW:
01011           {
01012 
01013             m_cam->setEye(ngl::Vec4(0,0.2,1,1));
01014 
01015 
01016             if(!(m_impactPtsFilled))
01017             {
01018               if(m_playerA->checkDataProcessed() && m_playerB->checkDataProcessed())
01019               {
01020                   fillAllImpactPointsBothPlayers();
01021               }
01022             }
01023 
01024             if(!(m_trajectoryBuilt) && (m_impactPtsFilled == true))
01025             {
01026                 buildTrajectory();
01027             }
01028 
01029             // draw field in WORLD coordinates
01030             // as the trajectory view is in
01031             // METRES SCALE
01032             // SHOW THE SCALE SOMEWHERE---font rendering
01033             ngl::ShaderLib *shader=ngl::ShaderLib::instance();
01034             ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01035 
01036             if(m_trajectoryBuilt)
01037             {
01038                 drawCrowd("trajectoryPlane");
01039                 drawTable("trajectoryPlane");
01040                 drawContainingGridScaleXY();
01041             }
01042 
01043             switch(m_whichPlayer)
01044             {
01045               case PLAYERA:
01046               {
01047 
01048                 (*shader)["PerFragADS"]->use();
01049                 shader->setShaderParam3f("material.Kd",0.8,0.8,0.8);
01050 
01051                 if(!(m_importFlag)) // live data
01052                 {
01053                     for(int i=0;i<m_playerAInterpPtsMappedToRallies.size();i++)
01054                     {
01055                         for(int j=0;j<m_playerAInterpPtsMappedToRallies[i].size();j++)
01056                         {
01057                             if(m_playerAInterpPtsMappedToRallies[i][j].y < 0.0)
01058                             {
01059                                 continue;
01060                             }
01061                             m_transformStack.pushTransform();
01062                             {
01063                                 m_transformStack.setPosition(m_playerAInterpPtsMappedToRallies[i][j].x,
01064                                                              m_playerAInterpPtsMappedToRallies[i][j].y,
01065                                                              m_playerAInterpPtsMappedToRallies[i][j].z);
01066 
01067 
01068 
01069                                 loadMatricesToADSShader();
01070                                 prim->draw("trajectorySphere");
01071                             }
01072                             m_transformStack.popTransform();
01073                         }
01074 
01075 
01076                     }
01077                 }
01078                 else // imported data
01079                 {
01080                     for(int j=0;j<m_playerATrajectoryFromFile.size();j = j+3)
01081                     {
01082                         if(m_playerATrajectoryFromFile[j + 1] < 0.0)
01083                         {
01084                             continue;
01085                         }
01086                         m_transformStack.pushTransform();
01087                         {
01088                             m_transformStack.setPosition(m_playerATrajectoryFromFile[j],
01089                                                          m_playerATrajectoryFromFile[j+1],
01090                                                          m_playerATrajectoryFromFile[j+2]);
01091 
01092 
01093                             loadMatricesToADSShader();
01094 
01095                             prim->draw("trajectorySphere");
01096                         }
01097                         m_transformStack.popTransform();
01098                     }
01099 
01100 
01101                 }
01102                   break;
01103               }
01104               case PLAYERB:
01105               {
01106 
01107                 (*shader)["PerFragADS"]->use();
01108                 shader->setShaderParam3f("material.Kd",0.8,0.0,0.0);
01109 
01110                 if(!(m_importFlag)) // live data
01111                 {
01112                     // render the vao1 for playerb data
01113                     for(int i=0;i<m_playerBInterpPtsMappedToRallies.size();i++)
01114                     {
01115 
01116                         for(int j=0;j<m_playerBInterpPtsMappedToRallies[i].size();j++)
01117                         {
01118                             // continue if the depth data is -1
01119                             // as that represents no impact point
01120                             // so move to next rally
01121                             if(m_playerBInterpPtsMappedToRallies[i][j].y < 0.0)
01122                             {
01123                                 continue;
01124                             }
01125                             m_transformStack.pushTransform();
01126                             {
01127                                 m_transformStack.setPosition(m_playerBInterpPtsMappedToRallies[i][j].x,
01128                                                              m_playerBInterpPtsMappedToRallies[i][j].y,
01129                                                              m_playerBInterpPtsMappedToRallies[i][j].z);
01130 
01131 
01132                                 loadMatricesToADSShader();
01133 
01134                                 prim->draw("trajectorySphere");
01135                             }
01136                             m_transformStack.popTransform();
01137                         }
01138 
01139                     }
01140 
01141 
01142                 }
01143                 else // imported data
01144                 {
01145                    for(int j=0;j<m_playerBTrajectoryFromFile.size();j = j+3)
01146                    {
01147                        // continue if the depth data is -1
01148                        // as that represents no impact point
01149                        // so move to next rally
01150                        if(m_playerBTrajectoryFromFile[j + 1] < 0.0)
01151                        {
01152                            continue;
01153                        }
01154                        m_transformStack.pushTransform();
01155                        {
01156                            m_transformStack.setPosition(m_playerBTrajectoryFromFile[j],
01157                                                         m_playerBTrajectoryFromFile[j+1],
01158                                                         m_playerBTrajectoryFromFile[j+2]);
01159 
01160 
01161                            loadMatricesToADSShader();
01162 
01163                            prim->draw("trajectorySphere");
01164                        }
01165                        m_transformStack.popTransform();
01166                    }
01167 
01168                 }
01169                 break;
01170               }
01171 
01172               case BOTH:
01173               {
01174                 // cannot view 3d stats for both players at a time
01175                 break;
01176               }
01177             }
01178               //3d trajectory
01179               break;
01180           }
01181           case VELOCITY_VIEW:
01182           {
01183             //velocity graphics view
01184             m_cam->setEye(ngl::Vec4(0,3.0,5,1));
01185 
01186 
01187             if(!(m_impactPtsFilled))
01188             {
01189               if(m_playerA->checkDataProcessed() && m_playerB->checkDataProcessed())
01190               {
01191                   fillAllImpactPointsBothPlayers();
01192               }
01193             }
01194 
01195             if(!(m_speedMapBuilt) && (m_impactPtsFilled == true))
01196             {
01197                 buildSpeedMap();
01198             }
01199 
01200               //ngl::ShaderLib *shader=ngl::ShaderLib::instance();
01201               ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01202 
01203             if(m_speedMapBuilt)
01204             {
01205                 drawCrowd("speedPlane");
01206                 drawTable("speedPlane");
01207             }
01208 
01209             switch(m_whichPlayer)
01210             {
01211               case PLAYERA:
01212               {
01213                 if(m_speedAData.size() != 0)
01214                 {
01215                     for(int i=0;i<m_playerAImpactPtsAllRalliesIn3D.size();i++)
01216                     {
01217                         // put your colour condition as m_speedAData[i] is within a range
01218                         // set the shader to different colors
01219                         m_transformStack.pushTransform();
01220                         {
01221                             m_transformStack.setPosition(m_playerAImpactPtsAllRalliesIn3D[i].x,
01222                                                          m_playerAImpactPtsAllRalliesIn3D[i].y,
01223                                                          m_playerAImpactPtsAllRalliesIn3D[i].z);
01224 
01225                              setColorBasedOnSpeedRange(m_speedAData[i]);
01226                             //(*shader)["PerFragADS"]->use();
01227                              loadMatricesToADSShader();
01228 
01229                             prim->draw("sphere");
01230                         }
01231                         m_transformStack.popTransform();
01232 
01233                         //std::cout<<"Speed data A:"<<m_speedAData[i]<<"\n";
01234                     }
01235                 }
01236                   break;
01237               }
01238               case PLAYERB:
01239               {
01240                 if(m_speedBData.size() != 0)
01241                 {
01242                     for(int i=0;i<m_playerBImpactPtsAllRalliesIn3D.size();i++)
01243                     {
01244                            // put your colour condition as m_speedAData[i] is within a range
01245                         // set the shader to different colors
01246                         m_transformStack.pushTransform();
01247                         {
01248                             m_transformStack.setPosition(m_playerBImpactPtsAllRalliesIn3D[i].x,
01249                                                          m_playerBImpactPtsAllRalliesIn3D[i].y,
01250                                                          m_playerBImpactPtsAllRalliesIn3D[i].z);
01251 
01252                             setColorBasedOnSpeedRange(m_speedBData[i]);
01253                             loadMatricesToADSShader();
01254                             //(*shader)["PerFragADS"]->use();
01255 
01256                             prim->draw("sphere");
01257                         }
01258                         m_transformStack.popTransform();
01259 
01260                         //std::cout<<"Speed data B:"<<m_speedBData[i]<<"\n";
01261                     }
01262                 }
01263                 break;
01264               }
01265               case BOTH:
01266               {
01267                 // not allowed, just a placeholder
01268                 break;
01269               }
01270             }
01271               break;
01272           }
01273           case RPM_VIEW:
01274           {
01275             //rpm graphic
01276             m_cam->setEye(ngl::Vec4(0,3.0,5,1));
01277 
01278 
01279             if(!(m_impactPtsFilled))
01280             {
01281               if(m_playerA->checkDataProcessed() && m_playerB->checkDataProcessed())
01282               {
01283                   fillAllImpactPointsBothPlayers();
01284               }
01285             }
01286 
01287             if(!(m_rpmDataBuilt) && (m_impactPtsFilled == true))
01288             {
01289                 buildRPMData();
01290             }
01291 
01292             //ngl::ShaderLib *shader=ngl::ShaderLib::instance();
01293             ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01294 
01295             if(m_rpmDataBuilt)
01296             {
01297               drawCrowd("rpmPlane");
01298               drawTable("rpmPlane");
01299             }
01300 
01301             switch(m_whichPlayer)
01302             {
01303               case PLAYERA:
01304               {
01305                 if(m_playerARPM.size() != 0)
01306                 {
01307                     for(int i=0;i<m_playerAImpactPtsAllRalliesIn3D.size();i++)
01308                     {
01309                         m_transformStack.pushTransform();
01310                         {
01311                             m_transformStack.setPosition(m_playerAImpactPtsAllRalliesIn3D[i].x,
01312                                                          m_playerAImpactPtsAllRalliesIn3D[i].y,
01313                                                          m_playerAImpactPtsAllRalliesIn3D[i].z);
01314 
01315 
01316 
01317                             setColorBasedOnRPMRange(m_playerARPM[i]);
01318                             loadMatricesToADSShader();
01319                             //(*shader)["PerFragADS"]->use();
01320 
01321                             prim->draw("rpmSphere");
01322                         }
01323                         m_transformStack.popTransform();
01324                     }
01325                 }
01326                   break;
01327               }
01328               case PLAYERB:
01329               {
01330                   if(m_playerBRPM.size() != 0)
01331                   {
01332                       for(int i=0;i<m_playerBImpactPtsAllRalliesIn3D.size();i++)
01333                       {
01334                           m_transformStack.pushTransform();
01335                           {
01336                               m_transformStack.setPosition(m_playerBImpactPtsAllRalliesIn3D[i].x,
01337                                                            m_playerBImpactPtsAllRalliesIn3D[i].y,
01338                                                            m_playerBImpactPtsAllRalliesIn3D[i].z);
01339 
01340 
01341                               setColorBasedOnRPMRange(m_playerBRPM[i]);
01342                               loadMatricesToADSShader();
01343                               //(*shader)["PerFragADS"]->use();
01344 
01345                               prim->draw("rpmSphere");
01346                           }
01347                           m_transformStack.popTransform();
01348 
01349                        }
01350                   }
01351                   break;
01352               }
01353               case BOTH:
01354               {
01355                   // not allowed, just a place holder
01356                   break;
01357               }
01358             }
01359               break;
01360           }
01361         }
01362           // or disable start tracking once process stats is clicked--easier way
01363       }
01364 
01365 
01366       if(!(m_3dFlag))
01367       {
01368 
01369         m_transformStack.pushTransform();
01370         {
01371             m_2DScreen->draw(&drawing);
01372         }
01373         m_transformStack.popTransform();
01374 
01375         // this ngl text rendering should
01376         // have been placed along with the multiple switch cases
01377         // above, but for some reason ngl text was not rendering
01378         // when placed there, probably because of opencv buffer
01379         // rendering and shader switch....
01380         // so we first draw the texture shader buffer and then finally render the percentages
01381         // in a seperate module renderPercentages()
01382         if(m_whichStat == IMPACT_PERCENTAGE_DISTRIBUTION_VIEW)
01383         {
01384             renderPercentages();
01385         }
01386         else
01387         {
01388             // other stats do not rely on text rendering,so
01389             // do nothing
01390         }
01391       }
01392       else
01393       {
01394 
01395 
01396 
01397         // 3D drawing, taken care in multiple switch cases in place,so
01398         // do nothing other than drawing the appropriate net lines
01399           //loadMatricesToADSShader();
01400 
01401 
01402           ngl::VertexArrayObject *vao= ngl::VertexArrayObject::createVOA(GL_LINES);
01403           ngl::Vec3 points[2];
01404 
01405 
01406           m_transformStack.pushTransform();
01407           {
01408             // middle net line representaion for ht map
01409             if(m_whichStat == IMPACT_HEIGHT_MAP_VIEW)
01410             {
01411 
01412                 //draw line
01413                 vao->bind();
01414                 points[0].m_x=0;
01415                 points[0].m_y=0.2;
01416                 points[0].m_z=m_fieldOfPlay.height/20.0;
01417                 points[1].m_x= 0;
01418                 points[1].m_y= 0.2;
01419                 points[1].m_z= -(m_fieldOfPlay.height/20.0);
01420 
01421                 vao->setData(2*sizeof(ngl::Vec3),points[0].m_x);
01422                 vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(ngl::Vec3),0);
01423                 vao->setNumIndices(2);
01424                 ngl::ShaderLib *shader = ngl::ShaderLib::instance();
01425                 (*shader)["PerFragADS"]->use();
01426                 shader->setShaderParam3f("material.Kd",0.0,0.0,0.0);
01427                 loadMatricesToADSShader();
01428                 vao->draw();
01429                 vao->removeVOA();
01430 
01431                 legendWindow(m_heightMapLegend);
01432 
01433             }
01434             // middle net line representaion for trajectory
01435             else if(m_whichStat == TRAJECTORY_VIEW)
01436             {
01437                 //draw line
01438                 vao->bind();
01439                 points[0].m_x=0;
01440                 points[0].m_y=0.005;
01441                 points[0].m_z=m_finalCourtDepthWorld/2;
01442                 points[1].m_x= 0;
01443                 points[1].m_y= 0.005;
01444                 points[1].m_z= -(m_finalCourtDepthWorld/2);
01445 
01446                 vao->setData(2*sizeof(ngl::Vec3),points[0].m_x);
01447                 vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(ngl::Vec3),0);
01448                 vao->setNumIndices(2);
01449                 ngl::ShaderLib *shader = ngl::ShaderLib::instance();
01450                 (*shader)["PerFragADS"]->use();
01451                 shader->setShaderParam3f("material.Kd",0.0,0.0,0.0);
01452                 loadMatricesToADSShader();
01453                 vao->draw();
01454                 vao->removeVOA();
01455 
01456                 legendWindow(m_trajectoryLegend);
01457             }
01458             // for speed and rpm stats same scale is maintained
01459             else if(m_whichStat == VELOCITY_VIEW)
01460             {
01461 
01462                 //draw line
01463                 vao->bind();
01464                 points[0].m_x=0;
01465                 points[0].m_y=0;
01466                 points[0].m_z=(m_finalCourtDepthWorld*10)/2;
01467                 points[1].m_x= 0;
01468                 points[1].m_y= 0;
01469                 points[1].m_z= -((m_finalCourtDepthWorld*10)/2);
01470 
01471                 vao->setData(2*sizeof(ngl::Vec3),points[0].m_x);
01472                 vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(ngl::Vec3),0);
01473                 vao->setNumIndices(2);
01474                 ngl::ShaderLib *shader = ngl::ShaderLib::instance();
01475                 (*shader)["PerFragADS"]->use();
01476                 shader->setShaderParam3f("material.Kd",0.0,0.0,0.0);
01477                 loadMatricesToADSShader();
01478                 vao->draw();
01479                 vao->removeVOA();
01480 
01481 
01482                 legendWindow(m_speedLegend);
01483 
01484             }
01485 
01486             else if(m_whichStat == RPM_VIEW)
01487             {
01488 
01489                 //draw line
01490                 vao->bind();
01491                 points[0].m_x=0;
01492                 points[0].m_y=0;
01493                 points[0].m_z=(m_finalCourtDepthWorld*10)/2;
01494                 points[1].m_x= 0;
01495                 points[1].m_y= 0;
01496                 points[1].m_z= -((m_finalCourtDepthWorld*10)/2);
01497 
01498                 vao->setData(2*sizeof(ngl::Vec3),points[0].m_x);
01499                 vao->setVertexAttributePointer(0,3,GL_FLOAT,sizeof(ngl::Vec3),0);
01500                 vao->setNumIndices(2);
01501                 ngl::ShaderLib *shader = ngl::ShaderLib::instance();
01502                 (*shader)["PerFragADS"]->use();
01503                 shader->setShaderParam3f("material.Kd",0.0,0.0,0.0);
01504                 loadMatricesToADSShader();
01505                 vao->draw();
01506                 vao->removeVOA();
01507 
01508                 legendWindow(m_rpmLegend);
01509 
01510             }
01511 
01512           }
01513           m_transformStack.popTransform();
01514       }
01515 }
01516 
01517 
01518 void StatsVisualization::timerEvent(
01519                           QTimerEvent *_event
01520                          )
01521 {
01522     if(_event->timerId() == m_updateTimer)
01523     {
01524         KinectInterface *kinect=KinectInterface::instance();
01525 
01526         if(m_importFlag == false)
01527         {
01528 
01529 
01530         // when stats window is not created with import flag, it is live window
01531         // so go ahead with computation, if not fieldOfPlay and width and height
01532         // would be filled up by the parser
01533 
01534           if(kinect->getBounds())
01535           {
01536               m_fieldOfPlay = kinect->getBoxObject();
01537 
01538               m_width = m_fieldOfPlay.width;
01539               m_height = m_fieldOfPlay.height;
01540               m_midTopX = m_fieldOfPlay.x + m_width/2;
01541               m_midTopY = m_fieldOfPlay.y;
01542               m_midBottomX = m_midTopX;
01543               m_midBottomY = m_midTopY + m_height;
01544 
01545               m_midLeftX = m_fieldOfPlay.x;
01546               m_midLeftY = m_midTopY + m_height/2;
01547               m_midRightX = m_fieldOfPlay.x + m_width;
01548               m_midRightY = m_midLeftY;
01549 
01550               // we kill the timer once the bounds are calculated finally
01551               // when rt click is done
01552               killTimer(m_updateTimer);
01553           }
01554 
01555 
01556 
01557         }
01558         else if(m_importFlag)
01559         {
01560             killTimer(m_updateTimer);
01561         }
01562 
01563         updateGL();
01564     }
01565 
01566 
01567 }
01568 
01569 void StatsVisualization::processKey(
01570                                                     QKeyEvent *_event
01571                                                    )
01572 {
01573   // this method is called every time the main window recives a key event.
01574   // we then switch on the key value and set the camera in the StatsVisualization
01575  switch (_event->key())
01576   {
01577 
01578     default : break;
01579   }
01580   // finally update the StatsVisualization and re-draw
01581   updateGL();
01582 }
01583 
01584 
01585 void StatsVisualization::updateDisplay()
01586 {
01587     // this is trigerred when process stats is clicked
01588     // if process stats is clicked, then tracking has been stopped
01589     // and its time to check if data is processed - this check is done
01590     // in paintgl, so we do not have to do anything here apart from calling paintgl
01591     updateGL();
01592 }
01593 
01594 
01595 // Once ball pts processed thru ball pts processing, data will be available in the player instances
01596 // CALLS TO 2D AND 3D STATS FUNCTIONS WITH INPUTS BEING PLAYER SPECIFIC POINTS WILL BE SUFFICIENT
01597 void StatsVisualization::fillAllImpactPointsBothPlayers()
01598 {
01599     if(m_playerA->getPlayerBallPtsAll().size() != 0)
01600     {
01601         m_playerAImpactData = m_playerA->getPlayerImpactPtsAllRallies();
01602         m_impactPtsFilled = true;
01603     }
01604 
01605     if(m_playerB->getPlayerBallPtsAll().size() != 0)
01606     {
01607         m_playerBImpactData = m_playerB->getPlayerImpactPtsAllRallies();
01608         m_impactPtsFilled = true;
01609     }
01610 
01611 
01612 
01613 }
01614 
01615 void StatsVisualization::buildQuadSpecificData()
01616 {
01617     m_percentageABL = m_playerA->getPercentageDistributionData(m_midTopX,m_midRightY,BOTTOM_LEFT);
01618     m_quadSpecABL = m_playerA->getQuadSpecificPoints(BOTTOM_LEFT);
01619 
01620     m_percentageATL = m_playerA->getPercentageDistributionData(m_midTopX,m_midRightY,TOP_LEFT);
01621     m_quadSpecATL = m_playerA->getQuadSpecificPoints(TOP_LEFT);
01622 
01623     m_percentageATR = m_playerA->getPercentageDistributionData(m_midTopX,m_midRightY,TOP_RIGHT);
01624     m_quadSpecATR = m_playerA->getQuadSpecificPoints(TOP_RIGHT);
01625 
01626     m_percentageABR = m_playerA->getPercentageDistributionData(m_midTopX,m_midRightY,BOTTOM_RIGHT);
01627     m_quadSpecABR = m_playerA->getQuadSpecificPoints(BOTTOM_RIGHT);
01628 
01629     m_percentageBBL = m_playerB->getPercentageDistributionData(m_midTopX,m_midRightY,BOTTOM_LEFT);
01630     m_quadSpecBBL = m_playerB->getQuadSpecificPoints(BOTTOM_LEFT);
01631 
01632     m_percentageBTL = m_playerB->getPercentageDistributionData(m_midTopX,m_midRightY,TOP_LEFT);
01633     m_quadSpecBTL = m_playerB->getQuadSpecificPoints(TOP_LEFT);
01634 
01635     m_percentageBTR = m_playerB->getPercentageDistributionData(m_midTopX,m_midRightY,TOP_RIGHT);
01636     m_quadSpecBTR = m_playerB->getQuadSpecificPoints(TOP_RIGHT);
01637 
01638     m_percentageBBR = m_playerB->getPercentageDistributionData(m_midTopX,m_midRightY,BOTTOM_RIGHT);
01639     m_quadSpecBBR = m_playerB->getQuadSpecificPoints(BOTTOM_RIGHT);
01640 
01641     m_quadMapBuilt = true;
01642 }
01643 
01644 void StatsVisualization::setWhichStatToView(int _inputWhichStat)
01645 {
01646     m_whichStat = (WHICH_STAT)_inputWhichStat;
01647 
01648     if((m_whichStat == IMPACT_HEIGHT_MAP_VIEW) || (m_whichStat == TRAJECTORY_VIEW) ||
01649             (m_whichStat == VELOCITY_VIEW) || (m_whichStat == RPM_VIEW)) // add more later
01650     {
01651         m_3dFlag = true;
01652     }
01653     else
01654     {
01655         m_3dFlag = false;
01656     }
01657     updateGL();
01658 }
01659 
01660 void StatsVisualization::setWhoseStatToView(int _inputWhoseStat)
01661 {
01662     m_whichPlayer = (WHOSE_STATS)_inputWhoseStat;
01663     updateGL();
01664 }
01665 
01666 void StatsVisualization::setWhichQuadToView(int _inputWhichQuad)
01667 {
01668     m_whichQuad = (WHICH_QUADRANT)_inputWhichQuad;
01669     updateGL();
01670 }
01671 
01672 void StatsVisualization::setKinectToPlayAreaDistance(double _inputDistanceInMeters)
01673 {
01674     // if the user wishes to change this value from UI
01675     // it has to be done before starting the tracking
01676     // this is not a dynamic variable
01677     m_kinectToPlayAreaInMeters = _inputDistanceInMeters;
01678 }
01679 
01680 void StatsVisualization::setDiameterOfBallInMeters(double _inputDiaInMeters)
01681 {
01682     // if the user wishes to change this value from UI
01683     // it has to be done before starting the tracking
01684     // this is not a dynamic variable
01685     m_diameterOfBAllInMeters = _inputDiaInMeters;
01686 }
01687 
01688 void StatsVisualization::buildPointGraphBars()
01689 {
01690     // grid resol is set to 10 now...
01691     // make it dynamic later
01692 
01693     std::vector<cv::Point3f> aBarGraphVertices,bBarGraphVertices;
01694 
01695     aBarGraphVertices = m_playerA->getBarGraphVertices(cv::Point(m_fieldOfPlay.x,m_fieldOfPlay.y),m_fieldOfPlay.width,
01696                                                          m_fieldOfPlay.height,10);
01697 
01698     bBarGraphVertices = m_playerB->getBarGraphVertices(cv::Point(m_fieldOfPlay.x,m_fieldOfPlay.y),m_fieldOfPlay.width,
01699                                                          m_fieldOfPlay.height,10);
01700 
01701 
01702     fillDataVertsWithNormals(aBarGraphVertices,m_dataVertsA);
01703     fillDataVertsWithNormals(bBarGraphVertices,m_dataVertsB);
01704 
01705 
01706     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01707 
01708     // we scale it down only by 10 and not by 20 as tri plane is drawn from 0,0,0
01709     // so it will stretch from 10 untis up to 10 units down
01710     // similarly for width as well from left to right
01711 
01712     prim->createTrianglePlane("heightMapPlane",m_fieldOfPlay.width/10.0,m_fieldOfPlay.height/10.0,1,1,ngl::Vec3(0,1,0));
01713 
01714     // create a vao as a series of GL_TRIANGLES
01715     m_vao= ngl::VertexArrayObject::createVOA(GL_TRIANGLES);
01716 
01717 
01718 }
01719 
01720 
01721 void StatsVisualization::buildTrajectory()
01722 {
01723     m_playerAInterpPtsMappedToRallies = m_playerA->getPlayerInterpolatedBallPtsAll(m_kinectToPlayAreaInMeters);
01724     m_playerBInterpPtsMappedToRallies = m_playerB->getPlayerInterpolatedBallPtsAll(m_kinectToPlayAreaInMeters);
01725 
01726     // conversion to world coords just to draw a static field of play
01727     // plane to be relative to the scale of the trajectories
01728     // i.e, both the field of play and the trajectories would be in Metres scale
01729 
01730     // note to self: DISPLAY the METRES SCALE on the window
01731 
01732     calculateFieldOfPlayInWorldCoords();
01733 
01734     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01735 
01736     // no scaling... 1 unit = 1 meter
01737     prim->createTrianglePlane("trajectoryPlane",m_finalCourtWidthWorld,m_finalCourtDepthWorld,1,1,ngl::Vec3(0,1,0));
01738 
01739     prim->createSphere("trajectorySphere",0.004,10.0);
01740 
01741     m_trajectoryBuilt = true;
01742 
01743 
01744 
01745 }
01746 
01747 void StatsVisualization::buildSpeedMap()
01748 {
01749     m_speedAData = m_playerA->getPlayerSpeedData(m_kinectToPlayAreaInMeters);
01750     m_playerAImpactPtsAllRalliesIn3D = m_playerA->getPlayerImpactPtsIn3DAllRallies();
01751 
01752     m_speedBData = m_playerB->getPlayerSpeedData(m_kinectToPlayAreaInMeters);
01753     m_playerBImpactPtsAllRalliesIn3D = m_playerB->getPlayerImpactPtsIn3DAllRallies();
01754 
01755     std::cout<<"PlayerA speeddata size is:"<<m_speedAData.size()<<"\n";
01756     std::cout<<"PlayerA impct point size is:"<<m_playerAImpactPtsAllRalliesIn3D.size()<<"\n";
01757 
01758     std::cout<<"PlayerB speeddata size is:"<<m_speedBData.size()<<"\n";
01759     std::cout<<"PlayerB impct point size is:"<<m_playerBImpactPtsAllRalliesIn3D.size()<<"\n";
01760 
01761     calculateFieldOfPlayInWorldCoords();
01762 
01763     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01764 
01765     prim->createSphere("sphere",0.08,10.0);
01766 
01767     // scaled by 10 as the speedmap view's scale is
01768     // 1 unit = 0.1 meter
01769     prim->createTrianglePlane("speedPlane",m_finalCourtWidthWorld*10.0,m_finalCourtDepthWorld*10.0,1,1,ngl::Vec3(0,1,0));
01770 
01771     m_speedMapBuilt = true;
01772 
01773 
01774 
01775 }
01776 
01777 void StatsVisualization::calculateFieldOfPlayInWorldCoords()
01778 {
01779     // have to set 0.70 to 1.0 and check if scaling issue gets resolved
01780     // and set it to depth paramter if something other than 1
01781 
01782     float fieldOfPlayXWorld = (m_fieldOfPlay.x/640 - 0.5) * m_kinectToPlayAreaInMeters * 1.111467f;
01783     float fieldOfPlayYWorld = (0.5 - m_fieldOfPlay.y/480) * m_kinectToPlayAreaInMeters * 0.833599f;
01784 
01785     float fieldOfPlayDownY = m_fieldOfPlay.y + m_fieldOfPlay.height;
01786     float fieldOfPlayDownYWorld = (0.5 - fieldOfPlayDownY/480) * m_kinectToPlayAreaInMeters * 0.833599f;
01787 
01788     float fieldOfPlayExtremeLeftX = m_fieldOfPlay.x + m_fieldOfPlay.width;
01789     float fieldOfPlayExtremeLeftXWorld = (fieldOfPlayExtremeLeftX/640 - 0.5) * m_kinectToPlayAreaInMeters * 1.111467f;
01790 
01791     m_finalCourtWidthWorld = fabs(fieldOfPlayExtremeLeftXWorld - fieldOfPlayXWorld);
01792     m_finalCourtDepthWorld = fabs(fieldOfPlayDownYWorld - fieldOfPlayYWorld);
01793 }
01794 
01795 void StatsVisualization::setColorBasedOnSpeedRange(float _inputVelocity)
01796 {
01797     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
01798     (*shader)["PerFragADS"]->use();
01799 
01800     if(_inputVelocity >= 0.0 && _inputVelocity < 0.3)
01801     {
01802        shader->setShaderParam3f("material.Kd",0.0,0.8,1.0);
01803     }
01804     else if(_inputVelocity >= 0.3 && _inputVelocity < 0.6)
01805     {
01806        shader->setShaderParam3f("material.Kd",1.0,1.0,0.0);
01807     }
01808     else if(_inputVelocity >= 0.6)
01809     {
01810        shader->setShaderParam3f("material.Kd",1.0,0.5,0.0);
01811     }
01812 }
01813 
01814 void StatsVisualization::buildRPMData()
01815 {
01816     m_playerARPM = m_playerA->getRevolutionsPerMinute(m_diameterOfBAllInMeters,m_kinectToPlayAreaInMeters);
01817     m_playerAImpactPtsAllRalliesIn3D = m_playerA->getPlayerImpactPtsIn3DAllRallies();
01818 
01819     m_playerBRPM = m_playerB->getRevolutionsPerMinute(m_diameterOfBAllInMeters,m_kinectToPlayAreaInMeters);
01820     m_playerBImpactPtsAllRalliesIn3D = m_playerB->getPlayerImpactPtsIn3DAllRallies();
01821 
01822     std::cout<<"PlayerA rpmdata size is:"<<m_playerARPM.size()<<"\n";
01823     std::cout<<"PlayerA impct point size is:"<<m_playerAImpactPtsAllRalliesIn3D.size()<<"\n";
01824 
01825     std::cout<<"PlayerB rpmdata size is:"<<m_playerBRPM.size()<<"\n";
01826     std::cout<<"PlayerB impct point size is:"<<m_playerBImpactPtsAllRalliesIn3D.size()<<"\n";
01827 
01828     calculateFieldOfPlayInWorldCoords();
01829 
01830     // currently creating balls again which will be rendered color coded
01831     // based on the rpm value
01832 
01833     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
01834 
01835     prim->createSphere("rpmSphere",0.08,10.0);
01836 
01837     // scaled by 10 as the speedmap view's scale is
01838     // 1 unit = 0.1 meter
01839     prim->createTrianglePlane("rpmPlane",m_finalCourtWidthWorld*10.0,m_finalCourtDepthWorld*10.0,1,1,ngl::Vec3(0,1,0));
01840 
01841     m_rpmDataBuilt = true;
01842 
01843 
01844 }
01845 
01846 void StatsVisualization::setColorBasedOnRPMRange(float _inputRPM)
01847 {
01848     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
01849     (*shader)["PerFragADS"]->use();
01850 
01851     if(_inputRPM >= 0 && _inputRPM < 100)
01852     {
01853        shader->setShaderParam3f("material.Kd",0.0,0.8,1.0);
01854     }
01855     else if(_inputRPM >= 100 && _inputRPM < 200)
01856     {
01857        shader->setShaderParam3f("material.Kd",1.0,1.0,0.0);
01858     }
01859     else if(_inputRPM >= 200)
01860     {
01861        shader->setShaderParam3f("material.Kd",1.0,0.5,0.0);
01862     }
01863 }
01864 
01865 void StatsVisualization::fillDataVertsWithNormals(std::vector<cv::Point3f>& _inputVertList,
01866                                                   std::vector<VertData>& o_normalFilledDataVerts)
01867 {
01868     // we scale it down only by 10 and not by 20 as tri plane is drawn from 0,0,0
01869     // so it will stretch from 10 untis up to 10 units down
01870     // similarly for width as well from left to right
01871     int cubeIndex = 0;
01872     VertData d;
01873 
01874     // for every cube
01875     for(int i=0;i<_inputVertList.size();i=i+8)
01876     {
01877         //for every face in the cube - 6 vertices per face (2 triangle per face)
01878         for(int j=0;j<sizeof(indices)/sizeof(indices[0]);j=j+6)// size of indices = 36
01879         {
01880             // GUNDU FACE
01881 
01882             //triangle 1, v1
01883             d.x = _inputVertList[indices[j]+i].x;// - _gapFactor*normals[j/6].m_x;
01884             d.y = _inputVertList[indices[j]+i].y;//- _gapFactor*normals[j/6].m_y;
01885             d.z = _inputVertList[indices[j]+i].z;// - _gapFactor*normals[j/6].m_z;
01886 
01887             d.nx = normals[j/6].m_x;
01888             d.ny = normals[j/6].m_y;
01889             d.nz = normals[j/6].m_z;
01890             o_normalFilledDataVerts.push_back(d);
01891 
01892             //triangle 1, v2
01893             d.x = _inputVertList[indices[j+1]+i].x;// - _gapFactor*normals[j/6].m_x;
01894             d.y = _inputVertList[indices[j+1]+i].y;// - _gapFactor*normals[j/6].m_y;
01895             d.z = _inputVertList[indices[j+1]+i].z;// - _gapFactor*normals[j/6].m_z;
01896 
01897             d.nx = normals[j/6].m_x;
01898             d.ny = normals[j/6].m_y;
01899             d.nz = normals[j/6].m_z;
01900             o_normalFilledDataVerts.push_back(d);
01901 
01902             //triangle 1, v3
01903             d.x = _inputVertList[indices[j+2]+i].x;// - _gapFactor*normals[j/6].m_x;
01904             d.y = _inputVertList[indices[j+2]+i].y;// - _gapFactor*normals[j/6].m_y;
01905             d.z = _inputVertList[indices[j+2]+i].z;// - _gapFactor*normals[j/6].m_z;
01906 
01907             d.nx = normals[j/6].m_x;
01908             d.ny = normals[j/6].m_y;
01909             d.nz = normals[j/6].m_z;
01910             o_normalFilledDataVerts.push_back(d);
01911 
01912             //triangle 2, v1
01913             d.x = _inputVertList[indices[j+3]+i].x;// - _gapFactor*normals[j/6].m_x;
01914             d.y = _inputVertList[indices[j+3]+i].y;// - _gapFactor*normals[j/6].m_y;
01915             d.z = _inputVertList[indices[j+3]+i].z;// - _gapFactor*normals[j/6].m_z;
01916 
01917             d.nx = normals[j/6].m_x;
01918             d.ny = normals[j/6].m_y;
01919             d.nz = normals[j/6].m_z;
01920             o_normalFilledDataVerts.push_back(d);
01921 
01922             //triangle 2, v2
01923             d.x = _inputVertList[indices[j+4]+i].x;// - _gapFactor*normals[j/6].m_x;
01924             d.y = _inputVertList[indices[j+4]+i].y;// - _gapFactor*normals[j/6].m_y;
01925             d.z = _inputVertList[indices[j+4]+i].z;// - _gapFactor*normals[j/6].m_z;
01926 
01927             d.nx = normals[j/6].m_x;
01928             d.ny = normals[j/6].m_y;
01929             d.nz = normals[j/6].m_z;
01930             o_normalFilledDataVerts.push_back(d);
01931 
01932             //triangle 2, v3
01933             d.x = _inputVertList[indices[j+5]+i].x;// - _gapFactor*normals[j/6].m_x;
01934             d.y = _inputVertList[indices[j+5]+i].y;// - _gapFactor*normals[j/6].m_y;
01935             d.z = _inputVertList[indices[j+5]+i].z;// - _gapFactor*normals[j/6].m_z;
01936 
01937             d.nx = normals[j/6].m_x;
01938             d.ny = normals[j/6].m_y;
01939             d.nz = normals[j/6].m_z;
01940 
01941             o_normalFilledDataVerts.push_back(d);
01942         }
01943         cubeIndex++;
01944     }
01945 }
01946 
01947 void StatsVisualization::readFile(QString _inputFileName)
01948 {
01949     if(_inputFileName.isEmpty())
01950     {
01951         std::cout<<"Filename empty. Returning. Read Aborted\n";
01952         return;
01953     }
01954     //read
01955     std::cout <<"Reading: "<<"\n";
01956 
01957     cv::FileStorage fs;
01958     fs.open(_inputFileName.toStdString(), cv::FileStorage::READ);
01959 
01960 
01961     fillDataFromFileForBothPlayers(fs,PLAYERA);
01962     fillDataFromFileForBothPlayers(fs,PLAYERB);
01963 
01964     cv::FileNode n8 = fs["FieldOfPlay"];
01965     cv::FileNodeIterator it8 = n8.begin();
01966     m_fieldOfPlay.x = (int)*it8;
01967     m_fieldOfPlay.y = (int)*(++it8);
01968     m_fieldOfPlay.width = (int)*(++it8);
01969     m_fieldOfPlay.height = (int)*(++it8);
01970 
01971     m_finalCourtWidthWorld = (float)fs["CourtWidth"];
01972     m_finalCourtDepthWorld = (float)fs["CourtDepth"];
01973     m_width = (int)fs["Width"];
01974     m_height = (int)fs["Height"];
01975     m_midTopX = (int)fs["MidTopX"];
01976     m_midTopY = (int)fs["MidTopY"];
01977     m_midBottomX = (int)fs["MidBottomX"];
01978     m_midBottomY = (int)fs["MidBottomY"];
01979     m_midLeftX = (int)fs["MidLeftX"];
01980     m_midLeftY = (int)fs["MidLeftY"];
01981     m_midRightX = (int)fs["MidRightX"];
01982     m_midRightY = (int)fs["MidRightY"];
01983 
01984     m_quadMapBuilt = true;
01985     m_speedMapBuilt = true;
01986     m_rpmDataBuilt = true;
01987     m_trajectoryBuilt = true;
01988     m_impactPtsFilled = true;
01989 
01990     //Generating our rendering stuff
01991 
01992     // create a vao as a series of GL_TRIANGLES
01993     m_vao= ngl::VertexArrayObject::createVOA(GL_TRIANGLES);
01994 
01995     // we will create separate planes and spheres for various statistics instead of
01996     // trying to scale them each time as we have different units of scaling and
01997     // those scale factors are calculated at various times
01998     // and this is much easier than that even though it takes quite a bit of memory
01999 
02000     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
02001     prim->createTrianglePlane("heightMapPlane",m_fieldOfPlay.width/10.0,m_fieldOfPlay.height/10.0,1,1,ngl::Vec3(0,1,0));
02002     prim->createTrianglePlane("trajectoryPlane",m_finalCourtWidthWorld,m_finalCourtDepthWorld,1,1,ngl::Vec3(0,1,0));
02003     prim->createSphere("trajectorySphere",0.004,10.0);
02004     prim->createSphere("sphere",0.08,10.0);
02005     prim->createTrianglePlane("speedPlane",m_finalCourtWidthWorld*10.0,m_finalCourtDepthWorld*10.0,1,1,ngl::Vec3(0,1,0));
02006     prim->createSphere("rpmSphere",0.08,10.0);
02007     prim->createTrianglePlane("rpmPlane",m_finalCourtWidthWorld*10.0,m_finalCourtDepthWorld*10.0,1,1,ngl::Vec3(0,1,0));
02008 
02009     updateGL();
02010 
02011 }
02012 
02013 // recieve file name input from UI
02014 void StatsVisualization::writeFile()
02015 {
02016 
02017     QString fileName = QFileDialog::getSaveFileName(this, "Save File","archive"," Xml File (*.xml)");
02018 
02019 
02020     // check if filename is valid, if so call read
02021     if(fileName.isEmpty())
02022     {
02023         std::cout<<"File name empty. Write aborted.\n";
02024         return;
02025     }
02026 
02027     cv::FileStorage fs(fileName.toStdString(), cv::FileStorage::WRITE);
02028 
02029     // we build all the data if not already present in the respective buffers
02030     // this might take quite a while as all data are captured in buffers
02031     // sequentially
02032     if(!(m_impactPtsFilled))
02033     {
02034         fillAllImpactPointsBothPlayers();
02035     }
02036 
02037     if(!(m_quadMapBuilt))
02038     {
02039         buildQuadSpecificData();
02040     }
02041 
02042     if(!(m_vao))
02043     {
02044         buildPointGraphBars();
02045     }
02046 
02047     if(!(m_trajectoryBuilt))
02048     {
02049         buildTrajectory();
02050     }
02051 
02052     if(!(m_speedMapBuilt))
02053     {
02054         buildSpeedMap();
02055     }
02056 
02057     if(!(m_rpmDataBuilt))
02058     {
02059         buildRPMData();
02060     }
02061 
02062     // Data corresponding to both the players written out to xml
02063     // Also, common data such as field of play width etc are written out to xml
02064 
02065     // PLAYERA data
02066 
02067     fs << "PLAYERA";
02068     fs<< "{";
02069 
02070     fs<< "ImpactData"<<m_playerAImpactData;
02071 
02072     fs<< "QuadSpecBL"<<m_quadSpecABL;
02073 
02074     fs<< "QuadSpecTL"<<m_quadSpecATL;
02075 
02076     fs<< "QuadSpecTR"<<m_quadSpecATR;
02077 
02078     fs<< "QuadSpecBR"<<m_quadSpecABR;
02079 
02080     fs<< "PercentageBL"<< m_percentageABL;
02081 
02082     fs<< "PercentageTL"<< m_percentageATL;
02083 
02084     fs<< "PercentageTR"<< m_percentageATR;
02085 
02086     fs<< "PercentageBR"<< m_percentageABR;
02087 
02088     fs<< "InterpPtsMappedToRallies"<< m_playerAInterpPtsMappedToRallies;
02089 
02090     fs<< "CubeDataVertices"<<"[";
02091     for(int i=0;i<m_dataVertsA.size();i++)
02092     {
02093         fs<< m_dataVertsA[i].nx;
02094         fs<< m_dataVertsA[i].ny;
02095         fs<< m_dataVertsA[i].nz;
02096         fs<< m_dataVertsA[i].x;
02097         fs<< m_dataVertsA[i].y;
02098         fs<< m_dataVertsA[i].z;
02099     }
02100     fs<< "]";
02101 
02102     fs<< "SpeedData"<<m_speedAData;
02103 
02104     fs<< "PlayerImpactPointsIn3D"<<m_playerAImpactPtsAllRalliesIn3D;
02105 
02106     fs<< "RPMData"<<m_playerARPM;
02107 
02108     fs<< "}";
02109 
02110 
02111     //PLAYERB data
02112 
02113     fs<< "PLAYERB";
02114     fs<< "{";
02115 
02116     fs<< "ImpactData"<<m_playerBImpactData;
02117 
02118     fs<< "QuadSpecBL"<<m_quadSpecBBL;
02119 
02120     fs<< "QuadSpecTL"<<m_quadSpecBTL;
02121 
02122     fs<< "QuadSpecTR"<<m_quadSpecBTR;
02123 
02124     fs<< "QuadSpecBR"<<m_quadSpecBBR;
02125 
02126     fs<< "PercentageBL"<< m_percentageBBL;
02127 
02128     fs<< "PercentageTL"<< m_percentageBTL;
02129 
02130     fs<< "PercentageTR"<< m_percentageBTR;
02131 
02132     fs<< "PercentageBR"<< m_percentageBBR;
02133 
02134     fs<< "InterpPtsMappedToRallies"<< m_playerBInterpPtsMappedToRallies;
02135 
02136     fs<< "CubeDataVertices"<<"[";
02137     for(int i=0;i<m_dataVertsB.size();i++)
02138     {
02139         fs<< m_dataVertsB[i].nx;
02140         fs<< m_dataVertsB[i].ny;
02141         fs<< m_dataVertsB[i].nz;
02142         fs<< m_dataVertsB[i].x;
02143         fs<< m_dataVertsB[i].y;
02144         fs<< m_dataVertsB[i].z;
02145     }
02146     fs<< "]";
02147 
02148     fs<< "SpeedData"<<m_speedBData;
02149 
02150     fs<< "PlayerImpactPointsIn3D"<<m_playerBImpactPtsAllRalliesIn3D;
02151 
02152     fs<< "RPMData"<<m_playerBRPM;
02153 
02154     fs<< "}";
02155 
02156 
02157     fs<<"FieldOfPlay"<<"["<<m_fieldOfPlay.x<<m_fieldOfPlay.y<<m_fieldOfPlay.width<<m_fieldOfPlay.height<<"]";
02158     fs<<"CourtWidth"<<m_finalCourtWidthWorld;
02159     fs<<"CourtDepth"<<m_finalCourtDepthWorld;
02160     fs<<"Width"<<m_width;
02161     fs<<"Height"<<m_height;
02162     fs<<"MidTopX"<<m_midTopX;
02163     fs<<"MidTopY"<<m_midTopY;
02164     fs<<"MidBottomX"<<m_midBottomX;
02165     fs<<"MidBottomY"<<m_midBottomY;
02166     fs<<"MidLeftX"<<m_midLeftX;
02167     fs<<"MidLeftY"<<m_midLeftY;
02168     fs<<"MidRightX"<<m_midRightX;
02169     fs<<"MidRightY"<<m_midRightY;
02170 
02171     fs.release();                                       // explicit close
02172 
02173     std::cout << "Write Done.\n";
02174 
02175 
02176 }
02177 
02178 
02179 void StatsVisualization::fillDataFromFileForBothPlayers(cv::FileStorage& _fs,WHOSE_STATS _whichPlayer)
02180 {
02181     std::string whichPlayerString;
02182 
02183     if(_whichPlayer == PLAYERA)
02184     {
02185         whichPlayerString = "PLAYERA";
02186     }
02187     else
02188     {
02189         whichPlayerString = "PLAYERB";
02190     }
02191 
02192     cv::FileNode n1 = _fs[whichPlayerString]["ImpactData"];                         // Read string sequence - Get node
02193     if (n1.type() != cv::FileNode::SEQ)
02194     {
02195         std::cout << "Impact pt is not a sequence\n";
02196     }
02197 
02198     cv::FileNodeIterator it1 = n1.begin(), it1_end = n1.end(); // Go through the node
02199     for (; it1 != it1_end; ++it1++)
02200     {
02201         if(whichPlayerString == "PLAYERA")
02202         {
02203             this->m_playerAImpactData.push_back(cv::Point2f((float)*it1,(float)*(++it1)));
02204         }
02205         else if(whichPlayerString == "PLAYERB")
02206         {
02207             this->m_playerBImpactData.push_back(cv::Point2f((float)*it1,(float)*(++it1)));
02208         }
02209     }
02210 
02211 
02212 
02213     cv::FileNode n2 = _fs[whichPlayerString]["QuadSpecBL"];                         // Read string sequence - Get node
02214     if (n2.type() != cv::FileNode::SEQ)
02215     {
02216         std::cout << "ABL is not a sequence\n";
02217     }
02218 
02219     cv::FileNodeIterator it2 = n2.begin(), it2_end = n2.end(); // Go through the node
02220     for (; it2 != it2_end; ++it2++)
02221     {
02222         if(whichPlayerString == "PLAYERA")
02223         {
02224             this->m_quadSpecABL.push_back(cv::Point2f((float)*it2,(float)*(++it2)));
02225         }
02226         else if(whichPlayerString == "PLAYERB")
02227         {
02228             this->m_quadSpecBBL.push_back(cv::Point2f((float)*it2,(float)*(++it2)));
02229         }
02230     }
02231 
02232 
02233     cv::FileNode n3 = _fs[whichPlayerString]["QuadSpecTL"];                         // Read string sequence - Get node
02234     if (n3.type() != cv::FileNode::SEQ)
02235     {
02236         std::cout << "ATL is not a sequence\n";
02237     }
02238 
02239     cv::FileNodeIterator it3 = n3.begin(), it3_end = n3.end(); // Go through the node
02240     for (; it3 != it3_end; ++it3++)
02241     {
02242         if(whichPlayerString == "PLAYERA")
02243         {
02244             this->m_quadSpecATL.push_back(cv::Point2f((float)*it3,(float)*(++it3)));
02245         }
02246         else if(whichPlayerString == "PLAYERB")
02247         {
02248             this->m_quadSpecBTL.push_back(cv::Point2f((float)*it3,(float)*(++it3)));
02249         }
02250     }
02251 
02252 
02253     cv::FileNode n4 = _fs[whichPlayerString]["QuadSpecTR"];                         // Read string sequence - Get node
02254     if (n4.type() != cv::FileNode::SEQ)
02255     {
02256         std::cout << "ATR is not a sequence!\n";
02257     }
02258 
02259     cv::FileNodeIterator it4 = n4.begin(), it4_end = n4.end(); // Go through the node
02260     for (; it4 != it4_end; ++it4++)
02261     {
02262         if(whichPlayerString == "PLAYERA")
02263         {
02264             this->m_quadSpecATR.push_back(cv::Point2f((float)*it4,(float)*(++it4)));
02265         }
02266         else if(whichPlayerString == "PLAYERB")
02267         {
02268             this->m_quadSpecBTR.push_back(cv::Point2f((float)*it4,(float)*(++it4)));
02269         }
02270     }
02271 
02272     cv::FileNode n5 = _fs[whichPlayerString]["QuadSpecBR"];                         // Read string sequence - Get node
02273     if (n5.type() != cv::FileNode::SEQ)
02274     {
02275         std::cout << "ABR not a sequence!\n";
02276     }
02277 
02278     cv::FileNodeIterator it5 = n5.begin(), it5_end = n5.end(); // Go through the node
02279     for (; it5 != it5_end; ++it5++)
02280     {
02281         if(whichPlayerString == "PLAYERA")
02282         {
02283             this->m_quadSpecABR.push_back(cv::Point2f((float)*it5,(float)*(++it5)));
02284         }
02285         else if(whichPlayerString == "PLAYERB")
02286         {
02287             this->m_quadSpecBBR.push_back(cv::Point2f((float)*it5,(float)*(++it5)));
02288         }
02289     }
02290 
02291 
02292     if(whichPlayerString == "PLAYERA")
02293     {
02294         this->m_percentageABL = (float)_fs[whichPlayerString]["PercentageBL"];
02295         this->m_percentageATL = (float)_fs[whichPlayerString]["PercentageTL"];
02296         this->m_percentageATR = (float)_fs[whichPlayerString]["PercentageTR"];
02297         this->m_percentageABR = (float)_fs[whichPlayerString]["PercentageBR"];
02298     }
02299     else if(whichPlayerString == "PLAYERB")
02300     {
02301         this->m_percentageBBL = (float)_fs[whichPlayerString]["PercentageBL"];
02302         this->m_percentageBTL = (float)_fs[whichPlayerString]["PercentageTL"];
02303         this->m_percentageBTR = (float)_fs[whichPlayerString]["PercentageTR"];
02304         this->m_percentageBBR = (float)_fs[whichPlayerString]["PercentageBR"];
02305     }
02306 
02307 
02308 
02309     cv::FileNode trajectoryNode = _fs[whichPlayerString]["InterpPtsMappedToRallies"];  // Read string sequence - Get node
02310     if (trajectoryNode.type() != cv::FileNode::SEQ)
02311     {
02312         std::cout << "Trajectory node not a sequence!\n";
02313     }
02314 
02315     cv::FileNodeIterator trajectoryNodeit = trajectoryNode.begin(), trajectoryNodeit_end = trajectoryNode.end(); // Go through the node
02316     for (; trajectoryNodeit != trajectoryNodeit_end; ++trajectoryNodeit)
02317     {
02318         if(whichPlayerString == "PLAYERA")
02319         {
02320             this->m_playerATrajectoryFromFile.push_back((float)*trajectoryNodeit);
02321         }
02322         else if(whichPlayerString == "PLAYERB")
02323         {
02324             this->m_playerBTrajectoryFromFile.push_back((float)*trajectoryNodeit);
02325         }
02326     }
02327 
02328 
02329     cv::FileNode htMapNode = _fs[whichPlayerString]["CubeDataVertices"];  // Read string sequence - Get node
02330     if (htMapNode.type() != cv::FileNode::SEQ)
02331     {
02332         std::cout << "HtMap node not a sequence!\n";
02333     }
02334 
02335     cv::FileNodeIterator htMapNodeit = htMapNode.begin(), htMapNodeit_end = htMapNode.end(); // Go through the node
02336     for (; htMapNodeit != htMapNodeit_end; ++htMapNodeit)
02337     {
02338         VertData tempData;
02339         tempData.nx = (float)*(htMapNodeit);
02340         tempData.ny = (float)*(++htMapNodeit);
02341         tempData.nz = (float)*(++htMapNodeit);
02342 
02343         tempData.x = (float)*(++htMapNodeit);
02344         tempData.y = (float)*(++htMapNodeit);
02345         tempData.z = (float)*(++htMapNodeit);
02346 
02347         if(whichPlayerString == "PLAYERA")
02348         {
02349             this->m_dataVertsA.push_back(tempData);
02350         }
02351         else if(whichPlayerString == "PLAYERB")
02352         {
02353             this->m_dataVertsB.push_back(tempData);
02354         }
02355     }
02356 
02357 
02358     cv::FileNode n6 = _fs[whichPlayerString]["SpeedData"];                         // Read string sequence - Get node
02359     if (n6.type() != cv::FileNode::SEQ)
02360     {
02361         std::cout << "SpeedData not a sequence!\n";
02362     }
02363 
02364     cv::FileNodeIterator it6 = n6.begin(), it6_end = n6.end(); // Go through the node
02365     for (; it6 != it6_end; ++it6)
02366     {
02367         if(whichPlayerString == "PLAYERA")
02368         {
02369             this->m_speedAData.push_back((float)*it6);
02370         }
02371         else if(whichPlayerString == "PLAYERB")
02372         {
02373             this->m_speedBData.push_back((float)*it6);
02374         }
02375     }
02376 
02377 
02378     cv::FileNode impactPt3DNode = _fs[whichPlayerString]["PlayerImpactPointsIn3D"];  // Read string sequence - Get node
02379     if (impactPt3DNode.type() != cv::FileNode::SEQ)
02380     {
02381         std::cout << "PlayerImpactPointsIn3D node not a sequence!\n";
02382     }
02383 
02384     cv::FileNodeIterator impactPt3DNodeit = impactPt3DNode.begin(), impactPt3DNodeit_end = impactPt3DNode.end(); // Go through the node
02385     for (; impactPt3DNodeit != impactPt3DNodeit_end; ++impactPt3DNodeit)
02386     {
02387         cv::Point3f tempPoint3D((float)*(impactPt3DNodeit), (float)*(++impactPt3DNodeit), (float)*(++impactPt3DNodeit));
02388 
02389         if(whichPlayerString == "PLAYERA")
02390         {
02391             this->m_playerAImpactPtsAllRalliesIn3D.push_back(tempPoint3D);
02392         }
02393         else if(whichPlayerString == "PLAYERB")
02394         {
02395             this->m_playerBImpactPtsAllRalliesIn3D.push_back(tempPoint3D);
02396         }
02397     }
02398 
02399 
02400     cv::FileNode n7 = _fs[whichPlayerString]["RPMData"];                         // Read string sequence - Get node
02401     if (n7.type() != cv::FileNode::SEQ)
02402     {
02403         std::cout << "RPMData not a sequence!\n";
02404     }
02405 
02406     cv::FileNodeIterator it7 = n7.begin(), it7_end = n7.end(); // Go through the node
02407     for (; it7 != it7_end; ++it7)
02408     {
02409         if(whichPlayerString == "PLAYERA")
02410         {
02411             this->m_playerARPM.push_back((float)*it7);
02412         }
02413         else if(whichPlayerString == "PLAYERB")
02414         {
02415             this->m_playerBRPM.push_back((float)*it7);
02416         }
02417 
02418     }
02419 }
02420 
02421 void StatsVisualization::drawCrowd(const std::string& _inputPlaneName)
02422 {
02423 
02424     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
02425     (*shader)["TextureShaderStats"]->use();
02426     // need to bind the active texture before drawing
02427     glBindTexture(GL_TEXTURE_2D,m_crowdTextureName);
02428     //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
02429 
02430     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
02431 
02432     ngl::Real positionX,positionZ;
02433     positionX = positionZ = 0.0;
02434 
02435     if(_inputPlaneName == "heightMapPlane")
02436     {
02437         positionX = (m_fieldOfPlay.width/2);// + 300.0;
02438         positionZ = (m_fieldOfPlay.width/2) - 10; //285.0;
02439     }
02440     else if(_inputPlaneName == "trajectoryPlane")
02441     {
02442         positionX = m_finalCourtWidthWorld + 3.0;
02443         positionZ = m_finalCourtWidthWorld + 3.0;
02444     }
02445     else if((_inputPlaneName == "speedPlane") || (_inputPlaneName == "rpmPlane"))
02446     {
02447         positionX = (m_finalCourtWidthWorld * 10) + 30.0;
02448         positionZ = (m_finalCourtWidthWorld * 10) + 30.0;
02449     }
02450     // rt
02451     m_transformStack.pushTransform();
02452     {
02453         m_transformStack.setScale(10,10,10);
02454         m_transformStack.setRotation(0,90,90);
02455         m_transformStack.setPosition(positionX,0,0);
02456 
02457         loadMatricesToTextureShader();
02458         prim->draw(_inputPlaneName);
02459     }
02460     m_transformStack.popTransform();
02461 
02462 
02463 
02464     // lt
02465     m_transformStack.pushTransform();
02466     {
02467         m_transformStack.setScale(10,10,10);
02468         m_transformStack.setRotation(0,90,90);
02469         m_transformStack.setPosition(-(positionX),0,0);
02470 
02471 
02472         loadMatricesToTextureShader();
02473         prim->draw(_inputPlaneName);
02474     }
02475     m_transformStack.popTransform();
02476 
02477 
02478 
02479     // far
02480     m_transformStack.pushTransform();
02481     {
02482         m_transformStack.setScale(10,10,10);
02483         m_transformStack.setRotation(-90,0,0);
02484         m_transformStack.setPosition(0,0,positionZ);
02485 
02486 
02487         loadMatricesToTextureShader();
02488         prim->draw(_inputPlaneName);
02489     }
02490     m_transformStack.popTransform();
02491 
02492 
02493 
02494     // back
02495     m_transformStack.pushTransform();
02496     {
02497         m_transformStack.setScale(10,10,10);
02498         m_transformStack.setRotation(-90,0,0);
02499         m_transformStack.setPosition(0,0,-(positionZ));
02500 
02501 
02502         loadMatricesToTextureShader();
02503         prim->draw(_inputPlaneName);
02504     }
02505     m_transformStack.popTransform();
02506 
02507 
02508 
02509 }
02510 
02511 void StatsVisualization::drawTable(const std::string& _inputTableName)
02512 {
02513     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
02514     (*shader)["TextureShaderStats"]->use();
02515     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
02516 
02517     ngl::Real positionY = 0.0;
02518 
02519     if((_inputTableName == "speedPlane") || (_inputTableName == "rpmPlane"))
02520     {
02521         positionY = -0.08;
02522     }
02523     else
02524     {
02525         positionY = 0.0;
02526     }
02527     m_transformStack.pushTransform();
02528     {
02529         m_transformStack.setPosition(0,positionY,0);
02530         glBindTexture(GL_TEXTURE_2D,m_tableTextureName);
02531         loadMatricesToTextureShader();
02532         prim->draw(_inputTableName);
02533     }
02534     m_transformStack.popTransform();
02535 
02536 }
02537 
02538 void StatsVisualization::drawContainingGridScaleXY()
02539 {
02540     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
02541     (*shader)["TextureShaderStats"]->use();
02542     // need to bind the active texture before drawing
02543     glBindTexture(GL_TEXTURE_2D,m_gridXYHtMap);
02544     //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
02545 
02546     ngl::VAOPrimitives *prim = ngl::VAOPrimitives::instance();
02547     ngl::Real positionX,positionZ,positionY;
02548     positionX = positionZ = positionY = 0;
02549 
02550     // we will create separate planes and spheres for various statistics instead of
02551     // trying to scale them each time as we have different units of scaling and
02552     // those scale factors are calculated at various times
02553     // and this is much easier than that even though it takes quite a bit of memory
02554     if(m_whichStat == IMPACT_HEIGHT_MAP_VIEW)
02555     {
02556         prim->createTrianglePlane("xygridrtplane",m_fieldOfPlay.height/10.0,20,1,1,ngl::Vec3(0,1,0));
02557         prim->createTrianglePlane("xygridfarplane",m_fieldOfPlay.width/10.0,20,1,1,ngl::Vec3(0,1,0));
02558         positionX = -(m_fieldOfPlay.width/20.0);
02559         positionY = 10;
02560         positionZ = -(m_fieldOfPlay.height/20.0);
02561     }
02562     else if(m_whichStat == TRAJECTORY_VIEW)
02563     {
02564         prim->createTrianglePlane("xygridrtplane",m_finalCourtDepthWorld,0.5,1,1,ngl::Vec3(0,1,0));
02565         prim->createTrianglePlane("xygridfarplane",m_finalCourtWidthWorld,0.5,1,1,ngl::Vec3(0,1,0));
02566         positionX = -(m_finalCourtWidthWorld/2.0);
02567         positionY = 0.25;
02568         positionZ = -(m_finalCourtDepthWorld/2.0);
02569     }
02570 
02571 
02572     // rt
02573     m_transformStack.pushTransform();
02574     {
02575         //m_transformStack.setScale(m_fieldOfPlay.width,20,0);
02576         m_transformStack.setRotation(0,90,-270);
02577         m_transformStack.setPosition(positionX,positionY,0);
02578         loadMatricesToTextureShader();
02579         prim->draw("xygridrtplane");
02580 
02581     }
02582     m_transformStack.popTransform();
02583 
02584 
02585 
02586     // far
02587     m_transformStack.pushTransform();
02588     {
02589         //m_transformStack.setScale(m_fieldOfPlay.width,20,0);
02590         m_transformStack.setRotation(-90,0,0);
02591         m_transformStack.setPosition(0,positionY,positionZ);
02592         loadMatricesToTextureShader();
02593         prim->draw("xygridfarplane");
02594 
02595     }
02596     m_transformStack.popTransform();
02597 
02598 
02599 }
02600 
02601 void StatsVisualization::renderPercentages()
02602 {
02603 
02604     QString text;
02605 
02606     float bottomLeftPosX = m_midTopX - (m_fieldOfPlay.width/4);
02607     float bottomLeftPosY = m_midTopY + (m_fieldOfPlay.height/2);
02608 
02609     float topLeftPosX = m_midTopX - (m_fieldOfPlay.width/4);
02610     float topLeftPosY = m_midTopY + (m_fieldOfPlay.height/4);
02611 
02612     float topRightPosX = m_midTopX + (m_fieldOfPlay.width/8);
02613     float topRightPosY = m_midTopY + (m_fieldOfPlay.height/4);
02614 
02615     float bottomRightPosX = m_midTopX + (m_fieldOfPlay.width/8);
02616     float bottomRightPosY = m_midTopY + (m_fieldOfPlay.height/2);
02617 
02618     //m_text->setScreenSize(640,480);
02619 
02620     switch(m_whichStat)
02621     {
02622         case IMPACT_PERCENTAGE_DISTRIBUTION_VIEW:
02623         {
02624             switch(m_whichPlayer)
02625             {
02626                 case PLAYERA:
02627                 {
02628                     m_text->setColour(1,1,0);
02629                     switch(m_whichQuad)
02630                     {
02631                         case BOTTOM_LEFT:
02632                         {
02633                             text.sprintf("%3.2f %%",m_percentageABL);
02634                             m_text->renderText(bottomLeftPosX,bottomLeftPosY,text);//bl
02635                             break;
02636                         }
02637                         case TOP_LEFT:
02638                         {
02639                             text.sprintf("%3.2f %%",m_percentageATL);
02640                             m_text->renderText(topLeftPosX,topLeftPosY,text);//tl
02641                             break;
02642                         }
02643                         case TOP_RIGHT:
02644                         {
02645                             text.sprintf("%3.2f %%",m_percentageATR);
02646                             m_text->renderText(topRightPosX,topRightPosY,text);//tr
02647                             break;
02648                         }
02649                         case BOTTOM_RIGHT:
02650                         {
02651                             text.sprintf("%3.2f %%",m_percentageABR);
02652                             m_text->renderText(bottomRightPosX,bottomRightPosY,text);//br
02653                             break;
02654                         }
02655                         case ALL:
02656                         {
02657                             text.sprintf("%3.2f %%",m_percentageABL);
02658                             m_text->renderText(bottomLeftPosX,bottomLeftPosY,text);//bl
02659 
02660                             text.sprintf("%3.2f %%",m_percentageATL);
02661                             m_text->renderText(topLeftPosX,topLeftPosY,text);//tl
02662 
02663                             text.sprintf("%3.2f %%",m_percentageATR);
02664                             m_text->renderText(topRightPosX,topRightPosY,text);//tr
02665 
02666                             text.sprintf("%3.2f %%",m_percentageABR);
02667                             m_text->renderText(bottomRightPosX,bottomRightPosY,text);//br
02668 
02669                             break;
02670                         }
02671 
02672                     }
02673                     break;
02674                 }
02675 
02676             case PLAYERB:
02677             {
02678                 m_text->setColour(0,0,0);
02679                 switch(m_whichQuad)
02680                 {
02681                     case BOTTOM_LEFT:
02682                     {
02683                         text.sprintf("%3.2f %%",m_percentageBBL);
02684                         m_text->renderText(bottomLeftPosX,bottomLeftPosY,text);//bl
02685                         break;
02686                     }
02687                     case TOP_LEFT:
02688                     {
02689                         text.sprintf("%3.2f %%",m_percentageBTL);
02690                         m_text->renderText(topLeftPosX,topLeftPosY,text);//tl
02691                         break;
02692                     }
02693                     case TOP_RIGHT:
02694                     {
02695                         text.sprintf("%3.2f %%",m_percentageBTR);
02696                         m_text->renderText(topRightPosX,topRightPosY,text);//tr
02697                         break;
02698                     }
02699                     case BOTTOM_RIGHT:
02700                     {
02701                         text.sprintf("%3.2f %%",m_percentageBBR);
02702                         m_text->renderText(bottomRightPosX,bottomRightPosY,text);//br
02703                         break;
02704                     }
02705                     case ALL:
02706                     {
02707                         text.sprintf("%3.2f %%",m_percentageBBL);
02708                         m_text->renderText(bottomLeftPosX,bottomLeftPosY,text);//bl
02709 
02710                         text.sprintf("%3.2f %%",m_percentageBTL);
02711                         m_text->renderText(topLeftPosX,topLeftPosY,text);//tl
02712 
02713                         text.sprintf("%3.2f %%",m_percentageBTR);
02714                         m_text->renderText(topRightPosX,topRightPosY,text);//tr
02715 
02716                         text.sprintf("%3.2f %%",m_percentageBBR);
02717                         m_text->renderText(bottomRightPosX,bottomRightPosY,text);//br
02718                         break;
02719                     }
02720 
02721                 }
02722                 break;
02723             }
02724             case BOTH:
02725             {
02726                 switch(m_whichQuad)
02727                 {
02728                     case BOTTOM_LEFT:
02729                     {
02730                         m_text->setColour(1,1,0);
02731                         text.sprintf("(%3.0f / ",m_percentageABL);
02732                         m_text->renderText(bottomLeftPosX - 80,bottomLeftPosY,text);//bl
02733 
02734                         m_text->setColour(0,0,0);
02735                         text.sprintf("%3.0f)%%",m_percentageBBL);
02736                         m_text->renderText(bottomLeftPosX + 10,bottomLeftPosY,text);//bl
02737                         break;
02738                     }
02739                     case TOP_LEFT:
02740                     {
02741                         m_text->setColour(1,1,0);
02742                         text.sprintf("(%3.0f / ",m_percentageATL);
02743                         m_text->renderText(topLeftPosX - 80,topLeftPosY,text);//tl
02744 
02745                         m_text->setColour(0,0,0);
02746                         text.sprintf("%3.0f)%%",m_percentageBTL);
02747                         m_text->renderText(topLeftPosX + 10,topLeftPosY,text);//tl
02748                         break;
02749                     }
02750                     case TOP_RIGHT:
02751                     {
02752                        m_text->setColour(1,1,0);
02753                        text.sprintf("(%3.0f / ",m_percentageATR);
02754                        m_text->renderText(topRightPosX - 60,topRightPosY,text);//tr
02755 
02756                        m_text->setColour(0,0,0);
02757                        text.sprintf("%3.0f)%%",m_percentageBTR);
02758                        m_text->renderText(topRightPosX + 30,topRightPosY,text);//tr
02759 
02760                        break;
02761                     }
02762                     case BOTTOM_RIGHT:
02763                     {
02764                         m_text->setColour(1,1,0);
02765                         text.sprintf("(%3.0f / ",m_percentageABR);
02766                         m_text->renderText(bottomRightPosX - 60,bottomRightPosY,text);//br
02767 
02768                         m_text->setColour(0,0,0);
02769                         text.sprintf("%3.0f)%%",m_percentageBBR);
02770                         m_text->renderText(bottomRightPosX + 30,bottomRightPosY,text);//br
02771                         break;
02772                     }
02773                     case ALL:
02774                     {
02775                         m_text->setColour(1,1,0);
02776                         text.sprintf("(%3.0f / ",m_percentageABL);
02777                         m_text->renderText(bottomLeftPosX - 80,bottomLeftPosY,text);//bl
02778                         m_text->setColour(0,0,0);
02779                         text.sprintf("%3.0f)%%",m_percentageBBL);
02780                         m_text->renderText(bottomLeftPosX + 10,bottomLeftPosY,text);//bl
02781 
02782                         m_text->setColour(1,1,0);
02783                         text.sprintf("(%3.0f / ",m_percentageATL);
02784                         m_text->renderText(topLeftPosX - 80,topLeftPosY,text);//tl
02785                         m_text->setColour(0,0,0);
02786                         text.sprintf("%3.0f)%%",m_percentageBTL);
02787                         m_text->renderText(topLeftPosX + 10,topLeftPosY,text);//tl
02788 
02789                         m_text->setColour(1,1,0);
02790                         text.sprintf("(%3.0f / ",m_percentageATR);
02791                         m_text->renderText(topRightPosX - 60,topRightPosY,text);//tr
02792                         m_text->setColour(0,0,0);
02793                         text.sprintf("%3.0f)%%",m_percentageBTR);
02794                         m_text->renderText(topRightPosX + 30,topRightPosY,text);//tr
02795 
02796                         m_text->setColour(1,1,0);
02797                         text.sprintf("(%3.0f / ",m_percentageABR);
02798                         m_text->renderText(bottomRightPosX - 60,bottomRightPosY,text);//br
02799                         m_text->setColour(0,0,0);
02800                         text.sprintf("%3.0f)%%",m_percentageBBR);
02801                         m_text->renderText(bottomRightPosX + 30,bottomRightPosY,text);//br
02802 
02803                         break;
02804                     }
02805 
02806                 }
02807                 break;
02808             }
02809 
02810             }
02811             break;
02812         }
02813 
02814         default:
02815             break;
02816     }
02817 
02818     // this has to be done at the end to avoid 3d stats rendering in black
02819     // ngl text has something which makes other shaders work only when ngl
02820     // text color is set to white before using other shaders
02821     m_text->setColour(1,1,1);
02822 }
02823 
02824 //--------------------------------------------------
02825 /* ALL MOUSE EVENTS SHOULD ONLY WORK IN 3D....so place the parentvar check before processing any mouse events*/
02826 //--------------------------------------------------
02827 
02828 
02829 //----------------------------------------------------------------------------------------------------------------------
02830 void StatsVisualization::mouseMoveEvent (
02831                                QMouseEvent * _event
02832                               )
02833 {
02834   // note the method buttons() is the button state when event was called
02835   // this is different from button() which is used to check which button was
02836   // pressed when the mousePress/Release event is generated
02837   if(m_rotate && _event->buttons() == Qt::LeftButton)
02838   {
02839     int diffx=_event->x()-m_origX;
02840     int diffy=_event->y()-m_origY;
02841     m_spinXFace += (float) 0.5f * diffy;
02842     m_spinYFace += (float) 0.5f * diffx;
02843     m_origX = _event->x();
02844     m_origY = _event->y();
02845     updateGL();
02846 
02847   }
02848   // right mouse translate code
02849   else if(m_translate && _event->buttons() == Qt::RightButton)
02850   {
02851     int diffX = (int)(_event->x() - m_origXPos);
02852     int diffY = (int)(_event->y() - m_origYPos);
02853     m_origXPos=_event->x();
02854     m_origYPos=_event->y();
02855     m_modelPos.m_x += INCREMENT * diffX;
02856     m_modelPos.m_y -= INCREMENT * diffY;
02857     updateGL();
02858 
02859   }
02860 
02861 }
02862 
02863 
02864 //----------------------------------------------------------------------------------------------------------------------
02865 void StatsVisualization::mousePressEvent (
02866                                 QMouseEvent * _event
02867                                )
02868 {
02869   // this method is called when the mouse button is pressed in this case we
02870   // store the value where the maouse was clicked (x,y) and set the Rotate flag to true
02871   if(_event->button() == Qt::LeftButton)
02872   {
02873     m_origX = _event->x();
02874     m_origY = _event->y();
02875     m_rotate =true;
02876   }
02877   // right mouse translate mode
02878   else if(_event->button() == Qt::RightButton)
02879   {
02880     m_origXPos = _event->x();
02881     m_origYPos = _event->y();
02882     m_translate=true;
02883   }
02884 
02885 }
02886 
02887 //----------------------------------------------------------------------------------------------------------------------
02888 void StatsVisualization::mouseReleaseEvent (
02889                                   QMouseEvent * _event
02890                                  )
02891 {
02892   // this event is called when the mouse button is released
02893   // we then set Rotate to false
02894   if (_event->button() == Qt::LeftButton)
02895   {
02896     m_rotate=false;
02897   }
02898   // right mouse translate mode
02899   if (_event->button() == Qt::RightButton)
02900   {
02901     m_translate=false;
02902   }
02903 }
02904 
02905 //----------------------------------------------------------------------------------------------------------------------
02906 void StatsVisualization::wheelEvent(QWheelEvent *_event)
02907 {
02908 
02909   // check the diff of the wheel position (0 means no change)
02910   if(_event->delta() > 0)
02911   {
02912     m_modelPos.m_z+=ZOOM;
02913   }
02914   else if(_event->delta() <0 )
02915   {
02916     m_modelPos.m_z-=ZOOM;
02917   }
02918   updateGL();
02919 }
02920 
02921 
02922 void StatsVisualization::legendWindow(GLuint _inputLegendName)
02923 {
02924     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
02925     (*shader)["TextureShaderStats"]->use();
02926     // need to bind the active texture before drawing
02927     glBindTexture(GL_TEXTURE_2D,_inputLegendName);
02928 
02929     ngl::Transformation trans;
02930 
02931      // get the VBO instance and draw the built in teapot
02932     ngl::VAOPrimitives *prim=ngl::VAOPrimitives::instance();
02933 
02934     // we will create separate planes and spheres for various statistics instead of
02935     // trying to scale them each time as we have different units of scaling and
02936     // those scale factors are calculated at various times
02937     // and this is much easier than that even though it takes quite a bit of memory
02938     prim->createTrianglePlane("legendplane",0.8,0.8,1,1,ngl::Vec3(0,1,0));
02939 
02940     // first draw a top  persp // front //side
02941     ngl::Vec3 from(0,2,0);
02942     ngl::Vec3 to(0,0,0);
02943     ngl::Vec3 up(0,0,-1);
02945     m_transformStack.pushTransform();
02946     {
02947       from.set(0,0,2);
02948       up.set(0,1,0);
02949       m_view=ngl::lookAt(from,to,up);
02950       m_projection=ngl::ortho(-1,1,-1,1, 0.01f, 200.0f);
02951 
02952       glViewport(10,10,m_legendWidth,m_legendHeight);
02953       //m_2DScreen->draw();
02954 
02955       m_transformStack.setGlobal(trans);
02956       m_transformStack.setRotation(90,180,180);
02957       m_transformStack.setPosition(0,0,0);
02958       //m_transformStack.setScale(m_legendWidth,m_legendHeight,0);
02959       //loadMatricesToTextureShader();
02960       loadMatricesToLegendShader();
02961       prim->draw("legendplane");
02962 
02963     }
02964     m_transformStack.popTransform();
02965 
02966 }
02967 
02968 void StatsVisualization::loadMatricesToLegendShader()
02969 {
02970     ngl::ShaderLib *shader=ngl::ShaderLib::instance();
02971     ngl::Mat4 MVP;
02972     ngl::Mat4 MV;
02973     ngl::Mat4 M;
02974     M=m_transformStack.getCurrAndGlobal().getMatrix();
02975     MV=  m_transformStack.getCurrAndGlobal().getMatrix()*m_view;
02976     MVP= M*m_view*m_projection;
02977     shader->setShaderParamFromMat4("MVP",MVP);
02978     shader->setUniform("textureFlag",true);
02979 
02980 }
02981 
 All Classes Files Functions Variables Enumerations Enumerator