OpenSceneGraph/src/osg/Shape.cpp

176 lines
3.4 KiB
C++
Raw Normal View History

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osg/Shape>
#include <algorithm>
using namespace osg;
2004-08-02 17:11:31 +08:00
Shape::~Shape()
{
}
From Patrick Hartling, "I encountered a bug related to RTTI for subclasses of osg::Shape. The circumstances under which this bug occur are rather specific, but the basic problem occurs when one translation unit other than libosg.so constructs an object that is a subclass of osg::Shape and another translation unit other than libosg.so tries to perform a dynamic_cast or other RTTI-based operation on that object. Under these circumstances, the RTTI operation will fail. In my case, the translation units involved were an application and osgdb_ive.so. The application constructed a scene graph that included instantiations of subclasses of osg::Shape. Depending on how the user ran the application, it would write the scene graph to an IVE file using osgDB::writeNodeFile(). The dynamic_cast operations in DataOutputStream::writeShape() would fail on the first subclass of osg::Shape that was encountered. This is because there were two different RTTI data objects for all osg::Shape subclasses being compared: one in the application and one in osgdb_ive.so. The fix for this is simple. We must ensure that at least one member function of each of the subclasses of the polymorphic type osg::Shape is compiled into libosg.so so that there is exactly one RTTI object for that type in libosg.so. Then, all code linking against libosg.so will use that single RTTI object. The following message from a list archive sort of explains the issue and the solution: http://aspn.activestate.com/ASPN/Mail/Message/1688156 While the posting has to do with Boost.Python, the problem applies to C++ libraries in general."
2009-01-28 17:21:46 +08:00
ShapeVisitor::~ShapeVisitor()
{
}
ConstShapeVisitor::~ConstShapeVisitor()
{
}
Sphere::~Sphere()
{
}
Box::~Box()
{
}
Cone::~Cone()
{
}
Cylinder::~Cylinder()
{
}
Capsule::~Capsule()
{
}
InfinitePlane::~InfinitePlane()
{
}
TriangleMesh::~TriangleMesh()
{
}
ConvexHull::~ConvexHull()
{
}
HeightField::HeightField():
_columns(0),
_rows(0),
_origin(0.0f,0.0f,0.0f),
_dx(1.0f),
_dy(1.0f),
_skirtHeight(0.0f),
_borderWidth(0)
{
_heights = new osg::FloatArray;
}
HeightField::HeightField(const HeightField& mesh,const CopyOp& copyop):
Shape(mesh,copyop),
_columns(mesh._columns),
_rows(mesh._rows),
_origin(mesh._origin),
_dx(mesh._dx),
_dy(mesh._dy),
_skirtHeight(mesh._skirtHeight),
_borderWidth(mesh._borderWidth),
_heights(new osg::FloatArray(*mesh._heights))
{
}
2004-08-02 17:11:31 +08:00
HeightField::~HeightField()
{
}
void HeightField::allocate(unsigned int numColumns,unsigned int numRows)
2003-10-28 00:07:21 +08:00
{
if (_columns!=numColumns || _rows!=numRows)
{
_heights->resize(numColumns*numRows);
2003-10-28 00:07:21 +08:00
}
_columns=numColumns;
_rows=numRows;
}
Vec3 HeightField::getNormal(unsigned int c,unsigned int r) const
2002-11-01 18:25:27 +08:00
{
// four point normal generation.
float dz_dx;
2002-11-01 18:25:27 +08:00
if (c==0)
{
dz_dx = (getHeight(c+1,r)-getHeight(c,r))/getXInterval();
2002-11-01 18:25:27 +08:00
}
else if (c==getNumColumns()-1)
{
dz_dx = (getHeight(c,r)-getHeight(c-1,r))/getXInterval();
2002-11-01 18:25:27 +08:00
}
else // assume 0<c<_numColumns-1
{
dz_dx = 0.5f*(getHeight(c+1,r)-getHeight(c-1,r))/getXInterval();
2002-11-01 18:25:27 +08:00
}
2002-11-01 18:25:27 +08:00
float dz_dy;
if (r==0)
{
dz_dy = (getHeight(c,r+1)-getHeight(c,r))/getYInterval();
2002-11-01 18:25:27 +08:00
}
else if (r==getNumRows()-1)
{
dz_dy = (getHeight(c,r)-getHeight(c,r-1))/getYInterval();
2002-11-01 18:25:27 +08:00
}
else // assume 0<r<_numRows-1
{
dz_dy = 0.5f*(getHeight(c,r+1)-getHeight(c,r-1))/getYInterval();
2002-11-01 18:25:27 +08:00
}
2002-11-01 18:25:27 +08:00
Vec3 normal(-dz_dx,-dz_dy,1.0f);
normal.normalize();
2002-11-01 18:25:27 +08:00
return normal;
}
Vec2 HeightField::getHeightDelta(unsigned int c,unsigned int r) const
{
// four point height generation.
Vec2 heightDelta;
if (c==0)
{
heightDelta.x() = (getHeight(c+1,r)-getHeight(c,r));
}
else if (c==getNumColumns()-1)
{
heightDelta.x() = (getHeight(c,r)-getHeight(c-1,r));
}
else // assume 0<c<_numColumns-1
{
heightDelta.x() = 0.5f*(getHeight(c+1,r)-getHeight(c-1,r));
}
if (r==0)
{
heightDelta.y() = (getHeight(c,r+1)-getHeight(c,r));
}
else if (r==getNumRows()-1)
{
heightDelta.y() = (getHeight(c,r)-getHeight(c,r-1));
}
else // assume 0<r<_numRows-1
{
heightDelta.y() = 0.5f*(getHeight(c,r+1)-getHeight(c,r-1));
}
return heightDelta;
}
From Patrick Hartling, "I encountered a bug related to RTTI for subclasses of osg::Shape. The circumstances under which this bug occur are rather specific, but the basic problem occurs when one translation unit other than libosg.so constructs an object that is a subclass of osg::Shape and another translation unit other than libosg.so tries to perform a dynamic_cast or other RTTI-based operation on that object. Under these circumstances, the RTTI operation will fail. In my case, the translation units involved were an application and osgdb_ive.so. The application constructed a scene graph that included instantiations of subclasses of osg::Shape. Depending on how the user ran the application, it would write the scene graph to an IVE file using osgDB::writeNodeFile(). The dynamic_cast operations in DataOutputStream::writeShape() would fail on the first subclass of osg::Shape that was encountered. This is because there were two different RTTI data objects for all osg::Shape subclasses being compared: one in the application and one in osgdb_ive.so. The fix for this is simple. We must ensure that at least one member function of each of the subclasses of the polymorphic type osg::Shape is compiled into libosg.so so that there is exactly one RTTI object for that type in libosg.so. Then, all code linking against libosg.so will use that single RTTI object. The following message from a list archive sort of explains the issue and the solution: http://aspn.activestate.com/ASPN/Mail/Message/1688156 While the posting has to do with Boost.Python, the problem applies to C++ libraries in general."
2009-01-28 17:21:46 +08:00
CompositeShape::~CompositeShape()
{
}