[Bf-blender-cvs] [91b70d3] master: New operator for copying (hair) particle systems from one object to another, including edit data (grooming).

Lukas Tönne noreply at git.blender.org
Tue Jan 20 09:53:52 CET 2015


Commit: 91b70d3c56cb863b9c6184a726b35d32e5f4480c
Author: Lukas Tönne
Date:   Thu Jan 15 11:51:30 2015 +0100
Branches: master
https://developer.blender.org/rB91b70d3c56cb863b9c6184a726b35d32e5f4480c

New operator for copying (hair) particle systems from one object to
another, including edit data (grooming).

This uses basically the same method as the existing connect/disconnect
feature. The main difference is that it allows working with multiple
objects and transferring the //particle/hair data// instead of the
//mesh// data (which is what connect/disconnect expects). This is a much
more realistic workflow when rigging, topology etc. changes and
groomed hair has to be transferred to the changed model.

===================================================================

M	source/blender/blenkernel/intern/particle.c
M	source/blender/editors/physics/particle_edit.c
M	source/blender/editors/physics/particle_object.c
M	source/blender/editors/physics/physics_intern.h
M	source/blender/editors/physics/physics_ops.c

===================================================================

diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 4994751..72cb69a 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3041,6 +3041,7 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob)
 	DAG_relations_tag_update(G.main);
 	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 }
+
 static void default_particle_settings(ParticleSettings *part)
 {
 	part->type = PART_EMITTER;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 3d97956..29b9db2 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -83,9 +83,11 @@
 
 #include "physics_intern.h"
 
-static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
-static void PTCacheUndo_clear(PTCacheEdit *edit);
-static void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+void PTCacheUndo_clear(PTCacheEdit *edit);
+void recalc_lengths(PTCacheEdit *edit);
+void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+void update_world_cos(Object *ob, PTCacheEdit *edit);
 
 #define KEY_K					PTCacheEditKey *key; int k
 #define POINT_P					PTCacheEditPoint *point; int p
@@ -1074,7 +1076,7 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
 	}
 }
 /* set current distances to be kept between neighbouting keys */
-static void recalc_lengths(PTCacheEdit *edit)
+void recalc_lengths(PTCacheEdit *edit)
 {
 	POINT_P; KEY_K;
 
@@ -1090,7 +1092,7 @@ static void recalc_lengths(PTCacheEdit *edit)
 }
 
 /* calculate a tree for finding nearest emitter's vertice */
-static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
+void recalc_emitter_field(Object *ob, ParticleSystem *psys)
 {
 	DerivedMesh *dm=psys_get_modifier(ob, psys)->dm;
 	PTCacheEdit *edit= psys->edit;
@@ -1178,7 +1180,7 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag)
 		point->flag &= ~PEP_EDIT_RECALC;
 }
 
-static void update_world_cos(Object *ob, PTCacheEdit *edit)
+void update_world_cos(Object *ob, PTCacheEdit *edit)
 {
 	ParticleSystem *psys = edit->psys;
 	ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
@@ -4452,7 +4454,7 @@ int PE_undo_valid(Scene *scene)
 	return 0;
 }
 
