35#include "RNA_prototypes.hh"
84 const float3 &plane_normal,
89 if (lambda <= 0.0f || lambda >= 1.0f) {
118 const float diff_dir = p1_dir - p2_dir;
120 const float u = [=]() {
121 if (diff_dir == 0.0f) {
123 return p1_sqr < p2_sqr ? 1.0f : 0.0f;
126 const float p = p2_dir / diff_dir;
130 const float q = (2 * diff_p2 * p2_dir - p2_sqr * diff_dir) / (diff_dir * diff_sqr);
132 return 0.5f - std::copysign(0.5f, p);
142 if (
v < 0 || !isfinite(
v)) {
159 const int point_num = positions.size();
168 const int from_i = (point - line_i - 2 + point_num) % point_num;
169 const int to_i = (point - line_i - 1 + point_num) % point_num;
171 positions[from_i] - center, positions[to_i] - center, direction);
172 result = std::min(result, limit);
176 const int from_i = (point + line_i + 1 + point_num) % point_num;
177 const int to_i = (point + line_i + 2 + point_num) % point_num;
179 positions[from_i] - center, positions[to_i] - center, direction);
180 result = std::min(result, limit);
184 if (point == 0 || point >= point_num - 1) {
188 const int spread_left = std::min(spread, std::max(point - 2, 0));
189 for (
const int line_i :
IndexRange(spread_left)) {
190 const int from_i = std::max(point - line_i - 2, 0);
191 const int to_i = std::max(point - line_i - 1, 0);
193 positions[from_i] - center, positions[to_i] - center, direction);
194 result = std::min(result, limit);
197 const int spread_right = std::min(spread, std::max(point_num - point - 2, 0));
198 for (
const int line_i :
IndexRange(spread_right)) {
199 const int from_i = std::min(point + line_i + 1, point_num - 1);
200 const int to_i = std::min(point + line_i + 2, point_num - 1);
202 positions[from_i] - center, positions[to_i] - center, direction);
203 result = std::min(result, limit);
223 positions[points.contains(point - 1) ? point - 1 : (
is_cyclic ? points.last() :
point)];
225 positions[points.contains(point + 1) ? point + 1 : (
is_cyclic ? points.first() :
point)];
232 float max_distance1 = 0.0f;
233 float max_distance2 = 0.0f;
236 for (
const int line_i :
IndexRange(spread + 2)) {
238 const int from_spread_i = point - spread - 1 + line_i;
239 const int to_spread_i = point + line_i;
241 const int from_i =
is_cyclic ? (from_spread_i + points.size()) % points.size() :
242 std::max(from_spread_i,
int(points.first()));
243 const int to_i =
is_cyclic ? (to_spread_i + points.size()) % points.size() :
244 std::min(to_spread_i,
int(points.last()));
245 const float3 &from_pos = positions[from_i];
246 const float3 &to_pos = positions[to_i];
247 const float3 line_delta = to_pos - from_pos;
250 pos, plane_normal, from_pos, to_pos);
251 if (!line_intersect) {
254 const float3 line_direction = line_intersect.value() -
pos;
255 const float line_distance =
math::length(line_direction);
260 const float diameter = line_distance * 2.0f * cos_angle / (1 + cos_angle);
263 max_distance1 = diameter;
264 intersect1 = line_intersect.value();
268 if (
math::dot(intersect1 -
pos, line_direction) >= 0.0f) {
269 if (diameter > max_distance1) {
270 intersect1 = line_intersect.value();
271 max_distance1 = diameter;
275 if (diameter > max_distance2) {
276 intersect2 = line_intersect.value();
277 max_distance2 = diameter;
282 r_radius = 0.5f * (max_distance1 + max_distance2);
283 if (r_radius < FLT_EPSILON) {
287 const float3 new_center = 0.5f * (intersect1 + intersect2);
309 const VArray<bool> cyclic_flags = *attributes.lookup_or_default(
316 const IndexRange points = points_by_curve[curve_i];
317 const bool cyclic = cyclic_flags[curve_i];
318 const int point_num = points.
size();
319 const int spread = cyclic ?
320 math::abs(((emd.
spread + point_num / 2) % point_num) - point_num / 2) :
321 std::min(emd.
spread, point_num - 1);
323 for (
const int64_t i : points.index_range()) {
324 const int64_t point_i = points[i];
325 const float weight = vgroup_weights[point_i];
328 float envelope_radius;
339 const float target_radius = radii[point_i] * emd.
thickness + envelope_radius;
341 positions[point_i] =
math::interpolate(old_positions[point_i], envelope_center, weight);
346 curves.tag_radii_changed();
388 return is_cyclic_curve ? std::min(info.
spread, point_num / 2) : info.
spread;
393 const bool is_cyclic_curve)
395 const int spread =
curve_spread(info, point_num, is_cyclic_curve);
397 const int num_strokes = point_num + spread - 1;
399 const int num_strokes_simplified = (num_strokes + info.
skip) / (1 + info.
skip);
400 return num_strokes_simplified;
429 const bool src_curve_cyclic,
432 const int base_length,
435 const int point_num = src_curve_points.
size();
439 auto get_index = [=](
const int index) ->
int {
440 return src_curve_cyclic ? (index + point_num) % point_num :
445 const int reverse_i = base_length - 1 - i;
446 const int point_left = get_index(point - spread + reverse_i);
447 const int point_right = get_index(point + reverse_i);
448 point_src_indices[i] = src_curve_points[point_left];
449 point_src_indices[base_length + i] = src_curve_points[point_right];
454 const int src_curve_index,
456 const bool src_curve_cyclic,
464 const int src_point_num = src_curve_points.
size();
465 const int spread =
curve_spread(info, src_point_num, src_curve_cyclic);
469 const int base_length = use_fills ? 2 + info.
skip : 1;
476 curve_src_indices.
fill(src_curve_index);
485 for (
const int dst_i :
IndexRange(num_strokes)) {
486 const int src_i = dst_i * (1 + info.
skip);
489 curve_offsets[dst_i] = dst_points[dst_envelope_points.start()];
491 src_material_indices[src_curve_index];
498 point_src_indices.
slice(dst_envelope_points));
505 const bool keep_original)
513 const int src_curves_num = src_curves.
curves_num();
514 const int src_points_num = src_curves.
points_num();
517 Array<int> envelope_curves_by_curve(src_curves_num + 1);
518 Array<int> envelope_points_by_curve(src_curves_num + 1);
522 envelope_curves_by_curve[src_curve_i] = curve_num;
526 const int dst_curve_start_offset = keep_original ? src_curves_num : 0;
527 const int dst_points_start_offset = keep_original ? src_points_num : 0;
529 envelope_curves_by_curve, dst_curve_start_offset);
531 envelope_points_by_curve, dst_points_start_offset);
532 const int dst_curve_num = envelope_curve_offsets.
total_size() + dst_curve_start_offset;
533 const int dst_point_num = envelope_point_offsets.
total_size() + dst_points_start_offset;
534 if (dst_curve_num == 0 || dst_point_num == 0) {
555 src_curve_indices.as_mutable_span().slice(src_curves.
curves_range()));
564 const bool src_curve_cyclic = src_cyclic[i];
566 const IndexRange envelope_curves = envelope_curve_offsets[i];
567 const IndexRange envelope_points = envelope_point_offsets[i];
573 src_material_indices,
576 dst_material_indices.
span.slice(envelope_curves),
577 src_curve_indices.as_mutable_span().slice(envelope_curves),
607 const IndexRange all_new_points = keep_original ?
611 for (
const int point_i : all_new_points) {
613 opacity_writer.span[point_i] *= info.
strength;
616 opacity_writer.finish();
620 dst_material_indices.
finish();
665 const int frame = grease_pencil.
runtime->eval_frame;
669 grease_pencil, emd->influence, mask_memory);
672 grease_pencil, layer_mask, frame);
705 C, layout,
ptr,
"open_influence_panel",
IFACE_(
"Influence")))
738 "GreasePencilEnvelope",
740 "GreasePencilEnvelopeModifierData",
742 &RNA_GreasePencilEnvelopeModifier,
Low-level operations for curves.
Low-level operations for grease pencil.
General operations, lookup, etc. for materials.
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_AcceptsGreasePencil
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
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
struct GreasePencilEnvelopeModifierData GreasePencilEnvelopeModifierData
GreasePencilEnvelopeModifierMode
@ MOD_GREASE_PENCIL_ENVELOPE_SEGMENTS
@ MOD_GREASE_PENCIL_ENVELOPE_FILLS
@ MOD_GREASE_PENCIL_ENVELOPE_DEFORM
ModifierTypeInfo modifierType_GreasePencilEnvelope
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
PanelLayout uiLayoutPanelProp(const bContext *C, uiLayout *layout, PointerRNA *open_prop_owner, const char *open_prop_name)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
constexpr int64_t size() 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 void copy_from(Span< T > values) const
constexpr T & last(const int64_t n=0) const
constexpr Span drop_back(int64_t n) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
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, eCustomDataType 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_layer_mask(const GreasePencil &grease_pencil, const std::optional< StringRef > layer_name_filter, const std::optional< int > layer_pass_filter, const bool layer_filter_invert, const bool layer_pass_filter_invert, IndexMaskMemory &memory)
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)
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)
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