WIP: Geometry Nodes: Shperical Ico Sphere #116982

Draft
Iliya Katushenock wants to merge 48 commits from mod_moder/blender:new_ico_sphere_alg into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
1 changed files with 104 additions and 59 deletions
Showing only changes of commit 1de316944e - Show all commits

View File

@ -535,23 +535,32 @@ static bool elem_of(int elem, const int2 elems)
static void corner_edges_topology(const int edge_edges_num,
const int face_faces_num,
MutableSpan<int> corner_edges,
const Span<int2> edges)
MutableSpan<int> corner_edges)
{
const Span<int2> base_edge_points = base_edge_point_indices();
const Span<int3> base_face_points = base_face_point_indices();
const Span<int3> base_faces_edges = base_face_edge_indices();
if (edge_edges_num == 1) {
corner_edges.copy_from(base_faces_edges.cast<int>());
return;
}
const int edge_faces_num = edge_edges_num - 2;
const IndexRange corner_faces_corners(3 * 3);
const IndexRange edge_faces_corners(corner_faces_corners.one_after_last(),
edge_faces_num * 3 * 3);
const IndexRange face_top_faces_corners(edge_faces_corners.one_after_last(),
pyramid_sum(edge_edges_num - 1) * 3);
const IndexRange face_bottom_faces_corners(face_top_faces_corners.one_after_last(),
pyramid_sum(edge_edges_num - 3) * 3);
for (const int face_i : IndexRange(base_faces_num)) {
const int3 face_vert_indices = base_face_points[face_i];
const int3 face_edge_indices = base_faces_edges[face_i];
// MutableSpan<int> face_cornder_edges = corner_edges.slice(face_i * face_faces_num * 3,
// face_faces_num * 3);
MutableSpan<int> face_cornder_edges = corner_edges.slice(
face_i * (3 * (3 + (edge_edges_num - 2) * 3)), 3 * (3 + (edge_edges_num - 2) * 3));
MutableSpan<int> face_cornder_edges = corner_edges.slice(face_i * face_faces_num * 3,
face_faces_num * 3);
const IndexRange edge_a_edges(face_edge_indices[0] * edge_edges_num, edge_edges_num);
const IndexRange edge_b_edges(face_edge_indices[1] * edge_edges_num, edge_edges_num);
@ -570,84 +579,108 @@ static void corner_edges_topology(const int edge_edges_num,
pyramid_sum(edge_edges_num - 1),
pyramid_sum(edge_edges_num - 1));
face_cornder_edges[0] = elem_of(base_edge_points[face_edge_indices[2]][0],
base_edge_points[face_edge_indices[1]]) ?
edge_c_edges.first() :
edge_c_edges.last();
face_cornder_edges[1] = face_edges_a.last();
face_cornder_edges[2] = elem_of(base_edge_points[face_edge_indices[1]][0],
base_edge_points[face_edge_indices[2]]) ?
edge_b_edges.first() :
edge_b_edges.last();
const bool corner_a_order = elem_of(base_edge_points[face_edge_indices[2]][0],
base_edge_points[face_edge_indices[1]]);
const bool corner_b_order = elem_of(base_edge_points[face_edge_indices[0]][0],
base_edge_points[face_edge_indices[2]]);
const bool corner_c_order = elem_of(base_edge_points[face_edge_indices[1]][0],
base_edge_points[face_edge_indices[2]]);
face_cornder_edges[3] = elem_of(base_edge_points[face_edge_indices[2]][0],
base_edge_points[face_edge_indices[0]]) ?
edge_c_edges.first() :
edge_c_edges.last();
face_cornder_edges[4] = face_edges_b.last();
face_cornder_edges[5] = elem_of(base_edge_points[face_edge_indices[0]][0],
base_edge_points[face_edge_indices[2]]) ?
edge_a_edges.first() :
edge_a_edges.last();
face_cornder_edges[6] = elem_of(base_edge_points[face_edge_indices[0]][0],
base_edge_points[face_edge_indices[1]]) ?
edge_a_edges.first() :
edge_a_edges.last();
face_cornder_edges[7] = face_edges_c.last();
face_cornder_edges[8] = elem_of(base_edge_points[face_edge_indices[1]][0],
base_edge_points[face_edge_indices[0]]) ?
edge_b_edges.first() :
edge_b_edges.last();
face_cornder_edges = face_cornder_edges.drop_front(3 * 3);
const int edge_faces_num = edge_edges_num - 2;
face_cornder_edges[corner_faces_corners[0]] = corner_a_order ? edge_c_edges.first() :
edge_c_edges.last();
face_cornder_edges[corner_faces_corners[1]] = face_edges_a.last();
face_cornder_edges[corner_faces_corners[2]] = corner_c_order ? edge_b_edges.first() :
edge_b_edges.last();
face_cornder_edges[corner_faces_corners[3]] = !corner_a_order ? edge_c_edges.first() :
edge_c_edges.last();
face_cornder_edges[corner_faces_corners[4]] = face_edges_b.last();
face_cornder_edges[corner_faces_corners[5]] = corner_b_order ? edge_a_edges.first() :
edge_a_edges.last();
face_cornder_edges[corner_faces_corners[6]] = !corner_b_order ? edge_a_edges.first() :
edge_a_edges.last();
face_cornder_edges[corner_faces_corners[7]] = face_edges_c.last();
face_cornder_edges[corner_faces_corners[8]] = !corner_c_order ? edge_b_edges.first() :
edge_b_edges.last();
const bool edge_a_order = int2(face_vert_indices[0], face_vert_indices[1]) ==
base_edge_points[face_edge_indices[0]];
for (const int i : IndexRange(edge_faces_num)) {
face_cornder_edges[i * 3 + 0] = edge_a_order ? edge_a_edges.drop_front(1)[i] :
edge_a_edges.drop_back(1)[edge_faces_num - i];
face_cornder_edges[edge_faces_corners[i * 3 + 0]] = edge_a_order ?
edge_a_edges.drop_front(1)[i] :
edge_a_edges.drop_back(
1)[edge_faces_num - i];
const IndexRange b_line = face_edges_c.slice(pyramid_slice(edge_edges_num - 1, i));
const IndexRange c_line = face_edges_b.slice(
pyramid_slice(edge_edges_num - 1, edge_faces_num - 1 - i));
face_cornder_edges[i * 3 + 1] = b_line.first();
face_cornder_edges[i * 3 + 2] = c_line.first();
face_cornder_edges[edge_faces_corners[i * 3 + 1]] = b_line.first();
face_cornder_edges[edge_faces_corners[i * 3 + 2]] = c_line.first();
}
const bool edge_b_order = int2(face_vert_indices[1], face_vert_indices[2]) !=
base_edge_points[face_edge_indices[1]];
for (const int i : IndexRange(edge_faces_num)) {
face_cornder_edges[(edge_faces_num + i) * 3 + 0] = edge_b_order ?
edge_b_edges.drop_front(1)[i] :
edge_b_edges.drop_back(
1)[edge_faces_num - i];
face_cornder_edges[edge_faces_corners[(edge_faces_num + i) * 3 + 0]] =
edge_b_order ? edge_b_edges.drop_front(1)[i] :
edge_b_edges.drop_back(1)[edge_faces_num - i];
const IndexRange a_line = face_edges_c.slice(pyramid_slice(edge_edges_num - 1, i));
const IndexRange c_line = face_edges_a.slice(
pyramid_slice(edge_edges_num - 1, edge_faces_num - 1 - i));
face_cornder_edges[(edge_faces_num + i) * 3 + 1] = a_line.last();
face_cornder_edges[(edge_faces_num + i) * 3 + 2] = c_line.last();
face_cornder_edges[edge_faces_corners[(edge_faces_num + i) * 3 + 1]] = a_line.last();
face_cornder_edges[edge_faces_corners[(edge_faces_num + i) * 3 + 2]] = c_line.last();
}
const bool edge_c_order = int2(face_vert_indices[0], face_vert_indices[2]) ==
base_edge_points[face_edge_indices[2]];
for (const int i : IndexRange(edge_faces_num)) {
face_cornder_edges[(edge_faces_num * 2 + i) * 3 + 0] = edge_c_order ?
edge_c_edges.drop_front(1)[i] :
edge_c_edges.drop_back(
1)[edge_faces_num - i];
face_cornder_edges[edge_faces_corners[(edge_faces_num * 2 + i) * 3 + 0]] =
edge_c_order ? edge_c_edges.drop_front(1)[i] :
edge_c_edges.drop_back(1)[edge_faces_num - i];
const IndexRange a_line = face_edges_a.slice(pyramid_slice(edge_edges_num - 1, i));
const IndexRange b_line = face_edges_b.slice(
pyramid_slice(edge_edges_num - 1, edge_faces_num - 1 - i));
face_cornder_edges[(edge_faces_num * 2 + i) * 3 + 1] = a_line.first();
face_cornder_edges[(edge_faces_num * 2 + i) * 3 + 2] = b_line.last();
face_cornder_edges[edge_faces_corners[(edge_faces_num * 2 + i) * 3 + 1]] = a_line.first();
face_cornder_edges[edge_faces_corners[(edge_faces_num * 2 + i) * 3 + 2]] = b_line.last();
}
for (const int line_i : IndexRange(edge_edges_num - 1)) {
const IndexRange line_range = pyramid_slice(edge_edges_num - 1, line_i);
MutableSpan<int> face_line_corners = face_cornder_edges.slice(
face_top_faces_corners.slice(line_range.start() * 3, line_range.size() * 3));
for (const int i : line_range.index_range()) {
face_line_corners[i * 3 + 0] = face_edges_a.slice(line_range)[i];
const IndexRange b_line = face_edges_c.slice(pyramid_slice(edge_edges_num - 1, i));
const IndexRange c_line = face_edges_b.slice(
pyramid_slice(edge_edges_num - 1, edge_faces_num - i - line_i));
face_line_corners[i * 3 + 1] = b_line.drop_front(line_i).first();
face_line_corners[i * 3 + 2] = c_line.drop_front(line_i).first();
}
}
const int bottom_faces_num = math::max<int>(0, edge_edges_num - 3);
for (const int line_i : IndexRange(bottom_faces_num)) {
const IndexRange line_range = pyramid_slice(bottom_faces_num, line_i);
const IndexRange line_range_ = pyramid_slice(edge_edges_num - 1, line_i);
MutableSpan<int> face_line_corners = face_cornder_edges.slice(
face_bottom_faces_corners.slice(line_range.start() * 3, line_range.size() * 3));
for (const int i : line_range.index_range()) {
face_line_corners[i * 3 + 0] = face_edges_a.slice(line_range_)[i + 1];
const IndexRange b_line = face_edges_c.slice(pyramid_slice(edge_edges_num - 1, i));
const IndexRange c_line = face_edges_b.slice(
pyramid_slice(edge_edges_num - 1, edge_faces_num - i - line_i - 2));
face_line_corners[i * 3 + 1] = b_line.drop_front(line_i + 1).first();
face_line_corners[i * 3 + 2] = c_line.drop_front(line_i + 1).first();
}
}
}
}
@ -693,8 +726,7 @@ static Mesh *ico_sphere(const int subdivisions, const float radius)
const int verts_num = base_verts_num + (base_edges_num - base_face_quads) * edge_verts_num +
base_face_quads * edge_verts_num * edge_verts_num;
const int edges_num = base_edges_num * edge_edges_num + face_edges_num * base_faces_num * 3;
// const int faces_num = base_faces_num * face_faces_num;
const int faces_num = base_faces_num * (3 + (edge_edges_num - 2) * 3);
const int faces_num = base_faces_num * face_faces_num;
const int corners_num = faces_num * 3;
Mesh *mesh = BKE_mesh_new_nomain(verts_num, edges_num, faces_num, corners_num);
@ -724,15 +756,28 @@ static Mesh *ico_sphere(const int subdivisions, const float radius)
face_edge_topology(
edge_edges_num, face_verts_num, edge_verts_num, face_points, edges.slice(face_edges));
corner_edges_topology(edge_edges_num, face_faces_num, corner_edges, edges);
corner_edges_topology(edge_edges_num, face_faces_num, corner_edges);
corner_verts_from_edges(corner_edges, edges, faces_num, corner_verts);
IndexMaskMemory memory;
const IndexMask normals_mask = IndexMask::from_predicate(
IndexMask(faces_num), GrainSize(2048), memory, [&](const int i) -> bool {
const int face_i = i * 3;
const float3 normal = bke::mesh::face_normal_calc(positions,
corner_verts.slice(face_i, 3));
const float3 pos_a = math::normalize(positions[corner_verts[face_i]]);
return !math::is_equal(normal, pos_a, 0.4f);
});
bke::mesh_flip_faces(*mesh, normals_mask);
BLI_assert(std::all_of(edges.cast<int>().begin(),
edges.cast<int>().end(),
[=](const int i) -> bool { return IndexRange(verts_num).contains(i); }));
// mesh->tag_loose_verts_none();
// mesh->tag_overlapping_none();
mesh->tag_loose_verts_none();
mesh->tag_loose_edges_none();
mesh->tag_overlapping_none();
BKE_id_material_eval_ensure_default_slot(&mesh->id);
mesh->bounds_set_eager(calculate_bounds_ico_sphere(radius, subdivisions));