]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGClipGroup.cxx
Merge branch 'timoore/aptsign' into next
[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 #ifdef HAVE_CONFIG_H
23 #  include <simgear_config.h>
24 #endif
25
26 #include "SGClipGroup.hxx"
27
28 #include <osg/ClipPlane>
29 #include <osg/NodeCallback>
30 #include <osg/StateSet>
31 #include <osg/Version>
32
33 #include <osgUtil/RenderBin>
34 #include <osgUtil/RenderLeaf>
35 #include <osgUtil/CullVisitor>
36
37 class SGClipGroup::ClipRenderBin : public osgUtil::RenderBin {
38 public:
39   virtual osg::Object* cloneType() const
40   { return new ClipRenderBin(); }
41   virtual osg::Object* clone(const osg::CopyOp& copyop) const
42   { return new ClipRenderBin; }
43   virtual bool isSameKindAs(const osg::Object* obj) const
44   { return dynamic_cast<const ClipRenderBin*>(obj)!=0L; }
45   virtual const char* libraryName() const
46   { return "SimGear"; }
47   virtual const char* className() const
48   { return "ClipRenderBin"; }
49
50   virtual void drawImplementation(osg::RenderInfo& renderInfo,
51                                   osgUtil::RenderLeaf*& previous)
52   {
53     osg::State* state = renderInfo.getState();
54
55     state->applyModelViewMatrix(mModelView.get());
56     for (unsigned i = 0; i < mClipPlanes.size(); ++i) {
57       osg::StateAttribute::GLMode planeNum;
58       planeNum = GL_CLIP_PLANE0 + mClipPlanes[i]->getClipPlaneNum();
59       state->applyMode(planeNum, false);
60       glClipPlane(planeNum, mClipPlanes[i]->getClipPlane().ptr());
61     }
62
63     osgUtil::RenderBin::drawImplementation(renderInfo, previous);
64   }
65
66   virtual void reset()
67   { mClipPlanes.resize(0); }
68  
69   std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
70   osg::ref_ptr<osg::RefMatrix> mModelView;
71 };
72
73 osgUtil::RegisterRenderBinProxy
74 SGClipGroup::clipBinProxy("ClipRenderBin", new SGClipGroup::ClipRenderBin);
75
76 class SGClipGroup::CullCallback : public osg::NodeCallback {
77 public:
78   virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
79   {
80     osgUtil::CullVisitor* cullVisitor;
81     cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
82     
83     if (cullVisitor) {
84       osgUtil::RenderBin* renderBin = cullVisitor->getCurrentRenderBin();
85       ClipRenderBin* clipBin = dynamic_cast<ClipRenderBin*>(renderBin);
86       SGClipGroup* clipGroup;
87       clipGroup = dynamic_cast<SGClipGroup*>(node);
88       if (clipGroup && clipBin) {
89         clipBin->mClipPlanes = clipGroup->mClipPlanes;
90         clipBin->mModelView = cullVisitor->getModelViewMatrix();
91       }
92     }
93     
94     // note, callback is responsible for scenegraph traversal so
95     // they must call traverse(node,nv) to ensure that the
96     // scene graph subtree (and associated callbacks) are traversed.
97     traverse(node, nv);
98   }
99 };
100
101 #if 0
102 static osg::Vec4d clipPlane(const osg::Vec2& p0, const osg::Vec2& p1)
103 {
104   osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
105   return osg::Vec4d(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
106 }
107 #endif
108
109 SGClipGroup::SGClipGroup()
110 {
111   getOrCreateStateSet()->setRenderBinDetails(0, "ClipRenderBin");
112   setCullCallback(new CullCallback);
113 }
114
115 SGClipGroup::SGClipGroup(const SGClipGroup& clip, const osg::CopyOp& copyop) :
116   osg::Group(clip, copyop)
117 {
118   for (unsigned i = 0; i < mClipPlanes.size(); ++i) {
119     osg::StateAttribute* sa = copyop(mClipPlanes[i].get());
120     mClipPlanes.push_back(static_cast<osg::ClipPlane*>(sa));
121   }
122 }
123
124 osg::BoundingSphere
125 SGClipGroup::computeBound() const
126 {
127   return _initialBound;
128 }
129
130 void
131 SGClipGroup::addClipPlane(unsigned num, const SGVec2d& p0,
132                           const SGVec2d& p1)
133 {
134   osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
135   osg::Vec4d planeEquation(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
136   osg::ClipPlane* clipPlane = new osg::ClipPlane(num, planeEquation);
137   getStateSet()->setAssociatedModes(clipPlane, osg::StateAttribute::ON);
138   mClipPlanes.push_back(clipPlane);
139 }
140
141 void
142 SGClipGroup::setDrawArea(const SGVec2d& lowerLeft,
143                          const SGVec2d& upperRight)
144 {
145   setDrawArea(lowerLeft,
146               SGVec2d(lowerLeft[0], upperRight[1]),
147               SGVec2d(upperRight[0], lowerLeft[1]),
148               upperRight);
149 }
150
151 void
152 SGClipGroup::setDrawArea(const SGVec2d& bottomLeft,
153                          const SGVec2d& topLeft,
154                          const SGVec2d& bottomRight,
155                          const SGVec2d& topRight)
156 {
157 #if (OPENSCENEGRAPH_MAJOR_VERSION > 2) || (OPENSCENEGRAPH_MINOR_VERSION > 2)
158   for (unsigned i = 0; i < mClipPlanes.size(); ++i)
159     getStateSet()->removeAssociatedModes(mClipPlanes[i].get());
160 #endif
161   mClipPlanes.resize(0);
162   addClipPlane(2, bottomLeft, topLeft);
163   addClipPlane(3, topLeft, topRight);
164   addClipPlane(4, topRight, bottomRight);
165   addClipPlane(5, bottomRight, bottomLeft);
166   _initialBound.init();
167   _initialBound.expandBy(osg::Vec3(bottomLeft[0], bottomLeft[1], 0));
168   _initialBound.expandBy(osg::Vec3(topLeft[0], topLeft[1], 0));
169   _initialBound.expandBy(osg::Vec3(bottomRight[0], bottomRight[1], 0));
170   _initialBound.expandBy(osg::Vec3(topRight[0], topRight[1], 0));
171   _boundingSphere = _initialBound;
172   _boundingSphereComputed = true;
173 }
174