51#define EDIT_CURVES_NURBS_CONTROL_POINT (1u)
52#define EDIT_CURVES_BEZIER_HANDLE (1u << 1)
53#define EDIT_CURVES_ACTIVE_HANDLE (1u << 2)
54#define EDIT_CURVES_HANDLE_TYPES_SHIFT (4u)
119 return (cache && cache->
is_dirty ==
false);
127 cache = MEM_new<CurvesBatchCache>(__func__);
128 curves.batch_cache = cache;
219 for (const int i_curve : range) {
220 const IndexRange points = points_by_curve[i_curve];
222 Span<float3> curve_positions = positions.slice(points);
223 MutableSpan<PositionAndParameter> curve_posTime_data = posTime_data.slice(points);
225 float total_len = 0.0f;
226 for (const int i_point : curve_positions.index_range()) {
228 total_len += math::distance(curve_positions[i_point - 1], curve_positions[i_point]);
230 curve_posTime_data[i_point].position = curve_positions[i_point];
231 curve_posTime_data[i_point].parameter = total_len;
233 hairLength_data[i_curve] = total_len;
236 if (total_len > 0.0f) {
237 const float factor = 1.0f / total_len;
239 for (const int i_point : curve_positions.index_range()) {
240 curve_posTime_data[i_point].parameter *= factor;
291 Span<float3> deformed_positions = deformation.positions;
292 const int bezier_point_count = bezier_dst_offsets.
total_size();
293 const int size = deformed_positions.
size() + bezier_point_count * 2;
301 pos_dst.
take_front(deformed_positions.
size()).copy_from(deformed_positions);
308 data_dst.
data() + deformed_positions.
size() + bezier_point_count, bezier_point_count);
310 const Span<float3> left_handle_positions = curves.handle_positions_left();
311 const Span<float3> right_handle_positions = curves.handle_positions_right();
312 const VArray<int8_t> left_handle_types = curves.handle_types_left();
313 const VArray<int8_t> right_handle_types = curves.handle_types_right();
316 const VArray<bool> selection_attr = *curves.attributes().lookup_or_default<
bool>(
317 ".selection", bke::AttrDomain::Point,
true);
319 auto handle_other_curves = [&](
const uint32_t fill_value,
const bool mark_active) {
321 selection.foreach_index(
GrainSize(256), [&](
const int curve_i) {
322 const IndexRange points = points_by_curve[curve_i];
323 bool is_active =
false;
325 is_active = array_utils::count_booleans(selection_attr, points) > 0;
333 bke::curves::foreach_curve_by_type(
334 curves.curve_types(),
335 curves.curve_type_counts(),
336 curves.curves_range(),
337 handle_other_curves(0,
false),
338 handle_other_curves(0,
false),
340 const VArray<bool> selection_left = *curves.attributes().lookup_or_default<bool>(
341 ".selection_handle_left", bke::AttrDomain::Point,
true);
342 const VArray<bool> selection_right = *curves.attributes().lookup_or_default<bool>(
343 ".selection_handle_right", bke::AttrDomain::Point,
true);
345 selection.foreach_index(
GrainSize(256), [&](
const int src_i,
const int64_t dst_i) {
346 for (
const int point : points_by_curve[src_i]) {
347 const int point_in_curve = point - points_by_curve[src_i].start();
348 const int dst_index = bezier_dst_offsets[dst_i].start() + point_in_curve;
351 bool is_active = selection_attr[
point] || selection_left[
point] ||
352 selection_right[
point];
353 handle_data_left[dst_index] =
bezier_data_value(left_handle_types[point], is_active);
354 handle_data_right[dst_index] =
bezier_data_value(right_handle_types[point], is_active);
360 if (!bezier_point_count) {
366 pos_dst.
data() + deformed_positions.
size() + bezier_point_count, bezier_point_count);
369 array_utils::gather_group_to_group(
370 points_by_curve, bezier_dst_offsets, bezier_curves, left_handle_positions, left_handles);
371 array_utils::gather_group_to_group(
372 points_by_curve, bezier_dst_offsets, bezier_curves, right_handle_positions, right_handles);
383 const int bezier_point_count = bezier_dst_offsets.
total_size();
384 const int vert_count = curves.points_num() + bezier_point_count * 2;
389 const VArray<float> attribute = *curves.attributes().lookup_or_default<
float>(
390 ".selection", bke::AttrDomain::Point, 1.0f);
391 attribute.
materialize(data.slice(0, curves.points_num()));
393 if (!bezier_point_count) {
397 const VArray<float> attribute_left = *curves.attributes().lookup_or_default<
float>(
398 ".selection_handle_left", bke::AttrDomain::Point, 1.0f);
399 const VArray<float> attribute_right = *curves.attributes().lookup_or_default<
float>(
400 ".selection_handle_right", bke::AttrDomain::Point, 1.0f);
404 IndexRange dst_range = IndexRange::from_begin_size(curves.points_num(), bezier_point_count);
405 array_utils::gather_group_to_group(
406 points_by_curve, bezier_dst_offsets, bezier_curves, attribute_left, data.slice(dst_range));
408 dst_range = dst_range.
shift(bezier_point_count);
409 array_utils::gather_group_to_group(
410 points_by_curve, bezier_dst_offsets, bezier_curves, attribute_right, data.
slice(dst_range));
416 const int points_num = points_by_curve.
total_size();
417 const int curves_num = points_by_curve.
size();
418 const int indices_num = points_num + curves_num;
423 for (
const int i : points_by_curve.
index_range()) {
425 for (
const int i_point : points) {
439 const int bezier_point_count = bezier_offsets.
total_size();
441 const int vert_len = curves.points_num() + 2 * bezier_point_count;
443 const int index_len_for_bezier_handles = 4 * bezier_point_count;
448 const int index_len_for_other_handles = (curves.points_num() - bezier_point_count -
449 other_curves.
size()) *
451 array_utils::count_booleans(cyclic, other_curves) * 2;
452 const int index_len = index_len_for_other_handles + index_len_for_bezier_handles;
456 memcpy(&right_elb, &elb,
sizeof(elb));
457 right_elb.
index_len = 2 * bezier_point_count;
459 const OffsetIndices points_by_curve = curves.points_by_curve();
462 IndexRange bezier_points = points_by_curve[src_i];
463 const int index_shift = curves.points_num() - bezier_points.
first() +
464 bezier_offsets[dst_i].first();
465 for (
const int point : bezier_points) {
466 const int point_left_i = index_shift +
point;
472 IndexRange curve_points = points_by_curve[src_i];
473 if (curve_points.
size() <= 1) {
476 for (
const int point : curve_points.
drop_back(1)) {
479 if (cyclic[src_i] && curve_points.
size() > 2) {
518 request.
domain == bke::AttrDomain::Point ? curves.geometry.point_num :
519 curves.geometry.curve_num);
533 attribute.varray.materialize(vbo_span);
541 char sampler_name[32];
555 if (request.
domain == bke::AttrDomain::Point) {
564 for (
const int i : points_by_curve.
index_range()) {
611 point_len =
max_ii(1, point_len);
618 const int thickness_res)
627 if (use_strip_prims) {
650 if (curves.curves_num()) {
661 const CustomData &cd_curve = curves.geometry.curve_data;
662 const CustomData &cd_point = curves.geometry.point_data;
671 const char *name = gpu_attr->name;
674 std::optional<bke::AttrDomain> domain;
681 if (name[0] !=
'\0') {
684 domain = bke::AttrDomain::Curve;
690 domain = bke::AttrDomain::Point;
693 domain = bke::AttrDomain::Curve;
712 domain = bke::AttrDomain::Curve;
715 domain = bke::AttrDomain::Point;
722 layer = (name[0] !=
'\0') ?
726 domain = bke::AttrDomain::Curve;
730 layer = (name[0] !=
'\0') ?
734 domain = bke::AttrDomain::Point;
738 if (layer != -1 && name[0] ==
'\0' && domain.has_value()) {
740 domain == bke::AttrDomain::Curve ? &cd_curve : &cd_point,
CD_PROP_FLOAT2, layer);
743 if (layer != -1 && domain.has_value()) {
763 if (layer != -1 && domain.has_value()) {
784 bool need_tf_update =
false;
793 if (request.
domain == bke::AttrDomain::Point) {
794 need_tf_update =
true;
800 return need_tf_update;
818 const CustomData &custom_data = domain == bke::AttrDomain::Point ? curves.geometry.point_data :
819 curves.geometry.curve_data;
832 BLI_snprintf(r_sampler_name, 32,
"a%s", attr_safe_name);
839 const int thickness_res)
842 bool need_ft_update =
false;
863 need_ft_update =
true;
874 need_ft_update =
true;
884 *r_cache = &eval_cache;
885 return need_ft_update;
891 if (cache ==
nullptr) {
915 MEM_delete(batch_cache);
916 curves->batch_cache =
nullptr;
922 if (cache ==
nullptr) {
926 bool do_discard =
false;
947 return max_ii(1, curves->totcol);
976 bool *r_is_point_domain)
990 if (request_i == -1) {
991 *r_is_point_domain =
false;
995 case bke::AttrDomain::Point:
996 *r_is_point_domain =
true;
998 case bke::AttrDomain::Curve:
999 *r_is_point_domain =
false;
1009 const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
1013 for (
const int i : curves.curves_range()) {
1014 edges_len += bke::curves::segments_num(points_by_curve[i].
size(), cyclic[i]);
1017 const int index_len = edges_len + curves.curves_num() * 2;
1022 for (
const int i : curves.curves_range()) {
1023 const IndexRange points = points_by_curve[i];
1024 if (cyclic[i] && points.size() > 1) {
1027 for (
const int i_point : points) {
1046 const Span<float3> positions = curves.evaluated_positions();
1057 if (ob_orig ==
nullptr) {
1073 curves_orig.
points_by_curve(), bezier_curves, bezier_point_offset_data);
1076 bke::crazyspace::get_evaluated_curves_deformation(ob, *ob_orig);
1100 curves_orig, bezier_curves, bezier_offsets, deformation, cache);
@ BKE_CURVES_BATCH_DIRTY_ALL
Low-level operations for curves.
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_named_layer(const CustomData *data, eCustomDataType type, blender::StringRef name)
const char * CustomData_get_layer_name(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_render_layer(const CustomData *data, eCustomDataType type)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
MINLINE int max_ii(int a, int b)
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
Object * DEG_get_original_object(Object *object)
Object is a sort of wrapper for general info.
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
#define GPU_BATCH_DISCARD_SAFE(batch)
eGPUBackendType GPU_backend_get_type()
#define GPU_INDEXBUF_DISCARD_SAFE(elem)
void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *)
void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *, uint v1, uint v2)
void GPU_indexbuf_join(GPUIndexBufBuilder *builder, const GPUIndexBufBuilder *builder_from)
blender::gpu::IndexBuf * GPU_indexbuf_build_curves_on_device(GPUPrimType prim_type, uint curves_num, uint verts_per_curve)
void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *, uint v)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, blender::gpu::IndexBuf *)
void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len)
ListBase GPU_material_attributes(const GPUMaterial *material)
void GPU_vertbuf_attr_get_raw_data(blender::gpu::VertBuf *, uint a_idx, GPUVertBufRaw *access)
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_attr_fill(blender::gpu::VertBuf *, uint a_idx, const void *data)
blender::gpu::VertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat &format, GPUUsageType usage)
#define GPU_vertbuf_init_with_format(verts, format)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY
Read Guarded memory(de)allocation.
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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr int64_t first() const
constexpr IndexRange shift(int64_t n) const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T * data() const
constexpr void fill(const T &value) const
constexpr MutableSpan take_front(const int64_t n) const
constexpr int64_t size() const
void materialize(MutableSpan< T > r_span) const
std::optional< AttributeMetaData > lookup_meta_data(const StringRef attribute_id) const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
AttributeAccessor attributes() const
VArray< int8_t > curve_types() const
IndexMask slice(IndexRange range) const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
IndexRange index_range() const
Utilities for rendering attributes.
#define EDIT_CURVES_ACTIVE_HANDLE
#define EDIT_CURVES_HANDLE_TYPES_SHIFT
#define EDIT_CURVES_BEZIER_HANDLE
#define EDIT_CURVES_NURBS_CONTROL_POINT
bool DRW_batch_requested(blender::gpu::Batch *batch, GPUPrimType prim_type)
blender::gpu::Batch * DRW_batch_request(blender::gpu::Batch **batch)
void DRW_vbo_request(blender::gpu::Batch *batch, blender::gpu::VertBuf **vbo)
bool DRW_vbo_requested(blender::gpu::VertBuf *vbo)
void DRW_ibo_request(blender::gpu::Batch *batch, blender::gpu::IndexBuf **ibo)
bool DRW_ibo_requested(blender::gpu::IndexBuf *ibo)
struct @620::@623 attr_id
int DRW_curves_material_count_get(const Curves *curves)
static void ensure_final_attribute(const Curves &curves, CurvesEvalCache &cache, const DRW_AttributeRequest &request, const int index)
static void clear_eval_data(CurvesEvalCache &eval_cache)
void DRW_curves_batch_cache_validate(Curves *curves)
static void create_points_position_time_vbo(const bke::CurvesGeometry &curves, CurvesEvalCache &cache)
static void alloc_final_attribute_vbo(CurvesEvalCache &cache, const GPUVertFormat &format, const int index, const char *)
blender::gpu::Batch * DRW_curves_batch_cache_get_edit_points(Curves *curves)
static void create_edit_lines_ibo(const bke::CurvesGeometry &curves, CurvesBatchCache &cache)
static bool batch_cache_is_dirty(const Curves &curves)
static void fill_points_position_time_vbo(const OffsetIndices< int > points_by_curve, const Span< float3 > positions, MutableSpan< PositionAndParameter > posTime_data, MutableSpan< float > hairLength_data)
void DRW_curves_batch_cache_free_old(Curves *curves, int ctime)
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32])
void drw_attributes_clear(DRW_Attributes *attributes)
static void create_edit_points_selection(const bke::CurvesGeometry &curves, const IndexMask bezier_curves, const OffsetIndices< int > bezier_dst_offsets, CurvesBatchCache &cache)
static void clear_edit_data(CurvesBatchCache *cache)
blender::gpu::Batch * DRW_curves_batch_cache_get_edit_curves_handles(Curves *curves)
bool drw_custom_data_match_attribute(const CustomData &custom_data, const char *name, int *r_layer_index, eCustomDataType *r_type)
static void alloc_final_points_vbo(CurvesEvalCache &cache)
static void init_batch_cache(Curves &curves)
static void create_sculpt_cage_ibo(const OffsetIndices< int > points_by_curve, CurvesBatchCache &cache)
static GPUVertFormat single_attr_vbo_format(const char *name, const GPUVertCompType comp_type, const uint comp_len, const GPUVertFetchMode fetch_mode, uint &attr_id=DUMMY_ID)
blender::gpu::Batch * DRW_curves_batch_cache_get_sculpt_curves_cage(Curves *curves)
static void calc_edit_handles_ibo(const bke::CurvesGeometry &curves, const IndexMask bezier_curves, const OffsetIndices< int > bezier_offsets, const IndexMask other_curves, CurvesBatchCache &cache)
static void create_edit_points_position_and_data(const bke::CurvesGeometry &curves, const IndexMask bezier_curves, const OffsetIndices< int > bezier_dst_offsets, const bke::crazyspace::GeometryDeformation deformation, CurvesBatchCache &cache)
static void create_curve_offsets_vbos(const OffsetIndices< int > points_by_curve, CurvesEvalCache &cache)
static void calc_final_indices(const bke::CurvesGeometry &curves, CurvesEvalCache &cache, const int thickness_res)
static void create_edit_points_position_vbo(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &, CurvesBatchCache &cache)
static void clear_batch_cache(Curves &curves)
static CurvesBatchCache & get_batch_cache(Curves &curves)
void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
static uint32_t bezier_data_value(int8_t handle_type, bool is_active)
gpu::VertBuf ** DRW_curves_texture_for_evaluated_attribute(Curves *curves, const char *name, bool *r_is_point_domain)
static bool ensure_attributes(const Curves &curves, CurvesBatchCache &cache, const GPUMaterial *gpu_material)
bool curves_ensure_procedural_data(Curves *curves_id, CurvesEvalCache **r_cache, const GPUMaterial *gpu_material, const int subdiv, const int thickness_res)
static void fill_curve_offsets_vbos(const OffsetIndices< int > points_by_curve, GPUVertBufRaw &data_step, GPUVertBufRaw &seg_step)
void drw_attributes_merge(DRW_Attributes *dst, const DRW_Attributes *src, std::mutex &render_mutex)
static void discard_attributes(CurvesEvalCache &eval_cache)
blender::gpu::Batch * DRW_curves_batch_cache_get_edit_curves_lines(Curves *curves)
static void ensure_control_point_attribute(const Curves &curves, CurvesEvalCache &cache, const DRW_AttributeRequest &request, const int index, const GPUVertFormat &format)
void drw_attributes_add_request(DRW_Attributes *attrs, const char *name, const eCustomDataType type, const int layer_index, const blender::bke::AttrDomain domain)
void DRW_curves_batch_cache_free(Curves *curves)
void DRW_curves_batch_cache_create_requested(Object *ob)
static void clear_final_data(CurvesEvalFinalCache &final_cache)
bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b)
static void request_attribute(Curves &curves, const char *name)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
gpu::IndexBuf * edit_handles_ibo
gpu::VertBuf * edit_points_pos
CurvesEvalCache eval_cache
gpu::Batch * edit_curves_lines
gpu::VertBuf * edit_points_selection
gpu::IndexBuf * edit_curves_lines_ibo
gpu::IndexBuf * sculpt_cage_ibo
gpu::VertBuf * edit_curves_lines_pos
gpu::VertBuf * edit_points_data
gpu::Batch * edit_handles
gpu::VertBuf * proc_strand_seg_buf
CurvesEvalFinalCache final
gpu::VertBuf * proc_length_buf
gpu::VertBuf * proc_attributes_buf[GPU_MAX_ATTR]
gpu::VertBuf * proc_point_buf
gpu::VertBuf * proc_strand_buf
DRW_Attributes attr_used_over_time
gpu::VertBuf * attributes_buf[GPU_MAX_ATTR]
int last_attr_matching_time
blender::bke::AttrDomain domain
DRW_AttributeRequest requests[GPU_MAX_ATTR]