]> git.mxchange.org Git - flightgear.git/blobdiff - src/Model/panelnode.cxx
Compile with MSVC10
[flightgear.git] / src / Model / panelnode.cxx
index b257a3bee2884fe1828ff07a8fd32d5c202b2089..be6889fda55d048d80e0a63044be888fcfbb5d82 100644 (file)
@@ -3,31 +3,36 @@
 #endif
 
 #include <simgear/compiler.h>
-#include <vector>
+#include <simgear/structure/exception.hxx>
 
-#include <GL/gl.h>
-#include <plib/sg.h>
+#include <vector>
 
-#include <Main/fg_props.hxx>
 #include <Cockpit/panel.hxx>
 #include <Cockpit/panel_io.hxx>
 #include "panelnode.hxx"
 
-// Static (!) handling for all 3D panels in the program.  Very
-// clumsy.  Replace with per-aircraft handling.
+using std::vector;
+
+
+// Static (!) handling for all 3D panels in the program.
+// OSGFIXME: Put the panel as different elements in the scenegraph.
+// Then just pick in that scenegraph.
 vector<FGPanelNode*> all_3d_panels;
-bool fgHandle3DPanelMouseEvent(int button, int updown, int x, int y)
+bool fgHandle3DPanelMouseEvent( int button, int updown, int x, int y )
 {
-    for(int i=0; i<all_3d_panels.size(); i++)
-        if(all_3d_panels[i]->doMouseAction(button, updown, x, y))
+    for ( unsigned int i = 0; i < all_3d_panels.size(); i++ ) {
+        if ( all_3d_panels[i]->doMouseAction(button, updown, x, y) ) {
             return true;
+        }
+    }
     return false;
 }
 
 void fgUpdate3DPanels()
 {
-    for(int i=0; i<all_3d_panels.size(); i++)
+    for ( unsigned int i = 0; i < all_3d_panels.size(); i++ ) {
         all_3d_panels[i]->getPanel()->updateMouseDelay();
+    }
 }
 
 FGPanelNode::FGPanelNode(SGPropertyNode* props)
@@ -36,19 +41,18 @@ FGPanelNode::FGPanelNode(SGPropertyNode* props)
 
     // Make an FGPanel object.  But *don't* call init() or bind() on
     // it -- those methods touch static state.
-    _panel = fgReadPanel(props->getStringValue("path"));
+    const char *path = props->getStringValue("path");
+    _panel = fgReadPanel(path);
+    if (!_panel)
+        throw sg_io_exception(string("Failed to load panel ") + path);
 
     // Never mind.  We *have* to call init to make sure the static
     // state is initialized (it's not, if there aren't any 2D
     // panels).  This is a memory leak and should be fixed!`
+    // FIXME
     _panel->init();
 
-    // Initialize the matrices to the identity.  PLib prints warnings
-    // when trying to invert singular matrices (e.g. when not using a
-    // 3D panel).
-    for(i=0; i<4; i++)
-        for(int j=0; j<4; j++)
-            _lastModelview[4*i+j] = _lastProjection[4*i+j] = i==j ? 1 : 0;
+    _panel->setDepthTest( props->getBoolValue("depth-test") );
 
     // Read out the pixel-space info
     _xmax = _panel->getWidth();
@@ -74,44 +78,43 @@ FGPanelNode::FGPanelNode(SGPropertyNode* props)
     // "a", "b", and "c" as our corners and "m" as the matrix. The
     // vector u goes from a to b, v from a to c, and w is a
     // perpendicular cross product.
-    float *a = _bottomLeft, *b = _bottomRight, *c = _topLeft, *m = _xform;
-    float u[3], v[3], w[3];
-    for(i=0; i<3; i++) u[i] = b[i] - a[i]; // U = B - A
-    for(i=0; i<3; i++) v[i] = c[i] - a[i]; // V = C - A
-
-    w[0] = u[1]*v[2] - v[1]*u[2];          // W = U x V
-    w[1] = u[2]*v[0] - v[2]*u[0];
-    w[2] = u[0]*v[1] - v[0]*u[1];
-
+    osg::Vec3 a = _bottomLeft;
+    osg::Vec3 b = _bottomRight;
+    osg::Vec3 c = _topLeft;
+    osg::Vec3 u = b - a;
+    osg::Vec3 v = c - a;
+    osg::Vec3 w = u^v;
+
+    osg::Matrix& m = _xform;
     // Now generate a trivial basis transformation matrix.  If we want
     // to map the three unit vectors to three arbitrary vectors U, V,
     // and W, then those just become the columns of the 3x3 matrix.
-    m[0] = u[0]; m[4] = v[0]; m[8]  = w[0]; m[12] = a[0]; //     |Ux Vx Wx|
-    m[1] = u[1]; m[5] = v[1]; m[9]  = w[1]; m[13] = a[1]; // m = |Uy Vy Wy|
-    m[2] = u[2]; m[6] = v[2]; m[10] = w[2]; m[14] = a[2]; //     |Uz Vz Wz|
-    m[3] = 0;    m[7] = 0;    m[11] = 0;    m[15] = 1;
+    m(0,0) = u[0]; m(1,0) = v[0]; m(2,0) = w[0]; m(3,0) = a[0];//    |Ux Vx Wx|
+    m(0,1) = u[1]; m(1,1) = v[1]; m(2,1) = w[1]; m(3,1) = a[1];//m = |Uy Vy Wy|
+    m(0,2) = u[2]; m(1,2) = v[2]; m(2,2) = w[2]; m(3,2) = a[2];//    |Uz Vz Wz|
+    m(0,3) = 0;    m(1,3) = 0;    m(2,3) = 0;    m(3,3) = 1;
 
     // The above matrix maps the unit (!) square to the panel
     // rectangle.  Postmultiply scaling factors that match the
     // pixel-space size of the panel.
