[Bf-blender-cvs] [fec39ff862a] hair_guides_grooming: Function for generating guide curve vertices from groom data.

Lukas Tönne noreply at git.blender.org
Mon Jun 25 08:40:31 CEST 2018


Commit: fec39ff862a4faaf490e5cc1b4148f7dc360f5b6
Author: Lukas Tönne
Date:   Mon Jun 25 07:37:44 2018 +0100
Branches: hair_guides_grooming
https://developer.blender.org/rBfec39ff862a4faaf490e5cc1b4148f7dc360f5b6

Function for generating guide curve vertices from groom data.

This should eventually allow re-sampling vertices add equal distances,
as well as allowing for additional deformation (e.g. curls).

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

M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/groom.c

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

diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 73f8e3d9c12..adea3696893 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -55,6 +55,12 @@ void BKE_hair_free(struct HairSystem *hsys);
 
 /* === Guide Strands === */
 
+/* Allocate buffers for defining guide curves
+ * \param totcurves Number of guide curves to allocate
+ * \param totverts Number of guide curve vertices to allocate
+ */
+void BKE_hair_guide_curves_alloc(struct HairSystem *hsys, int totcurves, int totverts);
+
 /* Allocate buffers for defining guide curves
  * \param totcurves Number of guide curves to allocate
  */
diff --git a/source/blender/blenkernel/intern/groom.c b/source/blender/blenkernel/intern/groom.c
index bb992304581..704f2b25ad9 100644
--- a/source/blender/blenkernel/intern/groom.c
+++ b/source/blender/blenkernel/intern/groom.c
@@ -36,6 +36,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_array.h"
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
@@ -859,6 +860,68 @@ void BKE_groom_hair_distribute(const Depsgraph *depsgraph, Groom *groom, unsigne
 	}
 }
 
