forked from blender/blender
me-main #1
@ -25,7 +25,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Blender file format version. */
|
/* Blender file format version. */
|
||||||
#define BLENDER_FILE_VERSION BLENDER_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
|
/* 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
|
* 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.
|
* 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_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_ui_text(prop, "Distribution Method", "Method to use for scattering points");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
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)
|
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);
|
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)
|
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));
|
bNodeSocket *sock_distance_min = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
|
||||||
@ -325,11 +330,73 @@ struct AttributeOutputs {
|
|||||||
};
|
};
|
||||||
} // namespace
|
} // 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,
|
BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh,
|
||||||
PointCloud &points,
|
PointCloud &points,
|
||||||
const Span<float3> bary_coords,
|
const Span<float3> bary_coords,
|
||||||
const Span<int> looptri_indices,
|
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();
|
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);
|
attribute_outputs.rotation_id.get(), ATTR_DOMAIN_POINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Span<float3> positions = mesh.vert_positions();
|
threading::parallel_for(bary_coords.index_range(), 1024, [&](const IndexRange range) {
|
||||||
const Span<MLoop> loops = mesh.loops();
|
for (const int i : range) {
|
||||||
const Span<MLoopTri> looptris = mesh.looptris();
|
|
||||||
|
|
||||||
for (const int i : bary_coords.index_range()) {
|
|
||||||
const int looptri_index = looptri_indices[i];
|
const int looptri_index = looptri_indices[i];
|
||||||
const MLoopTri &looptri = looptris[looptri_index];
|
|
||||||
const float3 &bary_coord = bary_coords[i];
|
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);
|
ids.span[i] = noise::hash(noise::hash_float(bary_coord), looptri_index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
float3 normal;
|
if (normals) {
|
||||||
if (!normals.span.is_empty() || !rotations.span.is_empty()) {
|
if (use_legacy_normal) {
|
||||||
normal_tri_v3(normal, v0_pos, v1_pos, v2_pos);
|
compute_legacy_normal_outputs(mesh, bary_coords, looptri_indices, normals.span);
|
||||||
}
|
}
|
||||||
if (!normals.span.is_empty()) {
|
else {
|
||||||
normals.span[i] = normal;
|
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);
|
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)
|
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");
|
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
|
||||||
|
|
||||||
AttributeOutputs attribute_outputs;
|
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.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();
|
lazy_threading::send_hint();
|
||||||
|
|
||||||
@ -567,5 +628,6 @@ void register_node_type_geo_distribute_points_on_faces()
|
|||||||
ntype.declare = file_ns::node_declare;
|
ntype.declare = file_ns::node_declare;
|
||||||
ntype.geometry_node_execute = file_ns::node_geo_exec;
|
ntype.geometry_node_execute = file_ns::node_geo_exec;
|
||||||
ntype.draw_buttons = file_ns::node_layout;
|
ntype.draw_buttons = file_ns::node_layout;
|
||||||
|
ntype.draw_buttons_ex = file_ns::node_layout_ex;
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user