00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_COLLISION_MESH_BUILD_H
00027 #define NL_COLLISION_MESH_BUILD_H
00028
00029 #include <vector>
00030 #include <map>
00031
00032 #include "nel/misc/types_nl.h"
00033 #include "nel/misc/vector.h"
00034 #include "nel/misc/file.h"
00035
00036 #include "nel/misc/vector.h"
00037 #include "nel/misc/aabbox.h"
00038
00039
00040 namespace NLPACS
00041 {
00042
00043 struct CCollisionFace
00044 {
00046
00047
00049 uint32 V[3];
00050
00052 bool Visibility[3];
00053
00055 sint32 Surface;
00056
00058 sint32 Material;
00059
00060
00061
00062
00064
00065
00067 sint32 Edge[3];
00068
00070 sint32 InternalSurface;
00071
00073 bool EdgeFlags[3];
00074
00075
00076
00077
00079 enum
00080 {
00081 ExteriorSurface = -1,
00082 InteriorSurfaceFirst = 0
00083 };
00084
00086 void serial(NLMISC::IStream &f)
00087 {
00088 f.serial(V[0]);
00089 f.serial(V[1]);
00090 f.serial(V[2]);
00091
00092 f.serial(Visibility[0]);
00093 f.serial(Visibility[1]);
00094 f.serial(Visibility[2]);
00095
00096 f.serial(Surface, Material);
00097 }
00098 };
00099
00106 class CCollisionMeshBuild
00107 {
00108 private:
00109
00110 struct CEdgeKey
00111 {
00112 uint32 V0;
00113 uint32 V1;
00114
00115 CEdgeKey() {}
00116 CEdgeKey(uint32 v0, uint32 v1) : V0(v0), V1(v1) {}
00117
00118 bool operator() (const CEdgeKey &a, const CEdgeKey &b) const
00119 {
00120 return a.V0 < b.V0 || (a.V0 == b.V0 && a.V1 < b.V1);
00121 }
00122 };
00123
00124
00125 struct CEdgeInfo
00126 {
00127 sint32 Left, LeftEdge;
00128 sint32 Right, RightEdge;
00129
00130 CEdgeInfo(sint32 left=-1, sint32 leftEdge=-1, sint32 right=-1, sint32 rightEdge=-1) : Left(left), LeftEdge(leftEdge), Right(right), RightEdge(rightEdge) {}
00131 };
00132
00133 typedef std::map<CEdgeKey, CEdgeInfo, CEdgeKey> TLinkRelloc;
00134 typedef TLinkRelloc::iterator ItTLinkRelloc;
00135
00136 public:
00137
00138
00139 public:
00141 std::vector<NLMISC::CVector> Vertices;
00142
00144 std::vector<CCollisionFace> Faces;
00145
00146
00147 public:
00148 void serial(NLMISC::IStream &f)
00149 {
00150 f.serialCont(Vertices);
00151 f.serialCont(Faces);
00152 }
00153
00154 void translate(const NLMISC::CVector &translation)
00155 {
00156 uint i;
00157 for (i=0; i<Vertices.size(); ++i)
00158 Vertices[i] += translation;
00159 }
00160
00161 NLMISC::CVector computeTrivialTranslation() const
00162 {
00163 uint i;
00164 NLMISC::CAABBox bbox;
00165
00166 if (!Vertices.empty())
00167 {
00168 bbox.setCenter(Vertices[0]);
00169 for (i=1; i<Vertices.size(); ++i)
00170 bbox.extend(Vertices[i]);
00171 }
00172
00173 return -bbox.getCenter();
00174 }
00175
00176
00177 void link(bool linkInterior, std::vector<std::string> &errors)
00178 {
00179 uint i, j;
00180 TLinkRelloc relloc;
00181
00182
00183
00184 for (i=0; i<Faces.size(); ++i)
00185 {
00186 if (Faces[i].Surface == CCollisionFace::ExteriorSurface && linkInterior ||
00187 Faces[i].Surface >= CCollisionFace::InteriorSurfaceFirst && !linkInterior)
00188 continue;
00189
00190 for (j=0; j<3; ++j)
00191 {
00192 Faces[i].Edge[j] = -1;
00193
00194 uint edge = (j+2)%3;
00195 uint32 va = Faces[i].V[j],
00196 vb = Faces[i].V[(j+1)%3];
00197
00198 ItTLinkRelloc it;
00199 if ((it = relloc.find(CEdgeKey(va, vb))) != relloc.end())
00200 {
00201 CCollisionFace &left0 = Faces[(*it).second.Left];
00202 CCollisionFace &left1 = Faces[i];
00203
00204
00205 NLMISC::CVector eva = Vertices[va], evb = Vertices[vb];
00206 static char buf[512];
00207 sprintf(buf, "Edge issue: (%.2f,%.2f,%.2f)-(%.2f,%.2f,%.2f) [left face already found]\n"
00208 "left.0:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f) surf=%d material=%d\n"
00209 "left.1:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f) surf=%d material=%d",
00210 eva.x, eva.y, eva.z, evb.x, evb.y, evb.z,
00211 (*it).second.Left, Vertices[left0.V[0]].x, Vertices[left0.V[0]].y, Vertices[left0.V[1]].x, Vertices[left0.V[1]].y, Vertices[left0.V[2]].x, Vertices[left0.V[2]].y, Faces[(*it).second.Left].Surface, Faces[(*it).second.Left].Material,
00212 i, Vertices[left1.V[0]].x, Vertices[left1.V[0]].y, Vertices[left1.V[1]].x, Vertices[left1.V[1]].y, Vertices[left1.V[2]].x, Vertices[left1.V[2]].y, Faces[i].Surface, Faces[i].Material);
00213 errors.push_back(std::string(buf));
00214 continue;
00215
00216
00217 }
00218 else if ((it = relloc.find(CEdgeKey(vb, va))) != relloc.end())
00219 {
00220
00221 if ((*it).second.Right != -1)
00222 {
00223 CCollisionFace &right0 = Faces[(*it).second.Right];
00224 CCollisionFace &right1 = Faces[i];
00225 NLMISC::CVector eva = Vertices[va], evb = Vertices[vb];
00226 static char buf[512];
00227 sprintf(buf, "Edge issue: (%.2f,%.2f,%.2f)-(%.2f,%.2f,%.2f) [right face already found]\n"
00228 "right.0:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f)\n"
00229 "right.1:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f)",
00230 eva.x, eva.y, eva.z, evb.x, evb.y, evb.z,
00231 (*it).second.Right, Vertices[right0.V[0]].x, Vertices[right0.V[0]].y, Vertices[right0.V[1]].x, Vertices[right0.V[1]].y, Vertices[right0.V[2]].x, Vertices[right0.V[2]].y,
00232 i, Vertices[right1.V[0]].x, Vertices[right1.V[0]].y, Vertices[right1.V[1]].x, Vertices[right1.V[1]].y, Vertices[right1.V[2]].x, Vertices[right1.V[2]].y);
00233 errors.push_back(std::string(buf));
00234 continue;
00235
00236
00237 }
00238
00239 (*it).second.Right = i;
00240 (*it).second.RightEdge = edge;
00241 }
00242 else
00243 {
00244
00245 relloc.insert(std::make_pair(CEdgeKey(va, vb), CEdgeInfo(i, edge, -1, -1)));
00246 }
00247 }
00248 }
00249
00250
00251 ItTLinkRelloc it;
00252 for (it=relloc.begin(); it!=relloc.end(); ++it)
00253 {
00254 sint32 left, leftEdge;
00255 sint32 right, rightEdge;
00256
00257
00258 left = (*it).second.Left;
00259 leftEdge = (*it).second.LeftEdge;
00260 right = (*it).second.Right;
00261 rightEdge = (*it).second.RightEdge;
00262
00263
00264 if (left != -1)
00265 Faces[left].Edge[leftEdge] = right;
00266 if (right != -1)
00267 Faces[right].Edge[rightEdge] = left;
00268 }
00269 }
00270 };
00271
00272 };
00273
00274 #endif // NL_COLLISION_MESH_BUILD_H
00275
00276