#include "Polygon3.h" #include "Mesh.h" #define SIDE_TOLERANCE 0.002 // TODO: Test different values Polygon3::Polygon3(): mMaterial(NULL) {} Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL) {} Polygon3::Polygon3(Face *face, Mesh *parent) { VertexIndexContainer::const_iterator it; for (it = face->mVertexIndices.begin(); it != face->mVertexIndices.end(); ++ it) { mVertices.push_back(parent->mVertices[*it]); mMaterial = parent->mMaterial; Debug << parent->mVertices[*it] << endl; } } Plane3 Polygon3::GetSupportingPlane() const { Vector3 v1 = mVertices[0] - mVertices[1]; Vector3 v2 = mVertices[2] - mVertices[1]; #ifdef _DEBUG Debug << "plane spanned by " << v1 << ", " << v2 << endl; #endif return Plane3(mVertices[0], mVertices[1], mVertices[2]); } void Polygon3::DeletePolygons(PolygonContainer *polys) { // don't need to store polygon information => delete polygons while(!polys->empty()) { Polygon3 *poly = polys->back(); polys->pop_back(); DEL_PTR(poly); } } void Polygon3::Split(Plane3 *partition, Polygon3 *front, Polygon3 *back, int &splits) { splits = 0; Vector3 ptA = mVertices[mVertices.size() - 1]; int sideA = partition->Side(ptA, SIDE_TOLERANCE); VertexContainer::const_iterator it; // find line - plane intersections for (it = mVertices.begin(); it != mVertices.end(); ++ it) { Vector3 ptB = (*it); int sideB = partition->Side(ptB, SIDE_TOLERANCE); // vertices on different sides => split if (sideB > 0) { if (sideA < 0) { //-- plane - line intersection Vector3 splitPt = partition->FindIntersection(ptA, ptB); // add vertex to both polygons front->mVertices.push_back(splitPt); back->mVertices.push_back(splitPt); ++ splits; } front->mVertices.push_back(ptB); } else if (sideB < 0) { if (sideA > 0) { //-- plane - line intersection Vector3 splitPt = partition->FindIntersection(ptA, ptB); // add vertex to both polygons front->mVertices.push_back(splitPt); back->mVertices.push_back(splitPt); ++ splits; } back->mVertices.push_back(ptB); } else { // vertex on plane => add vertex to both polygons front->mVertices.push_back(ptB); back->mVertices.push_back(ptB); } ptA = ptB; sideA = sideB; } } int Polygon3::Side(const Plane3 &plane) const { int classification = ClassifyPlane(plane); if (classification == BACK_SIDE) return -1; else if (classification == FRONT_SIDE) return 1; return 0; } int Polygon3::ClassifyPlane(const Plane3 &plane) const { VertexContainer::const_iterator it; bool onFrontSide = false; bool onBackSide = false; // find possible line-plane intersections for (it = mVertices.begin(); it != mVertices.end(); ++ it) { int side = plane.Side(*it, SIDE_TOLERANCE); if (side > 0) { onFrontSide = true; } else if (side < 0) { onBackSide = true; } if (onFrontSide && onBackSide) // split //TODO: check if through vvertex { return SPLIT; } } if (onBackSide) { return BACK_SIDE; } else if (onFrontSide) { return FRONT_SIDE; } // plane and polygon are coincident return COINCIDENT; } Vector3 Polygon3::Center() const { int i; Vector3 sum = mVertices[0]; for (i=1; i < mVertices.size(); i++) sum += mVertices[i]; return sum/i; } void Polygon3::Scale(const float scale) { int i; Vector3 center = Center(); for (i=0; i < mVertices.size(); i++) { mVertices[i] = center + scale*(mVertices[i] - center); } }