[Bf-blender-cvs] [2c3e4fb] master: Add Custom Loop Normals to Data Transfer.

Bastien Montagne noreply at git.blender.org
Thu Feb 5 14:46:03 CET 2015


Commit: 2c3e4fbd7e91e7faeaaed3946874beb4be4e7817
Author: Bastien Montagne
Date:   Thu Feb 5 14:38:59 2015 +0100
Branches: master
https://developer.blender.org/rB2c3e4fbd7e91e7faeaaed3946874beb4be4e7817

Add Custom Loop Normals to Data Transfer.

Titles says everything, just two notes:
* We have to actually transfer plain *normals*, not 'compressed' clnors,
  so had to add pre/post process to transfer to make the conversions.
* Also added interpolation and advanced copy/mixing to CD_NORMAL, for same reasons.

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

M	source/blender/blenkernel/BKE_customdata.h
M	source/blender/blenkernel/BKE_data_transfer.h
M	source/blender/blenkernel/intern/customdata.c
M	source/blender/blenkernel/intern/data_transfer.c
M	source/blender/editors/object/object_data_transfer.c
M	source/blender/makesrna/intern/rna_modifier.c

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

diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index f11aad2..f3f1e0a 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -397,6 +397,8 @@ enum {
 	CD_FAKE_BWEIGHT     = CD_FAKE | CD_BWEIGHT,  /* *sigh*. */
 	CD_FAKE_UV          = CD_FAKE | CD_MLOOPUV,  /* UV flag, because we handle both loop's UVs and poly's textures. */
 
+	CD_FAKE_LNOR        = CD_FAKE | CD_CUSTOMLOOPNORMAL,  /* Because we play with clnor and temp lnor layers here. */
+
 	CD_FAKE_SHARP       = CD_FAKE | 200,  /* Sharp flag for edges, smooth flag for faces. */
 };
 
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index d31804b..cea093a 100644
--- a/source/blender/blenkernel/BKE_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -57,6 +57,7 @@ enum {
 	DT_TYPE_FREESTYLE_EDGE          = 1 << 12,
 
 	DT_TYPE_VCOL                    = 1 << 16,
+	DT_TYPE_LNOR                    = 1 << 17,
 
 	DT_TYPE_UV                      = 1 << 24,
 	DT_TYPE_SHARP_FACE              = 1 << 25,
@@ -67,7 +68,7 @@ enum {
 	DT_TYPE_VERT_ALL                = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT,
 	DT_TYPE_EDGE_ALL                = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE |
 	                                  DT_TYPE_FREESTYLE_EDGE,
-	DT_TYPE_LOOP_ALL                = DT_TYPE_VCOL | DT_TYPE_UV,
+	DT_TYPE_LOOP_ALL                = DT_TYPE_VCOL | DT_TYPE_LNOR | DT_TYPE_UV,
 	DT_TYPE_POLY_ALL                = DT_TYPE_UV | DT_TYPE_SHARP_FACE | DT_TYPE_FREESTYLE_FACE,
 };
 
@@ -85,7 +86,7 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type);
 #define DT_DATATYPE_IS_EDGE(_dt) \
 	ELEM(_dt, DT_TYPE_CREASE, DT_TYPE_SHARP_EDGE, DT_TYPE_SEAM, DT_TYPE_BWEIGHT_EDGE, DT_TYPE_FREESTYLE_EDGE)
 #define DT_DATATYPE_IS_LOOP(_dt) \
-	ELEM(_dt, DT_TYPE_UV, DT_TYPE_VCOL)
+	ELEM(_dt, DT_TYPE_UV, DT_TYPE_VCOL, DT_TYPE_LNOR)
 #define DT_DATATYPE_IS_POLY(_dt) \
 	ELEM(_dt, DT_TYPE_UV, DT_TYPE_SHARP_FACE, DT_TYPE_FREESTYLE_FACE)
 
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 0c437f6..0436ec0 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -300,6 +300,49 @@ static void layerInterp_mdeformvert(void **sources, const float *weights,
 	}
 }
 
