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

RevLine 
[235]1#include "Polygon3.h"
2#include "Mesh.h"
[268]3#include "ViewCellBsp.h" // TODO: erase this
[286]4#include "Intersectable.h"
[295]5#include "AxisAlignedBox3.h"
[286]6
[268]7// tolerance value for side relation
[261]8#define SIDE_TOLERANCE 0.002f // TODO: Test different values
[289]9#define SIDE_TOLERANCE_SQRD 0.000004f
[238]10
[286]11Polygon3::Polygon3(): mMaterial(NULL), mParent(NULL)
[235]12{}
13
[286]14Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL), mParent(NULL)
[235]15{}
16
[286]17Polygon3::Polygon3(Intersectable *parent): mMaterial(NULL), mParent(parent)
18{
19}
20Polygon3::Polygon3(Face *face, Mesh *parentMesh)
[264]21{       
22        VertexIndexContainer::iterator it = face->mVertexIndices.begin();
23        for (; it != face->mVertexIndices.end();  ++it)
[235]24        {
[286]25                mVertices.push_back(parentMesh->mVertices[*it]);
26                mMaterial = parentMesh->mMaterial;
[235]27        }
28}
29
[238]30Plane3 Polygon3::GetSupportingPlane() const
[235]31{
[238]32        Vector3 v1 = mVertices[0] - mVertices[1];
[239]33        Vector3 v2 = mVertices[2] - mVertices[1];
34#ifdef _DEBUG
35        Debug << "plane spanned by " <<  v1 << ", " << v2  << endl;
36#endif
[235]37        return Plane3(mVertices[0], mVertices[1], mVertices[2]);
38}
39
[289]40void Polygon3::Split(Plane3 *partition, Polygon3 *front, Polygon3 *back)
[235]41{
[289]42        Vector3 ptA = mVertices.back();
[235]43       
[238]44        int sideA = partition->Side(ptA, SIDE_TOLERANCE);
[235]45       
46        VertexContainer::const_iterator it;
[289]47        bool foundSplit = false;
[235]48
[289]49        Vector3 prevSplitPt(ptA);
50
[235]51        // find line - plane intersections
52        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
53        {
[289]54                Vector3 ptB = *it;
[238]55                int sideB = partition->Side(ptB, SIDE_TOLERANCE);
[239]56       
[235]57                // vertices on different sides => split
[237]58            if (sideB > 0)
59                {
60                        if (sideA < 0)
61                        {
62                                //-- plane - line intersection
63                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
[294]64                       
[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);
[294]83                       
[289]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);
[237]89
[289]90                                        foundSplit = true;
91                                        prevSplitPt = splitPt;
[294]92                                }       
[235]93                        }
[239]94                        back->mVertices.push_back(ptB);
[235]95                }
[237]96                else
[235]97                {
[237]98                        // vertex on plane => add vertex to both polygons
[235]99                        front->mVertices.push_back(ptB);
[239]100                        back->mVertices.push_back(ptB);
[235]101                }
[237]102       
[235]103                ptA = ptB;
104                sideA = sideB;
105        }
106}
107
[238]108int Polygon3::Side(const Plane3 &plane) const
[235]109{
[238]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{
[235]122        VertexContainer::const_iterator it;
123
124        bool onFrontSide = false;
125        bool onBackSide = false;
[294]126        // threshold for coincident classification
127        const float dot_thres = 0.99f;
[235]128
[265]129        int count = 0;
[238]130        // find possible line-plane intersections
[235]131        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
132        {
[238]133                int side = plane.Side(*it, SIDE_TOLERANCE);
[294]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
[294]149                        if (DotProd(plane.mNormal, GetSupportingPlane().mNormal) > dot_thres)
[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
[294]166        if (DotProd(plane.mNormal, GetSupportingPlane().mNormal) > dot_thres)
[291]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}
[295]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.