X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2Fpanelnode.cxx;h=be6889fda55d048d80e0a63044be888fcfbb5d82;hb=461b5fe00baac88933da3c6b89dddf6d832f6a7f;hp=b257a3bee2884fe1828ff07a8fd32d5c202b2089;hpb=9a3f0c5c19e9232509cff521e8d4e2124e6a0ef9;p=flightgear.git diff --git a/src/Model/panelnode.cxx b/src/Model/panelnode.cxx index b257a3bee..be6889fda 100644 --- a/src/Model/panelnode.cxx +++ b/src/Model/panelnode.cxx @@ -3,31 +3,36 @@ #endif #include -#include +#include -#include -#include +#include -#include
#include #include #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 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; idoMouseAction(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; igetPanel()->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 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); -} -