1#include <rrapi/rrapi.h>
3#include "Platform/Instrumentation.h"
5#include "../Extensions/GeometryProcessing/GeometryProcessing.h"
8#include "Foundation/Logging/Logger.h"
10#include <glm/gtc/type_ptr.hpp>
21 rr_bool_t extractPrimitives(
void * handle,
void * userdata)
23 CpuInstrumentationScope(SCOPE_RATIONALREDUCER,
"RRextractPrimitives");
26 auto * state = task->state;
27 auto & inputSet = state->meshSets.front();
29 for (
size_t m = 0; m < inputSet.meshes.size(); m++) {
30 auto & mesh = inputSet.meshes[m];
32 auto transverts = rr_add_vertices(handle, (
int)mesh.positions.size(),
reinterpret_cast<const float *
>(mesh.positions.data()));
34 auto triangleData =
static_cast<TriangleData*
>(rr_malloc(handle,
static_cast<unsigned int>(
sizeof(TriangleData))));
35 triangleData->meshIndex = m;
36 triangleData->material = state->items.meshes[m].matlInst;
38 glm::vec2 * tex =
nullptr;
40 tex =
static_cast<glm::vec2*
>(rr_malloc(handle,
static_cast<unsigned int>(
sizeof(glm::vec2) * 3 * mesh.indices.size())));
41 if (mesh.texcoords.size() != 0) {
42 for (
size_t i = 0; i < mesh.indices.size(); i++) {
43 tex[i] = mesh.texcoords[mesh.indices[i]];
47 for (
size_t i = 0; i < mesh.indices.size(); i++) {
48 tex[i] = glm::vec2(0.f);
53 for (
size_t i = 0; i < mesh.indices.size(); i += 3) {
54 rr_add_indexed_polygon(handle, 3,
reinterpret_cast<int*
>(mesh.indices.data() + i), transverts, triangleData,
reinterpret_cast<float*
>(tex ? tex + i :
nullptr), RR_REDUCABLE);
61 rr_bool_t stuffPrimitives(
void *handle,
void *userdata)
63 CpuInstrumentationScope(SCOPE_RATIONALREDUCER,
"RRstuffPrimitives");
66 auto * state = task->state;
68 auto Nt =
static_cast<unsigned>(rr_get_num_triangles(handle));
71 if (state->meshSets.back().triangles == Nt || Nt == 0)
return TRUE;
75 state->meshSets.emplace_back();
76 auto & currentSet = state->meshSets.back();
78 currentSet.triangles = Nt;
79 currentSet.error = rr_get_approximation_error(handle);
80 currentSet.bboxMin = state->meshSets.front().bboxMin;
81 currentSet.bboxMax = state->meshSets.front().bboxMax;
82 currentSet.meshes.resize(state->meshSets.front().meshes.size());
85 currentSet.error = glm::distance(currentSet.bboxMin, currentSet.bboxMax);
88 LOG_TRACE(logger,
"Stuff primitives invoked error=%f, triangles=%d", currentSet.error, currentSet.triangles);
90 std::vector<std::vector<rr_triangle_t*>> groupedTriangles(currentSet.meshes.size());
91 for (
unsigned i = 0; i < currentSet.triangles; i++) {
92 auto rr_triangle = rr_get_triangle(handle, i);
93 auto * triangleData =
static_cast<TriangleData*
>(rr_triangle_get_data(rr_triangle));
94 groupedTriangles[triangleData->meshIndex].push_back(rr_triangle);
97 for (
size_t l = 0; l < currentSet.meshes.size(); l++) {
98 auto & mesh = currentSet.meshes[l];
99 auto & triangles = groupedTriangles[l];
101 mesh.indices.clear();
102 if (triangles.empty()) {
103 mesh.positions.clear();
104 mesh.normals.clear();
105 mesh.texcoords.clear();
106 mesh.tangents.clear();
110 mesh.positions.resize(3 * triangles.size(),
false);
111 mesh.normals.clear();
113 for (
size_t j = 0; j < triangles.size(); j++) {
114 for (
unsigned i = 0; i < 3; i++) {
115 auto * vertex = rr_triangle_get_vertex(triangles[j], i);
116 mesh.positions[3 * j + i] = glm::make_vec3(rr_vertex_get_coord(vertex));
120 if (mesh.texcoords.size() != 0 || task->textured) {
121 mesh.texcoords.resize(3 * triangles.size(),
false);
122 for (
size_t j = 0; j < triangles.size(); j++) {
123 auto * tex = rr_triangle_get_texcoords(triangles[j]);
124 for (
size_t i = 0; i < 3; i++) {
125 mesh.texcoords[3 * j + i] = tex ? glm::make_vec2(tex + 2 * i) : glm::vec2(0.f);
137 void progressModal(
float fraction,
void *userdata)
140 auto * state = task->state;
142 state->progress = fraction;
144 rr_abort(task->rrHandle);
148 void progressBatch(
float fraction,
void *userdata)
151 auto * state = task->state;
153 if (floor(10.f*(state->progress)) != floor(10.f*fraction)) {
154 float appError = rr_get_approximation_error(task->rrHandle);
155 LOG_TRACE(logger,
"Progress=%.1f%%, approximation error=%f", 100.f*fraction, appError);
158 state->progress = fraction;
161 rr_abort(task->rrHandle);
165 float sameMaterial(
void * triangle1data,
void * triangle2data,
void * )
167 auto tri1 =
static_cast<TriangleData *
>(triangle1data);
168 auto tri2 =
static_cast<TriangleData *
>(triangle2data);
169 return tri1->material == tri2->material ? 0.0f : 1.0f;
173void Cogs::Core::RRTaskBase::initRR()
175 assert(state->meshSets.size() == 1);
177 auto & inputSet = state->meshSets.front();
178 inputSet.triangles = 0;
179 inputSet.error = 0.f;
182 inputSet.bboxMin = glm::vec3(std::numeric_limits<float>::max());
183 inputSet.bboxMax = glm::vec3(-std::numeric_limits<float>::max());
185 for (
auto & mesh : inputSet.meshes) {
186 for (
size_t i = 0; i < mesh.positions.size(); i++) {
187 inputSet.bboxMin = glm::min(inputSet.bboxMin, mesh.positions[i]);
188 inputSet.bboxMax = glm::max(inputSet.bboxMax, mesh.positions[i]);
191 textured = textured || mesh.texcoords.size() != 0;
192 inputSet.triangles +=
static_cast<int>(mesh.indices.size() / 3);
199 rrHandle = rr_init(textured);
201 state->progress = 0.f;
202 rr_set_extract_primitives(rrHandle, ::extractPrimitives, &state);
203 rr_set_stuff_primitives(rrHandle, ::stuffPrimitives, &state);
204 rr_set_simple_progress(rrHandle, modal ? ::progressModal : ::progressBatch, &state);
205 rr_set_same_texture(rrHandle, ::sameMaterial, &state);
206 rr_set_same_material(rrHandle, ::sameMaterial, &state);
207 rr_set_same_surfaceappearance(rrHandle, ::sameMaterial, &state);
208 rr_set_num_native_triangles(rrHandle, inputSet.triangles);
209 rr_set_epsilon(rrHandle, epsilon);
211 if (edgeLengthWeight != 1.0f) {
212 rr_set_edgelength_weight(rrHandle, edgeLengthWeight);
216void Cogs::Core::RRTaskBase::runRR()
218 auto & inputSet = state->meshSets.front();
219 if (inputSet.bboxMin.x == inputSet.bboxMax.x && inputSet.bboxMin.y == inputSet.bboxMax.y)
return;
221 auto ret = rr_reduce(rrHandle);
227 std::vector<glm::vec3> N;
228 std::vector<uint32_t> map;
229 std::vector<uint32_t> unique;
231 std::vector<uint32_t> newIndices;
234 for (
auto & meshSet : state->meshSets) {
235 for (
auto & mesh : meshSet.meshes) {
238 if (!textured) mesh.texcoords.clear();
239 mesh.normals.clear();
243 GeometryProcessing::uniqueVertexSubset(state->context, unique, map,
244 (
float*)mesh.positions.data(),
246 mesh.normals.size() ? (
float*)mesh.normals.data() :
nullptr,
248 mesh.texcoords.size() ? (
float*)mesh.texcoords.data() :
nullptr,
250 static_cast<uint32_t
>(mesh.positions.size()), std::numeric_limits<float>::epsilon());
252 if (mesh.indices.size() == 0) {
253 mesh.indices.resize(mesh.positions.size(),
false);
254 for (
size_t i = 0; i < mesh.positions.size(); i++) {
255 mesh.indices[i] = uint32_t(i);
259 remapVertices(state->context, mesh, unique);
260 remapIndices(state->context, mesh, map);
266 GeometryProcessing::normalsFromIndexedTriangles(state->context,
267 N, unique, newIndices,
268 reinterpret_cast<const float*
>(mesh.positions.data()), 3 *
sizeof(
float),
static_cast<uint32_t
>(mesh.positions.size()),
269 mesh.indices.data(),
static_cast<uint32_t
>(mesh.indices.size()),
270 normalGenArgs.featureAngle,
271 normalGenArgs.protrusionAngle,
273 assert(N.size() == unique.size());
275 remapVertices(state->context, mesh, unique);
277 mesh.indices.resize(newIndices.size());
278 std::memcpy(mesh.indices.data(), newIndices.data(),
sizeof(uint32_t)*newIndices.size());
280 mesh.normals.resize(unique.size(),
false);
281 std::memcpy(mesh.normals.data(), N.data(), mesh.normals.byteSize());
285 state->running =
false;
289 case RR_ABORT: LOG_WARNING(logger,
"rr_reduce returned RR_ABORT");
break;
290 case RR_CALLBACK_ERROR: LOG_ERROR(logger,
"rr_reduce returned RR_CALLBACK_ERROR");
break;
293 for (
auto& meshSet : state->meshSets) {
294 meshSet.triangles = 0;
295 meshSet.meshes.clear();
297 LOG_ERROR(logger,
"rr_reduce returned RR_ERROR. Meshes deleted");
299 case RR_NODATA: LOG_ERROR(logger,
"rr_reduce returned RR_NODATA");
break;
300 case RR_NONUMTRIS: LOG_ERROR(logger,
"rr_reduce returned RR_NONUMTRIS");
break;
305 state->cancel =
true;
306 state->running =
false;
310void Cogs::Core::RRTriangleGuidedTask::operator()()
312 CpuInstrumentationScope(SCOPE_RATIONALREDUCER,
"RRtask");
314 rr_set_percentage(rrHandle, percentage);
318void Cogs::Core::RRMinMaxErrorGuidedTask::operator()()
320 CpuInstrumentationScope(SCOPE_RATIONALREDUCER,
"RRtask");
322 rr_set_minmax_error(rrHandle, error_threshold);
326void Cogs::Core::RRMultiTriangleGuidedTask::operator()()
328 CpuInstrumentationScope(SCOPE_RATIONALREDUCER,
"RRtask");
331 assert(!thresholds.empty());
332 auto steps = thresholds.size();
334 auto Nt = state->meshSets.front().triangles;
335 std::vector<unsigned> lodLevels(steps);
336 for (
size_t i = 0; i < steps; i++) {
337 lodLevels[i] = unsigned(std::max(0.f, 0.01f*Nt*thresholds[i]));
341 rr_set_lod_levels(rrHandle,
unsigned(steps - 1), lodLevels.data());
343 rr_set_target_tris(rrHandle, lodLevels.back());
347void Cogs::Core::RRMultiMinMaxErrorGuidedTask::operator()()
349 CpuInstrumentationScope(SCOPE_RATIONALREDUCER,
"RRtask");
352 assert(!thresholds.empty());
353 auto steps = thresholds.size();
356 rr_set_error_lod_levels(rrHandle,
unsigned(steps - 1), thresholds.data());
358 rr_set_minmax_error(rrHandle, thresholds.back());
Log implementation class.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Material instances represent a specialized Material combined with state for all its buffers and prope...