- Timestamp:
- 09/07/08 13:44:28 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp
r2802 r2911 1 #include "AxisAlignedBox3.h" 2 #include "Plane3.h" 3 #include "Polygon3.h" 4 #include "Polyhedron.h" 5 1 6 #include <cassert> 2 7 #include <iostream> 3 #include "AxisAlignedBox3.h"4 #include "Plane3.h"5 6 8 7 9 using namespace std; … … 50 52 Minimize(mMin, newpt); 51 53 Maximize(mMax, newpt); 54 } 55 56 57 void AxisAlignedBox3::Include(const Polygon3 &newpoly) 58 { 59 VertexArray::const_iterator it, it_end = newpoly.mVertices.end(); 60 61 for (it = newpoly.mVertices.begin(); it != it_end; ++ it) 62 Include(*it); 63 } 64 65 66 void AxisAlignedBox3::Include(const PolygonContainer &polys) 67 { 68 PolygonContainer::const_iterator it, it_end = polys.end(); 69 70 for (it = polys.begin(); it != it_end; ++ it) 71 Include(*(*it)); 52 72 } 53 73 … … 1026 1046 } 1027 1047 1028 } 1029 1048 1049 struct VertexData 1050 { 1051 Vector3 mVertex; 1052 float mAngle; 1053 1054 VertexData(Vector3 vtx, float angle): mVertex(vtx), mAngle(angle) 1055 {} 1056 1057 bool operator<(const VertexData &b) const 1058 { 1059 return mAngle > b.mAngle; 1060 } 1061 }; 1062 1063 // TODO: use a table to avoid normal and distance computations 1064 Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const 1065 { 1066 Polygon3 *planePoly = new Polygon3(); 1067 1068 int side[8]; 1069 bool onFrontSide = false, onBackSide = false; 1070 1071 Vector3 vtx; 1072 1073 ////////////// 1074 //-- compute classification of vertices 1075 1076 for (int i = 0; i < 8; ++i) 1077 { 1078 GetVertex(i, vtx); 1079 side[i] = plane.Side(vtx); 1080 if (side[i] > 0) 1081 onFrontSide = true; 1082 else if (side[i] < 0) 1083 onBackSide = true; 1084 else // vertex coincident => push_back 1085 planePoly->mVertices.push_back(vtx); 1086 } 1087 1088 /////////// 1089 //-- find intersections 1090 1091 if (onFrontSide && onBackSide) 1092 { 1093 Vector3 ptA, ptB; 1094 for (int i = 0; i < 12; ++ i) 1095 { 1096 int aIdx, bIdx; 1097 GetEdge(i, aIdx, bIdx); 1098 1099 ptA = GetVertex(aIdx); 1100 ptB = GetVertex(bIdx); 1101 1102 int sideA = side[aIdx]; 1103 int sideB = side[bIdx]; 1104 1105 if (((sideA > 0) && (sideB < 0)) || (sideA < 0) && (sideB > 0)) 1106 planePoly->mVertices.push_back(plane.FindIntersection(ptA, ptB)); 1107 } 1108 } 1109 1110 // order intersections 1111 if (planePoly->mVertices.size() > 3) 1112 { 1113 Vector3 centerOfMass(0); 1114 1115 int i; 1116 // compute center of mass 1117 for (i = 0; i < (int)planePoly->mVertices.size(); ++ i) 1118 centerOfMass += planePoly->mVertices[i]; 1119 1120 centerOfMass /= (float)planePoly->mVertices.size(); 1121 1122 vector<VertexData> vertexData; 1123 Vector3 refVec = Normalize(centerOfMass - planePoly->mVertices[0]); 1124 1125 // compute angle to reference point 1126 for (i = 1; i < (int)planePoly->mVertices.size(); ++ i) 1127 { 1128 float angle = 1129 Angle(refVec, centerOfMass - planePoly->mVertices[i], plane.mNormal); 1130 1131 vertexData.push_back(VertexData(planePoly->mVertices[i], angle)); 1132 } 1133 1134 std::stable_sort(vertexData.begin(), vertexData.end()); 1135 1136 // update vertices 1137 for (i = 1; i < (int)planePoly->mVertices.size(); ++ i) 1138 planePoly->mVertices[i] = vertexData[i - 1].mVertex; 1139 } 1140 else if (planePoly->mVertices.size() == 3) 1141 { 1142 // fix orientation if needed 1143 if (DotProd(planePoly->GetNormal(), plane.mNormal) < 0) 1144 { 1145 Vector3 v = planePoly->mVertices[1]; 1146 planePoly->mVertices[1] = planePoly->mVertices[2]; 1147 planePoly->mVertices[2] = v; 1148 } 1149 } 1150 1151 return planePoly; 1152 } 1153 1154 1155 Plane3 AxisAlignedBox3::GetPlane(const int face) const 1156 { 1157 switch (face) 1158 { 1159 1160 case 0: 1161 return Plane3(Vector3(-1, 0, 0), mMin); 1162 case 1: 1163 return Plane3(Vector3(1, 0, 0), mMax); 1164 case 2: 1165 return Plane3(Vector3(0, -1, 0), mMin); 1166 case 3: 1167 return Plane3(Vector3(0, 1, 0), mMax); 1168 case 4: 1169 return Plane3(Vector3(0, 0, -1), mMin); 1170 case 5: 1171 return Plane3(Vector3(0, 0, 1), mMax); 1172 } 1173 1174 // should not come here 1175 return Plane3(); 1176 } 1177 1178 1179 int AxisAlignedBox3::Side(const Plane3 &plane) const 1180 { 1181 int s = 0; 1182 // if exactly one of the vertices lies on the plane 1183 // and the others are on the same side, the plane is tangent 1184 // to the box on either side and not intersecting 1185 for (int i = 0; i < 8; ++ i) 1186 { 1187 Vector3 pt; 1188 GetVertex(i, pt); 1189 1190 int side = plane.Side(pt); 1191 1192 if (side != 0) 1193 { 1194 if (side == -s) 1195 return 0; // sign changed => intersects 1196 1197 s = side; 1198 } 1199 } 1200 1201 return s; 1202 } 1203 1204 1205 Polyhedron *AxisAlignedBox3::CalcIntersection(Polyhedron *polyhedron) const 1206 { 1207 Polyhedron *oldPolyhedron = new Polyhedron(*polyhedron); 1208 1209 Polyhedron *newPolyhedron = NULL; 1210 1211 for (int i = 0; i < 6; ++ i) 1212 { 1213 Polyhedron *newPolyhedron = oldPolyhedron->CalcIntersection(GetPlane(i)); 1214 DEL_PTR(oldPolyhedron); 1215 1216 if (!newPolyhedron) 1217 return NULL; 1218 } 1219 1220 return newPolyhedron; 1221 } 1222 1223 1224 } 1225
Note: See TracChangeset
for help on using the changeset viewer.