source: trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp @ 295

Revision 295, 4.9 KB checked in by mattausch, 19 years ago (diff)

put out debug output. added new subdivision strategies

Line 
1#include "Polygon3.h"
2#include "Mesh.h"
3#include "ViewCellBsp.h" // TODO: erase this
4#include "Intersectable.h"
5#include "AxisAlignedBox3.h"
6
7// tolerance value for side relation
8#define SIDE_TOLERANCE 0.002f // TODO: Test different values
9#define SIDE_TOLERANCE_SQRD 0.000004f
10
11Polygon3::Polygon3(): mMaterial(NULL), mParent(NULL)
12{}
13
14Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL), mParent(NULL)
15{}
16
17Polygon3::Polygon3(Intersectable *parent): mMaterial(NULL), mParent(parent)
18{
19}
20Polygon3::Polygon3(Face *face, Mesh *parentMesh)
21{       
22        VertexIndexContainer::iterator it = face->mVertexIndices.begin();
23        for (; it != face->mVertexIndices.end();  ++it)
24        {
25                mVertices.push_back(parentMesh->mVertices[*it]);
26                mMaterial = parentMesh->mMaterial;
27        }
28}
29
30Plane3 Polygon3::GetSupportingPlane() const
31{
32        Vector3 v1 = mVertices[0] - mVertices[1];
33        Vector3 v2 = mVertices[2] - mVertices[1];
34#ifdef _DEBUG
35        Debug << "plane spanned by " <<  v1 << ", " << v2  << endl;
36#endif
37        return Plane3(mVertices[0], mVertices[1], mVertices[2]);
38}
39
40void Polygon3::Split(Plane3 *partition, Polygon3 *front, Polygon3 *back)
41{
42        Vector3 ptA = mVertices.back();
43       
44        int sideA = partition->Side(ptA, SIDE_TOLERANCE);
45       
46        VertexContainer::const_iterator it;
47        bool foundSplit = false;
48
49        Vector3 prevSplitPt(ptA);
50
51        // find line - plane intersections
52        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
53        {
54                Vector3 ptB = *it;
55                int sideB = partition->Side(ptB, SIDE_TOLERANCE);
56       
57                // vertices on different sides => split
58            if (sideB > 0)
59                {
60                        if (sideA < 0)
61                        {
62                                //-- plane - line intersection
63                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
64                       
65                                if (!foundSplit || (SqrDistance(splitPt, prevSplitPt) > SIDE_TOLERANCE_SQRD))
66                                {
67                                        // add vertex to both polygons
68                                        front->mVertices.push_back(splitPt);
69                                        back->mVertices.push_back(splitPt);
70
71                                        foundSplit = true;
72                                        prevSplitPt = splitPt;
73                                }
74                        }
75                        front->mVertices.push_back(ptB);
76                }
77                else if (sideB < 0)
78                {
79                        if (sideA > 0)
80                        {
81                                //-- plane - line intersection
82                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
83                       
84                                if (!foundSplit || (SqrDistance(splitPt, prevSplitPt) > SIDE_TOLERANCE_SQRD))
85                                {
86                                        // add vertex to both polygons
87                                        front->mVertices.push_back(splitPt);
88                                        back->mVertices.push_back(splitPt);
89
90                                        foundSplit = true;
91                                        prevSplitPt = splitPt;
92                                }       
93                        }
94                        back->mVertices.push_back(ptB);
95                }
96                else
97                {
98                        // vertex on plane => add vertex to both polygons
99                        front->mVertices.push_back(ptB);
100                        back->mVertices.push_back(ptB);
101                }
102       
103                ptA = ptB;
104                sideA = sideB;
105        }
106}
107
108int Polygon3::Side(const Plane3 &plane) const
109{
110        int classification = ClassifyPlane(plane);
111       
112        if (classification == BACK_SIDE)
113                return -1;
114        else if (classification == FRONT_SIDE)
115                return 1;
116
117        return 0;
118}
119
120int Polygon3::ClassifyPlane(const Plane3 &plane) const
121{
122        VertexContainer::const_iterator it;
123
124        bool onFrontSide = false;
125        bool onBackSide = false;
126        // threshold for coincident classification
127        const float dot_thres = 0.99f;
128
129        int count = 0;
130        // find possible line-plane intersections
131        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
132        {
133                int side = plane.Side(*it, SIDE_TOLERANCE);
134               
135                if (side > 0)
136                        onFrontSide = true;
137                else if (side < 0)
138                        onBackSide = true;
139               
140                //TODO: check if split goes through vertex
141                if (onFrontSide && onBackSide) // split
142                {
143                        return SPLIT;
144                }
145                // 3 vertices enough to decide coincident
146                else if (((++ count) >= 3) && !onFrontSide && !onBackSide)
147                {
148                        // Decide if plane and surface normal are same
149                        if (DotProd(plane.mNormal, GetSupportingPlane().mNormal) > dot_thres)
150                                return COINCIDENT; // plane and polygon are coincident
151                        else
152                                return FRONT_SIDE;
153                }
154        }
155
156        if (onBackSide)
157        {
158                return BACK_SIDE;
159        }
160        else if (onFrontSide)
161        {
162                return FRONT_SIDE;
163        }
164
165        // Decide if plane and surface normal are same
166        if (DotProd(plane.mNormal, GetSupportingPlane().mNormal) > dot_thres)
167                return COINCIDENT; // plane and polygon are coincident
168        else
169                return FRONT_SIDE;
170}
171
172
173Vector3
174Polygon3::Center() const
175{
176        int i;
177        Vector3 sum = mVertices[0];
178        for (i=1; i < mVertices.size(); i++)
179                sum += mVertices[i];
180       
181        return sum/(float)i;
182}
183
184
185void
186Polygon3::Scale(const float scale)
187{
188        int i;
189        Vector3 center = Center();
190        for (i=0; i < mVertices.size(); i++) {
191                mVertices[i] = center + scale*(mVertices[i] - center);
192        }
193}
194
195bool Polygon3::CheckValid() const
196{
197        if (mVertices.size() < 3)
198                return false;
199
200        Vector3 vtx = mVertices.back();
201        VertexContainer::const_iterator it, it_end = mVertices.end();
202
203        for (it = mVertices.begin(); it != it_end; ++it)
204        {
205                if (!(SqrDistance(vtx, *it) > SIDE_TOLERANCE_SQRD))
206                {
207                        Debug << "Malformed vertices:\n" << *this << endl;
208                        return false;
209                }
210                vtx = *it;
211        }
212       
213        return true;
214}
215
216void Polygon3::IncludeInBox(const PolygonContainer &polys, AxisAlignedBox3 &box)
217{
218        PolygonContainer::const_iterator it, it_end = polys.end();
219
220        for (it = polys.begin(); it != it_end; ++ it)
221                box.Include(*(*it));
222}
Note: See TracBrowser for help on using the repository browser.