Blender V5.0
MOD_cloth.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
10
11#include "BLI_utildefines.h"
12
13#include "BLI_listbase.h"
14
15#include "BLT_translation.hh"
16
17#include "DNA_cloth_types.h"
18#include "DNA_defaults.h"
19#include "DNA_key_types.h"
20#include "DNA_mesh_types.h"
22#include "DNA_object_types.h"
23#include "DNA_screen_types.h"
24
25#include "MEM_guardedalloc.h"
26
27#include "BKE_cloth.hh"
28#include "BKE_customdata.hh"
29#include "BKE_effect.h"
30#include "BKE_global.hh"
31#include "BKE_key.hh"
32#include "BKE_lib_id.hh"
33#include "BKE_lib_query.hh"
34#include "BKE_modifier.hh"
35#include "BKE_pointcache.h"
36
38#include "UI_resources.hh"
39
40#include "RNA_prototypes.hh"
41
44
45#include "MOD_ui_common.hh"
46
47static void init_data(ModifierData *md)
48{
50
52
56
57 clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
58
59 /* check for alloc failing */
60 if (!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache) {
61 return;
62 }
63
64 if (!clmd->sim_parms->effector_weights) {
66 }
67
68 if (clmd->point_cache) {
69 clmd->point_cache->step = 1;
70 }
71}
72
73static void deform_verts(ModifierData *md,
74 const ModifierEvalContext *ctx,
75 Mesh *mesh,
77{
80
81 /* check for alloc failing */
82 if (!clmd->sim_parms || !clmd->coll_parms) {
83 init_data(md);
84
85 if (!clmd->sim_parms || !clmd->coll_parms) {
86 return;
87 }
88 }
89
90 /* TODO(sergey): For now it actually duplicates logic from mesh_data_update.cc
91 * and needs some more generic solution. But starting experimenting with
92 * this so close to the release is not that nice..
93 *
94 * Also hopefully new cloth system will arrive soon..
95 */
96 if (mesh == nullptr && clmd->sim_parms->shapekey_rest) {
99 if (kb && kb->data != nullptr) {
100 float (*layerorco)[3] = static_cast<float (*)[3]>(
102 if (!layerorco) {
103 layerorco = static_cast<float (*)[3]>(CustomData_add_layer(
105 }
106
107 memcpy(layerorco, kb->data, sizeof(float[3]) * positions.size());
108 }
109 }
110
111 mesh->vert_positions_for_write().copy_from(positions);
112 mesh->tag_positions_changed();
113
114 clothModifier_do(clmd,
115 ctx->depsgraph,
116 scene,
117 ctx->object,
118 mesh,
119 reinterpret_cast<float (*)[3]>(positions.data()));
120}
121
123{
125 if (clmd != nullptr) {
128 ctx->object,
129 clmd->coll_parms->group,
131 nullptr,
132 "Cloth Collision");
133 }
135 ctx->node, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
136 }
137 DEG_add_depends_on_transform_relation(ctx->node, "Cloth Modifier");
138}
139
140static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
141{
143
144 if (cloth_uses_vgroup(clmd)) {
145 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
146 }
147
148 if (clmd->sim_parms->shapekey_rest != 0) {
149 r_cddata_masks->vmask |= CD_MASK_CLOTH_ORCO;
150 }
151}
152
153static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
154{
155 const ClothModifierData *clmd = (const ClothModifierData *)md;
156 ClothModifierData *tclmd = (ClothModifierData *)target;
157
158 if (tclmd->sim_parms) {
159 if (tclmd->sim_parms->effector_weights) {
161 }
162 MEM_freeN(tclmd->sim_parms);
163 }
164
165 if (tclmd->coll_parms) {
166 MEM_freeN(tclmd->coll_parms);
167 }
168
171 /* Share the cache with the original object's modifier. */
173 tclmd->ptcaches = clmd->ptcaches;
174 tclmd->point_cache = clmd->point_cache;
175 }
176 else {
177 const int clmd_point_cache_index = BLI_findindex(&clmd->ptcaches, clmd->point_cache);
179 tclmd->point_cache = static_cast<PointCache *>(
180 BLI_findlink(&tclmd->ptcaches, clmd_point_cache_index));
181 }
182
183 tclmd->sim_parms = static_cast<ClothSimSettings *>(MEM_dupallocN(clmd->sim_parms));
184 if (clmd->sim_parms->effector_weights) {
185 tclmd->sim_parms->effector_weights = static_cast<EffectorWeights *>(
187 }
188 tclmd->coll_parms = static_cast<ClothCollSettings *>(MEM_dupallocN(clmd->coll_parms));
189 tclmd->clothObject = nullptr;
190 tclmd->hairdata = nullptr;
191 tclmd->solver_result = nullptr;
192}
193
194static bool depends_on_time(Scene * /*scene*/, ModifierData * /*md*/)
195{
196 return true;
197}
198
199static void free_data(ModifierData *md)
200{
202
203 if (clmd) {
204 if (G.debug & G_DEBUG_SIMDATA) {
205 printf("clothModifier_freeData\n");
206 }
207
209
210 if (clmd->sim_parms) {
211 if (clmd->sim_parms->effector_weights) {
213 }
214 MEM_freeN(clmd->sim_parms);
215 }
216 if (clmd->coll_parms) {
217 MEM_freeN(clmd->coll_parms);
218 }
219
222 }
223 else {
225 }
226 clmd->point_cache = nullptr;
227
228 if (clmd->hairdata) {
229 MEM_freeN(clmd->hairdata);
230 }
231
232 if (clmd->solver_result) {
234 }
235 }
236}
237
238static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
239{
241
242 if (clmd->coll_parms) {
243 walk(user_data, ob, (ID **)&clmd->coll_parms->group, IDWALK_CB_NOP);
244 }
245
246 if (clmd->sim_parms && clmd->sim_parms->effector_weights) {
247 walk(user_data, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_USER);
248 }
249}
250
251static void panel_draw(const bContext * /*C*/, Panel *panel)
252{
253 uiLayout *layout = panel->layout;
254
256
257 layout->label(RPT_("Settings are inside the Physics tab"), ICON_NONE);
258
260}
261
262static void panel_register(ARegionType *region_type)
263{
265}
266
268 /*idname*/ "Cloth",
269 /*name*/ N_("Cloth"),
270 /*struct_name*/ "ClothModifierData",
271 /*struct_size*/ sizeof(ClothModifierData),
272 /*srna*/ &RNA_ClothModifier,
276 /*icon*/ ICON_MOD_CLOTH,
277
278 /*copy_data*/ copy_data,
279
280 /*deform_verts*/ deform_verts,
281 /*deform_matrices*/ nullptr,
282 /*deform_verts_EM*/ nullptr,
283 /*deform_matrices_EM*/ nullptr,
284 /*modify_mesh*/ nullptr,
285 /*modify_geometry_set*/ nullptr,
286
287 /*init_data*/ init_data,
288 /*required_data_mask*/ required_data_mask,
289 /*free_data*/ free_data,
290 /*is_disabled*/ nullptr,
291 /*update_depsgraph*/ update_depsgraph,
292 /*depends_on_time*/ depends_on_time,
293 /*depends_on_normals*/ nullptr,
294 /*foreach_ID_link*/ foreach_ID_link,
295 /*foreach_tex_link*/ nullptr,
296 /*free_runtime_data*/ nullptr,
297 /*panel_register*/ panel_register,
298 /*blend_write*/ nullptr,
299 /*blend_read*/ nullptr,
300 /*foreach_cache*/ nullptr,
301 /*foreach_working_space_color*/ nullptr,
302};
void cloth_free_modifier_extern(ClothModifierData *clmd)
Definition cloth.cc:493
void clothModifier_do(ClothModifierData *clmd, Depsgraph *depsgraph, Scene *scene, Object *ob, const Mesh *mesh, float(*vertexCos)[3])
Definition cloth.cc:320
int cloth_uses_vgroup(ClothModifierData *clmd)
Definition cloth.cc:586
CustomData interface, see also DNA_customdata_types.h.
@ CD_SET_DEFAULT
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:58
@ G_DEBUG_SIMDATA
KeyBlock * BKE_keyblock_find_by_index(Key *key, int index)
Definition key.cc:1907
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1791
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
@ eModifierTypeFlag_Single
@ eModifierTypeFlag_UsesPointCache
@ eModifierTypeFlag_AcceptsMesh
struct PointCache * BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, int flag)
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
void BKE_ptcache_free_list(struct ListBase *ptcaches)
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define RPT_(msgid)
void DEG_add_depends_on_transform_relation(DepsNodeHandle *node_handle, const char *description)
void DEG_add_collision_relations(DepsNodeHandle *handle, Object *object, Collection *collection, unsigned int modifier_type, DEG_CollobjFilterFunction filter_function, const char *name)
void DEG_add_forcefield_relations(DepsNodeHandle *handle, Object *object, EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ CLOTH_COLLSETTINGS_FLAG_ENABLED
#define CD_MASK_MDEFORMVERT
@ CD_CLOTH_ORCO
#define CD_MASK_CLOTH_ORCO
#define DNA_struct_default_get(struct_name)
#define DNA_struct_default_alloc(struct_name)
@ eModifierFlag_SharedCaches
@ eModifierType_Cloth
@ eModifierType_Collision
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static void deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
static void panel_register(ARegionType *region_type)
static void required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:272
static bool depends_on_time(Scene *, ModifierData *)
Definition MOD_build.cc:47
static void init_data(ModifierData *md)
Definition MOD_cloth.cc:47
static void deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
Definition MOD_cloth.cc:73
static void panel_register(ARegionType *region_type)
Definition MOD_cloth.cc:262
static void free_data(ModifierData *md)
Definition MOD_cloth.cc:199
static void panel_draw(const bContext *, Panel *panel)
Definition MOD_cloth.cc:251
static bool depends_on_time(Scene *, ModifierData *)
Definition MOD_cloth.cc:194
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Definition MOD_cloth.cc:140
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
Definition MOD_cloth.cc:238
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
Definition MOD_cloth.cc:122
ModifierTypeInfo modifierType_Cloth
Definition MOD_cloth.cc:267
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
Definition MOD_cloth.cc:153
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr T * data() const
Definition BLI_span.hh:539
nullptr float
#define printf(...)
static void update_depsgraph(tGraphSliderOp *gso)
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
struct Collection * group
struct ListBase ptcaches
struct ClothSolverResult * solver_result
struct ClothHairData * hairdata
struct Cloth * clothObject
struct PointCache * point_cache
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct EffectorWeights * effector_weights
struct Collection * group
Definition DNA_ID.h:414
void * data
CustomData vert_data
int verts_num
struct uiLayout * layout
void label(blender::StringRef name, int icon)
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145