[Bf-blender-cvs] [24caf4f] alembic: Major optimization for cache size when storing child strands.

Lukas Tönne noreply at git.blender.org
Tue Apr 14 11:06:25 CEST 2015


Commit: 24caf4f98fffdb5372e4b3459f6b2ee8d4184a35
Author: Lukas Tönne
Date:   Tue Apr 14 10:59:52 2015 +0200
Branches: alembic
https://developer.blender.org/rB24caf4f98fffdb5372e4b3459f6b2ee8d4184a35

Major optimization for cache size when storing child strands.

The basis for this optimization is that child strands have a shape that
does not actually change over time: the particle code does not enforce
this formally, but in fact all the clump/kink/roughness algorithms take
great care to not introduce changes of shape over time.

The final look of child hairs is achieved only by following the parent
hair deformation, i.e. by applying the offset of the matching parametric
position on the parent strand.

This means that for caching child strands it is sufficient to store the
full vertex data only in the first sample, and then apply the parent
deformation on subsequent frames using only the animated root matrices.

In test cases this seems to reduce the cache size to something between
10-20 % of the original size (down to some hundred MB from some 10 GB).
Further optimizations could be achieved by using smaller data types,
such as quaternions instead of 3x3 or 4x4 matrices for the remaining
child data.

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

M	source/blender/blenkernel/BKE_particle.h
M	source/blender/blenkernel/BKE_strands.h
M	source/blender/blenkernel/intern/cache_library.c
M	source/blender/blenkernel/intern/object_dupli.c
M	source/blender/blenkernel/intern/particle.c
M	source/blender/blenkernel/intern/strands.c
M	source/blender/makesdna/DNA_strands_types.h
M	source/blender/pointcache/alembic/abc_particles.cpp
M	source/blender/pointcache/alembic/abc_particles.h

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

diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 27eeb09..767d631 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -393,6 +393,7 @@ void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float
 void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
 void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
 void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
+void psys_child_mat_to_object(struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct ChildParticle *cpa, float hairmat[4][4]);
 
 float psys_get_dietime_from_cache(struct PointCache *cache, int index);
 