+static void layerInterp_normal(void **sources, const float *weights,
+                               const float *UNUSED(sub_weights), int count, void *dest)
+{
+	float no[3] = {0.0f};
+
+	while (count--) {
+		madd_v3_v3fl(no, (float *)sources[count], weights[count]);
+	}
+
+	copy_v3_v3((float *)dest, no);
+}
+
+static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor)
+{
+	const float *no_src = source;
+	float *no_dst = dest;
+	float no_tmp[3];
+
+	if (ELEM(mixmode, CDT_MIX_NOMIX, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+		/* Above/below threshold modes are not supported here, fallback to nomix (just in case). */
+		copy_v3_v3(no_dst, no_src);
+	}
+	else {  /* Modes that support 'real' mix factor. */
+		/* Since we normalize in the end, MIX and ADD are the same op here. */
+		if (ELEM(mixmode, CDT_MIX_MIX, CDT_MIX_ADD)) {
+			add_v3_v3v3(no_tmp, no_dst, no_src);
+			normalize_v3(no_tmp);
+		}
+		else if (mixmode == CDT_MIX_SUB) {
+			sub_v3_v3v3(no_tmp, no_dst, no_src);
+			normalize_v3(no_tmp);
+		}
+		else if (mixmode == CDT_MIX_MUL) {
+			mul_v3_v3v3(no_tmp, no_dst, no_src);
+			normalize_v3(no_tmp);
+		}
+		else {
+			copy_v3_v3(no_tmp, no_src);
+		}
+		interp_v3_v3v3_slerp_safe(no_dst, no_dst, no_tmp, mixfactor);
+	}
+}
+
 static void layerCopy_tface(const void *source, void *dest, int count)
 {
 	const MTFace *source_tf = (const MTFace *)source;
@@ -1165,7 +1208,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
 	{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_origindex},
 	/* 8: CD_NORMAL */
 	/* 3 floats per normal vector */
-	{sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
+	{sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, layerInterp_normal, NULL, NULL,
+	 NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal},
 	/* 9: CD_POLYINDEX (deprecated) */
 	{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
 	/* 10: CD_PROP_FLT */
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 3704174..5ac7b92 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -47,6 +47,7 @@
 #include "BKE_data_transfer.h"
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
 #include "BKE_mesh_remap.h"
 #include "BKE_object.h"
@@ -79,6 +80,9 @@ CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types
 		else if (cddata_type == CD_FAKE_UV) {
 			cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV;
 		}
+		else if (cddata_type == CD_FAKE_LNOR) {
+			cddata_mask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
+		}
 	}
 
 	return cddata_mask;
@@ -143,6 +147,10 @@ bool BKE_object_data_transfer_get_dttypes_capacity(
 				*r_threshold = true;
 				ret = true;
 				break;
+			case DT_TYPE_LNOR:
+				*r_advanced_mixing = true;
+				ret = true;
+				break;
 			case DT_TYPE_SHARP_FACE:
 				*r_threshold = true;
 				ret = true;
@@ -217,6 +225,8 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type)
 
 		case DT_TYPE_VCOL:
 			return CD_MLOOPCOL;
+		case DT_TYPE_LNOR:
+			return CD_FAKE_LNOR;
 
 		default:
 			BLI_assert(0);
@@ -242,6 +252,105 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
 
 /* ********** */
 
+/* Generic pre/post processing, only used by custom loop normals currently. */
+
+static void data_transfer_dtdata_type_preprocess(
+        Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst,
+        const int dtdata_type, const bool dirty_nors_dst, const bool use_split_nors_src, const float split_angle_src)
+{
+	if (dtdata_type == DT_TYPE_LNOR) {
+		/* Compute custom normals into regular loop normals, which will be used for the transfer. */
+		MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+		const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+		MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+		const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+		MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+		const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+		MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+		const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+		CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+		CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+		const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0;
+		const float split_angle_dst = me_dst->smoothresh;
+
+		dm_src->calcLoopNormals(dm_src, use_split_nors_src, split_angle_src);
+
+		if (dm_dst) {
+			dm_dst->calcLoopNormals(dm_dst, use_split_nors_dst, split_angle_dst);
+		}
+		else {
+			float (*poly_nors_dst)[3];
+			float (*loop_nors_dst)[3];
+			short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
+
+			/* Cache poly nors into a temp CDLayer. */
+			poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
+			if (dirty_nors_dst || !poly_nors_dst) {
+				if (!poly_nors_dst) {
+					poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst);
+					CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+				}
+				BKE_mesh_calc_normals_poly(verts_dst, num_verts_dst, loops_dst, polys_dst,
+				                           num_loops_dst, num_polys_dst, poly_nors_dst, true);
+			}
+			/* Cache loop nors into a temp CDLayer. */
+			loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
+			if (dirty_nors_dst || loop_nors_dst) {
+				if (!loop_nors_dst) {
+					loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, num_loops_dst);
+					CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+				}
+				BKE_mesh_normals_loop_split(verts_dst, num_verts_dst, edges_dst, num_edges_dst,
+				                            loops_dst, loop_nors_dst, num_loops_dst,
+				                            polys_dst, (const float (*)[3])poly_nors_dst, num_polys_dst,
+				                            use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL);
+			}
+		}
+	}
+}
+
+static void data_transfer_dtdata_type_postprocess(
+        Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *UNUSED(dm_src), DerivedMesh *dm_dst, Mesh *me_dst,
+        const int dtdata_type, const bool changed)
+{
+	if (dtdata_type == DT_TYPE_LNOR) {
+		/* Bake edited destination loop normals into custom normals again. */
+		MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+		const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+		MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+		const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+		MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+		const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+		MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+		const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+		CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+		CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+		const float (*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL);
+		fl

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list