diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_pointcache.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 99 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcloud.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/simulation.cc | 135 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 13 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 24 | ||||
-rw-r--r-- | source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc | 14 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_draw.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_simulation_types.h | 40 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 14 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_simulation.cc | 41 |
11 files changed, 380 insertions, 7 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 164783f4d14..2dd364f3c48 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -64,6 +64,7 @@ extern "C" { #define PTCACHE_TYPE_SMOKE_HIGHRES 4 #define PTCACHE_TYPE_DYNAMICPAINT 5 #define PTCACHE_TYPE_RIGIDBODY 6 +#define PTCACHE_TYPE_SIM_PARTICLES 7 /* high bits reserved for flags that need to be stored in file */ #define PTCACHE_TYPEFLAG_COMPRESS (1 << 16) @@ -84,10 +85,12 @@ struct ListBase; struct Main; struct Object; struct ParticleKey; +struct ParticleSimulationState; struct ParticleSystem; struct PointCache; struct RigidBodyWorld; struct Scene; +struct Simulation; struct SoftBody; struct ViewLayer; @@ -292,6 +295,7 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface); void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); +void BKE_ptcache_id_from_sim_particles(PTCacheID *pid, struct ParticleSimulationState *state); PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache); void BKE_ptcache_ids_from_object(struct ListBase *lb, diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 5ee61667eca..17c41d992ed 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -41,6 +41,7 @@ #include "DNA_particle_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -1828,6 +1829,87 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r pid->file_type = PTCACHE_FILE_PTCACHE; } +static int ptcache_sim_particle_totpoint(void *state_v, int UNUSED(cfra)) +{ + ParticleSimulationState *state = (ParticleSimulationState *)state_v; + return state->tot_particles; +} + +static void ptcache_sim_particle_error(void *UNUSED(state_v), const char *UNUSED(message)) +{ +} + +static int ptcache_sim_particle_write(int index, void *state_v, void **data, int UNUSED(cfra)) +{ + ParticleSimulationState *state = (ParticleSimulationState *)state_v; + + const float *positions = (const float *)CustomData_get_layer_named( + &state->attributes, CD_LOCATION, "Position"); + + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, positions + (index * 3)); + + return 1; +} +static void ptcache_sim_particle_read( + int index, void *state_v, void **data, float UNUSED(cfra), float *UNUSED(old_data)) +{ + ParticleSimulationState *state = (ParticleSimulationState *)state_v; + + BLI_assert(index < state->tot_particles); + float *positions = (float *)CustomData_get_layer_named( + &state->attributes, CD_LOCATION, "Position"); + + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, positions + (index * 3)); +} + +void BKE_ptcache_id_from_sim_particles(PTCacheID *pid, ParticleSimulationState *state) +{ + memset(pid, 0, sizeof(PTCacheID)); + + ParticleSimulationState *state_orig; + if (state->head.orig_state != NULL) { + state_orig = (ParticleSimulationState *)state->head.orig_state; + } + else { + state_orig = state; + } + + pid->calldata = state; + pid->type = PTCACHE_TYPE_SIM_PARTICLES; + pid->cache = state_orig->point_cache; + pid->cache_ptr = &state_orig->point_cache; + pid->ptcaches = &state_orig->ptcaches; + pid->totpoint = ptcache_sim_particle_totpoint; + pid->totwrite = ptcache_sim_particle_totpoint; + pid->error = ptcache_sim_particle_error; + + pid->write_point = ptcache_sim_particle_write; + pid->read_point = ptcache_sim_particle_read; + pid->interpolate_point = NULL; + + pid->write_stream = NULL; + pid->read_stream = NULL; + + pid->write_openvdb_stream = NULL; + pid->read_openvdb_stream = NULL; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = NULL; + pid->read_header = NULL; + + pid->data_types = 1 << BPHYS_DATA_LOCATION; + pid->info_types = 0; + + pid->stack_index = 0; + + pid->default_step = 1; + pid->max_step = 1; + pid->file_type = PTCACHE_FILE_PTCACHE; +} + /** * \param ob: Optional, may be NULL. * \param scene: Optional may be NULL. @@ -1926,6 +2008,23 @@ static bool foreach_object_modifier_ptcache(Object *object, } } } + else if (md->type == eModifierType_Simulation) { + SimulationModifierData *smd = (SimulationModifierData *)md; + if (smd->simulation) { + LISTBASE_FOREACH (SimulationState *, state, &smd->simulation->states) { + switch ((eSimulationStateType)state->type) { + case SIM_STATE_TYPE_PARTICLES: { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + BKE_ptcache_id_from_sim_particles(&pid, particle_state); + if (!callback(&pid, callback_user_data)) { + return false; + } + break; + } + } + } + } + } } return true; } diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index e03888dcad7..df5d93beccb 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -192,6 +192,7 @@ void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint) { PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_PT, NULL); + CustomData_free(&pointcloud_dst->pdata, pointcloud_dst->totpoint); STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name); pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat); diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index d5ba345928b..20386869ca9 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -27,7 +27,9 @@ #include "DNA_scene_types.h" #include "DNA_simulation_types.h" +#include "BLI_array_ref.hh" #include "BLI_compiler_compat.h" +#include "BLI_float3.hh" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" @@ -35,12 +37,14 @@ #include "BKE_anim_data.h" #include "BKE_animsys.h" +#include "BKE_customdata.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_pointcache.h" #include "BKE_simulation.h" #include "NOD_simulation.h" @@ -50,6 +54,10 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +using BLI::ArrayRef; +using BLI::float3; +using BLI::MutableArrayRef; + static void simulation_init_data(ID *id) { Simulation *simulation = (Simulation *)id; @@ -59,6 +67,14 @@ static void simulation_init_data(ID *id) bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname); simulation->nodetree = ntree; + + /* Add a default particle simulation state for now. */ + ParticleSimulationState *state = (ParticleSimulationState *)MEM_callocN( + sizeof(ParticleSimulationState), __func__); + CustomData_reset(&state->attributes); + + state->point_cache = BKE_ptcache_add(&state->ptcaches); + BLI_addtail(&simulation->states, state); } static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) @@ -75,6 +91,21 @@ static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons (ID **)&simulation_dst->nodetree, flag_private_id_data); } + + BLI_listbase_clear(&simulation_dst->states); + + LISTBASE_FOREACH (const SimulationState *, state_src, &simulation_src->states) { + switch ((eSimulationStateType)state_src->type) { + case SIM_STATE_TYPE_PARTICLES: { + ParticleSimulationState *particle_state_dst = (ParticleSimulationState *)MEM_callocN( + sizeof(ParticleSimulationState), __func__); + CustomData_reset(&particle_state_dst->attributes); + + BLI_addtail(&simulation_dst->states, particle_state_dst); + break; + } + } + } } static void simulation_free_data(ID *id) @@ -88,6 +119,18 @@ static void simulation_free_data(ID *id) MEM_freeN(simulation->nodetree); simulation->nodetree = nullptr; } + + LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) { + switch ((eSimulationStateType)state->type) { + case SIM_STATE_TYPE_PARTICLES: { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + CustomData_free(&particle_state->attributes, particle_state->tot_particles); + BKE_ptcache_free_list(&particle_state->ptcaches); + break; + } + } + MEM_freeN(state); + } } static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) @@ -125,8 +168,94 @@ void *BKE_simulation_add(Main *bmain, const char *name) return simulation; } -void BKE_simulation_data_update(Depsgraph *UNUSED(depsgraph), - Scene *UNUSED(scene), - Simulation *UNUSED(simulation)) +static MutableArrayRef<float3> get_particle_positions(ParticleSimulationState *state) { + return MutableArrayRef<float3>( + (float3 *)CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position"), + state->tot_particles); +} + +static void ensure_attributes_exist(ParticleSimulationState *state) +{ + if (CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position") == nullptr) { + CustomData_add_layer_named( + &state->attributes, CD_LOCATION, CD_CALLOC, nullptr, state->tot_particles, "Position"); + } +} + +static void copy_particle_state_to_cow(ParticleSimulationState *state_orig, + ParticleSimulationState *state_cow) +{ + ensure_attributes_exist(state_cow); + CustomData_free(&state_cow->attributes, state_cow->tot_particles); + CustomData_copy(&state_orig->attributes, + &state_cow->attributes, + CD_MASK_ALL, + CD_DUPLICATE, + state_orig->tot_particles); + state_cow->current_frame = state_orig->current_frame; + state_cow->tot_particles = state_orig->tot_particles; +} + +void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation) +{ + int current_frame = scene->r.cfra; + + ParticleSimulationState *state_cow = (ParticleSimulationState *)simulation->states.first; + ParticleSimulationState *state_orig = (ParticleSimulationState *)state_cow->head.orig_state; + + if (current_frame == state_cow->current_frame) { + return; + } + + /* Number of particles should be stored in the cache, but for now assume it is constant. */ + state_cow->tot_particles = state_orig->tot_particles; + CustomData_realloc(&state_cow->attributes, state_orig->tot_particles); + ensure_attributes_exist(state_cow); + + PTCacheID pid_cow; + BKE_ptcache_id_from_sim_particles(&pid_cow, state_cow); + BKE_ptcache_id_time(&pid_cow, scene, current_frame, nullptr, nullptr, nullptr); + + /* If successfull, this will read the state directly into the cow state. */ + int cache_result = BKE_ptcache_read(&pid_cow, current_frame, true); + if (cache_result == PTCACHE_READ_EXACT) { + state_cow->current_frame = current_frame; + return; + } + + /* Below we modify the original state/cache. Only the active depsgraph is allowed to do that. */ + if (!DEG_is_active(depsgraph)) { + return; + } + + PTCacheID pid_orig; + BKE_ptcache_id_from_sim_particles(&pid_orig, state_orig); + BKE_ptcache_id_time(&pid_orig, scene, current_frame, nullptr, nullptr, nullptr); + + if (current_frame == 1) { + state_orig->tot_particles = 100; + state_orig->current_frame = 1; + CustomData_realloc(&state_orig->attributes, state_orig->tot_particles); + ensure_attributes_exist(state_orig); + + MutableArrayRef<float3> positions = get_particle_positions(state_orig); + for (uint i : positions.index_range()) { + positions[i] = {i / 10.0f, 0, 0}; + } + + BKE_ptcache_write(&pid_orig, current_frame); + copy_particle_state_to_cow(state_orig, state_cow); + } + else if (current_frame == state_orig->current_frame + 1) { + state_orig->current_frame = current_frame; + ensure_attributes_exist(state_orig); + MutableArrayRef<float3> positions = get_particle_positions(state_orig); + for (float3 &position : positions) { + position.z += 0.1f; + } + + BKE_ptcache_write(&pid_orig, current_frame); + copy_particle_state_to_cow(state_orig, state_cow); + } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f7f18d98e73..1e09f01fa57 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9105,6 +9105,19 @@ static void direct_link_simulation(BlendDataReader *reader, Simulation *simulati { BLO_read_data_address(reader, &simulation->adt); direct_link_animdata(reader, simulation->adt); + + BLO_read_list(reader, &simulation->states); + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + switch ((eSimulationStateType)state->type) { + case SIM_STATE_TYPE_PARTICLES: { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + direct_link_customdata(reader, &particle_state->attributes, particle_state->tot_particles); + direct_link_pointcache_list( + reader, &particle_state->ptcaches, &particle_state->point_cache, 0); + break; + }; + } + } } /** \} */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 205184e6e7c..3fa36c6995e 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -3915,6 +3915,30 @@ static void write_simulation(BlendWriter *writer, Simulation *simulation, const BLO_write_struct(writer, bNodeTree, simulation->nodetree); write_nodetree_nolib(writer, simulation->nodetree); } + + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + switch ((eSimulationStateType)state->type) { + case SIM_STATE_TYPE_PARTICLES: { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + BLO_write_struct(writer, ParticleSimulationState, particle_state); + + CustomDataLayer *layers = NULL; + CustomDataLayer layers_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_file_write_prepare( + &particle_state->attributes, &layers, layers_buff, ARRAY_SIZE(layers_buff)); + + write_customdata(writer, + &simulation->id, + particle_state->tot_particles, + &particle_state->attributes, + layers, + CD_MASK_ALL); + + write_pointcaches(writer, &particle_state->ptcaches); + break; + } + } + } } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 2f2e05d410e..70a6875f1c0 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -63,6 +63,7 @@ #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DRW_engine.h" @@ -709,6 +710,13 @@ void update_modifiers_orig_pointers(const Object *object_orig, Object *object_co &object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data); } +void update_simulation_states_orig_pointers(const Simulation *simulation_orig, + Simulation *simulation_cow) +{ + update_list_orig_pointers( + &simulation_orig->states, &simulation_cow->states, &SimulationState::orig_state); +} + void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow) { NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first); @@ -808,6 +816,12 @@ void update_id_after_copy(const Depsgraph *depsgraph, update_scene_orig_pointers(scene_orig, scene_cow); break; } + case ID_SIM: { + Simulation *simulation_cow = (Simulation *)id_cow; + const Simulation *simulation_orig = (const Simulation *)id_orig; + update_simulation_states_orig_pointers(simulation_orig, simulation_cow); + break; + } default: break; } diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 52287b07b28..ada4243ab4e 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -360,6 +360,7 @@ static bool timeline_cache_is_hidden_by_setting(SpaceAction *saction, PTCacheID } break; case PTCACHE_TYPE_PARTICLES: + case PTCACHE_TYPE_SIM_PARTICLES: if ((saction->cache_display & TIME_CACHE_PARTICLES) == 0) { return true; } @@ -399,6 +400,7 @@ static void timeline_cache_color_get(PTCacheID *pid, float color[4]) color[3] = 0.1; break; case PTCACHE_TYPE_PARTICLES: + case PTCACHE_TYPE_SIM_PARTICLES: color[0] = 1.0; color[1] = 0.1; color[2] = 0.02; diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h index 113c301bb9e..93ba9c425f0 100644 --- a/source/blender/makesdna/DNA_simulation_types.h +++ b/source/blender/makesdna/DNA_simulation_types.h @@ -22,6 +22,7 @@ #define __DNA_SIMULATION_TYPES_H__ #include "DNA_ID.h" +#include "DNA_customdata_types.h" typedef struct Simulation { ID id; @@ -30,12 +31,49 @@ typedef struct Simulation { struct bNodeTree *nodetree; int flag; - int _pad1[1]; + int _pad; + + /** List containing SimulationState objects. */ + struct ListBase states; } Simulation; +typedef struct SimulationState { + struct SimulationState *next; + struct SimulationState *prev; + + /** This is only initialized on cow copies of the simulation. It points to the state on the + * original data block. That is where the cache is stored. */ + struct SimulationState *orig_state; + + /** eSimulationStateType */ + int type; + int _pad; + + char name[64]; +} SimulationState; + +typedef struct ParticleSimulationState { + SimulationState head; + + /** Contains the state of the particles at time current_frame. */ + float current_frame; + int tot_particles; + struct CustomData attributes; + + /** Caches the state of the particles over time. The cache only exists on the original data + * block, not on cow copies. */ + struct PointCache *point_cache; + struct ListBase ptcaches; +} ParticleSimulationState; + /* Simulation.flag */ enum { SIM_DS_EXPAND = (1 << 0), }; +/* SimulationCache.type */ +typedef enum eSimulationStateType { + SIM_STATE_TYPE_PARTICLES = 0, +} eSimulationStateType; + #endif /* __DNA_SIMULATION_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index b8dad8cf5c1..a0026797c68 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -29,6 +29,7 @@ #include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "MEM_guardedalloc.h" @@ -1631,6 +1632,17 @@ static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, CLAMP_MIN(psmd->psys, 1); } +# ifdef WITH_NEW_SIMULATION_TYPE +static void rna_SimulationModifier_simulation_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + SimulationModifierData *smd = ptr->data; + if (smd->simulation != NULL) { + DEG_id_tag_update(&smd->simulation->id, ID_RECALC_ALL); + } + rna_Modifier_dependency_update(bmain, scene, ptr); +} +# endif + #else /* NOTE: *MUST* return subdivision_type property. */ @@ -6794,7 +6806,7 @@ static void rna_def_modifier_simulation(BlenderRNA *brna) prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Simulation", "Simulation to access"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + RNA_def_property_update(prop, 0, "rna_SimulationModifier_simulation_update"); # endif prop = RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc index f126d1af959..5ccf945b5a6 100644 --- a/source/blender/modifiers/intern/MOD_simulation.cc +++ b/source/blender/modifiers/intern/MOD_simulation.cc @@ -21,11 +21,14 @@ * \ingroup modifiers */ +#include <cstring> #include <iostream> #include <string> #include "MEM_guardedalloc.h" +#include "BLI_float3.hh" +#include "BLI_listbase.h" #include "BLI_utildefines.h" #include "DNA_mesh_types.h" @@ -41,6 +44,8 @@ #include "BKE_lib_query.h" #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_pointcloud.h" +#include "BKE_simulation.h" /* SpaceType struct has a member called 'new' which obviously conflicts with C++ * so temporarily redefining the new keyword to make it compile. */ @@ -59,6 +64,8 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" +using BLI::float3; + static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) { SimulationModifierData *smd = (SimulationModifierData *)md; @@ -81,12 +88,42 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return smd->simulation == nullptr; } +static const ParticleSimulationState *find_particle_state(SimulationModifierData *smd) +{ + if (smd->simulation == nullptr) { + return nullptr; + } + LISTBASE_FOREACH (const SimulationState *, state, &smd->simulation->states) { + if (state->type == SIM_STATE_TYPE_PARTICLES) { + return (ParticleSimulationState *)state; + } + } + return nullptr; +} + static PointCloud *modifyPointCloud(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), - PointCloud *pointcloud) + PointCloud *input_pointcloud) { SimulationModifierData *smd = (SimulationModifierData *)md; - UNUSED_VARS(smd); + const ParticleSimulationState *state = find_particle_state(smd); + if (state == nullptr) { + return input_pointcloud; + } + + PointCloud *pointcloud = BKE_pointcloud_new_for_eval(input_pointcloud, state->tot_particles); + if (state->tot_particles == 0) { + return pointcloud; + } + + const float3 *positions = (const float3 *)CustomData_get_layer_named( + &state->attributes, CD_LOCATION, "Position"); + memcpy(pointcloud->co, positions, sizeof(float3) * state->tot_particles); + + for (int i = 0; i < state->tot_particles; i++) { + pointcloud->radius[i] = 0.05f; + } + return pointcloud; } |