# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

collision_mesh_build.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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         // a reference on an edge
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         // the info on an edge
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                 // check each edge of each face
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                                         // in this case, the left triangle of the edge has already been found.
00204                                         // should throw an error
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 /*                                      nlerror("On face %d, edge %d: left side of edge (%d,%d) already linked to face %d",
00216                                                         i, edge, va, vb, (*it).second.Left);*/
00217                                 }
00218                                 else if ((it = relloc.find(CEdgeKey(vb, va))) != relloc.end())
00219                                 {
00220                                         // in this case, we must check the right face has been set yet
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 /*                                              nlerror("On face %d, edge %d: right side of edge (%d,%d) already linked to face %d",
00236                                                                 i, edge, vb, va, (*it).second.Right);*/
00237                                         }
00238 
00239                                         (*it).second.Right = i;
00240                                         (*it).second.RightEdge = edge;
00241                                 }
00242                                 else
00243                                 {
00244                                         // if the edge wasn't present yet, create it and set it up.
00245                                         relloc.insert(std::make_pair(CEdgeKey(va, vb), CEdgeInfo(i, edge, -1, -1)));
00246                                 }
00247                         }
00248                 }
00249 
00250                 // for each checked edge, update the edge info inside the faces
00251                 ItTLinkRelloc   it;
00252                 for (it=relloc.begin(); it!=relloc.end(); ++it)
00253                 {
00254                         sint32  left, leftEdge;
00255                         sint32  right, rightEdge;
00256 
00257                         // get the link info on the edge
00258                         left = (*it).second.Left;
00259                         leftEdge = (*it).second.LeftEdge;
00260                         right = (*it).second.Right;
00261                         rightEdge = (*it).second.RightEdge;
00262 
00263                         // update both faces
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 }; // NLPACS
00273 
00274 #endif // NL_COLLISION_MESH_BUILD_H
00275 
00276 /* End of collision_mesh_build.h */