[Bf-blender-cvs] [b44af40eec6] hair_guides: New HairExportCache struct to unify pre-computation of hair data for OpenGL, render, and eventual data export.
Lukas Tönne
noreply at git.blender.org
Sat May 12 10:44:32 CEST 2018
Commit: b44af40eec6cd6d602b50b28719d8556f38abcc7
Author: Lukas Tönne
Date: Sat May 12 09:41:58 2018 +0100
Branches: hair_guides
https://developer.blender.org/rBb44af40eec6cd6d602b50b28719d8556f38abcc7
New HairExportCache struct to unify pre-computation of hair data for OpenGL, render, and eventual data export.
===================================================================
M source/blender/blenkernel/BKE_hair.h
M source/blender/blenkernel/intern/hair.c
M source/blender/blenkernel/intern/hair_draw.c
M source/blender/draw/intern/draw_cache_impl_hair.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 3c5ba7803a4..b2034cd4507 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -110,6 +110,26 @@ struct HairDrawSettings* BKE_hair_draw_settings_new(void);
struct HairDrawSettings* BKE_hair_draw_settings_copy(struct HairDrawSettings *draw_settings);
void BKE_hair_draw_settings_free(struct HairDrawSettings *draw_settings);
+/* === Export === */
+
+/* Intermediate data for export */
+typedef struct HairExportCache
+{
+ int totguidecurves;
+ int totguideverts;
+
+ int totfibercurves;
+ int totfiberverts;
+ int *fiber_numverts; /* Number of vertices in each fiber */
+
+ const struct HairFollicle *follicles;
+ struct HairGuideCurve *guide_curves;
+ struct HairGuideVertex *guide_verts;
+} HairExportCache;
+
+struct HairExportCache* BKE_hair_export_cache_new(const struct HairSystem *hsys, int subdiv);
+void BKE_hair_export_cache_free(struct HairExportCache *cache);
+
/* === Draw Cache === */
enum {
@@ -120,18 +140,33 @@ enum {
void BKE_hair_batch_cache_dirty(struct HairSystem* hsys, int mode);
void BKE_hair_batch_cache_free(struct HairSystem* hsys);
-int* BKE_hair_get_fiber_lengths(const struct HairSystem* hsys, int subdiv);
void BKE_hair_get_texture_buffer_size(
- const struct HairSystem* hsys,
- int subdiv,
+ const struct HairExportCache *cache,
int *r_size,
int *r_strand_map_start,
int *r_strand_vertex_start,
int *r_fiber_start);
void BKE_hair_get_texture_buffer(
- const struct HairSystem* hsys,
+ const struct HairExportCache *cache,
struct DerivedMesh *scalp,
- int subdiv,
void *texbuffer);
+/* === Render API === */
+
+/* Calculate required size for render buffers. */
+void BKE_hair_render_get_buffer_size(
+ const struct HairExportCache* cache,
+ int *r_totcurves,
+ int *r_totverts);
+
+/* Create render data in existing buffers.
+ * Buffers must be large enough according to BKE_hair_get_render_buffer_size.
+ */
+void BKE_hair_render_fill_buffers(
+ const struct HairExportCache* cache,
+ int vertco_stride,
+ int *r_curvestart,
+ int *r_curvelen,
+ float *r_vertco);
+
#endif
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 32794412826..f9e89a5e132 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -419,3 +419,139 @@ void BKE_hair_bind_follicles(HairSystem *hsys, DerivedMesh *scalp)
MEM_freeN(strandloc);
}
+/* === Export === */
+
+BLI_INLINE int hair_get_strand_subdiv_numverts(int numstrands, int numverts, int subdiv)
+{
+ return ((numverts - numstrands) << subdiv) + numstrands;
+}
+
+BLI_INLINE int hair_get_strand_subdiv_length(int orig_length, int subdiv)
+{
+ return ((orig_length - 1) << subdiv) + 1;
+}
+
+static int hair_strand_subdivide(const HairGuideCurve* curve, const HairGuideVertex* verts, int subdiv, HairGuideVertex *r_verts)
+{
+ {
+ /* Move vertex positions from the dense array to their initial configuration for subdivision. */
+ const int step = (1 << subdiv);
+ HairGuideVertex *dst = r_verts;
+ for (int i = 0; i < curve->numverts; ++i) {
+ copy_v3_v3(dst->co, verts[i].co);
+ dst += step;
+ }
+ }
+
+ /* Subdivide */
+ for (int d = 0; d < subdiv; ++d) {
+ const int num_edges = (curve->numverts - 1) << d;
+ const int hstep = 1 << (subdiv - d - 1);
+ const int step = 1 << (subdiv - d);
+
+ /* Calculate edge points */
+ {
+ int index = 0;
+ for (int k = 0; k < num_edges; ++k, index += step) {
+ add_v3_v3v3(r_verts[index + hstep].co, r_verts[index].co, r_verts[index + step].co);
+ mul_v3_fl(r_verts[index + hstep].co, 0.5f);
+ }
+ }
+
+ /* Move original points */
+ {
+ int index = step;
+ for (int k = 1; k < num_edges; ++k, index += step) {
+ add_v3_v3v3(r_verts[index].co, r_verts[index - hstep].co, r_verts[index + hstep].co);
+ mul_v3_fl(r_verts[index].co, 0.5f);
+ }
+ }
+ }
+
+ const int num_verts = ((curve->numverts - 1) << subdiv) + 1;
+ return num_verts;
+}
+
+HairExportCache* BKE_hair_export_cache_new(const HairSystem *hsys, int subdiv)
+{
+ HairExportCache *cache = MEM_callocN(sizeof(HairExportCache), "hair export cache");
+
+ const int totguidecurves = cache->totguidecurves = hsys->guides.totcurves;
+ cache->guide_curves = MEM_mallocN(sizeof(HairGuideCurve) * totguidecurves, "hair export guide curves");
+
+ /* Cache subdivided curves for repeated lookup */
+ int totguideverts = 0;
+ for (int i = 0; i < totguidecurves; ++i) {
+ const HairGuideCurve *curve_orig = &hsys->guides.curves[i];
+ HairGuideCurve *curve = &cache->guide_curves[i];
+
+ memcpy(&curve->mesh_sample, &curve_orig->mesh_sample, sizeof(MeshSample));
+ curve->numverts = hair_get_strand_subdiv_length(curve_orig->numverts, subdiv);
+ curve->vertstart = totguideverts;
+
+ totguideverts += curve->numverts;
+ }
+
+ cache->totguideverts = totguideverts;
+ cache->guide_verts = MEM_mallocN(sizeof(HairGuideVertex) * totguideverts, "hair export guide verts");
+
+ for (int i = 0; i < totguidecurves; ++i) {
+ const HairGuideCurve *curve_orig = &hsys->guides.curves[i];
+ const HairGuideVertex *verts_orig = &hsys->guides.verts[curve_orig->vertstart];
+ const HairGuideCurve *curve = &cache->guide_curves[i];
+ HairGuideVertex *verts = &cache->guide_verts[curve->vertstart];
+
+ hair_strand_subdivide(curve_orig, verts_orig, subdiv, verts);
+ }
+
+ if (hsys->pattern)
+ {
+ const int totfibercurves = cache->totfibercurves = hsys->pattern->num_follicles;
+
+ cache->follicles = hsys->pattern->follicles;
+
+ cache->fiber_numverts = MEM_mallocN(sizeof(int) * totfibercurves, "fiber numverts");
+
+ // Calculate the length of the fiber from the weighted average of its guide strands
+ cache->totfiberverts = 0;
+ HairFollicle *follicle = hsys->pattern->follicles;
+ for (int i = 0; i < totfibercurves; ++i, ++follicle) {
+ float fiblen = 0.0f;
+
+ for (int k = 0; k < 4; ++k) {
+ const int si = follicle->parent_index[k];
+ const float sw = follicle->parent_weight[k];
+ if (si == HAIR_STRAND_INDEX_NONE || sw == 0.0f) {
+ break;
+ }
+ BLI_assert(si < totguidecurves);
+
+ fiblen += (float)cache->guide_curves[si].numverts * sw;
+ }
+
+ // Use rounded number of segments
+ const int numverts = (int)(fiblen + 0.5f);
+ cache->fiber_numverts[i] = numverts;
+ cache->totfiberverts += numverts;
+ }
+ }
+
+ return cache;
+}
+
+void BKE_hair_export_cache_free(HairExportCache *cache)
+{
+ if (cache->fiber_numverts)
+ {
+ MEM_freeN(cache->fiber_numverts);
+ }
+ if (cache->guide_curves)
+ {
+ MEM_freeN(cache->guide_curves);
+ }
+ if (cache->guide_verts)
+ {
+ MEM_freeN(cache->guide_verts);
+ }
+ MEM_freeN(cache);
+}
diff --git a/source/blender/blenkernel/intern/hair_draw.c b/source/blender/blenkernel/intern/hair_draw.c
index da90ff7aa4a..a17522b0aef 100644
--- a/source/blender/blenkernel/intern/hair_draw.c
+++ b/source/blender/blenkernel/intern/hair_draw.c
@@ -67,57 +67,6 @@ void BKE_hair_draw_settings_free(HairDrawSettings *draw_settings)
/* === Draw Cache === */
-static int hair_get_strand_subdiv_numverts(int numstrands, int numverts, int subdiv)
-{
- return ((numverts - numstrands) << subdiv) + numstrands;
-}
-
-BLI_INLINE int hair_get_strand_subdiv_length(int orig_length, int subdiv)
-{
- return ((orig_length - 1) << subdiv) + 1;
-}
-
-int* BKE_hair_get_fiber_lengths(const HairSystem *hsys, int subdiv)
-{
- if (!hsys->pattern) {
- return NULL;
- }
-
- const int totfibers = hsys->pattern->num_follicles;
- int *fiber_length = MEM_mallocN(sizeof(int) * totfibers, "fiber length");
-
- const int num_strands = hsys->guides.totcurves;
- /* Cache subdivided lengths for repeated lookup */
- int *lengths = MEM_mallocN(sizeof(int) * num_strands, "strand length");
- for (int i = 0; i < hsys->guides.totcurves; ++i) {
- lengths[i] = hair_get_strand_subdiv_length(hsys->guides.curves[i].numverts, subdiv);
- }
-
- // Calculate the length of the fiber from the weighted average of its guide strands
- HairFollicle *follicle = hsys->pattern->follicles;
- for (int i = 0; i < totfibers; ++i, ++follicle) {
- float fiblen = 0.0f;
-
- for (int k = 0; k < 4; ++k) {
- int si = follicle->parent_index[k];
- float sw = follicle->parent_weight[k];
- if (si == HAIR_STRAND_INDEX_NONE || sw == 0.0f) {
- break;
- }
- BLI_assert(si < num_strands);
-
- fiblen += (float)lengths[si] * sw;
- }
-
- // use rounded number of segments
- fiber_length[i] = (int)(fiblen + 0.5f);
- }
-
- MEM_freeN(lengths);
-
- return fiber_length;
-}
-
typedef struct HairFiberTextureBuffer {
unsigned int parent_index[4];
float parent_weight[4];
@@ -157,11 +106,11 @@ static void hair_strand_transport_frame(const float co1[3], const float co2[3],
copy_v3_v3(prev_nor, r_nor);
}
-static void hair_strand_calc_vectors(const float (*positions)[3], int num_verts, float rootmat[3][3],
+static void hair_strand_calc_vectors(const HairGuideVertex* verts, int num_verts, float rootmat[3][3],
HairStrandVertexTextureBuffer *strand)
{
for (int i = 0; i < num_verts; ++i) {
- copy_v3_v3(strand[i].co, positions[i]);
+ copy_v3_v3(strand[i].co, verts[i].co);
}
// Calculate tangent and normal vectors
@@ -190,134 +139,68 @@ static void hair_strand_calc_vectors(const float (*positions)[3], int num_verts,
}
}
-static int hair_strand_subdivide(const HairSystem *hsys, const HairGuideCurve* curve, int subdiv, float (*verts)[3])
-{
- {
- /* Move vertex positions from the dense array to their initial configuration for subdivision. */
- const int step = (1 << subdiv);
- float (*dst)[3] = verts;
- int vertend = curve->vertstart + curve->numverts;
- for (int i = curve->vertstart; i < vertend; ++i) {
- copy_v3_v3(*dst, hsys->guides.verts[i].co);
- dst += step;
- }
- }
-
- /* Subdivide */
- for (int d = 0; d < subdiv; ++d) {
- const int num_edges = (curve->numverts - 1) << d;
- const int hstep = 1 << (subdiv - d - 1);
- const int step = 1 << (subdiv -
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list