[Bf-blender-cvs] [c1cab4aa685] temp-geometry-nodes-fields--fields-jacques: add common base class for field input/operation

Jacques Lucke noreply at git.blender.org
Wed Sep 1 11:39:26 CEST 2021


Commit: c1cab4aa685fa40bc98fcf4c94f25000ec810315
Author: Jacques Lucke
Date:   Wed Sep 1 11:39:18 2021 +0200
Branches: temp-geometry-nodes-fields--fields-jacques
https://developer.blender.org/rBc1cab4aa685fa40bc98fcf4c94f25000ec810315

add common base class for field input/operation

===================================================================

M	source/blender/functions/FN_field.hh
M	source/blender/functions/intern/field.cc
M	source/blender/functions/tests/FN_field_test.cc
M	source/blender/modifiers/intern/MOD_nodes_evaluator.cc
M	source/blender/nodes/NOD_geometry_exec.hh

===================================================================

diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 4b0dee88491..9217d98d75b 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -41,69 +41,57 @@
 
 namespace blender::fn {
 
-class FieldInput;
-class FieldFunction;
+class FieldSource {
+ public:
+  ~FieldSource() = default;
+
+  virtual const CPPType &cpp_type_of_output_index(int output_index) const = 0;
+
+  virtual bool is_input() const
+  {
+    return false;
+  }
+};
 
 /**
  * Descibes the output of a function. Generally corresponds to the combination of an output socket
  * and link combination in a node graph.
  */
 class GField {
-  /**
-   * The function that calculates this field's values. Many fields can share the same function,
-   * since a function can have many outputs, just like a node graph, where a single output can be
-   * used as multiple inputs. This avoids calling the same function many times, only using one of
-   * its results.
-   */
-  std::shared_ptr<FieldFunction> function_;
-  /**
-   * Which output of the function this field corresponds to.
-   */
-  int output_index_ = 0;
-
-  std::shared_ptr<FieldInput> input_;
+  std::shared_ptr<FieldSource> source_;
+  int source_output_index_ = 0;
 
  public:
   GField() = default;
 
-  GField(std::shared_ptr<FieldFunction> function, const int output_index)
-      : function_(std::move(function)), output_index_(output_index)
+  GField(std::shared_ptr<FieldSource> source, const int source_output_index = 0)
+      : source_(std::move(source)), source_output_index_(source_output_index)
   {
   }
 
-  GField(std::shared_ptr<FieldInput> input) : input_(std::move(input))
+  operator bool() const
   {
+    return source_ != nullptr;
   }
 
-  const fn::CPPType &cpp_type() const;
-
-  bool is_input() const
-  {
-    return input_.get() != nullptr;
-  }
-  const FieldInput &input() const
+  const fn::CPPType &cpp_type() const
   {
-    BLI_assert(!function_);
-    BLI_assert(input_);
-    return *input_;
+    return source_->cpp_type_of_output_index(source_output_index_);
   }
 
-  bool is_function() const
+  bool is_input() const
   {
-    return function_.get() != nullptr;
+    return source_->is_input();
   }
-  const FieldFunction &function() const
+
+  const FieldSource &source() const
   {
-    BLI_assert(function_ != nullptr);
-    BLI_assert(input_ == nullptr);
-    return *function_;
+    return *source_;
   }
 
-  int function_output_index() const
+  int source_output_index() const
   {
-    BLI_assert(function_ != nullptr);
-    BLI_assert(input_ == nullptr);
-    return output_index_;
+    return source_output_index_;
   }
 };
 
@@ -117,30 +105,20 @@ template<typename T> class Field : public GField {
   }
 };
 
