Canvas: do not write bounding box to property tree.

- Prevent writing to property tree in wrong thread.
 - Add Element::getBoundingBox and
   Element::getTightBoundingBox as uniform way to
   retrieve bounding boxes of all canvas elements.
 - Update path bounding boxe in update traversal.
This commit is contained in:
Thomas Geymayer
2014-03-31 13:24:33 +02:00
parent 6ea55c6851
commit d332da0605
6 changed files with 48 additions and 36 deletions

View File

@@ -452,8 +452,7 @@ namespace canvas
//----------------------------------------------------------------------------
void Canvas::valueChanged(SGPropertyNode* node)
{
if( boost::starts_with(node->getNameString(), "status")
|| node->getParent()->getNameString() == "bounding-box" )
if( boost::starts_with(node->getNameString(), "status") )
return;
_render_dirty = true;

View File

@@ -189,6 +189,7 @@ namespace canvas
// Trigger matrix update
getMatrix();
// TODO limit bounding box to scissor
if( _attributes_dirty & SCISSOR_COORDS )
{
if( _scissor && _scissor->_coord_reference != GLOBAL )
@@ -296,9 +297,11 @@ namespace canvas
// Drawables have a bounding box...
if( _drawable )
return _drawable->getBound().contains(osg::Vec3f(local_pos, 0));
else
else if( _transform.valid() )
// ... for other elements, i.e. groups only a bounding sphere is available
return _transform->getBound().contains(osg::Vec3f(parent_pos, 0));
else
return false;
}
@@ -534,22 +537,23 @@ namespace canvas
}
//----------------------------------------------------------------------------
void Element::setBoundingBox(const osg::BoundingBox& bb)
osg::BoundingBox Element::getBoundingBox() const
{
if( _bounding_box.empty() )
{
SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
_bounding_box.resize(4);
_bounding_box[0] = bb_node->getChild("min-x", 0, true);
_bounding_box[1] = bb_node->getChild("min-y", 0, true);
_bounding_box[2] = bb_node->getChild("max-x", 0, true);
_bounding_box[3] = bb_node->getChild("max-y", 0, true);
}
if( _drawable )
return _drawable->getBound();
_bounding_box[0]->setFloatValue(bb._min.x());
_bounding_box[1]->setFloatValue(bb._min.y());
_bounding_box[2]->setFloatValue(bb._max.x());
_bounding_box[3]->setFloatValue(bb._max.y());
osg::BoundingBox bb;
if( _transform.valid() )
bb.expandBy(_transform->getBound());
return bb;
}
//----------------------------------------------------------------------------
osg::BoundingBox Element::getTightBoundingBox() const
{
return getTransformedBounds(getMatrix());
}
//----------------------------------------------------------------------------
@@ -569,6 +573,9 @@ namespace canvas
//----------------------------------------------------------------------------
osg::Matrix Element::getMatrix() const
{
if( !_transform )
return osg::Matrix::identity();
if( !(_attributes_dirty & TRANSFORM) )
return _transform->getMatrix();

View File

@@ -164,9 +164,16 @@ namespace canvas
void setClipFrame(ReferenceFrame rf);
/**
* Write the given bounding box to the property tree
* Get bounding box (may not be as tight as bounding box returned by
* #getTightBounds)
*/
void setBoundingBox(const osg::BoundingBox& bb);
osg::BoundingBox getBoundingBox() const;
/**
* Get tight bounding box (child points are transformed to elements
* coordinate space before calculating the bounding box).
*/
osg::BoundingBox getTightBoundingBox() const;
/**
* Get bounding box with children/drawables transformed by passed matrix
@@ -227,9 +234,8 @@ namespace canvas
osg::observer_ptr<osg::MatrixTransform> _transform;
std::vector<TransformType> _transform_types;
Style _style;
std::vector<SGPropertyNode_ptr> _bounding_box;
RelativeScissor *_scissor;
Style _style;
RelativeScissor *_scissor;
typedef std::vector<EventListener> Listener;
typedef std::map<Event::Type, Listener> ListenerMap;
@@ -237,7 +243,7 @@ namespace canvas
ListenerMap _listener;
typedef std::map<std::string, StyleInfo> StyleSetters;
static StyleSetters _style_setters;
static StyleSetters _style_setters;
static void staticInit();

View File

@@ -271,7 +271,6 @@ namespace canvas
_vertices->dirty();
_attributes_dirty &= ~DEST_SIZE;
_geom->dirtyBound();
setBoundingBox(_geom->getBound());
}
if( _attributes_dirty & SRC_RECT )

View File

@@ -381,14 +381,11 @@ namespace canvas
// vgPathBounds doesn't take stroke width into account
float ext = 0.5 * _stroke_width;
osg::BoundingBox bb
return osg::BoundingBox
(
min[0] - ext, min[1] - ext, -0.1,
min[0] + size[0] + ext, min[1] + size[1] + ext, 0.1
);
_path_element->setBoundingBox(bb);
return bb;
}
private:
@@ -463,7 +460,12 @@ namespace canvas
}
if( _attributes_dirty & BOUNDING_BOX )
{
dirtyBound();
// Recalculate bounding box now (prevent race condition)
getBound();
}
}
struct PathUpdateCallback:

View File

@@ -179,18 +179,17 @@ namespace canvas
osg::BoundingBox Text::TextOSG::computeBound() const
{
osg::BoundingBox bb = osgText::Text::computeBound();
if( !bb.valid() )
return bb;
#if OSG_VERSION_LESS_THAN(3,1,0)
// TODO bounding box still doesn't seem always right (eg. with center
// horizontal alignment not completely accurate)
bb._min.y() += _offset.y();
bb._max.y() += _offset.y();
if( bb.valid() )
{
// TODO bounding box still doesn't seem always right (eg. with center
// horizontal alignment not completely accurate)
bb._min.y() += _offset.y();
bb._max.y() += _offset.y();
}
#endif
_text_element->setBoundingBox(bb);
return bb;
}