[Bf-blender-cvs] [09d95bc] soc-2014-shapekey: Dirty prototype for modal Blend From Shape with PE

Grigory Revzin noreply at git.blender.org
Tue Jul 8 01:58:24 CEST 2014


Commit: 09d95bc8ca2f559888cf092d993babee78b139cf
Author: Grigory Revzin
Date:   Tue Jul 8 03:58:11 2014 +0400
https://developer.blender.org/rB09d95bc8ca2f559888cf092d993babee78b139cf

Dirty prototype for modal Blend From Shape with PE

Supports intepreting between keys for now. Move mouse L/R to adjust intensity and Up/Down to adjust PE falloff!

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

M	source/blender/bmesh/intern/bmesh_pe.c
M	source/blender/bmesh/intern/bmesh_pe.h
M	source/blender/editors/mesh/editmesh_tools.c

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

diff --git a/source/blender/bmesh/intern/bmesh_pe.c b/source/blender/bmesh/intern/bmesh_pe.c
index 877e972..06cb4cd 100644
--- a/source/blender/bmesh/intern/bmesh_pe.c
+++ b/source/blender/bmesh/intern/bmesh_pe.c
@@ -26,8 +26,12 @@
 #include "BLI_utildefines.h"
 #include "BLI_linklist_stack.h"
 #include "BLI_math.h"
+#include "BLI_rand.h"
+
 #include "MEM_guardedalloc.h"
 
+#include "DNA_scene_types.h"
+
 #include "bmesh.h"
 
 
@@ -276,3 +280,49 @@ void BM_prop_dist_calc(BMesh *bm, float loc_to_world_mtx[3][3], float proj_plane
 
 	MEM_freeN(vindexes);
 }
+
+
+float BM_prop_factor_distance(float dist, float maxdist, int mode)
+{
+	float factor;
+
+	if (dist == 0.0f) /* signal for selected */
+		return 1.0f;
+
+	if (dist < 0.0f)
+		dist = 0.0f;
+
+	if (dist > maxdist)
+		return 0.0f;
+
+	dist = dist / maxdist;
+
+	CLAMP(dist, 0.0f, maxdist);
+
+	switch (mode) {
+		case PROP_SHARP:
+			factor = dist * dist;
+			break;
+		case PROP_SMOOTH: /* bell-ish hermite spline h_0_0 */
+			factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
+			break;
+		case PROP_ROOT:
+			factor = sqrtf(dist);
+			break;
+		case PROP_LIN:
+			factor = dist;
+			break;
+		case PROP_SPHERE:
+			factor = sqrtf(2 * dist - dist * dist);
+			break;
+		case PROP_RANDOM:
+			factor = BLI_frand() * dist;
+			break;
+		case PROP_CONST: /* fall-through */
+		default:
+			factor = 1.0f;
+			break;
+	}
+
+	return 1.0f - factor;
+}
\ No newline at end of file
diff --git a/source/blender/bmesh/intern/bmesh_pe.h b/source/blender/bmesh/intern/bmesh_pe.h
index 232aa65..f9cd39b 100644
--- a/source/blender/bmesh/intern/bmesh_pe.h
+++ b/source/blender/bmesh/intern/bmesh_pe.h
@@ -34,4 +34,10 @@ void BM_prop_dist_calc_connected(BMesh *bm, float loc_to_world_mtx[3][3], float
  * in the projection plane from the closest selected vertex */
 void BM_prop_dist_calc(BMesh *bm, float loc_to_world_mtx[3][3], float proj_plane_n[3], float dists[]);
 
+/* get the PE factor for a given distance 
+ * mode is one of the following: 
+ * PROP_SMOOTH, PROP_SPHERE, PROP_ROOT, PROP_SHARP, PROP_LIN, PROP_CONST, PROP_RANDOM  
+ * from DNA_scene_types.h */
+float BM_prop_factor_distance(float dist, float maxdist, int mode);
+
 #endif
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 79916f9..88b95b2 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -46,6 +46,7 @@
 #include "BLI_math.h"
 #include "BLI_rand.h"
 #include "BLI_sort_utils.h"
+#include "BLI_string.h"
 
 #include "BKE_material.h"
 #include "BKE_context.h"
@@ -2033,6 +2034,54 @@ void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ================================== Blend From Shape ===================================== */
+
+typedef struct bfs_customdata {
+	KeyBlock *opkb;
+	float   *add_shape_co;  /* argument co minus basis co, float triplets */
+
+	float	*origcos;
+
+	float	*distances,	    /* proportional falloff distances */
+			*factors;       /* proportional falloff factors (why not cache?) */
+
+	float	amount;		    /* blending intensity */
+
+	float   basedistance;   /* */
+	float	distance;	    /* PE falloff distance */
+
+	int		origx, origy;	/* mouse coords at previous state */
+	float	xscale, yscale; /* scale between mousemove and changes in mouse pos */
+
+	int		blend_mode;		/* 0 = interp, 1 = add */
+
+	int		prop_mode;		/* from DNA_scene_types.h, PE falloff interpolator mode, if -1 consider
+							 * no PE */
+	int		prop_type;		/* simple/connected/projected */
+
+	BMEditMesh *em;			/* editmesh */
+	Key *key;
+} bfs_customdata;
+
+enum {
+	BFS_MODE_INTERP = 0,
+	BFS_MODE_ADD = 1
+};
+
+static void bfs_freedata(bfs_customdata *mem)
+{
+	if (mem->distances)
+		MEM_freeN(mem->distances);
+	if (mem->factors)
+		MEM_freeN(mem->factors);
+	if (mem->add_shape_co)
+		MEM_freeN(mem->add_shape_co);
+	if (mem->origcos)
+		MEM_freeN(mem->origcos);
+
+	MEM_freeN(mem);
+}
+
 /* BMESH_TODO this should be properly encapsulated in a bmop.  but later.*/
 static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
 {
@@ -2111,6 +2160,7 @@ static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr),  Prop
 	return item;
 }
 
