Merge pull request #619 from zeux/simp-pcol

simplify: Add color support to simplifyPoints
This commit is contained in:
Arseny Kapoulkine
2023-10-13 10:17:27 -07:00
committed by GitHub
5 changed files with 42 additions and 15 deletions
+1 -1
View File
@@ -524,7 +524,7 @@ void simplifyPoints(const Mesh& mesh, float threshold = 0.2f)
size_t target_vertex_count = size_t(mesh.vertices.size() * threshold);
std::vector<unsigned int> indices(target_vertex_count);
indices.resize(meshopt_simplifyPoints(&indices[0], &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_vertex_count));
indices.resize(meshopt_simplifyPoints(&indices[0], &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), NULL, 0, 0, target_vertex_count));
double end = timestamp();
+1 -1
View File
@@ -1004,7 +1004,7 @@ static void simplifyPointsStuck()
const float vb[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
// simplifying down to 0 points results in 0 immediately
assert(meshopt_simplifyPoints(0, vb, 3, 12, 0) == 0);
assert(meshopt_simplifyPoints(0, vb, 3, 12, 0, 0, 0, 0) == 0);
}
static void simplifyFlip()
+5 -1
View File
@@ -696,6 +696,8 @@ static void simplifyPointMesh(Mesh& mesh, float threshold)
if (!positions)
return;
const Stream* colors = getStream(mesh, cgltf_attribute_type_color);
size_t vertex_count = mesh.streams[0].data.size();
size_t target_vertex_count = size_t(double(vertex_count) * threshold);
@@ -703,8 +705,10 @@ static void simplifyPointMesh(Mesh& mesh, float threshold)
if (target_vertex_count < 1)
return;
const float color_weight = 1e-2f;
std::vector<unsigned int> indices(target_vertex_count);
indices.resize(meshopt_simplifyPoints(&indices[0], positions->data[0].f, vertex_count, sizeof(Attr), target_vertex_count));
indices.resize(meshopt_simplifyPoints(&indices[0], positions->data[0].f, vertex_count, sizeof(Attr), colors ? colors->data[0].f : NULL, sizeof(Attr), color_weight, target_vertex_count));
std::vector<Attr> scratch(indices.size());
+2 -1
View File
@@ -382,8 +382,9 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destinati
*
* destination must contain enough space for the target index buffer (target_vertex_count elements)
* vertex_positions should have float3 position in the first 12 bytes of each vertex
* vertex_colors should can be NULL; when it's not NULL, it should have float3 color in the first 12 bytes of each vertex
*/
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_vertex_count);
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_colors, size_t vertex_colors_stride, float color_weight, size_t target_vertex_count);
/**
* Returns the error scaling factor used by the simplifier to convert between absolute and relative extents
+33 -11
View File
@@ -461,6 +461,7 @@ struct QuadricGrad
struct Reservoir
{
float x, y, z;
float r, g, b;
float w;
};
@@ -1322,20 +1323,27 @@ static void fillCellQuadrics(Quadric* cell_quadrics, const unsigned int* indices
}
}
static void fillCellReservoirs(Reservoir* cell_reservoirs, size_t cell_count, const Vector3* vertex_positions, size_t vertex_count, const unsigned int* vertex_cells)
static void fillCellReservoirs(Reservoir* cell_reservoirs, size_t cell_count, const Vector3* vertex_positions, const float* vertex_colors, size_t vertex_colors_stride, size_t vertex_count, const unsigned int* vertex_cells)
{
static const float dummy_color[] = { 0.f, 0.f, 0.f };
size_t vertex_colors_stride_float = vertex_colors_stride / sizeof(float);
for (size_t i = 0; i < vertex_count; ++i)
{
unsigned int cell = vertex_cells[i];
const Vector3& v = vertex_positions[i];
Reservoir& r = cell_reservoirs[cell];
float w = 1.f;
const float* color = vertex_colors ? &vertex_colors[i * vertex_colors_stride_float] : dummy_color;
r.x += v.x * w;
r.y += v.y * w;
r.z += v.z * w;
r.w += w;
r.x += v.x;
r.y += v.y;
r.z += v.z;
r.r += color[0];
r.g += color[1];
r.b += color[2];
r.w += 1.f;
}
for (size_t i = 0; i < cell_count; ++i)
@@ -1347,6 +1355,9 @@ static void fillCellReservoirs(Reservoir* cell_reservoirs, size_t cell_count, co
r.x *= iw;
r.y *= iw;
r.z *= iw;
r.r *= iw;
r.g *= iw;
r.b *= iw;
}
}
@@ -1367,8 +1378,12 @@ static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t c
}
}
static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t cell_count, const unsigned int* vertex_cells, const Reservoir* cell_reservoirs, const Vector3* vertex_positions, size_t vertex_count)
static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t cell_count, const unsigned int* vertex_cells, const Reservoir* cell_reservoirs, const Vector3* vertex_positions, const float* vertex_colors, size_t vertex_colors_stride, float color_weight, size_t vertex_count)
{
static const float dummy_color[] = { 0.f, 0.f, 0.f };
size_t vertex_colors_stride_float = vertex_colors_stride / sizeof(float);
memset(cell_remap, -1, cell_count * sizeof(unsigned int));
for (size_t i = 0; i < vertex_count; ++i)
@@ -1377,7 +1392,11 @@ static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t c
const Vector3& v = vertex_positions[i];
const Reservoir& r = cell_reservoirs[cell];
float error = (v.x - r.x) * (v.x - r.x) + (v.y - r.y) * (v.y - r.y) + (v.z - r.z) * (v.z - r.z);
const float* color = vertex_colors ? &vertex_colors[i * vertex_colors_stride_float] : dummy_color;
float pos_error = (v.x - r.x) * (v.x - r.x) + (v.y - r.y) * (v.y - r.y) + (v.z - r.z) * (v.z - r.z);
float col_error = (color[0] - r.r) * (color[0] - r.r) + (color[1] - r.g) * (color[1] - r.g) + (color[2] - r.b) * (color[2] - r.b);
float error = pos_error + color_weight * col_error;
if (cell_remap[cell] == ~0u || cell_errors[cell] > error)
{
@@ -1755,12 +1774,15 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind
return write;
}
size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_vertex_count)
size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_colors, size_t vertex_colors_stride, float color_weight, size_t target_vertex_count)
{
using namespace meshopt;
assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256);
assert(vertex_positions_stride % sizeof(float) == 0);
assert(vertex_colors_stride == 0 || (vertex_colors_stride >= 12 && vertex_colors_stride <= 256));
assert(vertex_colors_stride % sizeof(float) == 0);
assert(vertex_colors == NULL || vertex_colors_stride != 0);
assert(target_vertex_count <= vertex_count);
size_t target_cell_count = target_vertex_count;
@@ -1848,13 +1870,13 @@ size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_pos
Reservoir* cell_reservoirs = allocator.allocate<Reservoir>(cell_count);
memset(cell_reservoirs, 0, cell_count * sizeof(Reservoir));
fillCellReservoirs(cell_reservoirs, cell_count, vertex_positions, vertex_count, vertex_cells);
fillCellReservoirs(cell_reservoirs, cell_count, vertex_positions, vertex_colors, vertex_colors_stride, vertex_count, vertex_cells);
// for each target cell, find the vertex with the minimal error
unsigned int* cell_remap = allocator.allocate<unsigned int>(cell_count);
float* cell_errors = allocator.allocate<float>(cell_count);
fillCellRemap(cell_remap, cell_errors, cell_count, vertex_cells, cell_reservoirs, vertex_positions, vertex_count);
fillCellRemap(cell_remap, cell_errors, cell_count, vertex_cells, cell_reservoirs, vertex_positions, vertex_colors, vertex_colors_stride, color_weight * color_weight, vertex_count);
// copy results to the output
assert(cell_count <= target_vertex_count);