diff options
-rw-r--r-- | source/blender/blenlib/BLI_math_matrix.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 13 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_smart_stitch.c | 82 |
3 files changed, 70 insertions, 27 deletions
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index a5ab2373b89..97cd6a60862 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -88,6 +88,7 @@ void mul_serie_m4(float R[4][4], void mul_m4_v3(float M[4][4], float r[3]); void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]); +void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]); void mul_mat3_m4_v3(float M[4][4], float r[3]); void mul_m4_v4(float M[4][4], float r[4]); void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]); @@ -170,6 +171,7 @@ void mat4_to_size(float r[3], float M[4][4]); void translate_m4(float mat[4][4], float tx, float ty, float tz); void rotate_m4(float mat[4][4], const char axis, const float angle); +void rotate_m2(float mat[2][2], const float angle); void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 5c443b9b1f3..c12588463b0 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -344,6 +344,12 @@ void mul_v3_m4v3(float in[3], float mat[4][4], const float vec[3]) in[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; } +void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]) +{ + r[0] = M[0][0]*v[0] + M[1][0]*v[1]; + r[1] = M[0][1]*v[0] + M[1][1]*v[1]; +} + /* same as mul_m4_v3() but doesnt apply translation component */ void mul_mat3_m4_v3(float mat[4][4], float vec[3]) { @@ -1304,6 +1310,13 @@ void rotate_m4(float mat[4][4], const char axis, const float angle) } } +void rotate_m2(float mat[2][2], const float angle) +{ + mat[0][0] = mat[1][1] = cosf(angle); + mat[0][1] = sinf(angle); + mat[1][0] = -mat[0][1]; +} + void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight) { float srot[3][3], drot[3][3]; diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 1b43d829947..b7e12dda663 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -100,11 +100,13 @@ struct IslandStitchData; typedef struct IslandStitchData { /* rotation can be used only for edges, for vertices there is no such notion */ float rotation; + float rotation_neg; float translation[2]; /* Used for rotation, the island will rotate around this point */ float medianPoint[2]; int numOfElements; int num_rot_elements; + int num_rot_elements_neg; /* flag to remember if island has been added for preview */ char addedForPreview; /* flag an island to be considered for determining static island */ @@ -286,20 +288,15 @@ static int getNumOfIslandUvs(UvElementMap *elementMap, int island) } } -static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2], float aspect) +static void stitch_uv_rotate(float mat[2][2], float medianPoint[2], float uv[2], float aspect) { float uv_rotation_result[2]; uv[1] /= aspect; - uv[0] -= medianPoint[0]; - uv[1] -= medianPoint[1]; - - uv_rotation_result[0] = cosf(rotation) * uv[0] - sinf(rotation) * uv[1]; - uv_rotation_result[1] = sinf(rotation) * uv[0] + cosf(rotation) * uv[1]; - - uv[0] = uv_rotation_result[0] + medianPoint[0]; - uv[1] = uv_rotation_result[1] + medianPoint[1]; + sub_v2_v2(uv, medianPoint); + mul_v2_m2v2(uv_rotation_result, mat, uv); + add_v2_v2v2(uv, uv_rotation_result, medianPoint); uv[1] *= aspect; } @@ -412,17 +409,35 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition for (i = 0; i < state->element_map->totalIslands; i++) { if (island_stitch_data[i].addedForPreview) { int numOfIslandUVs = 0, j; + int totelem = island_stitch_data[i].num_rot_elements_neg + island_stitch_data[i].num_rot_elements; + float rotation; + float rotation_mat[2][2]; /* check to avoid divide by 0 */ - if (island_stitch_data[i].num_rot_elements > 0) { + if (island_stitch_data[i].num_rot_elements > 1) island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements; + + if (island_stitch_data[i].num_rot_elements_neg > 1) + island_stitch_data[i].rotation_neg /= island_stitch_data[i].num_rot_elements_neg; + + if (island_stitch_data[i].numOfElements > 1) { island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements; island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements; - island_stitch_data[i].medianPoint[1] /= state->aspect; + + island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements; + island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements; } - island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements; - island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements; + island_stitch_data[i].medianPoint[1] /= state->aspect; + if ((island_stitch_data[i].rotation + island_stitch_data[i].rotation_neg < M_PI_2) || + island_stitch_data[i].num_rot_elements == 0 || island_stitch_data[i].num_rot_elements_neg == 0) + rotation = (island_stitch_data[i].rotation*island_stitch_data[i].num_rot_elements - + island_stitch_data[i].rotation_neg*island_stitch_data[i].num_rot_elements_neg)/totelem; + else + rotation = (island_stitch_data[i].rotation*island_stitch_data[i].num_rot_elements + + (2*M_PI - island_stitch_data[i].rotation_neg)*island_stitch_data[i].num_rot_elements_neg)/totelem; + + rotate_m2(rotation_mat, rotation); numOfIslandUVs = getNumOfIslandUvs(state->element_map, i); element = &state->element_map->buf[state->element_map->islandIndices[i]]; for (j = 0; j < numOfIslandUVs; j++, element++) { @@ -436,15 +451,16 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition if (final) { - stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv, state->aspect); + stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect); add_v2_v2(luv->uv, island_stitch_data[i].translation); } else { + int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position; - stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, + stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, preview->preview_polys + face_preview_pos + 2 * element->tfindex, state->aspect); add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex, @@ -500,13 +516,15 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta edgecos = dot_v2v2(uv1, uv2); edgesin = cross_v2v2(uv1, uv2); + rotation = acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))); - rotation = (edgesin > 0.0f) ? - +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) : - -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))); - - island_stitch_data[element1->island].num_rot_elements++; - island_stitch_data[element1->island].rotation += rotation; + if (edgesin > 0.0f) { + island_stitch_data[element1->island].num_rot_elements++; + island_stitch_data[element1->island].rotation += rotation; + } else { + island_stitch_data[element1->island].num_rot_elements_neg++; + island_stitch_data[element1->island].rotation_neg += rotation; + } } @@ -515,7 +533,8 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat float edgecos = 1.0f, edgesin = 0.0f; int index; UvElement *element_iter; - float rotation = 0; + float rotation = 0, rotation_neg = 0; + int rot_elem = 0, rot_elem_neg = 0; BMLoop *l; if (element->island == state->static_island && !state->midpoints) @@ -544,16 +563,25 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat negate_v2_v2(normal, state->normals + index_tmp2 * 2); edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2); edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2); - rotation += (edgesin > 0.0f) ? - +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) : - -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))); + if (edgesin > 0.0f) { + rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))); + rot_elem++; + } + else { + rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))); + rot_elem_neg++; + } } } - if (state->midpoints) + if (state->midpoints) { rotation /= 2.0f; - island_stitch_data[element->island].num_rot_elements++; + rotation_neg /= 2.0f; + } + island_stitch_data[element->island].num_rot_elements += rot_elem; island_stitch_data[element->island].rotation += rotation; + island_stitch_data[element->island].num_rot_elements_neg += rot_elem_neg; + island_stitch_data[element->island].rotation_neg += rotation_neg; } |