-static void PTCacheUndo_clear(PTCacheEdit *edit)
+void PTCacheUndo_clear(PTCacheEdit *edit)
 {
 	PTCacheUndo *undo;
 
@@ -4553,7 +4555,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
 /************************ particle edit toggle operator ************************/
 
 /* initialize needed data for bake edit */
-static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
 {
 	PTCacheEdit *edit;
 	ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 5a61f77..37ee708 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -40,18 +40,22 @@
 #include "BLI_math.h"
 #include "BLI_listbase.h"
 #include "BLI_utildefines.h"
+#include "BLI_string.h"
 
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
 #include "BKE_global.h"
+#include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
 #include "BKE_report.h"
 
-
 #include "RNA_access.h"
 #include "RNA_define.h"
 
@@ -62,8 +66,31 @@
 #include "ED_screen.h"
 #include "ED_object.h"
 
+#include "UI_resources.h"
+
 #include "physics_intern.h"
 
+extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+extern void PTCacheUndo_clear(PTCacheEdit *edit);
+extern void recalc_lengths(PTCacheEdit *edit);
+extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+extern void update_world_cos(Object *ob, PTCacheEdit *edit);
+
+#define KEY_K					PTCacheEditKey *key; int k
+#define POINT_P					PTCacheEditPoint *point; int p
+#define LOOP_POINTS				for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
+#define LOOP_VISIBLE_POINTS		for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
+#define LOOP_SELECTED_POINTS	for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
+#define LOOP_UNSELECTED_POINTS	for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
+#define LOOP_EDITED_POINTS		for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
+#define LOOP_TAGGED_POINTS		for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
+#define LOOP_KEYS				for (k=0, key=point->keys; k<point->totkey; k++, key++)
+#define LOOP_VISIBLE_KEYS		for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
+#define LOOP_SELECTED_KEYS		for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
+#define LOOP_TAGGED_KEYS		for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
+
+#define KEY_WCO					(key->flag & PEK_USE_WCO ? key->world_co : key->co)
+
 /********************** particle system slot operators *********************/
 
 static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
@@ -623,37 +650,32 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
 	RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
 }
 
-static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+static bool remap_hair_emitter(Scene *scene, Object *UNUSED(ob), ParticleSystem *psys,
+                               Object *target_ob, DerivedMesh *target_dm, ParticleSystem *target_psys, PTCacheEdit *target_edit,
+                               bool from_world_space, bool to_world_space)
 {
-	ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-	ParticleData *pa;
-	PTCacheEdit *edit;
-	PTCacheEditPoint *point;
-	PTCacheEditKey *ekey = NULL;
-	HairKey *key;
+	ParticleData *pa, *tpa;
+	PTCacheEditPoint *edit_point;
+	PTCacheEditKey *ekey;
 	BVHTreeFromMesh bvhtree= {NULL};
-	BVHTreeNearest nearest;
 	MFace *mface = NULL, *mf;
 	MEdge *medge = NULL, *me;
 	MVert *mvert;
-	DerivedMesh *dm = NULL;
+	DerivedMesh *dm;
 	int numverts;
 	int i, k;
-	float hairmat[4][4], imat[4][4];
-	float v[4][3], vec[3];
 
-	if (!psys || !psys->part || psys->part->type != PART_HAIR || !psmd->dm)
+	if (!psys->part || psys->part->type != PART_HAIR || !target_psys->part || target_psys->part->type != PART_HAIR)
 		return false;
 	
-	edit= psys->edit;
-	point=  edit ? edit->points : NULL;
+	edit_point = target_edit ? target_edit->points : NULL;
 	
-	if (psmd->dm->deformedOnly) {
-		/* we don't want to mess up psmd->dm when converting to global coordinates below */
-		dm = psmd->dm;
+	if (target_dm->deformedOnly) {
+		/* we don't want to mess up target_dm when converting to global coordinates below */
+		dm = target_dm;
 	}
 	else {
-		dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+		dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH);
 	}
 	/* don't modify the original vertices */
 	dm = CDDM_copy(dm);
@@ -662,12 +684,11 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
 	DM_ensure_tessface(dm);
 
 	numverts = dm->getNumVerts(dm);
-
 	mvert = dm->getVertArray(dm);
 
 	/* convert to global coordinates */
 	for (i=0; i<numverts; i++)
-		mul_m4_v3(ob->obmat, mvert[i].co);
+		mul_m4_v3(target_ob->obmat, mvert[i].co);
 
 	if (dm->getNumTessFaces(dm) != 0) {
 		mface = dm->getTessFaceArray(dm);
@@ -682,13 +703,17 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
 		return false;
 	}
 
-	for (i=0, pa= psys->particles; i<psys->totpart; i++, pa++) {
-		key = pa->hair;
+	for (i = 0, tpa = target_psys->particles, pa = psys->particles;
+	     i < target_psys->totpart;
+	     i++, tpa++, pa++) {
+
+		const float *co = from_world_space ? pa->hair[0].co : pa->hair[0].world_co;
+		BVHTreeNearest nearest;
 
 		nearest.index = -1;
 		nearest.dist_sq = FLT_MAX;
 
-		BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);
+		BLI_bvhtree_find_nearest(bvhtree.tree, co, &nearest, bvhtree.nearest_callback, &bvhtree);
 
 		if (nearest.index == -1) {
 			if (G.debug & G_DEBUG)
@@ -697,6 +722,8 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
 		}
 
 		if (mface) {
+			float v[4][3];
+			
 			mf = &mface[nearest.index];
 
 			copy_v3_v3(v[0], mvert[mf->v1].co);
@@ -704,44 +731,71 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
 			copy_v3_v3(v[2], mvert[mf->v3].co);
 			if (mf->v4) {
 				copy_v3_v3(v[3], mvert[mf->v4].co);
-				interp_weights_poly_v3(pa->fuv, v, 4, nearest.co);
+				interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
 			}
 			else
-				interp_weights_poly_v3(pa->fuv, v, 3, nearest.co);
+				interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
+			tpa->foffset = 0.0f;
 
-			pa->num = nearest.index;
-			pa->num_dmcache = psys_particle_dm_face_lookup(ob, psmd->dm, pa->num, pa->fuv, NULL);
+			tpa->num = nearest.index;
+			tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, dm, tpa->num, tpa->fuv, NULL);
 		}
 		else {
 			me = &medge[nearest.index];
 
-			pa->fuv[1] = line_point_factor_v3(nearest.co,
-			                                  mvert[me->v2].co,
-			                                  mvert[me->v2].co);
-			pa->fuv[0] = 1.0f - pa->fuv[1];
-			pa->fuv[2] = pa->fuv[3] = 0.0f;
+			tpa->fuv[1] = line_point_factor_v3(nearest.co,
+			                                   mvert[me->v1].co,
+			                                   

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list