Files
test/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
Campbell Barton e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
Listing the "Blender Foundation" as copyright holder implied the Blender
Foundation holds copyright to files which may include work from many
developers.

While keeping copyright on headers makes sense for isolated libraries,
Blender's own code may be refactored or moved between files in a way
that makes the per file copyright holders less meaningful.

Copyright references to the "Blender Foundation" have been replaced with
"Blender Authors", with the exception of `./extern/` since these this
contains libraries which are more isolated, any changed to license
headers there can be handled on a case-by-case basis.

Some directories in `./intern/` have also been excluded:

- `./intern/cycles/` it's own `AUTHORS` file is planned.
- `./intern/opensubdiv/`.

An "AUTHORS" file has been added, using the chromium projects authors
file as a template.

Design task: #110784

Ref !110783.
2023-08-16 00:20:26 +10:00

244 lines
6.8 KiB
C++

/* SPDX-FileCopyrightText: 2012-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
* \brief Class to define a cleaner of geometry providing a set of useful tools
*/
#if 0
# 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
#endif
#include <cstdio>
#include <list>
#include <map>
#include "GeomCleaner.h"
#include "../system/TimeUtils.h"
#include "BKE_global.h"
#include "BLI_sys_types.h"
using namespace std;
namespace Freestyle {
void GeomCleaner::SortIndexedVertexArray(const float *iVertices,
uint iVSize,
const uint *iIndices,
uint iISize,
float **oVertices,
uint **oIndices)
{
// First, we build a list of IndexVertex:
list<IndexedVertex> indexedVertices;
uint i;
for (i = 0; i < iVSize; i += 3) {
indexedVertices.emplace_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]), i / 3);
}
// q-sort
indexedVertices.sort();
// build the indices mapping array:
uint *mapIndices = new uint[iVSize / 3];
*oVertices = new float[iVSize];
list<IndexedVertex>::iterator iv;
uint newIndex = 0;
uint 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 uint[iISize];
for (i = 0; i < iISize; i++) {
(*oIndices)[i] = 3 * mapIndices[iIndices[i] / 3];
}
delete[] mapIndices;
}
void GeomCleaner::CompressIndexedVertexArray(const float *iVertices,
uint iVSize,
const uint *iIndices,
uint iISize,
float **oVertices,
uint *oVSize,
uint **oIndices)
{
// First, we build a list of IndexVertex:
vector<Vec3f> vertices;
uint i;
for (i = 0; i < iVSize; i += 3) {
vertices.emplace_back(iVertices[i], iVertices[i + 1], iVertices[i + 2]);
}
uint *mapVertex = new uint[iVSize];
vector<Vec3f>::iterator v = vertices.begin();
vector<Vec3f> compressedVertices;
Vec3f previous = *v;
mapVertex[0] = 0;
compressedVertices.push_back(vertices.front());
v++;
Vec3f 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 float[*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 uint[iISize];
for (i = 0; i < iISize; i++) {
(*oIndices)[i] = 3 * mapVertex[iIndices[i] / 3];
}
delete[] mapVertex;
}
void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices,
uint iVSize,
const uint *iIndices,
uint iISize,
float **oVertices,
uint *oVSize,
uint **oIndices)
{
// tmp arrays used to store the sorted data:
float *tmpVertices;
uint *tmpIndices;
Chronometer chrono;
// Sort data
chrono.start();
GeomCleaner::SortIndexedVertexArray(
iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
if (G.debug & G_DEBUG_FREESTYLE) {
printf("Sorting: %lf sec.\n", chrono.stop());
}
// compress data
chrono.start();
GeomCleaner::CompressIndexedVertexArray(
tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
real duration = chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
printf("Merging: %lf sec.\n", duration);
}
// 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 = ulong(p[0] * _MUL) % _MOD;
res = (res + ulong(p[1]) * _MUL) % _MOD;
return (res + ulong(p[2]) * _MUL) % _MOD;
}
#undef _MUL
#undef _MOD
};
void GeomCleaner::CleanIndexedVertexArray(const float *iVertices,
uint iVSize,
const uint *iIndices,
uint iISize,
float **oVertices,
uint *oVSize,
uint **oIndices)
{
using cleanHashTable = map<Vec3f, uint>;
vector<Vec3f> vertices;
uint i;
for (i = 0; i < iVSize; i += 3) {
vertices.emplace_back(iVertices[i], iVertices[i + 1], iVertices[i + 2]);
}
cleanHashTable ht;
vector<uint> newIndices;
vector<Vec3f> newVertices;
// elimination of needless points
uint currentIndex = 0;
vector<Vec3f>::const_iterator v = vertices.begin();
vector<Vec3f>::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 float[*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 uint[iISize];
for (i = 0; i < iISize; i++) {
(*oIndices)[i] = 3 * newIndices[iIndices[i] / 3];
}
}
} /* namespace Freestyle */