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

Revision 291, 5.1 KB checked in by mattausch, 19 years ago (diff)
RevLine 
[235]1#include "Polygon3.h"
2#include "Mesh.h"
[268]3#include "ViewCellBsp.h" // TODO: erase this
[286]4#include "Intersectable.h"
5
[268]6// tolerance value for side relation
[261]7#define SIDE_TOLERANCE 0.002f // TODO: Test different values
[289]8#define SIDE_TOLERANCE_SQRD 0.000004f
[238]9
[286]10Polygon3::Polygon3(): mMaterial(NULL), mParent(NULL)
[235]11{}
12
[286]13Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL), mParent(NULL)
[235]14{}
15
[286]16Polygon3::Polygon3(Intersectable *parent): mMaterial(NULL), mParent(parent)
17{
18}
19Polygon3::Polygon3(Face *face, Mesh *parentMesh)
[264]20{       
21        VertexIndexContainer::iterator it = face->mVertexIndices.begin();
22        for (; it != face->mVertexIndices.end();  ++it)
[235]23        {
[286]24                mVertices.push_back(parentMesh->mVertices[*it]);
25                mMaterial = parentMesh->mMaterial;
[235]26        }
27}
28
[238]29Plane3 Polygon3::GetSupportingPlane() const
[235]30{
[238]31        Vector3 v1 = mVertices[0] - mVertices[1];
[239]32        Vector3 v2 = mVertices[2] - mVertices[1];
33#ifdef _DEBUG
34        Debug << "plane spanned by " <<  v1 << ", " << v2  << endl;
35#endif
[235]36        return Plane3(mVertices[0], mVertices[1], mVertices[2]);
37}
38
[289]39void Polygon3::Split(Plane3 *partition, Polygon3 *front, Polygon3 *back)
[235]40{
[289]41        Vector3 ptA = mVertices.back();
[235]42       
[238]43        int sideA = partition->Side(ptA, SIDE_TOLERANCE);
[235]44       
45        VertexContainer::const_iterator it;
[289]46        bool foundSplit = false;
[235]47
[289]48        Vector3 prevSplitPt(ptA);
49
[235]50        // find line - plane intersections
51        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
52        {
[289]53                Vector3 ptB = *it;
[238]54                int sideB = partition->Side(ptB, SIDE_TOLERANCE);
[239]55       
[235]56                // vertices on different sides => split
[237]57            if (sideB > 0)
58                {
59                        if (sideA < 0)
60                        {
61                                //-- plane - line intersection
62                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
[290]63                                Debug << "fpg " << splitPt << " side " << partition->Side(splitPt, SIDE_TOLERANCE) <<
64                                        "\nptA " << ptA << " side " << sideA << "\nptB " << ptB << " side " << sideB << " " << Distance(ptB, splitPt) << endl;
[289]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                                }
[237]74                        }
[239]75                        front->mVertices.push_back(ptB);
[237]76                }
77                else if (sideB < 0)
78                {
79                        if (sideA > 0)
[235]80                        {
[237]81                                //-- plane - line intersection
82                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
[289]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);
[237]90
[289]91                                        foundSplit = true;
92                                        prevSplitPt = splitPt;
93                                }//else Debug << "reject back split vertex " << splitPt << endl;       
[235]94                        }
[239]95                        back->mVertices.push_back(ptB);
[235]96                }
[237]97                else
[235]98                {
[237]99                        // vertex on plane => add vertex to both polygons
[235]100                        front->mVertices.push_back(ptB);
[239]101                        back->mVertices.push_back(ptB);
[235]102                }
[237]103       
[235]104                ptA = ptB;
105                sideA = sideB;
106        }
107}
108
[238]109int Polygon3::Side(const Plane3 &plane) const
[235]110{
[238]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{
[235]123        VertexContainer::const_iterator it;
124
125        bool onFrontSide = false;
126        bool onBackSide = false;
127
[265]128        int count = 0;
[238]129        // find possible line-plane intersections
[235]130        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
131        {
[238]132                int side = plane.Side(*it, SIDE_TOLERANCE);
[289]133                //Debug << "side: " << side << " " << plane.Distance(*it) << endl;
[265]134
[235]135                if (side > 0)
136                        onFrontSide = true;
137                else if (side < 0)
138                        onBackSide = true;
[265]139               
[264]140                //TODO: check if split goes through vertex
141                if (onFrontSide && onBackSide) // split
[235]142                {
143                        return SPLIT;
144                }
[265]145                // 3 vertices enough to decide coincident
146                else if (((++ count) >= 3) && !onFrontSide && !onBackSide)
[289]147                {
148                        // Decide if plane and surface normal are same
149                        if (DotProd(plane.mNormal, GetSupportingPlane().mNormal) > 0)
[291]150                                return COINCIDENT; // plane and polygon are coincident
[289]151                        else
152                                return FRONT_SIDE;
153                }
[235]154        }
155
156        if (onBackSide)
157        {
158                return BACK_SIDE;
159        }
160        else if (onFrontSide)
161        {
162                return FRONT_SIDE;
163        }
164
[291]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;
[235]170}
171
[256]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       
[289]181        return sum/(float)i;
[256]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}
[289]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.