collision_mesh_build.h

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #ifndef NL_COLLISION_MESH_BUILD_H
00025 #define NL_COLLISION_MESH_BUILD_H
00026 
00027 #include <vector>
00028 #include <map>
00029 
00030 #include "nel/misc/types_nl.h"
00031 #include "nel/misc/vector.h"
00032 #include "nel/misc/matrix.h"
00033 #include "nel/misc/file.h"
00034 
00035 #include "nel/misc/vector.h"
00036 #include "nel/misc/aabbox.h"
00037 
00038 
00039 namespace NLPACS
00040 {
00041 
00042 struct CCollisionFace
00043 {
00045     // @{
00046 
00048     uint32  V[3];
00049 
00051     bool    Visibility[3];
00052 
00054     sint32  Surface;
00055 
00057     sint32  Material;
00058 
00059     // @}
00060 
00061 
00063     // @{
00064 
00066     sint32  Edge[3];
00067 
00069     sint32  InternalSurface;
00070 
00072     bool    EdgeFlags[3];
00073 
00074     // @}
00075 
00076 
00078     enum
00079     {
00080         ExteriorSurface = -1,
00081         InteriorSurfaceFirst = 0
00082     };
00083 
00085     void    serial(NLMISC::IStream &f)
00086     {
00087         f.serial(V[0]);
00088         f.serial(V[1]);
00089         f.serial(V[2]);
00090 
00091         f.serial(Visibility[0]);
00092         f.serial(Visibility[1]);
00093         f.serial(Visibility[2]);
00094 
00095         f.serial(Surface, Material);
00096     }
00097 };
00098 
00105 class CCollisionMeshBuild
00106 {
00107 private:
00108     // a reference on an edge
00109     struct CEdgeKey
00110     {
00111         uint32  V0;
00112         uint32  V1;
00113 
00114         CEdgeKey() {}
00115         CEdgeKey(uint32 v0, uint32 v1) : V0(v0), V1(v1) {}
00116 
00117         bool    operator() (const CEdgeKey &a, const CEdgeKey &b) const
00118         {
00119             return a.V0 < b.V0 || (a.V0 == b.V0 && a.V1 < b.V1);
00120         }
00121     };
00122 
00123     // the info on an edge
00124     struct CEdgeInfo
00125     {
00126         sint32  Left, LeftEdge;
00127         sint32  Right, RightEdge;
00128 
00129         CEdgeInfo(sint32 left=-1, sint32 leftEdge=-1, sint32 right=-1, sint32 rightEdge=-1) : Left(left), LeftEdge(leftEdge), Right(right), RightEdge(rightEdge) {}
00130     };
00131 
00132     typedef std::map<CEdgeKey, CEdgeInfo, CEdgeKey> TLinkRelloc;
00133     typedef TLinkRelloc::iterator                   ItTLinkRelloc;
00134 
00135 public:
00136 
00137 
00138 public:
00140     std::vector<NLMISC::CVector>    Vertices;
00141 
00143     std::vector<CCollisionFace>     Faces;
00144 
00145 
00146 public:
00147     void    serial(NLMISC::IStream &f)
00148     {
00149         f.serialCont(Vertices);
00150         f.serialCont(Faces);
00151     }
00152 
00153     void    translate(const NLMISC::CVector &translation)
00154     {
00155         uint    i;
00156         for (i=0; i<Vertices.size(); ++i)
00157             Vertices[i] += translation;
00158     }
00159 
00160     void    transform(const NLMISC::CMatrix &tranfo)
00161     {
00162         uint    i;
00163         for (i=0; i<Vertices.size(); ++i)
00164             Vertices[i] = tranfo * Vertices[i];
00165     }
00166 
00167     NLMISC::CVector computeTrivialTranslation() const
00168     {
00169         uint    i;
00170         NLMISC::CAABBox bbox;
00171 
00172         if (!Vertices.empty())
00173         {
00174             bbox.setCenter(Vertices[0]);
00175             for (i=1; i<Vertices.size(); ++i)
00176                 bbox.extend(Vertices[i]);
00177         }
00178 
00179         return -bbox.getCenter();
00180     }
00181 
00182     //
00183     void    link(bool linkInterior, std::vector<std::string> &errors)
00184     {
00185         uint            i, j;
00186         TLinkRelloc     relloc;
00187 
00188 
00189         // check each edge of each face
00190         for (i=0; i<Faces.size(); ++i)
00191         {
00192             if (Faces[i].Surface == CCollisionFace::ExteriorSurface && linkInterior ||
00193                 Faces[i].Surface >= CCollisionFace::InteriorSurfaceFirst && !linkInterior)
00194                 continue;
00195 
00196             for (j=0; j<3; ++j)
00197             {
00198                 Faces[i].Edge[j] = -1;
00199 
00200                 uint    edge = (j+2)%3;
00201                 uint32  va = Faces[i].V[j],
00202                         vb = Faces[i].V[(j+1)%3];
00203 
00204                 ItTLinkRelloc   it;
00205                 if ((it = relloc.find(CEdgeKey(va, vb))) != relloc.end())
00206                 {
00207                     CCollisionFace  &left0 = Faces[(*it).second.Left];
00208                     CCollisionFace  &left1 = Faces[i];
00209                     // in this case, the left triangle of the edge has already been found.
00210                     // should throw an error
00211                     NLMISC::CVector eva = Vertices[va], evb = Vertices[vb];
00212                     static char buf[512];
00213                     sprintf(buf, "Edge issue: (%.2f,%.2f,%.2f)-(%.2f,%.2f,%.2f) [left face already found]\n"
00214                                  "left.0:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f) surf=%d material=%d\n"
00215                                  "left.1:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f) surf=%d material=%d",
00216                                     eva.x, eva.y, eva.z, evb.x, evb.y, evb.z,
00217                                     (*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,
00218                                     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);
00219                     errors.push_back(std::string(buf));
00220                     continue;
00221 /*                  nlerror("On face %d, edge %d: left side of edge (%d,%d) already linked to face %d",
00222                             i, edge, va, vb, (*it).second.Left);*/
00223                 }
00224                 else if ((it = relloc.find(CEdgeKey(vb, va))) != relloc.end())
00225                 {
00226                     // in this case, we must check the right face has been set yet
00227                     if ((*it).second.Right != -1)
00228                     {
00229                         CCollisionFace  &right0 = Faces[(*it).second.Right];
00230                         CCollisionFace  &right1 = Faces[i];
00231                         NLMISC::CVector eva = Vertices[va], evb = Vertices[vb];
00232                         static char buf[512];
00233                         sprintf(buf, "Edge issue: (%.2f,%.2f,%.2f)-(%.2f,%.2f,%.2f) [right face already found]\n"
00234                                      "right.0:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f)\n"
00235                                      "right.1:%d: v0:(%.2f,%.2f) v1:(%.2f,%.2f), v2:(%.2f,%.2f)",
00236                                         eva.x, eva.y, eva.z, evb.x, evb.y, evb.z,
00237                                         (*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,
00238                                         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);
00239                         errors.push_back(std::string(buf));
00240                         continue;
00241 /*                      nlerror("On face %d, edge %d: right side of edge (%d,%d) already linked to face %d",
00242                                 i, edge, vb, va, (*it).second.Right);*/
00243                     }
00244 
00245                     (*it).second.Right = i;
00246                     (*it).second.RightEdge = edge;
00247                 }
00248                 else
00249                 {
00250                     // if the edge wasn't present yet, create it and set it up.
00251                     relloc.insert(std::make_pair(CEdgeKey(va, vb), CEdgeInfo(i, edge, -1, -1)));
00252                 }
00253             }
00254         }
00255 
00256         // for each checked edge, update the edge info inside the faces
00257         ItTLinkRelloc   it;
00258         for (it=relloc.begin(); it!=relloc.end(); ++it)
00259         {
00260             sint32  left, leftEdge;
00261             sint32  right, rightEdge;
00262 
00263             // get the link info on the edge
00264             left = (*it).second.Left;
00265             leftEdge = (*it).second.LeftEdge;
00266             right = (*it).second.Right;
00267             rightEdge = (*it).second.RightEdge;
00268 
00269             // update both faces
00270             if (left != -1)
00271                 Faces[left].Edge[leftEdge] = right;
00272             if (right != -1)
00273                 Faces[right].Edge[rightEdge] = left;
00274         }
00275     }
00276 };
00277 
00278 }; // NLPACS
00279 
00280 #endif // NL_COLLISION_MESH_BUILD_H
00281 
00282 /* End of collision_mesh_build.h */

Generated on Thu Jan 7 08:26:36 2010 for NeL by  doxygen 1.6.1