[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 = ®ion->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 = ®ion->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 = ®ion->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 = ®ion->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 = ®ion->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