Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/pbvh_uv_islands.cc
| Show All 30 Lines | |||||
| /** \name Mesh Primitives | /** \name Mesh Primitives | ||||
| * \{ */ | * \{ */ | ||||
| static int primitive_get_other_uv_vertex(const MeshData &mesh_data, | static int primitive_get_other_uv_vertex(const MeshData &mesh_data, | ||||
| const MLoopTri &looptri, | const MLoopTri &looptri, | ||||
| const int v1, | const int v1, | ||||
| const int v2) | const int v2) | ||||
| { | { | ||||
| const Span<MLoop> mesh_loops = mesh_data.loops; | const Span<int> corner_verts = mesh_data.corner_verts; | ||||
| BLI_assert(ELEM(v1, | BLI_assert(ELEM(v1, | ||||
| mesh_loops[looptri.tri[0]].v, | corner_verts[looptri.tri[0]], | ||||
| mesh_loops[looptri.tri[1]].v, | corner_verts[looptri.tri[1]], | ||||
| mesh_loops[looptri.tri[2]].v)); | corner_verts[looptri.tri[2]])); | ||||
| BLI_assert(ELEM(v2, | BLI_assert(ELEM(v2, | ||||
| mesh_loops[looptri.tri[0]].v, | corner_verts[looptri.tri[0]], | ||||
| mesh_loops[looptri.tri[1]].v, | corner_verts[looptri.tri[1]], | ||||
| mesh_loops[looptri.tri[2]].v)); | corner_verts[looptri.tri[2]])); | ||||
| for (const int loop : looptri.tri) { | for (const int loop : looptri.tri) { | ||||
| const int vert = mesh_loops[loop].v; | const int vert = corner_verts[loop]; | ||||
| if (vert != v1 && vert != v2) { | if (vert != v1 && vert != v2) { | ||||
| return vert; | return vert; | ||||
| } | } | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| static bool primitive_has_shared_uv_edge(const Span<float2> uv_map, | static bool primitive_has_shared_uv_edge(const Span<float2> uv_map, | ||||
| Show All 9 Lines | |||||
| } | } | ||||
| } | } | ||||
| return shared_uv_verts >= 2; | return shared_uv_verts >= 2; | ||||
| } | } | ||||
| static int get_uv_loop(const MeshData &mesh_data, const MLoopTri &looptri, const int vert) | static int get_uv_loop(const MeshData &mesh_data, const MLoopTri &looptri, const int vert) | ||||
| { | { | ||||
| for (const int loop : looptri.tri) { | for (const int loop : looptri.tri) { | ||||
| if (mesh_data.loops[loop].v == vert) { | if (mesh_data.corner_verts[loop] == vert) { | ||||
| return loop; | return loop; | ||||
| } | } | ||||
| } | } | ||||
| BLI_assert_unreachable(); | BLI_assert_unreachable(); | ||||
| return looptri.tri[0]; | return looptri.tri[0]; | ||||
| } | } | ||||
| static rctf primitive_uv_bounds(const MLoopTri &looptri, const Span<float2> uv_map) | static rctf primitive_uv_bounds(const MLoopTri &looptri, const Span<float2> uv_map) | ||||
| Show All 15 Lines | |||||
| static void mesh_data_init_edges(MeshData &mesh_data) | static void mesh_data_init_edges(MeshData &mesh_data) | ||||
| { | { | ||||
| mesh_data.edges.reserve(mesh_data.looptris.size() * 2); | mesh_data.edges.reserve(mesh_data.looptris.size() * 2); | ||||
| EdgeHash *eh = BLI_edgehash_new_ex(__func__, mesh_data.looptris.size() * 3); | EdgeHash *eh = BLI_edgehash_new_ex(__func__, mesh_data.looptris.size() * 3); | ||||
| for (int64_t i = 0; i < mesh_data.looptris.size(); i++) { | for (int64_t i = 0; i < mesh_data.looptris.size(); i++) { | ||||
| const MLoopTri &tri = mesh_data.looptris[i]; | const MLoopTri &tri = mesh_data.looptris[i]; | ||||
| Vector<int, 3> edges; | Vector<int, 3> edges; | ||||
| for (int j = 0; j < 3; j++) { | for (int j = 0; j < 3; j++) { | ||||
| int v1 = mesh_data.loops[tri.tri[j]].v; | int v1 = mesh_data.corner_verts[tri.tri[j]]; | ||||
| int v2 = mesh_data.loops[tri.tri[(j + 1) % 3]].v; | int v2 = mesh_data.corner_verts[tri.tri[(j + 1) % 3]]; | ||||
| void **edge_index_ptr; | void **edge_index_ptr; | ||||
| int64_t edge_index; | int64_t edge_index; | ||||
| if (BLI_edgehash_ensure_p(eh, v1, v2, &edge_index_ptr)) { | if (BLI_edgehash_ensure_p(eh, v1, v2, &edge_index_ptr)) { | ||||
| edge_index = POINTER_AS_INT(*edge_index_ptr) - 1; | edge_index = POINTER_AS_INT(*edge_index_ptr) - 1; | ||||
| *edge_index_ptr = POINTER_FROM_INT(edge_index); | *edge_index_ptr = POINTER_FROM_INT(edge_index); | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
| static void mesh_data_init(MeshData &mesh_data) | static void mesh_data_init(MeshData &mesh_data) | ||||
| { | { | ||||
| mesh_data_init_edges(mesh_data); | mesh_data_init_edges(mesh_data); | ||||
| mesh_data.uv_island_len = mesh_data_init_primitive_uv_island_ids(mesh_data); | mesh_data.uv_island_len = mesh_data_init_primitive_uv_island_ids(mesh_data); | ||||
| } | } | ||||
| MeshData::MeshData(const Span<MLoopTri> looptris, | MeshData::MeshData(const Span<MLoopTri> looptris, | ||||
| const Span<MLoop> loops, | const Span<int> corner_verts, | ||||
| const int verts_num, | const int verts_num, | ||||
| const Span<float2> uv_map, | const Span<float2> uv_map, | ||||
| const Span<float3> vertex_positions) | const Span<float3> vertex_positions) | ||||
| : looptris(looptris), | : looptris(looptris), | ||||
| verts_num(verts_num), | verts_num(verts_num), | ||||
| loops(loops), | corner_verts(corner_verts), | ||||
| uv_map(uv_map), | uv_map(uv_map), | ||||
| vertex_positions(vertex_positions), | vertex_positions(vertex_positions), | ||||
| vert_to_edge_map(verts_num), | vert_to_edge_map(verts_num), | ||||
| edge_to_primitive_map(0), | edge_to_primitive_map(0), | ||||
| primitive_to_edge_map(looptris.size()) | primitive_to_edge_map(looptris.size()) | ||||
| { | { | ||||
| mesh_data_init(*this); | mesh_data_init(*this); | ||||
| } | } | ||||
| Show All 11 Lines | |||||
| } | } | ||||
| UVVertex::UVVertex() | UVVertex::UVVertex() | ||||
| { | { | ||||
| uv_vertex_init_flags(*this); | uv_vertex_init_flags(*this); | ||||
| } | } | ||||
| UVVertex::UVVertex(const MeshData &mesh_data, const int loop) | UVVertex::UVVertex(const MeshData &mesh_data, const int loop) | ||||
| : vertex(mesh_data.loops[loop].v), uv(mesh_data.uv_map[loop]) | : vertex(mesh_data.corner_verts[loop]), uv(mesh_data.uv_map[loop]) | ||||
| { | { | ||||
| uv_vertex_init_flags(*this); | uv_vertex_init_flags(*this); | ||||
| } | } | ||||
| /** | /** | ||||
| * Get a list containing the indices of mesh primitives (primitive of the input mesh), that | * Get a list containing the indices of mesh primitives (primitive of the input mesh), that | ||||
| * surround the given uv_vertex in uv-space. | * surround the given uv_vertex in uv-space. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| const int primitive_index, | const int primitive_index, | ||||
| const MLoopTri *primitive, | const MLoopTri *primitive, | ||||
| int vertex) | int vertex) | ||||
| : primitive_index(primitive_index), primitive(primitive) | : primitive_index(primitive_index), primitive(primitive) | ||||
| { | { | ||||
| flags.found = false; | flags.found = false; | ||||
| /* Reorder so the first edge starts with the given vertex. */ | /* Reorder so the first edge starts with the given vertex. */ | ||||
| if (mesh_data.loops[primitive->tri[1]].v == vertex) { | if (mesh_data.corner_verts[primitive->tri[1]] == vertex) { | ||||
| vert_order[0] = 1; | vert_order[0] = 1; | ||||
| vert_order[1] = 2; | vert_order[1] = 2; | ||||
| vert_order[2] = 0; | vert_order[2] = 0; | ||||
| } | } | ||||
| else if (mesh_data.loops[primitive->tri[2]].v == vertex) { | else if (mesh_data.corner_verts[primitive->tri[2]] == vertex) { | ||||
| vert_order[0] = 2; | vert_order[0] = 2; | ||||
| vert_order[1] = 0; | vert_order[1] = 0; | ||||
| vert_order[2] = 1; | vert_order[2] = 1; | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(mesh_data.loops[primitive->tri[0]].v == vertex); | BLI_assert(mesh_data.corner_verts[primitive->tri[0]] == vertex); | ||||
| vert_order[0] = 0; | vert_order[0] = 0; | ||||
| vert_order[1] = 1; | vert_order[1] = 1; | ||||
| vert_order[2] = 2; | vert_order[2] = 2; | ||||
| } | } | ||||
| } | } | ||||
| void print_debug(const MeshData &mesh_data) const | void print_debug(const MeshData &mesh_data) const | ||||
| { | { | ||||
| std::stringstream ss; | std::stringstream ss; | ||||
| ss << "# p:" << primitive->poly; | ss << "# p:" << primitive->poly; | ||||
| ss << " v1:" << mesh_data.loops[primitive->tri[vert_order[0]]].v; | ss << " v1:" << mesh_data.corner_verts[primitive->tri[vert_order[0]]]; | ||||
| ss << " v2:" << mesh_data.loops[primitive->tri[vert_order[1]]].v; | ss << " v2:" << mesh_data.corner_verts[primitive->tri[vert_order[1]]]; | ||||
| ss << " v3:" << mesh_data.loops[primitive->tri[vert_order[2]]].v; | ss << " v3:" << mesh_data.corner_verts[primitive->tri[vert_order[2]]]; | ||||
| ss << " uv1:" << uvs[0]; | ss << " uv1:" << uvs[0]; | ||||
| ss << " uv2:" << uvs[1]; | ss << " uv2:" << uvs[1]; | ||||
| ss << " uv3:" << uvs[2]; | ss << " uv3:" << uvs[2]; | ||||
| if (flags.found) { | if (flags.found) { | ||||
| ss << " *found"; | ss << " *found"; | ||||
| } | } | ||||
| ss << "\n"; | ss << "\n"; | ||||
| std::cout << ss.str(); | std::cout << ss.str(); | ||||
| ▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
| for (FanSegment &fan_edge : segments) { | for (FanSegment &fan_edge : segments) { | ||||
| fan_edge.flags.found = mesh_primitive_indices.contains(fan_edge.primitive_index); | fan_edge.flags.found = mesh_primitive_indices.contains(fan_edge.primitive_index); | ||||
| } | } | ||||
| } | } | ||||
| void init_uv_coordinates(const MeshData &mesh_data, UVVertex &uv_vertex) | void init_uv_coordinates(const MeshData &mesh_data, UVVertex &uv_vertex) | ||||
| { | { | ||||
| for (FanSegment &fan_edge : segments) { | for (FanSegment &fan_edge : segments) { | ||||
| int other_v = mesh_data.loops[fan_edge.primitive->tri[fan_edge.vert_order[0]]].v; | int other_v = mesh_data.corner_verts[fan_edge.primitive->tri[fan_edge.vert_order[0]]]; | ||||
| if (other_v == uv_vertex.vertex) { | if (other_v == uv_vertex.vertex) { | ||||
| other_v = mesh_data.loops[fan_edge.primitive->tri[fan_edge.vert_order[1]]].v; | other_v = mesh_data.corner_verts[fan_edge.primitive->tri[fan_edge.vert_order[1]]]; | ||||
| } | } | ||||
| for (UVEdge *edge : uv_vertex.uv_edges) { | for (UVEdge *edge : uv_vertex.uv_edges) { | ||||
| const UVVertex *other_uv_vertex = edge->get_other_uv_vertex(uv_vertex.vertex); | const UVVertex *other_uv_vertex = edge->get_other_uv_vertex(uv_vertex.vertex); | ||||
| int64_t other_edge_v = other_uv_vertex->vertex; | int64_t other_edge_v = other_uv_vertex->vertex; | ||||
| if (other_v == other_edge_v) { | if (other_v == other_edge_v) { | ||||
| fan_edge.uvs[0] = uv_vertex.uv; | fan_edge.uvs[0] = uv_vertex.uv; | ||||
| fan_edge.uvs[1] = other_uv_vertex->uv; | fan_edge.uvs[1] = other_uv_vertex->uv; | ||||
| Show All 11 Lines | |||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||
| /** | /** | ||||
| * Check if the given vertex is part of the outside of the fan. | * Check if the given vertex is part of the outside of the fan. | ||||
| * Return true if the given vertex is found on the outside of the fan, otherwise returns false. | * Return true if the given vertex is found on the outside of the fan, otherwise returns false. | ||||
| */ | */ | ||||
| bool contains_vertex_on_outside(const MeshData &mesh_data, const int vertex_index) const | bool contains_vertex_on_outside(const MeshData &mesh_data, const int vertex_index) const | ||||
| { | { | ||||
| for (const FanSegment &segment : segments) { | for (const FanSegment &segment : segments) { | ||||
| int v2 = mesh_data.loops[segment.primitive->tri[segment.vert_order[1]]].v; | int v2 = mesh_data.corner_verts[segment.primitive->tri[segment.vert_order[1]]]; | ||||
| if (vertex_index == v2) { | if (vertex_index == v2) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| #endif | #endif | ||||
| static bool is_path_valid(const Span<FanSegment *> &path, | static bool is_path_valid(const Span<FanSegment *> &path, | ||||
| const MeshData &mesh_data, | const MeshData &mesh_data, | ||||
| const int from_vertex, | const int from_vertex, | ||||
| const int to_vertex) | const int to_vertex) | ||||
| { | { | ||||
| int current_vert = from_vertex; | int current_vert = from_vertex; | ||||
| for (FanSegment *segment : path) { | for (FanSegment *segment : path) { | ||||
| int v1 = mesh_data.loops[segment->primitive->tri[segment->vert_order[1]]].v; | int v1 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[1]]]; | ||||
| int v2 = mesh_data.loops[segment->primitive->tri[segment->vert_order[2]]].v; | int v2 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[2]]]; | ||||
| if (!ELEM(current_vert, v1, v2)) { | if (!ELEM(current_vert, v1, v2)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| current_vert = v1 == current_vert ? v2 : v1; | current_vert = v1 == current_vert ? v2 : v1; | ||||
| } | } | ||||
| return current_vert == to_vertex; | return current_vert == to_vertex; | ||||
| } | } | ||||
| Show All 13 Lines | |||||
| const int to_vert_order = 2; | const int to_vert_order = 2; | ||||
| const int index_increment = reversed ? -1 : 1; | const int index_increment = reversed ? -1 : 1; | ||||
| Vector<FanSegment *> result; | Vector<FanSegment *> result; | ||||
| result.reserve(edge_order.size()); | result.reserve(edge_order.size()); | ||||
| int index = 0; | int index = 0; | ||||
| while (true) { | while (true) { | ||||
| FanSegment *segment = edge_order[index]; | FanSegment *segment = edge_order[index]; | ||||
| int v2 = mesh_data.loops[segment->primitive->tri[segment->vert_order[from_vert_order]]].v; | int v2 = | ||||
| mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[from_vert_order]]]; | |||||
| if (v2 == from_vertex) { | if (v2 == from_vertex) { | ||||
| break; | break; | ||||
| } | } | ||||
| index = (index + index_increment + edge_order.size()) % edge_order.size(); | index = (index + index_increment + edge_order.size()) % edge_order.size(); | ||||
| } | } | ||||
| while (true) { | while (true) { | ||||
| FanSegment *segment = edge_order[index]; | FanSegment *segment = edge_order[index]; | ||||
| result.append(segment); | result.append(segment); | ||||
| int v3 = mesh_data.loops[segment->primitive->tri[segment->vert_order[to_vert_order]]].v; | int v3 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[to_vert_order]]]; | ||||
| if (v3 == to_vertex) { | if (v3 == to_vertex) { | ||||
| break; | break; | ||||
| } | } | ||||
| index = (index + index_increment + edge_order.size()) % edge_order.size(); | index = (index + index_increment + edge_order.size()) % edge_order.size(); | ||||
| } | } | ||||
| return result; | return result; | ||||
| ▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | |||||
| mesh_data, looptri, connected_vert_1->vertex, connected_vert_2->vertex); | mesh_data, looptri, connected_vert_1->vertex, connected_vert_2->vertex); | ||||
| UVVertex vert_template; | UVVertex vert_template; | ||||
| vert_template.uv = uv_unconnected; | vert_template.uv = uv_unconnected; | ||||
| vert_template.vertex = other_vert_i; | vert_template.vertex = other_vert_i; | ||||
| UVVertex *vert_ptr = island.lookup_or_create(vert_template); | UVVertex *vert_ptr = island.lookup_or_create(vert_template); | ||||
| const int loop_1 = get_uv_loop(mesh_data, looptri, connected_vert_1->vertex); | const int loop_1 = get_uv_loop(mesh_data, looptri, connected_vert_1->vertex); | ||||
| vert_template.uv = connected_vert_1->uv; | vert_template.uv = connected_vert_1->uv; | ||||
| vert_template.vertex = mesh_data.loops[loop_1].v; | vert_template.vertex = mesh_data.corner_verts[loop_1]; | ||||
| UVVertex *vert_1_ptr = island.lookup_or_create(vert_template); | UVVertex *vert_1_ptr = island.lookup_or_create(vert_template); | ||||
| const int loop_2 = get_uv_loop(mesh_data, looptri, connected_vert_2->vertex); | const int loop_2 = get_uv_loop(mesh_data, looptri, connected_vert_2->vertex); | ||||
| vert_template.uv = connected_vert_2->uv; | vert_template.uv = connected_vert_2->uv; | ||||
| vert_template.vertex = mesh_data.loops[loop_2].v; | vert_template.vertex = mesh_data.corner_verts[loop_2]; | ||||
| UVVertex *vert_2_ptr = island.lookup_or_create(vert_template); | UVVertex *vert_2_ptr = island.lookup_or_create(vert_template); | ||||
| UVEdge edge_template; | UVEdge edge_template; | ||||
| edge_template.vertices[0] = vert_1_ptr; | edge_template.vertices[0] = vert_1_ptr; | ||||
| edge_template.vertices[1] = vert_2_ptr; | edge_template.vertices[1] = vert_2_ptr; | ||||
| prim1.edges.append(island.lookup_or_create(edge_template)); | prim1.edges.append(island.lookup_or_create(edge_template)); | ||||
| edge_template.vertices[0] = vert_2_ptr; | edge_template.vertices[0] = vert_2_ptr; | ||||
| edge_template.vertices[1] = vert_ptr; | edge_template.vertices[1] = vert_ptr; | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * Get the UVVertex in the order that the verts are ordered in the MeshPrimitive. | * Get the UVVertex in the order that the verts are ordered in the MeshPrimitive. | ||||
| */ | */ | ||||
| const UVVertex *UVPrimitive::get_uv_vertex(const MeshData &mesh_data, | const UVVertex *UVPrimitive::get_uv_vertex(const MeshData &mesh_data, | ||||
| const uint8_t mesh_vert_index) const | const uint8_t mesh_vert_index) const | ||||
| { | { | ||||
| const MLoopTri &looptri = mesh_data.looptris[this->primitive_i]; | const MLoopTri &looptri = mesh_data.looptris[this->primitive_i]; | ||||
| const int mesh_vertex = mesh_data.loops[looptri.tri[mesh_vert_index]].v; | const int mesh_vertex = mesh_data.corner_verts[looptri.tri[mesh_vert_index]]; | ||||
| for (const UVEdge *uv_edge : edges) { | for (const UVEdge *uv_edge : edges) { | ||||
| for (const UVVertex *uv_vert : uv_edge->vertices) { | for (const UVVertex *uv_vert : uv_edge->vertices) { | ||||
| if (uv_vert->vertex == mesh_vertex) { | if (uv_vert->vertex == mesh_vertex) { | ||||
| return uv_vert; | return uv_vert; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_assert_unreachable(); | BLI_assert_unreachable(); | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||