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

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