[Bf-blender-cvs] [159985a] hair_immediate_fixes: CustomData layer for storing hair root locations as MSurfaceSamples.

Lukas Tönne noreply at git.blender.org
Sat Dec 27 11:31:57 CET 2014


Commit: 159985a2c1877bdc62da8ae2554e5fe4896d667d
Author: Lukas Tönne
Date:   Fri Nov 28 12:42:50 2014 +0100
Branches: hair_immediate_fixes
https://developer.blender.org/rB159985a2c1877bdc62da8ae2554e5fe4896d667d

CustomData layer for storing hair root locations as MSurfaceSamples.

This requires converting the old messy particle num/num_dmcache/fuv/foffset
data into the new mesh samples, which can potentially introduce floating
point errors and inaccuracies due to lack of face index mapping in the
new system. However, in any well-constructed particle system the hair
roots should be nearest to their num face, so mapping would be accurate
enough. If necessary face index data could be added to samples as a
legacy code hack, but probably it's best to eventually replace the
hair system as a whole anyway.

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

M	source/blender/blenkernel/BKE_mesh_sample.h
M	source/blender/blenkernel/BKE_particle.h
M	source/blender/blenkernel/intern/edithair_particles.c
M	source/blender/blenkernel/intern/mesh_sample.c
M	source/blender/blenkernel/intern/particle.c
M	source/blender/bmesh/intern/bmesh_strands_conv.c
M	source/blender/bmesh/intern/bmesh_strands_conv.h
M	source/blender/makesdna/DNA_customdata_types.h

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

diff --git a/source/blender/blenkernel/BKE_mesh_sample.h b/source/blender/blenkernel/BKE_mesh_sample.h
index 7bcce9f..bc125af 100644
--- a/source/blender/blenkernel/BKE_mesh_sample.h
+++ b/source/blender/blenkernel/BKE_mesh_sample.h
@@ -49,4 +49,13 @@ void BKE_mesh_sample_storage_release(struct MSurfaceSampleStorage *storage);
 
 void BKE_mesh_sample_generate_random(MSurfaceSampleStorage *dst, struct DerivedMesh *dm, unsigned int seed, int totsample);
 
+/* ==== Utilities ==== */
+
+struct ParticleSystem;
+struct ParticleData;
+struct BVHTreeFromMesh;
+
+bool BKE_mesh_sample_from_particle(struct MSurfaceSample *sample, struct ParticleSystem *psys, struct DerivedMesh *dm, struct ParticleData *pa);
+bool BKE_mesh_sample_to_particle(struct MSurfaceSample *sample, struct ParticleSystem *psys, struct DerivedMesh *dm, struct BVHTreeFromMesh *bvhtree, struct ParticleData *pa);
+
 #endif  /* __BKE_MESH_SAMPLE_H__ */
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 42cbd5d..212eeb4 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -404,6 +404,7 @@ void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFa
                            float orco[3], float ornor[3]);
 float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values);
 void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time);
+int psys_get_index_on_dm(struct ParticleSystem *psys, struct DerivedMesh *dm, ParticleData *pa, int *mapindex, float mapfw[4]);
 
 /* BLI_bvhtree_ray_cast callback */
 void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
diff --git a/source/blender/blenkernel/intern/edithair_particles.c b/source/blender/blenkernel/intern/edithair_particles.c
index 785ee00..dc245d9 100644
--- a/source/blender/blenkernel/intern/edithair_particles.c
+++ b/source/blender/blenkernel/intern/edithair_particles.c
@@ -33,32 +33,53 @@
 
 #include "BLI_math.h"
 
+#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_particle_types.h"
 
+#include "BKE_bvhutils.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_edithair.h"
 #include "BKE_particle.h"
 
 #include "intern/bmesh_strands_conv.h"
 
-BMesh *BKE_particles_to_bmesh(Object *UNUSED(ob), ParticleSystem *psys)
+BMesh *BKE_particles_to_bmesh(Object *ob, ParticleSystem *psys)
 {
-	BMesh *bm;
+	ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
+	
 	const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_PSYS(psys);
+	BMesh *bm;
 
 	bm = BM_mesh_create(&allocsize);
 
-	BM_strands_bm_from_psys(bm, psys, true, psys->shapenr);
+	if (psmd && psmd->dm) {
+		DM_ensure_tessface(psmd->dm);
+		
+		BM_strands_bm_from_psys(bm, psys, psmd->dm, true, psys->shapenr);
+	}
 
 	return bm;
 }
 
