Cleanup: Make mesh primitive topology building more parallel
Avoid using an incremented "loop index" variable which makes the whole data-filling necessarily sequential. No functional changes expected, this just simplifies some refactors to face corner storage.
This commit is contained in:
parent
fd9b197226
commit
ff324ab716
Notes:
blender-bot
2023-02-14 06:55:40 +01:00
Referenced by commit a63a41177d
, Fix: Uninitialized variable in mesh primitive refactor
|
@ -372,45 +372,51 @@ static void calculate_cone_faces(const ConeConfig &config,
|
|||
MutableSpan<MLoop> loops,
|
||||
MutableSpan<MPoly> polys)
|
||||
{
|
||||
int loop_index = 0;
|
||||
int poly_index = 0;
|
||||
|
||||
int rings_poly_start;
|
||||
int rings_loop_start;
|
||||
if (config.top_has_center_vert) {
|
||||
rings_poly_start = config.circle_segments;
|
||||
rings_loop_start = config.circle_segments * 3;
|
||||
|
||||
/* Top cone tip or center triangle fan in the fill. */
|
||||
const int top_center_vert = 0;
|
||||
const int top_fan_edges_start = 0;
|
||||
|
||||
for (const int i : IndexRange(config.circle_segments)) {
|
||||
MPoly &poly = polys[poly_index++];
|
||||
poly.loopstart = loop_index;
|
||||
const int loop_start = i * 3;
|
||||
MPoly &poly = polys[i];
|
||||
poly.loopstart = loop_start;
|
||||
poly.totloop = 3;
|
||||
|
||||
MLoop &loop_a = loops[loop_index++];
|
||||
loop_a.v = config.first_ring_verts_start + i;
|
||||
loop_a.e = config.first_ring_edges_start + i;
|
||||
MLoop &loop_b = loops[loop_index++];
|
||||
loop_b.v = config.first_ring_verts_start + ((i + 1) % config.circle_segments);
|
||||
loop_b.e = top_fan_edges_start + ((i + 1) % config.circle_segments);
|
||||
MLoop &loop_c = loops[loop_index++];
|
||||
loop_c.v = top_center_vert;
|
||||
loop_c.e = top_fan_edges_start + i;
|
||||
loops[loop_start + 0].v = config.first_ring_verts_start + i;
|
||||
loops[loop_start + 0].e = config.first_ring_edges_start + i;
|
||||
|
||||
loops[loop_start + 1].v = config.first_ring_verts_start + ((i + 1) % config.circle_segments);
|
||||
loops[loop_start + 1].e = top_fan_edges_start + ((i + 1) % config.circle_segments);
|
||||
|
||||
loops[loop_start + 2].v = top_center_vert;
|
||||
loops[loop_start + 2].e = top_fan_edges_start + i;
|
||||
}
|
||||
}
|
||||
else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
|
||||
rings_poly_start = 1;
|
||||
rings_loop_start = config.circle_segments;
|
||||
|
||||
/* Center n-gon in the fill. */
|
||||
MPoly &poly = polys[poly_index++];
|
||||
poly.loopstart = loop_index;
|
||||
MPoly &poly = polys[0];
|
||||
poly.loopstart = 0;
|
||||
poly.totloop = config.circle_segments;
|
||||
for (const int i : IndexRange(config.circle_segments)) {
|
||||
MLoop &loop = loops[loop_index++];
|
||||
loop.v = i;
|
||||
loop.e = i;
|
||||
loops[i].v = i;
|
||||
loops[i].e = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Quads connect one edge ring to the next one. */
|
||||
if (config.tot_quad_rings > 0) {
|
||||
for (const int i : IndexRange(config.tot_quad_rings)) {
|
||||
const int this_ring_poly_start = rings_poly_start + i * config.circle_segments;
|
||||
const int this_ring_loop_start = rings_loop_start + i * config.circle_segments * 4;
|
||||
const int this_ring_vert_start = config.first_ring_verts_start +
|
||||
(i * config.circle_segments);
|
||||
const int next_ring_vert_start = this_ring_vert_start + config.circle_segments;
|
||||
|
@ -421,55 +427,58 @@ static void calculate_cone_faces(const ConeConfig &config,
|
|||
const int ring_connections_start = this_ring_edges_start + config.circle_segments;
|
||||
|
||||
for (const int j : IndexRange(config.circle_segments)) {
|
||||
MPoly &poly = polys[poly_index++];
|
||||
poly.loopstart = loop_index;
|
||||
const int loop_start = this_ring_loop_start + j * 4;
|
||||
MPoly &poly = polys[this_ring_poly_start + j];
|
||||
poly.loopstart = loop_start;
|
||||
poly.totloop = 4;
|
||||
|
||||
MLoop &loop_a = loops[loop_index++];
|
||||
loop_a.v = this_ring_vert_start + j;
|
||||
loop_a.e = ring_connections_start + j;
|
||||
MLoop &loop_b = loops[loop_index++];
|
||||
loop_b.v = next_ring_vert_start + j;
|
||||
loop_b.e = next_ring_edges_start + j;
|
||||
MLoop &loop_c = loops[loop_index++];
|
||||
loop_c.v = next_ring_vert_start + ((j + 1) % config.circle_segments);
|
||||
loop_c.e = ring_connections_start + ((j + 1) % config.circle_segments);
|
||||
MLoop &loop_d = loops[loop_index++];
|
||||
loop_d.v = this_ring_vert_start + ((j + 1) % config.circle_segments);
|
||||
loop_d.e = this_ring_edges_start + j;
|
||||
loops[loop_start + 0].v = this_ring_vert_start + j;
|
||||
loops[loop_start + 0].e = ring_connections_start + j;
|
||||
|
||||
loops[loop_start + 1].v = next_ring_vert_start + j;
|
||||
loops[loop_start + 1].e = next_ring_edges_start + j;
|
||||
|
||||
loops[loop_start + 2].v = next_ring_vert_start + ((j + 1) % config.circle_segments);
|
||||
loops[loop_start + 2].e = ring_connections_start + ((j + 1) % config.circle_segments);
|
||||
|
||||
loops[loop_start + 3].v = this_ring_vert_start + ((j + 1) % config.circle_segments);
|
||||
loops[loop_start + 3].e = this_ring_edges_start + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int bottom_poly_start = rings_poly_start + config.tot_quad_rings * config.circle_segments;
|
||||
const int bottom_loop_start = rings_loop_start +
|
||||
config.tot_quad_rings * config.circle_segments * 4;
|
||||
|
||||
if (config.bottom_has_center_vert) {
|
||||
/* Bottom cone tip or center triangle fan in the fill. */
|
||||
for (const int i : IndexRange(config.circle_segments)) {
|
||||
MPoly &poly = polys[poly_index++];
|
||||
poly.loopstart = loop_index;
|
||||
const int loop_start = bottom_loop_start + i * 3;
|
||||
MPoly &poly = polys[bottom_poly_start + i];
|
||||
poly.loopstart = loop_start;
|
||||
poly.totloop = 3;
|
||||
|
||||
MLoop &loop_a = loops[loop_index++];
|
||||
loop_a.v = config.last_ring_verts_start + i;
|
||||
loop_a.e = config.last_fan_edges_start + i;
|
||||
MLoop &loop_b = loops[loop_index++];
|
||||
loop_b.v = config.last_vert;
|
||||
loop_b.e = config.last_fan_edges_start + (i + 1) % config.circle_segments;
|
||||
MLoop &loop_c = loops[loop_index++];
|
||||
loop_c.v = config.last_ring_verts_start + (i + 1) % config.circle_segments;
|
||||
loop_c.e = config.last_ring_edges_start + i;
|
||||
loops[loop_start + 0].v = config.last_ring_verts_start + i;
|
||||
loops[loop_start + 0].e = config.last_fan_edges_start + i;
|
||||
|
||||
loops[loop_start + 1].v = config.last_vert;
|
||||
loops[loop_start + 1].e = config.last_fan_edges_start + (i + 1) % config.circle_segments;
|
||||
|
||||
loops[loop_start + 2].v = config.last_ring_verts_start + (i + 1) % config.circle_segments;
|
||||
loops[loop_start + 2].e = config.last_ring_edges_start + i;
|
||||
}
|
||||
}
|
||||
else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
|
||||
/* Center n-gon in the fill. */
|
||||
MPoly &poly = polys[poly_index++];
|
||||
poly.loopstart = loop_index;
|
||||
MPoly &poly = polys[bottom_poly_start];
|
||||
poly.loopstart = bottom_loop_start;
|
||||
poly.totloop = config.circle_segments;
|
||||
|
||||
for (const int i : IndexRange(config.circle_segments)) {
|
||||
/* Go backwards to reverse surface normal. */
|
||||
MLoop &loop = loops[loop_index++];
|
||||
loop.v = config.last_vert - i;
|
||||
loop.e = config.last_edge - ((i + 1) % config.circle_segments);
|
||||
loops[bottom_loop_start + i].v = config.last_vert - i;
|
||||
loops[bottom_loop_start + i].e = config.last_edge - ((i + 1) % config.circle_segments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,7 +184,6 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan<MLoop> loops,
|
|||
const int segments,
|
||||
const int rings)
|
||||
{
|
||||
int loop_index = 0;
|
||||
auto segment_next_or_first = [&](const int segment) {
|
||||
return segment == segments - 1 ? 0 : segment + 1;
|
||||
};
|
||||
|
@ -192,63 +191,67 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan<MLoop> loops,
|
|||
/* Add the triangles connected to the top vertex. */
|
||||
const int first_vert_ring_index_start = 1;
|
||||
for (const int segment : IndexRange(segments)) {
|
||||
const int loop_start = segment * 3;
|
||||
const int segment_next = segment_next_or_first(segment);
|
||||
|
||||
MLoop &loop_a = loops[loop_index++];
|
||||
loop_a.v = 0;
|
||||
loop_a.e = segment;
|
||||
MLoop &loop_b = loops[loop_index++];
|
||||
loop_b.v = first_vert_ring_index_start + segment;
|
||||
loop_b.e = segments + segment;
|
||||
MLoop &loop_c = loops[loop_index++];
|
||||
loop_c.v = first_vert_ring_index_start + segment_next;
|
||||
loop_c.e = segment_next;
|
||||
loops[loop_start + 0].v = 0;
|
||||
loops[loop_start + 0].e = segment;
|
||||
|
||||
loops[loop_start + 1].v = first_vert_ring_index_start + segment;
|
||||
loops[loop_start + 1].e = segments + segment;
|
||||
|
||||
loops[loop_start + 2].v = first_vert_ring_index_start + segment_next;
|
||||
loops[loop_start + 2].e = segment_next;
|
||||
}
|
||||
|
||||
int ring_vert_index_start = 1;
|
||||
int ring_edge_index_start = segments;
|
||||
for ([[maybe_unused]] const int ring : IndexRange(1, rings - 2)) {
|
||||
const int rings_vert_index_start = 1;
|
||||
const int rings_edge_index_start = segments;
|
||||
const int rings_loop_index_start = segments * 3;
|
||||
for (const int ring : IndexRange(1, rings - 2)) {
|
||||
const int ring_vert_index_start = rings_vert_index_start + (ring - 1) * segments;
|
||||
const int ring_edge_index_start = rings_edge_index_start + (ring - 1) * segments * 2;
|
||||
const int ring_loop_index_start = rings_loop_index_start + (ring - 1) * segments * 4;
|
||||
|
||||
const int next_ring_vert_index_start = ring_vert_index_start + segments;
|
||||
const int next_ring_edge_index_start = ring_edge_index_start + segments * 2;
|
||||
const int ring_vertical_edge_index_start = ring_edge_index_start + segments;
|
||||
|
||||
for (const int segment : IndexRange(segments)) {
|
||||
const int loop_start = ring_loop_index_start + segment * 4;
|
||||
const int segment_next = segment_next_or_first(segment);
|
||||
|
||||
MLoop &loop_a = loops[loop_index++];
|
||||
loop_a.v = ring_vert_index_start + segment;
|
||||
loop_a.e = ring_vertical_edge_index_start + segment;
|
||||
MLoop &loop_b = loops[loop_index++];
|
||||
loop_b.v = next_ring_vert_index_start + segment;
|
||||
loop_b.e = next_ring_edge_index_start + segment;
|
||||
MLoop &loop_c = loops[loop_index++];
|
||||
loop_c.v = next_ring_vert_index_start + segment_next;
|
||||
loop_c.e = ring_vertical_edge_index_start + segment_next;
|
||||
MLoop &loop_d = loops[loop_index++];
|
||||
loop_d.v = ring_vert_index_start + segment_next;
|
||||
loop_d.e = ring_edge_index_start + segment;
|
||||
loops[loop_start + 0].v = ring_vert_index_start + segment;
|
||||
loops[loop_start + 0].e = ring_vertical_edge_index_start + segment;
|
||||
|
||||
loops[loop_start + 1].v = next_ring_vert_index_start + segment;
|
||||
loops[loop_start + 1].e = next_ring_edge_index_start + segment;
|
||||
|
||||
loops[loop_start + 2].v = next_ring_vert_index_start + segment_next;
|
||||
loops[loop_start + 2].e = ring_vertical_edge_index_start + segment_next;
|
||||
|
||||
loops[loop_start + 3].v = ring_vert_index_start + segment_next;
|
||||
loops[loop_start + 3].e = ring_edge_index_start + segment;
|
||||
}
|
||||
ring_vert_index_start += segments;
|
||||
ring_edge_index_start += segments * 2;
|
||||
}
|
||||
|
||||
/* Add the triangles connected to the bottom vertex. */
|
||||
const int bottom_loop_index_start = rings_loop_index_start + segments * (rings - 2) * 4;
|
||||
const int last_edge_ring_start = segments * (rings - 2) * 2 + segments;
|
||||
const int bottom_edge_fan_start = last_edge_ring_start + segments;
|
||||
const int last_vert_index = sphere_vert_total(segments, rings) - 1;
|
||||
const int last_vert_ring_start = last_vert_index - segments;
|
||||
for (const int segment : IndexRange(segments)) {
|
||||
const int loop_start = bottom_loop_index_start + segment * 3;
|
||||
const int segment_next = segment_next_or_first(segment);
|
||||
|
||||
MLoop &loop_a = loops[loop_index++];
|
||||
loop_a.v = last_vert_index;
|
||||
loop_a.e = bottom_edge_fan_start + segment_next;
|
||||
MLoop &loop_b = loops[loop_index++];
|
||||
loop_b.v = last_vert_ring_start + segment_next;
|
||||
loop_b.e = last_edge_ring_start + segment;
|
||||
MLoop &loop_c = loops[loop_index++];
|
||||
loop_c.v = last_vert_ring_start + segment;
|
||||
loop_c.e = bottom_edge_fan_start + segment;
|
||||
loops[loop_start + 0].v = last_vert_index;
|
||||
loops[loop_start + 0].e = bottom_edge_fan_start + segment_next;
|
||||
|
||||
loops[loop_start + 1].v = last_vert_ring_start + segment_next;
|
||||
loops[loop_start + 1].e = last_edge_ring_start + segment;
|
||||
|
||||
loops[loop_start + 2].v = last_vert_ring_start + segment;
|
||||
loops[loop_start + 2].e = bottom_edge_fan_start + segment;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,34 +263,39 @@ BLI_NOINLINE static void calculate_sphere_uvs(Mesh *mesh, const float segments,
|
|||
"uv_map", ATTR_DOMAIN_CORNER);
|
||||
MutableSpan<float2> uvs = uv_attribute.span;
|
||||
|
||||
int loop_index = 0;
|
||||
const float dy = 1.0f / rings;
|
||||
|
||||
const float segments_inv = 1.0f / segments;
|
||||
|
||||
for (const int i_segment : IndexRange(segments)) {
|
||||
const int loop_start = i_segment * 3;
|
||||
const float segment = float(i_segment);
|
||||
uvs[loop_index++] = float2((segment + 0.5f) * segments_inv, 0.0f);
|
||||
uvs[loop_index++] = float2(segment * segments_inv, dy);
|
||||
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, dy);
|
||||
uvs[loop_start + 0] = float2((segment + 0.5f) * segments_inv, 0.0f);
|
||||
uvs[loop_start + 1] = float2(segment * segments_inv, dy);
|
||||
uvs[loop_start + 2] = float2((segment + 1.0f) * segments_inv, dy);
|
||||
}
|
||||
|
||||
const int rings_loop_index_start = segments * 3;
|
||||
for (const int i_ring : IndexRange(1, rings - 2)) {
|
||||
const int ring_loop_index_start = rings_loop_index_start + (i_ring - 1) * segments * 4;
|
||||
const float ring = float(i_ring);
|
||||
for (const int i_segment : IndexRange(segments)) {
|
||||
const int loop_start = ring_loop_index_start + i_segment * 4;
|
||||
const float segment = float(i_segment);
|
||||
uvs[loop_index++] = float2(segment * segments_inv, ring / rings);
|
||||
uvs[loop_index++] = float2(segment * segments_inv, (ring + 1.0f) / rings);
|
||||
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, (ring + 1.0f) / rings);
|
||||
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, ring / rings);
|
||||
uvs[loop_start + 0] = float2(segment * segments_inv, ring / rings);
|
||||
uvs[loop_start + 1] = float2(segment * segments_inv, (ring + 1.0f) / rings);
|
||||
uvs[loop_start + 2] = float2((segment + 1.0f) * segments_inv, (ring + 1.0f) / rings);
|
||||
uvs[loop_start + 3] = float2((segment + 1.0f) * segments_inv, ring / rings);
|
||||
}
|
||||
}
|
||||
|
||||
const int bottom_loop_index_start = rings_loop_index_start + segments * (rings - 2) * 4;
|
||||
for (const int i_segment : IndexRange(segments)) {
|
||||
const int loop_start = bottom_loop_index_start + i_segment * 3;
|
||||
const float segment = float(i_segment);
|
||||
uvs[loop_index++] = float2((segment + 0.5f) * segments_inv, 1.0f);
|
||||
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, 1.0f - dy);
|
||||
uvs[loop_index++] = float2(segment * segments_inv, 1.0f - dy);
|
||||
uvs[loop_start + 0] = float2((segment + 0.5f) * segments_inv, 1.0f);
|
||||
uvs[loop_start + 1] = float2((segment + 1.0f) * segments_inv, 1.0f - dy);
|
||||
uvs[loop_start + 2] = float2(segment * segments_inv, 1.0f - dy);
|
||||
}
|
||||
|
||||
uv_attribute.finish();
|
||||
|
@ -321,6 +329,8 @@ static Mesh *create_uv_sphere_mesh(const float radius, const int segments, const
|
|||
|
||||
mesh->loose_edges_tag_none();
|
||||
|
||||
BLI_assert(BKE_mesh_is_valid(mesh));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue