37 if (mesh_ !=
nullptr) {
47 if (mesh_ !=
nullptr) {
57 return mesh_ !=
nullptr;
65 ownership_ = ownership;
93 return mesh_ ==
nullptr;
140 for (
const int i :
mask) {
141 const MEdge &edge = edges[i];
153 return mesh_component.
attributes()->adapt_domain(
182 const T value = old_values[loop_index];
205 if (!old_values[loop_index]) {
212 if (loose_verts[vert_index]) {
213 r_values[vert_index] =
false;
222 using T = decltype(dummy);
223 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
226 Array<T> values(mesh.totvert);
227 adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values);
228 new_varray = VArray<T>::ForContainer(std::move(values));
241 using T = decltype(dummy);
242 new_varray = VArray<T>::ForFunc(mesh.totloop,
243 [&mesh, varray = varray.typed<T>()](const int64_t loop_index) {
244 const int vertex_index = mesh.mloop[loop_index].v;
245 return varray[vertex_index];
255 using T = decltype(dummy);
256 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
257 if constexpr (std::is_same_v<T, bool>) {
258 new_varray = VArray<T>::ForFunc(
259 mesh.totpoly, [&mesh, varray = varray.typed<bool>()](const int face_index) {
261 const MPoly &poly = mesh.mpoly[face_index];
262 for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
263 if (!varray[loop_index]) {
271 new_varray = VArray<T>::ForFunc(
272 mesh.totpoly, [&mesh, varray = varray.typed<T>()](const int face_index) {
274 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
275 const MPoly &poly = mesh.mpoly[face_index];
276 for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
277 const T value = varray[loop_index];
278 mixer.mix_in(0, value);
302 const int next_i = (i + 1) % poly.
totloop;
304 const int next_loop_i = poly.
loopstart + next_i;
306 const int edge_index = loop.
e;
307 mixer.mix_in(edge_index, old_values[loop_i]);
308 mixer.mix_in(edge_index, old_values[next_loop_i]);
331 const int next_i = (i + 1) % poly.
totloop;
333 const int next_loop_i = poly.
loopstart + next_i;
335 const int edge_index = loop.
e;
337 loose_edges[edge_index] =
false;
339 if (!old_values[loop_i] || !old_values[next_loop_i]) {
340 r_values[edge_index] =
false;
347 for (const int edge_index : range) {
348 if (loose_edges[edge_index]) {
349 r_values[edge_index] = false;
359 using T = decltype(dummy);
360 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
361 Array<T> values(mesh.totedge);
362 adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values);
363 new_varray = VArray<T>::ForContainer(std::move(values));
379 const T value = old_values[poly_index];
398 r_values.
fill(
false);
401 if (old_values[poly_index]) {
404 const int vert_index = loop.
v;
405 r_values[vert_index] =
true;
415 using T = decltype(dummy);
416 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
417 Array<T> values(mesh.totvert);
418 adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values);
419 new_varray = VArray<T>::ForContainer(std::move(values));
434 for (const int poly_index : range) {
435 const MPoly &poly = mesh.mpoly[poly_index];
436 MutableSpan<T> poly_corner_values = r_values.slice(poly.loopstart, poly.totloop);
437 poly_corner_values.fill(old_values[poly_index]);
446 using T = decltype(dummy);
447 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
448 Array<T> values(mesh.totloop);
449 adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values);
450 new_varray = VArray<T>::ForContainer(std::move(values));
466 const T value = old_values[poly_index];
469 mixer.mix_in(loop.
e, value);
483 r_values.
fill(
false);
486 if (old_values[poly_index]) {
489 const int edge_index = loop.
e;
490 r_values[edge_index] =
true;
500 using T = decltype(dummy);
501 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
502 Array<T> values(mesh.totedge);
503 adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values);
504 new_varray = VArray<T>::ForContainer(std::move(values));
514 using T = decltype(dummy);
515 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
516 if constexpr (std::is_same_v<T, bool>) {
517 new_varray = VArray<T>::ForFunc(
518 mesh.totpoly, [&mesh, varray = varray.typed<bool>()](const int face_index) {
520 const MPoly &poly = mesh.mpoly[face_index];
521 for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
522 const MLoop &loop = mesh.mloop[loop_index];
523 if (!varray[loop.v]) {
531 new_varray = VArray<T>::ForFunc(
532 mesh.totpoly, [&mesh, varray = varray.typed<T>()](const int face_index) {
534 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
535 const MPoly &poly = mesh.mpoly[face_index];
536 for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
537 const MLoop &loop = mesh.mloop[loop_index];
538 const T value = varray[loop.v];
539 mixer.mix_in(0, value);
554 using T = decltype(dummy);
555 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
556 if constexpr (std::is_same_v<T, bool>) {
558 new_varray = VArray<bool>::ForFunc(
559 mesh.totedge, [&mesh, varray = varray.typed<bool>()](const int edge_index) {
560 const MEdge &edge = mesh.medge[edge_index];
561 return varray[edge.v1] && varray[edge.v2];
565 new_varray = VArray<T>::ForFunc(
566 mesh.totedge, [&mesh, varray = varray.typed<T>()](const int edge_index) {
568 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
569 const MEdge &edge = mesh.medge[edge_index];
570 mixer.mix_in(0, varray[edge.v1]);
571 mixer.mix_in(0, varray[edge.v2]);
594 const int loop_index_prev = loop_index - 1 + (loop_index == poly.
loopstart) * poly.
totloop;
597 mixer.mix_in(loop_index, old_values[loop.e]);
598 mixer.mix_in(loop_index, old_values[loop_prev.e]);
613 r_values.
fill(
false);
618 const int loop_index_prev = loop_index - 1 + (loop_index == poly.
loopstart) * poly.
totloop;
621 if (old_values[loop.e] && old_values[loop_prev.e]) {
622 r_values[loop_index] =
true;
632 using T = decltype(dummy);
633 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
634 Array<T> values(mesh.totloop);
635 adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values);
636 new_varray = VArray<T>::ForContainer(std::move(values));
652 const T value = old_values[edge_index];
653 mixer.mix_in(edge.v1, value);
654 mixer.mix_in(edge.v2, value);
668 r_values.
fill(
false);
671 if (old_values[edge_index]) {
672 r_values[edge.v1] =
true;
673 r_values[edge.v2] =
true;
682 using T = decltype(dummy);
683 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
684 Array<T> values(mesh.totvert);
685 adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values);
686 new_varray = VArray<T>::ForContainer(std::move(values));
696 using T = decltype(dummy);
697 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
698 if constexpr (std::is_same_v<T, bool>) {
700 new_varray = VArray<bool>::ForFunc(
701 mesh.totpoly, [&mesh, varray = varray.typed<T>()](const int face_index) {
702 const MPoly &poly = mesh.mpoly[face_index];
703 for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
704 const MLoop &loop = mesh.mloop[loop_index];
705 if (!varray[loop.e]) {
713 new_varray = VArray<T>::ForFunc(
714 mesh.totpoly, [&mesh, varray = varray.typed<T>()](const int face_index) {
716 attribute_math::DefaultMixer<T> mixer({&return_value, 1});
717 const MPoly &poly = mesh.mpoly[face_index];
718 for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
719 const MLoop &loop = mesh.mloop[loop_index];
720 const T value = varray[loop.e];
721 mixer.mix_in(0, value);
742 if (varray.
size() == 0) {
745 if (from_domain == to_domain) {
749 switch (from_domain) {
811 template<
typename StructT,
typename ElemT, ElemT (*GetFunc)(const StructT &)>
818 template<
typename StructT,
820 ElemT (*GetFunc)(
const StructT &),
821 void (*SetFunc)(StructT &, ElemT)>
841 if (
mesh !=
nullptr) {
848 return static_cast<int>(mpoly.
mat_nr);
878 return edge.crease / 255.0f;
889 const int dvert_index_;
899 if (dverts_ ==
nullptr) {
902 if (
const MDeformWeight *weight = this->find_weight_at_index(index)) {
903 return weight->weight;
912 if (
MDeformWeight *weight = this->find_weight_at_index(index)) {
913 weight->weight = 0.0f;
924 for (
const int64_t index :
src.index_range()) {
925 this->set(index,
src[index]);
931 if (dverts_ ==
nullptr) {
935 if (
const MDeformWeight *weight = this->find_weight_at_index(index)) {
936 r_span[index] = weight->weight;
939 r_span[index] = 0.0f;
946 this->materialize(
mask, r_span);
953 if (weight.def_nr == dvert_index_) {
961 for (
const MDeformWeight &weight :
Span(dverts_[index].dw, dverts_[index].totweight)) {
962 if (weight.def_nr == dvert_index_) {
978 if (!attribute_id.is_named()) {
982 if (
mesh ==
nullptr) {
985 const std::string name = attribute_id.
name();
988 if (vertex_group_index < 0) {
992 static const float default_value = 0.0f;
1002 if (!attribute_id.is_named()) {
1006 if (
mesh ==
nullptr) {
1010 const std::string name = attribute_id.
name();
1013 if (vertex_group_index < 0) {
1031 if (!attribute_id.is_named()) {
1035 if (
mesh ==
nullptr) {
1039 const std::string name = attribute_id.
name();
1060 if (weight.
def_nr > index) {
1071 if (
mesh ==
nullptr) {
1076 if (!
callback(group->name, {ATTR_DOMAIN_POINT, CD_PROP_FLOAT})) {
1137 static auto update_custom_data_pointers = [](
void *owner) {
1142 #define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME) \
1143 [](void *owner) -> CustomData * { \
1144 Mesh *mesh = static_cast<Mesh *>(owner); \
1145 return &mesh->NAME; \
1147 #define MAKE_CONST_CUSTOM_DATA_GETTER(NAME) \
1148 [](const void *owner) -> const CustomData * { \
1149 const Mesh *mesh = static_cast<const Mesh *>(owner); \
1150 return &mesh->NAME; \
1152 #define MAKE_GET_ELEMENT_NUM_GETTER(NAME) \
1153 [](const void *owner) -> int { \
1154 const Mesh *mesh = static_cast<const Mesh *>(owner); \
1155 return mesh->NAME; \
1161 update_custom_data_pointers};
1165 update_custom_data_pointers};
1169 update_custom_data_pointers};
1173 update_custom_data_pointers};
1175 #undef MAKE_CONST_CUSTOM_DATA_GETTER
1176 #undef MAKE_MUTABLE_CUSTOM_DATA_GETTER
1187 make_derived_read_attribute<MVert, float3, get_vertex_position>,
1188 make_derived_write_attribute<MVert, float3, get_vertex_position, set_vertex_position>,
1201 make_array_read_attribute<int>,
1202 make_array_write_attribute<int>,
1214 make_derived_read_attribute<MPoly, int, get_material_index>,
1215 make_derived_write_attribute<MPoly, int, get_material_index, set_material_index>,
1227 make_derived_read_attribute<MPoly, bool, get_shade_smooth>,
1228 make_derived_write_attribute<MPoly, bool, get_shade_smooth, set_shade_smooth>,
1240 make_derived_read_attribute<MEdge, float, get_crease>,
1241 make_derived_write_attribute<MEdge, float, get_crease, set_crease>,
1249 make_derived_read_attribute<MLoopUV, float2, get_loop_uv>,
1250 make_derived_write_attribute<MLoopUV, float2, get_loop_uv, set_loop_uv>);
1259 {&position, &
id, &material_index, &shade_smooth, &
normal, &crease},
1261 &corner_custom_data,
1265 &face_custom_data});
1272 attribute_accessor_functions::accessor_functions_for_providers<providers>();
1274 if (owner ==
nullptr) {
1298 if (owner ==
nullptr) {
typedef float(TangentPoint)[2]
void * CustomData_duplicate_referenced_layer(struct CustomData *data, int type, int totelem)
@ GEO_COMPONENT_TYPE_MESH
void BKE_id_free(struct Main *bmain, void *idv)
struct Mesh * BKE_mesh_copy_for_eval(const struct Mesh *source, bool reference)
const float(* BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
void BKE_mesh_update_customdata_pointers(struct Mesh *me, bool do_ensure_tess_cd)
void BKE_mesh_tag_coords_changed(struct Mesh *mesh)
#define LISTBASE_FOREACH(type, var, list)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE unsigned char round_fl_to_uchar_clamp(float a)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define SET_FLAG_FROM_TEST(value, test, flag)
Object is a sort of wrapper for general info.
std::optional< blender::bke::MutableAttributeAccessor > attributes_for_write() final
const Mesh * get_for_read() const
bool is_empty() const final
void replace(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
std::optional< blender::bke::AttributeAccessor > attributes() const final
GeometryComponent * copy() const override
bool owns_direct_data() const override
void ensure_owns_direct_data() override
const CPPType & type() const
constexpr int64_t size() const
constexpr void fill(const T &value)
constexpr void fill_indices(Span< int64_t > indices, const T &value)
static VArray ForContainer(ContainerT container)
static VArray ForSingle(T value, const int64_t size)
static VArray ForSpan(Span< T > values)
GAttributeWriter try_get_for_write(void *UNUSED(owner)) const final
GVArray try_get_for_read(const void *owner) const final
bool exists(const void *owner) const final
bool try_delete(void *UNUSED(owner)) const final
bool try_create(void *UNUSED(owner), const AttributeInit &UNUSED(initializer)) const final
NormalAttributeProvider()
void set_all(Span< float > src) override
float get(const int64_t index) const override
void set(const int64_t index, const float value) override
VArrayImpl_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
void materialize(IndexMask mask, MutableSpan< float > r_span) const override
void materialize_to_uninitialized(IndexMask mask, MutableSpan< float > r_span) const override
bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final
GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final
GAttributeReader try_get_for_read(const void *owner, const AttributeIDRef &attribute_id) const final
void foreach_domain(const FunctionRef< void(eAttrDomain)> callback) const final
bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final
DEGForeachIDComponentCallback callback
SyclQueue void void * src
#define MAKE_CONST_CUSTOM_DATA_GETTER(NAME)
MDeformVert * BKE_object_defgroup_data_create(ID *id)
#define MAKE_GET_ELEMENT_NUM_GETTER(NAME)
#define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME)
static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh, const blender::GVArray &varray, const eAttrDomain from_domain, const eAttrDomain to_domain)
IconTextureDrawCall normal
void(* MEM_freeN)(void *vmemh)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
typename DefaultMixerStruct< T >::type DefaultMixer
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
static AttributeAccessorFunctions get_mesh_accessor_functions()
static float3 get_vertex_position(const MVert &vert)
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
static void set_shade_smooth(MPoly &mpoly, bool value)
static GVArray make_derived_read_attribute(const void *data, const int domain_num)
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, const VArray< bool > &old_values, MutableSpan< bool > r_values)
static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray)
static float get_crease(const MEdge &edge)
void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh, const VArray< bool > &old_values, MutableSpan< bool > r_values)
static void set_crease(MEdge &edge, float value)
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
static void tag_component_positions_changed(void *owner)
void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, const VArray< bool > &old_values, MutableSpan< bool > r_values)
static void set_vertex_position(MVert &vert, float3 position)
static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
static GVMutableArray make_derived_write_attribute(void *data, const int domain_num)
static bool get_shade_smooth(const MPoly &mpoly)
static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, const VArray< bool > &old_values, MutableSpan< bool > 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)
static void set_loop_uv(MLoopUV &uv, float2 co)
static void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, const VArray< T > &old_values, MutableSpan< T > r_values)
static void set_material_index(MPoly &mpoly, int index)
VArray< float3 > mesh_normals_varray(const MeshComponent &mesh_component, const Mesh &mesh, const IndexMask mask, eAttrDomain domain)
static ComponentAttributeProviders create_attribute_providers_for_mesh()
static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
AttributeAccessor mesh_attributes(const Mesh &mesh)
void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, const VArray< bool > &old_values, MutableSpan< bool > r_values)
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 const AttributeAccessorFunctions & get_mesh_accessor_functions_ref()
static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
static float2 get_loop_uv(const MLoopUV &uv)
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
static int get_material_index(const MPoly &mpoly)
T clamp(const T &a, const T &min, const T &max)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
T interpolate(const T &a, const T &b, const FactorT &t)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
vec_base< float, 3 > float3
vec_base< float, 2 > float2
struct MDeformVert * dvert
ListBase vertex_group_names
bool(* domain_supported)(const void *owner, eAttrDomain domain)
GVArray(* adapt_domain)(const void *owner, const GVArray &varray, eAttrDomain from_domain, eAttrDomain to_domain)
int(* domain_size)(const void *owner, eAttrDomain domain)