-void BKE_particles_from_bmesh(Object *UNUSED(ob), ParticleSystem *psys)
+void BKE_particles_from_bmesh(Object *ob, ParticleSystem *psys)
 {
+	ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
 	BMesh *bm = psys->hairedit ? psys->hairedit->bm : NULL;
 	
-	if (bm)
-		BM_strands_bm_to_psys(bm, psys);
+	if (bm) {
+		if (psmd && psmd->dm) {
+			BVHTreeFromMesh bvhtree = {NULL};
+			
+			DM_ensure_tessface(psmd->dm);
+			
+			bvhtree_from_mesh_faces(&bvhtree, psmd->dm, 0.0, 2, 6);
+			
+			BM_strands_bm_to_psys(bm, psys, psmd->dm, &bvhtree);
+			
+			free_bvhtree_from_mesh(&bvhtree);
+		}
+	}
 }
 
 
diff --git a/source/blender/blenkernel/intern/mesh_sample.c b/source/blender/blenkernel/intern/mesh_sample.c
index d1493f3..7300dbe 100644
--- a/source/blender/blenkernel/intern/mesh_sample.c
+++ b/source/blender/blenkernel/intern/mesh_sample.c
@@ -151,3 +151,93 @@ void BKE_mesh_sample_generate_random(MSurfaceSampleStorage *dst, DerivedMesh *dm
 	
 	BLI_rng_free(rng);
 }
+
+/* ==== Utilities ==== */
+
+#include "DNA_particle_types.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_particle.h"
+
+bool BKE_mesh_sample_from_particle(MSurfaceSample *sample, ParticleSystem *psys, DerivedMesh *dm, ParticleData *pa)
+{
+	MVert *mverts;
+	MFace *mface;
+	float mapfw[4];
+	int mapindex;
+	float *co1 = NULL, *co2 = NULL, *co3 = NULL, *co4 = NULL;
+	float vec[3];
+	float w[4];
+	
+	if (!psys_get_index_on_dm(psys, dm, pa, &mapindex, mapfw))
+		return false;
+	
+	mface = dm->getTessFaceData(dm, mapindex, CD_MFACE);
+	mverts = dm->getVertDataArray(dm, CD_MVERT);
+	
+	co1 = mverts[mface->v1].co;
+	co2 = mverts[mface->v2].co;
+	co3 = mverts[mface->v3].co;
+	
+	if (mface->v4) {
+		co4 = mverts[mface->v4].co;
+		
+		interp_v3_v3v3v3v3(vec, co1, co2, co3, co4, mapfw);
+	}
+	else {
+		interp_v3_v3v3v3(vec, co1, co2, co3, mapfw);
+	}
+	
+	/* test both triangles of the face */
+	interp_weights_face_v3(w, co1, co2, co3, NULL, vec);
+	if (w[0] <= 1.0f && w[1] <= 1.0f && w[2] <= 1.0f) {
+		sample->orig_verts[0] = mface->v1;
+		sample->orig_verts[1] = mface->v2;
+		sample->orig_verts[2] = mface->v3;
+	
+		copy_v3_v3(sample->orig_weights, w);
+		return true;
+	}
+	else if (mface->v4) {
+		interp_weights_face_v3(w, co3, co4, co1, NULL, vec);
+		sample->orig_verts[0] = mface->v3;
+		sample->orig_verts[1] = mface->v4;
+		sample->orig_verts[2] = mface->v1;
+	
+		copy_v3_v3(sample->orig_weights, w);
+		return true;
+	}
+	else
+		return false;
+}
+
+bool BKE_mesh_sample_to_particle(MSurfaceSample *sample, ParticleSystem *UNUSED(psys), DerivedMesh *dm, BVHTreeFromMesh *bvhtree, ParticleData *pa)
+{
+	BVHTreeNearest nearest;
+	float vec[3], nor[3];
+	
+	BKE_mesh_sample_eval(dm, sample, vec, nor);
+	
+	nearest.index = -1;
+	nearest.dist_sq = FLT_MAX;
+	BLI_bvhtree_find_nearest(bvhtree->tree, vec, &nearest, bvhtree->nearest_callback, bvhtree);
+	if (nearest.index >= 0) {
+		MFace *mface = dm->getTessFaceData(dm, nearest.index, CD_MFACE);
+		MVert *mverts = dm->getVertDataArray(dm, CD_MVERT);
+		
+		float *co1 = mverts[mface->v1].co;
+		float *co2 = mverts[mface->v2].co;
+		float *co3 = mverts[mface->v3].co;
+		float *co4 = mface->v4 ? mverts[mface->v4].co : NULL;
+		
+		pa->num = nearest.index;
+		pa->num_dmcache = DMCACHE_NOTFOUND;
+		
+		interp_weights_face_v3(pa->fuv, co1, co2, co3, co4, vec);
+		pa->foffset = 0.0f; /* XXX any sensible way to reconstruct this? */
+		
+		return true;
+	}
+	else
+		return false;
+}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 458144c..8500dee 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1546,6 +1546,11 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
 	return 1;
 }
 
