mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Merge branch 'blender-v3.6-release'
This commit is contained in:
commit
0c0cd10e55
2 changed files with 21 additions and 50 deletions
|
|
@ -120,6 +120,14 @@ struct CornerNormalSpaceArray {
|
|||
* same as #Mesh::totloop). Rare -1 values define face corners without a coordinate space.
|
||||
*/
|
||||
Array<int> corner_space_indices;
|
||||
|
||||
/**
|
||||
* A map containing the face corners that make up each space,
|
||||
* in the order that they were processed (winding around a vertex).
|
||||
*/
|
||||
Array<Array<int>> corners_by_space;
|
||||
/** Whether to create the above map when calculating normals. */
|
||||
bool create_corners_by_space;
|
||||
};
|
||||
|
||||
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
||||
|
|
|
|||
|
|
@ -923,6 +923,10 @@ static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
|||
clnors_data[ml_curr_index],
|
||||
loop_normals[ml_curr_index]);
|
||||
}
|
||||
|
||||
if (!lnors_spacearr->corners_by_space.is_empty()) {
|
||||
lnors_spacearr->corners_by_space[space_index] = {ml_curr_index};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1039,6 +1043,9 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
/* We store here all edges-normalized vectors processed. */
|
||||
edge_vectors->append(vec_curr);
|
||||
}
|
||||
if (!lnors_spacearr->corners_by_space.is_empty()) {
|
||||
lnors_spacearr->corners_by_space[space_index] = processed_corners.as_span();
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_EDGE_SHARP(edge_to_loops[corner_edges[mlfan_curr_index]]) || (edge == edge_orig)) {
|
||||
|
|
@ -1380,6 +1387,9 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
if (r_lnors_spacearr) {
|
||||
r_lnors_spacearr->spaces.reinitialize(single_corners.size() + fan_corners.size());
|
||||
r_lnors_spacearr->corner_space_indices = Array<int>(corner_verts.size(), -1);
|
||||
if (r_lnors_spacearr->create_corners_by_space) {
|
||||
r_lnors_spacearr->corners_by_space.reinitialize(r_lnors_spacearr->spaces.size());
|
||||
}
|
||||
}
|
||||
|
||||
threading::parallel_for(single_corners.index_range(), 1024, [&](const IndexRange range) {
|
||||
|
|
@ -1403,35 +1413,6 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
#undef INDEX_INVALID
|
||||
#undef IS_EDGE_SHARP
|
||||
|
||||
/**
|
||||
* Take an array of N indices that points to \a items_num items, where multiple indices map to the
|
||||
* same item, and reverse the indices to create an array of all the indices that reference each
|
||||
* item. Group each item's indices together consecutively, encoding the grouping in #r_offsets,
|
||||
* which is meant to be used by #OffsetIndices.
|
||||
*
|
||||
* \param r_offsets: An array to be filled with the first index of each item in
|
||||
* \a r_reverse_indices, used to split the indices into chunks by item. (See #OffsetIndices).
|
||||
* \param r_reverse_indices: The indices into \a item_indices that point to each item, split by \a
|
||||
* r_offsets.
|
||||
*/
|
||||
static void reverse_index_array(const Span<int> item_indices,
|
||||
const int items_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_reverse_indices)
|
||||
{
|
||||
r_offsets = Array<int>(items_num + 1, 0);
|
||||
offset_indices::build_reverse_offsets(item_indices, r_offsets);
|
||||
|
||||
r_reverse_indices.reinitialize(r_offsets.last());
|
||||
|
||||
Array<int> count_per_item(items_num, 0);
|
||||
for (const int corner : item_indices.index_range()) {
|
||||
const int space = item_indices[corner];
|
||||
r_reverse_indices[r_offsets[space] + count_per_item[space]] = corner;
|
||||
count_per_item[space]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute internal representation of given custom normals (as an array of float[2]).
|
||||
* It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed
|
||||
|
|
@ -1461,6 +1442,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
* when importing custom normals, and modifier (and perhaps from some editing tools later?). So
|
||||
* better to keep some simplicity here, and just call #bke::mesh::normals_calc_loop() twice! */
|
||||
CornerNormalSpaceArray lnors_spacearr;
|
||||
lnors_spacearr.create_corners_by_space = true;
|
||||
BitVector<> done_loops(corner_verts.size(), false);
|
||||
Array<float3> loop_normals(corner_verts.size());
|
||||
const Array<int> loop_to_poly = build_loop_to_poly_map(polys);
|
||||
|
|
@ -1512,14 +1494,6 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
done_loops.fill(true);
|
||||
}
|
||||
else {
|
||||
Array<int> fan_corners_from_space_offset_indices;
|
||||
Array<int> fan_corners_from_space_data;
|
||||
reverse_index_array(lnors_spacearr.corner_space_indices,
|
||||
lnors_spacearr.spaces.size(),
|
||||
fan_corners_from_space_offset_indices,
|
||||
fan_corners_from_space_data);
|
||||
const OffsetIndices<int> fan_corner_offsets(fan_corners_from_space_offset_indices);
|
||||
|
||||
for (const int i : corner_verts.index_range()) {
|
||||
if (lnors_spacearr.corner_space_indices[i] == -1) {
|
||||
/* This should not happen in theory, but in some rare case (probably ugly geometry)
|
||||
|
|
@ -1536,8 +1510,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
}
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[i];
|
||||
const Span<int> fan_corners = fan_corners_from_space_data.as_span().slice(
|
||||
fan_corner_offsets[space_index]);
|
||||
const Span<int> fan_corners = lnors_spacearr.corners_by_space[space_index];
|
||||
|
||||
/* Notes:
|
||||
* - In case of mono-loop smooth fan, we have nothing to do.
|
||||
|
|
@ -1601,7 +1574,6 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
}
|
||||
|
||||
/* And now, recompute our new auto `loop_normals` and lnor spacearr! */
|
||||
lnors_spacearr = {};
|
||||
normals_calc_loop(positions,
|
||||
edges,
|
||||
polys,
|
||||
|
|
@ -1619,14 +1591,6 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
loop_normals);
|
||||
}
|
||||
|
||||
Array<int> fan_corners_from_space_offset_indices;
|
||||
Array<int> fan_corners_from_space_data;
|
||||
reverse_index_array(lnors_spacearr.corner_space_indices,
|
||||
lnors_spacearr.spaces.size(),
|
||||
fan_corners_from_space_offset_indices,
|
||||
fan_corners_from_space_data);
|
||||
const OffsetIndices<int> fan_corner_offsets(fan_corners_from_space_offset_indices);
|
||||
|
||||
/* And we just have to convert plain object-space custom normals to our
|
||||
* lnor space-encoded ones. */
|
||||
for (const int i : corner_verts.index_range()) {
|
||||
|
|
@ -1643,8 +1607,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
}
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[i];
|
||||
const Span<int> fan_corners = fan_corners_from_space_data.as_span().slice(
|
||||
fan_corner_offsets[space_index]);
|
||||
const Span<int> fan_corners = lnors_spacearr.corners_by_space[space_index];
|
||||
|
||||
/* Note we accumulate and average all custom normals in current smooth fan,
|
||||
* to avoid getting different clnors data (tiny differences in plain custom normals can
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue