Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/curves_geometry.cc
| Show All 25 Lines | |||||
| static const std::string ATTR_POSITION = "position"; | static const std::string ATTR_POSITION = "position"; | ||||
| static const std::string ATTR_RADIUS = "radius"; | static const std::string ATTR_RADIUS = "radius"; | ||||
| static const std::string ATTR_TILT = "tilt"; | static const std::string ATTR_TILT = "tilt"; | ||||
| static const std::string ATTR_CURVE_TYPE = "curve_type"; | static const std::string ATTR_CURVE_TYPE = "curve_type"; | ||||
| static const std::string ATTR_CYCLIC = "cyclic"; | static const std::string ATTR_CYCLIC = "cyclic"; | ||||
| static const std::string ATTR_RESOLUTION = "resolution"; | static const std::string ATTR_RESOLUTION = "resolution"; | ||||
| static const std::string ATTR_NORMAL_MODE = "normal_mode"; | 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_LEFT = "handle_type_left"; | ||||
| static const std::string ATTR_HANDLE_TYPE_RIGHT = "handle_type_right"; | static const std::string ATTR_HANDLE_TYPE_RIGHT = "handle_type_right"; | ||||
| static const std::string ATTR_HANDLE_POSITION_LEFT = "handle_left"; | static const std::string ATTR_HANDLE_POSITION_LEFT = "handle_left"; | ||||
| static const std::string ATTR_HANDLE_POSITION_RIGHT = "handle_right"; | static const std::string ATTR_HANDLE_POSITION_RIGHT = "handle_right"; | ||||
| static const std::string ATTR_NURBS_ORDER = "nurbs_order"; | static const std::string ATTR_NURBS_ORDER = "nurbs_order"; | ||||
| static const std::string ATTR_NURBS_WEIGHT = "nurbs_weight"; | static const std::string ATTR_NURBS_WEIGHT = "nurbs_weight"; | ||||
| static const std::string ATTR_NURBS_KNOTS_MODE = "knots_mode"; | static const std::string ATTR_NURBS_KNOTS_MODE = "knots_mode"; | ||||
| static const std::string ATTR_SURFACE_UV_COORDINATE = "surface_uv_coordinate"; | static const std::string ATTR_SURFACE_UV_COORDINATE = "surface_uv_coordinate"; | ||||
| ▲ Show 20 Lines • Show All 302 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| return get_varray_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NORMAL_MODE, 0); | return get_varray_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NORMAL_MODE, 0); | ||||
| } | } | ||||
| MutableSpan<int8_t> CurvesGeometry::normal_mode_for_write() | MutableSpan<int8_t> CurvesGeometry::normal_mode_for_write() | ||||
| { | { | ||||
| return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NORMAL_MODE); | 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 | VArray<float> CurvesGeometry::tilt() const | ||||
| { | { | ||||
| return get_varray_attribute<float>(*this, ATTR_DOMAIN_POINT, ATTR_TILT, 0.0f); | return get_varray_attribute<float>(*this, ATTR_DOMAIN_POINT, ATTR_TILT, 0.0f); | ||||
| } | } | ||||
| MutableSpan<float> CurvesGeometry::tilt_for_write() | MutableSpan<float> CurvesGeometry::tilt_for_write() | ||||
| { | { | ||||
| return get_mutable_attribute<float>(*this, ATTR_DOMAIN_POINT, ATTR_TILT); | return get_mutable_attribute<float>(*this, ATTR_DOMAIN_POINT, ATTR_TILT); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 286 Lines • ▼ Show 20 Lines | Span<float3> CurvesGeometry::evaluated_positions() const | ||||
| }); | }); | ||||
| return this->runtime->evaluated_positions_span; | return this->runtime->evaluated_positions_span; | ||||
| } | } | ||||
| Span<float3> CurvesGeometry::evaluated_tangents() const | Span<float3> CurvesGeometry::evaluated_tangents() const | ||||
| { | { | ||||
| this->runtime->tangent_cache_mutex.ensure([&]() { | this->runtime->tangent_cache_mutex.ensure([&]() { | ||||
| const Span<float3> evaluated_positions = this->evaluated_positions(); | const Span<float3> evaluated_positions = this->evaluated_positions(); | ||||
| Span<float3> positions = this->positions(); | |||||
| VArray<int> resolution = this->resolution(); | |||||
| const VArray<bool> cyclic = this->cyclic(); | const VArray<bool> cyclic = this->cyclic(); | ||||
| const VArray<int8_t> types = this->curve_types(); | |||||
| this->runtime->evaluated_tangent_cache.resize(this->evaluated_points_num()); | this->runtime->evaluated_tangent_cache.resize(this->evaluated_points_num()); | ||||
| MutableSpan<float3> tangents = this->runtime->evaluated_tangent_cache; | MutableSpan<float3> tangents = this->runtime->evaluated_tangent_cache; | ||||
| threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { | threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { | ||||
| for (const int curve_index : curves_range) { | for (const int curve_index : curves_range) { | ||||
| const IndexRange points = this->points_for_curve(curve_index); | |||||
| const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); | const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); | ||||
| switch (types[curve_index]) { | |||||
| case CURVE_TYPE_CATMULL_ROM: | |||||
| /* NOTE: this causes test geo_node_curves_test_sample_curves to fail. */ | |||||
| curves::catmull_rom::calculate_tangents(positions.slice(points), | |||||
| cyclic[curve_index], | |||||
| resolution[curve_index], | |||||
| tangents.slice(evaluated_points)); | |||||
| break; | |||||
| default: | |||||
| curves::poly::calculate_tangents(evaluated_positions.slice(evaluated_points), | curves::poly::calculate_tangents(evaluated_positions.slice(evaluated_points), | ||||
| cyclic[curve_index], | cyclic[curve_index], | ||||
| tangents.slice(evaluated_points)); | tangents.slice(evaluated_points)); | ||||
| break; | |||||
| } | |||||
| } | } | ||||
| }); | }); | ||||
| /* Correct the first and last tangents of non-cyclic Bezier curves so that they align with | /* Correct the first and last tangents of non-cyclic Bezier curves so that they align with | ||||
| * the inner handles. This is a separate loop to avoid the cost when Bezier type curves are | * the inner handles. This is a separate loop to avoid the cost when Bezier type curves are | ||||
| * not used. */ | * not used. */ | ||||
| Vector<int64_t> bezier_indices; | Vector<int64_t> bezier_indices; | ||||
| const IndexMask bezier_mask = this->indices_for_curve_type(CURVE_TYPE_BEZIER, bezier_indices); | const IndexMask bezier_mask = this->indices_for_curve_type(CURVE_TYPE_BEZIER, bezier_indices); | ||||
| Show All 20 Lines | if (!bezier_mask.is_empty()) { | ||||
| handles_left[points.last()], positions[points.last()], epsilon)) { | handles_left[points.last()], positions[points.last()], epsilon)) { | ||||
| tangents[evaluated_points.last()] = math::normalize(positions[points.last()] - | tangents[evaluated_points.last()] = math::normalize(positions[points.last()] - | ||||
| handles_left[points.last()]); | handles_left[points.last()]); | ||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| }); | }); | ||||
| return this->runtime->evaluated_tangent_cache; | return this->runtime->evaluated_tangent_cache; | ||||
| } | } | ||||
| static void rotate_directions_around_axes(MutableSpan<float3> directions, | static void rotate_directions_around_axes(MutableSpan<float3> directions, | ||||
| const Span<float3> axes, | const Span<float3> axes, | ||||
| const Span<float> angles) | const Span<float> angles) | ||||
| { | { | ||||
| for (const int i : directions.index_range()) { | for (const int i : directions.index_range()) { | ||||
| directions[i] = math::rotate_direction_around_axis(directions[i], axes[i], angles[i]); | directions[i] = math::rotate_direction_around_axis(directions[i], axes[i], angles[i]); | ||||
| } | } | ||||
| } | } | ||||
| Span<float3> CurvesGeometry::evaluated_normals() const | Span<float3> CurvesGeometry::evaluated_normals() const | ||||
| { | { | ||||
| this->runtime->normal_cache_mutex.ensure([&]() { | this->runtime->normal_cache_mutex.ensure([&]() { | ||||
| const Span<float3> evaluated_tangents = this->evaluated_tangents(); | const Span<float3> evaluated_tangents = this->evaluated_tangents(); | ||||
| const VArray<bool> cyclic = this->cyclic(); | 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> normal_mode = this->normal_mode(); | ||||
| const VArray<int8_t> types = this->curve_types(); | const VArray<int8_t> types = this->curve_types(); | ||||
| const VArray<float> tilt = this->tilt(); | const VArray<float> tilt = this->tilt(); | ||||
| this->runtime->evaluated_normal_cache.resize(this->evaluated_points_num()); | this->runtime->evaluated_normal_cache.resize(this->evaluated_points_num()); | ||||
| MutableSpan<float3> evaluated_normals = this->runtime->evaluated_normal_cache; | MutableSpan<float3> evaluated_normals = this->runtime->evaluated_normal_cache; | ||||
| threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { | threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { | ||||
| /* Reuse a buffer for the evaluated tilts. */ | /* Reuse a buffer for the evaluated tilts. */ | ||||
| Vector<float> evaluated_tilts; | Vector<float> evaluated_tilts; | ||||
| for (const int curve_index : curves_range) { | for (const int curve_index : curves_range) { | ||||
| const IndexRange points = this->points_for_curve(curve_index); | |||||
| const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); | const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); | ||||
| switch (normal_mode[curve_index]) { | switch (normal_mode[curve_index]) { | ||||
| case NORMAL_MODE_Z_UP: | case NORMAL_MODE_Z_UP: | ||||
| curves::poly::calculate_normals_z_up(evaluated_tangents.slice(evaluated_points), | curves::poly::calculate_normals_z_up(evaluated_tangents.slice(evaluated_points), | ||||
| evaluated_normals.slice(evaluated_points)); | evaluated_normals.slice(evaluated_points)); | ||||
| break; | break; | ||||
| case NORMAL_MODE_MINIMUM_TWIST: | case NORMAL_MODE_MINIMUM_TWIST: | ||||
| curves::poly::calculate_normals_minimum(evaluated_tangents.slice(evaluated_points), | curves::poly::calculate_normals_minimum(evaluated_tangents.slice(evaluated_points), | ||||
| cyclic[curve_index], | cyclic[curve_index], | ||||
| evaluated_normals.slice(evaluated_points)); | evaluated_normals.slice(evaluated_points)); | ||||
| break; | break; | ||||
| case NORMAL_MODE_CURVATURE_VECTOR: | |||||
| switch (types[curve_index]) { | |||||
| case CURVE_TYPE_CATMULL_ROM: | |||||
| curves::catmull_rom::calculate_normals(positions.slice(points), | |||||
| cyclic[curve_index], | |||||
| resolution[curve_index], | |||||
| weight[curve_index], | |||||
| evaluated_normals.slice(evaluated_points)); | |||||
| break; | |||||
| default: | |||||
| curves::poly::calculate_curvature_vectors( | |||||
| positions.slice(points), | |||||
| evaluated_tangents.slice(evaluated_points), | |||||
| cyclic[curve_index], | |||||
| evaluated_normals.slice(evaluated_points)); | |||||
| break; | |||||
| } | |||||
| break; | |||||
| } | } | ||||
| /* If the "tilt" attribute exists, rotate the normals around the tangents by the | /* If the "tilt" attribute exists, rotate the normals around the tangents by the | ||||
| * evaluated angles. We can avoid copying the tilts to evaluate them for poly curves. */ | * evaluated angles. We can avoid copying the tilts to evaluate them for poly curves. */ | ||||
| if (!(tilt.is_single() && tilt.get_internal_single() == 0.0f)) { | if (!(tilt.is_single() && tilt.get_internal_single() == 0.0f)) { | ||||
| const IndexRange points = this->points_for_curve(curve_index); | const IndexRange points = this->points_for_curve(curve_index); | ||||
| Span<float> curve_tilt = tilt.get_internal_span().slice(points); | Span<float> curve_tilt = tilt.get_internal_span().slice(points); | ||||
| if (types[curve_index] == CURVE_TYPE_POLY) { | if (types[curve_index] == CURVE_TYPE_POLY) { | ||||
| ▲ Show 20 Lines • Show All 772 Lines • Show Last 20 Lines | |||||