Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/uvedit/uvedit_smart_stitch.c
| Show First 20 Lines • Show All 316 Lines • ▼ Show 20 Lines | static bool stitch_check_uvs_stitchable(UvElement *element, | ||||
| if (element_iter == element) { | if (element_iter == element) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| limit = ssc->limit_dist; | limit = ssc->limit_dist; | ||||
| if (ssc->use_limit) { | if (ssc->use_limit) { | ||||
| MLoopUV *luv, *luv_iter; | |||||
| BMLoop *l; | BMLoop *l; | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| l = element_iter->l; | l = element_iter->l; | ||||
| luv_iter = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv_iter = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit && | if (fabsf(luv[0] - luv_iter[0]) < limit && fabsf(luv[1] - luv_iter[1]) < limit) { | ||||
| fabsf(luv->uv[1] - luv_iter->uv[1]) < limit) { | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| static bool stitch_check_edges_stitchable(UvEdge *edge, | static bool stitch_check_edges_stitchable(UvEdge *edge, | ||||
| UvEdge *edge_iter, | UvEdge *edge_iter, | ||||
| StitchStateContainer *ssc, | StitchStateContainer *ssc, | ||||
| StitchState *state) | StitchState *state) | ||||
| { | { | ||||
| BMesh *bm = state->em->bm; | BMesh *bm = state->em->bm; | ||||
| float limit; | float limit; | ||||
| if (edge_iter == edge) { | if (edge_iter == edge) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| limit = ssc->limit_dist; | limit = ssc->limit_dist; | ||||
| if (ssc->use_limit) { | if (ssc->use_limit) { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv_orig1, *luv_iter1; | |||||
| MLoopUV *luv_orig2, *luv_iter2; | |||||
| l = state->uvs[edge->uv1]->l; | l = state->uvs[edge->uv1]->l; | ||||
| luv_orig1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv_orig1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| l = state->uvs[edge_iter->uv1]->l; | l = state->uvs[edge_iter->uv1]->l; | ||||
| luv_iter1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv_iter1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| l = state->uvs[edge->uv2]->l; | l = state->uvs[edge->uv2]->l; | ||||
| luv_orig2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv_orig2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| l = state->uvs[edge_iter->uv2]->l; | l = state->uvs[edge_iter->uv2]->l; | ||||
| luv_iter2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv_iter2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit && | if (fabsf(luv_orig1[0] - luv_iter1[0]) < limit && fabsf(luv_orig1[1] - luv_iter1[1]) < limit && | ||||
| fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit && | fabsf(luv_orig2[0] - luv_iter2[0]) < limit && fabsf(luv_orig2[1] - luv_iter2[1]) < limit) { | ||||
| fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit && | |||||
| fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit) { | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| static bool stitch_check_uvs_state_stitchable(UvElement *element, | static bool stitch_check_uvs_state_stitchable(UvElement *element, | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | if (island_stitch_data[i].addedForPreview) { | ||||
| } | } | ||||
| angle_to_mat2(rotation_mat, rotation); | angle_to_mat2(rotation_mat, rotation); | ||||
| numOfIslandUVs = state->element_map->island_total_uvs[i]; | numOfIslandUVs = state->element_map->island_total_uvs[i]; | ||||
| element = &state->element_map->storage[state->element_map->island_indices[i]]; | element = &state->element_map->storage[state->element_map->island_indices[i]]; | ||||
| for (j = 0; j < numOfIslandUVs; j++, element++) { | for (j = 0; j < numOfIslandUVs; j++, element++) { | ||||
| /* stitchable uvs have already been processed, don't process */ | /* stitchable uvs have already been processed, don't process */ | ||||
| if (!(element->flag & STITCH_PROCESSED)) { | if (!(element->flag & STITCH_PROCESSED)) { | ||||
| MLoopUV *luv; | |||||
| BMLoop *l; | BMLoop *l; | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| if (final) { | if (final) { | ||||
| stitch_uv_rotate( | stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, luv, state->aspect); | ||||
| rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect); | |||||
| add_v2_v2(luv->uv, island_stitch_data[i].translation); | add_v2_v2(luv, island_stitch_data[i].translation); | ||||
| } | } | ||||
| else { | else { | ||||
| int face_preview_pos = | int face_preview_pos = | ||||
| preview_position[BM_elem_index_get(element->l->f)].data_position; | preview_position[BM_elem_index_get(element->l->f)].data_position; | ||||
| stitch_uv_rotate(rotation_mat, | stitch_uv_rotate(rotation_mat, | ||||
| Show All 21 Lines | static void stitch_island_calculate_edge_rotation(UvEdge *edge, | ||||
| IslandStitchData *island_stitch_data) | IslandStitchData *island_stitch_data) | ||||
| { | { | ||||
| BMesh *bm = state->em->bm; | BMesh *bm = state->em->bm; | ||||
| UvElement *element1, *element2; | UvElement *element1, *element2; | ||||
| float uv1[2], uv2[2]; | float uv1[2], uv2[2]; | ||||
| float edgecos, edgesin; | float edgecos, edgesin; | ||||
| int index1, index2; | int index1, index2; | ||||
| float rotation; | float rotation; | ||||
| MLoopUV *luv1, *luv2; | |||||
| element1 = state->uvs[edge->uv1]; | element1 = state->uvs[edge->uv1]; | ||||
| element2 = state->uvs[edge->uv2]; | element2 = state->uvs[edge->uv2]; | ||||
| luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_MLOOPUV); | float *luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_PROP_FLOAT2); | ||||
| luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_MLOOPUV); | float *luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_PROP_FLOAT2); | ||||
| if (ssc->mode == STITCH_VERT) { | if (ssc->mode == STITCH_VERT) { | ||||
| index1 = uvfinal_map[element1 - state->element_map->storage]; | index1 = uvfinal_map[element1 - state->element_map->storage]; | ||||
| index2 = uvfinal_map[element2 - state->element_map->storage]; | index2 = uvfinal_map[element2 - state->element_map->storage]; | ||||
| } | } | ||||
| else { | else { | ||||
| index1 = edge->uv1; | index1 = edge->uv1; | ||||
| index2 = edge->uv2; | index2 = edge->uv2; | ||||
| } | } | ||||
| /* the idea here is to take the directions of the edges and find the rotation between | /* the idea here is to take the directions of the edges and find the rotation between | ||||
| * final and initial direction. This, using inner and outer vector products, | * final and initial direction. This, using inner and outer vector products, | ||||
| * gives the angle. Directions are differences so... */ | * gives the angle. Directions are differences so... */ | ||||
| uv1[0] = luv2->uv[0] - luv1->uv[0]; | uv1[0] = luv2[0] - luv1[0]; | ||||
| uv1[1] = luv2->uv[1] - luv1->uv[1]; | uv1[1] = luv2[1] - luv1[1]; | ||||
| uv1[1] /= state->aspect; | uv1[1] /= state->aspect; | ||||
| uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0]; | uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0]; | ||||
| uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1]; | uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1]; | ||||
| uv2[1] /= state->aspect; | uv2[1] /= state->aspect; | ||||
| ▲ Show 20 Lines • Show All 353 Lines • ▼ Show 20 Lines | static void stitch_propagate_uv_final_position(Scene *scene, | ||||
| UVVertAverage *final_position, | UVVertAverage *final_position, | ||||
| StitchStateContainer *ssc, | StitchStateContainer *ssc, | ||||
| StitchState *state, | StitchState *state, | ||||
| const bool final) | const bool final) | ||||
| { | { | ||||
| BMesh *bm = state->em->bm; | BMesh *bm = state->em->bm; | ||||
| StitchPreviewer *preview = state->stitch_preview; | StitchPreviewer *preview = state->stitch_preview; | ||||
| const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); | ||||
| if (element->flag & STITCH_STITCHABLE) { | if (element->flag & STITCH_STITCHABLE) { | ||||
| UvElement *element_iter = element; | UvElement *element_iter = element; | ||||
| /* propagate to coincident uvs */ | /* propagate to coincident uvs */ | ||||
| do { | do { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv; | |||||
| l = element_iter->l; | l = element_iter->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | float *luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| element_iter->flag |= STITCH_PROCESSED; | element_iter->flag |= STITCH_PROCESSED; | ||||
| /* either flush to preview or to the MTFace, if final */ | /* either flush to preview or to the MTFace, if final */ | ||||
| if (final) { | if (final) { | ||||
| copy_v2_v2(luv->uv, final_position[index].uv); | copy_v2_v2(luv, final_position[index].uv); | ||||
| uvedit_uv_select_enable(scene, state->em->bm, l, false, cd_loop_uv_offset); | uvedit_uv_select_enable(scene, state->em->bm, l, false, offsets); | ||||
| } | } | ||||
| else { | else { | ||||
| int face_preview_pos = | int face_preview_pos = | ||||
| preview_position[BM_elem_index_get(element_iter->l->f)].data_position; | preview_position[BM_elem_index_get(element_iter->l->f)].data_position; | ||||
| if (face_preview_pos != STITCH_NO_PREVIEW) { | if (face_preview_pos != STITCH_NO_PREVIEW) { | ||||
| copy_v2_v2(preview->preview_polys + face_preview_pos + | copy_v2_v2(preview->preview_polys + face_preview_pos + | ||||
| 2 * element_iter->loop_of_poly_index, | 2 * element_iter->loop_of_poly_index, | ||||
| final_position[index].uv); | final_position[index].uv); | ||||
| ▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | static int stitch_process_data(StitchStateContainer *ssc, | ||||
| } | } | ||||
| /********************************************************************* | /********************************************************************* | ||||
| * Setup the stitchable & unstitchable preview buffers and fill * | * Setup the stitchable & unstitchable preview buffers and fill * | ||||
| * them with the appropriate data * | * them with the appropriate data * | ||||
| *********************************************************************/ | *********************************************************************/ | ||||
| if (!final) { | if (!final) { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv; | float *luv; | ||||
| int stitchBufferIndex = 0, unstitchBufferIndex = 0; | int stitchBufferIndex = 0, unstitchBufferIndex = 0; | ||||
| int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4; | int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4; | ||||
| /* initialize the preview buffers */ | /* initialize the preview buffers */ | ||||
| preview->preview_stitchable = (float *)MEM_mallocN( | preview->preview_stitchable = (float *)MEM_mallocN( | ||||
| preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stitchable_data"); | preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stitchable_data"); | ||||
| preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * | preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * | ||||
| sizeof(float) * preview_size, | sizeof(float) * preview_size, | ||||
| "stitch_preview_unstitchable_data"); | "stitch_preview_unstitchable_data"); | ||||
| /* will cause cancel and freeing of all data structures so OK */ | /* will cause cancel and freeing of all data structures so OK */ | ||||
| if (!preview->preview_stitchable || !preview->preview_unstitchable) { | if (!preview->preview_stitchable || !preview->preview_unstitchable) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* fill the appropriate preview buffers */ | /* fill the appropriate preview buffers */ | ||||
| if (ssc->mode == STITCH_VERT) { | if (ssc->mode == STITCH_VERT) { | ||||
| for (i = 0; i < state->total_separate_uvs; i++) { | for (i = 0; i < state->total_separate_uvs; i++) { | ||||
| UvElement *element = (UvElement *)state->uvs[i]; | UvElement *element = (UvElement *)state->uvs[i]; | ||||
| if (element->flag & STITCH_STITCHABLE) { | if (element->flag & STITCH_STITCHABLE) { | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv); | copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv); | ||||
| stitchBufferIndex++; | stitchBufferIndex++; | ||||
| } | } | ||||
| else if (element->flag & STITCH_SELECTED) { | else if (element->flag & STITCH_SELECTED) { | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv); | copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv); | ||||
| unstitchBufferIndex++; | unstitchBufferIndex++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| for (i = 0; i < state->total_separate_edges; i++) { | for (i = 0; i < state->total_separate_edges; i++) { | ||||
| UvEdge *edge = state->edges + i; | UvEdge *edge = state->edges + i; | ||||
| UvElement *element1 = state->uvs[edge->uv1]; | UvElement *element1 = state->uvs[edge->uv1]; | ||||
| UvElement *element2 = state->uvs[edge->uv2]; | UvElement *element2 = state->uvs[edge->uv2]; | ||||
| if (edge->flag & STITCH_STITCHABLE) { | if (edge->flag & STITCH_STITCHABLE) { | ||||
| l = element1->l; | l = element1->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv); | copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv); | ||||
| l = element2->l; | l = element2->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv); | copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv); | ||||
| stitchBufferIndex++; | stitchBufferIndex++; | ||||
| BLI_assert(stitchBufferIndex <= preview->num_stitchable); | BLI_assert(stitchBufferIndex <= preview->num_stitchable); | ||||
| } | } | ||||
| else if (edge->flag & STITCH_SELECTED) { | else if (edge->flag & STITCH_SELECTED) { | ||||
| l = element1->l; | l = element1->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv); | copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv); | ||||
| l = element2->l; | l = element2->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv); | copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv); | ||||
| unstitchBufferIndex++; | unstitchBufferIndex++; | ||||
| BLI_assert(unstitchBufferIndex <= preview->num_unstitchable); | BLI_assert(unstitchBufferIndex <= preview->num_unstitchable); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 21 Lines | static int stitch_process_data(StitchStateContainer *ssc, | ||||
| /********************************************************************* | /********************************************************************* | ||||
| * Setup the remaining preview buffers and fill them with the * | * Setup the remaining preview buffers and fill them with the * | ||||
| * appropriate data * | * appropriate data * | ||||
| *********************************************************************/ | *********************************************************************/ | ||||
| if (!final) { | if (!final) { | ||||
| BMIter liter; | BMIter liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv; | float *luv; | ||||
| uint buffer_index = 0; | uint buffer_index = 0; | ||||
| /* initialize the preview buffers */ | /* initialize the preview buffers */ | ||||
| preview->preview_polys = MEM_mallocN(sizeof(float[2]) * preview->preview_uvs, | preview->preview_polys = MEM_mallocN(sizeof(float[2]) * preview->preview_uvs, | ||||
| "tri_uv_stitch_prev"); | "tri_uv_stitch_prev"); | ||||
| preview->uvs_per_polygon = MEM_mallocN(sizeof(*preview->uvs_per_polygon) * preview->num_polys, | preview->uvs_per_polygon = MEM_mallocN(sizeof(*preview->uvs_per_polygon) * preview->num_polys, | ||||
| "tri_uv_stitch_prev"); | "tri_uv_stitch_prev"); | ||||
| preview->static_tris = MEM_mallocN( | preview->static_tris = MEM_mallocN( | ||||
| (sizeof(float[6]) * state->tris_per_island[ssc->static_island]), | (sizeof(float[6]) * state->tris_per_island[ssc->static_island]), | ||||
| "static_island_preview_tris"); | "static_island_preview_tris"); | ||||
| preview->num_static_tris = state->tris_per_island[ssc->static_island]; | preview->num_static_tris = state->tris_per_island[ssc->static_island]; | ||||
| /* will cause cancel and freeing of all data structures so OK */ | /* will cause cancel and freeing of all data structures so OK */ | ||||
| if (!preview->preview_polys) { | if (!preview->preview_polys) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* copy data from MLoopUVs to the preview display buffers */ | /* copy data from UVs to the preview display buffers */ | ||||
| BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | ||||
| /* just to test if face was added for processing. | /* just to test if face was added for processing. | ||||
| * uvs of unselected vertices will return NULL */ | * uvs of unselected vertices will return NULL */ | ||||
| UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa)); | UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa)); | ||||
| if (element) { | if (element) { | ||||
| int numoftris = efa->len - 2; | int numoftris = efa->len - 2; | ||||
| int index = BM_elem_index_get(efa); | int index = BM_elem_index_get(efa); | ||||
| int face_preview_pos = preview_position[index].data_position; | int face_preview_pos = preview_position[index].data_position; | ||||
| if (face_preview_pos != STITCH_NO_PREVIEW) { | if (face_preview_pos != STITCH_NO_PREVIEW) { | ||||
| preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->len; | preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->len; | ||||
| BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv->uv); | copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv); | ||||
| } | } | ||||
| } | } | ||||
| /* if this is the static_island on the active object */ | /* if this is the static_island on the active object */ | ||||
| if (element->island == ssc->static_island) { | if (element->island == ssc->static_island) { | ||||
| BMLoop *fl = BM_FACE_FIRST_LOOP(efa); | BMLoop *fl = BM_FACE_FIRST_LOOP(efa); | ||||
| MLoopUV *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_MLOOPUV); | float *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_PROP_FLOAT2); | ||||
| BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | ||||
| if (i < numoftris) { | if (i < numoftris) { | ||||
| /* using next since the first uv is already accounted for */ | /* using next since the first uv is already accounted for */ | ||||
| BMLoop *lnext = l->next; | BMLoop *lnext = l->next; | ||||
| MLoopUV *luvnext = CustomData_bmesh_get( | float *luvnext = CustomData_bmesh_get( | ||||
| &bm->ldata, lnext->next->head.data, CD_MLOOPUV); | &bm->ldata, lnext->next->head.data, CD_PROP_FLOAT2); | ||||
| luv = CustomData_bmesh_get(&bm->ldata, lnext->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, lnext->head.data, CD_PROP_FLOAT2); | ||||
| memcpy(preview->static_tris + buffer_index, fuv->uv, sizeof(float[2])); | memcpy(preview->static_tris + buffer_index, fuv, sizeof(float[2])); | ||||
| memcpy(preview->static_tris + buffer_index + 2, luv->uv, sizeof(float[2])); | memcpy(preview->static_tris + buffer_index + 2, luv, sizeof(float[2])); | ||||
| memcpy(preview->static_tris + buffer_index + 4, luvnext->uv, sizeof(float[2])); | memcpy(preview->static_tris + buffer_index + 4, luvnext, sizeof(float[2])); | ||||
| buffer_index += 6; | buffer_index += 6; | ||||
| } | } | ||||
| else { | else { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 17 Lines | static int stitch_process_data(StitchStateContainer *ssc, | ||||
| /* first pass, calculate final position for stitchable uvs of the static island */ | /* first pass, calculate final position for stitchable uvs of the static island */ | ||||
| for (i = 0; i < state->selection_size; i++) { | for (i = 0; i < state->selection_size; i++) { | ||||
| if (ssc->mode == STITCH_VERT) { | if (ssc->mode == STITCH_VERT) { | ||||
| UvElement *element = state->selection_stack[i]; | UvElement *element = state->selection_stack[i]; | ||||
| if (element->flag & STITCH_STITCHABLE) { | if (element->flag & STITCH_STITCHABLE) { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv; | float *luv; | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| uvfinal_map[element - state->element_map->storage] = i; | uvfinal_map[element - state->element_map->storage] = i; | ||||
| copy_v2_v2(final_position[i].uv, luv->uv); | copy_v2_v2(final_position[i].uv, luv); | ||||
| final_position[i].count = 1; | final_position[i].count = 1; | ||||
| if (ssc->snap_islands && element->island == ssc->static_island && !stitch_midpoints) { | if (ssc->snap_islands && element->island == ssc->static_island && !stitch_midpoints) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| UvElement *element_iter = state->element_map->vertex[BM_elem_index_get(l->v)]; | UvElement *element_iter = state->element_map->vertex[BM_elem_index_get(l->v)]; | ||||
| for (; element_iter; element_iter = element_iter->next) { | for (; element_iter; element_iter = element_iter->next) { | ||||
| if (element_iter->separate) { | if (element_iter->separate) { | ||||
| if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) { | if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) { | ||||
| l = element_iter->l; | l = element_iter->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| if (stitch_midpoints) { | if (stitch_midpoints) { | ||||
| add_v2_v2(final_position[i].uv, luv->uv); | add_v2_v2(final_position[i].uv, luv); | ||||
| final_position[i].count++; | final_position[i].count++; | ||||
| } | } | ||||
| else if (element_iter->island == ssc->static_island) { | else if (element_iter->island == ssc->static_island) { | ||||
| /* if multiple uvs on the static island exist, | /* if multiple uvs on the static island exist, | ||||
| * last checked remains. to disambiguate we need to limit or use | * last checked remains. to disambiguate we need to limit or use | ||||
| * edge stitch */ | * edge stitch */ | ||||
| copy_v2_v2(final_position[i].uv, luv->uv); | copy_v2_v2(final_position[i].uv, luv); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (stitch_midpoints) { | if (stitch_midpoints) { | ||||
| final_position[i].uv[0] /= final_position[i].count; | final_position[i].uv[0] /= final_position[i].count; | ||||
| final_position[i].uv[1] /= final_position[i].count; | final_position[i].uv[1] /= final_position[i].count; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| UvEdge *edge = state->selection_stack[i]; | UvEdge *edge = state->selection_stack[i]; | ||||
| if (edge->flag & STITCH_STITCHABLE) { | if (edge->flag & STITCH_STITCHABLE) { | ||||
| MLoopUV *luv2, *luv1; | float *luv2, *luv1; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| UvEdge *edge_iter; | UvEdge *edge_iter; | ||||
| l = state->uvs[edge->uv1]->l; | l = state->uvs[edge->uv1]->l; | ||||
| luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| l = state->uvs[edge->uv2]->l; | l = state->uvs[edge->uv2]->l; | ||||
| luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| copy_v2_v2(final_position[edge->uv1].uv, luv1->uv); | copy_v2_v2(final_position[edge->uv1].uv, luv1); | ||||
| copy_v2_v2(final_position[edge->uv2].uv, luv2->uv); | copy_v2_v2(final_position[edge->uv2].uv, luv2); | ||||
| final_position[edge->uv1].count = 1; | final_position[edge->uv1].count = 1; | ||||
| final_position[edge->uv2].count = 1; | final_position[edge->uv2].count = 1; | ||||
| state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE; | state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE; | ||||
| state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE; | state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE; | ||||
| if (ssc->snap_islands && edge->element->island == ssc->static_island && | if (ssc->snap_islands && edge->element->island == ssc->static_island && | ||||
| !stitch_midpoints) { | !stitch_midpoints) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) { | for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) { | ||||
| if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) { | if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) { | ||||
| l = state->uvs[edge_iter->uv1]->l; | l = state->uvs[edge_iter->uv1]->l; | ||||
| luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| l = state->uvs[edge_iter->uv2]->l; | l = state->uvs[edge_iter->uv2]->l; | ||||
| luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| if (stitch_midpoints) { | if (stitch_midpoints) { | ||||
| add_v2_v2(final_position[edge->uv1].uv, luv1->uv); | add_v2_v2(final_position[edge->uv1].uv, luv1); | ||||
| final_position[edge->uv1].count++; | final_position[edge->uv1].count++; | ||||
| add_v2_v2(final_position[edge->uv2].uv, luv2->uv); | add_v2_v2(final_position[edge->uv2].uv, luv2); | ||||
| final_position[edge->uv2].count++; | final_position[edge->uv2].count++; | ||||
| } | } | ||||
| else if (edge_iter->element->island == ssc->static_island) { | else if (edge_iter->element->island == ssc->static_island) { | ||||
| copy_v2_v2(final_position[edge->uv1].uv, luv1->uv); | copy_v2_v2(final_position[edge->uv1].uv, luv1); | ||||
| copy_v2_v2(final_position[edge->uv2].uv, luv2->uv); | copy_v2_v2(final_position[edge->uv2].uv, luv2); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* take mean position here. | /* take mean position here. | ||||
| * For edge case, this can't be done inside the loop for shared uvverts */ | * For edge case, this can't be done inside the loop for shared uvverts */ | ||||
| if (ssc->mode == STITCH_EDGE && stitch_midpoints) { | if (ssc->mode == STITCH_EDGE && stitch_midpoints) { | ||||
| for (i = 0; i < state->total_separate_uvs; i++) { | for (i = 0; i < state->total_separate_uvs; i++) { | ||||
| final_position[i].uv[0] /= final_position[i].count; | final_position[i].uv[0] /= final_position[i].count; | ||||
| final_position[i].uv[1] /= final_position[i].count; | final_position[i].uv[1] /= final_position[i].count; | ||||
| } | } | ||||
| } | } | ||||
| /* second pass, calculate island rotation and translation before modifying any uvs */ | /* second pass, calculate island rotation and translation before modifying any uvs */ | ||||
| if (ssc->snap_islands) { | if (ssc->snap_islands) { | ||||
| if (ssc->mode == STITCH_VERT) { | if (ssc->mode == STITCH_VERT) { | ||||
| for (i = 0; i < state->selection_size; i++) { | for (i = 0; i < state->selection_size; i++) { | ||||
| UvElement *element = state->selection_stack[i]; | UvElement *element = state->selection_stack[i]; | ||||
| if (element->flag & STITCH_STITCHABLE) { | if (element->flag & STITCH_STITCHABLE) { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv; | float *luv; | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| /* accumulate each islands' translation from stitchable elements. | /* accumulate each islands' translation from stitchable elements. | ||||
| * It is important to do here because in final pass MTFaces | * It is important to do here because in final pass MTFaces | ||||
| * get modified and result is zero. */ | * get modified and result is zero. */ | ||||
| island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - | island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv[0]; | ||||
| luv->uv[0]; | island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv[1]; | ||||
| island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - | island_stitch_data[element->island].medianPoint[0] += luv[0]; | ||||
| luv->uv[1]; | island_stitch_data[element->island].medianPoint[1] += luv[1]; | ||||
| island_stitch_data[element->island].medianPoint[0] += luv->uv[0]; | |||||
| island_stitch_data[element->island].medianPoint[1] += luv->uv[1]; | |||||
| island_stitch_data[element->island].numOfElements++; | island_stitch_data[element->island].numOfElements++; | ||||
| } | } | ||||
| } | } | ||||
| /* only calculate rotation when an edge has been fully selected */ | /* only calculate rotation when an edge has been fully selected */ | ||||
| for (i = 0; i < state->total_separate_edges; i++) { | for (i = 0; i < state->total_separate_edges; i++) { | ||||
| UvEdge *edge = state->edges + i; | UvEdge *edge = state->edges + i; | ||||
| if ((edge->flag & STITCH_BOUNDARY) && (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && | if ((edge->flag & STITCH_BOUNDARY) && (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && | ||||
| Show All 25 Lines | if (ssc->mode == STITCH_VERT) { | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| for (i = 0; i < state->total_separate_uvs; i++) { | for (i = 0; i < state->total_separate_uvs; i++) { | ||||
| UvElement *element = state->uvs[i]; | UvElement *element = state->uvs[i]; | ||||
| if (element->flag & STITCH_STITCHABLE) { | if (element->flag & STITCH_STITCHABLE) { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| MLoopUV *luv; | float *luv; | ||||
| l = element->l; | l = element->l; | ||||
| luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); | luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2); | ||||
| /* accumulate each islands' translation from stitchable elements. | /* accumulate each islands' translation from stitchable elements. | ||||
| * it is important to do here because in final pass MTFaces | * it is important to do here because in final pass MTFaces | ||||
| * get modified and result is zero. */ | * get modified and result is zero. */ | ||||
| island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - | island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv[0]; | ||||
| luv->uv[0]; | island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv[1]; | ||||
| island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - | island_stitch_data[element->island].medianPoint[0] += luv[0]; | ||||
| luv->uv[1]; | island_stitch_data[element->island].medianPoint[1] += luv[1]; | ||||
| island_stitch_data[element->island].medianPoint[0] += luv->uv[0]; | |||||
| island_stitch_data[element->island].medianPoint[1] += luv->uv[1]; | |||||
| island_stitch_data[element->island].numOfElements++; | island_stitch_data[element->island].numOfElements++; | ||||
| } | } | ||||
| } | } | ||||
| for (i = 0; i < state->selection_size; i++) { | for (i = 0; i < state->selection_size; i++) { | ||||
| UvEdge *edge = state->selection_stack[i]; | UvEdge *edge = state->selection_stack[i]; | ||||
| if (edge->flag & STITCH_STITCHABLE) { | if (edge->flag & STITCH_STITCHABLE) { | ||||
| ▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Lines | static void stitch_switch_selection_mode_all(StitchStateContainer *ssc) | ||||
| else { | else { | ||||
| ssc->mode = STITCH_VERT; | ssc->mode = STITCH_VERT; | ||||
| } | } | ||||
| } | } | ||||
| static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect) | static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect) | ||||
| { | { | ||||
| BMLoop *l1 = edge->element->l; | BMLoop *l1 = edge->element->l; | ||||
| MLoopUV *luv1, *luv2; | |||||
| float tangent[2]; | float tangent[2]; | ||||
| luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV); | float *luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_PROP_FLOAT2); | ||||
| luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV); | float *luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_PROP_FLOAT2); | ||||
| sub_v2_v2v2(tangent, luv2->uv, luv1->uv); | sub_v2_v2v2(tangent, luv2, luv1); | ||||
| tangent[1] /= aspect; | tangent[1] /= aspect; | ||||
| normal[0] = tangent[1]; | normal[0] = tangent[1]; | ||||
| normal[1] = -tangent[0]; | normal[1] = -tangent[0]; | ||||
| normalize_v2(normal); | normalize_v2(normal); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | static StitchState *stitch_init(bContext *C, | ||||
| GHashIterator gh_iter; | GHashIterator gh_iter; | ||||
| UvEdge *all_edges; | UvEdge *all_edges; | ||||
| StitchState *state; | StitchState *state; | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ToolSettings *ts = scene->toolsettings; | ToolSettings *ts = scene->toolsettings; | ||||
| float aspx, aspy; | float aspx, aspy; | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); | ||||
| state = MEM_callocN(sizeof(StitchState), "stitch state obj"); | state = MEM_callocN(sizeof(StitchState), "stitch state obj"); | ||||
| /* initialize state */ | /* initialize state */ | ||||
| state->obedit = obedit; | state->obedit = obedit; | ||||
| state->em = em; | state->em = em; | ||||
| /* Workaround for sync-select & face-select mode which implies all selected faces are detached, | /* Workaround for sync-select & face-select mode which implies all selected faces are detached, | ||||
| ▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | static StitchState *stitch_init(bContext *C, | ||||
| else { | else { | ||||
| if (ssc->mode == STITCH_VERT) { | if (ssc->mode == STITCH_VERT) { | ||||
| state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * | state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * | ||||
| state->total_separate_uvs, | state->total_separate_uvs, | ||||
| "uv_stitch_selection_stack"); | "uv_stitch_selection_stack"); | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | ||||
| if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { | if (uvedit_uv_select_test(scene, l, offsets)) { | ||||
| UvElement *element = BM_uv_element_get(state->element_map, efa, l); | UvElement *element = BM_uv_element_get(state->element_map, efa, l); | ||||
| if (element) { | if (element) { | ||||
| stitch_select_uv(element, state, 1); | stitch_select_uv(element, state, 1); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * | state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * | ||||
| state->total_separate_edges, | state->total_separate_edges, | ||||
| "uv_stitch_selection_stack"); | "uv_stitch_selection_stack"); | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!(ts->uv_flag & UV_SYNC_SELECTION) && | if (!(ts->uv_flag & UV_SYNC_SELECTION) && | ||||
| (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { | (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (uvedit_edge_select_test(scene, l, cd_loop_uv_offset)) { | if (uvedit_edge_select_test(scene, l, offsets)) { | ||||
| UvEdge *edge = uv_edge_get(l, state); | UvEdge *edge = uv_edge_get(l, state); | ||||
| if (edge) { | if (edge) { | ||||
| stitch_select_edge(edge, state, true); | stitch_select_edge(edge, state, true); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 666 Lines • Show Last 20 Lines | |||||