1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 20017 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 
14 #include <osg/Polytope>
15 #include <osg/Notify>
16 
17 using namespace osg;
18 
contains(const osg::Vec3f & v0,const osg::Vec3f & v1,const osg::Vec3f & v2) const19 bool Polytope::contains(const osg::Vec3f& v0, const osg::Vec3f& v1, const osg::Vec3f& v2) const
20 {
21     if (!_maskStack.back()) return true;
22 
23     // initialize the set of vertices to test.
24     typedef std::vector<osg::Vec3d> Vertices;
25 
26     Vertices src, dest;
27     src.reserve(4+_planeList.size());
28     dest.reserve(4+_planeList.size());
29 
30     src.push_back(v0);
31     src.push_back(v1);
32     src.push_back(v2);
33     src.push_back(v0);
34 
35     ClippingMask resultMask = _maskStack.back();
36     ClippingMask selector_mask = 0x1;
37 
38     for(PlaneList::const_iterator pitr = _planeList.begin();
39         pitr != _planeList.end();
40         ++pitr)
41     {
42         if (resultMask&selector_mask)
43         {
44             //OSG_NOTICE<<"Polytope::contains() Plane testing"<<std::endl;
45 
46             dest.clear();
47 
48             const osg::Plane& plane = *pitr;
49             Vertices::iterator vitr = src.begin();
50 
51             osg::Vec3d* v_previous = &(*(vitr++));
52             double d_previous = plane.distance(*v_previous);
53 
54             for(; vitr != src.end(); ++vitr)
55             {
56                 osg::Vec3d* v_current = &(*vitr);
57                 double d_current = plane.distance(*v_current);
58 
59                 if (d_previous>=0.0)
60                 {
61                     dest.push_back(*v_previous);
62                 }
63 
64                 if (d_previous*d_current<0.0)
65                 {
66                     // edge crosses plane so insert the vertex between them.
67                     double distance = d_previous-d_current;
68                     double r_current = d_previous/distance;
69                     osg::Vec3d v_new = (*v_previous)*(1.0-r_current) + (*v_current)*r_current;
70                     dest.push_back(v_new);
71                 }
72 
73                 d_previous = d_current;
74                 v_previous = v_current;
75 
76             }
77 
78             if (d_previous>=0.0)
79             {
80                 dest.push_back(*v_previous);
81             }
82 
83             if (dest.size()<=1)
84             {
85                 // OSG_NOTICE<<"Polytope::contains() All points on triangle culled, dest.size()="<<dest.size()<<std::endl;
86                 return false;
87             }
88 
89             dest.swap(src);
90         }
91         else
92         {
93             // OSG_NOTICE<<"Polytope::contains() Plane disabled"<<std::endl;
94         }
95 
96         selector_mask <<= 1;
97     }
98 
99     //OSG_NOTICE<<"Polytope::contains() triangle within Polytope, src.size()="<<src.size()<<std::endl;
100     return true;
101 }
102