diff --git a/source/blender/geometry/intern/mesh_boolean.cc b/source/blender/geometry/intern/mesh_boolean.cc index 201086148f6..37dc71c7513 100644 --- a/source/blender/geometry/intern/mesh_boolean.cc +++ b/source/blender/geometry/intern/mesh_boolean.cc @@ -78,6 +78,21 @@ static float4x4 clean_transform(const float4x4 &mat) return cleaned; } +static float3 clean_float3(const float3 &co) +{ + float3 cleaned = co; + if (UNLIKELY(!isfinite(co[0]))) { + cleaned[0] = 0.0f; + } + if (UNLIKELY(!isfinite(co[1]))) { + cleaned[1] = 0.0f; + } + if (UNLIKELY(!isfinite(co[2]))) { + cleaned[2] = 0.0f; + } + return cleaned; +} + /* `MeshesToIMeshInfo` keeps track of information used when combining a number * of `Mesh`es into a single `IMesh` for doing boolean on. * Mostly this means keeping track of the index offsets for various mesh elements. */ @@ -329,7 +344,7 @@ static meshintersect::IMesh meshes_to_imesh(Span meshes, if (transforms.is_empty() || r_info->to_target_transform[mi] == float4x4::identity()) { threading::parallel_for(vert_positions.index_range(), 2048, [&](IndexRange range) { for (int i : range) { - float3 co = vert_positions[i]; + float3 co = clean_float3(vert_positions[i]); mpq3 mco = mpq3(co.x, co.y, co.z); double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d()); verts[i] = new meshintersect::Vert(mco, dco, meshintersect::NO_INDEX, i); @@ -339,7 +354,8 @@ static meshintersect::IMesh meshes_to_imesh(Span meshes, else { threading::parallel_for(vert_positions.index_range(), 2048, [&](IndexRange range) { for (int i : range) { - float3 co = math::transform_point(r_info->to_target_transform[mi], vert_positions[i]); + float3 co = math::transform_point(r_info->to_target_transform[mi], + clean_float3(vert_positions[i])); mpq3 mco = mpq3(co.x, co.y, co.z); double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d()); verts[i] = new meshintersect::Vert(mco, dco, meshintersect::NO_INDEX, i);