Attributes: Add quaternion rotation type #108678

Merged
Hans Goudey merged 10 commits from HooglyBoogly/blender:attributes-quaternion-type into main 2023-06-12 15:49:57 +02:00
16 changed files with 198 additions and 18 deletions

View File

@ -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<T, void>) {
/* 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<typename T, typename AccumulationT, T (*ConvertToT)(const AccumulationT &value)>
template<typename T,
typename AccumulationT,
AccumulationT (*ValueToAccumulate)(const T &value),
T (*AccumulateToValue)(const AccumulationT &value)>
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<AccumulationT>(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<AccumulationT>(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<ColorGeometry4b> {
using type = ColorGeometry4bMixer;
};
template<> struct DefaultMixerStruct<int> {
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<int, double, double_to_int>;
using type = SimpleMixerWithAccumulationType<int, double, int_to_double, double_to_int>;
};
template<> struct DefaultMixerStruct<int2> {
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<int2, double2, double_to_int>;
using type = SimpleMixerWithAccumulationType<int2, double2, int_to_double, double_to_int>;
};
template<> struct DefaultMixerStruct<bool> {
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<bool, float, float_to_bool>;
using type = SimpleMixerWithAccumulationType<bool, float, bool_to_float, float_to_bool>;
};
template<> struct DefaultMixerStruct<int8_t> {
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<int8_t, float, float_to_int8_t>;
using type = SimpleMixerWithAccumulationType<int8_t, float, int8_t_to_float, float_to_int8_t>;
};
template<> struct DefaultMixerStruct<math::Quaternion> {
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<math::Quaternion, float3, quat_to_expmap, expmap_to_quat>;
};
template<typename T> struct DefaultPropagationMixerStruct {

View File

@ -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. */

View File

@ -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<ColorGeometry4f> buffer,
ColorGeometry4f default_color)
: ColorGeometry4fMixer(buffer, buffer.index_range(), default_color)

View File

@ -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<int8_t>();
case CD_PROP_BYTE_COLOR:
return &CPPType::get<ColorGeometry4b>();
case CD_PROP_QUATERNION:
return &CPPType::get<math::Quaternion>();
case CD_PROP_STRING:
return &CPPType::get<MStringProperty>();
default:
@ -5390,6 +5395,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
if (type.is<ColorGeometry4b>()) {
return CD_PROP_BYTE_COLOR;
}
if (type.is<math::Quaternion>()) {
return CD_PROP_QUATERNION;
}
if (type.is<MStringProperty>()) {
return CD_PROP_STRING;
}

View File

@ -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;

View File

@ -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<io::serialize::Value> serialize_primitive_value(
const ColorGeometry4f value = *static_cast<const ColorGeometry4f *>(value_ptr);
return serialize_float_array({&value.r, 4});
}
case CD_PROP_QUATERNION: {
const math::Quaternion value = *static_cast<const math::Quaternion *>(value_ptr);
return serialize_float_array({&value.x, 4});
}
default:
break;
}
@ -966,6 +971,9 @@ template<typename T>
case CD_PROP_COLOR: {
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4});
}
case CD_PROP_QUATERNION: {
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4});
}
default:
break;
}

View File

@ -11,6 +11,7 @@
#include "BLI_index_mask.hh"
#include "BLI_math_base.hh"
#include "BLI_math_color.hh"
#include "BLI_math_quaternion.hh"
Review

Why this include?

Why this include?
Review

Currently that's the best way I found to solve this build error. But I don't fully understand why isn't necessary. I thought I'd just be able to include it in resample_curves.cc, rather than the header. It's the same reason that BLI_math_color.hh is there though.

/home/hans/blender-git/blender/source/blender/blenkernel/BKE_attribute_math.hh:37:48:   required from ‘void blender::bke::attribute_math::convert_to_static_type(const blender::CPPType&, const Func&) [with Func = blender::geometry::resample_to_uniform(const blender::bke::CurvesGeometry&, const blender::fn::Field<bool>&, const blender::fn::Field<int>&, const ResampleCurvesOutputAttributeIDs&)::<lambda(blender::index_mask::IndexMaskSegment)>::<lambda(auto:173)>]’
/home/hans/blender-git/blender/source/blender/geometry/intern/resample_curves.cc:324:50:   required from here
/home/hans/blender-git/blender/source/blender/blenlib/BLI_math_base.hh:208:29: error: no match for ‘operator+’ (operand types are ‘blender::math::QuaternionBase<float>’ and ‘blender::math::QuaternionBase<float>’)
  208 |   auto result = a * (1 - t) + b * t;
      |                 ~~~~~~~~~~~~^~~~~~~
