WIP: uv-simple-select #1

Closed
Chris Blackbourn wants to merge 182 commits from uv-simple-select into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 114 additions and 29 deletions
Showing only changes of commit 31f03b9607 - Show all commits

View File

@ -25,7 +25,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 8
#define BLENDER_FILE_SUBVERSION 9
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -3892,6 +3892,21 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 305, 9)) {
/* Enable legacy normal and rotation outputs in Distribute Points on Faces node. */
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type != NTREE_GEOMETRY) {
continue;
}
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type != GEO_NODE_DISTRIBUTE_POINTS_ON_FACES) {
continue;
}
node->custom2 = true;
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -9645,6 +9645,14 @@ static void def_geo_distribute_points_on_faces(StructRNA *srna)
RNA_def_property_enum_default(prop, GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM);
RNA_def_property_ui_text(prop, "Distribution Method", "Method to use for scattering points");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
prop = RNA_def_property(srna, "use_legacy_normal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1);
RNA_def_property_ui_text(prop,
"Legacy Normal",
"Output the normal and rotation values that have been output "
"before the node started taking smooth normals into account");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
static void def_geo_curve_spline_type(StructRNA *srna)

View File

@ -67,6 +67,11 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE);
}
static void node_layout_ex(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "use_legacy_normal", 0, nullptr, ICON_NONE);
}
static void node_point_distribute_points_on_faces_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock_distance_min = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
@ -325,11 +330,73 @@ struct AttributeOutputs {
};
} // namespace
static void compute_normal_outputs(const Mesh &mesh,
const Span<float3> bary_coords,
const Span<int> looptri_indices,
MutableSpan<float3> r_normals)
{
Array<float3> corner_normals(mesh.totloop);
BKE_mesh_calc_normals_split_ex(
const_cast<Mesh *>(&mesh), nullptr, reinterpret_cast<float(*)[3]>(corner_normals.data()));
const Span<MLoopTri> looptris = mesh.looptris();
threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) {
for (const int i : range) {
const int looptri_index = looptri_indices[i];
const MLoopTri &looptri = looptris[looptri_index];
const float3 &bary_coord = bary_coords[i];
const float3 normal = math::normalize(
bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords(
bary_coord, looptri, corner_normals.as_span()));
r_normals[i] = normal;
}
});
}
static void compute_legacy_normal_outputs(const Mesh &mesh,
const Span<float3> bary_coords,
const Span<int> looptri_indices,
MutableSpan<float3> r_normals)
{
const Span<float3> positions = mesh.vert_positions();
const Span<MLoop> loops = mesh.loops();
const Span<MLoopTri> looptris = mesh.looptris();
for (const int i : bary_coords.index_range()) {
const int looptri_index = looptri_indices[i];
const MLoopTri &looptri = looptris[looptri_index];
const int v0_index = loops[looptri.tri[0]].v;
const int v1_index = loops[looptri.tri[1]].v;
const int v2_index = loops[looptri.tri[2]].v;
const float3 v0_pos = positions[v0_index];
const float3 v1_pos = positions[v1_index];
const float3 v2_pos = positions[v2_index];
float3 normal;
normal_tri_v3(normal, v0_pos, v1_pos, v2_pos);
r_normals[i] = normal;
}
}
static void compute_rotation_output(const Span<float3> normals, MutableSpan<float3> r_rotations)
{
threading::parallel_for(normals.index_range(), 256, [&](const IndexRange range) {
for (const int i : range) {
r_rotations[i] = normal_to_euler_rotation(normals[i]);
}
});
}
BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh,
PointCloud &points,
const Span<float3> bary_coords,
const Span<int> looptri_indices,
const AttributeOutputs &attribute_outputs)
const AttributeOutputs &attribute_outputs,
const bool use_legacy_normal)
{
MutableAttributeAccessor point_attributes = points.attributes_for_write();
@ -348,33 +415,24 @@ BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh,
attribute_outputs.rotation_id.get(), ATTR_DOMAIN_POINT);
}
const Span<float3> positions = mesh.vert_positions();
const Span<MLoop> loops = mesh.loops();
const Span<MLoopTri> looptris = mesh.looptris();
for (const int i : bary_coords.index_range()) {
threading::parallel_for(bary_coords.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
const int looptri_index = looptri_indices[i];
const MLoopTri &looptri = looptris[looptri_index];
const float3 &bary_coord = bary_coords[i];
const int v0_index = loops[looptri.tri[0]].v;
const int v1_index = loops[looptri.tri[1]].v;
const int v2_index = loops[looptri.tri[2]].v;
const float3 v0_pos = positions[v0_index];
const float3 v1_pos = positions[v1_index];
const float3 v2_pos = positions[v2_index];
ids.span[i] = noise::hash(noise::hash_float(bary_coord), looptri_index);
}
});
float3 normal;
if (!normals.span.is_empty() || !rotations.span.is_empty()) {
normal_tri_v3(normal, v0_pos, v1_pos, v2_pos);
if (normals) {
if (use_legacy_normal) {
compute_legacy_normal_outputs(mesh, bary_coords, looptri_indices, normals.span);
}
if (!normals.span.is_empty()) {
normals.span[i] = normal;
else {
compute_normal_outputs(mesh, bary_coords, looptri_indices, normals.span);
}
if (!rotations.span.is_empty()) {
rotations.span[i] = normal_to_euler_rotation(normal);
if (rotations) {
compute_rotation_output(normals.span, rotations.span);
}
}
@ -507,7 +565,9 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
propagate_existing_attributes(mesh, attributes, *pointcloud, bary_coords, looptri_indices);
compute_attribute_outputs(mesh, *pointcloud, bary_coords, looptri_indices, attribute_outputs);
const bool use_legacy_normal = params.node().custom2 != 0;
compute_attribute_outputs(
mesh, *pointcloud, bary_coords, looptri_indices, attribute_outputs, use_legacy_normal);
}
static void node_geo_exec(GeoNodeExecParams params)
@ -521,8 +581,9 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
AttributeOutputs attribute_outputs;
attribute_outputs.normal_id = params.get_output_anonymous_attribute_id_if_needed("Normal");
attribute_outputs.rotation_id = params.get_output_anonymous_attribute_id_if_needed("Rotation");
attribute_outputs.normal_id = params.get_output_anonymous_attribute_id_if_needed(
"Normal", bool(attribute_outputs.rotation_id));
lazy_threading::send_hint();
@ -567,5 +628,6 @@ void register_node_type_geo_distribute_points_on_faces()
ntype.declare = file_ns::node_declare;
ntype.geometry_node_execute = file_ns::node_geo_exec;
ntype.draw_buttons = file_ns::node_layout;
ntype.draw_buttons_ex = file_ns::node_layout_ex;
nodeRegisterType(&ntype);
}