Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/curve_eval.cc')
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc237
1 files changed, 237 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
new file mode 100644
index 00000000000..19bbd8178b7
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -0,0 +1,237 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_array.hh"
+#include "BLI_listbase.h"
+#include "BLI_span.hh"
+
+#include "DNA_curve_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_spline.hh"
+
+using blender::Array;
+using blender::float3;
+using blender::float4x4;
+using blender::Span;
+
+blender::Span<SplinePtr> CurveEval::splines() const
+{
+ return splines_;
+}
+
+blender::MutableSpan<SplinePtr> CurveEval::splines()
+{
+ return splines_;
+}
+
+void CurveEval::add_spline(SplinePtr spline)
+{
+ splines_.append(std::move(spline));
+}
+
+void CurveEval::remove_splines(blender::IndexMask mask)
+{
+ for (int i = mask.size() - 1; i >= 0; i--) {
+ splines_.remove_and_reorder(mask.indices()[i]);
+ }
+}
+
+CurveEval *CurveEval::copy()
+{
+ CurveEval *new_curve = new CurveEval();
+
+ for (SplinePtr &spline : this->splines()) {
+ new_curve->add_spline(spline->copy());
+ }
+
+ return new_curve;
+}
+
+void CurveEval::translate(const float3 &translation)
+{
+ for (SplinePtr &spline : this->splines()) {
+ spline->translate(translation);
+ spline->mark_cache_invalid();
+ }
+}
+
+void CurveEval::transform(const float4x4 &matrix)
+{
+ for (SplinePtr &spline : this->splines()) {
+ spline->transform(matrix);
+ }
+}
+
+void CurveEval::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) const
+{
+ for (const SplinePtr &spline : this->splines()) {
+ spline->bounds_min_max(min, max, use_evaluated);
+ }
+}
+
+/**
+ * Return the start indices for each of the curve spline's evaluated points, as if they were part
+ * of a flattened array. This can be used to facilitate parallelism by avoiding the need to
+ * accumulate an offset while doing more complex calculations.
+ *
+ * \note The result array is one longer than the spline count; the last element is the total size.
+ */
+blender::Array<int> CurveEval::control_point_offsets() const
+{
+ Array<int> offsets(splines_.size() + 1);
+ int offset = 0;
+ for (const int i : splines_.index_range()) {
+ offsets[i] = offset;
+ offset += splines_[i]->size();
+ }
+ offsets.last() = offset;
+ return offsets;
+}
+
+/**
+ * Exactly like #control_point_offsets, but uses the number of evaluated points instead.
+ */
+blender::Array<int> CurveEval::evaluated_point_offsets() const
+{
+ Array<int> offsets(splines_.size() + 1);
+ int offset = 0;
+ for (const int i : splines_.index_range()) {
+ offsets[i] = offset;
+ offset += splines_[i]->evaluated_points_size();
+ }
+ offsets.last() = offset;
+ return offsets;
+}
+
+static BezierSpline::HandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
+{
+ switch (dna_handle_type) {
+ case HD_FREE:
+ return BezierSpline::HandleType::Free;
+ case HD_AUTO:
+ return BezierSpline::HandleType::Auto;
+ case HD_VECT:
+ return BezierSpline::HandleType::Vector;
+ case HD_ALIGN:
+ return BezierSpline::HandleType::Align;
+ case HD_AUTO_ANIM:
+ return BezierSpline::HandleType::Auto;
+ case HD_ALIGN_DOUBLESIDE:
+ return BezierSpline::HandleType::Align;
+ }
+ BLI_assert_unreachable();
+ return BezierSpline::HandleType::Auto;
+}
+
+static Spline::NormalCalculationMode normal_mode_from_dna_curve(const int twist_mode)
+{
+ switch (twist_mode) {
+ case CU_TWIST_Z_UP:
+ return Spline::NormalCalculationMode::ZUp;
+ case CU_TWIST_MINIMUM:
+ return Spline::NormalCalculationMode::Minimum;
+ case CU_TWIST_TANGENT:
+ return Spline::NormalCalculationMode::Tangent;
+ }
+ BLI_assert_unreachable();
+ return Spline::NormalCalculationMode::Minimum;
+}
+
+static NURBSpline::KnotsMode knots_mode_from_dna_nurb(const short flag)
+{
+ switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
+ case CU_NURB_ENDPOINT:
+ return NURBSpline::KnotsMode::EndPoint;
+ case CU_NURB_BEZIER:
+ return NURBSpline::KnotsMode::Bezier;
+ default:
+ return NURBSpline::KnotsMode::Normal;
+ }
+
+ BLI_assert_unreachable();
+ return NURBSpline::KnotsMode::Normal;
+}
+
+std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
+{
+ std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
+
+ const ListBase *nurbs = BKE_curve_nurbs_get(&const_cast<Curve &>(dna_curve));
+
+ /* TODO: Optimize by reserving the correct points size. */
+ LISTBASE_FOREACH (const Nurb *, nurb, nurbs) {
+ switch (nurb->type) {
+ case CU_BEZIER: {
+ std::unique_ptr<BezierSpline> spline = std::make_unique<BezierSpline>();
+ spline->set_resolution(nurb->resolu);
+ spline->set_cyclic(nurb->flagu & CU_NURB_CYCLIC);
+
+ for (const BezTriple &bezt : Span(nurb->bezt, nurb->pntsu)) {
+ spline->add_point(bezt.vec[1],
+ handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h1),
+ bezt.vec[0],
+ handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h2),
+ bezt.vec[2],
+ bezt.radius,
+ bezt.tilt);
+ }
+
+ curve->add_spline(std::move(spline));
+ break;
+ }
+ case CU_NURBS: {
+ std::unique_ptr<NURBSpline> spline = std::make_unique<NURBSpline>();
+ spline->set_resolution(nurb->resolu);
+ spline->set_cyclic(nurb->flagu & CU_NURB_CYCLIC);
+ spline->set_order(nurb->orderu);
+ spline->knots_mode = knots_mode_from_dna_nurb(nurb->flagu);
+
+ for (const BPoint &bp : Span(nurb->bp, nurb->pntsu)) {
+ spline->add_point(bp.vec, bp.radius, bp.tilt, bp.vec[3]);
+ }
+
+ curve->add_spline(std::move(spline));
+ break;
+ }
+ case CU_POLY: {
+ std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
+ spline->set_cyclic(nurb->flagu & CU_NURB_CYCLIC);
+
+ for (const BPoint &bp : Span(nurb->bp, nurb->pntsu)) {
+ spline->add_point(bp.vec, bp.radius, bp.tilt);
+ }
+
+ curve->add_spline(std::move(spline));
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+ }
+
+ /* Note: Normal mode is stored separately in each spline to facilitate combining splines
+ * from multiple curve objects, where the value may be different. */
+ const Spline::NormalCalculationMode normal_mode = normal_mode_from_dna_curve(
+ dna_curve.twist_mode);
+ for (SplinePtr &spline : curve->splines()) {
+ spline->normal_mode = normal_mode;
+ }
+
+ return curve;
+}