On 8/27/2012 3:14 PM, Jeremy Moles wrote:
> A Drawable can have a special ComputeBoundsCallback() (something like
> that, I'm on my phone right now and can't look it up), so you could use
> that as well...
Here is the code I came up with after your suggestion that does resolve
my problem (I attach the callback directly to the PAT in question):

[code]

/// This callback is used to prevent the bounding sphere associated with a
/// osg::PositionAttitudeTransform from modifying the bounding sphere due to
/// its scaling factor.
class keep_bounding_sphere_t : public
osg::Node::ComputeBoundingSphereCallback
{
public:
  keep_bounding_sphere_t ();

  keep_bounding_sphere_t (const osg::Vec3 &axes);

  keep_bounding_sphere_t (
    const keep_bounding_sphere_t &other, const osg::CopyOp copyop
  );

  META_Object (anonymous, keep_bounding_sphere_t);

  /* * * osg::Node * * */

  virtual osg::BoundingSphere
  computeBound (const osg::Node &node) const;

private:
  /// The axes that might be scaled and should be checked.
  /// e.g. osg::Z_AXIS to check only the z-axis.
  osg::Vec3 axes_;
};

keep_bounding_sphere_t::keep_bounding_sphere_t ()
: ComputeBoundingSphereCallback (),
  axes_ (1.0f, 1.0f, 1.0f)
{
}

keep_bounding_sphere_t::keep_bounding_sphere_t (const osg::Vec3 &axes)
: ComputeBoundingSphereCallback (),
  axes_ (axes)
{
}

keep_bounding_sphere_t::keep_bounding_sphere_t (
  const keep_bounding_sphere_t &other, const osg::CopyOp copyop )
: ComputeBoundingSphereCallback (other, copyop),
  axes_ (other.axes_)
{
}

osg::BoundingSphere
keep_bounding_sphere_t::computeBound (const osg::Node &node) const
{
  osg::BoundingSphere out = node.computeBound ();

  const osg::PositionAttitudeTransform *pat =
    dynamic_cast <const osg::PositionAttitudeTransform *> (&node);
  if (!pat)
    return out;

  osg::Vec3d scale = pat->getScale ();

  double sscale = 1.0;
  if (axes_.x ())
    sscale = scale.x ();
  if (axes_.y () && scale.y () > sscale)
    sscale = scale.y ();
  if (axes_.z () && scale.z () > sscale)
    sscale = scale.z ();

  if (sscale)
    out.set (out.center () , out.radius () / sscale);

  return out;
}

[/code]

My understanding of Transform::computeBound() could be better, but in my
case, it was effectively multiplying the bounding sphere radius by the
scaling factor even though the scaling factor only applied to a single
axis and should not have been a factor when calculating the boundary sphere.

Thus, the code above works provided the extent of the geometry along the
axis being scaled will never be larger than the extent of the geometry
along the other axes. I can think of a few improvements to this code
(like compute the bounds of the child node(s) directly then determine
what to do with the scale values). However, does this seem like a
proper/common approach to solving this problem? Another approach might
be to override the PositionAttitudeTransform node directly?

Regards,

Judson
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to