+typedef struct GroomGuideVertex
+{
+	int flag;
+	float co[3];
+} GroomGuideVertex;
+
+static void groom_guide_buffer_reserve(int reserve, GroomGuideVertex **r_verts, int *r_totalloc)
+{
+	if (reserve > *r_totalloc)
+	{
+		static const int blocksize = 1024;
+		int totalloc = (int)((reserve + blocksize - 1) / blocksize) * blocksize;
+		
+		*r_verts = MEM_reallocN_id(*r_verts, sizeof(**r_verts) * totalloc, __func__);
+		*r_totalloc = totalloc;
+	}
+}
+
+/* Generate vertices for the curve based on a guide function.
+ * The guide function maps 1D parametric space to a continuous 3D position and direction.
+ * 
+ * \param stepsize      Desired distance between guide curve vertices
+ * \param maxverts      Maximum number of allowed vertices
+ * \param r_verts       Array of vertices generated for the guide curve
+ * \param r_numverts    Reserved size of the vertex array
+ * \param r_numused     Number of vertices in the guide curve
+ */
+static void groom_guide_curve_discretize(
+        const GroomRegion *region,
+        int guide_idx,
+        float stepsize,
+        int maxverts,
+        GroomGuideVertex **r_verts,
+        int *r_totalloc,
+        int *r_totverts)
+{
+	const GroomBundle *bundle = &region->bundle;
+	const int shapesize = region->numverts;
+	const int curvesize = bundle->curvesize;
+	const float *weights = &bundle->guide_shape_weights[guide_idx * shapesize];
+
+	int totverts = *r_totverts;
+	for (int i = 0; i < curvesize; ++i)
+	{
+		if (*r_totverts < maxverts)
+		{
+			totverts += 1;
+			groom_guide_buffer_reserve(totverts, r_verts, r_totalloc);
+			
+			GroomGuideVertex *v = &((*r_verts)[totverts - 1]);
+			/* Compute barycentric guide location from shape */
+			zero_v3(v->co);
+			for (int j = 0; j < shapesize; ++j)
+			{
+				madd_v3_v3fl(v->co, bundle->curvecache[j * curvesize + i].co, weights[j]);
+			}
+			v->flag = 0;
+		}
+	}
+	*r_totverts = totverts;
+}
+
 void BKE_groom_hair_update_guide_curves(const Depsgraph *depsgraph, Groom *groom)
 {
 	struct HairSystem *hsys = groom->hair_system;
@@ -872,50 +935,64 @@ void BKE_groom_hair_update_guide_curves(const Depsgraph *depsgraph, Groom *groom
 		totguides += bundle->totguides;
 	}
 	
-	/* First declare all guide curves and lengths */
-	BKE_hair_guide_curves_begin(hsys, totguides);
-	for (const GroomRegion *region = regions->first; region; region = region->next)
+	GroomGuideVertex *verts = NULL;
+	int totalloc = 0;
+	//groom_guide_buffer_reserve(totverts_est, &verts, &totalloc);
+	
+	int *numverts = MEM_callocN(sizeof(int) * totguides, __func__);
+	int totverts = 0;
+	// TODO multithreading here
 	{
-		const GroomBundle *bundle = &region->bundle;
-		const int curvesize = bundle->curvesize;
-		for (int i = 0; i < bundle->totguides; ++i)
+		static const float stepsize = 0.01f;
+		static const int maxverts = 100000;
+		int guide_idx = 0;
+		for (const GroomRegion *region = regions->first; region; region = region->next)
 		{
-			/* TODO implement optional factors using scalp textures/vgroups */
-			float taper_length = region->taper_length;
-			float taper_thickness = region->taper_thickness;
-			
-			BKE_hair_set_guide_curve(hsys, i, &bundle->guides[i].root, curvesize,
-			                         taper_length, taper_thickness);
+			const GroomBundle *bundle = &region->bundle;
+			for (int i = 0; i < bundle->totguides; ++i)
+			{
+				const int prev_totverts = totverts;
+				groom_guide_curve_discretize(region, i, stepsize, maxverts, &verts, &totalloc, &totverts);
+				numverts[guide_idx] = totverts - prev_totverts;
+				
+				++guide_idx;
+			}
 		}
 	}
-	BKE_hair_guide_curves_end(hsys);
 	
-	int idx = 0;
-	for (const GroomRegion *region = regions->first; region; region = region->next)
+	/* Declare all guide curves and lengths */
+	BKE_hair_guide_curves_begin(hsys, totguides);
 	{
-		const GroomBundle *bundle = &region->bundle;
-		const int shapesize = region->numverts;
-		const int curvesize = bundle->curvesize;
-		const float *weights = bundle->guide_shape_weights;
-		float co[3];
-		for (int guide_idx = 0; guide_idx < bundle->totguides; ++guide_idx)
+		int guide_idx = 0;
+		for (const GroomRegion *region = regions->first; region; region = region->next)
 		{
-			for (int j = 0; j < curvesize; ++j)
+			const GroomBundle *bundle = &region->bundle;
+			for (int i = 0; i < bundle->totguides; ++i)
 			{
-				/* Compute barycentric guide location from shape */
-				zero_v3(co);
-				for (int k = 0; k < shapesize; ++k)
-				{
-					madd_v3_v3fl(co, bundle->curvecache[k * curvesize + j].co, weights[k]);
-				}
+				/* TODO implement optional factors using scalp textures/vgroups */
+				float taper_length = region->taper_length;
+				float taper_thickness = region->taper_thickness;
 				
-				BKE_hair_set_guide_vertex(hsys, idx, 0, co);
-				++idx;
+				BKE_hair_set_guide_curve(
+				            hsys,
+				            i,
+				            &bundle->guides[i].root,
+				            numverts[guide_idx],
+				            taper_length,
+				            taper_thickness);
+				++guide_idx;
 			}
-			
-			weights += shapesize;
 		}
 	}
+	BKE_hair_guide_curves_end(hsys);
+	
+	for (int i = 0; i < totverts; ++i)
+	{
+		BKE_hair_set_guide_vertex(hsys, i, verts[i].flag, verts[i].co);
+	}
+	
+	MEM_freeN(numverts);
+	MEM_freeN(verts);
 	
 	const Mesh *scalp = BKE_groom_get_scalp(depsgraph, groom);
 	if (scalp)



More information about the Bf-blender-cvs mailing list