diff options
author | Maxime Curioni <maxime.curioni@gmail.com> | 2008-05-08 23:16:40 +0400 |
---|---|---|
committer | Maxime Curioni <maxime.curioni@gmail.com> | 2008-05-08 23:16:40 +0400 |
commit | 64e4a3ec9aed6c8abe095e2cd1fe1552f7cde51c (patch) | |
tree | 6c77358bd447b6c2d215324ef48fc12d1f5ae5ca /source/blender/freestyle/intern/geometry/GeomCleaner.cpp | |
parent | cf2e1e2857cfc5b3c2848c7fc6c9d919ac72fabb (diff) | |
parent | 106974a9d2d5caa5188322507980e3d57d2e3517 (diff) |
soc-2008-mxcurioni: merged changes to revision 14747, cosmetic changes for source/blender/freestyle
Diffstat (limited to 'source/blender/freestyle/intern/geometry/GeomCleaner.cpp')
-rwxr-xr-x | source/blender/freestyle/intern/geometry/GeomCleaner.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp new file mode 100755 index 00000000000..c148c521a46 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp @@ -0,0 +1,240 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +//#if defined(__GNUC__) && (__GNUC__ >= 3) +//// hash_map is not part of the C++ standard anymore; +//// hash_map.h has been kept though for backward compatibility +//# include <hash_map.h> +//#else +//# include <hash_map> +//#endif + +#include <stdio.h> +#include <list> +#include <map> +#include "../system/TimeUtils.h" +#include "GeomCleaner.h" + +using namespace std; + + +void GeomCleaner::SortIndexedVertexArray( const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, + unsigned **oIndices) +{ + // First, we build a list of IndexVertex: + list<IndexedVertex> indexedVertices; + unsigned i; + for(i=0; i<iVSize; i+= 3) + { + indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]), i/3)); + } + + // q-sort + indexedVertices.sort(); + + // build the indices mapping array: + unsigned *mapIndices = new unsigned[iVSize/3]; + *oVertices = new real[iVSize]; + list<IndexedVertex>::iterator iv; + unsigned newIndex = 0; + unsigned vIndex = 0; + for(iv=indexedVertices.begin(); iv!=indexedVertices.end(); iv++) + { + // Build the final results: + (*oVertices)[vIndex] = iv->x(); + (*oVertices)[vIndex+1] = iv->y(); + (*oVertices)[vIndex+2] = iv->z(); + + mapIndices[iv->index()] = newIndex; + newIndex++; + vIndex+=3; + } + + + // Build the final index array: + *oIndices = new unsigned[iISize]; + for(i=0; i<iISize; i++) + { + (*oIndices)[i] = 3*mapIndices[iIndices[i]/3]; + } + + delete [] mapIndices; +} + +void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices) +{ + // First, we build a list of IndexVertex: + vector<Vec3r> vertices; + unsigned i; + for(i=0; i<iVSize; i+= 3) + { + vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2])); + } + + unsigned *mapVertex = new unsigned[iVSize]; + vector<Vec3r>::iterator v = vertices.begin(); + + vector<Vec3r> compressedVertices; + Vec3r previous = *v; + mapVertex[0] = 0; + compressedVertices.push_back(vertices.front()); + + v++; + Vec3r current; + i=1; + for(; v!=vertices.end(); v++) + { + current = *v; + if(current == previous) + mapVertex[i] = compressedVertices.size()-1; + else + { + compressedVertices.push_back(current); + mapVertex[i] = compressedVertices.size()-1; + } + previous = current; + i++; + } + + // Builds the resulting vertex array: + *oVSize = 3*compressedVertices.size(); + *oVertices = new real [*oVSize]; + i=0; + for(v=compressedVertices.begin(); v!=compressedVertices.end(); v++) + { + (*oVertices)[i] = (*v)[0]; + (*oVertices)[i+1] = (*v)[1]; + (*oVertices)[i+2] = (*v)[2]; + i += 3; + } + + // Map the index array: + *oIndices = new unsigned[iISize]; + for(i=0; i<iISize; i++) + { + (*oIndices)[i] = 3*mapVertex[iIndices[i]/3]; + } + + delete [] mapVertex; +} + +void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices) +{ + + // tmp arrays used to store the sorted data: + real *tmpVertices; + unsigned *tmpIndices; + + Chronometer chrono; + // Sort data + chrono.start(); + GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, + iIndices, iISize, + &tmpVertices, &tmpIndices + ); + printf("Sorting: %lf\n", chrono.stop()); + + // compress data + chrono.start(); + GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, + tmpIndices, iISize, + oVertices, oVSize, + oIndices); + printf("Merging: %lf\n", chrono.stop()); + + // deallocates memory: + delete [] tmpVertices; + delete [] tmpIndices; +} + +/*! Defines a hash table used for searching the Cells */ +struct GeomCleanerHasher{ +#define _MUL 950706376UL +#define _MOD 2147483647UL + inline size_t operator() (const Vec3r& p) const { + size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD; + res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD; + return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD; + } +}; + +void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices) +{ + typedef map<Vec3r, unsigned> cleanHashTable; + vector<Vec3r> vertices; + unsigned i; + for(i=0; i<iVSize; i+= 3) + vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2])); + + cleanHashTable ht; + vector<unsigned> newIndices; + vector<Vec3r> newVertices; + + // elimination of needless points + unsigned currentIndex = 0; + vector<Vec3r>::const_iterator v = vertices.begin(); + vector<Vec3r>::const_iterator end = vertices.end(); + cleanHashTable::const_iterator found; + for(; v!=end; v++) + { + found = ht.find(*v); + if(found != ht.end()) + { + // The vertex is already in the new array. + newIndices.push_back((*found).second); + } + else + { + newVertices.push_back(*v); + newIndices.push_back(currentIndex); + ht[*v] = currentIndex; + currentIndex++; + } + } + + // creation of oVertices array: + *oVSize = 3*newVertices.size(); + *oVertices = new real[*oVSize]; + currentIndex = 0; + end = newVertices.end(); + for(v=newVertices.begin(); v!=end ; v++) + { + (*oVertices)[currentIndex++] = (*v)[0]; + (*oVertices)[currentIndex++] = (*v)[1]; + (*oVertices)[currentIndex++] = (*v)[2]; + } + + // map new indices: + *oIndices = new unsigned[iISize]; + for(i=0; i<iISize; i++) + (*oIndices)[i] = 3*newIndices[iIndices[i]/3]; +} |