In file included from /home/hans/blender-git/blender/source/blender/blenlib/BLI_linear_allocator.hh:15,
                 from /home/hans/blender-git/blender/source/blender/blenlib/BLI_index_mask.hh:13,
                 from /home/hans/blender-git/blender/source/blender/blenlib/BLI_length_parameterize.hh:11:
/home/hans/blender-git/blender/source/blender/blenlib/BLI_string_ref.hh:590:20: note: candidate: ‘std::string blender::operator+(StringRef, StringRef)’
  590 | inline std::string operator+(StringRef a, StringRef b)
      |                    ^~~~~~~~
/home/hans/blender-git/blender/source/blender/blenlib/BLI_string_ref.hh:590:40: note:   no known conversion for argument 1 from ‘blender::math::QuaternionBase<float>’ to ‘blender::StringRef’
  590 | inline std::string operator+(StringRef a, StringRef b)
      |                              ~~~~~~~~~~^
Currently that's the best way I found to solve this build error. But I don't fully understand why isn't necessary. I thought I'd just be able to include it in `resample_curves.cc`, rather than the header. It's the same reason that `BLI_math_color.hh` is there though. ``` /home/hans/blender-git/blender/source/blender/blenkernel/BKE_attribute_math.hh:37:48: required from ‘void blender::bke::attribute_math::convert_to_static_type(const blender::CPPType&, const Func&) [with Func = blender::geometry::resample_to_uniform(const blender::bke::CurvesGeometry&, const blender::fn::Field<bool>&, const blender::fn::Field<int>&, const ResampleCurvesOutputAttributeIDs&)::<lambda(blender::index_mask::IndexMaskSegment)>::<lambda(auto:173)>]’ /home/hans/blender-git/blender/source/blender/geometry/intern/resample_curves.cc:324:50: required from here /home/hans/blender-git/blender/source/blender/blenlib/BLI_math_base.hh:208:29: error: no match for ‘operator+’ (operand types are ‘blender::math::QuaternionBase<float>’ and ‘blender::math::QuaternionBase<float>’) 208 | auto result = a * (1 - t) + b * t; | ~~~~~~~~~~~~^~~~~~~ In file included from /home/hans/blender-git/blender/source/blender/blenlib/BLI_linear_allocator.hh:15, from /home/hans/blender-git/blender/source/blender/blenlib/BLI_index_mask.hh:13, from /home/hans/blender-git/blender/source/blender/blenlib/BLI_length_parameterize.hh:11: /home/hans/blender-git/blender/source/blender/blenlib/BLI_string_ref.hh:590:20: note: candidate: ‘std::string blender::operator+(StringRef, StringRef)’ 590 | inline std::string operator+(StringRef a, StringRef b) | ^~~~~~~~ /home/hans/blender-git/blender/source/blender/blenlib/BLI_string_ref.hh:590:40: note: no known conversion for argument 1 from ‘blender::math::QuaternionBase<float>’ to ‘blender::StringRef’ 590 | inline std::string operator+(StringRef a, StringRef b) | ~~~~~~~~~~^ ```
#include "BLI_math_vector.hh"
namespace blender::length_parameterize {

View File

@ -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);

View File

@ -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,
};

View File

@ -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:

View File

@ -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<float3>(mr, vbo, request);
break;
case CD_PROP_QUATERNION:
case CD_PROP_COLOR:
extract_attr_generic<float4>(mr, vbo, request);
break;

View File

@ -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<float *>(buffer));
break;
case CD_PROP_QUATERNION: {
float4 value;
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
*static_cast<math::Quaternion *>(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<int2>());
break;
case CD_PROP_QUATERNION: {
const math::Quaternion value = math::normalize(*active_value.get<math::Quaternion>());
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);
}
/** \} */

View File

@ -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);

View File

@ -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. */
HooglyBoogly marked this conversation as resolved Outdated

Remove padding line.

Remove padding line.
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)

View File

@ -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;

View File

@ -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);