[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