From: Thomas Geymayer Date: Thu, 5 Jun 2014 14:07:09 +0000 (+0200) Subject: Canvas: fix transformation of clip rect. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=7a65d42a4c5b799556697afaa1706cbe412da43c;p=simgear.git Canvas: fix transformation of clip rect. --- diff --git a/simgear/canvas/elements/CanvasElement.cxx b/simgear/canvas/elements/CanvasElement.cxx index af378e28..d67ba4f2 100644 --- a/simgear/canvas/elements/CanvasElement.cxx +++ b/simgear/canvas/elements/CanvasElement.cxx @@ -50,35 +50,50 @@ namespace canvas { public: - ReferenceFrame _coord_reference; - osg::Matrix _parent_inverse; + ReferenceFrame _coord_reference; + osg::observer_ptr _node; - RelativeScissor(): - _coord_reference(GLOBAL) - {} - - bool contains(const osg::Vec2f& pos) const + RelativeScissor(osg::Node* node = NULL): + _coord_reference(GLOBAL), + _node(node) { - return _x <= pos.x() && pos.x() <= _x + _width - && _y <= pos.y() && pos.y() <= _y + _height; + _width = 0; + _height = 0; } - bool contains( const osg::Vec2f& global_pos, - const osg::Vec2f& parent_pos, - const osg::Vec2f& local_pos ) const - { - switch( _coord_reference ) - { - case GLOBAL: return contains(global_pos); - case PARENT: return contains(parent_pos); - case LOCAL: return contains(local_pos); - } + /** Copy constructor using CopyOp to manage deep vs shallow copy. */ + RelativeScissor( const RelativeScissor& vp, + const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY ): + Scissor(vp, copyop), + _coord_reference(vp._coord_reference), + _node(vp._node) + {} - return false; + META_StateAttribute(simgear, RelativeScissor, SCISSOR); + + /** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */ + virtual int compare(const StateAttribute& sa) const + { + // check the types are equal and then create the rhs variable + // used by the COMPARE_StateAttribute_Parameter macros below. + COMPARE_StateAttribute_Types(RelativeScissor,sa) + + // compare each parameter in turn against the rhs. + COMPARE_StateAttribute_Parameter(_x) + COMPARE_StateAttribute_Parameter(_y) + COMPARE_StateAttribute_Parameter(_width) + COMPARE_StateAttribute_Parameter(_height) + COMPARE_StateAttribute_Parameter(_coord_reference) + COMPARE_StateAttribute_Parameter(_node) + + return 0; // passed all the above comparison macros, must be equal. } virtual void apply(osg::State& state) const { + if( _width <= 0 || _height <= 0 ) + return; + const osg::Viewport* vp = state.getCurrentViewport(); float w2 = 0.5 * vp->width(), h2 = 0.5 * vp->height(); @@ -94,17 +109,28 @@ namespace canvas if( _coord_reference != GLOBAL ) { - model_view.preMult(state.getModelViewMatrix()); + osg::Node* ref_obj = _node.get(); if( _coord_reference == PARENT ) - model_view.preMult(_parent_inverse); + { + if( _node->getNumParents() < 1 ) + { + SG_LOG(SG_GL, SG_WARN, "RelativeScissor: missing parent."); + return; + } + + ref_obj = _node->getParent(0); + } + + osg::MatrixList const& parent_matrices = ref_obj->getWorldMatrices(); + assert( !parent_matrices.empty() ); + model_view.preMult(parent_matrices.front()); } const osg::Vec2 scale( model_view(0,0), model_view(1,1)), offset(model_view(3,0), model_view(3,1)); // TODO check/warn for rotation? - GLint x = SGMiscf::roundToInt(scale.x() * _x + offset.x()), y = SGMiscf::roundToInt(scale.y() * _y + offset.y()), w = SGMiscf::roundToInt(std::fabs(scale.x()) * _width), @@ -117,6 +143,26 @@ namespace canvas glScissor(x, y, w, h); } + + bool contains(const osg::Vec2f& pos) const + { + return _x <= pos.x() && pos.x() <= _x + _width + && _y <= pos.y() && pos.y() <= _y + _height; + } + + bool contains( const osg::Vec2f& global_pos, + const osg::Vec2f& parent_pos, + const osg::Vec2f& local_pos ) const + { + switch( _coord_reference ) + { + case GLOBAL: return contains(global_pos); + case PARENT: return contains(parent_pos); + case LOCAL: return contains(local_pos); + } + + return false; + } }; //---------------------------------------------------------------------------- @@ -179,15 +225,6 @@ namespace canvas // Trigger matrix update getMatrix(); - // TODO limit bounding box to scissor - if( _attributes_dirty & SCISSOR_COORDS ) - { - if( _scissor && _scissor->_coord_reference != GLOBAL ) - _scissor->_parent_inverse = _transform->getInverseMatrix(); - - _attributes_dirty &= ~SCISSOR_COORDS; - } - // Update bounding box on manual update (manual updates pass zero dt) if( dt == 0 && _drawable ) _drawable->getBound(); @@ -524,28 +561,29 @@ namespace canvas return; } - _scissor = new RelativeScissor(); + if( !_scissor ) + _scissor = new RelativeScissor(_transform.get()); + // , , , _scissor->x() = SGMiscf::roundToInt(values[3]); _scissor->y() = SGMiscf::roundToInt(values[0]); _scissor->width() = SGMiscf::roundToInt(width); _scissor->height() = SGMiscf::roundToInt(height); - getOrCreateStateSet()->setAttributeAndModes(_scissor); - SGPropertyNode* clip_frame = _node->getChild("clip-frame", 0); if( clip_frame ) valueChanged(clip_frame); + else + _scissor->_coord_reference = GLOBAL; + + getOrCreateStateSet()->setAttributeAndModes(_scissor); } //---------------------------------------------------------------------------- void Element::setClipFrame(ReferenceFrame rf) { if( _scissor ) - { _scissor->_coord_reference = rf; - _attributes_dirty |= SCISSOR_COORDS; - } } //---------------------------------------------------------------------------- @@ -647,7 +685,6 @@ namespace canvas } _transform->setMatrix(m); _attributes_dirty &= ~TRANSFORM; - _attributes_dirty |= SCISSOR_COORDS; return m; } diff --git a/simgear/canvas/elements/CanvasElement.hxx b/simgear/canvas/elements/CanvasElement.hxx index 9e686739..7ae7d22c 100644 --- a/simgear/canvas/elements/CanvasElement.hxx +++ b/simgear/canvas/elements/CanvasElement.hxx @@ -211,8 +211,7 @@ namespace canvas { TRANSFORM = 1, BLEND_FUNC = TRANSFORM << 1, - SCISSOR_COORDS = BLEND_FUNC << 1, - LAST_ATTRIBUTE = SCISSOR_COORDS << 1 + LAST_ATTRIBUTE = BLEND_FUNC << 1 }; enum TransformType