Blender  V2.93
MOD_particlesystem.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <stddef.h>
25 #include <string.h>
26 
27 #include "BLI_utildefines.h"
28 
29 #include "BLT_translation.h"
30 
31 #include "DNA_defaults.h"
32 #include "DNA_material_types.h"
33 #include "DNA_mesh_types.h"
34 #include "DNA_screen_types.h"
35 
36 #include "BKE_context.h"
37 #include "BKE_editmesh.h"
38 #include "BKE_lib_id.h"
39 #include "BKE_mesh.h"
40 #include "BKE_modifier.h"
41 #include "BKE_particle.h"
42 #include "BKE_screen.h"
43 
44 #include "UI_interface.h"
45 #include "UI_resources.h"
46 
47 #include "RNA_access.h"
48 
49 #include "DEG_depsgraph_query.h"
50 
51 #include "BLO_read_write.h"
52 
53 #include "MOD_ui_common.h"
54 #include "MOD_util.h"
55 
56 static void initData(ModifierData *md)
57 {
59 
60  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(psmd, modifier));
61 
63 }
64 static void freeData(ModifierData *md)
65 {
67 
68  if (psmd->mesh_final) {
69  BKE_id_free(NULL, psmd->mesh_final);
70  psmd->mesh_final = NULL;
71  if (psmd->mesh_original) {
73  psmd->mesh_original = NULL;
74  }
75  }
76  psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
77 
78  /* ED_object_modifier_remove may have freed this first before calling
79  * BKE_modifier_free (which calls this function) */
80  if (psmd->psys) {
81  psmd->psys->flag |= PSYS_DELETE;
82  }
83 }
84 
85 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
86 {
87 #if 0
89 #endif
91 
92  BKE_modifier_copydata_generic(md, target, flag);
93 
94  /* NOTE: `psys` pointer here is just copied over from `md` to `target`. This is dangerous, as it
95  * will generate invalid data in case we are copying between different objects. Extra external
96  * code has to be called then to ensure proper remapping of that pointer. See e.g.
97  * `BKE_object_copy_particlesystems` or `BKE_object_copy_modifier`. */
98 
99  tpsmd->mesh_final = NULL;
100  tpsmd->mesh_original = NULL;
101  tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
102 }
103 
104 static void requiredDataMask(Object *UNUSED(ob),
105  ModifierData *md,
106  CustomData_MeshMasks *r_cddata_masks)
107 {
109 
110  psys_emitter_customdata_mask(psmd->psys, r_cddata_masks);
111 }
112 
113 /* saves the current emitter state for a particle system and calculates particles */
114 static void deformVerts(ModifierData *md,
115  const ModifierEvalContext *ctx,
116  Mesh *mesh,
117  float (*vertexCos)[3],
118  int numVerts)
119 {
120  Mesh *mesh_src = mesh;
122  ParticleSystem *psys = NULL;
123  /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */
124 
125  if (ctx->object->particlesystem.first) {
126  psys = psmd->psys;
127  }
128  else {
129  return;
130  }
131 
132  if (!psys_check_enabled(ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0)) {
133  return;
134  }
135 
136  if (mesh_src == NULL) {
137  mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, vertexCos, numVerts, false, true);
138  if (mesh_src == NULL) {
139  return;
140  }
141  }
142 
143  /* clear old dm */
144  bool had_mesh_final = (psmd->mesh_final != NULL);
145  if (psmd->mesh_final) {
146  BKE_id_free(NULL, psmd->mesh_final);
147  psmd->mesh_final = NULL;
148  if (psmd->mesh_original) {
150  psmd->mesh_original = NULL;
151  }
152  }
153  else if (psmd->flag & eParticleSystemFlag_file_loaded) {
154  /* in file read mesh just wasn't saved in file so no need to reset everything */
156  if (psys->particles == NULL) {
157  psys->recalc |= ID_RECALC_PSYS_RESET;
158  }
159  /* TODO(sergey): This is not how particles were working prior to copy on
160  * write, but now evaluation is similar to case when one duplicates the
161  * object. In that case particles were doing reset here.
162  *
163  * Don't do reset when entering particle edit mode, as that will destroy the edit mode data.
164  * Shouldn't be an issue, since particles are supposed to be evaluated once prior to entering
165  * edit mode anyway.
166  * Could in theory be an issue when everything is done in a script, but then solution is
167  * not known to me. */
168  if (ctx->object->mode != OB_MODE_PARTICLE_EDIT) {
169  psys->recalc |= ID_RECALC_PSYS_RESET;
170  }
171  }
172 
173  /* make new mesh */
174  psmd->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false);
175  BKE_mesh_vert_coords_apply(psmd->mesh_final, vertexCos);
177 
179 
180  if (!psmd->mesh_final->runtime.deformed_only) {
181  /* Get the original mesh from the object, this is what the particles
182  * are attached to so in case of non-deform modifiers we need to remap
183  * them to the final mesh (typically subdivision surfaces). */
184  Mesh *mesh_original = NULL;
185 
186  if (ctx->object->type == OB_MESH) {
188 
189  if (em) {
190  /* In edit mode get directly from the edit mesh. */
192  }
193  else {
194  /* Otherwise get regular mesh. */
195  mesh_original = ctx->object->data;
196  }
197  }
198  else {
199  mesh_original = mesh_src;
200  }
201 
202  if (mesh_original) {
203  /* Make a persistent copy of the mesh. We don't actually need
204  * all this data, just some topology for remapping. Could be
205  * optimized once. */
206  psmd->mesh_original = BKE_mesh_copy_for_eval(mesh_original, false);
207  }
208 
210  }
211 
212  if (!ELEM(mesh_src, NULL, mesh, psmd->mesh_final)) {
213  BKE_id_free(NULL, mesh_src);
214  }
215 
216  /* Report change in mesh structure.
217  * This is an unreliable check for the topology check, but allows some
218  * handy configuration like emitting particles from inside particle
219  * instance. */
220  if (had_mesh_final && (psmd->mesh_final->totvert != psmd->totdmvert ||
221  psmd->mesh_final->totedge != psmd->totdmedge ||
222  psmd->mesh_final->totface != psmd->totdmface)) {
223  psys->recalc |= ID_RECALC_PSYS_RESET;
224  }
225  psmd->totdmvert = psmd->mesh_final->totvert;
226  psmd->totdmedge = psmd->mesh_final->totedge;
227  psmd->totdmface = psmd->mesh_final->totface;
228 
229  {
233  ctx->depsgraph, scene, ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0);
235  }
236 
237  if (DEG_is_active(ctx->depsgraph)) {
238  Object *object_orig = DEG_get_original_object(ctx->object);
239  ModifierData *md_orig = BKE_modifiers_findby_name(object_orig, psmd->modifier.name);
240  BLI_assert(md_orig != NULL);
242  psmd_orig->flag = psmd->flag;
243  }
244 }
245 
246 /* disabled particles in editmode for now, until support for proper evaluated mesh
247  * updates is coded */
248 #if 0
249 static void deformVertsEM(ModifierData *md,
250  Object *ob,
251  BMEditMesh *editData,
252  Mesh *mesh,
253  float (*vertexCos)[3],
254  int numVerts)
255 {
256  const bool do_temp_mesh = (mesh == NULL);
257  if (do_temp_mesh) {
258  mesh = BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name);
259  BM_mesh_bm_to_me(NULL, editData->bm, mesh, &((BMeshToMeshParams){0}));
260  }
261 
262  deformVerts(md, ob, mesh, vertexCos, numVerts);
263 
264  if (derivedData) {
266  }
267 }
268 #endif
269 
270 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
271 {
272  uiLayout *layout = panel->layout;
273 
274  PointerRNA ob_ptr;
276 
277  Object *ob = ob_ptr.data;
278  ModifierData *md = (ModifierData *)ptr->data;
279  ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
280 
281  uiItemL(layout, IFACE_("Settings are in the particle tab"), ICON_NONE);
282 
283  if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
284  if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) {
285  uiItemO(layout,
287  ICON_NONE,
288  "OBJECT_OT_duplicates_make_real");
289  }
290  else if (psys->part->ren_as == PART_DRAW_PATH) {
291  uiItemO(layout,
293  ICON_NONE,
294  "OBJECT_OT_modifier_convert");
295  }
296  }
297 
298  modifier_panel_end(layout, ptr);
299 }
300 
301 static void panelRegister(ARegionType *region_type)
302 {
304 }
305 
306 static void blendRead(BlendDataReader *reader, ModifierData *md)
307 {
309 
310  psmd->mesh_final = NULL;
311  psmd->mesh_original = NULL;
312  /* This is written as part of ob->particlesystem. */
313  BLO_read_data_address(reader, &psmd->psys);
316 }
317 
319  /* name */ "ParticleSystem",
320  /* structName */ "ParticleSystemModifierData",
321  /* structSize */ sizeof(ParticleSystemModifierData),
322  /* srna */ &RNA_ParticleSystemModifier,
323  /* type */ eModifierTypeType_OnlyDeform,
326  eModifierTypeFlag_SupportsEditmode |
327  eModifierTypeFlag_EnableInEditmode */
328  ,
329  /* icon */ ICON_MOD_PARTICLES,
330 
331  /* copyData */ copyData,
332 
333  /* deformVerts */ deformVerts,
334  /* deformMatrices */ NULL,
335  /* deformVertsEM */ NULL,
336  /* deformMatricesEM */ NULL,
337  /* modifyMesh */ NULL,
338  /* modifyHair */ NULL,
339  /* modifyGeometrySet */ NULL,
340  /* modifyVolume */ NULL,
341 
342  /* initData */ initData,
343  /* requiredDataMask */ requiredDataMask,
344  /* freeData */ freeData,
345  /* isDisabled */ NULL,
346  /* updateDepsgraph */ NULL,
347  /* dependsOnTime */ NULL,
348  /* dependsOnNormals */ NULL,
349  /* foreachIDLink */ NULL,
350  /* foreachTexLink */ NULL,
351  /* freeRuntimeData */ NULL,
352  /* panelRegister */ panelRegister,
353  /* blendWrite */ NULL,
354  /* blendRead */ blendRead,
355 };
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
void * BKE_id_new_nomain(const short type, const char *name)
Definition: lib_id.c:1196
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float(*vert_coords)[3])
Definition: mesh.c:1755
void BKE_mesh_tessface_ensure(struct Mesh *mesh)
Definition: mesh.c:1560
struct Mesh * BKE_mesh_copy_for_eval(struct Mesh *source, bool reference)
Definition: mesh.c:995
struct Mesh * BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings)
void BKE_mesh_calc_normals(struct Mesh *me)
@ eModifierTypeFlag_UsesPointCache
Definition: BKE_modifier.h:104
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:82
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:58
struct ModifierData * BKE_modifiers_findby_name(const struct Object *ob, const char *name)
@ MOD_APPLY_RENDER
Definition: BKE_modifier.h:128
void particle_system_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params)
void psys_emitter_customdata_mask(struct ParticleSystem *psys, struct CustomData_MeshMasks *r_cddata_masks)
Definition: particle.c:2251
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params)
Definition: particle.c:789
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_read_data_address(reader, ptr_p)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:331
struct Object * DEG_get_original_object(struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_PSYS_RESET
Definition: DNA_ID.h:620
@ ID_ME
Definition: DNA_ID_enums.h:60
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ eParticleSystemFlag_psys_updated
@ eParticleSystemFlag_file_loaded
struct ParticleSystemModifierData ParticleSystemModifierData
@ eModifierType_ParticleSystem
@ OB_MODE_PARTICLE_EDIT
@ OB_MESH
#define PART_DRAW_PATH
#define PART_DRAW_OB
#define PSYS_DELETE
#define PART_DRAW_GR
static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *em, Mesh *mesh, float(*vertexCos)[3], int numVerts)
Definition: MOD_armature.c:168
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
ModifierTypeInfo modifierType_ParticleSystem
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], int numVerts)
static void blendRead(BlendDataReader *reader, ModifierData *md)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
static void freeData(ModifierData *md)
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
Mesh * MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float(*vertexCos)[3], const int num_verts, const bool use_normals, const bool use_orco)
Definition: MOD_util.c:186
StructRNA RNA_ParticleSystemModifier
#define C
Definition: RandGen.cpp:39
void uiItemL(uiLayout *layout, const char *name, int icon)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
Scene scene
struct BMesh * bm
Definition: BKE_editmesh.h:52
Definition: DNA_ID.h:273
void * first
Definition: DNA_listBase.h:47
int totedge
int totvert
int totface
Mesh_Runtime runtime
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:153
ModifierApplyFlag flag
Definition: BKE_modifier.h:155
struct Object * object
Definition: BKE_modifier.h:154
ListBase particlesystem
void * data
struct uiLayout * layout
struct ParticleSystem * psys
ParticleData * particles
void * data
Definition: RNA_types.h:52
PointerRNA * ptr
Definition: wm_files.c:3157