[Bf-blender-cvs] [d57bd6e] gooseberry: Sorting of child particles by primary parent and offset in hair space.

Lukas Tönne noreply at git.blender.org
Thu Jan 22 19:51:19 CET 2015


Commit: d57bd6e71b00e51cf3fb755aeaf8c5fc27dbd50a
Author: Lukas Tönne
Date:   Thu Jan 22 13:28:14 2015 +0100
Branches: gooseberry
https://developer.blender.org/rBd57bd6e71b00e51cf3fb755aeaf8c5fc27dbd50a

Sorting of child particles by primary parent and offset in hair space.

This is a prerequisite for constructing the convex hull of child paths
around a parent.

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

M	source/blender/blenkernel/intern/particle_distribute.c

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

diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 7a422ab..a721bf5 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -32,6 +32,7 @@
  */
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -1152,6 +1153,90 @@ static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSE
 	fprintf(stderr,"Shape emission not yet possible!\n");
 }
 
+/* placeholder for child particle sorting, storing emitter hair-space offset */
+typedef struct ChildParticleSort {
+	int index;
+	float x, y;
+	int parent;
+} ChildParticleSort;
+
+/* comparison function for sorting children.
+ * primary criterion is the childrens' primary parent
+ * secondary criterion is the combined offset from the parent in the tangential plane,
+ *   which is needed for further constructing the convex hull of children around each parent
+ */
+static int psys_child_cmp(const void *a, const void *b)
+{
+	const ChildParticleSort *cpa_a = a, *cpa_b = b;
+	
+	if (UNLIKELY(cpa_a->parent == cpa_b->parent)) {
+		if (UNLIKELY(cpa_a->x == cpa_b->x))
+			return cpa_a->y < cpa_b->y ? -1 : 1;
+		else
+			return cpa_a->x < cpa_b->x ? -1 : 1;
+	}
+	else
+		return cpa_a->parent < cpa_b->parent ? -1 : 1;
+}
+
+/* sort children by primary parent and relative emitter location,
+ * then calculate convex hulls using Andrew's Monotone Chain algorithm
+ * http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
+ */
+static void psys_sort_children(ParticleSimulationData *sim)
+{
+	ParticleSystem *psys = sim->psys;
+	ParticleSettings *part = psys->part;
+	const bool between = (part->childtype == PART_CHILD_FACES);
+	const int cpa_from = between ? PART_FROM_FACE : part->from;
+	
+	ChildParticleSort *childdata;
+	int i;
+	
+	if (psys->totchild == 0)
+		return;
+	if (!sim->psmd->dm)
+		return;
+	
+	childdata = MEM_mallocN(sizeof(ChildParticleSort) * psys->totchild, "child sorting data");
+	
+	for (i = 0; i < psys->totchild; ++i) {
+		ChildParticle *cpa = &psys->child[i];
+		ChildParticleSort *cdata = &childdata[i];
+		
+		ParticleData *parent;
+		float co[3], hairmat[4][4], hairimat[4][4];
+		
+		cdata->index = i;
+		cdata->parent = between ? cpa->pa[0] : cpa->parent;
+		
+		psys_particle_on_emitter(sim->psmd, cpa_from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, NULL, NULL, NULL, NULL, NULL);
+		
+		parent = &psys->particles[cdata->parent];
+		psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, parent, hairmat);
+		invert_m4_m4(hairimat, hairmat);
+		
+		mul_m4_v3(hairimat, co);
+		cdata->x = co[0];
+		cdata->y = co[1];
+	}
+	
+	qsort(childdata, psys->totchild, sizeof(ChildParticleSort), psys_child_cmp);
+	
+	{
+		ChildParticle *nchild = MEM_mallocN(sizeof(ChildParticle) * psys->totchild, "sorted child particles");
+		
+		for (i = 0; i < psys->totchild; ++i) {
+			memcpy(nchild + i, psys->child + childdata[i].index, sizeof(ChildParticle));
+		}
+		
+		MEM_freeN(psys->child);
+		psys->child = nchild;
+	}
+	
+	MEM_freeN(childdata);
+}
+
 void distribute_particles(ParticleSimulationData *sim, int from)
 {
 	PARTICLE_PSMD;
@@ -1166,6 +1251,9 @@ void distribute_particles(ParticleSimulationData *sim, int from)
 	else
 		distribute_particles_on_shape(sim, from);
 
+	if (from == PART_FROM_CHILD)
+		psys_sort_children(sim);
+
 	if (distr_error) {
 		distribute_invalid(sim->scene, sim->psys, from);




More information about the Bf-blender-cvs mailing list