Cogs.Core
UniqueVertices.cpp
1#include "GeometryProcessing.h"
2
3#include "Platform/Instrumentation.h"
4
5#include <algorithm>
6
7void Cogs::Core::GeometryProcessing::uniqueVertexSubset(Context* /*context*/,
8 std::vector<uint32_t>& unique,
9 std::vector<uint32_t>& map,
10 const float * P,
11 const size_t P_stride,
12 const float* N,
13 const size_t N_stride,
14 const float * T,
15 const size_t T_stride,
16 const uint32_t Vn,
17 const float epsilon)
18{
19 CpuInstrumentationScope(SCOPE_GEOMETRY, "uniqVtx");
20
21 unique.clear();
22 if (Vn == 0) return;
23
24 map.resize(Vn);
25
26 std::vector<uint32_t> q(Vn);
27 for (uint32_t i = 0; i < Vn; i++) {
28 q[i] = i;
29 }
30
31 uint32_t kind = (N != nullptr ? 1 : 0) | (T != nullptr ? 2 : 0);
32
33 // Lexicographical sort.
34 switch (kind) {
35 case 0:
36 std::sort(q.begin(), q.end(), [&](auto & a, auto &b)-> bool
37 {
38 auto * Pa = (float*)((const char*)P + a * P_stride);
39 auto * Pb = (float*)((const char*)P + b * P_stride);
40 bool l0 = Pa[0] < Pb[0];
41 bool l1 = Pa[1] < Pb[1];
42 bool l2 = Pa[2] < Pb[2];
43 bool e0 = Pa[0] == Pb[0];
44 bool e1 = Pa[1] == Pb[1];
45
46 return l0 || (e0 && (l1 || (e1 && l2)));
47 });
48 break;
49
50 case 1:
51 std::sort(q.begin(), q.end(), [&](auto & a, auto &b)-> bool
52 {
53 auto * Pa = (float*)((const char*)P + a * P_stride);
54 auto * Pb = (float*)((const char*)P + b * P_stride);
55 auto * Na = (float*)((const char*)N + a * T_stride);
56 auto * Nb = (float*)((const char*)N + b * T_stride);
57 bool l0 = Pa[0] < Pb[0];
58 bool l1 = Pa[1] < Pb[1];
59 bool l2 = Pa[2] < Pb[2];
60 bool l3 = Na[0] < Nb[0];
61 bool l4 = Na[1] < Nb[1];
62 bool l5 = Na[2] < Nb[2];
63 bool e0 = Pa[0] == Pb[0];
64 bool e1 = Pa[1] == Pb[1];
65 bool e2 = Pa[2] == Pb[2];
66 bool e3 = Na[0] == Nb[0];
67 bool e4 = Na[1] == Nb[1];
68
69 return l0 || (e0 && (l1 || (e1 && (l2 || (e2 && (l3 || (e3 && (l4 || (e4 && l5)))))))));
70 });
71 break;
72
73 case 2:
74 std::sort(q.begin(), q.end(), [&](auto & a, auto &b)-> bool
75 {
76 auto * Pa = (float*)((const char*)P + a * P_stride);
77 auto * Pb = (float*)((const char*)P + b * P_stride);
78 auto * Ta = (float*)((const char*)T + a * T_stride);
79 auto * Tb = (float*)((const char*)T + b * T_stride);
80 bool l0 = Pa[0] < Pb[0];
81 bool l1 = Pa[1] < Pb[1];
82 bool l2 = Pa[2] < Pb[2];
83 bool l3 = Ta[0] < Tb[0];
84 bool l4 = Ta[1] < Tb[1];
85 bool e0 = Pa[0] == Pb[0];
86 bool e1 = Pa[1] == Pb[1];
87 bool e2 = Pa[2] == Pb[2];
88 bool e3 = Ta[0] == Tb[0];
89
90 return l0 || (e0 && (l1 || (e1 && (l2 || (e2 && (l3 || (e3 && l4)))))));
91 });
92 break;
93
94 case 3:
95 std::sort(q.begin(), q.end(), [&](auto & a, auto &b)-> bool
96 {
97 auto * Pa = (float*)((const char*)P + a * P_stride);
98 auto * Pb = (float*)((const char*)P + b * P_stride);
99 auto * Na = (float*)((const char*)N + a * T_stride);
100 auto * Nb = (float*)((const char*)N + b * T_stride);
101 auto * Ta = (float*)((const char*)T + a * T_stride);
102 auto * Tb = (float*)((const char*)T + b * T_stride);
103 bool l0 = Pa[0] < Pb[0];
104 bool l1 = Pa[1] < Pb[1];
105 bool l2 = Pa[2] < Pb[2];
106 bool l3 = Na[0] < Nb[0];
107 bool l4 = Na[1] < Nb[1];
108 bool l5 = Na[2] < Nb[2];
109 bool l6 = Ta[0] < Tb[0];
110 bool l7 = Ta[1] < Tb[1];
111
112 bool e0 = Pa[0] == Pb[0];
113 bool e1 = Pa[1] == Pb[1];
114 bool e2 = Pa[2] == Pb[2];
115 bool e3 = Na[0] == Nb[0];
116 bool e4 = Na[1] == Nb[1];
117 bool e5 = Na[2] == Nb[2];
118 bool e6 = Ta[0] == Tb[0];
119
120 return l0 || (e0 && (l1 || (e1 && (l2 || (e2 && (l3 || (e3 && (l4 || (e4 && (l5 || (e5 && (l6 || (e6 && l7)))))))))))));
121 });
122 break;
123 }
124
125 // Collapse duplicates
126 unsigned l = 0;
127 unsigned v = q[0];
128 map[v] = l;
129 unique.push_back(v);
130 const auto * P0 = (float*)((const char*)P + v * P_stride);
131 const auto * N0 = (float*)((const char*)N + v * N_stride);
132 const auto * T0 = (float*)((const char*)T + v * T_stride);
133
134 switch (kind) {
135 case 0:
136 for (unsigned i = 1; i < Vn; i++) {
137 v = q[i];
138 const auto * Pi = (float*)((const char*)P + v * P_stride);
139 bool t0 = epsilon < std::abs(P0[0] - Pi[0]);
140 bool t1 = epsilon < std::abs(P0[1] - Pi[1]);
141 bool t2 = epsilon < std::abs(P0[2] - Pi[2]);
142 if (t0 || t1 || t2) {
143 unique.push_back(v);
144 P0 = Pi;
145 l++;
146 }
147 map[v] = l;
148 }
149 break;
150
151 case 1:
152 for (unsigned i = 1; i < Vn; i++) {
153 v = q[i];
154 const auto * Pi = (float*)((const char*)P + v * P_stride);
155 const auto * Ni = (float*)((const char*)N + v * N_stride);
156 bool t0 = epsilon < std::abs(P0[0] - Pi[0]);
157 bool t1 = epsilon < std::abs(P0[1] - Pi[1]);
158 bool t2 = epsilon < std::abs(P0[2] - Pi[2]);
159 bool t3 = epsilon < std::abs(N0[0] - Ni[0]);
160 bool t4 = epsilon < std::abs(N0[1] - Ni[1]);
161 bool t5 = epsilon < std::abs(N0[1] - Ni[1]);
162 if (t0 || t1 || t2 || t3 || t4 || t5) {
163 unique.push_back(v);
164 P0 = Pi;
165 N0 = Ni;
166 l++;
167 }
168 map[v] = l;
169 }
170 break;
171
172 case 2:
173 for (unsigned i = 1; i < Vn; i++) {
174 v = q[i];
175 const auto * Pi = (float*)((const char*)P + v * P_stride);
176 const auto * Ti = (float*)((const char*)T + v * T_stride);
177 bool t0 = epsilon < std::abs(P0[0] - Pi[0]);
178 bool t1 = epsilon < std::abs(P0[1] - Pi[1]);
179 bool t2 = epsilon < std::abs(P0[2] - Pi[2]);
180 bool t3 = epsilon < std::abs(T0[0] - Ti[0]);
181 bool t4 = epsilon < std::abs(T0[1] - Ti[1]);
182 if (t0 || t1 || t2 || t3 || t4) {
183 unique.push_back(v);
184 P0 = Pi;
185 T0 = Ti;
186 l++;
187 }
188 map[v] = l;
189 }
190 break;
191
192 case 3:
193 for (unsigned i = 1; i < Vn; i++) {
194 v = q[i];
195 const auto * Pi = (float*)((const char*)P + v * P_stride);
196 const auto * Ni = (float*)((const char*)N + v * N_stride);
197 const auto * Ti = (float*)((const char*)T + v * T_stride);
198 bool t0 = epsilon < std::abs(P0[0] - Pi[0]);
199 bool t1 = epsilon < std::abs(P0[1] - Pi[1]);
200 bool t2 = epsilon < std::abs(P0[2] - Pi[2]);
201 bool t3 = epsilon < std::abs(N0[0] - Ni[0]);
202 bool t4 = epsilon < std::abs(N0[1] - Ni[1]);
203 bool t5 = epsilon < std::abs(N0[2] - Ni[2]);
204 bool t6 = epsilon < std::abs(T0[0] - Ti[0]);
205 bool t7 = epsilon < std::abs(T0[1] - Ti[1]);
206
207 if (t0 || t1 || t2 || t3 || t4 || t5 || t6 || t7) {
208 unique.push_back(v);
209 P0 = Pi;
210 N0 = Ni;
211 T0 = Ti;
212 l++;
213 }
214 map[v] = l;
215 }
216 break;
217 }
218
219}