Blender  V3.3
curves_sculpt_brush.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <algorithm>
4 
6 
7 #include "BKE_attribute_math.hh"
8 #include "BKE_bvhutils.h"
9 #include "BKE_context.h"
10 #include "BKE_curves.hh"
11 #include "BKE_modifier.h"
12 #include "BKE_object.h"
13 #include "BKE_report.h"
14 
15 #include "ED_view3d.h"
16 
17 #include "UI_interface.h"
18 
19 #include "DNA_mesh_types.h"
20 #include "DNA_meshdata_types.h"
21 
24 #include "BLI_task.hh"
25 
26 #include "DEG_depsgraph_query.h"
27 
28 #include "BLT_translation.h"
29 
38 namespace blender::ed::sculpt_paint {
39 
44  float distance_sq_re = FLT_MAX;
46  float depth_sq_cu = FLT_MAX;
47 };
48 
52 static std::optional<float3> find_curves_brush_position(const CurvesGeometry &curves,
53  const float3 &ray_start_cu,
54  const float3 &ray_end_cu,
55  const float brush_radius_re,
56  const ARegion &region,
57  const RegionView3D &rv3d,
58  const Object &object,
59  const Span<float3> positions)
60 {
61  /* This value might have to be adjusted based on user feedback. */
62  const float brush_inner_radius_re = std::min<float>(brush_radius_re, (float)UI_UNIT_X / 3.0f);
63  const float brush_inner_radius_sq_re = pow2f(brush_inner_radius_re);
64 
65  float4x4 projection;
66  ED_view3d_ob_project_mat_get(&rv3d, &object, projection.values);
67 
68  float2 brush_pos_re;
69  ED_view3d_project_float_v2_m4(&region, ray_start_cu, brush_pos_re, projection.values);
70 
71  const float max_depth_sq_cu = math::distance_squared(ray_start_cu, ray_end_cu);
72 
73  /* Contains the logic that checks if `b` is a better candidate than `a`. */
74  auto is_better_candidate = [&](const BrushPositionCandidate &a,
75  const BrushPositionCandidate &b) {
76  if (b.distance_sq_re <= brush_inner_radius_sq_re) {
77  if (a.distance_sq_re > brush_inner_radius_sq_re) {
78  /* New candidate is in inner radius while old one is not. */
79  return true;
80  }
81  if (b.depth_sq_cu < a.depth_sq_cu) {
82  /* Both candidates are in inner radius, but new one is closer to the camera. */
83  return true;
84  }
85  }
86  else if (b.distance_sq_re < a.distance_sq_re) {
87  /* Both candidates are outside of inner radius, but new on is closer to the brush center. */
88  return true;
89  }
90  return false;
91  };
92 
93  auto update_if_better = [&](BrushPositionCandidate &a, const BrushPositionCandidate &b) {
94  if (is_better_candidate(a, b)) {
95  a = b;
96  }
97  };
98 
100  curves.curves_range(),
101  128,
103  [&](IndexRange curves_range, const BrushPositionCandidate &init) {
104  BrushPositionCandidate best_candidate = init;
105 
106  for (const int curve_i : curves_range) {
107  const IndexRange points = curves.points_for_curve(curve_i);
108 
109  if (points.size() == 1) {
110  const float3 &pos_cu = positions[points.first()];
111 
112  const float depth_sq_cu = math::distance_squared(ray_start_cu, pos_cu);
113  if (depth_sq_cu > max_depth_sq_cu) {
114  continue;
115  }
116 
117  float2 pos_re;
118  ED_view3d_project_float_v2_m4(&region, pos_cu, pos_re, projection.values);
119 
120  BrushPositionCandidate candidate;
121  candidate.position_cu = pos_cu;
122  candidate.depth_sq_cu = depth_sq_cu;
123  candidate.distance_sq_re = math::distance_squared(brush_pos_re, pos_re);
124 
125  update_if_better(best_candidate, candidate);
126  continue;
127  }
128 
129  for (const int segment_i : points.drop_back(1)) {
130  const float3 &p1_cu = positions[segment_i];
131  const float3 &p2_cu = positions[segment_i + 1];
132 
133  float2 p1_re, p2_re;
134  ED_view3d_project_float_v2_m4(&region, p1_cu, p1_re, projection.values);
135  ED_view3d_project_float_v2_m4(&region, p2_cu, p2_re, projection.values);
136 
137  float2 closest_re;
138  const float lambda = closest_to_line_segment_v2(
139  closest_re, brush_pos_re, p1_re, p2_re);
140 
141  const float3 closest_cu = math::interpolate(p1_cu, p2_cu, lambda);
142  const float depth_sq_cu = math::distance_squared(ray_start_cu, closest_cu);
143  if (depth_sq_cu > max_depth_sq_cu) {
144  continue;
145  }
146 
147  const float distance_sq_re = math::distance_squared(brush_pos_re, closest_re);
148 
149  float3 brush_position_cu;
150  closest_to_line_segment_v3(brush_position_cu, closest_cu, ray_start_cu, ray_end_cu);
151 
152  BrushPositionCandidate candidate;
153  candidate.position_cu = brush_position_cu;
154  candidate.depth_sq_cu = depth_sq_cu;
155  candidate.distance_sq_re = distance_sq_re;
156 
157  update_if_better(best_candidate, candidate);
158  }
159  }
160  return best_candidate;
161  },
162  [&](const BrushPositionCandidate &a, const BrushPositionCandidate &b) {
163  return is_better_candidate(a, b) ? b : a;
164  });
165 
166  if (best_candidate.distance_sq_re == FLT_MAX) {
167  /* Nothing found. */
168  return std::nullopt;
169  }
170 
171  return best_candidate.position_cu;
172 }
173 
174 std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
175  const ARegion &region,
176  const View3D &v3d,
177  const RegionView3D &rv3d,
178  const Object &curves_object,
179  const float2 &brush_pos_re,
180  const float brush_radius_re)
181 {
182  const Curves &curves_id = *static_cast<Curves *>(curves_object.data);
184  Object *surface_object = curves_id.surface;
185  Object *surface_object_eval = DEG_get_evaluated_object(&depsgraph, surface_object);
186 
187  float3 center_ray_start_wo, center_ray_end_wo;
189  &depsgraph, &region, &v3d, brush_pos_re, center_ray_start_wo, center_ray_end_wo, true);
190 
191  /* Shorten ray when the surface object is hit. */
192  if (surface_object_eval != nullptr) {
193  const float4x4 surface_to_world_mat = surface_object->obmat;
194  const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
195 
196  Mesh *surface_eval = BKE_object_get_evaluated_mesh(surface_object_eval);
197  BVHTreeFromMesh surface_bvh;
198  BKE_bvhtree_from_mesh_get(&surface_bvh, surface_eval, BVHTREE_FROM_LOOPTRI, 2);
199  BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); });
200 
201  const float3 center_ray_start_su = world_to_surface_mat * center_ray_start_wo;
202  float3 center_ray_end_su = world_to_surface_mat * center_ray_end_wo;
203  const float3 center_ray_direction_su = math::normalize(center_ray_end_su -
204  center_ray_start_su);
205 
206  BVHTreeRayHit center_ray_hit;
207  center_ray_hit.dist = FLT_MAX;
208  center_ray_hit.index = -1;
209  BLI_bvhtree_ray_cast(surface_bvh.tree,
210  center_ray_start_su,
211  center_ray_direction_su,
212  0.0f,
213  &center_ray_hit,
214  surface_bvh.raycast_callback,
215  &surface_bvh);
216  if (center_ray_hit.index >= 0) {
217  const float3 hit_position_su = center_ray_hit.co;
218  if (math::distance(center_ray_start_su, center_ray_end_su) >
219  math::distance(center_ray_start_su, hit_position_su)) {
220  center_ray_end_su = hit_position_su;
221  center_ray_end_wo = surface_to_world_mat * center_ray_end_su;
222  }
223  }
224  }
225 
226  const float4x4 curves_to_world_mat = curves_object.obmat;
227  const float4x4 world_to_curves_mat = curves_to_world_mat.inverted();
228 
229  const float3 center_ray_start_cu = world_to_curves_mat * center_ray_start_wo;
230  const float3 center_ray_end_cu = world_to_curves_mat * center_ray_end_wo;
231 
232  const bke::crazyspace::GeometryDeformation deformation =
234 
235  const std::optional<float3> brush_position_optional_cu = find_curves_brush_position(
236  curves,
237  center_ray_start_cu,
238  center_ray_end_cu,
239  brush_radius_re,
240  region,
241  rv3d,
242  curves_object,
243  deformation.positions);
244  if (!brush_position_optional_cu.has_value()) {
245  /* Nothing found. */
246  return std::nullopt;
247  }
248  const float3 brush_position_cu = *brush_position_optional_cu;
249 
250  /* Determine the 3D brush radius. */
251  float3 radius_ray_start_wo, radius_ray_end_wo;
253  &region,
254  &v3d,
255  brush_pos_re + float2(brush_radius_re, 0.0f),
256  radius_ray_start_wo,
257  radius_ray_end_wo,
258  true);
259  const float3 radius_ray_start_cu = world_to_curves_mat * radius_ray_start_wo;
260  const float3 radius_ray_end_cu = world_to_curves_mat * radius_ray_end_wo;
261 
262  CurvesBrush3D brush_3d;
263  brush_3d.position_cu = brush_position_cu;
264  brush_3d.radius_cu = dist_to_line_v3(brush_position_cu, radius_ray_start_cu, radius_ray_end_cu);
265  return brush_3d;
266 }
267 
268 std::optional<CurvesBrush3D> sample_curves_surface_3d_brush(
269  const Depsgraph &depsgraph,
270  const ARegion &region,
271  const View3D &v3d,
272  const CurvesSurfaceTransforms &transforms,
273  const BVHTreeFromMesh &surface_bvh,
274  const float2 &brush_pos_re,
275  const float brush_radius_re)
276 {
277  float3 brush_ray_start_wo, brush_ray_end_wo;
279  &depsgraph, &region, &v3d, brush_pos_re, brush_ray_start_wo, brush_ray_end_wo, true);
280  const float3 brush_ray_start_su = transforms.world_to_surface * brush_ray_start_wo;
281  const float3 brush_ray_end_su = transforms.world_to_surface * brush_ray_end_wo;
282 
283  const float3 brush_ray_direction_su = math::normalize(brush_ray_end_su - brush_ray_start_su);
284 
285  BVHTreeRayHit ray_hit;
286  ray_hit.dist = FLT_MAX;
287  ray_hit.index = -1;
288  BLI_bvhtree_ray_cast(surface_bvh.tree,
289  brush_ray_start_su,
290  brush_ray_direction_su,
291  0.0f,
292  &ray_hit,
293  surface_bvh.raycast_callback,
294  const_cast<void *>(static_cast<const void *>(&surface_bvh)));
295  if (ray_hit.index == -1) {
296  return std::nullopt;
297  }
298 
299  float3 brush_radius_ray_start_wo, brush_radius_ray_end_wo;
301  &region,
302  &v3d,
303  brush_pos_re + float2(brush_radius_re, 0),
304  brush_radius_ray_start_wo,
305  brush_radius_ray_end_wo,
306  true);
307  const float3 brush_radius_ray_start_cu = transforms.world_to_curves * brush_radius_ray_start_wo;
308  const float3 brush_radius_ray_end_cu = transforms.world_to_curves * brush_radius_ray_end_wo;
309 
310  const float3 brush_pos_su = ray_hit.co;
311  const float3 brush_pos_cu = transforms.surface_to_curves * brush_pos_su;
312  const float brush_radius_cu = dist_to_line_v3(
313  brush_pos_cu, brush_radius_ray_start_cu, brush_radius_ray_end_cu);
314  return CurvesBrush3D{brush_pos_cu, brush_radius_cu};
315 }
316 
318 {
319  Vector<float4x4> matrices;
320 
321  auto symmetry_to_factors = [&](const eCurvesSymmetryType type) -> Span<float> {
322  if (symmetry & type) {
323  static std::array<float, 2> values = {1.0f, -1.0f};
324  return values;
325  }
326  static std::array<float, 1> values = {1.0f};
327  return values;
328  };
329 
330  for (const float x : symmetry_to_factors(CURVES_SYMMETRY_X)) {
331  for (const float y : symmetry_to_factors(CURVES_SYMMETRY_Y)) {
332  for (const float z : symmetry_to_factors(CURVES_SYMMETRY_Z)) {
333  float4x4 matrix = float4x4::identity();
334  matrix.values[0][0] = x;
335  matrix.values[1][1] = y;
336  matrix.values[2][2] = z;
337  matrices.append(matrix);
338  }
339  }
340  }
341 
342  return matrices;
343 }
344 
346  const float3 &brush_position,
347  const float old_radius)
348 {
349  const float3 offset_position = brush_position + float3(old_radius, 0.0f, 0.0f);
350  const float3 new_position = transform * brush_position;
351  const float3 new_offset_position = transform * offset_position;
352  return math::distance(new_position, new_offset_position);
353 }
354 
356 {
357  /* Find the accumulated length of each point in the original curve,
358  * treating it as a poly curve for performance reasons and simplicity. */
359  Array<float> orig_lengths(length_parameterize::segments_num(positions.size(), false));
360  length_parameterize::accumulate_lengths<float3>(positions, false, orig_lengths);
361  const float orig_total_length = orig_lengths.last();
362 
363  /* Find the factor by which the new curve is shorter or longer than the original. */
364  const float new_last_segment_length = math::distance(positions.last(1), new_last_position);
365  const float new_total_length = orig_lengths.last(1) + new_last_segment_length;
366  const float length_factor = safe_divide(new_total_length, orig_total_length);
367 
368  /* Calculate the lengths to sample the original curve with by scaling the original lengths. */
369  Array<float> new_lengths(positions.size() - 1);
370  new_lengths.first() = 0.0f;
371  for (const int i : new_lengths.index_range().drop_front(1)) {
372  new_lengths[i] = orig_lengths[i - 1] * length_factor;
373  }
374 
375  Array<int> indices(positions.size() - 1);
376  Array<float> factors(positions.size() - 1);
377  length_parameterize::sample_at_lengths(orig_lengths, new_lengths, indices, factors);
378 
379  Array<float3> new_positions(positions.size() - 1);
380  length_parameterize::interpolate<float3>(positions, indices, factors, new_positions);
381  positions.drop_back(1).copy_from(new_positions);
382  positions.last() = new_last_position;
383 }
384 
385 CurvesSculptCommonContext::CurvesSculptCommonContext(const bContext &C)
386 {
388  this->scene = CTX_data_scene(&C);
389  this->region = CTX_wm_region(&C);
390  this->v3d = CTX_wm_view3d(&C);
391  this->rv3d = CTX_wm_region_view3d(&C);
392 }
393 
395 {
396  BKE_report(reports, RPT_WARNING, TIP_("Original surface mesh is empty"));
397 }
398 
400 {
401  BKE_report(reports, RPT_WARNING, TIP_("Evaluated surface mesh is empty"));
402 }
403 
405 {
406  BKE_report(reports, RPT_WARNING, TIP_("Missing surface mesh"));
407 }
408 
410 {
411  BKE_report(
412  reports, RPT_WARNING, TIP_("Missing UV map for attaching curves on original surface"));
413 }
414 
416 {
417  BKE_report(
418  reports, RPT_WARNING, TIP_("Missing UV map for attaching curves on evaluated surface"));
419 }
420 
422 {
423  BKE_report(reports, RPT_WARNING, TIP_("Invalid UV map: UV islands must not overlap"));
424 }
425 
426 } // namespace blender::ed::sculpt_paint
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.cc:1410
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:73
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition: bvhutils.cc:1213
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
Low-level operations for curves.
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1942
MINLINE float pow2f(float x)
float closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:379
float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:507
#define BLI_SCOPED_DEFER(function_to_defer)
#define TIP_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
eCurvesSymmetryType
@ CURVES_SYMMETRY_Y
@ CURVES_SYMMETRY_Z
@ CURVES_SYMMETRY_X
bool ED_view3d_win_to_segment_clipped(const struct Depsgraph *depsgraph, const struct ARegion *region, const struct View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], bool do_clip_planes)
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, const struct Object *ob, float r_pmat[4][4])
void ED_view3d_project_float_v2_m4(const struct ARegion *region, const float co[3], float r_co[2], const float mat[4][4])
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
float float2[2]
float float3[3]
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
#define C
Definition: RandGen.cpp:25
#define UI_UNIT_X
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
const T & first() const
Definition: BLI_array.hh:269
const T & last(const int64_t n=0) const
Definition: BLI_array.hh:284
IndexRange index_range() const
Definition: BLI_array.hh:348
constexpr int64_t size() const
constexpr IndexRange drop_front(int64_t n) const
void append(const T &value)
Definition: BLI_vector.hh:433
Scene scene
const Depsgraph * depsgraph
ccl_gpu_kernel_postfix int ccl_global int * indices
static unsigned a[3]
Definition: RandGen.cpp:78
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
Definition: crazyspace.cc:595
int segments_num(const int points_num, const bool cyclic)
Definition: BKE_curves.hh:462
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
std::optional< CurvesBrush3D > sample_curves_surface_3d_brush(const Depsgraph &depsgraph, const ARegion &region, const View3D &v3d, const CurvesSurfaceTransforms &transforms, const BVHTreeFromMesh &surface_bvh, const float2 &brush_pos_re, const float brush_radius_re)
void report_invalid_uv_map(ReportList *reports)
void report_empty_evaluated_surface(ReportList *reports)
static std::optional< float3 > find_curves_brush_position(const CurvesGeometry &curves, const float3 &ray_start_cu, const float3 &ray_end_cu, const float brush_radius_re, const ARegion &region, const RegionView3D &rv3d, const Object &object, const Span< float3 > positions)
std::optional< CurvesBrush3D > sample_curves_3d_brush(const Depsgraph &depsgraph, const ARegion &region, const View3D &v3d, const RegionView3D &rv3d, const Object &curves_object, const float2 &brush_pos_re, const float brush_radius_re)
void move_last_point_and_resample(MutableSpan< float3 > positions, const float3 &new_last_position)
void report_missing_uv_map_on_original_surface(ReportList *reports)
void report_missing_uv_map_on_evaluated_surface(ReportList *reports)
void report_missing_surface(ReportList *reports)
void report_empty_original_surface(ReportList *reports)
Vector< float4x4 > get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
float transform_brush_radius(const float4x4 &transform, const float3 &brush_position, const float old_radius)
void sample_at_lengths(Span< float > accumulated_segment_lengths, Span< float > sample_lengths, MutableSpan< int > r_segment_indices, MutableSpan< float > r_factors)
T distance_squared(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T distance(const T &a, const T &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
T safe_divide(const T &a, const T &b)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition: BLI_task.hh:73
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
BVHTree_RayCastCallback raycast_callback
Definition: BKE_bvhutils.h:54
struct BVHTree * tree
Definition: BKE_bvhutils.h:50
float co[3]
Definition: BLI_kdopbvh.h:68
CurvesGeometry geometry
struct Object * surface
float obmat[4][4]
void * data
float values[4][4]
Definition: BLI_float4x4.hh:13
float4x4 inverted() const