]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGClipGroup.cxx
fdf9305ae1a3af3f9ee3f95237712d06da58a909
[simgear.git] / simgear / scene / model / SGClipGroup.cxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2007 Mathias Froehlich 
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #include "SGClipGroup.hxx"
23
24 #include <osg/ClipPlane>
25 #include <osg/NodeCallback>
26 #include <osg/StateSet>
27 #include <osg/Version>
28
29 #include <osgUtil/RenderBin>
30 #include <osgUtil/RenderLeaf>
31 #include <osgUtil/CullVisitor>
32
33 class SGClipGroup::ClipRenderBin : public osgUtil::RenderBin {
34 public:
35   virtual osg::Object* cloneType() const
36   { return new ClipRenderBin(); }
37   virtual osg::Object* clone(const osg::CopyOp& copyop) const
38   { return new ClipRenderBin; }
39   virtual bool isSameKindAs(const osg::Object* obj) const
40   { return dynamic_cast<const ClipRenderBin*>(obj)!=0L; }
41   virtual const char* libraryName() const
42   { return "SimGear"; }
43   virtual const char* className() const
44   { return "ClipRenderBin"; }
45
46   virtual void drawImplementation(osg::RenderInfo& renderInfo,
47                                   osgUtil::RenderLeaf*& previous)
48   {
49     osg::State* state = renderInfo.getState();
50
51     glPushAttrib(GL_TRANSFORM_BIT);
52
53     state->applyModelViewMatrix(mModelView.get());
54     for (unsigned i = 0; i < mClipPlanes.size(); ++i)
55       mClipPlanes[i]->apply(*state);
56
57     osgUtil::RenderBin::drawImplementation(renderInfo, previous);
58
59     glPopAttrib();
60   }
61
62   virtual void reset()
63   { mClipPlanes.resize(0); }
64  
65   std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
66   osg::ref_ptr<osg::RefMatrix> mModelView;
67 };
68
69 osgUtil::RegisterRenderBinProxy
70 SGClipGroup::clipBinProxy("ClipRenderBin", new SGClipGroup::ClipRenderBin);
71
72 class SGClipGroup::CullCallback : public osg::NodeCallback {
73 public:
74   virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
75   {
76     osgUtil::CullVisitor* cullVisitor;
77     cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
78     
79     if (cullVisitor) {
80       osgUtil::RenderBin* renderBin = cullVisitor->getCurrentRenderBin();
81       ClipRenderBin* clipBin = dynamic_cast<ClipRenderBin*>(renderBin);
82       SGClipGroup* clipGroup;
83       clipGroup = dynamic_cast<SGClipGroup*>(node);
84       if (clipGroup && clipBin) {
85         clipBin->mClipPlanes = clipGroup->mClipPlanes;
86         clipBin->mModelView = cullVisitor->getModelViewMatrix();
87       }
88     }
89     
90     // note, callback is responsible for scenegraph traversal so
91     // they must call traverse(node,nv) to ensure that the
92     // scene graph subtree (and associated callbacks) are traversed.
93     traverse(node, nv);
94   }
95 };
96
97 static osg::Vec4d clipPlane(const osg::Vec2& p0, const osg::Vec2& p1)
98 {
99   osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
100   return osg::Vec4d(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
101 }
102
103 SGClipGroup::SGClipGroup()
104 {
105   getOrCreateStateSet()->setRenderBinDetails(0, "ClipRenderBin");
106   setCullCallback(new CullCallback);
107 }
108
109 osg::BoundingSphere
110 SGClipGroup::computeBound() const
111 {
112   return _initialBound;
113 }
114
115 void
116 SGClipGroup::addClipPlane(unsigned num, const SGVec2d& p0,
117                           const SGVec2d& p1)
118 {
119   osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
120   osg::Vec4d planeEquation(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
121   osg::ClipPlane* clipPlane = new osg::ClipPlane(num, planeEquation);
122   getStateSet()->setAssociatedModes(clipPlane, osg::StateAttribute::ON);
123   mClipPlanes.push_back(clipPlane);
124 }
125
126 void
127 SGClipGroup::setDrawArea(const SGVec2d& lowerLeft,
128                          const SGVec2d& upperRight)
129 {
130   setDrawArea(lowerLeft,
131               SGVec2d(lowerLeft[0], upperRight[1]),
132               SGVec2d(upperRight[0], lowerLeft[1]),
133               upperRight);
134 }
135
136 void
137 SGClipGroup::setDrawArea(const SGVec2d& bottomLeft,
138                          const SGVec2d& topLeft,
139                          const SGVec2d& bottomRight,
140                          const SGVec2d& topRight)
141 {
142 #if (OPENSCENEGRAPH_MAJOR_VERSION > 2) || (OPENSCENEGRAPH_MINOR_VERSION > 2)
143   for (unsigned i = 0; i < mClipPlanes.size(); ++i)
144     getStateSet()->removeAssociatedModes(mClipPlanes[i].get());
145 #endif
146   mClipPlanes.resize(0);
147   addClipPlane(2, bottomLeft, topLeft);
148   addClipPlane(3, topLeft, topRight);
149   addClipPlane(4, topRight, bottomRight);
150   addClipPlane(5, bottomRight, bottomLeft);
151   _initialBound.init();
152   _initialBound.expandBy(osg::Vec3(bottomLeft[0], bottomLeft[1], 0));
153   _initialBound.expandBy(osg::Vec3(topLeft[0], topLeft[1], 0));
154   _initialBound.expandBy(osg::Vec3(bottomRight[0], bottomRight[1], 0));
155   _initialBound.expandBy(osg::Vec3(topRight[0], topRight[1], 0));
156   _boundingSphere = _initialBound;
157   _boundingSphereComputed = true;
158 }
159