diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh index 52567befd3f..b6bb074437d 100644 --- a/source/blender/blenkernel/BKE_attribute_math.hh +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -9,7 +9,9 @@ #include "BLI_cpp_type.hh" #include "BLI_generic_span.hh" #include "BLI_generic_virtual_array.hh" +#include "BLI_math_axis_angle.hh" #include "BLI_math_color.hh" +#include "BLI_math_quaternion.hh" #include "BLI_math_vector.h" #include "BLI_math_vector.hh" @@ -31,7 +33,8 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func) bool, int8_t, ColorGeometry4f, - ColorGeometry4b>([&](auto type_tag) { + ColorGeometry4b, + math::Quaternion>([&](auto type_tag) { using T = typename decltype(type_tag)::type; if constexpr (std::is_same_v) { /* It's expected that the given cpp type is one of the supported ones. */ @@ -400,7 +403,10 @@ class BooleanPropagationMixer { * This mixer accumulates values in a type that is different from the one that is mixed. * Some types cannot encode the floating point weights in their values (e.g. int and bool). */ -template +template class SimpleMixerWithAccumulationType { private: struct Item { @@ -432,7 +438,7 @@ class SimpleMixerWithAccumulationType { void set(const int64_t index, const T &value, const float weight = 1.0f) { - const AccumulationT converted_value = static_cast(value); + const AccumulationT converted_value = ValueToAccumulate(value); Item &item = accumulation_buffer_[index]; item.value = converted_value * weight; item.weight = weight; @@ -440,7 +446,7 @@ class SimpleMixerWithAccumulationType { void mix_in(const int64_t index, const T &value, const float weight = 1.0f) { - const AccumulationT converted_value = static_cast(value); + const AccumulationT converted_value = ValueToAccumulate(value); Item &item = accumulation_buffer_[index]; item.value += converted_value * weight; item.weight += weight; @@ -457,7 +463,7 @@ class SimpleMixerWithAccumulationType { const Item &item = accumulation_buffer_[i]; if (item.weight > 0.0f) { const float weight_inv = 1.0f / item.weight; - const T converted_value = ConvertToT(item.value * weight_inv); + const T converted_value = AccumulateToValue(item.value * weight_inv); buffer_[i] = converted_value; } else { @@ -532,40 +538,68 @@ template<> struct DefaultMixerStruct { using type = ColorGeometry4bMixer; }; template<> struct DefaultMixerStruct { + static double int_to_double(const int &value) + { + return double(value); + } static int double_to_int(const double &value) { return int(std::round(value)); } /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It * uses double instead of float so that it is accurate for all 32 bit integers. */ - using type = SimpleMixerWithAccumulationType; + using type = SimpleMixerWithAccumulationType; }; template<> struct DefaultMixerStruct { + static double2 int_to_double(const int2 &value) + { + return double2(value); + } static int2 double_to_int(const double2 &value) { return int2(math::round(value)); } /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It * uses double instead of float so that it is accurate for all 32 bit integers. */ - using type = SimpleMixerWithAccumulationType; + using type = SimpleMixerWithAccumulationType; }; template<> struct DefaultMixerStruct { + static float bool_to_float(const bool &value) + { + return value ? 1.0f : 0.0f; + } static bool float_to_bool(const float &value) { return value >= 0.5f; } /* Store interpolated booleans in a float temporary. * Otherwise information provided by weights is easily rounded away. */ - using type = SimpleMixerWithAccumulationType; + using type = SimpleMixerWithAccumulationType; }; template<> struct DefaultMixerStruct { + static float int8_t_to_float(const int8_t &value) + { + return float(value); + } static int8_t float_to_int8_t(const float &value) { return int8_t(std::round(value)); } /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */ - using type = SimpleMixerWithAccumulationType; + using type = SimpleMixerWithAccumulationType; +}; +template<> struct DefaultMixerStruct { + static float3 quat_to_expmap(const math::Quaternion &value) + { + return value.expmap(); + } + static math::Quaternion expmap_to_quat(const float3 &value) + { + return math::Quaternion::expmap(value); + } + using type = + SimpleMixerWithAccumulationType; }; template struct DefaultPropagationMixerStruct { diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index bdbe1e0f28d..92333789f8c 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -107,11 +107,13 @@ static int attribute_data_type_complexity(const eCustomDataType data_type) return 6; case CD_PROP_BYTE_COLOR: return 7; - case CD_PROP_COLOR: + case CD_PROP_QUATERNION: return 8; + case CD_PROP_COLOR: + return 9; #if 0 /* These attribute types are not supported yet. */ case CD_PROP_STRING: - return 9; + return 10; #endif default: /* Only accept "generic" custom data types used by the attribute system. */ diff --git a/source/blender/blenkernel/intern/attribute_math.cc b/source/blender/blenkernel/intern/attribute_math.cc index ddbbd1df673..677ff85237a 100644 --- a/source/blender/blenkernel/intern/attribute_math.cc +++ b/source/blender/blenkernel/intern/attribute_math.cc @@ -3,11 +3,39 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_array_utils.hh" +#include "BLI_math_quaternion.hh" #include "BKE_attribute_math.hh" namespace blender::bke::attribute_math { +template<> +math::Quaternion mix2(const float factor, const math::Quaternion &a, const math::Quaternion &b) +{ + return math::interpolate(a, b, factor); +} + +template<> +math::Quaternion mix3(const float3 &weights, + const math::Quaternion &v0, + const math::Quaternion &v1, + const math::Quaternion &v2) +{ + const float3 expmap_mixed = mix3(weights, v0.expmap(), v1.expmap(), v2.expmap()); + return math::Quaternion::expmap(expmap_mixed); +} + +template<> +math::Quaternion mix4(const float4 &weights, + const math::Quaternion &v0, + const math::Quaternion &v1, + const math::Quaternion &v2, + const math::Quaternion &v3) +{ + const float3 expmap_mixed = mix4(weights, v0.expmap(), v1.expmap(), v2.expmap(), v3.expmap()); + return math::Quaternion::expmap(expmap_mixed); +} + ColorGeometry4fMixer::ColorGeometry4fMixer(MutableSpan buffer, ColorGeometry4f default_color) : ColorGeometry4fMixer(buffer, buffer.index_range(), default_color) diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 023cc428a90..1ed7d029a75 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -24,6 +24,7 @@ #include "BLI_index_range.hh" #include "BLI_math.h" #include "BLI_math_color_blend.h" +#include "BLI_math_quaternion_types.hh" #include "BLI_math_vector.hh" #include "BLI_mempool.h" #include "BLI_path_util.h" @@ -1933,6 +1934,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { nullptr}, /* 51: CD_HAIRLENGTH */ {sizeof(float), "float", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, + /* 52: CD_PROP_QUATERNION */ + {sizeof(float[4]), "vec4f", 1, N_("Quaternion"), nullptr, nullptr, nullptr, nullptr, nullptr}, }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -5354,6 +5357,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type) return &CPPType::get(); case CD_PROP_BYTE_COLOR: return &CPPType::get(); + case CD_PROP_QUATERNION: + return &CPPType::get(); case CD_PROP_STRING: return &CPPType::get(); default: @@ -5390,6 +5395,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type) if (type.is()) { return CD_PROP_BYTE_COLOR; } + if (type.is()) { + return CD_PROP_QUATERNION; + } if (type.is()) { return CD_PROP_STRING; } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 364dde9dadf..e55884261e2 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -661,6 +661,26 @@ static int customdata_compare( } break; } + case CD_PROP_QUATERNION: { + const float(*l1_data)[4] = (float(*)[4])l1->data; + const float(*l2_data)[4] = (float(*)[4])l2->data; + + for (int i = 0; i < total_length; i++) { + if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + if (compare_threshold_relative(l1_data[i][1], l2_data[i][1], thresh)) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + if (compare_threshold_relative(l1_data[i][2], l2_data[i][2], thresh)) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + if (compare_threshold_relative(l1_data[i][3], l2_data[i][3], thresh)) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } case CD_PROP_INT32: { const int *l1_data = (int *)l1->data; const int *l2_data = (int *)l2->data; diff --git a/source/blender/blenkernel/intern/simulation_state_serialize.cc b/source/blender/blenkernel/intern/simulation_state_serialize.cc index 3ffc2d13df7..8a5c78571e3 100644 --- a/source/blender/blenkernel/intern/simulation_state_serialize.cc +++ b/source/blender/blenkernel/intern/simulation_state_serialize.cc @@ -18,6 +18,7 @@ #include "BLI_endian_switch.h" #include "BLI_fileops.hh" #include "BLI_math_matrix_types.hh" +#include "BLI_math_quaternion_types.hh" #include "BLI_path_util.h" #include "RNA_access.h" @@ -778,6 +779,10 @@ static std::shared_ptr serialize_primitive_value( const ColorGeometry4f value = *static_cast(value_ptr); return serialize_float_array({&value.r, 4}); } + case CD_PROP_QUATERNION: { + const math::Quaternion value = *static_cast(value_ptr); + return serialize_float_array({&value.x, 4}); + } default: break; } @@ -966,6 +971,9 @@ template case CD_PROP_COLOR: { return deserialize_float_array(io_value, {static_cast(r_value), 4}); } + case CD_PROP_QUATERNION: { + return deserialize_float_array(io_value, {static_cast(r_value), 4}); + } default: break; } diff --git a/source/blender/blenlib/BLI_length_parameterize.hh b/source/blender/blenlib/BLI_length_parameterize.hh index 885737dfa97..e6c307e5100 100644 --- a/source/blender/blenlib/BLI_length_parameterize.hh +++ b/source/blender/blenlib/BLI_length_parameterize.hh @@ -11,6 +11,7 @@ #include "BLI_index_mask.hh" #include "BLI_math_base.hh" #include "BLI_math_color.hh" +#include "BLI_math_quaternion.hh" #include "BLI_math_vector.hh" namespace blender::length_parameterize { diff --git a/source/blender/blenlib/intern/cpp_types.cc b/source/blender/blenlib/intern/cpp_types.cc index 5fcd605c4bf..67e5ecc1402 100644 --- a/source/blender/blenlib/intern/cpp_types.cc +++ b/source/blender/blenlib/intern/cpp_types.cc @@ -6,6 +6,7 @@ #include "BLI_cpp_type_make.hh" #include "BLI_cpp_types_make.hh" #include "BLI_math_matrix_types.hh" +#include "BLI_math_quaternion_types.hh" #include "BLI_math_vector_types.hh" namespace blender { @@ -65,6 +66,8 @@ BLI_CPP_TYPE_MAKE(uint64_t, CPPTypeFlags::BasicType) BLI_CPP_TYPE_MAKE(blender::ColorGeometry4f, CPPTypeFlags::BasicType) BLI_CPP_TYPE_MAKE(blender::ColorGeometry4b, CPPTypeFlags::BasicType) +BLI_CPP_TYPE_MAKE(blender::math::Quaternion, CPPTypeFlags::BasicType) + BLI_CPP_TYPE_MAKE(std::string, CPPTypeFlags::BasicType) BLI_VECTOR_CPP_TYPE_MAKE(std::string) @@ -94,6 +97,8 @@ void register_cpp_types() BLI_CPP_TYPE_REGISTER(blender::ColorGeometry4f); BLI_CPP_TYPE_REGISTER(blender::ColorGeometry4b); + BLI_CPP_TYPE_REGISTER(math::Quaternion); + BLI_CPP_TYPE_REGISTER(std::string); BLI_VECTOR_CPP_TYPE_REGISTER(std::string); diff --git a/source/blender/draw/intern/draw_attributes.cc b/source/blender/draw/intern/draw_attributes.cc index 738e933360e..082d611dcb7 100644 --- a/source/blender/draw/intern/draw_attributes.cc +++ b/source/blender/draw/intern/draw_attributes.cc @@ -83,7 +83,7 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data, int *r_layer_index, eCustomDataType *r_type) { - const eCustomDataType possible_attribute_types[9] = { + const eCustomDataType possible_attribute_types[10] = { CD_PROP_BOOL, CD_PROP_INT8, CD_PROP_INT32_2D, @@ -92,6 +92,7 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data, CD_PROP_FLOAT2, CD_PROP_FLOAT3, CD_PROP_COLOR, + CD_PROP_QUATERNION, CD_PROP_BYTE_COLOR, }; diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index 9bce77454c7..e466029f8b6 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -392,6 +392,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, } case CD_PROP_BYTE_COLOR: case CD_PROP_COLOR: + case CD_PROP_QUATERNION: case CD_PROP_FLOAT3: case CD_PROP_BOOL: case CD_PROP_INT8: diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 4736b4f2bea..c170474412c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -107,6 +107,7 @@ static uint gpu_component_size_for_attribute_type(eCustomDataType type) return 3; case CD_PROP_COLOR: case CD_PROP_BYTE_COLOR: + case CD_PROP_QUATERNION: return 4; default: return 0; @@ -315,6 +316,7 @@ static void extract_attr(const MeshRenderData *mr, case CD_PROP_FLOAT3: extract_attr_generic(mr, vbo, request); break; + case CD_PROP_QUATERNION: case CD_PROP_COLOR: extract_attr_generic(mr, vbo, request); break; diff --git a/source/blender/editors/mesh/editmesh_attribute.cc b/source/blender/editors/mesh/editmesh_attribute.cc index 3a6e720c741..99cb2404fc0 100644 --- a/source/blender/editors/mesh/editmesh_attribute.cc +++ b/source/blender/editors/mesh/editmesh_attribute.cc @@ -8,6 +8,7 @@ #include "BLI_color.hh" #include "BLI_generic_pointer.hh" +#include "BLI_math_quaternion.hh" #include "BKE_attribute.h" #include "BKE_context.h" @@ -106,6 +107,8 @@ static StringRefNull rna_property_name_for_type(const eCustomDataType type) return "value_int"; case CD_PROP_INT32_2D: return "value_int_vector_2d"; + case CD_PROP_QUATERNION: + return "value_quat"; default: BLI_assert_unreachable(); return ""; @@ -198,6 +201,12 @@ static int mesh_set_attribute_exec(bContext *C, wmOperator *op) case CD_PROP_COLOR: RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast(buffer)); break; + case CD_PROP_QUATERNION: { + float4 value; + RNA_float_get_array(op->ptr, prop_name.c_str(), value); + *static_cast(buffer) = math::normalize(math::Quaternion(value)); + break; + } case CD_PROP_BYTE_COLOR: ColorGeometry4f value; RNA_float_get_array(op->ptr, prop_name.c_str(), value); @@ -330,6 +339,11 @@ static int mesh_set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent case CD_PROP_INT32_2D: RNA_property_int_set_array(op->ptr, prop, *active_value.get()); break; + case CD_PROP_QUATERNION: { + const math::Quaternion value = math::normalize(*active_value.get()); + RNA_property_float_set_array(op->ptr, prop, float4(value)); + break; + } default: BLI_assert_unreachable(); } @@ -408,6 +422,16 @@ void MESH_OT_attribute_set(wmOperatorType *ot) RNA_def_float_color( ot->srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f); RNA_def_boolean(ot->srna, "value_bool", false, "Value", ""); + RNA_def_float_array(ot->srna, + "value_quat", + 4, + rna_default_quaternion, + -FLT_MAX, + FLT_MAX, + "Value", + "", + FLT_MAX, + FLT_MAX); } /** \} */ diff --git a/source/blender/functions/intern/cpp_types.cc b/source/blender/functions/intern/cpp_types.cc index 3b8de055625..1473139fd7f 100644 --- a/source/blender/functions/intern/cpp_types.cc +++ b/source/blender/functions/intern/cpp_types.cc @@ -6,6 +6,7 @@ #include "BLI_cpp_type_make.hh" #include "BLI_cpp_types_make.hh" #include "BLI_math_matrix_types.hh" +#include "BLI_math_quaternion_types.hh" #include "BLI_math_vector_types.hh" #include "FN_field_cpp_type_make.hh" @@ -16,6 +17,7 @@ FN_FIELD_CPP_TYPE_MAKE(blender::float2); FN_FIELD_CPP_TYPE_MAKE(blender::float3); FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4f); FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4b); +FN_FIELD_CPP_TYPE_MAKE(blender::math::Quaternion); FN_FIELD_CPP_TYPE_MAKE(bool); FN_FIELD_CPP_TYPE_MAKE(int8_t); FN_FIELD_CPP_TYPE_MAKE(int32_t); @@ -31,6 +33,7 @@ void FN_register_cpp_types() FN_FIELD_CPP_TYPE_REGISTER(blender::float3); FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4f); FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4b); + FN_FIELD_CPP_TYPE_REGISTER(blender::math::Quaternion); FN_FIELD_CPP_TYPE_REGISTER(bool); FN_FIELD_CPP_TYPE_REGISTER(int8_t); FN_FIELD_CPP_TYPE_REGISTER(int32_t); diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 57d82413db6..677ae2ab6f1 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -84,8 +84,7 @@ typedef struct CustomData { * MUST be >= CD_NUMTYPES, but we can't use a define here. * Correct size is ensured in CustomData_update_typemap assert(). */ - int typemap[52]; - char _pad[4]; + int typemap[53]; /** Number of layers, size of layers array. */ int totlayer, maxlayer; /** In editmode, total size of all data layers. */ @@ -181,8 +180,9 @@ typedef enum eCustomDataType { CD_PROP_BOOL = 50, CD_HAIRLENGTH = 51, + CD_PROP_QUATERNION = 52, - CD_NUMTYPES = 52, + CD_NUMTYPES = 53, } eCustomDataType; /* Bits for eCustomDataMask */ @@ -224,6 +224,7 @@ typedef enum eCustomDataType { #define CD_MASK_PROP_BOOL (1ULL << CD_PROP_BOOL) #define CD_MASK_PROP_INT8 (1ULL << CD_PROP_INT8) #define CD_MASK_PROP_INT32_2D (1ULL << CD_PROP_INT32_2D) +#define CD_MASK_PROP_QUATERNION (1ULL << CD_PROP_QUATERNION) #define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH) @@ -237,7 +238,7 @@ typedef enum eCustomDataType { #define CD_MASK_PROP_ALL \ (CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | \ CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_PROP_BYTE_COLOR | CD_MASK_PROP_BOOL | \ - CD_MASK_PROP_INT8 | CD_MASK_PROP_INT32_2D) + CD_MASK_PROP_INT8 | CD_MASK_PROP_INT32_2D | CD_MASK_PROP_QUATERNION) /* All color attributes */ #define CD_MASK_COLOR_ALL (CD_MASK_PROP_COLOR | CD_MASK_PROP_BYTE_COLOR) diff --git a/source/blender/makesdna/DNA_vec_types.h b/source/blender/makesdna/DNA_vec_types.h index ff425b67fd9..d76a8c970cd 100644 --- a/source/blender/makesdna/DNA_vec_types.h +++ b/source/blender/makesdna/DNA_vec_types.h @@ -49,11 +49,11 @@ typedef struct vec3d { typedef struct vec4i { int x, y, z, w; } vec4i; - +*/ typedef struct vec4f { float x, y, z, w; } vec4f; - +/* typedef struct vec4d { double x, y, z, w; } vec4d; diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index 97221199076..a5920afb9b6 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -42,6 +42,7 @@ const EnumPropertyItem rna_enum_attribute_type_items[] = { {CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"}, {CD_PROP_INT8, "INT8", 0, "8-Bit Integer", "Smaller integer with a range from -128 to 127"}, {CD_PROP_INT32_2D, "INT32_2D", 0, "2D Integer Vector", "32-bit signed integer vector"}, + {CD_PROP_QUATERNION, "QUATERNION", 0, "Quaternion", "Floating point quaternion rotation"}, {0, NULL, 0, NULL, NULL}, }; @@ -70,6 +71,7 @@ const EnumPropertyItem rna_enum_attribute_type_with_auto_items[] = { {CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"}, {CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"}, {CD_PROP_INT32_2D, "INT32_2D", 0, "2D Integer Vector", "32-bit signed integer vector"}, + {CD_PROP_QUATERNION, "QUATERNION", 0, "Quaternion", "Floating point quaternion rotation"}, {0, NULL, 0, NULL, NULL}, }; @@ -168,6 +170,8 @@ static StructRNA *srna_by_custom_data_layer_type(const eCustomDataType type) return &RNA_ByteIntAttribute; case CD_PROP_INT32_2D: return &RNA_Int2Attribute; + case CD_PROP_QUATERNION: + return &RNA_QuaternionAttribute; default: return NULL; } @@ -301,6 +305,9 @@ static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRN case CD_PROP_INT32_2D: struct_size = sizeof(int[2]); break; + case CD_PROP_QUATERNION: + struct_size = sizeof(float[4]); + break; default: struct_size = 0; length = 0; @@ -1069,6 +1076,40 @@ static void rna_def_attribute_int2(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Attribute_update_data"); } +static void rna_def_attribute_quaternion(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "QuaternionAttribute", "Attribute"); + RNA_def_struct_sdna(srna, "CustomDataLayer"); + RNA_def_struct_ui_text(srna, "Quaternion Attribute", "Geometry attribute that stores rotation"); + + prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "QuaternionAttributeValue"); + RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); + RNA_def_property_collection_funcs(prop, + "rna_Attribute_data_begin", + "rna_iterator_array_next", + "rna_iterator_array_end", + "rna_iterator_array_get", + "rna_Attribute_data_length", + NULL, + NULL, + NULL); + + srna = RNA_def_struct(brna, "QuaternionAttributeValue", NULL); + RNA_def_struct_sdna(srna, "vec4f"); + RNA_def_struct_ui_text( + srna, "Quaternion Attribute Value", "Rotation value in geometry attribute"); + + prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Value", "Quaternion"); + RNA_def_property_float_sdna(prop, NULL, "x"); + RNA_def_property_array(prop, 4); + RNA_def_property_update(prop, 0, "rna_Attribute_update_data"); +} + static void rna_def_attribute_float2(BlenderRNA *brna) { StructRNA *srna; @@ -1149,6 +1190,7 @@ static void rna_def_attribute(BlenderRNA *brna) rna_def_attribute_byte_color(brna); rna_def_attribute_int(brna); rna_def_attribute_int2(brna); + rna_def_attribute_quaternion(brna); rna_def_attribute_string(brna); rna_def_attribute_bool(brna); rna_def_attribute_float2(brna);