35 const int l0 = looptri.
tri[0];
36 const int l1 = looptri.
tri[1];
37 const int l2 = looptri.
tri[2];
39 const float3 &l0_normal = corner_normals[l0];
40 const float3 &l1_normal = corner_normals[l1];
41 const float3 &l2_normal = corner_normals[l2];
52 const float step = 1.0f / (
float)(r_positions.
size() - 1);
59 const KDTree_3d &old_roots_kdtree)
61 const int tot_added_curves = root_positions.
size();
64 for (
const int i : range) {
65 const float3 root = root_positions[i];
66 std::array<KDTreeNearest_3d, max_neighbors> nearest_n;
67 const int found_neighbors = BLI_kdtree_3d_find_nearest_n(
69 float tot_weight = 0.0f;
70 for (
const int neighbor_i :
IndexRange(found_neighbors)) {
71 KDTreeNearest_3d &nearest = nearest_n[neighbor_i];
72 const float weight = 1.0f /
std::max(nearest.dist, 0.00001f);
74 neighbors_per_curve[i].append({nearest.index, weight});
78 neighbor.weight /= tot_weight;
82 return neighbors_per_curve;
85 template<
typename T,
typename GetValueF>
88 const GetValueF &get_value_from_neighbor,
93 for (const int i : range) {
94 const NeighborCurves &neighbors = neighbors_per_curve[i];
95 if (neighbors.is_empty()) {
96 mixer.mix_in(i, fallback, 1.0f);
99 for (const NeighborCurve &neighbor : neighbors) {
100 const T neighbor_value = get_value_from_neighbor(neighbor.index);
101 mixer.mix_in(i, neighbor_value, neighbor.weight);
111 const int old_curves_num,
115 const float4x4 &surface_to_curves_normal_mat)
117 const int added_curves_num = root_positions_cu.
size();
120 for (
const int i : range) {
121 const int curve_i = old_curves_num + i;
123 const float3 &root_cu = root_positions_cu[i];
124 const float length = new_lengths_cu[i];
125 const float3 &normal_su = new_normals_su[i];
137 const int old_curves_num,
145 const int added_curves_num = root_positions_cu.
size();
150 for (
const int added_curve_i : range) {
151 const NeighborCurves &neighbors = neighbors_per_curve[added_curve_i];
152 const int curve_i = old_curves_num + added_curve_i;
155 const float length_cu = new_lengths_cu[added_curve_i];
156 const float3 &normal_su = new_normals_su[added_curve_i];
159 const float3 &root_cu = root_positions_cu[added_curve_i];
163 const float3 tip_cu = root_cu + length_cu * normal_cu;
168 positions_cu.
slice(points).
fill(root_cu);
171 const int neighbor_curve_i = neighbor.index;
172 const float2 neighbor_uv = uv_coords[neighbor_curve_i];
174 if (
result.type != ReverseUVSampler::ResultType::Ok) {
179 *
result.looptri,
result.bary_weights, corner_normals_su);
185 float normal_rotation_cu[3][3];
188 const IndexRange neighbor_points =
curves.points_for_curve(neighbor_curve_i);
189 const float3 &neighbor_root_cu = positions_cu[neighbor_points[0]];
199 if (neighbor_positions_cu.
size() == 1) {
204 length_parameterize::accumulate_lengths<float3>(neighbor_positions_cu,
false, lengths);
205 const float neighbor_length_cu = lengths.
last();
208 const float length_factor =
std::min(1.0f, length_cu / neighbor_length_cu);
209 const float resample_factor = (1.0f / (points.
size() - 1.0f)) * length_factor;
211 sample_lengths[i] = i * resample_factor * neighbor_length_cu;
220 neighbor_positions_cu[
indices[i] + 1],
222 const float3 relative_to_root_cu = sample_cu - neighbor_root_cu;
223 float3 rotated_relative_coord = relative_to_root_cu;
224 mul_m3_v3(normal_rotation_cu, rotated_relative_coord);
225 positions_cu[points[i]] += neighbor.weight * rotated_relative_coord;
237 const bool use_interpolation =
inputs.interpolate_length ||
inputs.interpolate_point_count ||
246 for (
const int i :
inputs.uvs.index_range()) {
249 if (
result.type != ReverseUVSampler::ResultType::Ok) {
255 looptris.
append(&looptri);
256 const float3 root_position_su = attribute_math::mix3<float3>(
261 root_positions_cu.
append(
inputs.transforms->surface_to_curves * root_position_su);
266 if (use_interpolation) {
271 const int added_curves_num = root_positions_cu.
size();
272 const int old_points_num =
curves.points_num();
273 const int old_curves_num =
curves.curves_num();
274 const int new_curves_num = old_curves_num + added_curves_num;
277 curves.resize(old_points_num, new_curves_num);
282 if (
inputs.interpolate_point_count) {
283 interpolate_from_neighbors<int>(
285 inputs.fallback_point_count,
286 [&](
const int curve_i) { return curves.points_for_curve(curve_i).size(); },
287 new_point_counts_per_curve);
290 new_point_counts_per_curve.
fill(
inputs.fallback_point_count);
292 for (
const int i :
IndexRange(added_curves_num)) {
293 curve_offsets[old_curves_num + i + 1] += curve_offsets[old_curves_num + i];
296 const int new_points_num =
curves.offsets().last();
297 curves.resize(new_points_num, new_curves_num);
306 if (
inputs.interpolate_length) {
307 interpolate_from_neighbors<float>(
309 inputs.fallback_curve_length,
310 [&](
const int curve_i) {
311 const IndexRange points = curves.points_for_curve(curve_i);
313 for (const int segment_i : points.drop_back(1)) {
314 const float3 &p1 = positions_cu[segment_i];
315 const float3 &p2 = positions_cu[segment_i + 1];
316 length += math::distance(p1, p2);
323 new_lengths_cu.fill(
inputs.fallback_curve_length);
327 Array<float3> new_normals_su(added_curves_num);
329 for (
const int i : range) {
331 *looptris[i], bary_coords[i],
inputs.corner_normals_su);
336 const VArray<float> points_selection =
curves.selection_point_float();
337 if (points_selection.is_span()) {
338 MutableSpan<float> points_selection_span =
curves.selection_point_float_for_write();
339 points_selection_span.drop_front(old_points_num).fill(1.0f);
341 const VArray<float> curves_selection =
curves.selection_curve_float();
342 if (curves_selection.is_span()) {
343 MutableSpan<float> curves_selection_span =
curves.selection_curve_float_for_write();
344 curves_selection_span.drop_front(old_curves_num).fill(1.0f);
348 if (
inputs.interpolate_shape) {
356 *
inputs.reverse_uv_sampler,
357 inputs.corner_normals_su);
365 inputs.transforms->surface_to_curves_normal);
369 MutableSpan<int8_t> types_span =
curves.curve_types_for_write();
371 curves.update_curve_types();
typedef float(TangentPoint)[2]
void mul_m3_v3(const float M[3][3], float r[3])
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
struct CurvesGeometry CurvesGeometry
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
const T & last(const int64_t n=0) const
IndexRange index_range() const
constexpr int64_t size() const
constexpr int64_t size() const
constexpr void fill(const T &value)
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr MutableSpan take_back(const int64_t n) const
constexpr void copy_from(Span< T > values)
constexpr IndexRange index_range() const
constexpr int64_t size() const
void append(const T &value)
Result sample(const float2 &query_uv) const
IconTextureDrawCall normal
ccl_gpu_kernel_postfix int ccl_global int * indices
typename DefaultMixerStruct< T >::type DefaultMixer
T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2)
int segments_num(const int points_num, const bool cyclic)
static Array< NeighborCurves > find_curve_neighbors(const Span< float3 > root_positions, const KDTree_3d &old_roots_kdtree)
float3 compute_surface_point_normal(const MLoopTri &looptri, const float3 &bary_coord, const Span< float3 > corner_normals)
AddCurvesOnMeshOutputs add_curves_on_mesh(bke::CurvesGeometry &curves, const AddCurvesOnMeshInputs &inputs)
static void interpolate_position_without_interpolation(CurvesGeometry &curves, const int old_curves_num, const Span< float3 > root_positions_cu, const Span< float > new_lengths_cu, const Span< float3 > new_normals_su, const float4x4 &surface_to_curves_normal_mat)
static void initialize_straight_curve_positions(const float3 &p1, const float3 &p2, MutableSpan< float3 > r_positions)
static void interpolate_position_with_interpolation(CurvesGeometry &curves, const Span< float3 > root_positions_cu, const Span< NeighborCurves > neighbors_per_curve, const int old_curves_num, const Span< float > new_lengths_cu, const Span< float3 > new_normals_su, const bke::CurvesSurfaceTransforms &transforms, const ReverseUVSampler &reverse_uv_sampler, const Span< float3 > corner_normals_su)
static constexpr int max_neighbors
void interpolate_from_neighbors(const Span< NeighborCurves > neighbors_per_curve, const T &fallback, const GetValueF &get_value_from_neighbor, MutableSpan< T > r_interpolated_values)
void sample_at_lengths(Span< float > accumulated_segment_lengths, Span< float > sample_lengths, MutableSpan< int > r_segment_indices, MutableSpan< float > r_factors)
void interpolate(const Span< T > src, const Span< int > indices, const Span< float > factors, MutableSpan< T > dst)
T length(const vec_base< T, Size > &a)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
T interpolate(const T &a, const T &b, const FactorT &t)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
static bNodeSocketTemplate outputs[]
static bNodeSocketTemplate inputs[]