[Bf-blender-cvs] [aad2446] master: Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.

Bastien Montagne noreply at git.blender.org
Mon Jan 4 12:26:17 CET 2016


Commit: aad24468e2d32d46e2c3b3b4a37302a4f1f27ab6
Author: Bastien Montagne
Date:   Mon Jan 4 12:19:45 2016 +0100
Branches: master
https://developer.blender.org/rBaad24468e2d32d46e2c3b3b4a37302a4f1f27ab6

Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.

It also fixes another issue (crash) related to symmetric editing.

Quite involved, we (try to!) fix complete broken logic of parts of particle code, which would use poly index
as tessface one (or vice-versa). Issue most probably goes back to BMesh integration time...

This patch mostly fixes particle editing mode:
  - Adding/removing particles when using generative modifiers (like subsurf) should now work.
  - Adding/removing particles with a non-tessellated mesh (i.e. one having ngons) should also mostly work.
  - X-axis-mirror-editing particles over ngons does not really work, not sure why currently.
  - All this in both 'modes' (with or without using modifier stack for particles).

Tech side:
  - Store a deformed-only DM in particle modifier data.
  - Rename existing DM to make it clear it's a final one.
  - Use deformed-only DM's tessface2poly mapping to 'solve' poly/tessface mismatches.
  - Make (part of) mirror-editing code able to use a DM instead of raw mesh, so that we can mirror based on final DM
    when editing particles using modifier stack (mandatory, since there is no way currently to find orig tessface
    from an final DM tessface index).

Note that this patch is not really nice and clean (current particles are beyond hope on this side anyway),
it's more like some urgency bandage. Whole crap needs complete rewrite anyway,
BMesh's polygons make it really hard to work with current system (and looptri would not help much here).

Also, did not test everything possibly affected by those changes, so it needs some users' testing & validation too.

Reviewers: psy-fi

Subscribers: dfelinto, eyecandy

Maniphest Tasks: T47038

Differential Revision: https://developer.blender.org/D1685

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

M	source/blender/blenkernel/BKE_particle.h
M	source/blender/blenkernel/intern/DerivedMesh.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/particle.c
M	source/blender/blenkernel/intern/particle_distribute.c
M	source/blender/blenkernel/intern/particle_system.c
M	source/blender/blenlib/BLI_math_vector.h
M	source/blender/blenlib/intern/math_vector_inline.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/editors/armature/armature_skinning.c
M	source/blender/editors/armature/meshlaplacian.c
M	source/blender/editors/include/ED_mesh.h
M	source/blender/editors/mesh/editface.c
M	source/blender/editors/mesh/editmesh_utils.c
M	source/blender/editors/mesh/meshtools.c
M	source/blender/editors/object/object_edit.c
M	source/blender/editors/object/object_shapekey.c
M	source/blender/editors/object/object_vgroup.c
M	source/blender/editors/physics/particle_edit.c
M	source/blender/editors/physics/particle_object.c
M	source/blender/editors/sculpt_paint/paint_vertex.c
M	source/blender/editors/transform/transform_conversions.c
M	source/blender/editors/util/ed_util.c
M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesdna/DNA_particle_types.h
M	source/blender/makesrna/intern/rna_object_api.c
M	source/blender/makesrna/intern/rna_particle.c
M	source/blender/modifiers/intern/MOD_explode.c
M	source/blender/modifiers/intern/MOD_particleinstance.c
M	source/blender/modifiers/intern/MOD_particlesystem.c
M	source/blender/render/intern/source/convertblender.c
M	source/blender/render/intern/source/pointdensity.c
M	source/blenderplayer/bad_level_call_stubs/stubs.c

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

diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 00cc48c..ed45375 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -302,7 +302,7 @@ void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
 void psys_free(struct Object *ob, struct ParticleSystem *psys);
 
 void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
-void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
+void psys_render_restore(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
 bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
 
 void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
@@ -413,15 +413,15 @@ void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], floa
 
 /* BLI_bvhtree_ray_cast callback */
 void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
-void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache,
+void psys_particle_on_dm(struct DerivedMesh *dm_final, int from, int index, int index_dmcache,
                          const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
                          float orco[3], float ornor[3]);
 
 /* particle_system.c */
 void distribute_particles(struct ParticleSimulationData *sim, int from);
 void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
