Blender V4.3
GeomCleaner.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#if 0
11# if defined(__GNUC__) && (__GNUC__ >= 3)
12// hash_map is not part of the C++ standard anymore;
13// hash_map.h has been kept though for backward compatibility
14# include <hash_map.h>
15# else
16# include <hash_map>
17# endif
18#endif
19
20#include <cstdio>
21#include <list>
22#include <map>
23
24#include "GeomCleaner.h"
25
26#include "../system/TimeUtils.h"
27
28#include "BKE_global.hh"
29
30#include "BLI_sys_types.h"
31
32using namespace std;
33
34namespace Freestyle {
35
36void GeomCleaner::SortIndexedVertexArray(const float *iVertices,
37 uint iVSize,
38 const uint *iIndices,
39 uint iISize,
40 float **oVertices,
41 uint **oIndices)
42{
43 // First, we build a list of IndexVertex:
44 list<IndexedVertex> indexedVertices;
45 uint i;
46 for (i = 0; i < iVSize; i += 3) {
47 indexedVertices.emplace_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]), i / 3);
48 }
49
50 // q-sort
51 indexedVertices.sort();
52
53 // build the indices mapping array:
54 uint *mapIndices = new uint[iVSize / 3];
55 *oVertices = new float[iVSize];
56 list<IndexedVertex>::iterator iv;
57 uint newIndex = 0;
58 uint vIndex = 0;
59 for (iv = indexedVertices.begin(); iv != indexedVertices.end(); iv++) {
60 // Build the final results:
61 (*oVertices)[vIndex] = iv->x();
62 (*oVertices)[vIndex + 1] = iv->y();
63 (*oVertices)[vIndex + 2] = iv->z();
64
65 mapIndices[iv->index()] = newIndex;
66 newIndex++;
67 vIndex += 3;
68 }
69
70 // Build the final index array:
71 *oIndices = new uint[iISize];
72 for (i = 0; i < iISize; i++) {
73 (*oIndices)[i] = 3 * mapIndices[iIndices[i] / 3];
74 }
75
76 delete[] mapIndices;
77}
78
79void GeomCleaner::CompressIndexedVertexArray(const float *iVertices,
80 uint iVSize,
81 const uint *iIndices,
82 uint iISize,
83 float **oVertices,
84 uint *oVSize,
85 uint **oIndices)
86{
87 // First, we build a list of IndexVertex:
88 vector<Vec3f> vertices;
89 uint i;
90 for (i = 0; i < iVSize; i += 3) {
91 vertices.emplace_back(iVertices[i], iVertices[i + 1], iVertices[i + 2]);
92 }
93
94 uint *mapVertex = new uint[iVSize];
95 vector<Vec3f>::iterator v = vertices.begin();
96
97 vector<Vec3f> compressedVertices;
98 Vec3f previous = *v;
99 mapVertex[0] = 0;
100 compressedVertices.push_back(vertices.front());
101
102 v++;
103 Vec3f current;
104 i = 1;
105 for (; v != vertices.end(); v++) {
106 current = *v;
107 if (current == previous) {
108 mapVertex[i] = compressedVertices.size() - 1;
109 }
110 else {
111 compressedVertices.push_back(current);
112 mapVertex[i] = compressedVertices.size() - 1;
113 }
114 previous = current;
115 i++;
116 }
117
118 // Builds the resulting vertex array:
119 *oVSize = 3 * compressedVertices.size();
120 *oVertices = new float[*oVSize];
121 i = 0;
122 for (v = compressedVertices.begin(); v != compressedVertices.end(); v++) {
123 (*oVertices)[i] = (*v)[0];
124 (*oVertices)[i + 1] = (*v)[1];
125 (*oVertices)[i + 2] = (*v)[2];
126 i += 3;
127 }
128
129 // Map the index array:
130 *oIndices = new uint[iISize];
131 for (i = 0; i < iISize; i++) {
132 (*oIndices)[i] = 3 * mapVertex[iIndices[i] / 3];
133 }
134
135 delete[] mapVertex;
136}
137
139 uint iVSize,
140 const uint *iIndices,
141 uint iISize,
142 float **oVertices,
143 uint *oVSize,
144 uint **oIndices)
145{
146 // tmp arrays used to store the sorted data:
147 float *tmpVertices;
148 uint *tmpIndices;
149
150 Chronometer chrono;
151 // Sort data
152 chrono.start();
154 iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
155 if (G.debug & G_DEBUG_FREESTYLE) {
156 printf("Sorting: %lf sec.\n", chrono.stop());
157 }
158
159 // compress data
160 chrono.start();
162 tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
163 real duration = chrono.stop();
164 if (G.debug & G_DEBUG_FREESTYLE) {
165 printf("Merging: %lf sec.\n", duration);
166 }
167
168 // deallocates memory:
169 delete[] tmpVertices;
170 delete[] tmpIndices;
171}
172
175#define _MUL 950706376UL
176#define _MOD 2147483647UL
177 inline size_t operator()(const Vec3r &p) const
178 {
179 size_t res = ulong(p[0] * _MUL) % _MOD;
180 res = (res + ulong(p[1]) * _MUL) % _MOD;
181 return (res + ulong(p[2]) * _MUL) % _MOD;
182 }
183#undef _MUL
184#undef _MOD
185};
186
187void GeomCleaner::CleanIndexedVertexArray(const float *iVertices,
188 uint iVSize,
189 const uint *iIndices,
190 uint iISize,
191 float **oVertices,
192 uint *oVSize,
193 uint **oIndices)
194{
195 using cleanHashTable = map<Vec3f, uint>;
196 vector<Vec3f> vertices;
197 uint i;
198 for (i = 0; i < iVSize; i += 3) {
199 vertices.emplace_back(iVertices[i], iVertices[i + 1], iVertices[i + 2]);
200 }
201
202 cleanHashTable ht;
203 vector<uint> newIndices;
204 vector<Vec3f> newVertices;
205
206 // elimination of needless points
207 uint currentIndex = 0;
208 vector<Vec3f>::const_iterator v = vertices.begin();
209 vector<Vec3f>::const_iterator end = vertices.end();
210 cleanHashTable::const_iterator found;
211 for (; v != end; v++) {
212 found = ht.find(*v);
213 if (found != ht.end()) {
214 // The vertex is already in the new array.
215 newIndices.push_back((*found).second);
216 }
217 else {
218 newVertices.push_back(*v);
219 newIndices.push_back(currentIndex);
220 ht[*v] = currentIndex;
221 currentIndex++;
222 }
223 }
224
225 // creation of oVertices array:
226 *oVSize = 3 * newVertices.size();
227 *oVertices = new float[*oVSize];
228 currentIndex = 0;
229 end = newVertices.end();
230 for (v = newVertices.begin(); v != end; v++) {
231 (*oVertices)[currentIndex++] = (*v)[0];
232 (*oVertices)[currentIndex++] = (*v)[1];
233 (*oVertices)[currentIndex++] = (*v)[2];
234 }
235
236 // map new indices:
237 *oIndices = new uint[iISize];
238 for (i = 0; i < iISize; i++) {
239 (*oIndices)[i] = 3 * newIndices[iIndices[i] / 3];
240 }
241}
242
243} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
unsigned long ulong
unsigned int uint
#define _MOD
#define _MUL
Class to define a cleaner of geometry providing a set of useful tools.
Class to measure elapsed time.
ATTR_WARN_UNUSED_RESULT const BMVert * v
static void SortIndexedVertexArray(const float *iVertices, uint iVSize, const uint *iIndices, uint iISize, float **oVertices, uint **oIndices)
static void CompressIndexedVertexArray(const float *iVertices, uint iVSize, const uint *iIndices, uint iISize, float **oVertices, uint *oVSize, uint **oIndices)
static void SortAndCompressIndexedVertexArray(const float *iVertices, uint iVSize, const uint *iIndices, uint iISize, float **oVertices, uint *oVSize, uint **oIndices)
static void CleanIndexedVertexArray(const float *iVertices, uint iVSize, const uint *iIndices, uint iISize, float **oVertices, uint *oVSize, uint **oIndices)
#define printf
#define G(x, y, z)
VecMat::Vec3< float > Vec3f
Definition Geom.h:28
inherits from class Rep
Definition AppCanvas.cpp:20
double real
Definition Precision.h:14
size_t operator()(const Vec3r &p) const