86
87
#include "uvedit_intern.h"
87
88
#include "uvedit_parametrizer.h"
90
static void modifier_unwrap_state(Object *obedit, Scene *scene, short *use_subsurf)
93
short subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
95
md = obedit->modifiers.first;
97
/* subsurf will take the modifier settings only if modifier is first or right after mirror */
99
if (md && md->type == eModifierType_Subsurf)
105
*use_subsurf = subsurf;
89
108
static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
91
110
Main *bmain = CTX_data_main(C);
101
if (ED_uvedit_test(obedit)) {
120
if (ED_uvedit_test(obedit))
105
if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
106
BM_data_layer_add(em->bm, &em->bm->pdata, CD_MTEXPOLY);
107
BM_data_layer_add(em->bm, &em->bm->ldata, CD_MLOOPUV);
108
ED_mesh_uv_loop_reset_ex(C, obedit->data, 0);
111
if (!ED_uvedit_test(obedit)) {
123
if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY))
124
ED_mesh_uv_texture_add(C, obedit->data, NULL, TRUE);
126
if (!ED_uvedit_test(obedit))
115
129
ima = CTX_data_edit_image(C);
148
162
/****************** Parametrizer Conversion ***************/
150
static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
164
static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
154
168
BMIter iter, liter;
170
if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
171
return (em->bm->totfacesel != 0);
157
174
/* verify if we have any selected uv's before unwrapping,
158
175
* so we can cancel the operator early */
159
176
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
161
178
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
164
else if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))
181
else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
167
184
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
168
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
172
185
if (uvedit_uv_select_test(em, scene, l))
176
189
if (implicit && !l)
185
static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em,
198
void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
201
int selected = FALSE;
205
efa = BM_active_face_get(em->bm, sloppy, selected);
208
if (BKE_scene_use_new_shading_nodes(scene)) {
209
ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL);
212
MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
216
ED_image_get_uv_aspect(ima, NULL, aspx, aspy);
224
static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh *em,
186
225
short implicit, short fill, short sel,
187
226
short correct_aspect)
189
229
ScanFillContext sf_ctx;
190
230
ParamHandle *handle;
194
234
BMIter iter, liter;
236
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
197
238
handle = param_construct_begin();
199
241
if (correct_aspect) {
200
efa = BM_active_face_get(em->bm, TRUE);
204
tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
206
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
209
param_aspect_ratio(handle, aspx, aspy);
244
uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
247
param_aspect_ratio(handle, aspx, aspy);
213
250
/* we need the vert indices */
218
255
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
219
ScanFillVert *v, *lastv, *firstv;
256
ScanFillVert *sf_vert = NULL, *sf_vert_last, *sf_vert_first;
257
ScanFillFace *sf_tri;
221
258
ParamKey key, vkeys[4];
222
259
ParamBool pin[4], select[4];
228
265
if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0))
243
280
key = (ParamKey)efa;
282
// tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); // UNUSED
246
284
if (efa->len == 3 || efa->len == 4) {
247
286
/* for quads let parametrize split, it can make better decisions
248
287
* about which split is best for unwrapping than scanfill */
250
289
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
251
MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
290
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
252
291
vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
253
292
co[i] = l->v->co;
264
303
/* ngon - scanfill time! */
265
BLI_begin_edgefill(&sf_ctx);
304
BLI_scanfill_begin(&sf_ctx);
267
firstv = lastv = NULL;
306
sf_vert_first = sf_vert_last = NULL;
268
307
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
271
v = BLI_addfillvert(&sf_ctx, l->v->co);
310
sf_vert = BLI_scanfill_vert_add(&sf_ctx, l->v->co);
273
312
/* add small random offset */
274
313
for (i = 0; i < 3; i++) {
275
v->co[i] += (BLI_frand() - 0.5f) * FLT_EPSILON * 50;
314
sf_vert->co[i] += (BLI_frand() - 0.5f) * FLT_EPSILON * 50;
281
BLI_addfilledge(&sf_ctx, lastv, v);
320
BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
323
sf_vert_last = sf_vert;
325
sf_vert_first = sf_vert;
289
BLI_addfilledge(&sf_ctx, firstv, v);
328
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
291
BLI_edgefill_ex(&sf_ctx, TRUE, efa->no);
292
for (sefa = sf_ctx.fillfacebase.first; sefa; sefa = sefa->next) {
293
ls[0] = sefa->v1->tmp.p;
294
ls[1] = sefa->v2->tmp.p;
295
ls[2] = sefa->v3->tmp.p;
330
BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
331
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
333
ls[0] = sf_tri->v1->tmp.p;
334
ls[1] = sf_tri->v2->tmp.p;
335
ls[2] = sf_tri->v3->tmp.p;
297
337
for (i = 0; i < 3; i++) {
298
MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, ls[i]->head.data, CD_MLOOPUV);
338
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[i], cd_loop_uv_offset);
299
339
vkeys[i] = (ParamKey)BM_elem_index_get(ls[i]->v);
300
340
co[i] = ls[i]->v->co;
330
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene, BMEditMesh *em)
370
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
371
Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset)
343
384
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
344
385
if (BM_elem_index_get(l->v) == index) {
345
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
386
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
347
388
*pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
348
389
*select = (uvedit_uv_select_test(em, scene, l) != 0);
353
395
/* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above)
354
396
* work justified the existence of a new function. */
355
static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *em, short fill, short sel, short correct_aspect)
397
static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, BMEditMesh *em, short fill, short sel, short correct_aspect)
357
399
ParamHandle *handle;
358
400
/* index pointers */
405
/* pointers to modifier data for unwrap control */
407
SubsurfModifierData *smd_real;
364
408
/* modifier initialization data, will control what type of subdivision will happen*/
365
409
SubsurfModifierData smd = {{0}};
366
410
/* Used to hold subsurfed Mesh */
367
411
DerivedMesh *derivedMesh, *initialDerived;
368
412
/* holds original indices for subsurfed mesh */
369
int *origVertIndices, *origFaceIndices, *origEdgeIndices;
413
int *origVertIndices, *origEdgeIndices, *origFaceIndices, *origPolyIndices;
370
414
/* Holds vertices of subsurfed mesh */
371
415
MVert *subsurfedVerts;
372
416
MEdge *subsurfedEdges;
379
423
/* similar to the above, we need a way to map edges to their original ones */
380
424
BMEdge **edgeMap;
426
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
382
428
handle = param_construct_begin();
384
430
if (correct_aspect) {
385
editFace = BM_active_face_get(em->bm, TRUE);
390
tf = CustomData_bmesh_get(&em->bm->pdata, editFace->head.data, CD_MTEXPOLY);
392
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
395
param_aspect_ratio(handle, aspx, aspy);
433
uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
436
param_aspect_ratio(handle, aspx, aspy);
399
439
/* number of subdivisions to perform */
400
smd.levels = scene->toolsettings->uv_subsurf_level;
401
smd.subdivType = ME_CC_SUBSURF;
440
md = ob->modifiers.first;
441
smd_real = (SubsurfModifierData *)md;
443
smd.levels = smd_real->levels;
444
smd.subdivType = smd_real->subdivType;
403
initialDerived = CDDM_from_BMEditMesh(em, NULL, 0, 0);
446
initialDerived = CDDM_from_editbmesh(em, FALSE, FALSE);
404
447
derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd,
448
NULL, SUBSURF_IN_EDIT_MODE);
407
450
initialDerived->release(initialDerived);
414
457
origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
415
458
origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
416
459
origFaceIndices = derivedMesh->getTessFaceDataArray(derivedMesh, CD_ORIGINDEX);
460
origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX);
418
462
numOfEdges = derivedMesh->getNumEdges(derivedMesh);
419
463
numOfFaces = derivedMesh->getNumTessFaces(derivedMesh);
421
465
faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
423
467
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
424
EDBM_index_arrays_init(em, 0, 1, 1);
468
EDBM_index_arrays_ensure(em, BM_EDGE | BM_FACE);
426
470
/* map subsurfed faces to original editFaces */
427
471
for (i = 0; i < numOfFaces; i++)
428
faceMap[i] = EDBM_face_at_index(em, origFaceIndices[i]);
472
faceMap[i] = EDBM_face_at_index(em, DM_origindex_mface_mpoly(origFaceIndices, origPolyIndices, i));
430
474
edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
432
476
/* map subsurfed edges to original editEdges */
433
477
for (i = 0; i < numOfEdges; i++) {
434
478
/* not all edges correspond to an old edge */
435
edgeMap[i] = (origEdgeIndices[i] != -1) ?
479
edgeMap[i] = (origEdgeIndices[i] != ORIGINDEX_NONE) ?
436
480
EDBM_edge_at_index(em, origEdgeIndices[i]) : NULL;
439
EDBM_index_arrays_free(em);
441
483
/* Prepare and feed faces to the solver */
442
484
for (i = 0; i < numOfFaces; i++) {
443
485
ParamKey key, vkeys[4];
472
514
/* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus
473
515
* flushing the solution to the edit mesh. */
474
texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em);
475
texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em);
476
texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em);
477
texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em);
516
texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em, cd_loop_uv_offset);
517
texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em, cd_loop_uv_offset);
518
texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em, cd_loop_uv_offset);
519
texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em, cd_loop_uv_offset);
479
521
param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
515
static int minimize_stretch_init(bContext *C, wmOperator *op)
557
static bool minimize_stretch_init(bContext *C, wmOperator *op)
517
559
Scene *scene = CTX_data_scene(C);
518
560
Object *obedit = CTX_data_edit_object(C);
519
561
BMEditMesh *em = BMEdit_FromObject(obedit);
521
563
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
564
bool implicit = true;
524
566
if (!uvedit_have_selection(scene, em, implicit)) {
528
570
ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
532
574
ms->blend = RNA_float_get(op->ptr, "blend");
533
575
ms->iterations = RNA_int_get(op->ptr, "iterations");
535
ms->handle = construct_param_handle(scene, em, implicit, fill_holes, 1, 1);
577
ms->handle = construct_param_handle(scene, obedit, em, implicit, fill_holes, 1, 1);
536
578
ms->lasttime = PIL_check_seconds_timer();
538
580
param_stretch_begin(ms->handle);
561
603
param_flush(ms->handle);
564
BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f", ms->blend);
606
BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f (Press + and -, or scroll wheel to set)", ms->blend);
565
607
ED_area_headerprint(sa, str);
644
686
return OPERATOR_FINISHED;
646
688
case WHEELUPMOUSE:
647
if (ms->blend < 0.95f) {
650
RNA_float_set(op->ptr, "blend", ms->blend);
651
minimize_stretch_iteration(C, op, 1);
689
if (event->val == KM_PRESS) {
690
if (ms->blend < 0.95f) {
693
RNA_float_set(op->ptr, "blend", ms->blend);
694
minimize_stretch_iteration(C, op, 1);
655
699
case WHEELDOWNMOUSE:
656
if (ms->blend > 0.05f) {
659
RNA_float_set(op->ptr, "blend", ms->blend);
660
minimize_stretch_iteration(C, op, 1);
700
if (event->val == KM_PRESS) {
701
if (ms->blend > 0.05f) {
704
RNA_float_set(op->ptr, "blend", ms->blend);
705
minimize_stretch_iteration(C, op, 1);
715
761
Object *obedit = CTX_data_edit_object(C);
716
762
BMEditMesh *em = BMEdit_FromObject(obedit);
717
763
ParamHandle *handle;
764
bool implicit = true;
720
766
if (!uvedit_have_selection(scene, em, implicit)) {
721
767
return OPERATOR_CANCELLED;
724
if (RNA_struct_property_is_set(op->ptr, "margin")) {
770
if (RNA_struct_property_is_set(op->ptr, "margin"))
725
771
scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
728
773
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
731
handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
775
handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
732
776
param_pack(handle, scene->toolsettings->uvcalc_margin);
733
777
param_flush(handle);
734
778
param_delete(handle);
751
797
ot->poll = ED_operator_uvedit;
754
RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
800
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
757
803
/* ******************** Average Islands Scale operator **************** */
762
808
Object *obedit = CTX_data_edit_object(C);
763
809
BMEditMesh *em = BMEdit_FromObject(obedit);
764
810
ParamHandle *handle;
811
bool implicit = true;
767
813
if (!uvedit_have_selection(scene, em, implicit)) {
768
814
return OPERATOR_CANCELLED;
771
handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
817
handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
772
818
param_average(handle);
773
819
param_flush(handle);
774
820
param_delete(handle);
800
848
BMEditMesh *em = BMEdit_FromObject(obedit);
801
849
short abf = scene->toolsettings->unwrapper == 0;
802
850
short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
803
short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
853
modifier_unwrap_state(obedit, scene, &use_subsurf);
805
855
if (!ED_uvedit_test(obedit)) {
810
liveHandle = construct_param_handle_subsurfed(scene, em, fillholes, 0, 1);
860
liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, FALSE, TRUE);
812
liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
862
liveHandle = construct_param_handle(scene, obedit, em, FALSE, fillholes, FALSE, TRUE);
814
864
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
838
888
BMEditMesh *em = BMEdit_FromObject(obedit);
840
if (scene->toolsettings->edge_mode_live_unwrap &&
841
CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
842
ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
890
if (scene->toolsettings->edge_mode_live_unwrap &&
891
CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
893
ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
846
897
/*************** UV Map Common Transforms *****************/
855
906
static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
856
907
Object *ob, BMEditMesh *em)
861
float min[3], max[3], *cursx;
862
909
int around = (v3d) ? v3d->around : V3D_CENTER;
864
911
/* only operates on the edit object - this is all that's needed now */
866
913
switch (around) {
867
914
case V3D_CENTER: /* bounding box center */
868
min[0] = min[1] = min[2] = 1e20f;
869
max[0] = max[1] = max[2] = -1e20f;
919
float min[3], max[3];
921
INIT_MINMAX(min, max);
871
923
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
872
924
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
873
925
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
874
DO_MINMAX(l->v->co, min, max);
926
minmax_v3v3_v3(min, max, l->v->co);
878
930
mid_v3_v3v3(result, min, max);
881
case V3D_CURSOR: /*cursor center*/
882
cursx = give_cursor(scene, v3d);
933
case V3D_CURSOR: /* cursor center */
935
const float *curs = give_cursor(scene, v3d);
883
936
/* shift to objects world */
884
result[0] = cursx[0] - ob->obmat[3][0];
885
result[1] = cursx[1] - ob->obmat[3][1];
886
result[2] = cursx[2] - ob->obmat[3][2];
937
sub_v3_v3v3(result, curs, ob->obmat[3]);
889
case V3D_LOCAL: /*object center*/
890
case V3D_CENTROID: /* multiple objects centers, only one object here*/
940
case V3D_LOCAL: /* object center */
941
case V3D_CENTROID: /* multiple objects centers, only one object here*/
892
result[0] = result[1] = result[2] = 0.0;
897
static void uv_map_rotation_matrix(float result[][4], RegionView3D *rv3d, Object *ob,
948
static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Object *ob,
898
949
float upangledeg, float sideangledeg, float radius)
900
951
float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
925
976
/* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
926
977
/* i wanted to keep the reason here, so we're rotating*/
927
978
sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
928
rotside[0][0] = (float)cos(sideangle);
929
rotside[0][1] = -(float)sin(sideangle);
930
rotside[1][0] = (float)sin(sideangle);
931
rotside[1][1] = (float)cos(sideangle);
932
rotside[2][2] = 1.0f;
979
rotside[0][0] = cosf(sideangle);
980
rotside[0][1] = -sinf(sideangle);
981
rotside[1][0] = sinf(sideangle);
982
rotside[1][1] = cosf(sideangle);
983
rotside[2][2] = 1.0f;
934
985
upangle = (float)M_PI * upangledeg / 180.0f;
935
rotup[1][1] = (float)cos(upangle) / radius;
936
rotup[1][2] = -(float)sin(upangle) / radius;
937
rotup[2][1] = (float)sin(upangle) / radius;
938
rotup[2][2] = (float)cos(upangle) / radius;
939
rotup[0][0] = (float)1.0f / radius;
986
rotup[1][1] = cosf(upangle) / radius;
987
rotup[1][2] = -sinf(upangle) / radius;
988
rotup[2][1] = sinf(upangle) / radius;
989
rotup[2][2] = cosf(upangle) / radius;
990
rotup[0][0] = 1.0f / radius;
941
992
/* calculate transforms*/
942
993
mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
999
1050
"Radius of the sphere or cylinder", 0.0001f, 100.0f);
1002
static void correct_uv_aspect(BMEditMesh *em)
1053
static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
1004
BMFace *efa = BM_active_face_get(em->bm, TRUE);
1006
1056
BMIter iter, liter;
1008
float scale, aspx = 1.0f, aspy = 1.0f;
1059
float scale, aspx, aspy;
1061
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1013
tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1014
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
1063
uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
1017
1065
if (aspx == aspy)
1021
1069
scale = aspy / aspx;
1023
1071
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1024
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
1072
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1027
1075
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1028
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1029
luv->uv[0] = ((luv->uv[0] - 0.5) * scale) + 0.5;
1076
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1077
luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
1034
1082
scale = aspx / aspy;
1036
1084
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1037
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
1085
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1040
1088
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1041
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1042
luv->uv[1] = ((luv->uv[1] - 0.5) * scale) + 0.5;
1089
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1090
luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
1068
1116
int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
1069
1117
int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
1119
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1071
1121
/* correct for image aspect ratio */
1072
1122
if (correct_aspect)
1073
correct_uv_aspect(em);
1123
correct_uv_aspect(scene, ob, em);
1075
1125
if (scale_to_bounds) {
1076
1126
INIT_MINMAX2(min, max);
1082
1132
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1083
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1084
DO_MINMAX2(luv->uv, min, max);
1133
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1134
minmax_v2v2_v2(min, max, luv->uv);
1101
1151
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1102
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1152
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1104
1154
luv->uv[0] = (luv->uv[0] - min[0]) * dx;
1105
1155
luv->uv[1] = (luv->uv[1] - min[1]) * dy;
1115
1165
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1116
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1166
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1117
1167
CLAMP(luv->uv[0], 0.0f, 1.0f);
1118
1168
CLAMP(luv->uv[1], 0.0f, 1.0f);
1132
1182
const short fill_holes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
1133
1183
const short correct_aspect = !(scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT);
1134
const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
1186
modifier_unwrap_state(obedit, scene, &use_subsurf);
1136
1188
if (use_subsurf)
1137
handle = construct_param_handle_subsurfed(scene, em, fill_holes, sel, correct_aspect);
1189
handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
1139
handle = construct_param_handle(scene, em, 0, fill_holes, sel, correct_aspect);
1191
handle = construct_param_handle(scene, obedit, em, FALSE, fill_holes, sel, correct_aspect);
1141
1193
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
1142
1194
param_lscm_solve(handle);
1159
1211
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
1160
1212
int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1161
1213
int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
1162
int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level");
1163
float obsize[3], unitsize[3] = {1.0f, 1.0f, 1.0f};
1214
short use_subsurf_final;
1216
bool implicit = false;
1166
1218
if (!uvedit_have_selection(scene, em, implicit)) {
1167
1219
return OPERATOR_CANCELLED;
1175
1227
mat4_to_size(obsize, obedit->obmat);
1176
if (!compare_v3v3(obsize, unitsize, 1e-4f))
1177
BKE_report(op->reports, RPT_INFO, "Object scale is not 1.0. Unwrap will operate on a non-scaled version of the mesh.");
1228
if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f))
1229
BKE_report(op->reports, RPT_INFO,
1230
"Object has non-uniform scale, unwrap will operate on a non-scaled version of the mesh");
1179
1232
/* remember last method for live unwrap */
1180
if(RNA_struct_property_is_set(op->ptr, "method"))
1233
if (RNA_struct_property_is_set(op->ptr, "method"))
1181
1234
scene->toolsettings->unwrapper = method;
1183
scene->toolsettings->uv_subsurf_level = subsurf_level;
1236
RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper);
1238
/* remember packing marging */
1239
if (RNA_struct_property_is_set(op->ptr, "margin"))
1240
scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
1242
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
1185
1244
if (fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES;
1186
1245
else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
1191
1250
if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
1192
1251
else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
1253
/* double up the check here but better keep ED_unwrap_lscm interface simple and not
1254
* pass operator for warning append */
1255
modifier_unwrap_state(obedit, scene, &use_subsurf_final);
1256
if (use_subsurf != use_subsurf_final)
1257
BKE_report(op->reports, RPT_INFO, "Subsurf modifier needs to be first to work with unwrap");
1194
1259
/* execute unwrap */
1195
1260
ED_unwrap_lscm(scene, obedit, TRUE);
1205
1270
static EnumPropertyItem method_items[] = {
1206
1271
{0, "ANGLE_BASED", 0, "Angle Based", ""},
1207
1272
{1, "CONFORMAL", 0, "Conformal", ""},
1208
{0, NULL, 0, NULL, NULL}};
1273
{0, NULL, 0, NULL, NULL}
1210
1276
/* identifiers */
1211
1277
ot->name = "Unwrap";
1224
1290
"Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
1225
1291
RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
1226
1292
"Map UVs taking image aspect ratio into account");
1227
RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data",
1293
RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier",
1228
1294
"Map UVs taking vertex position after subsurf into account");
1229
RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "SubSurf Target",
1230
"Number of times to subdivide before calculating UVs", 1, 6);
1295
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
1233
1298
/**************** Project From View operator **************/
1247
1312
float rotmat[4][4];
1314
int cd_loop_uv_offset;
1249
1316
/* add uvs if they don't exist yet */
1250
1317
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1251
1318
return OPERATOR_CANCELLED;
1321
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1254
1323
/* establish the camera object, so we can default to view mapping if anything is wrong with it */
1255
1324
if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
1256
1325
camera = v3d->camera->data;
1266
1335
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1267
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1268
project_from_view_ortho(luv->uv, l->v->co, rotmat);
1336
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1337
BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat);
1272
1341
else if (camera) {
1273
struct UvCameraInfo *uci = project_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
1342
struct ProjCameraInfo *uci = BLI_uvproject_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
1276
1345
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1280
1349
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1281
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1282
project_from_camera(luv->uv, l->v->co, uci);
1350
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1351
BLI_uvproject_from_camera(luv->uv, l->v->co, uci);
1296
1365
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1297
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1298
project_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
1366
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1367
BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
1303
uv_map_clip_correct(em, op);
1372
uv_map_clip_correct(scene, obedit, em, op);
1305
1374
DAG_id_tag_update(obedit->data, 0);
1306
1375
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1394
BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__);
1466
float **uvs = BLI_array_alloca(uvs, efa->len);
1399
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1400
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1470
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1472
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
1473
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1401
1474
uvs[i] = luv->uv;
1430
1500
float center[3], rotmat[4][4];
1502
int cd_loop_uv_offset;
1432
1504
/* add uvs if they don't exist yet */
1433
1505
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1434
1506
return OPERATOR_CANCELLED;
1509
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1437
1511
uv_map_transform(C, op, center, rotmat);
1439
1513
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1443
1517
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1444
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1518
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1446
1520
uv_sphere_project(luv->uv, l->v->co, center, rotmat);
1450
1524
uv_map_mirror(em, efa, tf);
1453
uv_map_clip_correct(em, op);
1527
uv_map_clip_correct(scene, obedit, em, op);
1455
1529
DAG_id_tag_update(obedit->data, 0);
1456
1530
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1503
1579
float center[3], rotmat[4][4];
1581
int cd_loop_uv_offset;
1505
1583
/* add uvs if they don't exist yet */
1506
1584
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1507
1585
return OPERATOR_CANCELLED;
1588
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1510
1590
uv_map_transform(C, op, center, rotmat);
1512
1592
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1513
tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1514
1593
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1517
1596
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1518
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1597
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1520
1599
uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
1602
tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1523
1603
uv_map_mirror(em, efa, tf);
1526
uv_map_clip_correct(em, op);
1606
uv_map_clip_correct(scene, obedit, em, op);
1528
1608
DAG_id_tag_update(obedit->data, 0);
1529
1609
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1562
1644
float cube_size, *loc, dx, dy;
1647
int cd_loop_uv_offset;
1565
1649
/* add uvs if they don't exist yet */
1566
1650
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1567
1651
return OPERATOR_CANCELLED;
1654
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1570
1656
loc = obedit->obmat[3];
1571
1657
cube_size = RNA_float_get(op->ptr, "cube_size");
1586
1672
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1587
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1673
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1589
1675
luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]);
1590
1676
luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]);
1604
uv_map_clip_correct(em, op);
1690
uv_map_clip_correct(scene, obedit, em, op);
1606
1692
DAG_id_tag_update(obedit->data, 0);
1607
1693
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);