-/**
- * An operation acting on data described by fields. Generally corresponds
- * to a node or a subset of a node in a node graph.
- */
-class FieldFunction {
-  /**
-   * The function used to calculate the field.
-   */
+class FieldOperation : public FieldSource {
   std::unique_ptr<const MultiFunction> owned_function_;
   const MultiFunction *function_;
 
-  /**
-   * References to descriptions of the results from the functions this function depends on.
-   */
   blender::Vector<GField> inputs_;
 
  public:
-  FieldFunction(std::unique_ptr<const MultiFunction> function, Vector<GField> inputs = {})
+  FieldOperation(std::unique_ptr<const MultiFunction> function, Vector<GField> inputs = {})
       : owned_function_(std::move(function)), inputs_(std::move(inputs))
   {
     function_ = owned_function_.get();
   }
 
-  FieldFunction(const MultiFunction &function, Vector<GField> inputs = {})
+  FieldOperation(const MultiFunction &function, Vector<GField> inputs = {})
       : function_(&function), inputs_(std::move(inputs))
   {
   }
@@ -155,7 +133,7 @@ class FieldFunction {
     return *function_;
   }
 
-  const CPPType &cpp_type_of_output_index(int output_index) const
+  const CPPType &cpp_type_of_output_index(int output_index) const override
   {
     int output_counter = 0;
     for (const int param_index : function_->param_indices()) {
@@ -172,7 +150,7 @@ class FieldFunction {
   }
 };
 
-class FieldInput {
+class FieldInput : public FieldSource {
  protected:
   const CPPType *type_;
   std::string debug_name_;
@@ -194,6 +172,17 @@ class FieldInput {
   {
     return *type_;
   }
+
+  const CPPType &cpp_type_of_output_index(int output_index) const override
+  {
+    BLI_assert(output_index == 0);
+    return *type_;
+  }
+
+  bool is_input() const override
+  {
+    return true;
+  }
 };
 
 /**
@@ -216,20 +205,8 @@ template<typename T> T evaluate_constant_field(const Field<T> &field)
 template<typename T> Field<T> make_constant_field(T value)
 {
   auto constant_fn = std::make_unique<fn::CustomMF_Constant<T>>(std::forward<T>(value));
-  auto field_fn = std::make_shared<FieldFunction>(std::move(constant_fn));
-  return Field<T>{GField{std::move(field_fn), 0}};
-}
-
-/* --------------------------------------------------------------------
- * GField inline methods.
- */
-
-inline const CPPType &GField::cpp_type() const
-{
-  if (this->is_function()) {
-    return function_->cpp_type_of_output_index(output_index_);
-  }
-  return input_->cpp_type();
+  auto operation = std::make_shared<FieldOperation>(std::move(constant_fn));
+  return Field<T>{GField{std::move(operation), 0}};
 }
 
 }  // namespace blender::fn
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index 69a31699592..87cfc60d502 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -20,60 +20,12 @@
 
 #include "FN_field.hh"
 
-/**
- * TODO: There might be a more obvious way to implement this, or we might end up with
- * a separate map for functions and inputs anyway, so we could just remove it.
- */
-struct InputOrFunction {
-  const void *ptr;
-
- public:
-  InputOrFunction(const blender::fn::FieldFunction &function) : ptr(&function)
-  {
-  }
-  InputOrFunction(const blender::fn::FieldInput &input) : ptr(&input)
-  {
-  }
-  InputOrFunction(const blender::fn::GField &field) /* Maybe this is too clever. */
-  {
-    if (field.is_function()) {
-      ptr = &field.function();
-    }
-    else {
-      ptr = &field.input();
-    }
-  }
-  friend bool operator==(const InputOrFunction &a, const InputOrFunction &b)
-  {
-    return a.ptr == b.ptr;
-  }
-};
-
-template<> struct blender::DefaultHash<InputOrFunction> {
-  uint64_t operator()(const InputOrFunction &value) const
-  {
-    return DefaultHash<const void *>{}(value.ptr);
-  }
-};
-
 namespace blender::fn {
 
-/**
- * TODO: This exists because it seemed helpful for the procedure creation to be able to store
- * mutable data for each input or function output. That still may be helpful in the future, but
- * currently it isn't useful.
- */
-struct FieldVariable {
-  MFVariable *mf_variable;
-  FieldVariable(MFVariable &variable) : mf_variable(&variable)
-  {
-  }
-};
-
 /**
  * A map to hold the output variables for each function output or input so they can be reused.
  */
-using VariableMap = Map<InputOrFunction, Vector<FieldVariable>>;
+using VariableMap = Map<const FieldSource *, Vector<MFVariable *>>;
 
 /**
  * A map of the computed inputs for all of a field system's inputs, to avoid creating duplicates.
@@ -81,27 +33,27 @@ using VariableMap = Map<InputOrFunction, Vector<FieldVariable>>;
  */
 using ComputedInputMap = Map<const MFVariable *, GVArrayPtr>;
 
-static FieldVariable &get_field_variable(const GField &field, VariableMap &unique_variables)
+static MFVariable &get_field_variable(const GField &field, VariableMap &unique_variables)
 {
   if (field.is_input()) {
-    const FieldInput &input = field.input();
-    return unique_variables.lookup(input).first();
+    const FieldInput &input = dynamic_cast<const FieldInput &>(field.source());
+    return *unique_variables.lookup(&input).first();
   }
-  const FieldFunction &function = field.function();
-  MutableSpan<FieldVariable> function_outputs = unique_variables.lookup(function);
-  return function_outputs[field.function_output_index()];
+  const FieldOperation &operation = dynamic_cast<const FieldOperation &>(field.source());
+  MutableSpan<MFVariable *> operation_outputs = unique_variables.lookup(&operation);
+  return *operation_outputs[field.source_output_index()];
 }
 
-static const FieldVariable &get_field_variable(const GField &field,
-                                               const VariableMap &unique_variables)
+static const MFVariable &get_field_variable(const GField &field,
+                                            const VariableMap &unique_variables)
 {
   if (field.is_input()) {
-    const FieldInput &input = field.input();
-    return unique_variables.lookup(input).first();
+    const FieldInput &input = dynamic_cast<const FieldInput &>(field.source());
+    return *unique_variables.lookup(&input).first();
   }
-  const FieldFunction &function = field.function();
-  Span<FieldVariable> function_outputs = unique_variables.lookup(function);
-  return function_outputs[field.function_output_index()];
+  const FieldOperation &operation = dynamic_cast<const FieldOperation &>(field.source());
+  Span<MFVariable *> operation_outputs = unique_variables.lookup(&operation);
+  return *operation_outputs[field.source_output_index()];
 }
 
 /**
@@ -113,20 +65,20 @@ static void add_variables_for_input(const GField &field,
                                     VariableMap &unique_variables)
 {
   fields_to_visit.pop();
-  const FieldInput &input = field.input();
+  const FieldInput &input = dynamic_cast<const FieldInput &>(field.source());
   MFVariable &variable = builder.add_input_parameter(MFDataType::ForSingle(field.cpp_type()),
                                                      input.debug_name());
-  unique_variables.add(input, {variable});
+  unique_variables.add(&input, {&variable});
 }
 
-static void add_variables_for_function(const GField &field,
-                                       Stack<const GField *> &fields_to_visit,
-                                       MFProcedureBuilder &builder,
-                                       VariableMa

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list