diff --git a/source/blender/blenkernel/BKE_strands.h b/source/blender/blenkernel/BKE_strands.h
index 4d9c365..daee2f9 100644
--- a/source/blender/blenkernel/BKE_strands.h
+++ b/source/blender/blenkernel/BKE_strands.h
@@ -39,7 +39,7 @@ void BKE_strands_get_minmax(struct Strands *strands, float min[3], float max[3],
 struct StrandsChildren *BKE_strands_children_new(int strands, int verts);
 void BKE_strands_children_free(struct StrandsChildren *strands);
 
-void BKE_strands_children_deform_from_parents(struct StrandsChildren *strands, struct Strands *parents);
+void BKE_strands_children_deform(struct StrandsChildren *strands, struct Strands *parents, bool use_motion);
 
 void BKE_strands_children_ensure_normals(struct StrandsChildren *strands);
 
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index ee60206..8b9e3ac 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -413,7 +413,7 @@ bool BKE_cache_read_dupli_cache(CacheLibrary *cachelib, DupliCache *dupcache,
 	 * Note that this is an optional feature for viewport/render display,
 	 * strand motion is not usually applied to children in caches.
 	 */
-	if (for_display && read_strands_motion && read_strands_children) {
+	if (for_display && read_strands_children) {
 		struct  DupliCacheIterator *it = BKE_dupli_cache_iter_new(dupcache);
 		for (; BKE_dupli_cache_iter_valid(it); BKE_dupli_cache_iter_next(it)) {
 			DupliObjectData *dobdata = BKE_dupli_cache_iter_get(it);
@@ -421,7 +421,7 @@ bool BKE_cache_read_dupli_cache(CacheLibrary *cachelib, DupliCache *dupcache,
 			
 			for (link = dobdata->strands.first; link; link = link->next) {
 				if (link->strands_children)
-					BKE_strands_children_deform_from_parents(link->strands_children, link->strands);
+					BKE_strands_children_deform(link->strands_children, link->strands, read_strands_motion);
 			}
 		}
 		BKE_dupli_cache_iter_free(it);
@@ -462,11 +462,11 @@ bool BKE_cache_read_dupli_object(CacheLibrary *cachelib, DupliObjectData *data,
 	 * Note that this is an optional feature for viewport/render display,
 	 * strand motion is not usually applied to children in caches.
 	 */
-	if (for_display && read_strands_motion && read_strands_children) {
+	if (for_display && read_strands_children) {
 		DupliObjectDataStrands *link;
 		for (link = data->strands.first; link; link = link->next) {
 			if (link->strands_children)
-				BKE_strands_children_deform_from_parents(link->strands_children, link->strands);
+				BKE_strands_children_deform(link->strands_children, link->strands, read_strands_motion);
 		}
 	}
 	
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 870a9f8..b65d4f5 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -1661,6 +1661,7 @@ void BKE_dupli_cache_from_group(Scene *scene, Group *group, CacheLibrary *cachel
 							
 							for (k = 0, hkey = pa->hair; k < pa->totkey; ++k, ++hkey) {
 								copy_v3_v3(svert->co, hkey->co);
+								copy_v3_v3(svert->base, hkey->co); // XXX should be base for child deform, but not accessible here */
 								svert->time = hkey->time;
 								svert->weight = hkey->weight;
 								
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 5d553f5..8a2e9a3 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3009,6 +3009,25 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa
 	mul_m4_m4m4(hairmat, ob->obmat, facemat);
 }
 
+void psys_child_mat_to_object(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ChildParticle *cpa, float hairmat[4][4])
+{
+	const bool between = (psys->part->childtype == PART_CHILD_FACES);
+	float co[3];
+	
+	if (between) {
+		ParticleData *pa = &psys->particles[cpa->pa[0]];
+		psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, NULL, NULL, NULL, NULL, NULL);
+		psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
+	}
+	else {
+		ParticleData *pa = &psys->particles[cpa->parent];
+		psys_particle_on_emitter(psmd, psys->part->from, pa->num, DMCACHE_ISCHILD, pa->fuv, pa->foffset, co, NULL, NULL, NULL, NULL, NULL);
+		psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
+	}
+	
+	copy_v3_v3(hairmat[3], co);
+}
+
 /************************************************/
 /*			ParticleSettings handling			*/
 /************************************************/
diff --git a/source/blender/blenkernel/intern/strands.c b/source/blender/blenkernel/intern/strands.c
index 85a0b24..313b03f9 100644
--- a/source/blender/blenkernel/intern/strands.c
+++ b/source/blender/blenkernel/intern/strands.c
@@ -196,63 +196,82 @@ static int *strands_calc_vertex_start(Strands *strands)
 	return vertstart;
 }
 
-void BKE_strands_children_deform_from_parents(StrandsChildren *strands, Strands *parents)
+static void strands_children_apply_parent_deform(StrandChildIterator *it_strand, Strands *parents, int *vertstart, bool use_motion)
 {
-	int *vertstart;
-	StrandChildIterator it_strand;
+	int i;
 	
-	if (!parents || !parents->state)
+	if (!parents || !vertstart)
 		return;
 	
-	vertstart = strands_calc_vertex_start(parents);
+	if (!parents->state)
+		use_motion = false;
 	
-	if (!vertstart)
-		return;
-	
-	for (BKE_strand_child_iter_init(&it_strand, strands); BKE_strand_child_iter_valid(&it_strand); BKE_strand_child_iter_next(&it_strand)) {
-		int i;
-		
-		for (i = 0; i < 4; ++i) {
-			int p = it_strand.curve->parents[i];
-			float w = it_strand.curve->parent_weights[i];
-			if (p >= 0 && w > 0.0f) {
-				StrandsCurve *parent = &parents->curves[p];
-				StrandsVertex *pverts;
-				StrandsMotionState *pstate;
-				int pv0, pv1;
-				StrandChildVertexIterator it_vert;
+	for (i = 0; i < 4; ++i) {
+		int p = it_strand->curve->parents[i];
+		float w = it_strand->curve->parent_weights[i];
+		if (p >= 0 && w > 0.0f) {
+			StrandsCurve *parent = &parents->curves[p];
+			StrandsVertex *pverts;
+			StrandsMotionState *pstate;
+			int pv0, pv1;
+			StrandChildVertexIterator it_vert;
+			
+			if (parent->numverts <= 0)
+				continue;
+			
+			pverts = &parents->verts[vertstart[p]];
+			pstate = &parents->state[vertstart[p]];
+			pv0 = 0;
+			for (BKE_strand_child_vertex_iter_init(&it_vert, it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) {
+				float time = it_vert.vertex->time;
+				float dt, x;
+				float poffset0[3], poffset1[3], offset[3];
 				
-				if (parent->numverts <= 0)
-					continue;
+				/* advance to the matching parent edge for interpolation */
+				while (pv0 < parent->numverts-1 && pverts[pv0+1].time < time)
+					++pv0;
+				pv1 = (pv0 < parent->numverts-1)? pv0+1 : pv0;
 				
-				pverts = &parents->verts[vertstart[p]];
-				pstate = &parents->state[vertstart[p]];
-				pv0 = 0;
-				for (BKE_strand_child_vertex_iter_init(&it_vert, &it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) {
-					float time = it_vert.vertex->time;
-					float dt, x;
-					float poffset0[3], poffset1[3], offset[3];
-					
-					/* advance to the matching parent edge for interpolation */
-					while (pv0 < parent->numverts-1 && pverts[pv0+1].time < time)
-						++pv0;
-					pv1 = (pv0 < parent->numverts-1)? pv0+1 : pv0;
-					
-					sub_v3_v3v3(poffset0, pstate[pv0].co, pverts[pv0].co);
-					sub_v3_v3v3(poffset1, pstate[pv1].co, pverts[pv1].co);
-					
-					dt = pverts[pv1].time - pverts[pv0].time;
-					x = dt > 0.0f ? (time - pverts[pv0].time) / dt : 0.0f;
-					CLAMP(x, 0.0f, 1.0f);
-					interp_v3_v3v3(offset, poffset0, poffset1, x);
-					
-					madd_v3_v3fl(it_vert.vertex->co, offset, w);
+				if (use_motion) {
+					sub_v3_v3v3(poffset0, pstate[pv0].co, pverts[pv0].base);
+					sub_v3_v3v3(poffset1, pstate[pv1].co, pverts[pv1].base);
+				}
+				else {
+					sub_v3_v3v3(poffset0, pverts[pv0].co, pverts[pv0].base);
+					sub_v3_v3v3(poffset1, pverts[pv1].co, pverts[pv1].base);
 				}
+				
+				dt = pverts[pv1].time - pverts[pv0].time;
+				x = dt > 0.0f ? (time - pverts[pv0].time) / dt : 0.0f;
+				CLAMP(x, 0.0f, 1.0f);
+				interp_v3_v3v3(offset, poffset0, poffset1, x);
+				
+				madd_v3_v3fl(it_vert.vertex->co, offset, w);
 			}
 		}
 	}
+}
+
+void BKE_strands_children_deform(StrandsChildren *strands, Strands *parents, bool use_motion)
+{
+	int *vertstart;
+	StrandChildIterator it_strand;
+	
+	if (parents)
+		vertstart = strands_calc_vertex_start(parents);
+	
+	for (BKE_strand_child_iter_init(&it_strand, strands); BKE_strand_child_iter_valid(&it_strand); BKE_strand_child_iter_next(&it_strand)) {
+		/* move child strands from their local root space to object space */
+		StrandChildVertexIterator it_vert;
+		for (BKE_strand_child_vertex_iter_init(&it_vert, &it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) {
+			mul_m4_v3(it_strand.curve->root_matrix, it_vert.vertex->co);
+		}
+		
+		strands_children_apply_parent_deform(&it_stran

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list