-    for(i=0; i<4; i++) {
-        m[0+i] *= 1.0/_xmax;
-        m[4+i] *= 1.0/_ymax;
+    for(i=0; i<4; ++i) {
+        m(0,i) *= 1.0/_xmax;
+        m(1,i) *= 1.0/_ymax;
     }
 
-    // Now plib initialization.  The bounding sphere is defined nicely
-    // by our corner points:
-    float cx = (b[0]+c[0])/2;
-    float cy = (b[1]+c[1])/2;
-    float cz = (b[2]+c[2])/2;
-    float r = sqrt((cx-a[0])*(cx-a[0]) +
-                   (cy-a[1])*(cy-a[1]) +
-                   (cz-a[2])*(cz-a[2]));
-    bsphere.setCenter(cx, cy, cz);
-    bsphere.setRadius(r);
+    _lastViewport[0] = 0;
+    _lastViewport[1] = 0;
+    _lastViewport[2] = 0;
+    _lastViewport[3] = 0;
+
+    dirtyBound();
 
     // All done.  Add us to the list
     all_3d_panels.push_back(this);
+
+    setUseDisplayList(false);
+    getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+    getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
 }
 
 FGPanelNode::~FGPanelNode()
@@ -119,33 +122,46 @@ FGPanelNode::~FGPanelNode()
     delete _panel;
 }
 
-void FGPanelNode::draw()
+void
+FGPanelNode::drawImplementation(osg::State& state) const
 {
-    // What's the difference?
-    draw_geometry();
+  osg::ref_ptr<osg::RefMatrix> mv = new osg::RefMatrix;
+  mv->set(_xform*state.getModelViewMatrix());
+  state.applyModelViewMatrix(mv.get());
+  
+  // Grab the matrix state, so that we can get back from screen
+  // coordinates to panel coordinates when the user clicks the
+  // mouse.
+  // OSGFIXME: we don't need that when we can really pick
+  _lastModelview = state.getModelViewMatrix();
+  _lastProjection = state.getProjectionMatrix();
+
+  const osg::Viewport* vp = state.getCurrentViewport();
+  _lastViewport[0] = vp->x();
+  _lastViewport[1] = vp->y();
+  _lastViewport[2] = vp->width();
+  _lastViewport[3] = vp->height();
+  
+  _panel->draw(state);
 }
 
-void FGPanelNode::draw_geometry()
+osg::BoundingBox
+FGPanelNode::computeBound() const
 {
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glMultMatrixf(_xform);
-
-    // Grab the matrix state, so that we can get back from screen
-    // coordinates to panel coordinates when the user clicks the
-    // mouse.
-    glGetFloatv(GL_MODELVIEW_MATRIX, _lastModelview);
-    glGetFloatv(GL_PROJECTION_MATRIX, _lastProjection);
-    glGetIntegerv(GL_VIEWPORT, _lastViewport);
-
-    _panel->draw();
-
-
-    glPopMatrix();
+    osg::BoundingBox bb;
+    bb.expandBy(_bottomLeft);
+    bb.expandBy(_bottomRight);
+    bb.expandBy(_topLeft);
+    return bb;
 }
 
 bool FGPanelNode::doMouseAction(int button, int updown, int x, int y)
 {
+    if (_lastViewport[2] == 0 || _lastViewport[3] == 0) {
+        // we haven't been drawn yet, presumably
+        return false;
+    }
+
     // Covert the screen coordinates to viewport coordinates in the
     // range [0:1], then transform to OpenGL "post projection" coords
     // in [-1:1].  Remember the difference in Y direction!
@@ -156,7 +172,7 @@ bool FGPanelNode::doMouseAction(int button, int updown, int x, int y)
 
     // Make two vectors in post-projection coordinates at the given
     // screen, one in the near field and one in the far field.
-    sgVec3 a, b;
+    osg::Vec3 a, b;
     a[0] = b[0] = vx;
     a[1] = b[1] = vy;
     a[2] =  0.75; // "Near" Z value
@@ -164,12 +180,11 @@ bool FGPanelNode::doMouseAction(int button, int updown, int x, int y)
 
     // Run both vectors "backwards" through the OpenGL matrix
     // transformation.  Remember to w-normalize the vectors!
-    sgMat4 m;
-    sgMultMat4(m, *(sgMat4*)_lastProjection, *(sgMat4*)_lastModelview);
-    sgInvertMat4(m);
+    osg::Matrix m = _lastModelview*_lastProjection;
+    m = osg::Matrix::inverse(m);
 
-    sgFullXformPnt3(a, m);
-    sgFullXformPnt3(b, m);
+    a = m.preMult(a);
+    b = m.preMult(b);
 
     // And find their intersection on the z=0 plane.  The resulting X
     // and Y coordinates are the hit location in panel coordinates.
@@ -181,9 +196,3 @@ bool FGPanelNode::doMouseAction(int button, int updown, int x, int y)
     return _panel->doLocalMouseAction(button, updown, panelX, panelY);
 }
 
-void FGPanelNode::die()
-{
-    SG_LOG(SG_ALL,SG_ALERT,"Unimplemented function called on FGPanelNode");
-    exit(1);
-}
-