[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