Skip to content

Commit

Permalink
bug fixes; identified the potential source of man problem causing flo…
Browse files Browse the repository at this point in the history
…ating polygon partitioning to create duplicate vertices
  • Loading branch information
chitalu committed Jan 13, 2025
1 parent 29c766e commit 6f711e0
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 27 deletions.
6 changes: 6 additions & 0 deletions include/mcut/internal/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,19 @@ struct connected_component_t {
// ]
//
std::vector<uint32_t> seam_vertex_sequence_array_cache;
# if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
//
// The multiplier is a value that is used to convert between native user coordinates
// and rational integer coordinates. Each connected component has such a value, which
// we determine from the two respective input meshes from which the connected component
// came from. Refer to the "preproc" function for more detail on how it is computed.
//
double multiplier;
// the vertex centre of mass computed using the srcmesh and cutmesh (in user coordinates).
vec3_<double> srcmesh_cutmesh_com;
// translation vectors that shifts recentred coordinates to the positive quadrant.
vec3_<double> pre_quantization_translation;
#endif
};

// struct representing a fragment
Expand Down
15 changes: 13 additions & 2 deletions source/frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2051,8 +2051,10 @@ void get_connected_component_data_impl_detail(
for (int i = 0; i < 3; ++i) {
#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS

const float val = static_cast<float>(
scalar_t::dequantize(coords[i], cc_uptr->multiplier));
const float val = static_cast<float>(scalar_t::dequantize(
coords[i], cc_uptr->multiplier)) +
cc_uptr->srcmesh_cutmesh_com[i] -
cc_uptr->pre_quantization_translation[i];
#else
const float val = static_cast<float>(coords[i]);
#endif
Expand Down Expand Up @@ -2133,7 +2135,16 @@ void get_connected_component_data_impl_detail(

// for each component of coordinate
for (int i = 0; i < 3; ++i) {
#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
const double val =
scalar_t::dequantize(coords[i], cc_uptr->multiplier) +
cc_uptr->srcmesh_cutmesh_com[i] -
cc_uptr->pre_quantization_translation[i];
#else

const double val = static_cast<double>(coords[i]);

#endif
*(casted_ptr + elem_offset) = val;
elem_offset += 1;
}
Expand Down
86 changes: 73 additions & 13 deletions source/math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,37 @@
normal = vec3(0.0);
//int crossprods = 0;
for (int i = 1; i < polygon_vertex_count - 1; ++i) {
auto cross = cross_product( polygon_vertices[i] - polygon_vertices[0],
polygon_vertices[(i + 1) % polygon_vertex_count] - polygon_vertices[0]);
if(squared_length(cross) > scalar_t::zero())
{
#if !defined(MCUT_WITH_ARBITRARY_PRECISION_NUMBERS)
normal = normal +
normalize( cross_product(polygon_vertices[i] - polygon_vertices[0],
polygon_vertices[(i + 1) % polygon_vertex_count] -
polygon_vertices[0]) , multiplier);
//crossprods++;
}
#else
auto vec0 = polygon_vertices[i] - polygon_vertices[0];

auto vec1 = polygon_vertices[(i + 1) % polygon_vertex_count] - polygon_vertices[0];

if(squared_length(vec0) > scalar_t::zero() && squared_length(vec1) > scalar_t::zero())
{
vec3_<double> vec0_(scalar_t::dequantize(vec0[0], multiplier),
scalar_t::dequantize(vec0[1], multiplier),
scalar_t::dequantize(vec0[2], multiplier));
vec3_<double> vec1_(scalar_t::dequantize(vec1[0], multiplier),
scalar_t::dequantize(vec1[1], multiplier),
scalar_t::dequantize(vec1[2], multiplier));

auto cross_ = cross_product(vec0_, vec1_);
if(squared_length(cross_) > 0.)
{
auto cross_n = normalize(cross_);
vec3 cross = vec3(scalar_t::quantize(cross_n[0], multiplier),
scalar_t::quantize(cross_n[1], multiplier),
scalar_t::quantize(cross_n[2], multiplier));
normal = normal + cross;
break;
}
}
#endif
}


Expand Down Expand Up @@ -227,10 +246,48 @@
const int polygon_vertex_count = (int)polygon_vertices.size();
MCUT_ASSERT(polygon_vertex_count >= 3);

/*{
std::ofstream f("poly.obj");
for(int v = 0; v < polygon_vertices.size(); ++v)
{
f << "v " << scalar_t::dequantize(polygon_vertices[v][0], multiplier) << " "
<< scalar_t::dequantize(polygon_vertices[v][1], multiplier) << " "
<< scalar_t::dequantize(polygon_vertices[v][2], multiplier) << std::endl;
}
f << "f ";
for(int v = 0; v < polygon_vertices.size(); ++v)
{
f << v << " ";
}
f << std::endl;
f.close();
}*/

std::vector<vec2> x;
project_to_2d(x, polygon_vertices, polygon_normal, polygon_normal_largest_component, multiplier);
MCUT_ASSERT(x.size() == (size_t)polygon_vertex_count);

/*{
std::ofstream f("poly2.obj");
for(int v = 0; v < x.size(); ++v)
{
f << "v " << scalar_t::dequantize(x[v][0], multiplier) << " "
<< scalar_t::dequantize(x[v][1], multiplier) << " "
<< 0 << std::endl;
}
f << "f ";
for(int v = 0; v < x.size(); ++v)
{
f << v << " ";
}
f << std::endl;
f.close();
}*/

/*
NOTE: We cannot just use _any_/the first result of "colinear(x[i], x[j], x[k])" which returns true since
any three points that are _nearly_ colinear (in the limit of floating point precision)
Expand All @@ -245,17 +302,20 @@
*/

// get any three vertices that are not collinear
i = 0;
/*i = 0;
j = i + 1;
k = j + 1;
k = j + 1;*/
std::vector<std::tuple<int, int, int, scalar_t>> non_colinear_triplets;

for (; i < polygon_vertex_count; ++i) {
for (; j < polygon_vertex_count; ++j) {
for (; k < polygon_vertex_count; ++k) {
for (int i_=0; i_ < polygon_vertex_count; ++i_)
{
for (int j_=i_+1; j_ < polygon_vertex_count; ++j_) {
for(int k_ = j_ + 1; k_ < polygon_vertex_count; ++k_)
{
scalar_t predRes;
if (!collinear(x[i], x[j], x[k], predRes)) {
non_colinear_triplets.emplace_back(std::make_tuple(i, j, k, predRes));
//std::cout << "i=" << i_ << " j=" << j_ << " k="<<k_ << std::endl;
if (!collinear(x[i_], x[j_], x[k_], predRes)) {
non_colinear_triplets.emplace_back(std::make_tuple(i_, j_, k_, predRes));
}
}
}
Expand Down
56 changes: 44 additions & 12 deletions source/preproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ void resolve_floating_polygons(

// NOTE: using max (i.e. < operator) lead to floating point precision issues on
// test 40. The only solution to which is exact arithmetic. However, since we still
// want MCUT to work even if the user only has fixed precision numbers.
// want MCUT to work even if the user only has fixed precision numbers (outdated).
// We pick edges based on this which are closest. No worries about colinear edges
// because they will be detected later and skipped!
auto fp_max_dist_predicate = [&](std::pair<int, int> edgePairA,
Expand Down Expand Up @@ -1079,14 +1079,16 @@ void resolve_floating_polygons(
it != polyVerts.cend();
++it)
{

// TODO: call "collinear" with vec3_<double> not vec3. That is the only way to
// get a reliable measure because with double everything is in the same space/units
// (lengths areas etc).
bool are_collinear = collinear(segStart, segEnd, (*it), predResult);
// last ditch attempt to prevent the possibility of creating a partitioning
// edge that more-or-less passes through a vertex (of origin-face or the floatig poly itself)
// see: test41
const scalar_t epsilon = 1e-6;
const double epsilon = 1e-6;
#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
if(are_collinear || (!are_collinear && epsilon > absolute_value(predResult)))
if(are_collinear || epsilon > scalar_t::dequantize(absolute_value(predResult),multiplier))
#else
if(are_collinear || (!are_collinear && epsilon > std::fabs(predResult)))
#endif
Expand Down Expand Up @@ -2213,6 +2215,20 @@ bool calculate_vertex_parameters(

pre_quantization_translation = to_positive_quadrant + offset_from_origin;

//
// update bboxes and coms
//
srcmesh_com = srcmesh_com + pre_quantization_translation;
cutmesh_com = cutmesh_com + pre_quantization_translation;
srcmesh_cutmesh_com = srcmesh_cutmesh_com + pre_quantization_translation;
srcmesh_bboxmin = srcmesh_bboxmin + pre_quantization_translation;
srcmesh_bboxmax = srcmesh_bboxmax + pre_quantization_translation;
cutmesh_bboxmin = cutmesh_bboxmin + pre_quantization_translation;
cutmesh_bboxmax = cutmesh_bboxmax + pre_quantization_translation;
srcmesh_cutmesh_bboxmin = srcmesh_cutmesh_bboxmin + pre_quantization_translation;
srcmesh_cutmesh_bboxmax = srcmesh_cutmesh_bboxmax + pre_quantization_translation;


double max_coord = std::numeric_limits<double>::lowest();
double min_coord = std::numeric_limits<double>::max();

Expand Down Expand Up @@ -2307,8 +2323,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,
numSrcMeshVertices,
numSrcMeshFaces,
multiplier,
vec3_<double>(0.0) /*srcmesh_cutmesh_com*/,
vec3_<double>(0.0)/*pre_quantization_translation*/))
srcmesh_cutmesh_com,
pre_quantization_translation))
{
throw std::invalid_argument("invalid source-mesh arrays");
}
Expand All @@ -2331,12 +2347,12 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

kernel_input.src_mesh = source_hmesh;

kernel_input.verbose = false;
kernel_input.verbose = true;
kernel_input.require_looped_cutpaths = false;

kernel_input.verbose =
static_cast<bool>((context_ptr->get_flags() & MC_DEBUG) &&
(context_ptr->dbgCallbackBitfieldType & MC_DEBUG_SOURCE_KERNEL));
//kernel_input.verbose =
// static_cast<bool>((context_ptr->get_flags() & MC_DEBUG) &&
// (context_ptr->dbgCallbackBitfieldType & MC_DEBUG_SOURCE_KERNEL));
kernel_input.require_looped_cutpaths =
static_cast<bool>(dispatchFlags & MC_DISPATCH_REQUIRE_THROUGH_CUTS);
kernel_input.populate_vertex_maps =
Expand Down Expand Up @@ -2620,8 +2636,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,
numCutMeshVertices,
numCutMeshFaces,
multiplier,
vec3_<double>(0.0) /*srcmesh_cutmesh_com*/,
vec3_<double>(0.0) /*pre_quantization_translation*/,
srcmesh_cutmesh_com,
pre_quantization_translation,
((cut_mesh_perturbation_count == 0) ? NULL : &perturbation)))
{
throw std::invalid_argument("invalid cut-mesh arrays");
Expand Down Expand Up @@ -3030,6 +3046,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asFragPtr->multiplier = multiplier;
asFragPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asFragPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down Expand Up @@ -3095,6 +3113,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asFragPtr->multiplier = multiplier;
asFragPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asFragPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down Expand Up @@ -3164,6 +3184,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asPatchPtr->multiplier = multiplier;
asPatchPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asPatchPtr->pre_quantization_translation = pre_quantization_translation;
#endif
context_ptr->connected_components.push_front(
cc_ptr); // copy the connected component ptr into the context object
Expand Down Expand Up @@ -3229,6 +3251,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asPatchPtr->multiplier = multiplier;
asPatchPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asPatchPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down Expand Up @@ -3300,6 +3324,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asSrcMeshSeamPtr->multiplier = multiplier;
asSrcMeshSeamPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asSrcMeshSeamPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down Expand Up @@ -3365,6 +3391,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asCutMeshSeamPtr->multiplier = multiplier;
asCutMeshSeamPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asCutMeshSeamPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down Expand Up @@ -3498,6 +3526,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asCutMeshInputPtr->multiplier = multiplier;
asCutMeshInputPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asCutMeshInputPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down Expand Up @@ -3622,6 +3652,8 @@ extern "C" void preproc(std::shared_ptr<context_t> context_ptr,

#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
asSrcMeshInputPtr->multiplier = multiplier;
asSrcMeshInputPtr->srcmesh_cutmesh_com = srcmesh_cutmesh_com;
asSrcMeshInputPtr->pre_quantization_translation = pre_quantization_translation;
#endif

context_ptr->connected_components.push_front(
Expand Down
2 changes: 2 additions & 0 deletions tests/source/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ UTEST_I_TEARDOWN(Benchmark)

UTEST_I(Benchmark, inputID, NUMBER_OF_BENCHMARKS)
{

std::vector<std::pair<std::string, std::string>> benchmarkMeshPairs;

std::stringstream ss;
Expand Down Expand Up @@ -138,6 +139,7 @@ UTEST_I(Benchmark, inputID, NUMBER_OF_BENCHMARKS)
&utest_fixture->cutMesh.numVertices,
&utest_fixture->cutMesh.numFaces);


//
// do the cutting
//
Expand Down

0 comments on commit 6f711e0

Please sign in to comment.