44 if (mesh_ !=
nullptr) {
54 if (mesh_ !=
nullptr) {
64 return mesh_ !=
nullptr;
72 ownership_ = ownership;
100 return mesh_ ==
nullptr;
122 mesh_->count_memory(memory);
151 mask.foreach_index([&](
const int i) {
152 const int2 &edge = edges[i];
164 return mesh.attributes().adapt_domain(
188 mixer.mix_in(corner_verts[corner], old_values[corner]);
204 const int point_index = corner_verts[corner];
206 if (!old_values[corner]) {
207 r_values[point_index] =
false;
213 if (loose_verts.
count > 0) {
216 for (const int vert_index : range) {
217 if (bits[vert_index]) {
218 r_values[vert_index] = false;
229 using T = decltype(dummy);
230 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
233 adapt_mesh_domain_corner_to_point_impl<T>(
234 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
249 using T = decltype(dummy);
250 new_varray = VArray<T>::ForFunc(
251 mesh.corners_num, [corner_verts, varray = varray.typed<T>()](const int64_t corner) {
252 return varray[corner_verts[corner]];
264 using T = decltype(dummy);
265 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
266 if constexpr (std::is_same_v<T, bool>) {
267 new_varray = VArray<T>::ForFunc(
268 faces.size(), [faces, varray = varray.typed<bool>()](const int face_index) {
270 for (const int loop_index : faces[face_index]) {
271 if (!varray[loop_index]) {
279 new_varray = VArray<T>::ForFunc(
280 faces.size(), [faces, varray = varray.typed<T>()](const int face_index) {
282 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
283 for (const int loop_index : faces[face_index]) {
284 const T value = varray[loop_index];
285 mixer.mix_in(0, value);
307 for (
const int face_index :
faces.index_range()) {
311 for (
const int corner : face) {
313 const int edge_index = corner_edges[corner];
314 mixer.mix_in(edge_index, old_values[corner]);
315 mixer.mix_in(edge_index, old_values[next_corner]);
333 for (
const int face_index :
faces.index_range()) {
336 for (
const int corner : face) {
338 const int edge_index = corner_edges[corner];
339 if (!old_values[corner] || !old_values[next_corner]) {
340 r_values[edge_index] =
false;
346 if (loose_edges.
count > 0) {
349 for (const int edge_index : range) {
350 if (loose_edges.is_loose_bits[edge_index]) {
351 r_values[edge_index] = false;
362 using T = decltype(dummy);
363 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
364 adapt_mesh_domain_corner_to_edge_impl<T>(
365 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
382 for (
const int face_index :
faces.index_range()) {
383 const T value = old_values[face_index];
384 for (
const int vert : corner_verts.
slice(
faces[face_index])) {
385 mixer.mix_in(vert, value);
402 r_values.
fill(
false);
404 for (const int face_index : range) {
405 if (old_values[face_index]) {
406 for (const int vert : corner_verts.slice(faces[face_index])) {
407 r_values[vert] = true;
418 using T = decltype(dummy);
419 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
420 adapt_mesh_domain_face_to_point_impl<T>(
421 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
437 for (const int face_index : range) {
438 MutableSpan<T> face_corner_values = r_values.slice(faces[face_index]);
439 face_corner_values.fill(old_values[face_index]);
448 using T = decltype(dummy);
449 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
450 adapt_mesh_domain_face_to_corner_impl<T>(
451 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
468 for (
const int face_index :
faces.index_range()) {
469 const T value = old_values[face_index];
470 for (
const int edge : corner_edges.
slice(
faces[face_index])) {
471 mixer.mix_in(edge, value);
487 r_values.
fill(
false);
489 for (const int face_index : range) {
490 if (old_values[face_index]) {
491 for (const int edge : corner_edges.slice(faces[face_index])) {
492 r_values[edge] = true;
503 using T = decltype(dummy);
504 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
505 adapt_mesh_domain_face_to_edge_impl<T>(
506 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
519 using T = decltype(dummy);
520 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
521 if constexpr (std::is_same_v<T, bool>) {
522 new_varray = VArray<T>::ForFunc(
524 [corner_verts, faces, varray = varray.typed<bool>()](const int face_index) {
526 for (const int vert : corner_verts.slice(faces[face_index])) {
535 new_varray = VArray<T>::ForFunc(
537 [corner_verts, faces, varray = varray.typed<T>()](const int face_index) {
539 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
540 for (const int vert : corner_verts.slice(faces[face_index])) {
541 mixer.mix_in(0, varray[vert]);
558 using T = decltype(dummy);
559 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
560 if constexpr (std::is_same_v<T, bool>) {
562 new_varray = VArray<bool>::ForFunc(
563 edges.size(), [edges, varray = varray.typed<bool>()](const int edge_index) {
564 const int2 &edge = edges[edge_index];
565 return varray[edge[0]] && varray[edge[1]];
569 new_varray = VArray<T>::ForFunc(
570 edges.size(), [edges, varray = varray.typed<T>()](const int edge_index) {
572 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
573 const int2 &edge = edges[edge_index];
574 mixer.mix_in(0, varray[edge[0]]);
575 mixer.mix_in(0, varray[edge[1]]);
596 for (
const int face_index :
faces.index_range()) {
600 for (
const int loop_index : face) {
602 const int edge = corner_edges[loop_index];
603 const int edge_prev = corner_edges[loop_index_prev];
604 mixer.mix_in(loop_index, old_values[edge]);
605 mixer.mix_in(loop_index, old_values[edge_prev]);
622 r_values.
fill(
false);
625 for (const int face_index : range) {
626 const IndexRange face = faces[face_index];
627 for (const int loop_index : face) {
628 const int loop_index_prev = mesh::face_corner_prev(face, loop_index);
629 const int edge = corner_edges[loop_index];
630 const int edge_prev = corner_edges[loop_index_prev];
631 if (old_values[edge] && old_values[edge_prev]) {
632 r_values[loop_index] = true;
643 using T = decltype(dummy);
644 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
645 adapt_mesh_domain_edge_to_corner_impl<T>(
646 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
663 const int2 &edge = edges[edge_index];
664 const T value = old_values[edge_index];
665 mixer.mix_in(edge[0], value);
666 mixer.mix_in(edge[1], value);
683 r_values.
fill(
false);
685 for (const int edge_index : range) {
686 if (old_values[edge_index]) {
687 const int2 &edge = edges[edge_index];
688 r_values[edge[0]] = true;
689 r_values[edge[1]] = true;
699 using T = decltype(dummy);
700 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
701 adapt_mesh_domain_edge_to_point_impl<T>(
702 mesh, varray.typed<T>(), values.as_mutable_span().typed<T>());
715 using T = decltype(dummy);
716 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
717 if constexpr (std::is_same_v<T, bool>) {
719 new_varray = VArray<bool>::ForFunc(
720 faces.size(), [corner_edges, faces, varray = varray.typed<T>()](const int face_index) {
721 for (const int edge : corner_edges.slice(faces[face_index])) {
730 new_varray = VArray<T>::ForFunc(
731 faces.size(), [corner_edges, faces, varray = varray.typed<T>()](const int face_index) {
733 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
734 for (const int edge : corner_edges.slice(faces[face_index])) {
735 mixer.mix_in(0, varray[edge]);
753 switch (from_domain) {
759 return mesh.loose_verts().count == 0;
764 return mesh.verts_no_face().count == 0;
767 return mesh.loose_edges().count == 0;
772 return mesh.verts_no_face().count == 0;
775 return mesh.loose_edges().count == 0;
795 if (from_domain == to_domain) {
806 switch (from_domain) {
869 if (
mesh !=
nullptr) {
870 mesh->tag_positions_changed();
877 mesh->tag_sharpness_changed();
892 if (
mesh ==
nullptr) {
897 if (vertex_group_index < 0) {
906 const int vertex_group_index)
const
921 if (
mesh ==
nullptr) {
927 if (vertex_group_index < 0) {
940 if (
mesh ==
nullptr) {
944 const std::string name = attribute_id;
953 if (
mesh->deform_verts().is_empty()) {
966 if (
mesh ==
nullptr) {
974 const auto get_fn = [&]() {
999#define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME) \
1000 [](void *owner) -> CustomData * { \
1001 Mesh *mesh = static_cast<Mesh *>(owner); \
1002 return &mesh->NAME; \
1004#define MAKE_CONST_CUSTOM_DATA_GETTER(NAME) \
1005 [](const void *owner) -> const CustomData * { \
1006 const Mesh *mesh = static_cast<const Mesh *>(owner); \
1007 return &mesh->NAME; \
1009#define MAKE_GET_ELEMENT_NUM_GETTER(NAME) \
1010 [](const void *owner) -> int { \
1011 const Mesh *mesh = static_cast<const Mesh *>(owner); \
1012 return mesh->NAME; \
1028#undef MAKE_CONST_CUSTOM_DATA_GETTER
1029#undef MAKE_MUTABLE_CUSTOM_DATA_GETTER
1045 static const auto material_index_clamp = mf::build::SI1_SO<int, int>(
1046 "Material Index Validate",
1049 return std::clamp<int>(value, 0, std::numeric_limits<short>::max());
1051 mf::build::exec_presets::AllSpanOrSingle());
1060 static const auto int2_index_clamp = mf::build::SI1_SO<int2, int2>(
1063 mf::build::exec_presets::AllSpanOrSingle());
1074 static const auto int_index_clamp = mf::build::SI1_SO<int, int>(
1076 [](
int value) {
return std::max(value, 0); },
1077 mf::build::exec_presets::AllSpanOrSingle());
1121 {&corner_custom_data,
1125 &face_custom_data});
1133 fn.domain_size = [](
const void *owner,
const AttrDomain domain) {
1134 if (owner ==
nullptr) {
1140 return mesh.verts_num;
1142 return mesh.edges_num;
1144 return mesh.faces_num;
1146 return mesh.corners_num;
1151 fn.domain_supported = [](
const void * ,
const AttrDomain domain) {
1154 fn.adapt_domain = [](
const void *owner,
1158 if (owner ==
nullptr) {
1180blender::bke::MutableAttributeAccessor Mesh::attributes_for_write()
1182 return blender::bke::MutableAttributeAccessor(
this,
1186namespace blender::bke {
void BKE_id_free(Main *bmain, void *idv)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
#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(struct 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
static VArray ForContainer(ContainerT container)
static VArray ForSpan(Span< T > values)
GeometryComponent(Type type)
void ensure_owns_direct_data() override
bool is_empty() const final
void replace(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GeometryComponentPtr copy() const override
bool owns_direct_data() const override
void count_memory(MemoryCounter &memory) const override
std::optional< AttributeAccessor > attributes() const final
std::optional< MutableAttributeAccessor > attributes_for_write() final
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 attribute_id) const final
#define MAKE_CONST_CUSTOM_DATA_GETTER(NAME)
#define MAKE_GET_ELEMENT_NUM_GETTER(NAME)
#define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME)
void MEM_freeN(void *vmemh)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
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)
bool attribute_name_is_anonymous(const StringRef name)
void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
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)
ImplicitSharingPtr< GeometryComponent > GeometryComponentPtr
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)
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)
void remove_defgroup_index(MutableSpan< MDeformVert > dverts, int defgroup_index)
static const AttributeAccessorFunctions & get_mesh_accessor_functions_ref()
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 GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
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 void adapt_mesh_domain_corner_to_point_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)
VArray< float3 > mesh_normals_varray(const Mesh &mesh, const IndexMask &mask, AttrDomain domain)
static ComponentAttributeProviders create_attribute_providers_for_mesh()
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 interpolate(const T &a, const T &b, const FactorT &t)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
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
blender::BitVector is_loose_bits