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

Revision 291, 5.1 KB checked in by mattausch, 19 years ago (diff)
Line 
1#include "Polygon3.h"
2#include "Mesh.h"
3#include "ViewCellBsp.h" // TODO: erase this
4#include "Intersectable.h"
5
6// tolerance value for side relation
7#define SIDE_TOLERANCE 0.002f // TODO: Test different values
8#define SIDE_TOLERANCE_SQRD 0.000004f
9
10Polygon3::Polygon3(): mMaterial(NULL), mParent(NULL)
11{}
12
13Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL), mParent(NULL)
14{}
15
16Polygon3::Polygon3(Intersectable *parent): mMaterial(NULL), mParent(parent)
17{
18}
19Polygon3::Polygon3(Face *face, Mesh *parentMesh)
20{       
21        VertexIndexContainer::iterator it = face->mVertexIndices.begin();
22        for (; it != face->mVertexIndices.end();  ++it)
23        {
24                mVertices.push_back(parentMesh->mVertices[*it]);
25                mMaterial = parentMesh->mMaterial;
26        }
27}
28
29Plane3 Polygon3::GetSupportingPlane() const
30{
31        Vector3 v1 = mVertices[0] - mVertices[1];
32        Vector3 v2 = mVertices[2] - mVertices[1];
33#ifdef _DEBUG
34        Debug << "plane spanned by " <<  v1 << ", " << v2  << endl;
35#endif
36        return Plane3(mVertices[0], mVertices[1], mVertices[2]);
37}
38
39void Polygon3::Split(Plane3 *partition, Polygon3 *front, Polygon3 *back)
40{
41        Vector3 ptA = mVertices.back();
42       
43        int sideA = partition->Side(ptA, SIDE_TOLERANCE);
44       
45        VertexContainer::const_iterator it;
46        bool foundSplit = false;
47
48        Vector3 prevSplitPt(ptA);
49
50        // find line - plane intersections
51        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
52        {
53                Vector3 ptB = *it;
54                int sideB = partition->Side(ptB, SIDE_TOLERANCE);
55       
56                // vertices on different sides => split
57            if (sideB > 0)
58                {
59                        if (sideA < 0)
60                        {
61                                //-- plane - line intersection
62                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
63                                Debug << "fpg " << splitPt << " side " << partition->Side(splitPt, SIDE_TOLERANCE) <<
64                                        "\nptA " << ptA << " side " << sideA << "\nptB " << ptB << " side " << sideB << " " << Distance(ptB, splitPt) << endl;
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                        //      if (foundSplit) Debug << "back split pt " << splitPt << " prev " << prevSplitPt << endl;
84                                if (!foundSplit || (SqrDistance(splitPt, prevSplitPt) > SIDE_TOLERANCE_SQRD))
85                                {
86                                        //Debug << "add back split vertex " << splitPt << endl;
87                                        // add vertex to both polygons
88                                        front->mVertices.push_back(splitPt);
89                                        back->mVertices.push_back(splitPt);
90
91                                        foundSplit = true;
92                                        prevSplitPt = splitPt;
93                                }//else Debug << "reject back split vertex " << splitPt << endl;       
94                        }
95                        back->mVertices.push_back(ptB);
96                }
97                else
98                {
99                        // vertex on plane => add vertex to both polygons
100                        front->mVertices.push_back(ptB);
101                        back->mVertices.push_back(ptB);
102                }
103       
104                ptA = ptB;
105                sideA = sideB;
106        }
107}
108
109int Polygon3::Side(const Plane3 &plane) const
110{
111        int classification = ClassifyPlane(plane);
112       
113        if (classification == BACK_SIDE)
114                return -1;
115        else if (classification == FRONT_SIDE)
116                return 1;
117
118        return 0;
119}
120
121int Polygon3::ClassifyPlane(const Plane3 &plane) const
122{
123        VertexContainer::const_iterator it;
124
125        bool onFrontSide = false;
126        bool onBackSide = false;
127
128        int count = 0;
129        // find possible line-plane intersections
130        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
131        {
132                int side = plane.Side(*it, SIDE_TOLERANCE);
133                //Debug << "side: " << side << " " << plane.Distance(*it) << endl;
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) > 0)
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) > 0)
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}
Note: See TracBrowser for help on using the repository browser.