00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <simgear_config.h>
00024 #endif
00025
00026 #include "SGClipGroup.hxx"
00027
00028 #include <osg/ClipPlane>
00029 #include <osg/NodeCallback>
00030 #include <osg/StateSet>
00031 #include <osg/Version>
00032
00033 #include <osgUtil/RenderBin>
00034 #include <osgUtil/RenderLeaf>
00035 #include <osgUtil/CullVisitor>
00036
00037 class SGClipGroup::ClipRenderBin : public osgUtil::RenderBin {
00038 public:
00039 virtual osg::Object* cloneType() const
00040 { return new ClipRenderBin(); }
00041 virtual osg::Object* clone(const osg::CopyOp& copyop) const
00042 { return new ClipRenderBin; }
00043 virtual bool isSameKindAs(const osg::Object* obj) const
00044 { return dynamic_cast<const ClipRenderBin*>(obj)!=0L; }
00045 virtual const char* libraryName() const
00046 { return "SimGear"; }
00047 virtual const char* className() const
00048 { return "ClipRenderBin"; }
00049
00050 virtual void drawImplementation(osg::RenderInfo& renderInfo,
00051 osgUtil::RenderLeaf*& previous)
00052 {
00053 osg::State* state = renderInfo.getState();
00054
00055 state->applyModelViewMatrix(mModelView.get());
00056 for (unsigned i = 0; i < mClipPlanes.size(); ++i) {
00057 osg::StateAttribute::GLMode planeNum;
00058 planeNum = GL_CLIP_PLANE0 + mClipPlanes[i]->getClipPlaneNum();
00059 state->applyMode(planeNum, false);
00060 glClipPlane(planeNum, mClipPlanes[i]->getClipPlane().ptr());
00061 }
00062
00063 osgUtil::RenderBin::drawImplementation(renderInfo, previous);
00064 }
00065
00066 virtual void reset()
00067 { mClipPlanes.resize(0); }
00068
00069 std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
00070 osg::ref_ptr<osg::RefMatrix> mModelView;
00071 };
00072
00073 osgUtil::RegisterRenderBinProxy
00074 SGClipGroup::clipBinProxy("ClipRenderBin", new SGClipGroup::ClipRenderBin);
00075
00076 class SGClipGroup::CullCallback : public osg::NodeCallback {
00077 public:
00078 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
00079 {
00080 osgUtil::CullVisitor* cullVisitor;
00081 cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
00082
00083 if (cullVisitor) {
00084 osgUtil::RenderBin* renderBin = cullVisitor->getCurrentRenderBin();
00085 ClipRenderBin* clipBin = dynamic_cast<ClipRenderBin*>(renderBin);
00086 SGClipGroup* clipGroup;
00087 clipGroup = dynamic_cast<SGClipGroup*>(node);
00088 if (clipGroup && clipBin) {
00089 clipBin->mClipPlanes = clipGroup->mClipPlanes;
00090 clipBin->mModelView = cullVisitor->getModelViewMatrix();
00091 }
00092 }
00093
00094
00095
00096
00097 traverse(node, nv);
00098 }
00099 };
00100
00101 #if 0
00102 static osg::Vec4d clipPlane(const osg::Vec2& p0, const osg::Vec2& p1)
00103 {
00104 osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
00105 return osg::Vec4d(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
00106 }
00107 #endif
00108
00109 SGClipGroup::SGClipGroup()
00110 {
00111 getOrCreateStateSet()->setRenderBinDetails(0, "ClipRenderBin");
00112 setCullCallback(new CullCallback);
00113 }
00114
00115 SGClipGroup::SGClipGroup(const SGClipGroup& clip, const osg::CopyOp& copyop) :
00116 osg::Group(clip, copyop)
00117 {
00118 for (unsigned i = 0; i < mClipPlanes.size(); ++i) {
00119 osg::StateAttribute* sa = copyop(mClipPlanes[i].get());
00120 mClipPlanes.push_back(static_cast<osg::ClipPlane*>(sa));
00121 }
00122 }
00123
00124 osg::BoundingSphere
00125 SGClipGroup::computeBound() const
00126 {
00127 return _initialBound;
00128 }
00129
00130 void
00131 SGClipGroup::addClipPlane(unsigned num, const SGVec2d& p0,
00132 const SGVec2d& p1)
00133 {
00134 osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
00135 osg::Vec4d planeEquation(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
00136 osg::ClipPlane* clipPlane = new osg::ClipPlane(num, planeEquation);
00137 getStateSet()->setAssociatedModes(clipPlane, osg::StateAttribute::ON);
00138 mClipPlanes.push_back(clipPlane);
00139 }
00140
00141 void
00142 SGClipGroup::setDrawArea(const SGVec2d& lowerLeft,
00143 const SGVec2d& upperRight)
00144 {
00145 setDrawArea(lowerLeft,
00146 SGVec2d(lowerLeft[0], upperRight[1]),
00147 SGVec2d(upperRight[0], lowerLeft[1]),
00148 upperRight);
00149 }
00150
00151 void
00152 SGClipGroup::setDrawArea(const SGVec2d& bottomLeft,
00153 const SGVec2d& topLeft,
00154 const SGVec2d& bottomRight,
00155 const SGVec2d& topRight)
00156 {
00157 #if (OPENSCENEGRAPH_MAJOR_VERSION > 2) || (OPENSCENEGRAPH_MINOR_VERSION > 2)
00158 for (unsigned i = 0; i < mClipPlanes.size(); ++i)
00159 getStateSet()->removeAssociatedModes(mClipPlanes[i].get());
00160 #endif
00161 mClipPlanes.resize(0);
00162 addClipPlane(2, bottomLeft, topLeft);
00163 addClipPlane(3, topLeft, topRight);
00164 addClipPlane(4, topRight, bottomRight);
00165 addClipPlane(5, bottomRight, bottomLeft);
00166 _initialBound.init();
00167 _initialBound.expandBy(osg::Vec3(bottomLeft[0], bottomLeft[1], 0));
00168 _initialBound.expandBy(osg::Vec3(topLeft[0], topLeft[1], 0));
00169 _initialBound.expandBy(osg::Vec3(bottomRight[0], bottomRight[1], 0));
00170 _initialBound.expandBy(osg::Vec3(topRight[0], topRight[1], 0));
00171 _boundingSphere = _initialBound;
00172 _boundingSphereComputed = true;
00173 }
00174