root/OpenSceneGraph/trunk/src/osg/ClusterCullingCallback.cpp @ 13041

Revision 13041, 5.4 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/ClusterCullingCallback>
14#include <osg/TriangleFunctor>
15#include <osg/CullSettings>
16
17using namespace osg;
18
19
20///////////////////////////////////////////////////////////////////////////////////////////
21//
22//  Cluster culling callback
23//
24
25ClusterCullingCallback::ClusterCullingCallback():
26    _radius(-1.0f),
27    _deviation(-1.0f)
28{
29}
30
31ClusterCullingCallback::ClusterCullingCallback(const ClusterCullingCallback& ccc,const CopyOp& copyop):
32    Drawable::CullCallback(ccc,copyop),
33    _controlPoint(ccc._controlPoint),
34    _normal(ccc._normal),
35    _radius(ccc._radius),
36    _deviation(ccc._deviation)
37{
38}
39
40ClusterCullingCallback::ClusterCullingCallback(const osg::Vec3& controlPoint, const osg::Vec3& normal, float deviation):
41    _controlPoint(controlPoint),
42    _normal(normal),
43    _radius(-1.0f),
44    _deviation(deviation)
45{
46}
47
48ClusterCullingCallback::ClusterCullingCallback(const osg::Drawable* drawable)
49{
50    computeFrom(drawable);
51}
52
53struct ComputeAveragesFunctor
54{
55
56    ComputeAveragesFunctor():
57        _num(0) {}
58
59    inline void operator() ( const osg::Vec3 &v1, const osg::Vec3 &v2, const osg::Vec3 &v3, bool)
60    {
61        // calc orientation of triangle.
62        osg::Vec3d normal = (v2-v1)^(v3-v1);
63        if (normal.normalize()!=0.0f)
64        {
65            _normal += normal;
66        }
67        _center += v1;
68        _center += v2;
69        _center += v3;
70
71        ++_num;
72
73    }
74
75    osg::Vec3 center() { return _center /  (double)(3*_num); }
76    osg::Vec3 normal() { _normal.normalize(); return _normal; }
77
78    unsigned int _num;
79    Vec3d _center;
80    Vec3d _normal;
81};
82
83struct ComputeDeviationFunctor
84{
85
86    ComputeDeviationFunctor():
87        _deviation(1.0),
88        _radius2(0.0) {}
89
90    void set(const osg::Vec3& center,const osg::Vec3& normal)
91    {
92        _center = center;
93        _normal = normal;
94    }
95
96    inline void operator() ( const osg::Vec3 &v1, const osg::Vec3 &v2, const osg::Vec3 &v3, bool)
97    {
98        // calc orientation of triangle.
99        osg::Vec3 normal = (v2-v1)^(v3-v1);
100        if (normal.normalize()!=0.0f)
101        {
102            _deviation = osg::minimum(_normal*normal,_deviation);
103        }
104        _radius2 = osg::maximum((v1-_center).length2(),_radius2);
105        _radius2 = osg::maximum((v2-_center).length2(),_radius2);
106        _radius2 = osg::maximum((v3-_center).length2(),_radius2);
107
108    }
109    osg::Vec3 _center;
110    osg::Vec3 _normal;
111    float _deviation;
112    float _radius2;
113};
114
115
116void ClusterCullingCallback::computeFrom(const osg::Drawable* drawable)
117{
118    TriangleFunctor<ComputeAveragesFunctor> caf;
119    drawable->accept(caf);
120
121    _controlPoint = caf.center();
122    _normal = caf.normal();
123
124    TriangleFunctor<ComputeDeviationFunctor> cdf;
125    cdf.set(_controlPoint,_normal);
126    drawable->accept(cdf);
127
128//    OSG_NOTICE<<"ClusterCullingCallback::computeFrom() _controlPoint="<<_controlPoint<<std::endl;
129//    OSG_NOTICE<<"                                      _normal="<<_normal<<std::endl;
130//    OSG_NOTICE<<"                                      cdf._deviation="<<cdf._deviation<<std::endl;
131
132
133    if (_normal.length2()==0.0) _deviation = -1.0f;
134    else
135    {
136        float angle = acosf(cdf._deviation)+osg::PI*0.5f;
137        if (angle<osg::PI) _deviation = cosf(angle);
138        else _deviation = -1.0f;
139    }
140
141    _radius = sqrtf(cdf._radius2);
142}
143
144void ClusterCullingCallback::set(const osg::Vec3& controlPoint, const osg::Vec3& normal, float deviation, float radius)
145{
146    _controlPoint = controlPoint;
147    _normal = normal;
148    _deviation = deviation;
149    _radius = radius;
150}
151
152void ClusterCullingCallback::transform(const osg::Matrixd& matrix)
153{
154    _controlPoint = Vec3d(_controlPoint)*matrix;
155    _normal = Matrixd::transform3x3(Matrixd::inverse(matrix),Vec3d(_normal));
156    _normal.normalize();
157}
158
159
160bool ClusterCullingCallback::cull(osg::NodeVisitor* nv, osg::Drawable* , osg::State*) const
161{
162    CullSettings* cs = dynamic_cast<CullSettings*>(nv);
163    if (cs && !(cs->getCullingMode() & CullSettings::CLUSTER_CULLING))
164    {
165        // cluster culling switched off cull settings.
166        return false;
167    }
168
169    if (_deviation<=-1.0f)
170    {
171        // cluster culling switch off by deviation.
172        return false;
173    }
174
175    osg::Vec3 eye_cp = nv->getViewPoint() - _controlPoint;
176    float radius = eye_cp.length();
177
178    if (radius<_radius)
179    {
180        return false;
181    }
182
183
184    float deviation = (eye_cp * _normal)/radius;
185
186//    OSG_NOTICE<<"ClusterCullingCallback::cull() _normal="<<_normal<<" _controlPointtest="<<_controlPoint<<" eye_cp="<<eye_cp<<std::endl;
187//    OSG_NOTICE<<"                             deviation="<<deviation<<" _deviation="<<_deviation<<" test="<<(deviation < _deviation)<<std::endl;
188
189    return deviation < _deviation;
190}
191
192
193void ClusterCullingCallback::operator()(Node* node, NodeVisitor* nv)
194{
195    if (nv)
196    {
197        if (cull(nv,0,static_cast<State *>(0))) return;
198
199        traverse(node,nv);
200    }
201}
Note: See TracBrowser for help on using the browser.