33#include "RNA_prototypes.hh"
82 const float3 &plane_normal,
87 if (lambda <= 0.0f || lambda >= 1.0f) {
116 const float diff_dir = p1_dir - p2_dir;
118 const float u = [=]() {
119 if (diff_dir == 0.0f) {
121 return p1_sqr < p2_sqr ? 1.0f : 0.0f;
124 const float p = p2_dir / diff_dir;
128 const float q = (2 * diff_p2 * p2_dir - p2_sqr * diff_dir) / (diff_dir * diff_sqr);
130 return 0.5f - std::copysign(0.5f, p);
140 if (
v < 0 || !isfinite(
v)) {
157 const int point_num = positions.
size();
158 const float3 ¢er = positions[point];
166 const int from_i = (point - line_i - 2 + point_num) % point_num;
167 const int to_i = (point - line_i - 1 + point_num) % point_num;
169 positions[from_i] - center, positions[to_i] - center, direction);
174 const int from_i = (point + line_i + 1 + point_num) % point_num;
175 const int to_i = (point + line_i + 2 + point_num) % point_num;
177 positions[from_i] - center, positions[to_i] - center, direction);
182 if (point == 0 || point >= point_num - 1) {
186 const int spread_left = std::min(spread, std::max(point - 2, 0));
187 for (
const int line_i :
IndexRange(spread_left)) {
188 const int from_i = std::max(point - line_i - 2, 0);
189 const int to_i = std::max(point - line_i - 1, 0);
191 positions[from_i] - center, positions[to_i] - center, direction);
195 const int spread_right = std::min(spread, std::max(point_num - point - 2, 0));
196 for (
const int line_i :
IndexRange(spread_right)) {
197 const int from_i = std::min(point + line_i + 1, point_num - 1);
198 const int to_i = std::min(point + line_i + 2, point_num - 1);
200 positions[from_i] - center, positions[to_i] - center, direction);
230 float max_distance1 = 0.0f;
231 float max_distance2 = 0.0f;
234 for (
const int line_i :
IndexRange(spread + 2)) {
236 const int from_spread_i = point - spread - 1 + line_i;
237 const int to_spread_i = point + line_i;
240 std::max(from_spread_i,
int(points.
first()));
242 std::min(to_spread_i,
int(points.
last()));
243 const float3 &from_pos = positions[from_i];
244 const float3 &to_pos = positions[to_i];
245 const float3 line_delta = to_pos - from_pos;
248 pos, plane_normal, from_pos, to_pos);
249 if (!line_intersect) {
252 const float3 line_direction = line_intersect.value() -
pos;
253 const float line_distance =
math::length(line_direction);
258 const float diameter = line_distance * 2.0f * cos_angle / (1 + cos_angle);
261 max_distance1 = diameter;
262 intersect1 = line_intersect.value();
266 if (
math::dot(intersect1 -
pos, line_direction) >= 0.0f) {
267 if (diameter > max_distance1) {
268 intersect1 = line_intersect.value();
269 max_distance1 = diameter;
273 if (diameter > max_distance2) {
274 intersect2 = line_intersect.value();
275 max_distance2 = diameter;
280 r_radius = 0.5f * (max_distance1 + max_distance2);
281 if (r_radius < FLT_EPSILON) {
285 const float3 new_center = 0.5f * (intersect1 + intersect2);
314 const IndexRange points = points_by_curve[curve_i];
315 const bool cyclic = cyclic_flags[curve_i];
316 const int point_num = points.
size();
317 const int spread = cyclic ?
318 math::abs(((emd.
spread + point_num / 2) % point_num) - point_num / 2) :
319 std::min(emd.
spread, point_num - 1);
323 const float weight = vgroup_weights[point_i];
326 float envelope_radius;
337 const float target_radius = radii[point_i] * emd.
thickness + envelope_radius;
339 positions[point_i] =
math::interpolate(old_positions[point_i], envelope_center, weight);
386 return is_cyclic_curve ? std::min(info.
spread, point_num / 2) : info.
spread;
391 const bool is_cyclic_curve)
393 const int spread =
curve_spread(info, point_num, is_cyclic_curve);
395 const int num_strokes = point_num + spread - 1;
397 const int num_strokes_simplified = (num_strokes + info.
skip) / (1 + info.
skip);
398 return num_strokes_simplified;
427 const bool src_curve_cyclic,
430 const int base_length,
433 const int point_num = src_curve_points.
size();
437 auto get_index = [=](
const int index) ->
int {
438 return src_curve_cyclic ? (index + point_num) % point_num :
443 const int reverse_i = base_length - 1 -
i;
444 const int point_left = get_index(point - spread + reverse_i);
445 const int point_right = get_index(point + reverse_i);
446 point_src_indices[
i] = src_curve_points[point_left];
447 point_src_indices[base_length +
i] = src_curve_points[point_right];
452 const int src_curve_index,
454 const bool src_curve_cyclic,
462 const int src_point_num = src_curve_points.
size();
463 const int spread =
curve_spread(info, src_point_num, src_curve_cyclic);
467 const int base_length = use_fills ? 2 + info.
skip : 1;
474 curve_src_indices.
fill(src_curve_index);
483 for (
const int dst_i :
IndexRange(num_strokes)) {
484 const int src_i = dst_i * (1 + info.
skip);
487 curve_offsets[dst_i] = dst_points[dst_envelope_points.start()];
489 src_material_indices[src_curve_index];
496 point_src_indices.
slice(dst_envelope_points));
503 const bool keep_original)
511 const int src_curves_num = src_curves.
curves_num();
512 const int src_points_num = src_curves.
points_num();
515 Array<int> envelope_curves_by_curve(src_curves_num + 1, 0);
516 Array<int> envelope_points_by_curve(src_curves_num + 1, 0);
520 envelope_curves_by_curve[src_curve_i] = curve_num;
524 const int dst_curve_start_offset = keep_original ? src_curves_num : 0;
525 const int dst_points_start_offset = keep_original ? src_points_num : 0;
527 envelope_curves_by_curve, dst_curve_start_offset);
529 envelope_points_by_curve, dst_points_start_offset);
530 const int dst_curve_num = envelope_curve_offsets.
total_size() + dst_curve_start_offset;
531 const int dst_point_num = envelope_point_offsets.
total_size() + dst_points_start_offset;
532 if (dst_curve_num == 0 || dst_point_num == 0) {
553 src_curve_indices.as_mutable_span().slice(src_curves.
curves_range()));
562 const bool src_curve_cyclic = src_cyclic[
i];
564 const IndexRange envelope_curves = envelope_curve_offsets[
i];
565 const IndexRange envelope_points = envelope_point_offsets[
i];
571 src_material_indices,
574 dst_material_indices.
span.slice(envelope_curves),
575 src_curve_indices.as_mutable_span().slice(envelope_curves),
600 const IndexRange all_new_points = keep_original ?
604 for (
const int point_i : all_new_points) {
614 for (
const int point_i : all_new_points) {
615 opacity_writer.span[point_i] *= info.
strength;
617 opacity_writer.finish();
622 dst_material_indices.
finish();
667 const int frame = grease_pencil.
runtime->eval_frame;
671 grease_pencil, emd->influence, mask_memory);
674 grease_pencil, layer_mask, frame);
707 C,
ptr,
"open_influence_panel",
IFACE_(
"Influence")))
740 "GreasePencilEnvelope",
742 "GreasePencilEnvelopeModifierData",
744 &RNA_GreasePencilEnvelopeModifier,
Low-level operations for curves.
Low-level operations for grease pencil.
General operations, lookup, etc. for materials.
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_AcceptsGreasePencil
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], const float l1[3], const float l2[3])
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define DNA_struct_default_get(struct_name)
@ eModifierType_GreasePencilEnvelope
GreasePencilEnvelopeModifierMode
@ MOD_GREASE_PENCIL_ENVELOPE_SEGMENTS
@ MOD_GREASE_PENCIL_ENVELOPE_FILLS
@ MOD_GREASE_PENCIL_ENVELOPE_DEFORM
ModifierTypeInfo modifierType_GreasePencilEnvelope
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T & last(const int64_t n=0) const
constexpr Span drop_back(int64_t n) const
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool contains(int64_t value) const
constexpr IndexRange index_range() const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr void fill(const T &value) const
constexpr Span< T > as_span() const
constexpr void copy_from(Span< T > values) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
static VArray from_single(T value, const int64_t size)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
void update_curve_types()
MutableAttributeAccessor attributes_for_write()
IndexRange points_range() const
Span< int > offsets() const
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
MutableSpan< float > radii_for_write()
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_positions_changed()
void tag_topology_changed()
void foreach_index(Fn &&fn) const
static bool is_cyclic(const Nurb *nu)
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void fill_index_range(MutableSpan< T > span, const T start=0)
auto attribute_filter_from_skip_ref(const Span< StringRef > skip)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
T length_squared(const VecBase< T, Size > &a)
T clamp(const T &a, const T &min, const T &max)
T distance(const T &a, const T &b)
T length(const VecBase< T, Size > &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
void read_influence_data(BlendDataReader *reader, GreasePencilModifierInfluenceData *influence_data)
void init_influence_data(GreasePencilModifierInfluenceData *influence_data, const bool has_custom_curve)
static IndexMask get_filtered_stroke_mask(const Object *ob, const bke::CurvesGeometry &curves, const Material *material_filter, const std::optional< int > material_pass_filter, const bool material_filter_invert, const bool material_pass_filter_invert, IndexMaskMemory &memory)
void write_influence_data(BlendWriter *writer, const GreasePencilModifierInfluenceData *influence_data)
void draw_vertex_group_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
VArray< float > get_influence_vertex_weights(const bke::CurvesGeometry &curves, const GreasePencilModifierInfluenceData &influence_data)
static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil, const std::optional< StringRef > tree_node_name_filter, const std::optional< int > layer_pass_filter, const bool layer_filter_invert, const bool layer_pass_filter_invert, IndexMaskMemory &memory)
Vector< bke::greasepencil::Drawing * > get_drawings_for_write(GreasePencil &grease_pencil, const IndexMask &layer_mask, const int frame)
void draw_material_filter_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
void draw_layer_filter_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
void free_influence_data(GreasePencilModifierInfluenceData *influence_data)
void foreach_influence_ID_link(GreasePencilModifierInfluenceData *influence_data, Object *ob, IDWalkFunc walk, void *user_data)
void copy_influence_data(const GreasePencilModifierInfluenceData *influence_data_src, GreasePencilModifierInfluenceData *influence_data_dst, const int)
void ensure_no_bezier_curves(Drawing &drawing)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_for_each(Range &&range, const Function &function)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void blend_write(BlendWriter *writer, const ID *, const ModifierData *md)
static void create_envelope_strokes_for_curve(const EnvelopeInfo &info, const int src_curve_index, const IndexRange src_curve_points, const bool src_curve_cyclic, const VArray< int > &src_material_indices, const IndexRange dst_points, const MutableSpan< int > curve_offsets, const MutableSpan< int > material_indices, const MutableSpan< int > curve_src_indices, const MutableSpan< int > point_src_indices)
static const float unlimited_radius
static void init_data(ModifierData *md)
static void create_envelope_stroke_for_point(const IndexRange src_curve_points, const bool src_curve_cyclic, const int point, const int spread, const int base_length, const MutableSpan< int > point_src_indices)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void panel_draw(const bContext *C, Panel *panel)
static float3 calculate_plane(const float3 ¢er, const float3 &prev, const float3 &next)
static void modify_geometry_set(ModifierData *md, const ModifierEvalContext *ctx, bke::GeometrySet *geometry_set)
static float calc_radius_limit(const Span< float3 > positions, const bool is_cyclic, const int spread, const int point, const float3 &direction)
static void free_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void create_envelope_strokes(const EnvelopeInfo &info, bke::greasepencil::Drawing &drawing, const IndexMask &curves_mask, const bool keep_original)
static bool find_envelope(const Span< float3 > positions, const bool is_cyclic, const int spread, const int point, float3 &r_center, float &r_radius)
static void modify_drawing(const GreasePencilArrayModifierData &mmd, const ModifierEvalContext &ctx, bke::greasepencil::Drawing &drawing)
VecBase< float, 3 > float3
static void blend_read(BlendDataReader *reader, ModifierData *md)
static float calc_min_radius_v3v3(const float3 &p1, const float3 &p2, const float3 &dir)
static int curve_spread(const EnvelopeInfo &info, const int point_num, const bool is_cyclic_curve)
static void deform_drawing_as_envelope(const GreasePencilEnvelopeModifierData &emd, bke::greasepencil::Drawing &drawing, const IndexMask &curves_mask)
static EnvelopeInfo get_envelope_info(const GreasePencilEnvelopeModifierData &emd, const ModifierEvalContext &ctx)
static int curve_envelope_strokes_num(const EnvelopeInfo &info, const int point_num, const bool is_cyclic_curve)
static std::optional< float3 > find_plane_intersection(const float3 &plane_point, const float3 &plane_normal, const float3 &from, const float3 &to)
int RNA_enum_get(PointerRNA *ptr, const char *name)
GreasePencilModifierInfluenceData influence
GreasePencilRuntimeHandle * runtime
bool has_grease_pencil() const
GreasePencil * get_grease_pencil_for_write()
MutableVArraySpan< T > span
PanelLayout panel_prop(const bContext *C, PointerRNA *open_prop_owner, blender::StringRefNull open_prop_name)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)