27#define PROF_TABLE_MAX 512
35 CurveProfile *profile = MEM_cnew<CurveProfile>(__func__);
69 for (
int i = 0; i < target->
path_len; i++) {
93 profile->
table =
nullptr;
97 for (
int i = 0; i < profile->
path_len; i++) {
113 const float delta[2])
115 short handle_type = (handle_1) ?
point->h1 :
point->h2;
116 float *handle_location = (handle_1) ? &
point->h1_loc[0] : &
point->h2_loc[0];
118 float start_position[2];
127 handle_location[0] += delta ? delta[0] : 0.0f;
128 handle_location[1] += delta ? delta[1] : 0.0f;
130 handle_location[0] = 0.125f * roundf(8.0f * handle_location[0]);
131 handle_location[1] = 0.125f * roundf(8.0f * handle_location[1]);
136 short other_handle_type = (handle_1) ?
point->h2 :
point->h1;
137 if (other_handle_type ==
HD_ALIGN) {
138 float *other_handle_location = (handle_1) ? &
point->h2_loc[0] : &
point->h1_loc[0];
139 other_handle_location[0] = 2.0f *
point->x - handle_location[0];
140 other_handle_location[1] = 2.0f *
point->y - handle_location[1];
144 if (!
equals_v2v2(handle_location, start_position)) {
153 const float delta[2])
163 float origx =
point->x;
164 float origy =
point->y;
166 point->x += delta[0];
167 point->y += delta[1];
217 memcpy(new_path + i_delete,
218 profile->
path + i_delete + 1,
222 profile->
path = new_path;
237 new_path[0] = profile->
path[0];
238 for (; i_old < profile->
path_len - 1; i_old++) {
240 new_path[i_new] = profile->
path[i_old];
247 new_path[i_new] = profile->
path[i_old];
250 profile->
path = new_path;
268 const float new_loc[2] = {
x,
y};
278 for (
int i = 0; i < profile->
path_len - 1; i++) {
279 const float loc1[2] = {profile->
path[i].
x, profile->
path[i].
y};
280 const float loc2[2] = {profile->
path[i + 1].
x, profile->
path[i + 1].
y};
294 for (
int i_new = 0, i_old = 0; i_new < profile->
path_len; i_new++) {
295 if (i_new != i_insert) {
297 new_path[i_new] = profile->
path[i_old];
304 char new_handle_type = (new_path[i_new - 1].
h2 ==
HD_VECT &&
309 new_pt = &new_path[i_new];
317 profile->
path = new_path;
323 for (
int i = 0; i < profile->
path_len; i++) {
325 profile->
path[i].
h1 = type_1;
326 profile->
path[i].
h2 = type_2;
352 for (
int i = 0; i < profile->
path_len; i++) {
353 int i_reversed = profile->
path_len - i - 1;
356 new_path[i_reversed].
profile = profile;
371 profile->
path = new_path;
383 for (
int i = 1; i < n - 2; i++) {
384 const float x = 1.0f - (0.5f * (1.0f -
cosf(
float(i /
float(n - 3)) *
M_PI_2)));
385 const float y = 0.5f + 0.5f *
sinf(
float((i /
float(n - 3)) *
M_PI_2));
407 float n_steps_x = (n % 2 == 0) ? n : (n - 1);
408 float n_steps_y = (n % 2 == 0) ? (n - 2) : (n - 1);
410 for (
int i = 0; i < n; i++) {
411 int step_x = (i + 1) / 2;
413 const float x = 1.0f - (
float(2 * step_x) / n_steps_x);
414 const float y =
float(2 * step_y) / n_steps_y;
508 for (
int i = 0; i < profile->
path_len; i++) {
513 profile->
table =
nullptr;
525 const int resolution = 16;
552 float *point_loc = &
point->x;
555 const float *prev_loc, *next_loc;
556 if (prev ==
nullptr) {
558 pt[0] = 2.0f * point_loc[0] - next_loc[0];
559 pt[1] = 2.0f * point_loc[1] - next_loc[1];
566 if (
next ==
nullptr) {
568 pt[0] = 2.0f * point_loc[0] - prev_loc[0];
569 pt[1] = 2.0f * point_loc[1] - prev_loc[1];
576 float dvec_a[2], dvec_b[2];
580 float len_a =
len_v2(dvec_a);
581 float len_b =
len_v2(dvec_b);
591 tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a;
592 tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a;
618 for (
int i = 1; i < path_len - 1; i++) {
633 float start_handle_direction[2], end_handle_direction[2];
635 sub_v2_v2v2(start_handle_direction, path[i_edge].h2_loc, &path[i_edge].
x);
637 sub_v2_v2v2(end_handle_direction, &path[i_edge + 1].
x, path[i_edge + 1].h1_loc);
639 return angle_v2v2(start_handle_direction, end_handle_direction);
680 bool sample_straight_edges,
687 int totedges = totpoints - 1;
694 for (
int i = 0; i < totedges; i++) {
705 if (n_segments >= totedges) {
706 if (sample_straight_edges) {
709 int n_common = n_segments / totedges;
710 n_left = n_segments % totedges;
715 for (
int i = 0; i < totedges; i++) {
716 n_samples[i] = n_common;
723 int n_curved_edges = 0;
724 for (
int i = 0; i < totedges; i++) {
730 n_curved_edges = (n_curved_edges == 0) ? totedges : n_curved_edges;
733 n_left = n_segments - (totedges - n_curved_edges);
734 int n_common = n_left / n_curved_edges;
736 for (
int i = 0; i < totedges; i++) {
740 n_samples[i] += n_common;
749 n_left -= n_common * n_curved_edges;
758 for (
int i = 0; i < n_left; i++) {
768 for (
int i_sample = 0, i = 0; i < totedges; i++) {
769 if (n_samples[i] > 0) {
771 r_samples[i_sample].
h1 = path[i].
h1;
772 r_samples[i_sample].
h2 = path[i].
h2;
774 for (
int j = i_sample + 1; j < i_sample + n_samples[i]; j++) {
775 r_samples[j].
flag = 0;
784 path[i + 1].h1_loc[0],
786 &r_samples[i_sample].
x,
791 path[i + 1].h1_loc[1],
793 &r_samples[i_sample].
y,
797 i_sample += n_samples[i];
815 profile->
path[0].
x = 1.0f;
816 profile->
path[0].
y = 0.0f;
818 profile->
path[1].
x = 1.0f;
819 profile->
path[1].
y = 1.0f;
856 float total_length = 0;
876 const float segment_length = total_length / n_segments;
878 float distance_to_previous_table_point = 0.0f;
882 r_samples[0].
x = profile->
table[0].
x;
883 r_samples[0].
y = profile->
table[0].
y;
886 float segment_left = segment_length;
887 for (
int i = 1; i < n_segments; i++) {
889 while (distance_to_next_table_point < segment_left) {
890 segment_left -= distance_to_next_table_point;
893 distance_to_previous_table_point = 0.0f;
896 float factor = (distance_to_previous_table_point + segment_left) /
897 (distance_to_previous_table_point + distance_to_next_table_point);
901#ifdef DEBUG_CURVEPROFILE_EVALUATE
902 printf(
"segment_left: %.3f\n", segment_left);
903 printf(
"i_table: %d\n", i_table);
904 printf(
"distance_to_previous_table_point: %.3f\n", distance_to_previous_table_point);
905 printf(
"distance_to_next_table_point: %.3f\n", distance_to_next_table_point);
906 printf(
"Interpolating with factor %.3f from (%.3f, %.3f) to (%.3f, %.3f)\n\n",
908 profile->
table[i_table].
x,
909 profile->
table[i_table].
y,
910 profile->
table[i_table + 1].
x,
911 profile->
table[i_table + 1].
y);
915 distance_to_next_table_point -= segment_left;
916 distance_to_previous_table_point += segment_left;
917 segment_left = segment_length;
936 new_table[n_samples - 1].
x = 0.0f;
937 new_table[n_samples - 1].
y = 1.0f;
940 profile->
table = new_table;
950 if (n_samples <= 0) {
979 for (
int i = 0; i < profile->
path_len; i++) {
1001 for (
int i = 0; i < profile->
path_len - 1; i++) {
1024 float length_portion,
1029 const float requested_length = length_portion * total_length;
1033 float length_traveled = 0.0f;
1034 while (length_traveled < requested_length) {
1040 if (length_traveled + new_length >= requested_length) {
1043 length_traveled += new_length;
1050 float lerp_factor = (requested_length - length_traveled) / distance_to_next_point;
1052#ifdef DEBUG_CURVEPROFILE_EVALUATE
1053 printf(
"CURVEPROFILE EVALUATE\n");
1054 printf(
" length portion input: %f\n",
double(length_portion));
1055 printf(
" requested path length: %f\n",
double(requested_length));
1056 printf(
" distance to next point: %f\n",
double(distance_to_next_point));
1057 printf(
" length traveled: %f\n",
double(length_traveled));
1058 printf(
" lerp-factor: %f\n",
double(lerp_factor));
1059 printf(
" ith point (%f, %f)\n",
double(profile->
path[i].
x),
double(profile->
path[i].
y));
1060 printf(
" next point(%f, %f)\n",
double(profile->
path[i + 1].
x),
double(profile->
path[i + 1].
y));
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
@ PROF_UPDATE_REMOVE_DOUBLES
MINLINE float max_ff(float a, float b)
MINLINE float pow2f(float x)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE float interpf(float target, float origin, float t)
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
float angle_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
#define UNUSED_VARS_NDEBUG(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
@ PROF_SAMPLE_EVEN_LENGTHS
@ PROF_SAMPLE_STRAIGHT_EDGES
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
local_group_size(16, 16) .push_constant(Type b
static float bezt_edge_handle_angle(const CurveProfilePoint *path, int i_edge)
static float curveprofile_total_length(const CurveProfile *profile)
void BKE_curveprofile_init(CurveProfile *profile, short segments_len)
static void create_samples_even_spacing(CurveProfile *profile, int n_segments, CurveProfilePoint *r_samples)
void BKE_curveprofile_evaluate_length_portion(const CurveProfile *profile, float length_portion, float *x_out, float *y_out)
bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *point)
CurveProfilePoint * BKE_curveprofile_insert(CurveProfile *profile, float x, float y)
void BKE_curveprofile_copy_data(CurveProfile *target, const CurveProfile *profile)
void BKE_curveprofile_selected_handle_set(CurveProfile *profile, int type_1, int type_2)
static void curveprofile_build_steps(CurveProfile *profile)
bool BKE_curveprofile_move_handle(CurveProfilePoint *point, const bool handle_1, const bool snap, const float delta[2])
bool BKE_curveprofile_move_point(CurveProfile *profile, CurveProfilePoint *point, const bool snap, const float delta[2])
static void curveprofile_build_supports(CurveProfile *profile)
static void curveprofile_make_table(CurveProfile *profile)
void BKE_curveprofile_reset(CurveProfile *profile)
static void calculate_path_handles(CurveProfilePoint *path, int path_len)
static CurveProfilePoint mirror_point(const CurveProfilePoint *point)
static bool is_curved_edge(CurveProfilePoint *path, int i)
int BKE_curveprofile_table_size(const CurveProfile *profile)
void BKE_curveprofile_free_data(CurveProfile *profile)
void BKE_curveprofile_blend_write(BlendWriter *writer, const CurveProfile *profile)
void BKE_curveprofile_blend_read(BlendDataReader *reader, CurveProfile *profile)
void BKE_curveprofile_remove_by_flag(CurveProfile *profile, const short flag)
void BKE_curveprofile_reset_view(CurveProfile *profile)
static void point_calculate_handle(CurveProfilePoint *point, const CurveProfilePoint *prev, const CurveProfilePoint *next)
CurveProfile * BKE_curveprofile_add(eCurveProfilePresets preset)
void BKE_curveprofile_reverse(CurveProfile *profile)
static void point_init(CurveProfilePoint *point, float x, float y, short flag, char h1, char h2)
CurveProfile * BKE_curveprofile_copy(const CurveProfile *profile)
static void create_samples(CurveProfile *profile, int n_segments, bool sample_straight_edges, CurveProfilePoint *r_samples)
void BKE_curveprofile_free(CurveProfile *profile)
static float curveprofile_distance_to_next_table_point(const CurveProfile *profile, int i)
void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
static int sort_points_curvature(const void *in_a, const void *in_b)
static void curveprofile_make_segments_table(CurveProfile *profile)
void BKE_curveprofile_set_defaults(CurveProfile *profile)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const void *vmemh)
vector snap(vector a, vector b)
float distance(float a, float b)
struct CurveProfile * profile
CurveProfilePoint * table
CurveProfilePoint * segments