[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] | 10 | Polygon3::Polygon3(): mMaterial(NULL), mParent(NULL) |
---|
[235] | 11 | {} |
---|
| 12 | |
---|
[286] | 13 | Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL), mParent(NULL) |
---|
[235] | 14 | {} |
---|
| 15 | |
---|
[286] | 16 | Polygon3::Polygon3(Intersectable *parent): mMaterial(NULL), mParent(parent) |
---|
| 17 | { |
---|
| 18 | } |
---|
| 19 | Polygon3::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] | 29 | Plane3 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] | 39 | void 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] | 109 | int 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 | |
---|
| 121 | int 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 | |
---|
| 173 | Vector3 |
---|
| 174 | Polygon3::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 | |
---|
| 185 | void |
---|
| 186 | Polygon3::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 | |
---|
| 195 | bool 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 | } |
---|