Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/uvedit/uvedit_unwrap_ops.c
| Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "uvedit_intern.h" | #include "uvedit_intern.h" | ||||
| #include "uvedit_parametrizer.h" | #include "uvedit_parametrizer.h" | ||||
| #include "matrix_transfer.h" | |||||
| #include "slim_C_interface.h" | |||||
| #define max(x, y) (((x) > (y)) ? (x) : (y)) | |||||
| #define min(x, y) (((x) < (y)) ? (x) : (y)) | |||||
| static void modifier_unwrap_state(Object *obedit, Scene *scene, bool *r_use_subsurf) | static void modifier_unwrap_state(Object *obedit, Scene *scene, bool *r_use_subsurf) | ||||
| { | { | ||||
| ModifierData *md; | ModifierData *md; | ||||
| bool subsurf = (scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF) != 0; | bool subsurf = (scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF) != 0; | ||||
| md = obedit->modifiers.first; | md = obedit->modifiers.first; | ||||
| /* subsurf will take the modifier settings only if modifier is first or right after mirror */ | /* subsurf will take the modifier settings only if modifier is first or right after mirror */ | ||||
| ▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | static void construct_param_handle_face_add(ParamHandle *handle, Scene *scene, | ||||
| BMFace *efa, int face_index, const int cd_loop_uv_offset) | BMFace *efa, int face_index, const int cd_loop_uv_offset) | ||||
| { | { | ||||
| ParamKey key; | ParamKey key; | ||||
| ParamKey *vkeys = BLI_array_alloca(vkeys, efa->len); | ParamKey *vkeys = BLI_array_alloca(vkeys, efa->len); | ||||
| ParamBool *pin = BLI_array_alloca(pin, efa->len); | ParamBool *pin = BLI_array_alloca(pin, efa->len); | ||||
| ParamBool *select = BLI_array_alloca(select, efa->len); | ParamBool *select = BLI_array_alloca(select, efa->len); | ||||
| float **co = BLI_array_alloca(co, efa->len); | float **co = BLI_array_alloca(co, efa->len); | ||||
| float **uv = BLI_array_alloca(uv, efa->len); | float **uv = BLI_array_alloca(uv, efa->len); | ||||
| float *id = BLI_array_alloca(id, efa->len); | |||||
| int i; | int i; | ||||
| BMIter liter; | BMIter liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| key = (ParamKey)face_index; | key = (ParamKey)face_index; | ||||
| /* let parametrizer split the ngon, it can make better decisions | /* let parametrizer split the ngon, it can make better decisions | ||||
| * about which split is best for unwrapping than scanfill */ | * about which split is best for unwrapping than scanfill */ | ||||
| BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | ||||
| MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| vkeys[i] = (ParamKey)BM_elem_index_get(l->v); | vkeys[i] = (ParamKey)BM_elem_index_get(l->v); | ||||
| co[i] = l->v->co; | co[i] = l->v->co; | ||||
| uv[i] = luv->uv; | uv[i] = luv->uv; | ||||
| id[i] = l->v->id; | |||||
| pin[i] = (luv->flag & MLOOPUV_PINNED) != 0; | pin[i] = (luv->flag & MLOOPUV_PINNED) != 0; | ||||
| select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); | select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); | ||||
| } | } | ||||
| param_face_add(handle, key, i, vkeys, co, uv, pin, select, efa->no); | param_face_add(handle, key, i, vkeys, co, uv, id, pin, select, efa->no); | ||||
| } | } | ||||
| static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm, | static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm, | ||||
| const bool implicit, const bool fill, const bool sel, | const bool implicit, const bool fill, const bool sel, | ||||
| const bool correct_aspect) | const bool correct_aspect) | ||||
| { | { | ||||
| ParamHandle *handle; | ParamHandle *handle; | ||||
| BMFace *efa; | BMFace *efa; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm, | ||||
| } | } | ||||
| param_construct_end(handle, fill, implicit); | param_construct_end(handle, fill, implicit); | ||||
| return handle; | return handle; | ||||
| } | } | ||||
| static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, | static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, float *id, Scene *scene, const int cd_loop_uv_offset) | ||||
| Scene *scene, const int cd_loop_uv_offset) | |||||
| { | { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter liter; | BMIter liter; | ||||
| MLoopUV *luv; | MLoopUV *luv; | ||||
| *uv = NULL; | *uv = NULL; | ||||
| *pin = 0; | *pin = 0; | ||||
| *select = 1; | *select = 1; | ||||
| *id = 0; | |||||
| if (index == ORIGINDEX_NONE) | if (index == ORIGINDEX_NONE) | ||||
| return; | return; | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (BM_elem_index_get(l->v) == index) { | if (BM_elem_index_get(l->v) == index) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| *uv = luv->uv; | *uv = luv->uv; | ||||
| *id = l->v->id; | |||||
| *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0; | *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0; | ||||
| *select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); | *select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above) | /* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above) | ||||
| ▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, BMEditMesh *em, short fill, short sel, short correct_aspect) | ||||
| } | } | ||||
| /* Prepare and feed faces to the solver */ | /* Prepare and feed faces to the solver */ | ||||
| for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) { | for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) { | ||||
| ParamKey key, vkeys[4]; | ParamKey key, vkeys[4]; | ||||
| ParamBool pin[4], select[4]; | ParamBool pin[4], select[4]; | ||||
| float *co[4]; | float *co[4]; | ||||
| float *uv[4]; | float *uv[4]; | ||||
| float *id[4]; | |||||
| BMFace *origFace = faceMap[i]; | BMFace *origFace = faceMap[i]; | ||||
| if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { | if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { | ||||
| if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN)) | if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN)) | ||||
| continue; | continue; | ||||
| } | } | ||||
| else { | else { | ||||
| if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN) || (sel && !BM_elem_flag_test(origFace, BM_ELEM_SELECT))) | if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN) || (sel && !BM_elem_flag_test(origFace, BM_ELEM_SELECT))) | ||||
| Show All 12 Lines | for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) { | ||||
| co[0] = subsurfedVerts[mloop[0].v].co; | co[0] = subsurfedVerts[mloop[0].v].co; | ||||
| co[1] = subsurfedVerts[mloop[1].v].co; | co[1] = subsurfedVerts[mloop[1].v].co; | ||||
| co[2] = subsurfedVerts[mloop[2].v].co; | co[2] = subsurfedVerts[mloop[2].v].co; | ||||
| co[3] = subsurfedVerts[mloop[3].v].co; | co[3] = subsurfedVerts[mloop[3].v].co; | ||||
| /* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus | /* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus | ||||
| * flushing the solution to the edit mesh. */ | * flushing the solution to the edit mesh. */ | ||||
| texface_from_original_index(origFace, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0], scene, cd_loop_uv_offset); | texface_from_original_index(origFace, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0], &id[0], scene, cd_loop_uv_offset); | ||||
| texface_from_original_index(origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1], scene, cd_loop_uv_offset); | texface_from_original_index(origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1], &id[1], scene, cd_loop_uv_offset); | ||||
| texface_from_original_index(origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2], scene, cd_loop_uv_offset); | texface_from_original_index(origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2], &id[2], scene, cd_loop_uv_offset); | ||||
| texface_from_original_index(origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3], scene, cd_loop_uv_offset); | texface_from_original_index(origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3], &id[3], scene, cd_loop_uv_offset); | ||||
| param_face_add(handle, key, 4, vkeys, co, uv, pin, select, NULL); | param_face_add(handle, key, 4, vkeys, co, uv, pin, select, id, NULL); | ||||
| } | } | ||||
| /* these are calculated from original mesh too */ | /* these are calculated from original mesh too */ | ||||
| for (edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) { | for (edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) { | ||||
| if ((edgeMap[i] != NULL) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) { | if ((edgeMap[i] != NULL) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) { | ||||
| ParamKey vkeys[2]; | ParamKey vkeys[2]; | ||||
| vkeys[0] = (ParamKey)edge->v1; | vkeys[0] = (ParamKey)edge->v1; | ||||
| vkeys[1] = (ParamKey)edge->v2; | vkeys[1] = (ParamKey)edge->v2; | ||||
| param_edge_set_seam(handle, vkeys); | param_edge_set_seam(handle, vkeys); | ||||
| } | } | ||||
| } | } | ||||
| param_construct_end(handle, fill, 0); | param_construct_end(handle, fill, 0); | ||||
| /* cleanup */ | /* cleanup */ | ||||
| MEM_freeN(faceMap); | MEM_freeN(faceMap); | ||||
| MEM_freeN(edgeMap); | MEM_freeN(edgeMap); | ||||
| derivedMesh->release(derivedMesh); | derivedMesh->release(derivedMesh); | ||||
| return handle; | return handle; | ||||
| } | } | ||||
| int setup_weight_transfer(Object *obedit, BMEditMesh *em, char *vertex_group){ | |||||
| int defgrp_index = retrieve_weightmap_index(obedit, vertex_group); | |||||
| return defgrp_index; | |||||
| } | |||||
| void enrich_handle_slim(Scene *scene, Object *obedit, BMEditMesh *em, ParamHandle *handle, matrix_transfer *mt) { | |||||
| int weightMapIndex = setup_weight_transfer(obedit, em, scene->toolsettings->slim_vertex_group); | |||||
| bool with_weighted_parameterization = (weightMapIndex >=0); | |||||
| int n_iterations = scene->toolsettings->slim_n_iterations; | |||||
| bool skip_initialization = scene->toolsettings->slim_skip_initialization; | |||||
| bool pack_islands = scene->toolsettings->slim_pack_islands; | |||||
| double weight_influence = scene->toolsettings->slim_weight_influence; | |||||
| double relative_scale = scene->toolsettings->slim_relative_scale; | |||||
| MDeformVert *weightMapData = NULL; | |||||
| if (with_weighted_parameterization) { | |||||
| Mesh *me = obedit->data; | |||||
| DerivedMesh *dm = mesh_create_derived(me, NULL); | |||||
| weightMapData = dm->getVertDataArray(dm, CD_MDEFORMVERT); | |||||
| } | |||||
| param_slim_enrich_handle(obedit, | |||||
| em, | |||||
| handle, | |||||
| mt, | |||||
| weightMapData, | |||||
| weightMapIndex, | |||||
| weight_influence, | |||||
| relative_scale, | |||||
| n_iterations, | |||||
| skip_initialization, | |||||
| pack_islands, | |||||
| with_weighted_parameterization); | |||||
| } | |||||
| /* ******************** Minimize Stretch operator **************** */ | /* ******************** Minimize Stretch operator **************** */ | ||||
| typedef struct MinStretch { | typedef struct MinStretch { | ||||
| Scene *scene; | Scene *scene; | ||||
| Object *obedit; | Object *obedit; | ||||
| BMEditMesh *em; | BMEditMesh *em; | ||||
| ParamHandle *handle; | ParamHandle *handle; | ||||
| float blend; | float blend; | ||||
| ▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | void UV_OT_minimize_stretch(wmOperatorType *ot) | ||||
| ot->poll = ED_operator_uvedit; | ot->poll = ED_operator_uvedit; | ||||
| /* properties */ | /* properties */ | ||||
| RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry"); | RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry"); | ||||
| RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f); | RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f); | ||||
| RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100); | RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100); | ||||
| } | } | ||||
| /* AUREL THESIS | |||||
| ******************** Minimize Stretch SLIM operator **************** */ | |||||
| /* AUREL GRUBER | |||||
| Holds all necessary state for one session of interactive parametrisation. | |||||
| */ | |||||
| typedef struct { | |||||
| matrix_transfer *mt; | |||||
| ParamHandle *handle; | |||||
| Object *obedit; | |||||
| wmTimer *timer; | |||||
| void** slimPtrs; | |||||
| float blend; | |||||
| bool firstIteration; | |||||
| bool fixBorder; | |||||
| bool noPins; | |||||
| } MinStretchSlim; | |||||
| /* AUREL THESIS | |||||
| Initialises SLIM and transfars data matrices | |||||
| */ | |||||
| static bool minimize_stretch_SLIM_init(bContext *C, wmOperator *op) | |||||
| { | |||||
| Scene *scene = CTX_data_scene(C); | |||||
| Object *obedit = CTX_data_edit_object(C); | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| add_index_to_vertices(em); | |||||
| ParamHandle *handle = construct_param_handle(scene, obedit, em->bm, false, true, 1, 1); | |||||
| MinStretchSlim *mss = MEM_callocN(sizeof(MinStretchSlim), "Data for minimizing stretch with SLIM"); | |||||
| mss->mt = MEM_callocN(sizeof(matrix_transfer), "Matrix Transfer to SLIM"); | |||||
| mss->handle = handle; | |||||
| mss->obedit = obedit; | |||||
| mss->firstIteration = true; | |||||
| mss->fixBorder = true; | |||||
| mss->mt->fixed_boundary = true; | |||||
| scene->toolsettings->slim_skip_initialization = true; | |||||
| scene->toolsettings->slim_pack_islands = false; | |||||
| scene->toolsettings->slim_fixed_boundary = true; | |||||
| scene->toolsettings->slim_weight_influence = RNA_float_get(op->ptr, "slim_weight_influence"); | |||||
| enrich_handle_slim(scene, obedit, em, handle, mss->mt); | |||||
| param_slim_begin(handle); | |||||
| mss->slimPtrs = MEM_callocN(mss->mt->nCharts * sizeof(void*), "pointers to Slim-objects"); | |||||
| for (int chartNr = 0; chartNr < mss->mt->nCharts; chartNr++){ | |||||
| mss->slimPtrs[chartNr] = setup_slim_C(mss->mt, chartNr, mss->fixBorder, true); | |||||
| } | |||||
| op->customdata = mss; | |||||
| return true; | |||||
| } | |||||
| /* AUREL THESIS | |||||
| After initialisation, these iterations are executed, until applied or canceled by the user. | |||||
| */ | |||||
| static void minimize_stretch_SLIM_iteration(bContext *C, wmOperator *op, bool interactive) | |||||
| { | |||||
| // AUREL THESIS In first iteration, check if pins are present | |||||
| MinStretchSlim *mss = op->customdata; | |||||
| if (mss->firstIteration){ | |||||
| mss->firstIteration = false; | |||||
| if (!(mss->fixBorder)){ | |||||
| mss->noPins = mark_pins(mss->handle); | |||||
| } | |||||
| } | |||||
| // AUREL THESIS Do one iteration and tranfer UVs | |||||
| for (int chartNr = 0; chartNr < mss->mt->nCharts; chartNr++){ | |||||
| void *slimPtr = mss->slimPtrs[chartNr]; | |||||
| param_slim_single_iteration_C(slimPtr); | |||||
| transfer_uvs_blended_C(mss->mt, slimPtr, chartNr, mss->blend); | |||||
| } | |||||
| // AUREL THESIS Assign new UVs back to each vertex | |||||
| set_uv_param_slim(mss->handle, mss->mt); | |||||
| if (!(mss->fixBorder)){ | |||||
| if (mss->noPins){ | |||||
| param_pack(mss->handle, 0, false); | |||||
| } | |||||
| } | |||||
| param_flush(mss->handle); | |||||
| DAG_id_tag_update(mss->obedit->data, 0); | |||||
| WM_event_add_notifier(C, NC_GEOM | ND_DATA, mss->obedit->data); | |||||
| } | |||||
| void free_slimPtrs(void **slimPtrs, int nCharts){ | |||||
| for (int i = 0; i<nCharts; i++){ | |||||
| free_slim_data_C(slimPtrs[i]); | |||||
| } | |||||
| } | |||||
| /* AUREL THESIS | |||||
| Exit interactive parametrisation. Clean up memory. | |||||
| */ | |||||
| static void minimize_stretch_SLIM_exit(bContext *C, wmOperator *op, bool cancel) | |||||
| { | |||||
| MinStretchSlim *mss = op->customdata; | |||||
| /* | |||||
| if (!mss->fixBorder){ | |||||
| remove_pins(mss->handle); | |||||
| }*/ | |||||
| if (cancel){ | |||||
| mss->blend = 1.0f; | |||||
| } | |||||
| for (int chartNr = 0; chartNr < mss->mt->nCharts; chartNr++){ | |||||
| void *slimPtr = mss->slimPtrs[chartNr]; | |||||
| transfer_uvs_blended_C(mss->mt, slimPtr, chartNr, mss->blend); | |||||
| } | |||||
| set_uv_param_slim(mss->handle, mss->mt); | |||||
| if (!(mss->fixBorder)){ | |||||
| if (mss->noPins){ | |||||
| param_pack(mss->handle, 0, false); | |||||
| } | |||||
| } | |||||
| param_flush(mss->handle); | |||||
| param_delete(mss->handle); | |||||
| free_slimPtrs(mss->slimPtrs, mss->mt->nCharts); | |||||
| free_matrix_transfer(mss->mt); | |||||
| MEM_freeN(mss->slimPtrs); | |||||
| MEM_freeN(mss); | |||||
| op->customdata = NULL; | |||||
| } | |||||
| /* AUREL THESIS | |||||
| Used Only to adjust parameters. | |||||
| */ | |||||
| static int minimize_stretch_SLIM_exec(bContext *C, wmOperator *op) | |||||
| { | |||||
| return OPERATOR_FINISHED; | |||||
| } | |||||
| /* AUREL THESIS | |||||
| Entry point to interactive parametrisation. Already executes one iteration, allowing faster feedback. | |||||
| */ | |||||
| static int minimize_stretch_SLIM_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | |||||
| { | |||||
| MinStretchSlim *mss; | |||||
| if (!minimize_stretch_SLIM_init(C, op)) | |||||
| return OPERATOR_CANCELLED; | |||||
| minimize_stretch_SLIM_iteration(C, op, true); | |||||
| mss = op->customdata; | |||||
| WM_event_add_modal_handler(C, op); | |||||
| mss->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); | |||||
| return OPERATOR_RUNNING_MODAL; | |||||
| } | |||||
| /* AUREL THESIS | |||||
| The control structure of the modal operator. a next iteration is either started due to a timer or | |||||
| user input. | |||||
| */ | |||||
| static int minimize_stretch_SLIM_modal(bContext *C, wmOperator *op, const wmEvent *event) | |||||
| { | |||||
| MinStretchSlim *mss = op->customdata; | |||||
| switch (event->type) { | |||||
| case ESCKEY: | |||||
| case RIGHTMOUSE: | |||||
| minimize_stretch_SLIM_exit(C, op, true); | |||||
| return OPERATOR_CANCELLED; | |||||
| case RETKEY: | |||||
| case PADENTER: | |||||
| case LEFTMOUSE: | |||||
| minimize_stretch_SLIM_exit(C, op, false); | |||||
| return OPERATOR_FINISHED; | |||||
| case PADPLUSKEY: | |||||
| case WHEELUPMOUSE: | |||||
| if (event->val == KM_PRESS) { | |||||
| if (mss->blend < 1.0f) { | |||||
| mss->blend += min(0.1f, 1 - (mss->blend)); | |||||
| minimize_stretch_SLIM_iteration(C, op, true); | |||||
| } | |||||
| } | |||||
| break; | |||||
| case PADMINUS: | |||||
| case WHEELDOWNMOUSE: | |||||
| if (event->val == KM_PRESS) { | |||||
| if (mss->blend > 0.0f) { | |||||
| mss->blend -= min(0.1f, mss->blend); | |||||
| minimize_stretch_SLIM_iteration(C, op, true); | |||||
| } | |||||
| } | |||||
| break; | |||||
| case TIMER: | |||||
| if (mss->timer == event->customdata) { | |||||
| double start = PIL_check_seconds_timer(); | |||||
| do { | |||||
| minimize_stretch_SLIM_iteration(C, op, true); | |||||
| } while (PIL_check_seconds_timer() - start < 0.01); | |||||
| } | |||||
| break; | |||||
| } | |||||
| /*if (ms->iterations && ms->i >= ms->iterations) { | |||||
| minimize_stretch_exit(C, op, false); | |||||
| return OPERATOR_FINISHED; | |||||
| }*/ | |||||
| return OPERATOR_RUNNING_MODAL; | |||||
| } | |||||
| /* AUREL THESIS | |||||
| Cancels the interactive parametrisation and discards the obtained map. | |||||
| */ | |||||
| static void minimize_stretch_SLIM_cancel(bContext *C, wmOperator *op) | |||||
| { | |||||
| minimize_stretch_SLIM_exit(C, op, true); | |||||
| } | |||||
| /* AUREL THESIS | |||||
| Registration of the operator and integration into UI (can be executed with ctrl. + M) | |||||
| */ | |||||
| void UV_OT_minimize_stretch_slim(wmOperatorType *ot) | |||||
| { | |||||
| /* identifiers */ | |||||
| ot->name = "Minimize Stretch SLIM"; | |||||
| ot->idname = "UV_OT_minimize_stretch_slim"; | |||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; | |||||
| ot->description = "Reduce UV stretching by applying the SLIM algorithm"; | |||||
| /* api callbacks */ | |||||
| ot->exec = minimize_stretch_SLIM_exec; | |||||
| ot->invoke = minimize_stretch_SLIM_invoke; | |||||
| ot->modal = minimize_stretch_SLIM_modal; | |||||
| ot->cancel = minimize_stretch_SLIM_cancel; | |||||
| ot->poll = ED_operator_uvedit; | |||||
| /* properties */ | |||||
| RNA_def_boolean(ot->srna, "fill_holes_slim", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry"); | |||||
| RNA_def_float_factor(ot->srna, "blend_slim", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f); | |||||
| RNA_def_int(ot->srna, "iterations_slim", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100); | |||||
| RNA_def_float(ot->srna, "slim_weight_influence", 1.0, -10000.0, 10000.0, "SLIM Weight Map Influence", | |||||
| "How much influence the weightmap has for weighted parameterization, 0 being no influence.", 0.0, 10.0);} | |||||
| /* ******************** Pack Islands operator **************** */ | /* ******************** Pack Islands operator **************** */ | ||||
| void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate) | void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate) | ||||
| { | { | ||||
| ParamHandle *handle; | ParamHandle *handle; | ||||
| handle = construct_param_handle(scene, ob, bm, true, false, selected, correct_aspect); | handle = construct_param_handle(scene, ob, bm, true, false, selected, correct_aspect); | ||||
| param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate); | param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate); | ||||
| param_flush(handle); | param_flush(handle); | ||||
| ▲ Show 20 Lines • Show All 413 Lines • ▼ Show 20 Lines | static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOperator *op) | ||||
| } | } | ||||
| } | } | ||||
| /* ******************** Unwrap operator **************** */ | /* ******************** Unwrap operator **************** */ | ||||
| /* assumes UV Map is checked, doesn't run update funcs */ | /* assumes UV Map is checked, doesn't run update funcs */ | ||||
| void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel) | void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel) | ||||
| { | { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| ParamHandle *handle; | ParamHandle *handle; | ||||
| const bool fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0; | const bool fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0; | ||||
| const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0; | const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0; | ||||
| scene->toolsettings->slim_skip_initialization = false; | |||||
| scene->toolsettings->slim_pack_islands = true; | |||||
| scene->toolsettings->slim_fixed_boundary = false; | |||||
| bool use_subsurf; | bool use_subsurf; | ||||
| bool use_slim_method = (scene->toolsettings->unwrapper == 2); | |||||
| if(use_slim_method){ | |||||
| add_index_to_vertices(em); | |||||
| } | |||||
| modifier_unwrap_state(obedit, scene, &use_subsurf); | modifier_unwrap_state(obedit, scene, &use_subsurf); | ||||
| if (use_subsurf) | if (use_subsurf) | ||||
| handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect); | handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect); | ||||
| else | else | ||||
| handle = construct_param_handle(scene, obedit, em->bm, false, fill_holes, sel, correct_aspect); | handle = construct_param_handle(scene, obedit, em->bm, false, fill_holes, sel, correct_aspect); | ||||
| param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0); | if (use_slim_method){ | ||||
| param_lscm_solve(handle); | matrix_transfer *mt = MEM_callocN(sizeof(matrix_transfer), "matrix transfer data"); | ||||
| param_lscm_end(handle); | mt->slim_reflection_mode = scene->toolsettings->slim_reflection_mode; | ||||
| enrich_handle_slim(scene, obedit, em, handle, mt); | |||||
| } | |||||
| param_begin(handle, scene->toolsettings->unwrapper == 0, use_slim_method); | |||||
| param_solve(handle, use_slim_method); | |||||
| bool transform = (!use_slim_method || transformIslands(handle)); | |||||
| param_end(handle, use_slim_method); | |||||
| if (transform){ | |||||
| printf("packing & scaling islands"); | |||||
| param_average(handle); | param_average(handle); | ||||
| param_pack(handle, scene->toolsettings->uvcalc_margin, false); | param_pack(handle, scene->toolsettings->uvcalc_margin, false); | ||||
| } | |||||
| param_flush(handle); | param_flush(handle); | ||||
| param_delete(handle); | param_delete(handle); | ||||
| } | } | ||||
| static int unwrap_exec(bContext *C, wmOperator *op) | static int unwrap_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| Object *obedit = CTX_data_edit_object(C); | Object *obedit = CTX_data_edit_object(C); | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| int method = RNA_enum_get(op->ptr, "method"); | int method = RNA_enum_get(op->ptr, "method"); | ||||
| int n_slim_iterations = RNA_int_get(op->ptr, "slim_iterations"); | |||||
| double slim_weight_influence = RNA_float_get(op->ptr, "slim_weight_influence"); | |||||
| double slim_relative_scale = RNA_float_get(op->ptr, "slim_relative_scale"); | |||||
| int slim_reflection_mode = RNA_enum_get(op->ptr, "slim_reflection_mode"); | |||||
| char slim_vertex_group[64]; | |||||
| RNA_string_get(op->ptr, "slim_vertex_group", slim_vertex_group); | |||||
| const bool fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); | const bool fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); | ||||
| const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"); | const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"); | ||||
| const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data"); | const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data"); | ||||
| bool use_subsurf_final; | bool use_subsurf_final; | ||||
| float obsize[3]; | float obsize[3]; | ||||
| bool implicit = false; | bool implicit = false; | ||||
| if (!uvedit_have_selection(scene, em, implicit)) { | if (!uvedit_have_selection(scene, em, implicit)) { | ||||
| Show All 14 Lines | BKE_report(op->reports, RPT_INFO, | ||||
| "Object has negative scale, unwrap will operate on a non-flipped version of the mesh"); | "Object has negative scale, unwrap will operate on a non-flipped version of the mesh"); | ||||
| /* remember last method for live unwrap */ | /* remember last method for live unwrap */ | ||||
| if (RNA_struct_property_is_set(op->ptr, "method")) | if (RNA_struct_property_is_set(op->ptr, "method")) | ||||
| scene->toolsettings->unwrapper = method; | scene->toolsettings->unwrapper = method; | ||||
| else | else | ||||
| RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper); | RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper); | ||||
| /* get number of iterations and method in global phase for SLIM unwraping*/ | |||||
| scene->toolsettings->slim_n_iterations = n_slim_iterations; | |||||
| scene->toolsettings->slim_weight_influence = slim_weight_influence; | |||||
| scene->toolsettings->slim_reflection_mode = slim_reflection_mode; | |||||
| scene->toolsettings->slim_relative_scale = slim_relative_scale; | |||||
| scene->toolsettings->slim_vertex_group = slim_vertex_group; | |||||
| /* remember packing marging */ | /* remember packing marging */ | ||||
| if (RNA_struct_property_is_set(op->ptr, "margin")) | if (RNA_struct_property_is_set(op->ptr, "margin")) | ||||
| scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin"); | scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin"); | ||||
| else | else | ||||
| RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin); | RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin); | ||||
| if (fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES; | if (fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES; | ||||
| else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES; | else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES; | ||||
| Show All 19 Lines | static int unwrap_exec(bContext *C, wmOperator *op) | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void UV_OT_unwrap(wmOperatorType *ot) | void UV_OT_unwrap(wmOperatorType *ot) | ||||
| { | { | ||||
| static EnumPropertyItem method_items[] = { | static EnumPropertyItem method_items[] = { | ||||
| {0, "ANGLE_BASED", 0, "Angle Based", ""}, | {0, "ANGLE_BASED", 0, "Angle Based", ""}, | ||||
| {1, "CONFORMAL", 0, "Conformal", ""}, | {1, "CONFORMAL", 0, "Conformal", ""}, | ||||
| {2, "SLIM", 0, "SLIM", "" }, | |||||
| {0, NULL, 0, NULL, NULL} | |||||
| }; | |||||
| static EnumPropertyItem reflection_items[] = { | |||||
| {0, "ALLOW", 0, "Allow Flips", ""}, | |||||
| {1, "DISALLOW", 0, "Don't Allow Flips", ""}, | |||||
| {0, NULL, 0, NULL, NULL} | {0, NULL, 0, NULL, NULL} | ||||
| }; | }; | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Unwrap"; | ot->name = "Unwrap"; | ||||
| ot->description = "Unwrap the mesh of the object being edited"; | ot->description = "Unwrap the mesh of the object being edited"; | ||||
| ot->idname = "UV_OT_unwrap"; | ot->idname = "UV_OT_unwrap"; | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| /* api callbacks */ | /* api callbacks */ | ||||
| ot->exec = unwrap_exec; | ot->exec = unwrap_exec; | ||||
| ot->poll = ED_operator_uvmap; | ot->poll = ED_operator_uvmap; | ||||
| /* properties */ | /* properties */ | ||||
| RNA_def_enum(ot->srna, "method", method_items, 0, "Method", | RNA_def_enum(ot->srna, "method", method_items, 0, "Method", | ||||
| "Unwrapping method (Angle Based usually gives better results than Conformal, while being somewhat slower)"); | "Unwrapping method (Angle Based usually gives better results than Conformal, while being somewhat slower)"); | ||||
| RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", | RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", | ||||
| "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry"); | "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry"); | ||||
| RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect", | RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect", | ||||
| "Map UVs taking image aspect ratio into account"); | "Map UVs taking image aspect ratio into account"); | ||||
| RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier", | RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier", | ||||
| "Map UVs taking vertex position after Subdivision Surface modifier has been applied"); | "Map UVs taking vertex position after Subdivision Surface modifier has been applied"); | ||||
| RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); | RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); | ||||
| RNA_def_enum(ot->srna, "slim_reflection_mode", reflection_items, 0, "SLIM Reflection Mode", | |||||
| "Allowing reflections means that depending on the position of pins, the map may be flipped. Lower distortion."); | |||||
| RNA_def_int(ot->srna, "slim_iterations", 1, -10, 10000, "SLIM Iterations", | |||||
| "Number of Iterations if the SLIM algorithm is used.", 1, 30); | |||||
| RNA_def_float(ot->srna, "slim_relative_scale", 1.0, 0.001, 1000.0, "SLIM Relative Scale", | |||||
| "Relative Scale of UV Map with respect to pins.", 0.1, 10.0); | |||||
| PropertyRNA *prop; | |||||
| prop = RNA_def_property(ot->srna, "slim_vertex_group", PROP_STRING, PROP_NONE); | |||||
| RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); | |||||
| RNA_def_float(ot->srna, "slim_weight_influence", 1.0, -10000.0, 10000.0, "SLIM Weight Map Influence", | |||||
| "How much influence the weightmap has for weighted parameterization, 0 being no influence.", 0.0, 10.0); | |||||
| } | } | ||||
| /**************** Project From View operator **************/ | /**************** Project From View operator **************/ | ||||
| static int uv_from_view_exec(bContext *C, wmOperator *op); | static int uv_from_view_exec(bContext *C, wmOperator *op); | ||||
| static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | ||||
| { | { | ||||
| View3D *v3d = CTX_wm_view3d(C); | View3D *v3d = CTX_wm_view3d(C); | ||||
| ▲ Show 20 Lines • Show All 434 Lines • Show Last 20 Lines | |||||