forked from blender/blender
me-main #1
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user