[Bf-blender-cvs] [ec4ec90934e] hair_guides: Render support for hair systems in Cycles.
Lukas Tönne
noreply at git.blender.org
Sat May 12 15:37:37 CEST 2018
Commit: ec4ec90934ec8bc42f414ff61f921bdd11f4da97
Author: Lukas Tönne
Date: Sat May 12 14:37:13 2018 +0100
Branches: hair_guides
https://developer.blender.org/rBec4ec90934ec8bc42f414ff61f921bdd11f4da97
Render support for hair systems in Cycles.
===================================================================
M intern/cycles/blender/blender_curves.cpp
M intern/cycles/blender/blender_util.h
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/engines/eevee/shaders/hair_lib.glsl
===================================================================
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 62226f8c802..f773548286f 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -298,6 +298,102 @@ static void ObtainCacheVColFromParticleSystem(BL::Mesh *b_mesh,
}
}
+static void ObtainCacheDataFromHairSystem(Mesh *mesh,
+ BL::Object *b_ob,
+ BL::HairSystem *b_hsys,
+ ParticleCurveData *CData,
+ bool background,
+ int *curvenum,
+ int *keyno)
+{
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ BL::Mesh b_mesh(b_ob->data());
+ void *hair_cache = BKE_hair_export_cache_new_mesh(b_hsys->ptr.data, 0, b_mesh.ptr.data);
+
+ int totcurves, totverts;
+ BKE_hair_render_get_buffer_size(hair_cache, &totcurves, &totverts);
+
+ if(totcurves == 0)
+ {
+ BKE_hair_export_cache_free(hair_cache);
+ return;
+ }
+
+ CData->psys_firstcurve.push_back_slow(*curvenum);
+ CData->psys_curvenum.push_back_slow(totcurves);
+
+ {
+ // Material
+ int shader = clamp(b_hsys->material_index()-1, 0, mesh->used_shaders.size()-1);
+ CData->psys_shader.push_back_slow(shader);
+ }
+
+ {
+ // Cycles settings
+// PointerRNA cpsys = RNA_pointer_get(&b_hsys->ptr, "cycles");
+// float radius = get_float(cpsys, "radius_scale") * 0.5f;
+// CData->psys_rootradius.push_back_slow(radius * get_float(cpsys, "root_width"));
+// CData->psys_tipradius.push_back_slow(radius * get_float(cpsys, "tip_width"));
+// CData->psys_shape.push_back_slow(get_float(cpsys, "shape"));
+// CData->psys_closetip.push_back_slow(get_boolean(cpsys, "use_closetip"));
+ float radius = 0.01f * 0.5f;
+ CData->psys_rootradius.push_back_slow(radius * 1.0f);
+ CData->psys_tipradius.push_back_slow(radius * 0.0f);
+ CData->psys_shape.push_back_slow(0.0f);
+ CData->psys_closetip.push_back_slow(true);
+ }
+
+ // Allocate buffers
+ const size_t firstkey_start = CData->curve_firstkey.size();
+ const size_t keynum_start = CData->curve_keynum.size();
+ const size_t length_start = CData->curve_length.size();
+ const size_t co_start = CData->curvekey_co.size();
+ const size_t time_start = CData->curvekey_time.size();
+ CData->curve_firstkey.resize(firstkey_start + totcurves);
+ CData->curve_keynum.resize(keynum_start + totcurves);
+ CData->curve_length.resize(length_start + totcurves);
+ CData->curvekey_co.resize(co_start + totverts);
+ CData->curvekey_time.resize(time_start + totverts);
+
+ // Import render curves from hair system
+ BKE_hair_render_fill_buffers(
+ hair_cache,
+ (int)sizeof(float3),
+ CData->curve_firstkey.data() + firstkey_start,
+ CData->curve_keynum.data() + keynum_start,
+ (float*)(CData->curvekey_co.data() + co_start));
+
+ // Compute curve length and key times
+ for(int c = 0; c < totcurves; ++c) {
+ const int keynum = CData->curve_keynum[keynum_start + c];
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ for(int v = 0; v < keynum; v++) {
+ float3 cKey = CData->curvekey_co[co_start + v];
+ cKey = transform_point(&itfm, cKey);
+ if(v > 0) {
+ float step_length = len(cKey - pcKey);
+ if(step_length == 0.0f)
+ continue;
+ curve_length += step_length;
+ }
+
+ CData->curvekey_time.push_back_slow(curve_length);
+ pcKey = cKey;
+ }
+
+ CData->curve_length.push_back_slow(curve_length);
+ }
+
+ *curvenum += totcurves;
+ *keyno += totverts;
+
+ BKE_hair_export_cache_free(hair_cache);
+}
+
static bool ObtainCacheDataFromObject(Mesh *mesh,
BL::Mesh *b_mesh,
BL::Object *b_ob,
@@ -324,6 +420,17 @@ static bool ObtainCacheDataFromObject(Mesh *mesh,
&curvenum,
&keyno);
}
+ if((b_mod->type() == b_mod->type_FUR)) {
+ BL::FurModifier b_fmd((const PointerRNA)b_mod->ptr);
+ BL::HairSystem b_hsys = b_fmd.hair_system();
+ ObtainCacheDataFromHairSystem(mesh,
+ b_ob,
+ &b_hsys,
+ CData,
+ background,
+ &curvenum,
+ &keyno);
+ }
}
}
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 3eb09cbe3c0..b5d324309b5 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -36,6 +36,10 @@ void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
+void* BKE_hair_export_cache_new_mesh(const void *hsys, int subdiv, void *scalp);
+void BKE_hair_export_cache_free(void *hcache);
+void BKE_hair_render_get_buffer_size(void* hcache, int *r_totcurves, int *r_totverts);
+void BKE_hair_render_fill_buffers(void* hcache, int vertco_stride, int *r_curvestart, int *r_curvelen, float *r_vertco);
}
CCL_NAMESPACE_BEGIN
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index de3c69bb7b0..08a28593712 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -42,6 +42,7 @@ struct HairSystem;
struct HairDrawSettings;
struct HairGuideData;
struct DerivedMesh;
+struct Mesh;
struct MeshSample;
struct Object;
@@ -131,6 +132,7 @@ typedef struct HairExportCache
} HairExportCache;
struct HairExportCache* BKE_hair_export_cache_new(const struct HairSystem *hsys, int subdiv, struct DerivedMesh *scalp);
+struct HairExportCache* BKE_hair_export_cache_new_mesh(const struct HairSystem *hsys, int subdiv, struct Mesh *scalp);
void BKE_hair_export_cache_free(struct HairExportCache *cache);
/* === Draw Cache === */
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index d6e84ed6d2e..d6291dfa71f 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -46,6 +46,7 @@
#include "DNA_object_types.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_hair.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
@@ -611,6 +612,15 @@ HairExportCache* BKE_hair_export_cache_new(const HairSystem *hsys, int subdiv, D
return cache;
}
+/* XXX Temporary hack to support usage with Mesh from Cycles */
+HairExportCache* BKE_hair_export_cache_new_mesh(const HairSystem *hsys, int subdiv, struct Mesh *scalp)
+{
+ DerivedMesh *dm = CDDM_from_mesh(scalp);
+ HairExportCache *cache = BKE_hair_export_cache_new(hsys, subdiv, dm);
+ dm->release(dm);
+ return cache;
+}
+
void BKE_hair_export_cache_free(HairExportCache *cache)
{
if (cache->fiber_numverts)
diff --git a/source/blender/blenkernel/intern/hair_draw.c b/source/blender/blenkernel/intern/hair_draw.c
index bdb115ff589..8c7a29f8210 100644
--- a/source/blender/blenkernel/intern/hair_draw.c
+++ b/source/blender/blenkernel/intern/hair_draw.c
@@ -181,6 +181,147 @@ void BKE_hair_batch_cache_free(HairSystem* hsys)
}
}
+/* === Fiber Curve Interpolation === */
+
+/* NOTE: Keep this code in sync with the GLSL version!
+ * see hair_lib.glsl
+ */
+
+static void interpolate_parent_curve(
+ float curve_param,
+ int numverts,
+ const HairGuideVertex *verts,
+ const float (*tangents)[3],
+ const float (*normals)[3],
+ float r_co[3],
+ float r_tang[3],
+ float r_nor[3])
+{
+ float maxlen = (float)(numverts - 1);
+ float arclength = curve_param * maxlen;
+ int segment = (int)(arclength);
+ float lerpfac;
+ if (segment < numverts-1)
+ {
+ lerpfac = arclength - floor(arclength);
+ }
+ else
+ {
+ segment = numverts-2;
+ lerpfac = 1.0f;
+ }
+
+ mul_v3_v3fl(r_co, verts[segment].co, 1.0f - lerpfac);
+ madd_v3_v3fl(r_co, verts[segment + 1].co, lerpfac);
+ // Make relative to the parent root
+ sub_v3_v3(r_co, verts[0].co);
+
+ mul_v3_v3fl(r_tang, tangents[segment], 1.0f - lerpfac);
+ madd_v3_v3fl(r_tang, tangents[segment + 1], lerpfac);
+
+ mul_v3_v3fl(r_nor, normals[segment], 1.0f - lerpfac);
+ madd_v3_v3fl(r_nor, normals[segment + 1], lerpfac);
+}
+
+static void hair_fiber_interpolate_vertex(
+ float curve_param,
+ int parent_numverts,
+ const HairGuideVertex *parent_verts,
+ const float (*parent_tangents)[3],
+ const float (*parent_normals)[3],
+ float parent_weight,
+ float r_co[3],
+ float r_tangent[3],
+ float r_target_matrix[3][3])
+{
+ zero_v3(r_co);
+ zero_v3(r_tangent);
+ unit_m3(r_target_matrix);
+
+ float pco[3], ptang[3], pnor[3];
+ interpolate_parent_curve(
+ curve_param,
+ parent_numverts,
+ parent_verts,
+ parent_tangents,
+ parent_normals,
+ pco,
+ ptang,
+ pnor);
+
+ madd_v3_v3fl(r_co, pco, parent_weight);
+ normalize_v3(ptang);
+ madd_v3_v3fl(r_tangent, ptang, parent_weight);
+
+ if (r_target_matrix)
+ {
+ copy_v3_v3(r_target_matrix[0], pnor);
+ copy_v3_v3(r_target_matrix[1], ptang);
+ add_v3_v3v3(r_target_matrix[2], pco, parent_verts[0].co);
+ }
+}
+
+static void hair_fiber_interpolate(
+ const HairExportCache* cache,
+ int fiber_index,
+ int vertco_stride,
+ float *r_vertco)
+{
+ const int numverts = cache->fiber_numverts[fiber_index];
+ BLI_assert(numverts >= 2);
+ const float dcurve_param = 1.0f / (numverts - 1);
+ const float *rootco = cache->fiber_root_position[fiber_index];
+
+ // Add weighted data from each parent
+
+ for (int k = 0; k < 4; ++k)
+ {
+ const unsigned int parent_index = cache->follicles[fiber_index].parent_index[k];
+ if (parent_index == HAIR_STRAND_INDEX_NONE)
+ {
+ continue;
+ }
+
+ const float parent_weight = cache->
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list