Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_boolean_convert.cc')
-rw-r--r--source/blender/blenkernel/intern/mesh_boolean_convert.cc133
1 files changed, 76 insertions, 57 deletions
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index a1ef2d2e6b5..360c7da2ae2 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -9,6 +9,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -23,6 +24,7 @@
#include "BLI_mesh_intersect.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"
+#include "BLI_virtual_array.hh"
namespace blender::meshintersect {
@@ -112,7 +114,7 @@ class MeshesToIMeshInfo {
* input `Mesh` that contained the `MVert` that it came from. */
int MeshesToIMeshInfo::input_mesh_for_imesh_vert(int imesh_v) const
{
- int n = static_cast<int>(mesh_vert_offset.size());
+ int n = int(mesh_vert_offset.size());
for (int i = 0; i < n - 1; ++i) {
if (imesh_v < mesh_vert_offset[i + 1]) {
return i;
@@ -125,7 +127,7 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_vert(int imesh_v) const
* return the index of the input `Mesh` that contained the `MVert` that it came from. */
int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const
{
- int n = static_cast<int>(mesh_edge_offset.size());
+ int n = int(mesh_edge_offset.size());
for (int i = 0; i < n - 1; ++i) {
if (imesh_e < mesh_edge_offset[i + 1]) {
return i;
@@ -138,7 +140,7 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const
* input `Mesh` that contained the `MPoly` that it came from. */
int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const
{
- int n = static_cast<int>(mesh_poly_offset.size());
+ int n = int(mesh_poly_offset.size());
for (int i = 0; i < n - 1; ++i) {
if (imesh_f < mesh_poly_offset[i + 1]) {
return i;
@@ -160,9 +162,10 @@ const MPoly *MeshesToIMeshInfo::input_mpoly_for_orig_index(int orig_index,
int orig_mesh_index = input_mesh_for_imesh_face(orig_index);
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
const Mesh *me = meshes[orig_mesh_index];
+ const Span<MPoly> polys = me->polys();
int index_in_mesh = orig_index - mesh_poly_offset[orig_mesh_index];
BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totpoly);
- const MPoly *mp = &me->mpoly[index_in_mesh];
+ const MPoly *mp = &polys[index_in_mesh];
if (r_orig_mesh) {
*r_orig_mesh = me;
}
@@ -186,9 +189,10 @@ const MVert *MeshesToIMeshInfo::input_mvert_for_orig_index(int orig_index,
int orig_mesh_index = input_mesh_for_imesh_vert(orig_index);
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
const Mesh *me = meshes[orig_mesh_index];
+ const Span<MVert> verts = me->verts();
int index_in_mesh = orig_index - mesh_vert_offset[orig_mesh_index];
BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totvert);
- const MVert *mv = &me->mvert[index_in_mesh];
+ const MVert *mv = &verts[index_in_mesh];
if (r_orig_mesh) {
*r_orig_mesh = me;
}
@@ -206,9 +210,10 @@ const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index,
int orig_mesh_index = input_mesh_for_imesh_edge(orig_index);
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
const Mesh *me = meshes[orig_mesh_index];
+ const Span<MEdge> edges = me->edges();
int index_in_mesh = orig_index - mesh_edge_offset[orig_mesh_index];
BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totedge);
- const MEdge *medge = &me->medge[index_in_mesh];
+ const MEdge *medge = &edges[index_in_mesh];
if (r_orig_mesh) {
*r_orig_mesh = me;
}
@@ -304,17 +309,19 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
bool need_face_flip = r_info->has_negative_transform[mi] != r_info->has_negative_transform[0];
Vector<Vert *> verts(me->totvert);
- Span<MVert> mverts = Span(me->mvert, me->totvert);
+ const Span<MVert> mesh_verts = me->verts();
+ const Span<MPoly> polys = me->polys();
+ const Span<MLoop> loops = me->loops();
/* Allocate verts
* Skip the matrix multiplication for each point when there is no transform for a mesh,
* for example when the first mesh is already in the target space. (Note the logic
* directly above, which uses an identity matrix with a null input transform). */
if (obmats[mi] == nullptr) {
- threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) {
+ threading::parallel_for(mesh_verts.index_range(), 2048, [&](IndexRange range) {
float3 co;
for (int i : range) {
- co = float3(mverts[i].co);
+ co = float3(mesh_verts[i].co);
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 Vert(mco, dco, NO_INDEX, i);
@@ -322,26 +329,26 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
});
}
else {
- threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) {
+ threading::parallel_for(mesh_verts.index_range(), 2048, [&](IndexRange range) {
float3 co;
for (int i : range) {
- co = r_info->to_target_transform[mi] * float3(mverts[i].co);
+ co = r_info->to_target_transform[mi] * float3(mesh_verts[i].co);
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 Vert(mco, dco, NO_INDEX, i);
}
});
}
- for (int i : mverts.index_range()) {
+ for (int i : mesh_verts.index_range()) {
r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(verts[i]);
++v;
}
- for (const MPoly &poly : Span(me->mpoly, me->totpoly)) {
+ for (const MPoly &poly : polys) {
int flen = poly.totloop;
face_vert.resize(flen);
face_edge_orig.resize(flen);
- const MLoop *l = &me->mloop[poly.loopstart];
+ const MLoop *l = &loops[poly.loopstart];
for (int i = 0; i < flen; ++i) {
int mverti = r_info->mesh_vert_offset[mi] + l->v;
const Vert *fv = r_info->mesh_to_imesh_vert[mverti];
@@ -368,15 +375,10 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
* `mv` is in `dest_mesh` with index `mv_index`.
* The `orig_mv` vertex came from Mesh `orig_me` and had index `index_in_orig_me` there. */
static void copy_vert_attributes(Mesh *dest_mesh,
- MVert *mv,
- const MVert *orig_mv,
const Mesh *orig_me,
int mv_index,
int index_in_orig_me)
{
- mv->bweight = orig_mv->bweight;
- mv->flag = orig_mv->flag;
-
/* For all layers in the orig mesh, copy the layer information. */
CustomData *target_cd = &dest_mesh->vdata;
const CustomData *source_cd = &orig_me->vdata;
@@ -405,13 +407,17 @@ static void copy_poly_attributes(Mesh *dest_mesh,
const Mesh *orig_me,
int mp_index,
int index_in_orig_me,
- Span<short> material_remap)
+ Span<short> material_remap,
+ MutableSpan<int> dst_material_indices)
{
- if (material_remap.size() > 0 && material_remap.index_range().contains(orig_mp->mat_nr)) {
- mp->mat_nr = material_remap[orig_mp->mat_nr];
+ const VArray<int> src_material_indices = orig_me->attributes().lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
+ const int src_index = src_material_indices[index_in_orig_me];
+ if (material_remap.size() > 0 && material_remap.index_range().contains(src_index)) {
+ dst_material_indices[mp_index] = material_remap[src_index];
}
else {
- mp->mat_nr = orig_mp->mat_nr;
+ dst_material_indices[mp_index] = src_index;
}
mp->flag = orig_mp->flag;
@@ -439,8 +445,6 @@ static void copy_edge_attributes(Mesh *dest_mesh,
int medge_index,
int index_in_orig_me)
{
- medge->bweight = orig_medge->bweight;
- medge->crease = orig_medge->crease;
medge->flag = orig_medge->flag;
CustomData *target_cd = &dest_mesh->edata;
const CustomData *source_cd = &orig_me->edata;
@@ -473,14 +477,16 @@ static int fill_orig_loops(const Face *f,
const Mesh *orig_me,
int orig_me_index,
MeshesToIMeshInfo &mim,
- Array<int> &orig_loops)
+ MutableSpan<int> r_orig_loops)
{
- orig_loops.fill(-1);
+ r_orig_loops.fill(-1);
+ const Span<MLoop> orig_loops = orig_me->loops();
+
int orig_mplen = orig_mp->totloop;
if (f->size() != orig_mplen) {
return 0;
}
- BLI_assert(orig_loops.size() == orig_mplen);
+ BLI_assert(r_orig_loops.size() == orig_mplen);
/* We'll look for the case where the first vertex in f has an original vertex
* that is the same as one in orig_me (after correcting for offset in mim meshes).
* Then see that loop and any subsequent ones have the same start and end vertex.
@@ -502,7 +508,7 @@ static int fill_orig_loops(const Face *f,
int offset = -1;
for (int i = 0; i < orig_mplen; ++i) {
int loop_i = i + orig_mp->loopstart;
- if (orig_me->mloop[loop_i].v == first_orig_v_in_orig_me) {
+ if (orig_loops[loop_i].v == first_orig_v_in_orig_me) {
offset = i;
break;
}
@@ -513,7 +519,7 @@ static int fill_orig_loops(const Face *f,
int num_orig_loops_found = 0;
for (int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) {
int orig_mp_loop_index = (mp_loop_index + offset) % orig_mplen;
- MLoop *l = &orig_me->mloop[orig_mp->loopstart + orig_mp_loop_index];
+ const MLoop *l = &orig_loops[orig_mp->loopstart + orig_mp_loop_index];
int fv_orig = f->vert[mp_loop_index]->orig;
if (fv_orig != NO_INDEX) {
fv_orig -= orig_me_vert_offset;
@@ -522,7 +528,8 @@ static int fill_orig_loops(const Face *f,
}
}
if (l->v == fv_orig) {
- MLoop *lnext = &orig_me->mloop[orig_mp->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)];
+ const MLoop *lnext =
+ &orig_loops[orig_mp->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)];
int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig;
if (fvnext_orig != NO_INDEX) {
fvnext_orig -= orig_me_vert_offset;
@@ -531,7 +538,7 @@ static int fill_orig_loops(const Face *f,
}
}
if (lnext->v == fvnext_orig) {
- orig_loops[mp_loop_index] = orig_mp->loopstart + orig_mp_loop_index;
+ r_orig_loops[mp_loop_index] = orig_mp->loopstart + orig_mp_loop_index;
++num_orig_loops_found;
}
}
@@ -549,19 +556,18 @@ static void get_poly2d_cos(const Mesh *me,
const float4x4 &trans_mat,
float r_axis_mat[3][3])
{
- int n = mp->totloop;
+ const Span<MVert> verts = me->verts();
+ const Span<MLoop> loops = me->loops();
+ const Span<MLoop> poly_loops = loops.slice(mp->loopstart, mp->totloop);
/* Project coordinates to 2d in cos_2d, using normal as projection axis. */
float axis_dominant[3];
- BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, axis_dominant);
+ BKE_mesh_calc_poly_normal(mp, &loops[mp->loopstart], verts.data(), axis_dominant);
axis_dominant_v3_to_m3(r_axis_mat, axis_dominant);
- MLoop *ml = &me->mloop[mp->loopstart];
- const MVert *mverts = me->mvert;
- for (int i = 0; i < n; ++i) {
- float3 co = mverts[ml->v].co;
+ for (const int i : poly_loops.index_range()) {
+ float3 co = verts[poly_loops[i].v].co;
co = trans_mat * co;
mul_v2_m3v3(cos_2d[i], r_axis_mat, co);
- ++ml;
}
}
@@ -596,6 +602,8 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
get_poly2d_cos(orig_me, orig_mp, cos_2d, mim.to_target_transform[orig_me_index], axis_mat);
}
CustomData *target_cd = &dest_mesh->ldata;
+ const Span<MVert> dst_verts = dest_mesh->verts();
+ const Span<MLoop> dst_loops = dest_mesh->loops();
for (int i = 0; i < mp->totloop; ++i) {
int loop_index = mp->loopstart + i;
int orig_loop_index = norig > 0 ? orig_loops[i] : -1;
@@ -605,7 +613,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
* The coordinate needs to be projected into 2d, just like the interpolating polygon's
* coordinates were. The `dest_mesh` coordinates are already in object 0 local space. */
float co[2];
- mul_v2_m3v3(co, axis_mat, dest_mesh->mvert[dest_mesh->mloop[loop_index].v].co);
+ mul_v2_m3v3(co, axis_mat, dst_verts[dst_loops[loop_index].v].co);
interp_weights_poly_v2(weights.data(), cos_2d, orig_mp->totloop, co);
}
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
@@ -663,15 +671,15 @@ static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMesh
const Mesh *me = mim.meshes[mesh_index];
if (me->totvert) {
CustomData_merge(
- &me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_DEFAULT, target->totvert);
+ &me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, target->totvert);
}
if (me->totloop) {
CustomData_merge(
- &me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_DEFAULT, target->totloop);
+ &me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, target->totloop);
}
if (me->totpoly) {
CustomData_merge(
- &me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_DEFAULT, target->totpoly);
+ &me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, target->totpoly);
}
}
}
@@ -682,7 +690,7 @@ static void merge_edge_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
const Mesh *me = mim.meshes[mesh_index];
if (me->totedge) {
CustomData_merge(
- &me->edata, &target->edata, CD_MASK_MESH.emask, CD_DEFAULT, target->totedge);
+ &me->edata, &target->edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, target->totedge);
}
}
}
@@ -708,22 +716,28 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
merge_vertex_loop_poly_customdata_layers(result, mim);
/* Set the vertex coordinate values and other data. */
+ MutableSpan<MVert> verts = result->verts_for_write();
for (int vi : im->vert_index_range()) {
const Vert *v = im->vert(vi);
- MVert *mv = &result->mvert[vi];
- copy_v3fl_v3db(mv->co, v->co);
if (v->orig != NO_INDEX) {
const Mesh *orig_me;
int index_in_orig_me;
- const MVert *orig_mv = mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me);
- copy_vert_attributes(result, mv, orig_mv, orig_me, vi, index_in_orig_me);
+ mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me);
+ copy_vert_attributes(result, orig_me, vi, index_in_orig_me);
}
+ MVert *mv = &verts[vi];
+ copy_v3fl_v3db(mv->co, v->co);
}
/* Set the loopstart and totloop for each output poly,
* and set the vertices in the appropriate loops. */
+ bke::SpanAttributeWriter<int> dst_material_indices =
+ result->attributes_for_write().lookup_or_add_for_write_only_span<int>("material_index",
+ ATTR_DOMAIN_FACE);
int cur_loop_index = 0;
- MLoop *l = result->mloop;
+ MutableSpan<MLoop> dst_loops = result->loops_for_write();
+ MutableSpan<MPoly> dst_polys = result->polys_for_write();
+ MLoop *l = dst_loops.data();
for (int fi : im->face_index_range()) {
const Face *f = im->face(fi);
const Mesh *orig_me;
@@ -731,7 +745,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
int orig_me_index;
const MPoly *orig_mp = mim.input_mpoly_for_orig_index(
f->orig, &orig_me, &orig_me_index, &index_in_orig_me);
- MPoly *mp = &result->mpoly[fi];
+ MPoly *mp = &dst_polys[fi];
mp->totloop = f->size();
mp->loopstart = cur_loop_index;
for (int j : f->index_range()) {
@@ -750,9 +764,11 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
index_in_orig_me,
(mim.material_remaps.size() > 0) ?
mim.material_remaps[orig_me_index].as_span() :
- Span<short>());
+ Span<short>(),
+ dst_material_indices.span);
copy_or_interp_loop_attributes(result, f, mp, orig_mp, orig_me, orig_me_index, mim);
}
+ dst_material_indices.finish();
/* BKE_mesh_calc_edges will calculate and populate all the
* MEdges from the MPolys. */
@@ -761,17 +777,18 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
/* Now that the MEdges are populated, we can copy over the required attributes and custom layers.
*/
+ MutableSpan<MEdge> edges = result->edges_for_write();
for (int fi : im->face_index_range()) {
const Face *f = im->face(fi);
- MPoly *mp = &result->mpoly[fi];
+ const MPoly *mp = &dst_polys[fi];
for (int j : f->index_range()) {
if (f->edge_orig[j] != NO_INDEX) {
const Mesh *orig_me;
int index_in_orig_me;
const MEdge *orig_medge = mim.input_medge_for_orig_index(
f->edge_orig[j], &orig_me, &index_in_orig_me);
- int e_index = result->mloop[mp->loopstart + j].e;
- MEdge *medge = &result->medge[e_index];
+ int e_index = dst_loops[mp->loopstart + j].e;
+ MEdge *medge = &edges[e_index];
copy_edge_attributes(result, medge, orig_medge, orig_me, e_index, index_in_orig_me);
}
}
@@ -814,7 +831,7 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
return mi;
}
}
- return static_cast<int>(mim.mesh_poly_offset.size()) - 1;
+ return int(mim.mesh_poly_offset.size()) - 1;
};
IMesh m_out = boolean_mesh(m_in,
static_cast<BoolOpType>(boolean_mode),
@@ -833,12 +850,14 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
/* Store intersecting edge indices. */
if (r_intersecting_edges != nullptr) {
+ const Span<MPoly> polys = result->polys();
+ const Span<MLoop> loops = result->loops();
for (int fi : m_out.face_index_range()) {
const Face &face = *m_out.face(fi);
- const MPoly &poly = result->mpoly[fi];
+ const MPoly &poly = polys[fi];
for (int corner_i : face.index_range()) {
if (face.is_intersect[corner_i]) {
- int e_index = result->mloop[poly.loopstart + corner_i].e;
+ int e_index = loops[poly.loopstart + corner_i].e;
r_intersecting_edges->append(e_index);
}
}