MeshLODVector.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 
00022 // MeshLODVector.cpp: implementation of the MeshLODVector class.
00023 //
00024 //////////////////////////////////////////////////////////////////////
00025 
00026 #include <3dsparse/MeshLODTri.h>
00027 #include <3dsparse/MeshLODVector.h>
00028 #include <common/Defines.h>
00029 
00030 //////////////////////////////////////////////////////////////////////
00031 // Construction/Destruction
00032 //////////////////////////////////////////////////////////////////////
00033 
00034 MeshLODVector::MeshLODVector(Vector &v, int _id)
00035         : Vector(v), id(_id)
00036 {
00037 
00038 }
00039 
00040 MeshLODVector::~MeshLODVector()
00041 {
00042 
00043 }
00044 
00045 void MeshLODVector::addNeighbour(MeshLODVector *vector)
00046 {
00047         if (vector != this)
00048         {
00049                 bool found = false;
00050                 std::list<MeshLODVector *>::iterator neighborItor;
00051                 for (neighborItor = neighbor.begin();
00052                         neighborItor != neighbor.end();
00053                         neighborItor++)
00054                 {
00055                         if (*neighborItor == vector) 
00056                         {
00057                                 found = true;
00058                                 break;
00059                         }
00060                 }
00061                 if (!found) neighbor.push_back(vector);
00062         }
00063 }
00064 
00065 void MeshLODVector::removeNeighbor(MeshLODVector *vector)
00066 {
00067         for (unsigned int i=0; i<neighbor.size(); i++)
00068         {
00069                 MeshLODVector *vec = neighbor.front();
00070                 neighbor.pop_front();
00071                 if (vec == vector) 
00072                 {
00073                         break;
00074                 }
00075                 neighbor.push_back(vec);
00076         }
00077 }
00078 
00079 void MeshLODVector::removeIfNonNeighbor(MeshLODVector *n) 
00080 {
00081         // removes n from neighbor list if n isn't a neighbor.
00082         std::list<MeshLODTri *>::iterator faceItor;
00083         for (faceItor = face.begin();
00084                 faceItor != face.end();
00085                 faceItor++)
00086         {
00087                 MeshLODTri *tri = (*faceItor);
00088                 if(tri->hasVertex(n)) return;
00089         }
00090         removeNeighbor(n);
00091 }
00092 
00093 void MeshLODVector::removeFace(MeshLODTri *rface)
00094 {
00095         for (unsigned int i=0; i<face.size(); i++)
00096         {
00097                 MeshLODTri *tri = face.front();
00098                 face.pop_front();
00099                 if (tri == rface)
00100                 {
00101                         break;
00102                 }
00103                 face.push_back(tri);
00104         }
00105 }
00106 
00107 float MeshLODVector::computeEdgeCollapseCost(MeshLODVector *neigbour)
00108 {
00109         //(Vertex *u,Vertex *v)
00110         // if we collapse edge uv by moving u to v then how 
00111         // much different will the model change, i.e. how much "error".
00112         // Texture, vertex normal, and border vertex code was removed
00113         // to keep this demo as simple as possible.
00114         // The method of determining cost was designed in order 
00115         // to exploit small and coplanar regions for
00116         // effective polygon reduction.
00117         // Is is possible to add some checks here to see if "folds"
00118         // would be generated.  i.e. normal of a remaining face gets
00119         // flipped.  I never seemed to run into this problem and
00120         // therefore never added code to detect this case.
00121 
00122         float edgelength = (*neigbour - *this).Magnitude();
00123 
00124         // find the "sides" triangles that are on the edge uv
00125         std::list<MeshLODTri *> sides;
00126         std::list<MeshLODTri *>::iterator faceItor;
00127         for (faceItor = face.begin();
00128                 faceItor != face.end();
00129                 faceItor++)
00130         {
00131                 if ((*faceItor)->hasVertex(neigbour))
00132                 {
00133                         sides.push_back(*faceItor);
00134                 }
00135         }
00136 
00137         // use the triangle facing most away from the sides 
00138         // to determine our curvature term
00139         float curvature = 0;
00140         for (faceItor = face.begin();
00141                 faceItor != face.end();
00142                 faceItor++)
00143         {
00144                 float mincurv = 1; // curve for face i and closer side to it
00145 
00146                 std::list<MeshLODTri *>::iterator sideItor;
00147                 for (sideItor = sides.begin();
00148                         sideItor != sides.end();
00149                         sideItor++)
00150                 {
00151                         // use dot product of face normals. '^' defined in vector
00152                         float dotprod = (*faceItor)->normal.dotP((*sideItor)->normal);
00153                         mincurv = MIN(mincurv,(1-dotprod)/2.0f);
00154                 }
00155 
00156                 curvature = MAX(curvature,mincurv);
00157         }
00158 
00159         // the more coplanar the lower the curvature term   
00160         return edgelength * curvature;
00161 }
00162 
00163 void MeshLODVector::computeEdgeCostAtVertex()
00164 {
00165         // compute the edge collapse cost for all edges that start
00166         // from vertex v.  Since we are only interested in reducing
00167         // the object by selecting the min cost edge at each step, we
00168         // only cache the cost of the least cost edge at this vertex
00169         // (in member variable collapse) as well as the value of the 
00170         // cost (in member variable objdist).
00171 
00172         collapse = NULL;
00173         if(neighbor.empty()) 
00174         {
00175                 // v doesn't have neighbors so it costs nothing to collapse
00176                 objdist = -0.01f;
00177         }
00178         else
00179         {
00180                 // search all neighboring edges for "least cost" edge
00181                 objdist = 1000000;
00182                 std::list<MeshLODVector *>::iterator neighborItor;
00183                 for (neighborItor = neighbor.begin();
00184                         neighborItor != neighbor.end();
00185                         neighborItor++)
00186                 {
00187                         float dist = computeEdgeCollapseCost(*neighborItor);
00188                         if(dist < objdist) 
00189                         {
00190                                 collapse = *neighborItor;   // candidate for edge collapse
00191                                 objdist = dist;             // cost of the collapse
00192                         }
00193                 }
00194         }
00195 }
00196 
00197 void MeshLODVector::collapseVertex()
00198 
00199 {
00200         // Vertex *u = this,Vertex *v = collapse
00201         // Collapse the edge uv by moving vertex u onto v
00202         // Actually remove tris on uv, then update tris that
00203         // have u to have v, and then remove u.
00204 
00205         if(!collapse) 
00206         {
00207                 // u is a vertex all by itself so just delete it
00208         }
00209         else
00210         {
00211                 // make tmp a list of all the neighbors of u
00212                 std::list<MeshLODVector *> tmp(neighbor);
00213 
00214                 // delete triangles on edge uv:
00215                 std::list<MeshLODTri *> delList(face);
00216                 while (!delList.empty())
00217                 {
00218                         MeshLODTri *tri = delList.front();
00219                         if (tri->hasVertex(collapse))
00220                         {
00221                                 delete tri;
00222                         }
00223                         delList.pop_front();
00224                 }
00225 
00226                 // update remaining triangles to have v instead of u
00227                 std::list<MeshLODTri *> tmpList(face);
00228                 while (!tmpList.empty())
00229                 {
00230                         MeshLODTri *tri = tmpList.front();
00231                         tmpList.pop_front();
00232                         tri->replaceVertex(this, collapse);
00233                 }
00234 
00235                 // Remove from neigbours lists
00236                 while(!neighbor.empty()) 
00237                 {
00238                         neighbor.back()->removeNeighbor(this);
00239                         neighbor.pop_back();
00240                 }
00241 
00242                 // recompute the edge collapse costs for neighboring vertices
00243                 std::list<MeshLODVector *>::iterator tmpItor = tmp.begin();
00244                 for (tmpItor = tmp.begin();
00245                         tmpItor != tmp.end();
00246                         tmpItor++)
00247                 {
00248                         (*tmpItor)->computeEdgeCostAtVertex();
00249                 }
00250         }
00251 }

Generated on Mon Feb 16 15:14:48 2009 for Scorched3D by  doxygen 1.5.3