[Bf-blender-cvs] [8ee7e626a5a] microfacet_hair: Interpolate between the curvature vector and the minimal twist vector with custom weight
Weizhen Huang
noreply at git.blender.org
Mon Jan 9 17:33:11 CET 2023
Commit: 8ee7e626a5a6e4b5471fc1bddb508d77f072e0c2
Author: Weizhen Huang
Date: Mon Jan 9 17:32:17 2023 +0100
Branches: microfacet_hair
https://developer.blender.org/rB8ee7e626a5a6e4b5471fc1bddb508d77f072e0c2
Interpolate between the curvature vector and the minimal twist vector
with custom weight
===================================================================
M source/blender/blenkernel/BKE_curves.hh
M source/blender/blenkernel/intern/curve_catmull_rom.cc
M source/blender/blenkernel/intern/curves_geometry.cc
M source/blender/makesrna/intern/rna_curves.c
M source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 14aa854a4f2..2aa1e3b5156 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -242,6 +242,13 @@ class CurvesGeometry : public ::CurvesGeometry {
VArray<int8_t> normal_mode() const;
MutableSpan<int8_t> normal_mode_for_write();
+ /**
+ * Used for normal mode curvature vector, specifying the weight as opposed to the minimal twist
+ * normal.
+ */
+ VArray<float> curvature_vector_weight() const;
+ MutableSpan<float> curvature_vector_weight_for_write();
+
/**
* Handle types for Bezier control points. Call #tag_topology_changed after changes.
*/
@@ -707,6 +714,7 @@ void calculate_tangents(Span<float3> positions,
void calculate_normals(Span<float3> positions,
bool is_cyclic,
int resolution,
+ float weight_bending,
MutableSpan<float3> normals);
/**
diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc
index a93b90ea598..fa2fe01c0b0 100644
--- a/source/blender/blenkernel/intern/curve_catmull_rom.cc
+++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc
@@ -251,6 +251,7 @@ static float find_root_newton_bisection(float x_begin,
void calculate_normals(const Span<float3> positions,
const bool is_cyclic,
const int resolution,
+ const float weight_bending,
MutableSpan<float3> evaluated_normals)
{
if (evaluated_normals.size() == 1) {
@@ -258,6 +259,8 @@ void calculate_normals(const Span<float3> positions,
return;
}
+ const float weight_twist = 1.0f - clamp_f(weight_bending, 0.0f, 1.0f);
+
/* TODO: check if derivatives == 0.*/
Vector<float3> first_derivatives_(evaluated_normals.size());
MutableSpan<float3> first_derivatives = first_derivatives_;
@@ -265,21 +268,35 @@ void calculate_normals(const Span<float3> positions,
Vector<float3> second_derivatives_(evaluated_normals.size());
MutableSpan<float3> second_derivatives = second_derivatives_;
- interpolate_to_evaluated(2, positions, is_cyclic, resolution, second_derivatives);
-
- /* TODO: below are hair-specific values, assuming elliptical cross-section. Maybe make them more
- * general by specifying user-defined weight? */
- /* Values taken from Table 9.5 in book Chemical and Physical Behavior of Human Hair by Clarence
- * R. Robbins, 5th edition. Unit: GPa. */
- const float youngs_modulus = 3.89f;
- const float shear_modulus = 0.89f;
- /* Assuming major axis a = 1. */
- const float aspect_ratio = 0.5f; /* Minimal realistic value. */
- const float aspect_ratio_squared = aspect_ratio * aspect_ratio;
- const float torsion_constant = M_PI * aspect_ratio_squared * aspect_ratio /
- (1.0f + aspect_ratio_squared);
- const float moment_of_inertia_coefficient = M_PI * aspect_ratio * 0.25f *
- (1.0f - aspect_ratio_squared);
+ if (weight_twist < 1.0f) {
+ interpolate_to_evaluated(2, positions, is_cyclic, resolution, second_derivatives);
+ }
+ else {
+ /* TODO: Actually only the first entry needs to be evaluated. */
+ interpolate_to_evaluated(
+ 2,
+ positions,
+ is_cyclic,
+ [resolution](const int segment_i) -> IndexRange {
+ return {segment_i * resolution, 1};
+ },
+ second_derivatives);
+ }
+
+ /* Hair-specific values, taken from Table 9.5 in book Chemical and Physical Behavior of Human
+ * Hair by Clarence R. Robbins, 5th edition. Unit: GPa. */
+ // const float youngs_modulus = 3.89f;
+ // const float shear_modulus = 0.89f;
+ // /* Assuming major axis a = 1. */
+ // const float aspect_ratio = 0.5f; /* Minimal realistic value. */
+ // const float aspect_ratio_squared = aspect_ratio * aspect_ratio;
+ // const float torsion_constant = M_PI * aspect_ratio_squared * aspect_ratio /
+ // (1.0f + aspect_ratio_squared);
+ // const float moment_of_inertia_coefficient = M_PI * aspect_ratio * 0.25f *
+ // (1.0f - aspect_ratio_squared);
+
+ // const float weight_bending = 0.5f * youngs_modulus * moment_of_inertia_coefficient;
+ // const float weight_twist = 0.5f * shear_modulus * torsion_constant;
const float dt = 1.0f / resolution;
/* Compute evaluated_normals. */
@@ -296,15 +313,15 @@ void calculate_normals(const Span<float3> positions,
continue;
}
- const float first_derivative_norm = math::length(first_derivatives[i]);
- /* Arc length depends on the unit, assuming meter. */
- const float arc_length = first_derivative_norm * dt;
- const float curvature = math::length(binormal) / pow3f(first_derivative_norm);
-
- const float weight_twist = 0.5f * shear_modulus * torsion_constant / arc_length;
- const float weight_bending = 0.5f * arc_length * curvature * curvature * youngs_modulus *
- moment_of_inertia_coefficient;
+ if (weight_twist == 0.0f) {
+ if (angle_normalized_v3v3(curvature_vector, evaluated_normals[i - 1]) < 0) {
+ curvature_vector = -curvature_vector;
+ }
+ evaluated_normals[i] = curvature_vector;
+ continue;
+ }
+ const float first_derivative_norm = math::length(first_derivatives[i]);
const float3 last_tangent = math::normalize(first_derivatives[i - 1]);
const float3 current_tangent = first_derivatives[i] / first_derivative_norm;
const float angle = angle_normalized_v3v3(last_tangent, current_tangent);
@@ -315,6 +332,18 @@ void calculate_normals(const Span<float3> positions,
last_normal, math::normalize(math::cross(last_tangent, current_tangent)), angle) :
last_normal;
+ if (weight_twist == 1.0f) {
+ evaluated_normals[i] = minimal_twist_normal;
+ continue;
+ }
+
+ /* Arc length depends on the unit, assuming meter. */
+ const float arc_length = first_derivative_norm * dt;
+ const float curvature = math::length(binormal) / pow3f(first_derivative_norm);
+
+ const float coefficient_twist = weight_twist / arc_length;
+ const float coefficient_bending = weight_bending * arc_length * curvature * curvature;
+
/* Angle between the curvature vector and the minimal twist normal. */
float theta_t = angle_normalized_v3v3(curvature_vector, minimal_twist_normal);
if (theta_t > M_PI_2) {
@@ -326,18 +355,18 @@ void calculate_normals(const Span<float3> positions,
* equation: 2 * wt * (θ - θt) + wb * sin(2θ) = 0, with θ being the angle between the computed
* normal and the curvature vector. */
const float theta_begin = 0.0f;
- const float theta_end = weight_twist + weight_bending * cosf(2.0f * theta_t) < 0 ?
- 0.5f * acosf(-weight_twist / weight_bending) :
+ const float theta_end = coefficient_twist + coefficient_bending * cosf(2.0f * theta_t) < 0 ?
+ 0.5f * acosf(-coefficient_twist / coefficient_bending) :
theta_t;
const float theta = find_root_newton_bisection(
theta_begin,
theta_end,
- [weight_bending, weight_twist, theta_t](float t) -> float {
- return 2.0f * weight_twist * (t - theta_t) + weight_bending * sinf(2.0f * t);
+ [coefficient_bending, coefficient_twist, theta_t](float t) -> float {
+ return 2.0f * coefficient_twist * (t - theta_t) + coefficient_bending * sinf(2.0f * t);
},
- [weight_bending, weight_twist](float t) -> float {
- return 2.0f * (weight_twist + weight_bending * cosf(2.0f * t));
+ [coefficient_bending, coefficient_twist](float t) -> float {
+ return 2.0f * (coefficient_twist + coefficient_bending * cosf(2.0f * t));
},
1e-5f);
@@ -347,6 +376,8 @@ void calculate_normals(const Span<float3> positions,
-current_tangent;
evaluated_normals[i] = math::rotate_direction_around_axis(curvature_vector, axis, theta);
}
+
+ /* TODO: correct normals along the cyclic curve. */
}
} // namespace blender::bke::curves::catmull_rom
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 10325c0bed0..1ea8eb4ab18 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -31,6 +31,7 @@ static const std::string ATTR_CURVE_TYPE = "curve_type";
static const std::string ATTR_CYCLIC = "cyclic";
static const std::string ATTR_RESOLUTION = "resolution";
static const std::string ATTR_NORMAL_MODE = "normal_mode";
+static const std::string ATTR_CURVATURE_VECTOR_WEIGHT = "curvature_vector_weight";
static const std::string ATTR_HANDLE_TYPE_LEFT = "handle_type_left";
static const std::string ATTR_HANDLE_TYPE_RIGHT = "handle_type_right";
static const std::string ATTR_HANDLE_POSITION_LEFT = "handle_left";
@@ -349,6 +350,15 @@ MutableSpan<int8_t> CurvesGeometry::normal_mode_for_write()
return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NORMAL_MODE);
}
+VArray<float> CurvesGeometry::curvature_vector_weight() const
+{
+ return get_varray_attribute<float>(*this, ATTR_DOMAIN_CURVE, ATTR_CURVATURE_VECTOR_WEIGHT, 0.8f);
+}
+MutableSpan<float> CurvesGeometry::curvature_vector_weight_for_write()
+{
+ return get_mutable_attribute<float>(*this, ATTR_DOMAIN_CURVE, ATTR_CURVATURE_VECTOR_WEIGHT);
+}
+
VArray<float> CurvesGeometry::tilt() const
{
return get_varray_attribute<float>(*this, ATTR_DOMAIN_POINT, ATTR_TILT, 0.0f);
@@ -733,6 +743,7 @@ Span<float3> CurvesGeometry::evaluated_normals() const
const VArray<bool> cyclic = this->cyclic();
Span<float3> positions = this->positions();
VArray<int> resolution = this->resolution();
+ const VArray<float> weight = this->curvature_vector_weight();
const VArray<int8_t> normal_mode = this->normal_mode();
const VArray<int8_t> types = this->curve_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list