--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#include "SGClipGroup.hxx"
+
+#include <osg/ClipPlane>
+#include <osg/NodeCallback>
+#include <osg/StateSet>
+#include <osg/Version>
+
+#include <osgUtil/RenderBin>
+#include <osgUtil/RenderLeaf>
+#include <osgUtil/CullVisitor>
+
+class SGClipGroup::ClipRenderBin : public osgUtil::RenderBin {
+public:
+ virtual osg::Object* cloneType() const
+ { return new ClipRenderBin(); }
+ virtual osg::Object* clone(const osg::CopyOp& copyop) const
+ { return new ClipRenderBin; }
+ virtual bool isSameKindAs(const osg::Object* obj) const
+ { return dynamic_cast<const ClipRenderBin*>(obj)!=0L; }
+ virtual const char* libraryName() const
+ { return "SimGear"; }
+ virtual const char* className() const
+ { return "ClipRenderBin"; }
+
+ virtual void drawImplementation(osg::RenderInfo& renderInfo,
+ osgUtil::RenderLeaf*& previous)
+ {
+ osg::State* state = renderInfo.getState();
+
+ glPushAttrib(GL_TRANSFORM_BIT);
+
+ state->applyModelViewMatrix(mModelView.get());
+ for (unsigned i = 0; i < mClipPlanes.size(); ++i)
+ mClipPlanes[i]->apply(*state);
+
+ osgUtil::RenderBin::drawImplementation(renderInfo, previous);
+
+ glPopAttrib();
+ }
+
+ virtual void reset()
+ { mClipPlanes.resize(0); }
+
+ std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
+ osg::ref_ptr<osg::RefMatrix> mModelView;
+};
+
+osgUtil::RegisterRenderBinProxy
+SGClipGroup::clipBinProxy("ClipRenderBin", new SGClipGroup::ClipRenderBin);
+
+class SGClipGroup::CullCallback : public osg::NodeCallback {
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ osgUtil::CullVisitor* cullVisitor;
+ cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
+
+ if (cullVisitor) {
+ osgUtil::RenderBin* renderBin = cullVisitor->getCurrentRenderBin();
+ ClipRenderBin* clipBin = dynamic_cast<ClipRenderBin*>(renderBin);
+ SGClipGroup* clipGroup;
+ clipGroup = dynamic_cast<SGClipGroup*>(node);
+ if (clipGroup && clipBin) {
+ clipBin->mClipPlanes = clipGroup->mClipPlanes;
+ clipBin->mModelView = cullVisitor->getModelViewMatrix();
+ }
+ }
+
+ // note, callback is responsible for scenegraph traversal so
+ // they must call traverse(node,nv) to ensure that the
+ // scene graph subtree (and associated callbacks) are traversed.
+ traverse(node, nv);
+ }
+};
+
+static osg::Vec4d clipPlane(const osg::Vec2& p0, const osg::Vec2& p1)
+{
+ osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
+ return osg::Vec4d(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
+}
+
+SGClipGroup::SGClipGroup()
+{
+ getOrCreateStateSet()->setRenderBinDetails(0, "ClipRenderBin");
+ setCullCallback(new CullCallback);
+}
+
+osg::BoundingSphere
+SGClipGroup::computeBound() const
+{
+ return _initialBound;
+}
+
+void
+SGClipGroup::addClipPlane(unsigned num, const SGVec2d& p0,
+ const SGVec2d& p1)
+{
+ osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
+ osg::Vec4d planeEquation(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
+ osg::ClipPlane* clipPlane = new osg::ClipPlane(num, planeEquation);
+ getStateSet()->setAssociatedModes(clipPlane, osg::StateAttribute::ON);
+ mClipPlanes.push_back(clipPlane);
+}
+
+void
+SGClipGroup::setDrawArea(const SGVec2d& lowerLeft,
+ const SGVec2d& upperRight)
+{
+ setDrawArea(lowerLeft,
+ SGVec2d(lowerLeft[0], upperRight[1]),
+ SGVec2d(upperRight[0], lowerLeft[1]),
+ upperRight);
+}
+
+void
+SGClipGroup::setDrawArea(const SGVec2d& bottomLeft,
+ const SGVec2d& topLeft,
+ const SGVec2d& bottomRight,
+ const SGVec2d& topRight)
+{
+#if (OPENSCENEGRAPH_MAJOR_VERSION > 2) || (OPENSCENEGRAPH_MINOR_VERSION > 2)
+ for (unsigned i = 0; i < mClipPlanes.size(); ++i)
+ getStateSet()->removeAssociatedModes(mClipPlanes[i].get());
+#endif
+ mClipPlanes.resize(0);
+ addClipPlane(2, bottomLeft, topLeft);
+ addClipPlane(3, topLeft, topRight);
+ addClipPlane(4, topRight, bottomRight);
+ addClipPlane(5, bottomRight, bottomLeft);
+ _initialBound.init();
+ _initialBound.expandBy(osg::Vec3(bottomLeft[0], bottomLeft[1], 0));
+ _initialBound.expandBy(osg::Vec3(topLeft[0], topLeft[1], 0));
+ _initialBound.expandBy(osg::Vec3(bottomRight[0], bottomRight[1], 0));
+ _initialBound.expandBy(osg::Vec3(topRight[0], topRight[1], 0));
+ _boundingSphere = _initialBound;
+ _boundingSphereComputed = true;
+}
+
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_CLIP_GROUP_HXX
+#define SG_CLIP_GROUP_HXX
+
+#include <vector>
+#include <osg/ref_ptr>
+#include <osg/ClipPlane>
+#include <osg/Group>
+#include <osgUtil/RenderBin>
+
+#include <simgear/math/SGMath.hxx>
+
+class SGClipGroup : public osg::Group {
+public:
+ SGClipGroup();
+
+ virtual osg::BoundingSphere computeBound() const;
+
+ void addClipPlane(unsigned num, const SGVec2d& p0, const SGVec2d& p1);
+ void setDrawArea(const SGVec2d& lowerLeft, const SGVec2d& upperRight);
+ void setDrawArea(const SGVec2d& bottomLeft,
+ const SGVec2d& topLeft,
+ const SGVec2d& bottomRight,
+ const SGVec2d& topRight);
+
+protected:
+ class CullCallback;
+ class ClipRenderBin;
+
+ std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
+
+ static osgUtil::RegisterRenderBinProxy clipBinProxy;
+};
+
+#endif