-void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
-int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node);
+void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, struct ParticleSystem *psys);
+int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes);
 
 void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);
 
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index e26e514..9fc4383 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -43,6 +43,7 @@
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
+#include "BLI_array.h"
 #include "BLI_blenlib.h"
 #include "BLI_bitmap.h"
 #include "BLI_math.h"
@@ -3668,26 +3669,73 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
 
 void DM_init_origspace(DerivedMesh *dm)
 {
-	static float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+	const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
 
 	OrigSpaceLoop *lof_array = CustomData_get_layer(&dm->loopData, CD_ORIGSPACE_MLOOP);
-	OrigSpaceLoop *lof;
 	const int numpoly = dm->getNumPolys(dm);
 	// const int numloop = dm->getNumLoops(dm);
+	MVert *mv = dm->getVertArray(dm);
+	MLoop *ml = dm->getLoopArray(dm);
 	MPoly *mp = dm->getPolyArray(dm);
-	int i, j;
+	int i, j, k;
+
+	float (*vcos_2d)[2] = NULL;
+	BLI_array_staticdeclare(vcos_2d, 64);
 
 	for (i = 0; i < numpoly; i++, mp++) {
-		/* only quads/tri's for now */
+		OrigSpaceLoop *lof = lof_array + mp->loopstart;
+
 		if (mp->totloop == 3 || mp->totloop == 4) {
-			lof = lof_array + mp->loopstart;
 			for (j = 0; j < mp->totloop; j++, lof++) {
 				copy_v2_v2(lof->uv, default_osf[j]);
 			}
 		}
+		else {
+			MLoop *l = &ml[mp->loopstart];
+			float p_nor[3], co[3];
+			float mat[3][3];
+
+			float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {FLT_MIN, FLT_MIN};
+			float translate[2], scale[2];
+
+			BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
+			axis_dominant_v3_to_m3(mat, p_nor);
+
+			BLI_array_empty(vcos_2d);
+			BLI_array_reserve(vcos_2d, mp->totloop);
+			for (j = 0; j < mp->totloop; j++, l++) {
+				mul_v3_m3v3(co, mat, mv[l->v].co);
+				copy_v2_v2(vcos_2d[j], co);
+
+				for (k = 0; k < 2; k++) {
+					if (co[k] > max[k])
+						max[k] = co[k];
+					else if (co[k] < min[k])
+						min[k] = co[k];
+				}
+			}
+
+			/* Brings min to (0, 0). */
+			negate_v2_v2(translate, min);
+
+			/* Scale will bring max to (1, 1). */
+			sub_v2_v2v2(scale, max, min);
+			if (scale[0] == 0.0f)
+				scale[0] = 1e-9f;
+			if (scale[1] == 0.0f)
+				scale[1] = 1e-9f;
+			invert_v2(scale);
+
+			/* Finally, transform all vcos_2d into ((0, 0), (1, 1)) square and assing them as origspace. */
+			for (j = 0; j < mp->totloop; j++, lof++) {
+				add_v2_v2v2(lof->uv, vcos_2d[j], translate);
+				mul_v2_v2(lof->uv, scale);
+			}
+		}
 	}
 
 	dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+	BLI_array_free(vcos_2d);
 }
 
 
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 89f22b8..b448bec 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -364,10 +364,15 @@ void BKE_object_free_caches(Object *object)
 	for (md = object->modifiers.first; md != NULL; md = md->next) {
 		if (md->type == eModifierType_ParticleSystem) {
 			ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
-			if (psmd->dm != NULL) {
-				psmd->dm->needsFree = 1;
-				psmd->dm->release(psmd->dm);
-				psmd->dm = NULL;
+			if (psmd->dm_final != NULL) {
+				psmd->dm_final->needsFree = 1;
+				psmd->dm_final->release(psmd->dm_final);
+				psmd->dm_final = NULL;
+				if (psmd->dm_deformed != NULL) {
+					psmd->dm_deformed->needsFree = 1;
+					psmd->dm_deformed->release(psmd->dm_deformed);
+					psmd->dm_deformed = NULL;
+				}
 				psmd->flag |= eParticleSystemFlag_file_loaded;
 				update_flag |= OB_RECALC_DATA;
 			}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index b3be567..39f0e7c 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -623,8 +623,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
 	data->childcachebufs.last = psys->childcachebufs.last;
 	data->totchildcache = psys->totchildcache;
 
-	if (psmd->dm)
-		data->dm = CDDM_copy(psmd->dm);
+	if (psmd->dm_final)
+		data->dm = CDDM_copy(psmd->dm_final);
 	data->totdmvert = psmd->totdmvert;
 	data->totdmedge = psmd->totdmedge;
 	data->totdmface = psmd->totdmface;
@@ -651,7 +651,7 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
 		psys->recalc |= PSYS_RECALC_RESET;
 }
 
-void psys_render_restore(Object *ob, ParticleSystem *psys)
+void psys_render_restore(Scene *scene, Object *ob, ParticleSystem *psys)
 {
 	ParticleRenderData *data;
 	ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
@@ -665,9 +665,14 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
 	if (data->elems)
 		MEM_freeN(data->elems);
 
-	if (psmd->dm) {
-		psmd->dm->needsFree = 1;
-		psmd->dm->release(psmd->dm);
+	if (psmd->dm_final) {
+		psmd->dm_final->needsFree = 1;
+		psmd->dm_final->release(psmd->dm_final);
+	}
+	if (psmd->dm_deformed) {
+		psmd->dm_deformed->needsFree = 1;
+		psmd->dm_deformed->release(psmd->dm_deformed);
+		psmd->dm_deformed = NULL;
 	}
 
 	psys_free_path_cache(psys, NULL);
@@ -689,14 +694,19 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
 	psys->childcachebufs.last = data->childcachebufs.last;
 	psys->totchildcache = data->totchildcache;
 
-	psmd->dm = data->dm;
+	psmd->dm_final = data->dm;
 	psmd->totdmvert = data->totdmvert;
 	psmd->totdmedge = data->totdmedge;
 	psmd->totdmface = data->totdmface;
 	psmd->flag &= ~eParticleSystemFlag_psys_updated;
 
-	if (psmd->dm)
-		psys_calc_dmcache(ob, psmd->dm, psys);
+	if (psmd->dm_final) {
+		if (!psmd->dm_final->deformedOnly) {
+			psmd->dm_deformed = CDDM_copy(mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE));
+			DM_ensure_tessface(psmd->dm_deformed);
+		}
+		psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
+	}
 
 	MEM_freeN(data);
 	psys->renderdata = NULL;
@@ -1383,78 +1393,114 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4
 	}
 }
 
-/* find the derived mesh face for a particle, set the mf passed. this is slow
- * and can be optimized but only for many lookups. returns the face index. */
-int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node)
+/**
+ * Find the final derived mesh tessface for a particle, from its original tessface index.
+ * This is slow and can be optimized but only for many lookups.
+ *
+ * \param dm_final final DM, it may not have the same topology as original mesh.
+ * \param dm_deformed deformed-only DM, it has the exact same topology as original mesh.
+ * \param findex_orig the input tessface index.
+ * \param fw face weights (position of the particle inside the \a findex_orig tessface).
+ * \param poly_nodes may be NULL, otherwise an array of linked list, one for each final DM polygon, containing all
+ *                   its tessfaces indices.
+ * \return the DM tessface index.
+ */
+int psys_particle_dm_face_lookup(
+        DerivedMesh *dm_final, DerivedMesh *dm_deformed,
+        int findex_orig, const float fw[4], struct LinkNode **poly_nodes)
 {
-	Mesh *me = (Mesh *)ob->data;
-	MPoly *mpoly;
-	OrigSpaceFace *osface;
-	int quad, findex, totface;
+	MFace *mtessface_final;
+	OrigSpaceFace *osface_final;
+	int totface_final;
+	int pindex_orig;
 	float uv[2], (*faceuv)[2];
 
-	/* double lookup */
-	const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
-	const int *index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-	if (index_mf_to_mpoly == NULL) {
-		index_mp_to_orig = NULL;
+	const int *index_mf_to_mpoly_deformed = NULL;
+	const int *index_mf_to_mpoly = NULL;
+	const int *index_mp_to_orig = NULL;
+
+	index_mf_to_mpoly = dm_final->getTessFaceDataArray(dm_final, CD_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list