]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGClipGroup.cxx
Do not modify danymically generated textures.
[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 static osg::Vec4d clipPlane(const osg::Vec2& p0, const osg::Vec2& p1)
102 {
103   osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
104   return osg::Vec4d(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
105 }
106
107 SGClipGroup::SGClipGroup()
108 {
109   getOrCreateStateSet()->setRenderBinDetails(0, "ClipRenderBin");
110   setCullCallback(new CullCallback);
111 }
112
113 SGClipGroup::SGClipGroup(const SGClipGroup& clip, const osg::CopyOp& copyop) :
114   osg::Group(clip, copyop)
115 {
116   for (unsigned i = 0; i < mClipPlanes.size(); ++i) {
117     osg::StateAttribute* sa = copyop(mClipPlanes[i].get());
118     mClipPlanes.push_back(static_cast<osg::ClipPlane*>(sa));
119   }
120 }
121
122 osg::BoundingSphere
123 SGClipGroup::computeBound() const
124 {
125   return _initialBound;
126 }
127
128 void
129 SGClipGroup::addClipPlane(unsigned num, const SGVec2d& p0,
130                           const SGVec2d& p1)
131 {
132   osg::Vec2d v(p1[0] - p0[0], p1[1] - p0[1]);
133   osg::Vec4d planeEquation(v[1], -v[0], 0, v[0]*p0[1] - v[1]*p0[0]);
134   osg::ClipPlane* clipPlane = new osg::ClipPlane(num, planeEquation);
135   getStateSet()->setAssociatedModes(clipPlane, osg::StateAttribute::ON);
136   mClipPlanes.push_back(clipPlane);
137 }
138
139 void
140 SGClipGroup::setDrawArea(const SGVec2d& lowerLeft,
141                          const SGVec2d& upperRight)
142 {
143   setDrawArea(lowerLeft,
144               SGVec2d(lowerLeft[0], upperRight[1]),
145               SGVec2d(upperRight[0], lowerLeft[1]),
146               upperRight);
147 }
148
149 void
150 SGClipGroup::setDrawArea(const SGVec2d& bottomLeft,
151                          const SGVec2d& topLeft,
152                          const SGVec2d& bottomRight,
153                          const SGVec2d& topRight)
154 {
155 #if (OPENSCENEGRAPH_MAJOR_VERSION > 2) || (OPENSCENEGRAPH_MINOR_VERSION > 2)
156   for (unsigned i = 0; i < mClipPlanes.size(); ++i)
157     getStateSet()->removeAssociatedModes(mClipPlanes[i].get());
158 #endif
159   mClipPlanes.resize(0);
160   addClipPlane(2, bottomLeft, topLeft);
161   addClipPlane(3, topLeft, topRight);
162   addClipPlane(4, topRight, bottomRight);
163   addClipPlane(5, bottomRight, bottomLeft);
164   _initialBound.init();
165   _initialBound.expandBy(osg::Vec3(bottomLeft[0], bottomLeft[1], 0));
166   _initialBound.expandBy(osg::Vec3(topLeft[0], topLeft[1], 0));
167   _initialBound.expandBy(osg::Vec3(bottomRight[0], bottomRight[1], 0));
168   _initialBound.expandBy(osg::Vec3(topRight[0], topRight[1], 0));
169   _boundingSphere = _initialBound;
170   _boundingSphereComputed = true;
171 }
172