Facebook
From Sharp Flamingo, 3 Years ago, written in C++.
Embed
Download Paste or View Raw
Hits: 59
  1. /************************************************************************
  2.      File:        TrainView.cpp
  3.  
  4.      Author:    
  5.                   Michael Gleicher, [email protected]
  6.  
  7.      Modifier
  8.                   Yu-Chi Lai, [email protected]
  9.      
  10.      Comment:    
  11.                                                 The TrainView is the window that actually shows the
  12.                                                 train. Its a
  13.                                                 GL display canvas (Fl_Gl_Window).  It is held within
  14.                                                 a TrainWindow
  15.                                                 that is the outer window with all the widgets.
  16.                                                 The TrainView needs
  17.                                                 to be aware of the window - since it might need to
  18.                                                 check the widgets to see how to draw
  19.  
  20.           Note:        we need to have pointers to this, but maybe not know
  21.                                                 about it (beware circular references)
  22.  
  23.      Platform:    Visio Studio.Net 2003/2005
  24.  
  25. *************************************************************************/
  26.  
  27. #include <iostream>
  28. #include <Fl/fl.h>
  29.  
  30. // we will need OpenGL, and OpenGL needs windows.h
  31. #include <windows.h>
  32. //#include "GL/gl.h"
  33. #include <glad/glad.h>
  34. #include <glm/glm.hpp>
  35. #include "GL/glu.h"
  36.  
  37. #include "TrainView.H"
  38. #include "TrainWindow.H"
  39. #include "Utilities/3DUtils.H"
  40. #include<iostream>
  41. using namespace std;
  42.  
  43. #ifdef EXAMPLE_SOLUTION
  44. #       include "TrainExample/TrainExample.H"
  45. #endif
  46.  
  47.  
  48. //************************************************************************
  49. //
  50. // * Constructor to set up the GL window
  51. //========================================================================
  52. TrainView::
  53. TrainView(int x, int y, int w, int h, const char* l)
  54.         : Fl_Gl_Window(x,y,w,h,l)
  55. //========================================================================
  56. {
  57.         mode( FL_RGB|FL_ALPHA|FL_DOUBLE | FL_STENCIL );
  58.  
  59.         resetArcball();
  60. }
  61.  
  62. //************************************************************************
  63. //
  64. // * Reset the camera to look at the world
  65. //========================================================================
  66. void TrainView::
  67. resetArcball()
  68. //========================================================================
  69. {
  70.         // Set up the camera to look at the world
  71.         // these parameters might seem magical, and they kindof are
  72.         // a little trial and error goes a long way
  73.         arcball.setup(this, 40, 250, .2f, .4f, 0);
  74. }
  75.  
  76. //************************************************************************
  77. //
  78. // * FlTk Event handler for the window
  79. //########################################################################
  80. // TODO:
  81. //       if you want to make the train respond to other events
  82. //       (like key presses), you might want to hack this.
  83. //########################################################################
  84. //========================================================================
  85. int TrainView::handle(int event)
  86. {
  87.         // see if the ArcBall will handle the event - if it does,
  88.         // then we're done
  89.         // note: the arcball only gets the event if we're in world view
  90.         if (tw->worldCam->value())
  91.                 if (arcball.handle(event))
  92.                         return 1;
  93.  
  94.         // remember what button was used
  95.         static int last_push;
  96.  
  97.         switch(event) {
  98.                 // Mouse button being pushed event
  99.                 case FL_PUSH:
  100.                         last_push = Fl::event_button();
  101.                         // if the left button be pushed is left mouse button
  102.                         if (last_push == FL_LEFT_MOUSE  ) {
  103.                                 doPick();
  104.                                 damage(1);
  105.                                 return 1;
  106.                         };
  107.                         break;
  108.  
  109.            // Mouse button release event
  110.                 case FL_RELEASE: // button release
  111.                         damage(1);
  112.                         last_push = 0;
  113.                         return 1;
  114.  
  115.                 // Mouse button drag event
  116.                 case FL_DRAG:
  117.  
  118.                         // Compute the new control point position
  119.                         if ((last_push == FL_LEFT_MOUSE) && (selectedCube >= 0)) {
  120.                                 ControlPoint* cp = &m_pTrack->points[selectedCube];
  121.  
  122.                                 double r1x, r1y, r1z, r2x, r2y, r2z;
  123.                                 getMouseLine(r1x, r1y, r1z, r2x, r2y, r2z);
  124.  
  125.                                 double rx, ry, rz;
  126.                                 mousePoleGo(r1x, r1y, r1z, r2x, r2y, r2z,
  127.                                                                 static_cast<double>(cp->pos.x),
  128.                                                                 static_cast<double>(cp->pos.y),
  129.                                                                 static_cast<double>(cp->pos.z),
  130.                                                                 rx, ry, rz,
  131.                                                                 (Fl::event_state() & FL_CTRL) != 0);
  132.  
  133.                                 cp->pos.x = (float) rx;
  134.                                 cp->pos.y = (float) ry;
  135.                                 cp->pos.z = (float) rz;
  136.                                 damage(1);
  137.                         }
  138.                         break;
  139.  
  140.                 // in order to get keyboard events, we need to accept focus
  141.                 case FL_FOCUS:
  142.                         return 1;
  143.  
  144.                 // every time the mouse enters this window, aggressively take focus
  145.                 case FL_ENTER: 
  146.                         focus(this);
  147.                         break;
  148.  
  149.                 case FL_KEYBOARD:
  150.                                 int k = Fl::event_key();
  151.                                 int ks = Fl::event_state();
  152.                                 if (k == 'p') {
  153.                                         // Print out the selected control point information
  154.                                         if (selectedCube >= 0)
  155.                                                 printf("Selected(%d) (%g %g %g) (%g %g %g)\n",
  156.                                                                  selectedCube,
  157.                                                                  m_pTrack->points[selectedCube].pos.x,
  158.                                                                  m_pTrack->points[selectedCube].pos.y,
  159.                                                                  m_pTrack->points[selectedCube].pos.z,
  160.                                                                  m_pTrack->points[selectedCube].orient.x,
  161.                                                                  m_pTrack->points[selectedCube].orient.y,
  162.                                                                  m_pTrack->points[selectedCube].orient.z);
  163.                                         else
  164.                                                 printf("Nothing Selected\n");
  165.  
  166.                                         return 1;
  167.                                 };
  168.                                 break;
  169.         }
  170.  
  171.         return Fl_Gl_Window::handle(event);
  172. }
  173.  
  174. //************************************************************************
  175. //
  176. // * this is the code that actually draws the window
  177. //   it puts a lot of the work into other routines to simplify things
  178. //========================================================================
  179. void TrainView::draw()
  180. {
  181.  
  182.         //*********************************************************************
  183.         //
  184.         // * Set up basic opengl informaiton
  185.         //
  186.         //**********************************************************************
  187.         //initialized glad
  188.         if (gladLoadGL())
  189.         {
  190.                 //initiailize VAO, VBO, Shader...
  191.         }
  192.         else
  193.                 throw std::runtime_error("Could not initialize GLAD!");
  194.  
  195.         // Set up the view port
  196.         glViewport(0,0,w(),h());
  197.  
  198.         // clear the window, be sure to clear the Z-Buffer too
  199.         glClearColor(0,0,.3f,0);                // background should be blue
  200.  
  201.         // we need to clear out the stencil buffer since we'll use
  202.         // it for shadows
  203.         glClearStencil(0);
  204.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  205.         glEnable(GL_DEPTH);
  206.  
  207.         // Blayne prefers GL_DIFFUSE
  208.     glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  209.  
  210.         // prepare for projection
  211.         glMatrixMode(GL_PROJECTION);
  212.         glLoadIdentity();
  213.         setProjection();                // put the code to set up matrices here
  214.  
  215.         //######################################################################
  216.         // TODO:
  217.         // you might want to set the lighting up differently. if you do,
  218.         // we need to set up the lights AFTER setting up the projection
  219.         //######################################################################
  220.         // enable the lighting
  221.         glEnable(GL_COLOR_MATERIAL);
  222.         glEnable(GL_DEPTH_TEST);
  223.         glEnable(GL_LIGHTING);
  224.         glEnable(GL_LIGHT0);
  225.  
  226.         // top view only needs one light
  227.         if (tw->topCam->value()) {
  228.                 glDisable(GL_LIGHT1);
  229.                 glDisable(GL_LIGHT2);
  230.         } else {
  231.                 glEnable(GL_LIGHT1);
  232.                 glEnable(GL_LIGHT2);
  233.         }
  234.  
  235.         //*********************************************************************
  236.         //
  237.         // * set the light parameters
  238.         //
  239.         //**********************************************************************
  240.         GLfloat lightPosition1[]        = {0,1,1,0}; // {50, 200.0, 50, 1.0};
  241.         GLfloat lightPosition2[]        = {1, 0, 0, 0};
  242.         GLfloat lightPosition3[]        = {0, -1, 0, 0};
  243.         GLfloat yellowLight[]           = {0.5f, 0.5f, .1f, 1.0};
  244.         GLfloat whiteLight[]                    = {1.0f, 1.0f, 1.0f, 1.0};
  245.         GLfloat blueLight[]                     = {.1f,.1f,.3f,1.0};
  246.         GLfloat grayLight[]                     = {.3f, .3f, .3f, 1.0};
  247.  
  248.         glLightfv(GL_LIGHT0, GL_POSITION, lightPosition1);
  249.         glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteLight);
  250.         glLightfv(GL_LIGHT0, GL_AMBIENT, grayLight);
  251.  
  252.         glLightfv(GL_LIGHT1, GL_POSITION, lightPosition2);
  253.         glLightfv(GL_LIGHT1, GL_DIFFUSE, yellowLight);
  254.  
  255.         glLightfv(GL_LIGHT2, GL_POSITION, lightPosition3);
  256.         glLightfv(GL_LIGHT2, GL_DIFFUSE, blueLight);
  257.  
  258.  
  259.  
  260.         //*********************************************************************
  261.         // now draw the ground plane
  262.         //*********************************************************************
  263.         // set to opengl fixed pipeline(use opengl 1.x draw function)
  264.         glUseProgram(0);
  265.  
  266.         setupFloor();
  267.         glDisable(GL_LIGHTING);
  268.         drawFloor(200,10);
  269.  
  270.  
  271.         //*********************************************************************
  272.         // now draw the object and we need to do it twice
  273.         // once for real, and then once for shadows
  274.         //*********************************************************************
  275.         glEnable(GL_LIGHTING);
  276.         setupObjects();
  277.  
  278.         drawStuff();
  279.  
  280.         // this time drawing is for shadows (except for top view)
  281.         if (!tw->topCam->value()) {
  282.                 setupShadows();
  283.                 drawStuff(true);
  284.                 unsetupShadows();
  285.         }
  286. }
  287.  
  288. //************************************************************************
  289. //
  290. // * This sets up both the Projection and the ModelView matrices
  291. //   HOWEVER: it doesn't clear the projection first (the caller handles
  292. //   that) - its important for picking
  293. //========================================================================
  294. void TrainView::
  295. setProjection()
  296. //========================================================================
  297. {
  298.         // Compute the aspect ratio (we'll need it)
  299.         float aspect = static_cast<float>(w()) / static_cast<float>(h());
  300.  
  301.         // Check whether we use the world camp
  302.         if (tw->worldCam->value())
  303.                 arcball.setProjection(false);
  304.         // Or we use the top cam
  305.         else if (tw->topCam->value()) {
  306.                 float wi, he;
  307.                 if (aspect >= 1) {
  308.                         wi = 110;
  309.                         he = wi / aspect;
  310.                 }
  311.                 else {
  312.                         he = 110;
  313.                         wi = he * aspect;
  314.                 }
  315.  
  316.                 // Set up the top camera drop mode to be orthogonal and set
  317.                 // up proper projection matrix
  318.                 glMatrixMode(GL_PROJECTION);
  319.                 glOrtho(-wi, wi, -he, he, 200, -200);
  320.                 glMatrixMode(GL_MODELVIEW);
  321.                 glLoadIdentity();
  322.                 glRotatef(-90,1,0,0);
  323.         }
  324.         // Or do the train view or other view here
  325.         //####################################################################
  326.         // TODO:
  327.         // put code for train view projection here!    
  328.         //####################################################################
  329.         else {
  330. #ifdef EXAMPLE_SOLUTION
  331.                 trainCamView(this,aspect);
  332. #endif
  333.         }
  334. }
  335. //************************************************************************
  336. //
  337. // * this draws all of the stuff in the world
  338. //
  339. //      NOTE: if you're drawing shadows, DO NOT set colors (otherwise, you get
  340. //       colored shadows). this gets called twice per draw
  341. //       -- once for the objects, once for the shadows
  342. //########################################################################
  343. // TODO:
  344. // if you have other objects in the world, make sure to draw them
  345. //########################################################################
  346. //========================================================================
  347. void TrainView::drawStuff(bool doingShadows)
  348. {
  349.         // Draw the control points
  350.         // don't draw the control points if you're driving
  351.         // (otherwise you get sea-sick as you drive through them)
  352.         if (!tw->trainCam->value()) {
  353.                 for (size_t i = 0; i < m_pTrack->points.size(); ++i) {
  354.                         if (!doingShadows) {
  355.                                 if (((int)i) != selectedCube)
  356.                                         glColor3ub(240, 60, 60);
  357.                                 else
  358.                                         glColor3ub(240, 240, 30);
  359.                         }
  360.                         m_pTrack->points[i].draw();
  361.                 }
  362.         }
  363.         // draw the track
  364.         //####################################################################
  365.         // TODO:
  366.         // call your own track drawing code
  367.         //####################################################################
  368.         drawTrack(this, doingShadows);
  369.         // draw the train
  370.         //####################################################################
  371.         // TODO:
  372.         //      call your own train drawing code
  373.         //####################################################################
  374.         //if (!tw->trainCam->value())
  375.                 //drawTrain(this, doingShadows);
  376. }
  377.  
  378. //
  379. //************************************************************************
  380. //
  381. // * this tries to see which control point is under the mouse
  382. //        (for when the mouse is clicked)
  383. //              it uses OpenGL picking - which is always a trick
  384. //########################################################################
  385. // TODO:
  386. //              if you want to pick things other than control points, or you
  387. //              changed how control points are drawn, you might need to change this
  388. //########################################################################
  389. //========================================================================
  390. void TrainView::drawTrack(TrainView* TrainV, bool doingShadows) {
  391.         if (TrainV->tw->splineBrowser->value() == 1) {
  392.                 float DIVIDE_LINE = 20;
  393.                 for (size_t i = 0; i < m_pTrack->points.size(); i++) {
  394.                         // pos
  395.                         Pnt3f cp_pos_p1 = m_pTrack->points[i].pos;
  396.                         Pnt3f cp_pos_p2 = m_pTrack->points[(i + 1) % m_pTrack->points.size()].pos;
  397.                         // orient
  398.                         Pnt3f cp_orient_p1 = m_pTrack->points[i].orient;
  399.                         Pnt3f cp_orient_p2 = m_pTrack->points[(i + 1) % m_pTrack->points.size()].orient;
  400.                         float percent = 1.0f / DIVIDE_LINE;
  401.                         float t = 0;
  402.                         Pnt3f qt = (1 - t) * cp_pos_p1 + t * cp_pos_p2;
  403.                         for (size_t j = 0; j < DIVIDE_LINE; j++) {
  404.                                 Pnt3f qt0 = qt;
  405.                                 t += percent;
  406.                                 qt = (1 - t) * cp_pos_p1 + t * cp_pos_p2;
  407.                                 Pnt3f qt1 = qt;
  408.                                 Pnt3f orient_t = (1 - t) * cp_orient_p1 + t * cp_orient_p2;
  409.                                 orient_t.normalize();
  410.                                 Pnt3f cross_t = (qt1 - qt0) * orient_t;
  411.                                 cross_t.normalize();
  412.                                 cross_t = cross_t * 2.5f;
  413.                                 if (!doingShadows) {
  414.                                         glColor3ub(77, 19, 0);
  415.                                 }
  416.                                 glBegin(GL_LINES);
  417.                                 glVertex3f(qt0.x + cross_t.x, qt0.y + cross_t.y, qt0.z + cross_t.z);
  418.                                 glVertex3f(qt1.x + cross_t.x, qt1.y + cross_t.y, qt1.z + cross_t.z);
  419.                                 glVertex3f(qt0.x - cross_t.x, qt0.y - cross_t.y, qt0.z - cross_t.z);
  420.                                 glVertex3f(qt1.x - cross_t.x, qt1.y - cross_t.y, qt1.z - cross_t.z);
  421.                                 glEnd();
  422.                                 glLineWidth(1);
  423.                                 if (j % 2 == 0) {
  424.                                         if (!doingShadows) {
  425.                                                 glColor3ub(153, 102, 51);
  426.                                         }
  427.                                         glBegin(GL_QUADS);
  428.                                         glVertex3f(qt0.x + cross_t.x, qt0.y + cross_t.y, qt0.z + cross_t.z);
  429.                                         glVertex3f(qt1.x + cross_t.x, qt1.y + cross_t.y, qt1.z + cross_t.z);
  430.                                         glVertex3f(qt1.x - cross_t.x, qt1.y + cross_t.y, qt1.z - cross_t.z);
  431.                                         glVertex3f(qt0.x - cross_t.x, qt0.y + cross_t.y, qt0.z - cross_t.z);
  432.                                         glEnd();
  433.                                 }
  434.                         }
  435.                 }
  436.         }
  437.         else if (TrainV->tw->splineBrowser->value() == 2) {
  438.                 float DIVIDE_LINE = 20;
  439.                 for (size_t i = 0; i < m_pTrack->points.size(); i++) {
  440.                         // pos
  441.                         Pnt3f cp_pos_p1 = m_pTrack->points[(i - 1 + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  442.                         Pnt3f cp_pos_p2 = m_pTrack->points[(i + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  443.                         Pnt3f cp_pos_p3 = m_pTrack->points[(i + 1 + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  444.                         Pnt3f cp_pos_p4 = m_pTrack->points[(i + 2 + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  445.                         // orient
  446.                         Pnt3f cp_orient_p1 = m_pTrack->points[(i - 1 + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  447.                         Pnt3f cp_orient_p2 = m_pTrack->points[(i + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  448.                         Pnt3f cp_orient_p3 = m_pTrack->points[(i + 1 + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  449.                         Pnt3f cp_orient_p4 = m_pTrack->points[(i + 2 + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  450.                         glm::mat4x4 P = {
  451.                                 {cp_pos_p1.x,cp_pos_p1.y,cp_pos_p1.z,1},
  452.                                 {cp_pos_p2.x,cp_pos_p2.y,cp_pos_p2.z,1},
  453.                                 {cp_pos_p3.x,cp_pos_p3.y,cp_pos_p3.z,1},
  454.                                 {cp_pos_p4.x,cp_pos_p4.y,cp_pos_p4.z,1}
  455.                         };
  456.                         glm::mat4x4 O = {
  457.                                 {cp_orient_p1.x,cp_orient_p1.y,cp_orient_p1.z,1},
  458.                                 {cp_orient_p2.x,cp_orient_p2.y,cp_orient_p2.z,1},
  459.                                 {cp_orient_p3.x,cp_orient_p3.y,cp_orient_p3.z,1},
  460.                                 {cp_orient_p4.x,cp_orient_p4.y,cp_orient_p4.z,1}
  461.                         };
  462.                         /*glm::mat4x4 M = {
  463.                                 {-1.0f,3.0f,-3.0f,1.0f},
  464.                                 {3.0f,-6.0f,0.0f,4.0f},
  465.                                 {-3.0f,3.0f,3.0f,1.0f},
  466.                                 {1.0f,0.0f,0.0f,0.0f}
  467.                         };*/
  468.                         glm::mat4x4 M = {
  469.                                 {-1.0f,3.0f,-3.0f,1.0f},
  470.                                 {2.0f,-5.0f,4.0f,-1.0f},
  471.                                 {-1.0f,0.0f,1.0f,0.0f},
  472.                                 {0.0f,2.0f,0.0f,0.0f}
  473.                         };
  474.                         M /= 2;
  475.                         float percent = 1.0f / DIVIDE_LINE;
  476.                         float t = 0;
  477.                         for (size_t j = 0; j < DIVIDE_LINE; j++) {
  478.                                 glm::vec4 T0 = { pow(t,3),pow(t,2),t,1 };
  479.                                 glm::vec4 qtemp = P * M * T0;
  480.                                 glm::vec4 ot0 = O * M * T0;
  481.                                 Pnt3f qt0(qtemp[0], qtemp[1], qtemp[2]);
  482.                                 t += percent;
  483.                                 glm::vec4 T1 = { pow(t,3),pow(t,2),t,1 };
  484.                                 qtemp = P * M * T1;
  485.                                 Pnt3f qt1(qtemp[0], qtemp[1], qtemp[2]);
  486.                                 Pnt3f orient_t(ot0[0], ot0[1], ot0[2]);
  487.                                 orient_t.normalize();
  488.                                 Pnt3f cross_t = (qt1 - qt0) * orient_t;
  489.                                 cross_t.normalize();
  490.                                 cross_t = cross_t * 2.5f;
  491.                                 if (!doingShadows) {
  492.                                         glColor3ub(77, 19, 0);
  493.                                 }
  494.                                 glBegin(GL_LINES);
  495.                                 glVertex3f(qt0.x + cross_t.x, qt0.y + cross_t.y, qt0.z + cross_t.z);
  496.                                 glVertex3f(qt1.x + cross_t.x, qt1.y + cross_t.y, qt1.z + cross_t.z);
  497.                                 glVertex3f(qt0.x - cross_t.x, qt0.y - cross_t.y, qt0.z - cross_t.z);
  498.                                 glVertex3f(qt1.x - cross_t.x, qt1.y - cross_t.y, qt1.z - cross_t.z);
  499.                                 glEnd();
  500.                                 glLineWidth(1);
  501.                                 if (j % 2 == 0) {
  502.                                         if (!doingShadows) {
  503.                                                 glColor3ub(153, 102, 51);
  504.                                         }
  505.                                         glBegin(GL_QUADS);
  506.                                         glVertex3f(qt0.x + cross_t.x, qt0.y + cross_t.y, qt0.z + cross_t.z);
  507.                                         glVertex3f(qt1.x + cross_t.x, qt1.y + cross_t.y, qt1.z + cross_t.z);
  508.                                         glVertex3f(qt1.x - cross_t.x, qt1.y + cross_t.y, qt1.z - cross_t.z);
  509.                                         glVertex3f(qt0.x - cross_t.x, qt0.y + cross_t.y, qt0.z - cross_t.z);
  510.                                         glEnd();
  511.                                 }
  512.                         }
  513.                 }
  514.         }
  515.         else if (TrainV->tw->splineBrowser->value() == 3) {
  516.                 float DIVIDE_LINE = 20;
  517.                 for (size_t i = 0; i < m_pTrack->points.size(); i++) {
  518.                         // pos
  519.                         Pnt3f cp_pos_p1 = m_pTrack->points[(i - 1 + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  520.                         Pnt3f cp_pos_p2 = m_pTrack->points[(i + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  521.                         Pnt3f cp_pos_p3 = m_pTrack->points[(i +1 + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  522.                         Pnt3f cp_pos_p4 = m_pTrack->points[(i +2 + m_pTrack->points.size()) % m_pTrack->points.size()].pos;
  523.                         // orient
  524.                         Pnt3f cp_orient_p1 = m_pTrack->points[(i -1 + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  525.                         Pnt3f cp_orient_p2 = m_pTrack->points[(i + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  526.                         Pnt3f cp_orient_p3 = m_pTrack->points[(i + 1 + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  527.                         Pnt3f cp_orient_p4 = m_pTrack->points[(i + 2 + m_pTrack->points.size()) % m_pTrack->points.size()].orient;
  528.                         glm::mat4x4 P = {
  529.                                 {cp_pos_p1.x,cp_pos_p1.y,cp_pos_p1.z,1},
  530.                                 {cp_pos_p2.x,cp_pos_p2.y,cp_pos_p2.z,1},
  531.                                 {cp_pos_p3.x,cp_pos_p3.y,cp_pos_p3.z,1},
  532.                                 {cp_pos_p4.x,cp_pos_p4.y,cp_pos_p4.z,1}
  533.                         };
  534.                         glm::mat4x4 O = {
  535.                                 {cp_orient_p1.x,cp_orient_p1.y,cp_orient_p1.z,1},
  536.                                 {cp_orient_p2.x,cp_orient_p2.y,cp_orient_p2.z,1},
  537.                                 {cp_orient_p3.x,cp_orient_p3.y,cp_orient_p3.z,1},
  538.                                 {cp_orient_p4.x,cp_orient_p4.y,cp_orient_p4.z,1}
  539.                         };
  540.                         glm::mat4x4 M = {
  541.                                 {-1.0f,3.0f,-3.0f,1.0f},
  542.                                 {3.0f,-6.0f,3.0f,0.0f},
  543.                                 {-3.0f,0.0f,3.0f,0.0f},
  544.                                 {1.0f,4.0f,1.0f,0.0f}
  545.                         };
  546.                         M /= 6;
  547.                         float percent = 1.0f / DIVIDE_LINE;
  548.                         float t = 0;
  549.                         for (size_t j = 0; j < DIVIDE_LINE; j++) {
  550.                                 glm::vec4 T0 = { pow(t,3),pow(t,2),t,1 };
  551.                                 glm::vec4 qtemp = P * M * T0;
  552.                                 glm::vec4 ot0 = O * M * T0;
  553.                                 Pnt3f qt0(qtemp[0], qtemp[1], qtemp[2]);
  554.                                 t += percent;
  555.                                 glm::vec4 T1 = { pow(t,3),pow(t,2),t,1 };
  556.                                 qtemp = P * M * T1;
  557.                                 Pnt3f qt1(qtemp[0] ,qtemp[1],qtemp[2]);
  558.                                 Pnt3f orient_t(ot0[0], ot0[1], ot0[2]);
  559.                                 orient_t.normalize();
  560.                                 Pnt3f cross_t = (qt1 - qt0) * orient_t;
  561.                                 cross_t.normalize();
  562.                                 cross_t = cross_t * 2.5f;
  563.                                 if (!doingShadows) {
  564.                                         glColor3ub(77, 19, 0);
  565.                                 }
  566.                                 glBegin(GL_LINES);
  567.                                 glVertex3f(qt0.x + cross_t.x, qt0.y + cross_t.y, qt0.z + cross_t.z);
  568.                                 glVertex3f(qt1.x + cross_t.x, qt1.y + cross_t.y, qt1.z + cross_t.z);
  569.                                 glVertex3f(qt0.x - cross_t.x, qt0.y - cross_t.y, qt0.z - cross_t.z);
  570.                                 glVertex3f(qt1.x - cross_t.x, qt1.y - cross_t.y, qt1.z - cross_t.z);
  571.                                 glEnd();
  572.                                 glLineWidth(1);
  573.                                 if (j % 2 == 0) {
  574.                                         if (!doingShadows) {
  575.                                                 glColor3ub(153, 102, 51);
  576.                                         }
  577.                                         glBegin(GL_QUADS);
  578.                                         glVertex3f(qt0.x + cross_t.x, qt0.y + cross_t.y, qt0.z + cross_t.z);
  579.                                         glVertex3f(qt1.x + cross_t.x, qt1.y + cross_t.y, qt1.z + cross_t.z);
  580.                                         glVertex3f(qt1.x - cross_t.x, qt1.y + cross_t.y, qt1.z - cross_t.z);
  581.                                         glVertex3f(qt0.x - cross_t.x, qt0.y + cross_t.y, qt0.z - cross_t.z);
  582.                                         glEnd();
  583.                                 }
  584.                         }
  585.                 }
  586.         }
  587. }
  588.  
  589. //void TrainView::drawTrain(TrainView* train, bool doingShadows) {
  590. //}
  591.  
  592. void TrainView::
  593. doPick()
  594. //========================================================================
  595. {
  596.         // since we'll need to do some GL stuff so we make this window as
  597.         // active window
  598.         make_current();        
  599.  
  600.         // where is the mouse?
  601.         int mx = Fl::event_x();
  602.         int my = Fl::event_y();
  603.  
  604.         // get the viewport - most reliable way to turn mouse coords into GL coords
  605.         int viewport[4];
  606.         glGetIntegerv(GL_VIEWPORT, viewport);
  607.  
  608.         // Set up the pick matrix on the stack - remember, FlTk is
  609.         // upside down!
  610.         glMatrixMode(GL_PROJECTION);
  611.         glLoadIdentity ();
  612.         gluPickMatrix((double)mx, (double)(viewport[3]-my),
  613.                                                 5, 5, viewport);
  614.  
  615.         // now set up the projection
  616.         setProjection();
  617.  
  618.         // now draw the objects - but really only see what we hit
  619.         GLuint buf[100];
  620.         glSelectBuffer(100,buf);
  621.         glRenderMode(GL_SELECT);
  622.         glInitNames();
  623.         glPushName(0);
  624.  
  625.         // draw the cubes, loading the names as we go
  626.         for(size_t i=0; i<m_pTrack->points.size(); ++i) {
  627.                 glLoadName((GLuint) (i+1));
  628.                 m_pTrack->points[i].draw();
  629.         }
  630.  
  631.         // go back to drawing mode, and see how picking did
  632.         int hits = glRenderMode(GL_RENDER);
  633.         if (hits) {
  634.                 // warning; this just grabs the first object hit - if there
  635.                 // are multiple objects, you really want to pick the closest
  636.                 // one - see the OpenGL manual
  637.                 // remember: we load names that are one more than the index
  638.                 selectedCube = buf[3]-1;
  639.         } else // nothing hit, nothing selected
  640.                 selectedCube = -1;
  641.  
  642.         printf("Selected Cube %d\n",selectedCube);
  643. }