+
 static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op)
 {
 	uiLayout *layout = op->layout;
@@ -2127,6 +2177,303 @@ static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op)
 	uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE);
 }
 
+static int edbm_blend_from_shape_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+	Object *obedit = CTX_data_edit_object(C);
+	Mesh *me = obedit->data;
+	Key *k = me->key;
+	KeyBlock *kb = NULL;
+	BMEditMesh *em = me->edit_btmesh;
+	Scene *s = CTX_data_scene(C);
+	bfs_customdata *state;
+	ToolSettings *ts = CTX_data_tool_settings(C);
+	RegionView3D *rv3d = CTX_wm_region_view3d(C);
+	ScrArea *ar = CTX_wm_area(C);
+	float obmat3[3][3];
+	float proj_vec[3];
+	BMVert *v;
+	BMIter iter;
+	int a;
+
+	/* check properties aren't set (except the shape) */
+
+	/* check that we can safely blend */
+	LISTBASE_ITER_FWD(k->block, kb) {
+		if (kb->totelem != em->bm->totvert) {
+			BKE_report(op->reports, RPT_ERROR, "Shape topology has changed, can't blend!");
+			return OPERATOR_CANCELLED;
+		}
+	}
+
+	/* alloc customdata */
+	op->customdata = MEM_callocN(sizeof(bfs_customdata), "blend from shape modal data");
+	state = op->customdata;
+
+	//if (ts->proportional)
+		state->distances = MEM_callocN(sizeof(float)* em->bm->totvert, "blend from shape distances");
+
+	state->factors = MEM_callocN(sizeof(float) * em->bm->totvert, "blend from shape factors");
+	state->origcos = MEM_callocN(sizeof(float) * em->bm->totvert * 3, "blend from shape origcos");
+
+	state->blend_mode = BFS_MODE_INTERP; /* figure this one out in the modal */
+	state->origx = event->x;
+	state->origy = event->y;
+	state->em = em;
+	state->key = k;
+	state->prop_type = PROP_EDIT_CONNECTED; // ts->proportional; /* simple/cnct/proj */
+	state->prop_mode = ts->prop_mode;				/* falloffs */
+	state->opkb = BKE_keyblock_from_object(obedit); /* TODO */
+
+	{
+		float(*origshapeco)[3] = (float(*)[3]) state->origcos;
+		BM_ITER_MESH_INDEX(v, &iter, state->em->bm, BM_VERTS_OF_MESH, a) {
+			copy_v3_v3(origshapeco[a], v->co);
+		}
+	}
+
+	/* figure out control scales, TODO coefficient to be adjusted */
+	{
+		float bbox_diag[3];
+		copy_m3_m4(obmat3, obedit->obmat);
+		/* 0.5 * boundbox diagonal per entire view3d height */
+		zero_v3(bbox_diag);
+		copy_v3_v3(bbox_diag, obedit->bb->vec[0]);
+		sub_v3_v3(bbox_diag, obedit->bb->vec[6]);
+		mul_m3_v3(obmat3, bbox_diag);
+		state->yscale = 2.0f * len_v3(bbox_diag) / ar->winy;
+
+		//printf("BB diag len = %.3f\n", len_v3(bbox_diag));
+
+		/* initial falloff distance to 1/4 bbox_diag */
+		state->distance = 0.25 * len_v3(bbox_diag);
+
+		/* 2.0f blending amount per entire view3d width, simple*/
+		state->xscale = 2.0f / ar->winx;
+	}
+
+	if (state->prop_type) {
+		/* figure out distances */
+		switch (state->prop_type) {
+			case PROP_EDIT_ON:
+				BM_prop_dist_calc(state->em->bm, obmat3, NULL, state->distances);
+				break;
+
+			case PROP_EDIT_PROJECTED:
+				normalize_v3_v3(proj_vec, rv3d->viewinv[2]);
+				BM_prop_dist_calc(state->em->bm, obmat3, proj_vec, state->distances);
+				break;
+
+			case PROP_EDIT_CONNECTED:
+				BM_prop_dist_calc_connected(state->em->bm, obmat3, state->distances);
+				break;
+		}
+	}
+	else {
+		/* selected = 1.0 factor */
+		BM_ITER_MESH_INDEX(v, &iter, state->em->bm, BM_VERTS_OF_MESH, a) {
+			state->factors[a] = BM_elem_flag_test(v, BM_ELEM_SELECT) ? 1.0f : 0.0f;
+		}
+	}
+
+	/* shape selector! */
+
+	/* register modal handler */
+	WM_event_add_modal_handler(C, op);
+
+	return OPERATOR_RUNNING_MODAL;
+}
+
+static void edbm_blend_from_shape_handle_mousemove(short mx, short my, bfs_customdata *state)
+{
+	state->amount = -1.0f + mx * state->xscale;
+	state->distance = my * state->yscale;
+
+	CLAMP(state->amount, -1.0f, 1.0f);
+	CLAMP(state->distance, 0.0f, FLT_MAX);
+}
+
+static void edbm_blend_from_shape_recalc_factors(bfs_customdata *state) {
+	int a;
+	memset(state->factors, 0.0f, sizeof(float) * state->em->bm->totvert);
+	for (a = 0; a < state->em->bm->totvert; ++a) {
+		state->factors[a] = BM_prop_factor_distance(state->distances[a], state->distance, state->prop_mode);
+	}
+}
+
+static void edbm_blend_from_shape_recalc_shapes(bfs_customdata *state)
+{
+	int a;
+	float (*opshapeco)[3] = (float(*)[3]) state->opkb->data;
+	float (*addshapeco)[3] = (float(*)[3]) state->add_shape_co;
+	float (*origshapeco)[3] = (float(*)[3]) state->origcos;
+	float vec[3];
+	BMVert *v;
+	BMIter iter;
+
+	switch(state->blend_mode) {
+		case BFS_MODE_INTERP:
+			BM_ITER_MESH_INDEX(v, &iter, state->em->bm, BM_VERTS_OF_MESH, a) {
+				interp_v3_v3v3(v->co, origshapeco[a], opshapeco[a], state->amount * state->factors[a]);
+			}
+			break;
+
+		case BFS_MODE_ADD:
+			if (!addshapeco) {
+				KeyBlock *base_kb = BLI_findlink(&state->key->block, state->opkb->relative);
+				float (*baseshapeco)[3] = base_kb->data;
+
+				state->add_shape_co 
+					= MEM_mallocN(sizeof(float) * 3 * state->em->bm->totvert, "blend from shape add cos");
+
+				addshapeco = (float(*)[3]) state->add_shape_co;
+
+				for (a = 0; a < state->em->bm->totvert; ++a) {
+					sub_v3_v3v3(addshapeco[a], opshapeco[a], baseshapeco[a]);
+				}
+			}
+
+			BM_ITER_MESH_INDEX(v, &iter, state->em->bm, BM_VERTS_OF_MESH, a) {
+				copy_v3_v3(vec, addshapeco[a]);
+				mul_v3_fl(vec, state->amount * state->factors[a]);
+				add_v3_v3(v->co, vec);
+			}
+			break;
+
+		default:
+			BLI_assert(0);
+	}
+}
+
+/* print some info in header like Knife */
+static void edbm_draw_blend_from_shape_info(bContext *C, bfs_customdata *state)
+{
+#define BUFFER 1024 /* long keyblock names are a reality :\ */
+	char header[BUFFER];
+
+	BLI_snprintf(header, BUFFER, "Mousewheel: From (%s). LMB/RMB: Confirm, Mouse Left-Right: Intensity (%.3f), " 
+									"Mouse Up/Down: Falloff Distance (%.3f), MMB: Add/Blend (%s), PgUp/PgDwn: Falloff Type (%s).",
+										state->opkb->name,
+										state->amount,
+										state->distance,
+										"TODO",
+		

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list