+int psys_get_index_on_dm(ParticleSystem *psys, DerivedMesh *dm, ParticleData *pa, int *mapindex, float mapfw[4])
+{
+	return psys_map_index_on_dm(dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, mapindex, mapfw);
+}
+
 /* interprets particle data to get a point on a mesh in object space */
 void psys_particle_on_dm(DerivedMesh *dm, 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],
diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.c b/source/blender/bmesh/intern/bmesh_strands_conv.c
index d9eabd9..5238c24 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.c
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.c
@@ -39,6 +39,7 @@
 #include "BKE_customdata.h"
 #include "BKE_key.h"
 #include "BKE_main.h"
+#include "BKE_mesh_sample.h"
 #include "BKE_particle.h"
 
 #include "bmesh.h"
@@ -46,6 +47,25 @@
 
 const char *CD_PSYS_MASS = "PSYS_MASS";
 const char *CD_PSYS_WEIGHT = "PSYS_WEIGHT";
+const char *CD_PSYS_ROOT_LOCATION = "PSYS_ROOT_LOCATION";
+
+static void BM_elem_msample_data_named_get(CustomData *cd, void *element, int type, const char *name, MSurfaceSample *val)
+{
+	const MSurfaceSample *s = CustomData_bmesh_get_named(cd, ((BMHeader *)element)->data, type, name);
+	if (s)
+		memcpy(val, s, sizeof(MSurfaceSample));
+	else
+		memset(val, 0, sizeof(MSurfaceSample));
+}
+
+static void BM_elem_msample_data_named_set(CustomData *cd, void *element, int type, const char *name, const MSurfaceSample *val)
+{
+	MSurfaceSample *s = CustomData_bmesh_get_named(cd, ((BMHeader *)element)->data, type, name);
+	if (s)
+		memcpy(s, val, sizeof(MSurfaceSample));
+}
+
+/* ------------------------------------------------------------------------- */
 
 int BM_strands_count_psys_keys(ParticleSystem *psys)
 {
@@ -92,6 +112,9 @@ void BM_strands_cd_flag_apply(BMesh *bm, const char UNUSED(cd_flag))
 	if (CustomData_get_named_layer_index(&bm->vdata, CD_PROP_FLT, CD_PSYS_WEIGHT) < 0) {
 		BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLT, CD_PSYS_WEIGHT);
 	}
+	if (CustomData_get_named_layer_index(&bm->vdata, CD_MSURFACE_SAMPLE, CD_PSYS_ROOT_LOCATION) < 0) {
+		BM_data_layer_add_named(bm, &bm->vdata, CD_MSURFACE_SAMPLE, CD_PSYS_ROOT_LOCATION);
+	}
 }
 
 char BM_strands_cd_flag_from_bmesh(BMesh *UNUSED(bm))
@@ -148,7 +171,7 @@ static KeyBlock *bm_set_shapekey_from_psys(BMesh *bm, ParticleSystem *psys, int
 }
 
 /* create vertex and edge data for BMesh based on particle hair keys */
-static void bm_make_particles(BMesh *bm, ParticleSystem *psys, float (*keyco)[3], int cd_shape_keyindex_offset)
+static void bm_make_particles(BMesh *bm, ParticleSystem *psys, struct DerivedMesh *emitter_dm, float (*keyco)[3], int cd_shape_keyindex_offset)
 {
 	KeyBlock *block;
 	ParticleData *pa;
@@ -187,6 +210,14 @@ static void bm_make_particles(BMesh *bm, ParticleSystem *psys, float (*keyco)[3]
 			BM_elem_float_data_named_set(&bm->vdata, v, CD_PROP_FLT, CD_PSYS_MASS, mass);
 			BM_elem_float_data_named_set(&bm->vdata, v, CD_PROP_FLT, CD_PSYS_WEIGHT, hkey->weight);
 			
+			/* root */
+			if (k == 0) {
+				MSurfaceSample root_loc;
+				if (BKE_mesh_sample_from_particle(&root_loc, psys, emitter_dm, pa)) {
+					BM_elem_msample_data_named_set(&bm->vdata, v, CD_MSURFACE_SAMPLE, CD_PSYS_ROOT_LOCATION, &root_loc);
+				}
+			}
+			
 			/* set shapekey data */
 			if (psys->key) {
 				/* set shape key original index */
@@ -228,7 +259,

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list