31 constexpr
int estimated_max_facelen = 100;
43 const float fuzz = 1e-6f;
44 for (
int i = 0; i < 4; i++) {
45 for (
int j = 0; j < 4; j++) {
46 float f = mat.values[i][j];
47 if (
fabsf(f) <= fuzz) {
50 else if (
fabsf(f - 1.0f) <= fuzz) {
53 else if (
fabsf(f + 1.0f) <= fuzz) {
56 cleaned.values[i][j] = f;
65 class MeshesToIMeshInfo {
68 Span<const Mesh *> meshes;
71 Array<int> mesh_vert_offset;
73 Array<int> mesh_edge_offset;
75 Array<int> mesh_poly_offset;
78 Array<const Vert *> mesh_to_imesh_vert;
80 Array<Face *> mesh_to_imesh_face;
83 Array<float4x4> to_target_transform;
85 Array<bool> has_negative_transform;
88 Span<Array<short>> material_remaps;
96 int input_mesh_for_imesh_vert(
int imesh_v)
const;
97 int input_mesh_for_imesh_edge(
int imesh_e)
const;
98 int input_mesh_for_imesh_face(
int imesh_f)
const;
99 const MPoly *input_mpoly_for_orig_index(
int orig_index,
100 const Mesh **r_orig_mesh,
101 int *r_orig_mesh_index,
102 int *r_index_in_orig_mesh)
const;
103 const MVert *input_mvert_for_orig_index(
int orig_index,
104 const Mesh **r_orig_mesh,
105 int *r_index_in_orig_mesh)
const;
106 const MEdge *input_medge_for_orig_index(
int orig_index,
107 const Mesh **r_orig_mesh,
108 int *r_index_in_orig_mesh)
const;
113 int MeshesToIMeshInfo::input_mesh_for_imesh_vert(
int imesh_v)
const
115 int n =
static_cast<int>(mesh_vert_offset.size());
116 for (
int i = 0; i < n - 1; ++i) {
117 if (imesh_v < mesh_vert_offset[i + 1]) {
126 int MeshesToIMeshInfo::input_mesh_for_imesh_edge(
int imesh_e)
const
128 int n =
static_cast<int>(mesh_edge_offset.size());
129 for (
int i = 0; i < n - 1; ++i) {
130 if (imesh_e < mesh_edge_offset[i + 1]) {
139 int MeshesToIMeshInfo::input_mesh_for_imesh_face(
int imesh_f)
const
141 int n =
static_cast<int>(mesh_poly_offset.size());
142 for (
int i = 0; i < n - 1; ++i) {
143 if (imesh_f < mesh_poly_offset[i + 1]) {
155 const MPoly *MeshesToIMeshInfo::input_mpoly_for_orig_index(
int orig_index,
156 const Mesh **r_orig_mesh,
157 int *r_orig_mesh_index,
158 int *r_index_in_orig_mesh)
const
160 int orig_mesh_index = input_mesh_for_imesh_face(orig_index);
161 BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
162 const Mesh *me = meshes[orig_mesh_index];
163 int index_in_mesh = orig_index - mesh_poly_offset[orig_mesh_index];
164 BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totpoly);
169 if (r_orig_mesh_index) {
170 *r_orig_mesh_index = orig_mesh_index;
172 if (r_index_in_orig_mesh) {
173 *r_index_in_orig_mesh = index_in_mesh;
182 const MVert *MeshesToIMeshInfo::input_mvert_for_orig_index(
int orig_index,
183 const Mesh **r_orig_mesh,
184 int *r_index_in_orig_mesh)
const
186 int orig_mesh_index = input_mesh_for_imesh_vert(orig_index);
187 BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
188 const Mesh *me = meshes[orig_mesh_index];
189 int index_in_mesh = orig_index - mesh_vert_offset[orig_mesh_index];
190 BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totvert);
195 if (r_index_in_orig_mesh) {
196 *r_index_in_orig_mesh = index_in_mesh;
202 const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(
int orig_index,
203 const Mesh **r_orig_mesh,
204 int *r_index_in_orig_mesh)
const
206 int orig_mesh_index = input_mesh_for_imesh_edge(orig_index);
207 BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
208 const Mesh *me = meshes[orig_mesh_index];
209 int index_in_mesh = orig_index - mesh_edge_offset[orig_mesh_index];
210 BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totedge);
211 const MEdge *medge = &me->
medge[index_in_mesh];
215 if (r_index_in_orig_mesh) {
216 *r_index_in_orig_mesh = index_in_mesh;
233 static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
234 Span<const float4x4 *> obmats,
235 Span<Array<short>> material_remaps,
238 MeshesToIMeshInfo *r_info)
240 int nmeshes = meshes.size();
242 r_info->meshes = meshes;
243 r_info->tot_meshes_verts = 0;
244 r_info->tot_meshes_polys = 0;
245 int &totvert = r_info->tot_meshes_verts;
246 int &totedge = r_info->tot_meshes_edges;
247 int &totpoly = r_info->tot_meshes_polys;
248 for (
const Mesh *me : meshes) {
257 const int estimate_num_outv = 3 * totvert;
258 const int estimate_num_outf = 4 * totpoly;
259 arena.reserve(estimate_num_outv, estimate_num_outf);
260 r_info->mesh_to_imesh_vert.reinitialize(totvert);
261 r_info->mesh_to_imesh_face.reinitialize(totpoly);
262 r_info->mesh_vert_offset.reinitialize(nmeshes);
263 r_info->mesh_edge_offset.reinitialize(nmeshes);
264 r_info->mesh_poly_offset.reinitialize(nmeshes);
265 r_info->to_target_transform.reinitialize(nmeshes);
266 r_info->has_negative_transform.reinitialize(nmeshes);
267 r_info->material_remaps = material_remaps;
275 Vector<const Vert *, estimated_max_facelen> face_vert;
276 Vector<int, estimated_max_facelen> face_edge_orig;
282 const float4x4 inv_target_mat = clean_transform(target_transform).inverted();
289 for (
int mi : meshes.index_range()) {
290 const Mesh *me = meshes[mi];
291 r_info->mesh_vert_offset[mi] =
v;
292 r_info->mesh_edge_offset[mi] =
e;
293 r_info->mesh_poly_offset[mi] = f;
297 clean_transform(*obmats[mi]);
298 r_info->to_target_transform[mi] = inv_target_mat * objn_mat;
299 r_info->has_negative_transform[mi] = objn_mat.is_negative();
304 bool need_face_flip = r_info->has_negative_transform[mi] != r_info->has_negative_transform[0];
313 if (obmats[mi] ==
nullptr) {
316 for (int i : range) {
317 co = float3(mverts[i].co);
318 mpq3 mco = mpq3(co.x, co.y, co.z);
319 double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d());
320 verts[i] = new Vert(mco, dco, NO_INDEX, i);
327 for (int i : range) {
328 co = r_info->to_target_transform[mi] * float3(mverts[i].co);
329 mpq3 mco = mpq3(co.x, co.y, co.z);
330 double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d());
331 verts[i] = new Vert(mco, dco, NO_INDEX, i);
335 for (
int i : mverts.index_range()) {
336 r_info->mesh_to_imesh_vert[
v] = arena.add_or_find_vert(
verts[i]);
341 int flen = poly.totloop;
342 face_vert.resize(flen);
343 face_edge_orig.resize(flen);
345 for (
int i = 0; i < flen; ++i) {
346 int mverti = r_info->mesh_vert_offset[mi] +
l->
v;
347 const Vert *fv = r_info->mesh_to_imesh_vert[mverti];
348 if (need_face_flip) {
349 face_vert[flen - i - 1] = fv;
350 int iedge = i < flen - 1 ? flen - i - 2 : flen - 1;
351 face_edge_orig[iedge] =
e +
l->
e;
355 face_edge_orig[i] =
e +
l->
e;
359 r_info->mesh_to_imesh_face[f] = arena.add_face(face_vert, f, face_edge_orig);
364 return IMesh(r_info->mesh_to_imesh_face);
370 static void copy_vert_attributes(
Mesh *dest_mesh,
372 const MVert *orig_mv,
375 int index_in_orig_me)
383 for (
int source_layer_i = 0; source_layer_i < source_cd->
totlayer; ++source_layer_i) {
384 int ty = source_cd->
layers[source_layer_i].
type;
390 const char *name = source_cd->
layers[source_layer_i].
name;
394 if (target_layer_i != -1) {
396 source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, mv_index, 1);
402 static void copy_poly_attributes(
Mesh *dest_mesh,
404 const MPoly *orig_mp,
407 int index_in_orig_me,
408 Span<short> material_remap)
410 if (material_remap.size() > 0 && material_remap.index_range().contains(orig_mp->
mat_nr)) {
420 for (
int source_layer_i = 0; source_layer_i < source_cd->
totlayer; ++source_layer_i) {
421 int ty = source_cd->
layers[source_layer_i].
type;
425 const char *name = source_cd->
layers[source_layer_i].
name;
427 if (target_layer_i != -1) {
429 source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, mp_index, 1);
435 static void copy_edge_attributes(
Mesh *dest_mesh,
437 const MEdge *orig_medge,
440 int index_in_orig_me)
447 for (
int source_layer_i = 0; source_layer_i < source_cd->
totlayer; ++source_layer_i) {
448 int ty = source_cd->
layers[source_layer_i].
type;
452 const char *name = source_cd->
layers[source_layer_i].
name;
454 if (target_layer_i != -1) {
456 source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, medge_index, 1);
471 static int fill_orig_loops(
const Face *f,
472 const MPoly *orig_mp,
475 MeshesToIMeshInfo &mim,
476 Array<int> &orig_loops)
479 int orig_mplen = orig_mp->
totloop;
480 if (f->size() != orig_mplen) {
490 int first_orig_v = f->vert[0]->orig;
491 if (first_orig_v == NO_INDEX) {
495 if (orig_me_index != mim.input_mesh_for_imesh_vert(first_orig_v)) {
498 int orig_me_vert_offset = mim.mesh_vert_offset[orig_me_index];
499 int first_orig_v_in_orig_me = first_orig_v - orig_me_vert_offset;
500 BLI_assert(0 <= first_orig_v_in_orig_me && first_orig_v_in_orig_me < orig_me->totvert);
503 for (
int i = 0; i < orig_mplen; ++i) {
505 if (orig_me->
mloop[loop_i].
v == first_orig_v_in_orig_me) {
513 int num_orig_loops_found = 0;
514 for (
int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) {
515 int orig_mp_loop_index = (mp_loop_index +
offset) % orig_mplen;
517 int fv_orig = f->vert[mp_loop_index]->orig;
518 if (fv_orig != NO_INDEX) {
519 fv_orig -= orig_me_vert_offset;
520 if (fv_orig < 0 || fv_orig >= orig_me->
totvert) {
524 if (
l->
v == fv_orig) {
525 MLoop *lnext = &orig_me->
mloop[orig_mp->
loopstart + ((orig_mp_loop_index + 1) % orig_mplen)];
526 int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig;
527 if (fvnext_orig != NO_INDEX) {
528 fvnext_orig -= orig_me_vert_offset;
529 if (fvnext_orig < 0 || fvnext_orig >= orig_me->
totvert) {
530 fvnext_orig = NO_INDEX;
533 if (lnext->
v == fvnext_orig) {
534 orig_loops[mp_loop_index] = orig_mp->
loopstart + orig_mp_loop_index;
535 ++num_orig_loops_found;
539 return num_orig_loops_found;
546 static void get_poly2d_cos(
const Mesh *me,
550 float r_axis_mat[3][3])
555 float axis_dominant[3];
560 for (
int i = 0; i < n; ++i) {
571 static void copy_or_interp_loop_attributes(
Mesh *dest_mesh,
574 const MPoly *orig_mp,
577 MeshesToIMeshInfo &mim)
579 Array<int> orig_loops(mp->
totloop);
580 int norig = fill_orig_loops(f, orig_mp, orig_me, orig_me_index, mim, orig_loops);
584 Array<float> weights;
585 Array<const void *> src_blocks_ofs;
586 float axis_mat[3][3];
594 weights = Array<float>(orig_mp->
totloop);
595 src_blocks_ofs = Array<const void *>(orig_mp->
totloop);
596 get_poly2d_cos(orig_me, orig_mp, cos_2d, mim.to_target_transform[orig_me_index], axis_mat);
599 for (
int i = 0; i < mp->
totloop; ++i) {
601 int orig_loop_index = norig > 0 ? orig_loops[i] : -1;
603 if (orig_loop_index == -1) {
611 for (
int source_layer_i = 0; source_layer_i < source_cd->
totlayer; ++source_layer_i) {
612 int ty = source_cd->
layers[source_layer_i].
type;
616 const char *name = source_cd->
layers[source_layer_i].
name;
618 if (target_layer_i == -1) {
621 if (orig_loop_index != -1) {
623 source_cd, target_cd, source_layer_i, target_layer_i, orig_loop_index, loop_index, 1);
635 int source_layer_type_index = source_layer_i - source_cd->
typemap[ty];
636 BLI_assert(target_layer_type_index != -1 && source_layer_type_index >= 0);
637 for (
int j = 0; j < orig_mp->
totloop; ++j) {
639 source_cd, ty, orig_mp->
loopstart + j, source_layer_type_index);
641 void *dst_block_ofs =
CustomData_get_n(target_cd, ty, loop_index, target_layer_type_index);
643 src_blocks_ofs.data(),
660 static void merge_vertex_loop_poly_customdata_layers(
Mesh *target, MeshesToIMeshInfo &mim)
662 for (
int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
663 const Mesh *me = mim.meshes[mesh_index];
679 static void merge_edge_customdata_layers(
Mesh *target, MeshesToIMeshInfo &mim)
681 for (
int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
682 const Mesh *me = mim.meshes[mesh_index];
694 static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
696 constexpr
int dbg_level = 0;
699 int out_totvert = im->vert_size();
700 int out_totpoly = im->face_size();
702 for (
const Face *f : im->faces()) {
703 out_totloop += f->size();
707 mim.meshes[0], out_totvert, 0, 0, out_totloop, out_totpoly);
709 merge_vertex_loop_poly_customdata_layers(
result, mim);
711 for (
int vi : im->vert_index_range()) {
712 const Vert *
v = im->vert(vi);
715 if (
v->orig != NO_INDEX) {
717 int index_in_orig_me;
718 const MVert *orig_mv = mim.input_mvert_for_orig_index(
v->orig, &orig_me, &index_in_orig_me);
719 copy_vert_attributes(
result,
mv, orig_mv, orig_me, vi, index_in_orig_me);
725 int cur_loop_index = 0;
727 for (
int fi : im->face_index_range()) {
728 const Face *f = im->face(fi);
730 int index_in_orig_me;
732 const MPoly *orig_mp = mim.input_mpoly_for_orig_index(
733 f->orig, &orig_me, &orig_me_index, &index_in_orig_me);
737 for (
int j : f->index_range()) {
738 const Vert *vf = f->vert[j];
739 const int vfi = im->lookup_vert(vf);
745 copy_poly_attributes(
result,
751 (mim.material_remaps.size() > 0) ?
752 mim.material_remaps[orig_me_index].as_span() :
754 copy_or_interp_loop_attributes(
result, f, mp, orig_mp, orig_me, orig_me_index, mim);
760 merge_edge_customdata_layers(
result, mim);
764 for (
int fi : im->face_index_range()) {
765 const Face *f = im->face(fi);
767 for (
int j : f->index_range()) {
768 if (f->edge_orig[j] != NO_INDEX) {
770 int index_in_orig_me;
771 const MEdge *orig_medge = mim.input_medge_for_orig_index(
772 f->edge_orig[j], &orig_me, &index_in_orig_me);
775 copy_edge_attributes(
result, medge, orig_medge, orig_me, e_index, index_in_orig_me);
793 const bool hole_tolerant,
794 const int boolean_mode,
799 BLI_assert(material_remaps.size() == 0 || material_remaps.size() == meshes.
size());
800 if (meshes.
size() <= 0) {
804 const int dbg_level = 0;
806 std::cout <<
"\nDIRECT_MESH_INTERSECT, nmeshes = " << meshes.
size() <<
"\n";
808 MeshesToIMeshInfo mim;
810 IMesh m_in = meshes_to_imesh(meshes, transforms, material_remaps, target_transform, arena, &mim);
811 std::function<int(
int)> shape_fn = [&mim](
int f) {
812 for (
int mi = 0; mi < mim.mesh_poly_offset.size() - 1; ++mi) {
813 if (f < mim.mesh_poly_offset[mi + 1]) {
817 return static_cast<int>(mim.mesh_poly_offset.size()) - 1;
819 IMesh m_out = boolean_mesh(m_in,
820 static_cast<BoolOpType
>(boolean_mode),
829 write_obj_mesh(m_out,
"m_out");
835 if (r_intersecting_edges !=
nullptr) {
836 for (
int fi : m_out.face_index_range()) {
837 const Face &face = *m_out.face(fi);
839 for (
int corner_i : face.index_range()) {
840 if (face.is_intersect[corner_i]) {
842 r_intersecting_edges->
append(e_index);
857 r_intersecting_edges);
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
bool CustomData_layer_has_interp(const struct CustomData *data, int layer_n)
void CustomData_bmesh_interp_n(struct CustomData *data, const void **src_blocks, const float *weights, const float *sub_weights, int count, void *dst_block_ofs, int n)
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
void CustomData_copy_data_layer(const CustomData *source, CustomData *dest, int src_layer_index, int dst_layer_index, int src_index, int dst_index, int count)
void * CustomData_get_n(const struct CustomData *data, int type, int index, int n)
int CustomData_get_named_layer(const struct CustomData *data, int type, const char *name)
const CustomData_MeshMasks CD_MASK_MESH
General operations, lookup, etc. for materials.
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
bool BKE_mesh_validate(struct Mesh *me, bool do_verbose, bool cddata_check_mask)
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_no[3])
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, bool select_new_edges)
#define BLI_array_alloca(arr, realsize)
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
void interp_weights_poly_v2(float w[], float v[][2], int n, const float co[2])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
MINLINE void copy_v3fl_v3db(float r[3], const double a[3])
Object is a sort of wrapper for general info.
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t size() const
void append(const T &value)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
Mesh * direct_mesh_boolean(Span< const Mesh * > meshes, Span< const float4x4 * > transforms, const float4x4 &target_transform, Span< Array< short >> material_remaps, bool use_self, bool hole_tolerant, int boolean_mode, Vector< int > *r_intersecting_edges)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
static float4x4 identity()