From 759b50b20b96556f182e6d14ce23a89e2a673921 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Nov 2017 22:30:28 +1100 Subject: Fix UV Projection Center Calculation UV project mixed up global/local space, 3D cursor offset didn't take object scale into account. Minor improvements: - Match Cube Project 'center' behavior w/ sphere & cylinder. - Add active-element center. - Wrap UV's in Cube Project based on center instead of first vertex. --- source/blender/editors/include/ED_uvedit.h | 3 +- .../editors/sculpt_paint/paint_image_proj.c | 2 +- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 106 ++++++++++++++------- 3 files changed, 73 insertions(+), 38 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 535683823bf..354a9655a48 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -101,7 +101,8 @@ void ED_uvedit_live_unwrap_end(short cancel); void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit); void ED_uvedit_pack_islands(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate); -void ED_uvedit_unwrap_cube_project(struct Object *ob, struct BMesh *bm, float cube_size, bool use_select); +void ED_uvedit_unwrap_cube_project( + struct BMesh *bm, float cube_size, bool use_select, const float center[3]); /* single call up unwrap using scene settings, used for edge tag unwrapping */ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d14b75149c9..ae6dbbf440c 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5904,7 +5904,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) })); /* select all uv loops first - pack parameters needs this to make sure charts are registered */ ED_uvedit_select_all(bm); - ED_uvedit_unwrap_cube_project(ob, bm, 1.0, false); + ED_uvedit_unwrap_cube_project(bm, 1.0, false, NULL); /* set the margin really quickly before the packing operation*/ scene->toolsettings->uvcalc_margin = 0.001f; ED_uvedit_pack_islands(scene, ob, bm, false, false, true); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index b639a493b02..ce763243602 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -868,12 +868,10 @@ void ED_uvedit_live_unwrap(Scene *scene, Object *obedit) #define POLAR_ZX 0 #define POLAR_ZY 1 -static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, - Object *ob, BMEditMesh *em) +static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Object *ob, BMEditMesh *em) { - const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS; - /* only operates on the edit object - this is all that's needed now */ + const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS; switch (around) { case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */ @@ -884,7 +882,7 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, float min[3], max[3]; INIT_MINMAX(min, max); - + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -895,15 +893,41 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, mid_v3_v3v3(result, min, max); break; } + case V3D_AROUND_CENTER_MEAN: + { + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + int result_accum = 0; + + zero_v3(result); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + add_v3_v3(result, l->v->co); + result_accum += 1; + } + } + } + mul_v3_fl(result, 1.0f / (float)result_accum); + break; + } case V3D_AROUND_CURSOR: /* cursor center */ { - const float *curs = ED_view3d_cursor3d_get(scene, v3d); - /* shift to objects world */ - sub_v3_v3v3(result, curs, ob->obmat[3]); + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_m4v3(result, ob->imat, ED_view3d_cursor3d_get(scene, v3d)); break; } + case V3D_AROUND_ACTIVE: + { + BMEditSelection ese; + if (BM_select_history_active_get(em->bm, &ese)) { + BM_editselection_center(&ese, result); + break; + } + ATTR_FALLTHROUGH; + } case V3D_AROUND_LOCAL_ORIGINS: /* object center */ - case V3D_AROUND_CENTER_MEAN: /* multiple objects centers, only one object here*/ default: zero_v3(result); break; @@ -958,13 +982,10 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec mul_m4_series(result, rotup, rotside, viewmatrix, rotobj); } -static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4]) +static void uv_map_transform(bContext *C, wmOperator *op, float rotmat[4][4]) { /* context checks are messy here, making it work in both 3d view and uv editor */ - Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); /* common operator properties */ int align = RNA_enum_get(op->ptr, "align"); @@ -972,8 +993,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") : 1.0f; float upangledeg, sideangledeg; - uv_map_transform_center(scene, v3d, center, obedit, em); - if (direction == VIEW_ON_EQUATOR) { upangledeg = 90.0f; sideangledeg = 0.0f; @@ -1476,6 +1495,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; BMLoop *l; @@ -1493,7 +1513,8 @@ static int sphere_project_exec(bContext *C, wmOperator *op) cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - uv_map_transform(C, op, center, rotmat); + uv_map_transform(C, op, rotmat); + uv_map_transform_center(scene, v3d, center, obedit, em); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) @@ -1555,6 +1576,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; BMLoop *l; @@ -1572,12 +1594,13 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - uv_map_transform(C, op, center, rotmat); + uv_map_transform(C, op, rotmat); + uv_map_transform_center(scene, v3d, center, obedit, em); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; - + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -1616,68 +1639,79 @@ void UV_OT_cylinder_project(wmOperatorType *ot) /******************* Cube Project operator ****************/ -void ED_uvedit_unwrap_cube_project(Object *ob, BMesh *bm, float cube_size, bool use_select) +void ED_uvedit_unwrap_cube_project(BMesh *bm, float cube_size, bool use_select, const float center[3]) { BMFace *efa; BMLoop *l; BMIter iter, liter; /* MTexPoly *tf; */ /* UNUSED */ MLoopUV *luv; - float *loc, dx, dy; + float loc[3]; int cox, coy; int cd_loop_uv_offset; cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - loc = ob->obmat[3]; + if (center) { + copy_v3_v3(loc, center); + } + else { + zero_v3(loc); + } /* choose x,y,z axis for projection depending on the largest normal * component, but clusters all together around the center of map. */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - int first = 1; - /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; axis_dominant_v3(&cox, &coy, efa->no); - dx = dy = 0; + float uv_delta[2] = {0.0f}; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->uv[0] = 0.5f + 0.5f * cube_size * (l->v->co[cox] - loc[cox]); + luv->uv[1] = 0.5f + 0.5f * cube_size * (l->v->co[coy] - loc[coy]); - luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]); - luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]); - - if (first) { - dx = floor(luv->uv[0]); - dy = floor(luv->uv[1]); - first = 0; - } + add_v2_v2(uv_delta, luv->uv); + } + mul_v2_fl(uv_delta, 1.0f / (float)efa->len); + uv_delta[0] = floor(uv_delta[0]); + uv_delta[1] = floor(uv_delta[1]); - luv->uv[0] -= dx; - luv->uv[1] -= dy; + if (uv_delta[0] != 0.0f || uv_delta[1] != 0.0f) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->uv[0] -= uv_delta[0]; + luv->uv[1] -= uv_delta[1]; + } } } - } static int cube_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); float cube_size = RNA_float_get(op->ptr, "cube_size"); + float center[3]; /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } - ED_uvedit_unwrap_cube_project(obedit, em->bm, cube_size, true); + uv_map_transform_center(scene, v3d, center, obedit, em); + + ED_uvedit_unwrap_cube_project(em->bm, cube_size, true, center); + uv_map_clip_correct(scene, obedit, em, op); DAG_id_tag_update(obedit->data, 0); -- cgit v1.2.3 From c45afcfa81e67c7b560a5ee0a3e599902e3dfee9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 17 Nov 2017 14:56:51 +0100 Subject: Depsgraph: Don't make non-dynamic hair dependent on time This way hair system used for static forest does not make playblack slow. A bit dangerous, but let's see how far we can go! --- .../intern/builder/deg_builder_relations.cc | 33 ++++++++++++++++++++-- source/blender/makesrna/intern/rna_particle.c | 9 ++++-- 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 3ec42fd956f..f03cf679833 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -175,6 +175,31 @@ static bool python_driver_depends_on_time(ChannelDriver *driver) return false; } +static bool particle_system_depends_on_time(ParticleSystem *psys) +{ + ParticleSettings *part = psys->part; + /* Non-hair particles we always consider dependent on time. */ + if (part->type != PART_HAIR) { + return true; + } + /* Dynamics always depends on time. */ + if (psys->flag & PSYS_HAIR_DYNAMICS) { + return true; + } + /* TODO(sergey): Check what else makes hair dependent on time. */ + return false; +} + +static bool object_particles_depends_oin_time(Object *object) +{ + LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) { + if (particle_system_depends_on_time(psys)) { + return true; + } + } + return false; +} + /* **** General purpose functions **** */ RNAPathKey::RNAPathKey(ID *id, const char *path) : @@ -1558,13 +1583,15 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) * * for viewport being properly rendered in final render mode. * This relation is similar to what dag_object_time_update_flags() - * was doing for mesh objects with particle system/ + * was doing for mesh objects with particle system. * * Ideally we need to get rid of this relation. */ - if (ob->particlesystem.first != NULL) { + if (object_particles_depends_oin_time(ob)) { TimeSourceKey time_key; - OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + OperationKey obdata_ubereval_key(&ob->id, + DEG_NODE_TYPE_GEOMETRY, + DEG_OPCODE_GEOMETRY_UBEREVAL); add_relation(time_key, obdata_ubereval_key, "Legacy particle time"); } break; diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 7fc0ffeb747..53fe84707d1 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -675,6 +675,7 @@ static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr) { particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE); + DAG_relations_tag_update(bmain); } static void rna_Particle_change_physics(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -757,7 +758,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), } } -static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; ParticleSystem *psys = (ParticleSystem *)ptr->data; @@ -769,10 +770,12 @@ static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *pt psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; rna_Particle_redo(bmain, scene, ptr); } - else + else { WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL); + } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DAG_relations_tag_update(bmain); } static PointerRNA rna_particle_settings_get(PointerRNA *ptr) { @@ -3292,7 +3295,7 @@ static void rna_def_particle_system(BlenderRNA *brna) prop = RNA_def_property(srna, "use_hair_dynamics", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_HAIR_DYNAMICS); RNA_def_property_ui_text(prop, "Hair Dynamics", "Enable hair dynamics using cloth simulation"); - RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics"); + RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics_update"); prop = RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clmd"); -- cgit v1.2.3