35 for (const int64_t vert : range) {
36 const Span<int> vert_faces = vert_to_face_map[vert];
38 attribute_math::DefaultMixer<T> mixer({&r_dst[vert], 1});
39 for (const int face : vert_faces) {
40 const int corner = mesh::face_find_corner_from_vert(faces[face], corner_verts, int(vert));
41 mixer.mix_in(0, src[corner]);
59 for (const int corner : range) {
60 const int vert = corner_verts[corner];
68 const LooseVertCache &loose_verts = mesh.verts_no_face();
69 if (loose_verts.count > 0) {
72 for (const int vert_index : range) {
73 if (bits[vert_index]) {
74 r_dst[vert_index] = false;
85 using T = decltype(dummy);
86 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
89 adapt_mesh_domain_corner_to_point_impl<T>(
90 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
105 using T = decltype(dummy);
106 new_varray = VArray<T>::ForFunc(
107 mesh.corners_num, [corner_verts, varray = varray.typed<T>()](const int64_t corner) {
108 return varray[corner_verts[corner]];
120 using T = decltype(dummy);
121 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
122 if constexpr (std::is_same_v<T, bool>) {
123 new_varray = VArray<T>::ForFunc(
124 faces.size(), [faces, varray = varray.typed<bool>()](const int face_index) {
126 for (const int corner : faces[face_index]) {
127 if (!varray[corner]) {
135 new_varray = VArray<T>::ForFunc(
136 faces.size(), [faces, varray = varray.typed<T>()](const int face_index) {
138 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
139 for (const int corner : faces[face_index]) {
140 const T value = varray[corner];
141 mixer.mix_in(0, value);
163 for (
const int face_index :
faces.index_range()) {
167 for (
const int corner : face) {
169 const int edge_index = corner_edges[corner];
170 mixer.mix_in(edge_index, old_values[corner]);
171 mixer.mix_in(edge_index, old_values[next_corner]);
189 for (
const int face_index :
faces.index_range()) {
192 for (
const int corner : face) {
194 const int edge_index = corner_edges[corner];
195 if (!old_values[corner] || !old_values[next_corner]) {
196 r_values[edge_index] =
false;
202 if (loose_edges.
count > 0) {
205 for (const int edge_index : range) {
206 if (loose_edges.is_loose_bits[edge_index]) {
207 r_values[edge_index] = false;
218 using T = decltype(dummy);
219 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
220 adapt_mesh_domain_corner_to_edge_impl<T>(
221 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
236 for (const int vert : range) {
237 attribute_math::DefaultMixer<T> mixer({&r_dst[vert], 1});
238 for (const int face : vert_to_face_map[vert]) {
239 mixer.mix_in(0, src[face]);
256 for (const int vert : range) {
257 const Span<int> vert_faces = vert_to_face_map[vert];
258 r_dst[vert] = std::any_of(
259 vert_faces.begin(), vert_faces.end(), [&](const int face) { return src[face]; });
268 using T = decltype(dummy);
269 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
270 adapt_mesh_domain_face_to_point_impl<T>(
271 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
287 for (const int face_index : range) {
288 MutableSpan<T> face_corner_values = r_values.slice(faces[face_index]);
289 face_corner_values.fill(old_values[face_index]);
298 using T = decltype(dummy);
299 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
300 adapt_mesh_domain_face_to_corner_impl<T>(
301 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
318 for (
const int face_index :
faces.index_range()) {
319 const T value = old_values[face_index];
320 for (
const int edge : corner_edges.
slice(
faces[face_index])) {
321 mixer.mix_in(edge, value);
337 r_values.
fill(
false);
339 for (const int face_index : range) {
340 if (old_values[face_index]) {
341 for (const int edge : corner_edges.slice(faces[face_index])) {
342 r_values[edge] = true;
353 using T = decltype(dummy);
354 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
355 adapt_mesh_domain_face_to_edge_impl<T>(
356 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
369 using T = decltype(dummy);
370 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
371 if constexpr (std::is_same_v<T, bool>) {
372 new_varray = VArray<T>::ForFunc(
374 [corner_verts, faces, varray = varray.typed<bool>()](const int face_index) {
376 for (const int vert : corner_verts.slice(faces[face_index])) {
385 new_varray = VArray<T>::ForFunc(
387 [corner_verts, faces, varray = varray.typed<T>()](const int face_index) {
389 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
390 for (const int vert : corner_verts.slice(faces[face_index])) {
391 mixer.mix_in(0, varray[vert]);
408 using T = decltype(dummy);
409 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
410 if constexpr (std::is_same_v<T, bool>) {
412 new_varray = VArray<bool>::ForFunc(
413 edges.size(), [edges, varray = varray.typed<bool>()](const int edge_index) {
414 const int2 &edge = edges[edge_index];
415 return varray[edge[0]] && varray[edge[1]];
419 new_varray = VArray<T>::ForFunc(
420 edges.size(), [edges, varray = varray.typed<T>()](const int edge_index) {
421 const int2 &edge = edges[edge_index];
422 return attribute_math::mix2(0.5f, varray[edge[0]], varray[edge[1]]);
441 for (
const int face_index :
faces.index_range()) {
445 for (
const int corner : face) {
447 const int edge = corner_edges[corner];
448 const int edge_prev = corner_edges[corner_prev];
449 mixer.mix_in(corner, old_values[edge]);
450 mixer.mix_in(corner, old_values[edge_prev]);
467 r_values.
fill(
false);
470 for (const int face_index : range) {
471 const IndexRange face = faces[face_index];
472 for (const int corner : face) {
473 const int corner_prev = mesh::face_corner_prev(face, corner);
474 const int edge = corner_edges[corner];
475 const int edge_prev = corner_edges[corner_prev];
476 if (old_values[edge] && old_values[edge_prev]) {
477 r_values[corner] = true;
488 using T = decltype(dummy);
489 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
490 adapt_mesh_domain_edge_to_corner_impl<T>(
491 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
508 const int2 &edge = edges[edge_index];
509 const T value = old_values[edge_index];
510 mixer.mix_in(edge[0], value);
511 mixer.mix_in(edge[1], value);
528 r_values.
fill(
false);
530 for (const int edge_index : range) {
531 if (old_values[edge_index]) {
532 const int2 &edge = edges[edge_index];
533 r_values[edge[0]] = true;
534 r_values[edge[1]] = true;
544 using T = decltype(dummy);
545 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
546 adapt_mesh_domain_edge_to_point_impl<T>(
547 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
560 using T = decltype(dummy);
561 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
562 if constexpr (std::is_same_v<T, bool>) {
564 new_varray = VArray<bool>::ForFunc(
565 faces.size(), [corner_edges, faces, varray = varray.typed<T>()](const int face_index) {
566 for (const int edge : corner_edges.slice(faces[face_index])) {
575 new_varray = VArray<T>::ForFunc(
576 faces.size(), [corner_edges, faces, varray = varray.typed<T>()](const int face_index) {
578 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
579 for (const int edge : corner_edges.slice(faces[face_index])) {
580 mixer.mix_in(0, varray[edge]);
598 switch (from_domain) {
604 return mesh.loose_verts().count == 0;
609 return mesh.verts_no_face().count == 0;
612 return mesh.loose_edges().count == 0;
617 return mesh.verts_no_face().count == 0;
620 return mesh.loose_edges().count == 0;
640 if (from_domain == to_domain) {
651 switch (from_domain) {
714 if (
mesh !=
nullptr) {
715 mesh->tag_positions_changed();
722 mesh->tag_sharpness_changed();
729 mesh->tag_material_index_changed();
741 if (
mesh ==
nullptr) {
746 if (vertex_group_index < 0) {
755 const int vertex_group_index)
const
767 if (
mesh ==
nullptr) {
773 if (vertex_group_index < 0) {
783 if (
mesh ==
nullptr) {
794 if (
mesh->deform_verts().is_empty()) {
807 if (
mesh ==
nullptr) {
815 const auto get_fn = [&]() {
837 return [owner]() { (
static_cast<Mesh *
>(owner))->tag_visibility_changed(); };
839 if (name ==
"custom_normal") {
840 return [owner]() { (
static_cast<Mesh *
>(owner))->tag_custom_normals_changed(); };
851#define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME) \
852 [](void *owner) -> CustomData * { \
853 Mesh *mesh = static_cast<Mesh *>(owner); \
854 return &mesh->NAME; \
856#define MAKE_CONST_CUSTOM_DATA_GETTER(NAME) \
857 [](const void *owner) -> const CustomData * { \
858 const Mesh *mesh = static_cast<const Mesh *>(owner); \
859 return &mesh->NAME; \
861#define MAKE_GET_ELEMENT_NUM_GETTER(NAME) \
862 [](const void *owner) -> int { \
863 const Mesh *mesh = static_cast<const Mesh *>(owner); \
884#undef MAKE_CONST_CUSTOM_DATA_GETTER
885#undef MAKE_MUTABLE_CUSTOM_DATA_GETTER
901 static const auto material_index_clamp = mf::build::SI1_SO<int, int>(
902 "Material Index Validate",
905 return std::clamp<int>(value, 0, std::numeric_limits<short>::max());
907 mf::build::exec_presets::AllSpanOrSingle());
916 static const auto int2_index_clamp = mf::build::SI1_SO<int2, int2>(
919 mf::build::exec_presets::AllSpanOrSingle());
930 static const auto int_index_clamp = mf::build::SI1_SO<int, int>(
932 [](
int value) {
return std::max(value, 0); },
933 mf::build::exec_presets::AllSpanOrSingle());
977 {&corner_custom_data,
989 fn.domain_size = [](
const void *owner,
const AttrDomain domain) {
990 if (owner ==
nullptr) {
996 return mesh.verts_num;
998 return mesh.edges_num;
1000 return mesh.faces_num;
1002 return mesh.corners_num;
1007 fn.domain_supported = [](
const void * ,
const AttrDomain domain) {
1010 fn.adapt_domain = [](
const void *owner,
1014 if (owner ==
nullptr) {
#define BLI_assert_unreachable()
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Object is a sort of wrapper for general info.
static VArray ForSingle(T value, const int64_t size)
const CPPType & type() const
void get_internal_single(void *r_value) const
static GVArray ForGArray(GArray<> array)
static GVArray ForSingle(const CPPType &type, int64_t size, const void *value)
constexpr int64_t size() const
constexpr void fill(const T &value) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
constexpr bool startswith(StringRef prefix) const
GAttributeReader get_for_vertex_group_index(const Mesh &mesh, const Span< MDeformVert > dverts, const int vertex_group_index) const
GAttributeReader try_get_for_read(const void *owner, const StringRef attribute_id) const final
bool foreach_attribute(const void *owner, const FunctionRef< void(const AttributeIter &)> fn) const final
void foreach_domain(const FunctionRef< void(AttrDomain)> callback) const final
GAttributeWriter try_get_for_write(void *owner, const StringRef attribute_id) const final
bool try_delete(void *owner, const StringRef name) const final
void MEM_freeN(void *vmemh)
#define MAKE_CONST_CUSTOM_DATA_GETTER(NAME)
#define MAKE_GET_ELEMENT_NUM_GETTER(NAME)
#define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME)
AttributeAccessorFunctions accessor_functions_for_providers()
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
typename DefaultMixerStruct< T >::type DefaultMixer
int face_corner_prev(const IndexRange face, const int corner)
int face_corner_next(const IndexRange face, const int corner)
static std::function< void()> get_tag_modified_function(void *owner, const StringRef name)
static AttributeAccessorFunctions get_mesh_accessor_functions()
static void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, const VArray< T > &src, MutableSpan< T > r_dst)
static bool can_simple_adapt_for_single(const Mesh &mesh, const AttrDomain from_domain, const AttrDomain to_domain)
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
const AttributeAccessorFunctions & mesh_attribute_accessor_functions()
static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray)
static void tag_component_sharpness_changed(void *owner)
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
static void tag_component_positions_changed(void *owner)
static void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, const VArray< T > &src, MutableSpan< T > r_dst)
void remove_defgroup_index(MutableSpan< MDeformVert > dverts, int defgroup_index)
static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
static GeometryAttributeProviders create_attribute_providers_for_mesh()
static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
static void tag_material_index_changed(void *owner)
static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray)
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
static GVArray adapt_mesh_attribute_domain(const Mesh &mesh, const GVArray &varray, const AttrDomain from_domain, const AttrDomain to_domain)
static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray)
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
VMutableArray< float > varray_for_mutable_deform_verts(MutableSpan< MDeformVert > dverts, int defgroup_index)
VArray< float > varray_for_deform_verts(Span< MDeformVert > dverts, int defgroup_index)
T max(const T &a, const T &b)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< int32_t, 2 > int2
IndexRange index_range() const