From: Thomas Geymayer Date: Tue, 4 Dec 2012 22:58:08 +0000 (+0100) Subject: Extend Canvas to retrieve bounding box of groups X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=e9b499b82d3840ff6cb7db14dfd94fd39f9a6109;p=simgear.git Extend Canvas to retrieve bounding box of groups --- diff --git a/simgear/canvas/elements/CanvasElement.cxx b/simgear/canvas/elements/CanvasElement.cxx index 7b8a8c6b..0ca940d1 100644 --- a/simgear/canvas/elements/CanvasElement.cxx +++ b/simgear/canvas/elements/CanvasElement.cxx @@ -316,6 +316,12 @@ namespace canvas _bounding_box[3]->setFloatValue(bb._max.y()); } + //---------------------------------------------------------------------------- + osg::BoundingBox Element::getTransformedBounds(const osg::Matrix& m) const + { + return osg::BoundingBox(); + } + //---------------------------------------------------------------------------- Element::Element( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, diff --git a/simgear/canvas/elements/CanvasElement.hxx b/simgear/canvas/elements/CanvasElement.hxx index 0f4b31ed..9067c729 100644 --- a/simgear/canvas/elements/CanvasElement.hxx +++ b/simgear/canvas/elements/CanvasElement.hxx @@ -96,6 +96,11 @@ namespace canvas */ void setBoundingBox(const osg::BoundingBox& bb); + /** + * Get bounding box with children/drawables transformed by passed matrix + */ + virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const; + protected: enum Attributes diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx index 07400268..e8158edf 100644 --- a/simgear/canvas/elements/CanvasGroup.cxx +++ b/simgear/canvas/elements/CanvasGroup.cxx @@ -132,6 +132,28 @@ namespace canvas return false; } + //---------------------------------------------------------------------------- + osg::BoundingBox Group::getTransformedBounds(const osg::Matrix& m) const + { + osg::BoundingBox bb; + + BOOST_FOREACH( ChildList::value_type child, _children ) + { + if( !child.second->getMatrixTransform()->getNodeMask() ) + continue; + + bb.expandBy + ( + child.second->getTransformedBounds + ( + child.second->getMatrixTransform()->getMatrix() * m + ) + ); + } + + return bb; + } + //---------------------------------------------------------------------------- void Group::childAdded(SGPropertyNode* child) { diff --git a/simgear/canvas/elements/CanvasGroup.hxx b/simgear/canvas/elements/CanvasGroup.hxx index 38cb0cc9..02ea7e8b 100644 --- a/simgear/canvas/elements/CanvasGroup.hxx +++ b/simgear/canvas/elements/CanvasGroup.hxx @@ -58,6 +58,8 @@ namespace canvas virtual bool traverse(EventVisitor& visitor); + virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const; + protected: typedef std::map ChildFactories; diff --git a/simgear/canvas/elements/CanvasPath.cxx b/simgear/canvas/elements/CanvasPath.cxx index ebcb45ff..9fde6782 100644 --- a/simgear/canvas/elements/CanvasPath.cxx +++ b/simgear/canvas/elements/CanvasPath.cxx @@ -32,6 +32,25 @@ namespace canvas typedef std::vector CmdList; typedef std::vector CoordList; + + static const VGubyte shCoordsPerCommand[] = { + 0, /* VG_CLOSE_PATH */ + 2, /* VG_MOVE_TO */ + 2, /* VG_LINE_TO */ + 1, /* VG_HLINE_TO */ + 1, /* VG_VLINE_TO */ + 4, /* VG_QUAD_TO */ + 6, /* VG_CUBIC_TO */ + 2, /* VG_SQUAD_TO */ + 4, /* VG_SCUBIC_TO */ + 5, /* VG_SCCWARC_TO */ + 5, /* VG_SCWARC_TO */ + 5, /* VG_LCCWARC_TO */ + 5 /* VG_LCWARC_TO */ + }; + static const VGubyte shNumCommands = sizeof(shCoordsPerCommand) + / sizeof(shCoordsPerCommand[0]); + /** * Helper to split and convert comma/whitespace separated floating point * values @@ -255,6 +274,91 @@ namespace canvas glPopClientAttrib(); } + osg::BoundingBox getTransformedBounds(const osg::Matrix& mat) const + { + osg::BoundingBox bb; + + osg::Vec2f cur; // VG "Current point" (in local coordinates) + VGubyte cmd_index = 0; + for( size_t i = 0, ci = 0; + i < _cmds.size() && ci < _coords.size(); + ++i, ci += shCoordsPerCommand[cmd_index] ) + { + VGubyte rel = _cmds[i] & 1, + cmd = _cmds[i] & ~1; + + cmd_index = cmd / 2; + if( cmd_index >= shNumCommands ) + return osg::BoundingBox(); + + const VGubyte max_coords = 3; + osg::Vec2f points[max_coords]; + VGubyte num_coords = 0; + + switch( cmd ) + { + case VG_CLOSE_PATH: + break; + case VG_MOVE_TO: + case VG_LINE_TO: + case VG_SQUAD_TO: + // x0, y0 + points[ num_coords++ ].set(_coords[ci], _coords[ci + 1]); + break; + case VG_HLINE_TO: + // x0 + points[ num_coords++ ].set( _coords[ci] + (rel ? cur.x() : 0), + cur.y() ); + // We have handled rel/abs already, so no need to do it again... + rel = 0; + break; + case VG_VLINE_TO: + // y0 + points[ num_coords++ ].set( cur.x(), + _coords[ci] + (rel ? cur.y() : 0) ); + // We have handled rel/abs already, so no need to do it again... + rel = 0; + break; + case VG_QUAD_TO: + case VG_SCUBIC_TO: + // x0,y0,x1,y1 + points[ num_coords++ ].set(_coords[ci ], _coords[ci + 1]); + points[ num_coords++ ].set(_coords[ci + 2], _coords[ci + 3]); + break; + case VG_CUBIC_TO: + // x0,y0,x1,y1,x2,y2 + points[ num_coords++ ].set(_coords[ci ], _coords[ci + 1]); + points[ num_coords++ ].set(_coords[ci + 2], _coords[ci + 3]); + points[ num_coords++ ].set(_coords[ci + 4], _coords[ci + 5]); + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: + // rh,rv,rot,x0,y0 + points[ num_coords++ ].set(_coords[ci + 3], _coords[ci + 4]); + break; + default: + SG_LOG(SG_GL, SG_WARN, "Unknown VG command: " << (int)cmd); + return osg::BoundingBox(); + } + + assert(num_coords <= max_coords); + for(VGubyte i = 0; i < num_coords; ++i) + { + if( rel ) + points[i] += cur; + + bb.expandBy( transformPoint(mat, points[i]) ); + } + + if( num_coords > 0 ) + cur = points[ num_coords - 1 ]; + } + + return bb; + } + /** * Compute the bounding box */ @@ -309,6 +413,17 @@ namespace canvas std::vector _stroke_dash; VGCapStyle _stroke_linecap; + osg::Vec3f transformPoint( const osg::Matrix& m, + osg::Vec2f pos ) const + { + return osg::Vec3 + ( + m(0, 0) * pos[0] + m(1, 0) * pos[1] + m(3, 0), + m(0, 1) * pos[0] + m(1, 1) * pos[1] + m(3, 1), + 0 + ); + } + /** * Initialize/Update the OpenVG path */ @@ -396,6 +511,12 @@ namespace canvas Element::update(dt); } + //---------------------------------------------------------------------------- + osg::BoundingBox Path::getTransformedBounds(const osg::Matrix& m) const + { + return _path->getTransformedBounds(m); + } + //---------------------------------------------------------------------------- void Path::childRemoved(SGPropertyNode* child) { diff --git a/simgear/canvas/elements/CanvasPath.hxx b/simgear/canvas/elements/CanvasPath.hxx index 42854772..2cde2dc9 100644 --- a/simgear/canvas/elements/CanvasPath.hxx +++ b/simgear/canvas/elements/CanvasPath.hxx @@ -37,6 +37,8 @@ namespace canvas virtual void update(double dt); + virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const; + protected: enum PathAttributes