Blender  V3.3
curves.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <cmath>
8 #include <cstring>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_curves_types.h"
13 #include "DNA_defaults.h"
14 #include "DNA_material_types.h"
15 #include "DNA_object_types.h"
16 
17 #include "BLI_bounds.hh"
18 #include "BLI_index_range.hh"
19 #include "BLI_listbase.h"
20 #include "BLI_math_base.h"
21 #include "BLI_math_vector.hh"
22 #include "BLI_rand.hh"
23 #include "BLI_span.hh"
24 #include "BLI_string.h"
25 #include "BLI_utildefines.h"
26 #include "BLI_vector.hh"
27 
28 #include "BKE_anim_data.h"
29 #include "BKE_curves.hh"
30 #include "BKE_customdata.h"
31 #include "BKE_geometry_set.hh"
32 #include "BKE_global.h"
33 #include "BKE_idtype.h"
34 #include "BKE_lib_id.h"
35 #include "BKE_lib_query.h"
36 #include "BKE_lib_remap.h"
37 #include "BKE_main.h"
38 #include "BKE_modifier.h"
39 #include "BKE_object.h"
40 
41 #include "BLT_translation.h"
42 
43 #include "DEG_depsgraph_query.h"
44 
45 #include "BLO_read_write.h"
46 
47 using blender::float3;
51 using blender::Span;
52 using blender::Vector;
53 
54 static const char *ATTR_POSITION = "position";
55 
56 static void curves_init_data(ID *id)
57 {
58  Curves *curves = (Curves *)id;
60 
62 
63  new (&curves->geometry) blender::bke::CurvesGeometry();
64 }
65 
66 static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
67 {
68  using namespace blender;
69 
70  Curves *curves_dst = (Curves *)id_dst;
71  const Curves *curves_src = (const Curves *)id_src;
72  curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
73 
76 
77  /* We need special handling here because the generic ID management code has already done a
78  * shallow copy from the source to the destination, and because the copy-on-write functionality
79  * isn't supported more generically yet. */
80 
81  dst.point_num = src.point_num;
82  dst.curve_num = src.curve_num;
83 
84  const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
85  CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, alloc_type, dst.point_num);
86  CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, alloc_type, dst.curve_num);
87 
88  dst.curve_offsets = static_cast<int *>(MEM_dupallocN(src.curve_offsets));
89 
90  if (curves_src->surface_uv_map != nullptr) {
91  curves_dst->surface_uv_map = BLI_strdup(curves_src->surface_uv_map);
92  }
93 
94  dst.runtime = MEM_new<bke::CurvesGeometryRuntime>(__func__);
95 
96  dst.runtime->type_counts = src.runtime->type_counts;
97 
98  curves_dst->batch_cache = nullptr;
99 }
100 
101 static void curves_free_data(ID *id)
102 {
103  Curves *curves = (Curves *)id;
104  BKE_animdata_free(&curves->id, false);
105 
107 
109 
110  MEM_SAFE_FREE(curves->mat);
111  MEM_SAFE_FREE(curves->surface_uv_map);
112 }
113 
115 {
116  Curves *curves = (Curves *)id;
117  for (int i = 0; i < curves->totcol; i++) {
119  }
121 }
122 
123 static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
124 {
125  Curves *curves = (Curves *)id;
126 
127  Vector<CustomDataLayer, 16> point_layers;
128  Vector<CustomDataLayer, 16> curve_layers;
129  CustomData_blend_write_prepare(curves->geometry.point_data, point_layers);
130  CustomData_blend_write_prepare(curves->geometry.curve_data, curve_layers);
131 
132  /* Write LibData */
133  BLO_write_id_struct(writer, Curves, id_address, &curves->id);
134  BKE_id_blend_write(writer, &curves->id);
135 
136  /* Direct data */
137  CustomData_blend_write(writer,
138  &curves->geometry.point_data,
139  point_layers,
140  curves->geometry.point_num,
141  CD_MASK_ALL,
142  &curves->id);
143  CustomData_blend_write(writer,
144  &curves->geometry.curve_data,
145  curve_layers,
146  curves->geometry.curve_num,
147  CD_MASK_ALL,
148  &curves->id);
149 
150  BLO_write_int32_array(writer, curves->geometry.curve_num + 1, curves->geometry.curve_offsets);
151 
152  BLO_write_string(writer, curves->surface_uv_map);
153 
154  BLO_write_pointer_array(writer, curves->totcol, curves->mat);
155  if (curves->adt) {
156  BKE_animdata_blend_write(writer, curves->adt);
157  }
158 }
159 
160 static void curves_blend_read_data(BlendDataReader *reader, ID *id)
161 {
162  Curves *curves = (Curves *)id;
163  BLO_read_data_address(reader, &curves->adt);
164  BKE_animdata_blend_read_data(reader, curves->adt);
165 
166  /* Geometry */
167  CustomData_blend_read(reader, &curves->geometry.point_data, curves->geometry.point_num);
168  CustomData_blend_read(reader, &curves->geometry.curve_data, curves->geometry.curve_num);
169 
170  BLO_read_int32_array(reader, curves->geometry.curve_num + 1, &curves->geometry.curve_offsets);
171 
172  BLO_read_data_address(reader, &curves->surface_uv_map);
173 
174  curves->geometry.runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
175 
176  /* Recalculate curve type count cache that isn't saved in files. */
178 
179  /* Materials */
180  BLO_read_pointer_array(reader, (void **)&curves->mat);
181 }
182 
183 static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
184 {
185  Curves *curves = (Curves *)id;
186  for (int a = 0; a < curves->totcol; a++) {
187  BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]);
188  }
189  BLO_read_id_address(reader, curves->id.lib, &curves->surface);
190 }
191 
192 static void curves_blend_read_expand(BlendExpander *expander, ID *id)
193 {
194  Curves *curves = (Curves *)id;
195  for (int a = 0; a < curves->totcol; a++) {
196  BLO_expand(expander, curves->mat[a]);
197  }
198  BLO_expand(expander, curves->surface);
199 }
200 
202  /*id_code */ ID_CV,
203  /*id_filter */ FILTER_ID_CV,
204  /*main_listbase_index */ INDEX_ID_CV,
205  /*struct_size */ sizeof(Curves),
206  /*name */ "Curves",
207  /*name_plural */ "hair_curves",
208  /*translation_context */ BLT_I18NCONTEXT_ID_CURVES,
210  /*asset_type_info */ nullptr,
211 
212  /*init_data */ curves_init_data,
213  /*copy_data */ curves_copy_data,
214  /*free_data */ curves_free_data,
215  /*make_local */ nullptr,
216  /*foreach_id */ curves_foreach_id,
217  /*foreach_cache */ nullptr,
218  /*foreach_path */ nullptr,
219  /*owner_get */ nullptr,
220 
221  /*blend_write */ curves_blend_write,
222  /*blend_read_data */ curves_blend_read_data,
223  /*blend_read_lib */ curves_blend_read_lib,
224  /*blend_read_expand */ curves_blend_read_expand,
225 
226  /*blend_read_undo_preserve */ nullptr,
227 
228  /*lib_override_apply_post */ nullptr,
229 };
230 
231 void *BKE_curves_add(Main *bmain, const char *name)
232 {
233  Curves *curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, name));
234 
235  return curves;
236 }
237 
239 {
240  BLI_assert(ob->type == OB_CURVES);
241  const Curves *curves_id = static_cast<const Curves *>(ob->data);
242 
243  if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
244  return ob->runtime.bb;
245  }
246 
247  if (ob->runtime.bb == nullptr) {
248  ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
249 
251  curves_id->geometry);
252 
253  float3 min(FLT_MAX);
254  float3 max(-FLT_MAX);
255  if (!curves.bounds_min_max(min, max)) {
256  min = float3(-1);
257  max = float3(1);
258  }
259 
261  }
262 
263  return ob->runtime.bb;
264 }
265 
266 bool BKE_curves_customdata_required(const Curves *UNUSED(curves), const char *name)
267 {
268  return STREQ(name, ATTR_POSITION);
269 }
270 
271 Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
272 {
273  int flags = LIB_ID_COPY_LOCALIZE;
274 
275  if (reference) {
276  flags |= LIB_ID_COPY_CD_REFERENCE;
277  }
278 
279  Curves *result = (Curves *)BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, flags);
280  return result;
281 }
282 
284  struct Scene *scene,
285  Object *object,
286  GeometrySet &geometry_set)
287 {
288  /* Modifier evaluation modes. */
289  const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
290  const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
291  ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
292  const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
293 
295 
296  /* Get effective list of modifiers to execute. Some effects like shape keys
297  * are added as virtual modifiers before the user created modifiers. */
298  VirtualModifierData virtualModifierData;
299  ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
300 
301  /* Evaluate modifiers. */
302  for (; md; md = md->next) {
303  const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
304 
305  if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
306  continue;
307  }
308 
309  if (mti->modifyGeometrySet != nullptr) {
310  mti->modifyGeometrySet(md, &mectx, &geometry_set);
311  }
312  }
313 }
314 
316 {
317  /* Free any evaluated data and restore original data. */
319 
320  /* Evaluate modifiers. */
321  Curves *curves = static_cast<Curves *>(object->data);
324  if (object->mode == OB_MODE_SCULPT_CURVES) {
325  /* Try to propagate deformation data through modifier evaluation, so that sculpt mode can work
326  * on evaluated curves. */
327  GeometryComponentEditData &edit_component =
329  edit_component.curves_edit_hints_ = std::make_unique<blender::bke::CurvesEditHints>(
330  *static_cast<const Curves *>(DEG_get_original_object(object)->data));
331  }
332  curves_evaluate_modifiers(depsgraph, scene, object, geometry_set);
333 
334  /* Assign evaluated object. */
335  Curves *curves_eval = const_cast<Curves *>(geometry_set.get_curves_for_read());
336  if (curves_eval == nullptr) {
337  curves_eval = blender::bke::curves_new_nomain(0, 0);
338  BKE_object_eval_assign_data(object, &curves_eval->id, true);
339  }
340  else {
341  BKE_object_eval_assign_data(object, &curves_eval->id, false);
342  }
343  object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set));
344 }
345 
346 /* Draw Cache */
347 
350 
352 {
353  if (curves->batch_cache) {
355  }
356 }
357 
359 {
360  if (curves->batch_cache) {
362  }
363 }
364 
365 namespace blender::bke {
366 
367 Curves *curves_new_nomain(const int points_num, const int curves_num)
368 {
369  Curves *curves_id = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
371  curves.resize(points_num, curves_num);
372  return curves_id;
373 }
374 
375 Curves *curves_new_nomain_single(const int points_num, const CurveType type)
376 {
377  Curves *curves_id = curves_new_nomain(points_num, 1);
379  curves.offsets_for_write().last() = points_num;
380  curves.fill_curve_types(type);
381  return curves_id;
382 }
383 
385 {
386  Curves *curves_id = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
387  bke::CurvesGeometry::wrap(curves_id->geometry) = std::move(curves);
388  return curves_id;
389 }
390 
392 {
393  dst.flag = src.flag;
394  dst.attributes_active_index = src.attributes_active_index;
395  MEM_SAFE_FREE(dst.mat);
396  dst.mat = static_cast<Material **>(MEM_malloc_arrayN(src.totcol, sizeof(Material *), __func__));
397  dst.totcol = src.totcol;
398  MutableSpan(dst.mat, dst.totcol).copy_from(Span(src.mat, src.totcol));
399  dst.symmetry = src.symmetry;
400  dst.selection_domain = src.selection_domain;
401  dst.surface = src.surface;
403  if (src.surface_uv_map != nullptr) {
404  dst.surface_uv_map = BLI_strdup(src.surface_uv_map);
405  }
406 }
407 
409 {
410  this->curves_to_world = curves_ob.obmat;
411  this->world_to_curves = this->curves_to_world.inverted();
412 
413  if (surface_ob != nullptr) {
414  this->surface_to_world = surface_ob->obmat;
416  this->surface_to_curves = this->world_to_curves * this->surface_to_world;
417  this->curves_to_surface = this->world_to_surface * this->curves_to_world;
419  }
420 }
421 
423 {
424  const int point_num = this->curves_id_orig.geometry.point_num;
425  if (this->positions.has_value()) {
426  if (this->positions->size() != point_num) {
427  return false;
428  }
429  }
430  if (this->deform_mats.has_value()) {
431  if (this->deform_mats->size() != point_num) {
432  return false;
433  }
434  }
435  return true;
436 }
437 
438 } // namespace blender::bke
void BKE_animdata_free(struct ID *id, bool do_id_user)
Definition: anim_data.c:197
void BKE_animdata_blend_read_data(struct BlendDataReader *reader, struct AnimData *adt)
Definition: anim_data.c:1443
void BKE_animdata_blend_write(struct BlendWriter *writer, struct AnimData *adt)
Definition: anim_data.c:1421
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count)
Definition: customdata.cc:5215
eCDAllocType
@ CD_REFERENCE
@ CD_DUPLICATE
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition: BKE_idtype.h:39
@ LIB_ID_COPY_CD_REFERENCE
Definition: BKE_lib_id.h:156
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void * BKE_id_new_nomain(short type, const char *name)
Definition: lib_id.c:1173
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2008
void * BKE_id_new(struct Main *bmain, short type, const char *name)
Definition: lib_id.c:1159
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag)
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
void BKE_modifiers_clear_errors(struct Object *ob)
ModifierApplyFlag
Definition: BKE_modifier.h:113
@ MOD_APPLY_USECACHE
Definition: BKE_modifier.h:118
@ MOD_APPLY_RENDER
Definition: BKE_modifier.h:115
General operations, lookup, etc. for blender objects.
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3])
Definition: object.cc:3645
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.cc:1774
void BKE_object_eval_assign_data(struct Object *object, struct ID *data, bool is_owned)
Definition: object.cc:1745
#define BLI_assert(a)
Definition: BLI_assert.h:46
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define BLO_read_data_address(reader, ptr_p)
void BLO_write_int32_array(BlendWriter *writer, uint num, const int32_t *data_ptr)
Definition: writefile.c:1571
void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
Definition: readfile.c:5177
#define BLO_write_id_struct(writer, struct_name, id_address, id)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
Definition: writefile.c:1601
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_expand(expander, id)
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
Definition: readfile.c:5245
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr)
Definition: writefile.c:1591
#define BLT_I18NCONTEXT_ID_CURVES
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:46
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
struct Object * DEG_get_original_object(struct Object *object)
@ INDEX_ID_CV
Definition: DNA_ID.h:1029
#define FILTER_ID_CV
Definition: DNA_ID.h:930
@ ID_CV
Definition: DNA_ID_enums.h:81
CurveType
struct Curves Curves
#define CD_MASK_ALL
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ eModifierMode_Render
@ eModifierMode_Realtime
ModifierType
@ OB_MODE_SCULPT_CURVES
Object is a sort of wrapper for general info.
@ OB_CURVES
@ BOUNDBOX_DIRTY
_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 float3[3]
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
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
std::unique_ptr< blender::bke::CurvesEditHints > curves_edit_hints_
constexpr void copy_from(Span< T > values)
Definition: BLI_span.hh:707
std::optional< Array< float3 > > positions
Definition: BKE_curves.hh:434
std::optional< Array< float3x3 > > deform_mats
Definition: BKE_curves.hh:439
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
void BKE_curves_batch_cache_dirty_tag(Curves *curves, int mode)
Definition: curves.cc:351
static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
Definition: curves.cc:66
static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
Definition: curves.cc:183
void BKE_curves_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
Definition: curves.cc:315
static void curves_blend_read_data(BlendDataReader *reader, ID *id)
Definition: curves.cc:160
bool BKE_curves_customdata_required(const Curves *UNUSED(curves), const char *name)
Definition: curves.cc:266
BoundBox * BKE_curves_boundbox_get(Object *ob)
Definition: curves.cc:238
static const char * ATTR_POSITION
Definition: curves.cc:54
static void curves_init_data(ID *id)
Definition: curves.cc:56
static void curves_foreach_id(ID *id, LibraryForeachIDData *data)
Definition: curves.cc:114
static void curves_evaluate_modifiers(struct Depsgraph *depsgraph, struct Scene *scene, Object *object, GeometrySet &geometry_set)
Definition: curves.cc:283
void(* BKE_curves_batch_cache_free_cb)(Curves *curves)
Definition: curves.cc:349
void BKE_curves_batch_cache_free(Curves *curves)
Definition: curves.cc:358
Curves * BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
Definition: curves.cc:271
static void curves_blend_read_expand(BlendExpander *expander, ID *id)
Definition: curves.cc:192
static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: curves.cc:123
void(* BKE_curves_batch_cache_dirty_tag_cb)(Curves *curves, int mode)
Definition: curves.cc:348
void * BKE_curves_add(Main *bmain, const char *name)
Definition: curves.cc:231
IDTypeInfo IDType_ID_CV
Definition: curves.cc:201
static void curves_free_data(ID *id)
Definition: curves.cc:101
void CustomData_blend_write(BlendWriter *writer, CustomData *data, Span< CustomDataLayer > layers_to_write, int count, eCustomDataMask cddata_mask, ID *id)
Definition: customdata.cc:5108
void CustomData_blend_write_prepare(CustomData &data, Vector< CustomDataLayer, 16 > &layers_to_write)
Definition: customdata.cc:4253
Scene scene
const Depsgraph * depsgraph
SyclQueue void void * src
SyclQueue void void size_t num_bytes void
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
static unsigned a[3]
Definition: RandGen.cpp:78
void curves_copy_parameters(const Curves &src, Curves &dst)
Definition: curves.cc:391
Curves * curves_new_nomain_single(int points_num, CurveType type)
Definition: curves.cc:375
Curves * curves_new_nomain(int points_num, int curves_num)
Definition: curves.cc:367
vec_base< float, 3 > float3
#define min(a, b)
Definition: sort.c:35
CustomData point_data
CurvesGeometryRuntimeHandle * runtime
CustomData curve_data
CurvesGeometry geometry
char selection_domain
void * batch_cache
struct Object * surface
struct Material ** mat
short totcol
int attributes_active_index
char * surface_uv_map
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
static GeometrySet create_with_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Curves * get_curves_for_read() const
Definition: DNA_ID.h:368
Definition: BKE_main.h:121
struct ModifierData * next
void(* modifyGeometrySet)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct GeometrySet *geometry_set)
Definition: BKE_modifier.h:240
struct BoundBox * bb
Object_Runtime runtime
float obmat[4][4]
void * data
float4x4 inverted() const
float4x4 transposed() const
float max