Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/curves/intern/curves_ops.cc')
-rw-r--r--source/blender/editors/curves/intern/curves_ops.cc270
1 files changed, 147 insertions, 123 deletions
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index 3a4dcd4f5f6..7d07c211542 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -121,147 +121,171 @@ static float4 compute_mface_weights_for_position(const Mesh &mesh,
return mface_weights;
}
-static int curves_convert_to_particle_system_exec(bContext *C, wmOperator *UNUSED(op))
+static void try_convert_single_object(Object &curves_ob,
+ Main &bmain,
+ Scene &scene,
+ bool *r_could_not_convert_some_curves)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- CTX_DATA_BEGIN (C, Object *, curves_ob, selected_objects) {
- if (curves_ob->type != OB_CURVES) {
- continue;
- }
- Curves &curves_id = *static_cast<Curves *>(curves_ob->data);
- CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
- if (curves_id.surface == nullptr) {
- continue;
- }
- Object &surface_ob = *curves_id.surface;
- if (surface_ob.type != OB_MESH) {
- continue;
+ if (curves_ob.type != OB_CURVES) {
+ return;
+ }
+ Curves &curves_id = *static_cast<Curves *>(curves_ob.data);
+ CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
+ if (curves_id.surface == nullptr) {
+ return;
+ }
+ Object &surface_ob = *curves_id.surface;
+ if (surface_ob.type != OB_MESH) {
+ return;
+ }
+ Mesh &surface_me = *static_cast<Mesh *>(surface_ob.data);
+
+ const Span<float3> positions_cu = curves.positions();
+ const VArray<int> looptri_indices = curves.surface_triangle_indices();
+ const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&surface_me),
+ BKE_mesh_runtime_looptri_len(&surface_me)};
+
+ /* Find indices of curves that can be transferred to the old hair system. */
+ Vector<int> curves_indices_to_transfer;
+ for (const int curve_i : curves.curves_range()) {
+ const int looptri_i = looptri_indices[curve_i];
+ if (looptri_i >= 0 && looptri_i < looptris.size()) {
+ curves_indices_to_transfer.append(curve_i);
}
- Mesh &surface_me = *static_cast<Mesh *>(surface_ob.data);
-
- const Span<float3> positions_cu = curves.positions();
- const VArray<int> looptri_indices = curves.surface_triangle_indices();
- const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&surface_me),
- BKE_mesh_runtime_looptri_len(&surface_me)};
-
- /* Find indices of curves that can be transferred to the old hair system. */
- Vector<int> curves_indices_to_transfer;
- for (const int curve_i : curves.curves_range()) {
- const int looptri_i = looptri_indices[curve_i];
- if (looptri_i >= 0 && looptri_i < looptris.size()) {
- curves_indices_to_transfer.append(curve_i);
- }
+ else {
+ *r_could_not_convert_some_curves = true;
}
+ }
- const int hairs_num = curves_indices_to_transfer.size();
- if (hairs_num == 0) {
- continue;
- }
+ const int hairs_num = curves_indices_to_transfer.size();
+ if (hairs_num == 0) {
+ return;
+ }
- ParticleSystem *particle_system = nullptr;
- LISTBASE_FOREACH (ParticleSystem *, psys, &surface_ob.particlesystem) {
- if (STREQ(psys->name, curves_ob->id.name + 2)) {
- particle_system = psys;
- break;
- }
- }
- if (particle_system == nullptr) {
- ParticleSystemModifierData &psmd = *reinterpret_cast<ParticleSystemModifierData *>(
- object_add_particle_system(bmain, scene, &surface_ob, curves_ob->id.name + 2));
- particle_system = psmd.psys;
+ ParticleSystem *particle_system = nullptr;
+ LISTBASE_FOREACH (ParticleSystem *, psys, &surface_ob.particlesystem) {
+ if (STREQ(psys->name, curves_ob.id.name + 2)) {
+ particle_system = psys;
+ break;
}
+ }
+ if (particle_system == nullptr) {
+ ParticleSystemModifierData &psmd = *reinterpret_cast<ParticleSystemModifierData *>(
+ object_add_particle_system(&bmain, &scene, &surface_ob, curves_ob.id.name + 2));
+ particle_system = psmd.psys;
+ particle_system->part->draw_step = 3;
+ }
+
+ ParticleSettings &settings = *particle_system->part;
- ParticleSettings &settings = *particle_system->part;
+ psys_free_particles(particle_system);
+ settings.type = PART_HAIR;
+ settings.totpart = 0;
+ psys_changed_type(&surface_ob, particle_system);
- psys_free_particles(particle_system);
- settings.type = PART_HAIR;
- settings.totpart = 0;
- psys_changed_type(&surface_ob, particle_system);
+ MutableSpan<ParticleData> particles{
+ static_cast<ParticleData *>(MEM_calloc_arrayN(hairs_num, sizeof(ParticleData), __func__)),
+ hairs_num};
- MutableSpan<ParticleData> particles{
- static_cast<ParticleData *>(MEM_calloc_arrayN(hairs_num, sizeof(ParticleData), __func__)),
- hairs_num};
+ /* The old hair system still uses #MFace, so make sure those are available on the mesh. */
+ BKE_mesh_tessface_calc(&surface_me);
- /* The old hair system still uses #MFace, so make sure those are available on the mesh. */
- BKE_mesh_tessface_calc(&surface_me);
+ /* Prepare utility data structure to map hair roots to mfaces. */
+ const Span<int> mface_to_poly_map{
+ static_cast<int *>(CustomData_get_layer(&surface_me.fdata, CD_ORIGINDEX)),
+ surface_me.totface};
+ Array<Vector<int>> poly_to_mface_map(surface_me.totpoly);
+ for (const int mface_i : mface_to_poly_map.index_range()) {
+ const int poly_i = mface_to_poly_map[mface_i];
+ poly_to_mface_map[poly_i].append(mface_i);
+ }
- /* Prepare utility data structure to map hair roots to mfaces. */
- const Span<int> mface_to_poly_map{
- static_cast<int *>(CustomData_get_layer(&surface_me.fdata, CD_ORIGINDEX)),
- surface_me.totface};
- Array<Vector<int>> poly_to_mface_map(surface_me.totpoly);
- for (const int mface_i : mface_to_poly_map.index_range()) {
- const int poly_i = mface_to_poly_map[mface_i];
- poly_to_mface_map[poly_i].append(mface_i);
+ /* Prepare transformation matrices. */
+ const float4x4 curves_to_world_mat = curves_ob.obmat;
+ const float4x4 surface_to_world_mat = surface_ob.obmat;
+ const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
+ const float4x4 curves_to_surface_mat = world_to_surface_mat * curves_to_world_mat;
+
+ for (const int new_hair_i : curves_indices_to_transfer.index_range()) {
+ const int curve_i = curves_indices_to_transfer[new_hair_i];
+ const IndexRange points = curves.points_for_curve(curve_i);
+
+ const int looptri_i = looptri_indices[curve_i];
+ const MLoopTri &looptri = looptris[looptri_i];
+ const int poly_i = looptri.poly;
+
+ const float3 &root_pos_cu = positions_cu[points.first()];
+ const float3 root_pos_su = curves_to_surface_mat * root_pos_cu;
+
+ const int mface_i = find_mface_for_root_position(
+ surface_me, poly_to_mface_map[poly_i], root_pos_su);
+ const MFace &mface = surface_me.mface[mface_i];
+
+ const float4 mface_weights = compute_mface_weights_for_position(
+ surface_me, mface, root_pos_su);
+
+ ParticleData &particle = particles[new_hair_i];
+ const int num_keys = points.size();
+ MutableSpan<HairKey> hair_keys{
+ static_cast<HairKey *>(MEM_calloc_arrayN(num_keys, sizeof(HairKey), __func__)), num_keys};
+
+ particle.hair = hair_keys.data();
+ particle.totkey = hair_keys.size();
+ copy_v4_v4(particle.fuv, mface_weights);
+ particle.num = mface_i;
+ /* Not sure if there is a better way to initialize this. */
+ particle.num_dmcache = DMCACHE_NOTFOUND;
+
+ float4x4 hair_to_surface_mat;
+ psys_mat_hair_to_object(
+ &surface_ob, &surface_me, PART_FROM_FACE, &particle, hair_to_surface_mat.values);
+ /* In theory, #psys_mat_hair_to_object should handle this, but it doesn't right now. */
+ copy_v3_v3(hair_to_surface_mat.values[3], root_pos_su);
+ const float4x4 surface_to_hair_mat = hair_to_surface_mat.inverted();
+
+ for (const int key_i : hair_keys.index_range()) {
+ const float3 &key_pos_cu = positions_cu[points[key_i]];
+ const float3 key_pos_su = curves_to_surface_mat * key_pos_cu;
+ const float3 key_pos_ha = surface_to_hair_mat * key_pos_su;
+
+ HairKey &key = hair_keys[key_i];
+ copy_v3_v3(key.co, key_pos_ha);
+ key.time = 100.0f * key_i / (float)(hair_keys.size() - 1);
}
+ }
- /* Prepare transformation matrices. */
- const float4x4 curves_to_world_mat = curves_ob->obmat;
- const float4x4 surface_to_world_mat = surface_ob.obmat;
- const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
- const float4x4 curves_to_surface_mat = world_to_surface_mat * curves_to_world_mat;
+ particle_system->particles = particles.data();
+ particle_system->totpart = particles.size();
+ particle_system->flag |= PSYS_EDITED;
+ particle_system->recalc |= ID_RECALC_PSYS_RESET;
- for (const int new_hair_i : curves_indices_to_transfer.index_range()) {
- const int curve_i = curves_indices_to_transfer[new_hair_i];
- const IndexRange points = curves.points_for_curve(curve_i);
-
- const int looptri_i = looptri_indices[curve_i];
- const MLoopTri &looptri = looptris[looptri_i];
- const int poly_i = looptri.poly;
-
- const float3 &root_pos_cu = positions_cu[points.first()];
- const float3 root_pos_su = curves_to_surface_mat * root_pos_cu;
-
- const int mface_i = find_mface_for_root_position(
- surface_me, poly_to_mface_map[poly_i], root_pos_su);
- const MFace &mface = surface_me.mface[mface_i];
-
- const float4 mface_weights = compute_mface_weights_for_position(
- surface_me, mface, root_pos_su);
-
- ParticleData &particle = particles[new_hair_i];
- const int num_keys = points.size();
- MutableSpan<HairKey> hair_keys{
- static_cast<HairKey *>(MEM_calloc_arrayN(num_keys, sizeof(HairKey), __func__)),
- num_keys};
-
- particle.hair = hair_keys.data();
- particle.totkey = hair_keys.size();
- copy_v4_v4(particle.fuv, mface_weights);
- particle.num = mface_i;
- /* Not sure if there is a better way to initialize this. */
- particle.num_dmcache = DMCACHE_NOTFOUND;
-
- float4x4 hair_to_surface_mat;
- psys_mat_hair_to_object(
- &surface_ob, &surface_me, PART_FROM_FACE, &particle, hair_to_surface_mat.values);
- /* In theory, #psys_mat_hair_to_object should handle this, but it doesn't right now. */
- copy_v3_v3(hair_to_surface_mat.values[3], root_pos_su);
- const float4x4 surface_to_hair_mat = hair_to_surface_mat.inverted();
-
- for (const int key_i : hair_keys.index_range()) {
- const float3 &key_pos_cu = positions_cu[points[key_i]];
- const float3 key_pos_su = curves_to_surface_mat * key_pos_cu;
- const float3 key_pos_ha = surface_to_hair_mat * key_pos_su;
-
- HairKey &key = hair_keys[key_i];
- copy_v3_v3(key.co, key_pos_ha);
- key.time = 100.0f * key_i / (float)(hair_keys.size() - 1);
- }
- }
+ DEG_id_tag_update(&surface_ob.id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&settings.id, ID_RECALC_COPY_ON_WRITE);
+}
+
+static int curves_convert_to_particle_system_exec(bContext *C, wmOperator *op)
+{
+ Main &bmain = *CTX_data_main(C);
+ Scene &scene = *CTX_data_scene(C);
- particle_system->particles = particles.data();
- particle_system->totpart = particles.size();
- particle_system->flag |= PSYS_EDITED;
- particle_system->recalc |= ID_RECALC_PSYS_RESET;
+ bool could_not_convert_some_curves = false;
- DEG_id_tag_update(&surface_ob.id, ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&settings.id, ID_RECALC_COPY_ON_WRITE);
+ Object &active_object = *CTX_data_active_object(C);
+ try_convert_single_object(active_object, bmain, scene, &could_not_convert_some_curves);
+
+ CTX_DATA_BEGIN (C, Object *, curves_ob, selected_objects) {
+ if (curves_ob != &active_object) {
+ try_convert_single_object(*curves_ob, bmain, scene, &could_not_convert_some_curves);
+ }
}
CTX_DATA_END;
+ if (could_not_convert_some_curves) {
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Some curves could not be converted because they were not attached to the surface");
+ }
+
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, nullptr);
return OPERATOR_FINISHED;
@@ -473,7 +497,7 @@ static void CURVES_OT_snap_curves_to_surface(wmOperatorType *ot)
"Deform",
"Re-attach curves to a deformed surface using the existing attachment information. This "
"only works when the topology of the surface mesh has not changed"},
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
RNA_def_enum(ot->srna,