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:
authorJohnny Matthews <johnny.matthews@gmail.com>2021-12-01 18:36:25 +0300
committerJohnny Matthews <johnny.matthews@gmail.com>2021-12-01 18:36:25 +0300
commit17578408434fafd2463ed253eebb5cb1412a6c67 (patch)
tree7052f46de29ed0d7180c00d2a8b64c03c4941995 /source/blender/nodes/function/nodes/node_fn_compare.cc
parentf8dd03d3dd1b2d7f0ade7c209092212098c75cb4 (diff)
Geometry Nodes: Generalized Compare Node
Replace compare floats node with a generalized compare node. The node allows for the comparison of float, int, string, color, and vector. The datatypes support the following operators: Float, Int: <, >, <=, >=, ==, != String: ==, != Color: ==, !=, lighter, darker (using rgb_to_grayscale value as the brightness value) Vector Supports 5 comparison modes for: ==, !=, <, >, <=, >= Average: The average of the components of the vectors are compared. Dot Product: The dot product of the vectors are compared. Direction: The angle between the vectors is compared to an angle Element-wise: The individual components of the vectors are compared. Length: The lengths of the vectors are compared. Differential Revision: https://developer.blender.org/D13228
Diffstat (limited to 'source/blender/nodes/function/nodes/node_fn_compare.cc')
-rw-r--r--source/blender/nodes/function/nodes/node_fn_compare.cc490
1 files changed, 490 insertions, 0 deletions
diff --git a/source/blender/nodes/function/nodes/node_fn_compare.cc b/source/blender/nodes/function/nodes/node_fn_compare.cc
new file mode 100644
index 00000000000..5acd4ae1466
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_compare.cc
@@ -0,0 +1,490 @@
+/*
+ * 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 <cmath>
+
+//#include "node_geometry_util.hh"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_enum_types.h"
+
+#include "node_function_util.hh"
+
+namespace blender::nodes::node_fn_compare_cc {
+
+static void fn_node_compare_declare(NodeDeclarationBuilder &b)
+{
+ b.is_function_node();
+ b.add_input<decl::Float>(N_("A")).min(-10000.0f).max(10000.0f);
+ b.add_input<decl::Float>(N_("B")).min(-10000.0f).max(10000.0f);
+
+ b.add_input<decl::Int>(N_("A"), "A_INT");
+ b.add_input<decl::Int>(N_("B"), "B_INT");
+
+ b.add_input<decl::Vector>(N_("A"), "A_VEC3");
+ b.add_input<decl::Vector>(N_("B"), "B_VEC3");
+
+ b.add_input<decl::Color>(N_("A"), "A_COL");
+ b.add_input<decl::Color>(N_("B"), "B_COL");
+
+ b.add_input<decl::String>(N_("A"), "A_STR");
+ b.add_input<decl::String>(N_("B"), "B_STR");
+
+ b.add_input<decl::Float>(N_("C")).default_value(0.9f);
+ b.add_input<decl::Float>(N_("Angle")).default_value(0.0872665f).subtype(PROP_ANGLE);
+ b.add_input<decl::Float>(N_("Epsilon")).default_value(0.001).min(-10000.0f).max(10000.0f);
+
+ b.add_output<decl::Bool>(N_("Result"));
+};
+
+static void geo_node_compare_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ const NodeFunctionCompare *data = (NodeFunctionCompare *)((bNode *)(ptr->data))->storage;
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ if (data->data_type == SOCK_VECTOR) {
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+ }
+ uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
+}
+
+static void node_compare_update(bNodeTree *ntree, bNode *node)
+{
+ NodeFunctionCompare *data = (NodeFunctionCompare *)node->storage;
+
+ bNodeSocket *sock_comp = (bNodeSocket *)BLI_findlink(&node->inputs, 10);
+ bNodeSocket *sock_angle = (bNodeSocket *)BLI_findlink(&node->inputs, 11);
+ bNodeSocket *sock_epsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 12);
+
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
+ nodeSetSocketAvailability(ntree, socket, socket->type == (eNodeSocketDatatype)data->data_type);
+ }
+
+ nodeSetSocketAvailability(ntree,
+ sock_epsilon,
+ ELEM(data->operation, NODE_COMPARE_EQUAL, NODE_COMPARE_NOT_EQUAL) &&
+ !ELEM(data->data_type, SOCK_INT, SOCK_STRING));
+
+ nodeSetSocketAvailability(ntree,
+ sock_comp,
+ ELEM(data->mode, NODE_COMPARE_MODE_DOT_PRODUCT) &&
+ data->data_type == SOCK_VECTOR);
+
+ nodeSetSocketAvailability(ntree,
+ sock_angle,
+ ELEM(data->mode, NODE_COMPARE_MODE_DIRECTION) &&
+ data->data_type == SOCK_VECTOR);
+}
+
+static void node_compare_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeFunctionCompare *data = (NodeFunctionCompare *)MEM_callocN(sizeof(NodeFunctionCompare),
+ __func__);
+ data->operation = NODE_COMPARE_GREATER_THAN;
+ data->data_type = SOCK_FLOAT;
+ data->mode = NODE_COMPARE_MODE_ELEMENT;
+ node->storage = data;
+}
+
+static void node_compare_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
+{
+ const NodeFunctionCompare *data = (NodeFunctionCompare *)node->storage;
+ const char *name;
+ bool enum_label = RNA_enum_name(rna_enum_node_compare_operation_items, data->operation, &name);
+ if (!enum_label) {
+ name = "Unknown";
+ }
+ BLI_strncpy(label, IFACE_(name), maxlen);
+}
+
+static float component_average(float3 a)
+{
+ return (a.x + a.y + a.z) / 3.0f;
+}
+
+static const fn::MultiFunction *get_multi_function(bNode &node)
+{
+ const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage;
+
+ switch (data->data_type) {
+ case SOCK_FLOAT:
+ switch (data->operation) {
+ case NODE_COMPARE_LESS_THAN: {
+ static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
+ "Less Than", [](float a, float b) { return a < b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_LESS_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
+ "Less Equal", [](float a, float b) { return a <= b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_GREATER_THAN: {
+ static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
+ "Greater Than", [](float a, float b) { return a > b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_GREATER_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
+ "Greater Equal", [](float a, float b) { return a >= b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_EQUAL: {
+ static fn::CustomMF_SI_SI_SI_SO<float, float, float, bool> fn{
+ "Equal", [](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; }};
+ return &fn;
+ }
+ case NODE_COMPARE_NOT_EQUAL:
+ static fn::CustomMF_SI_SI_SI_SO<float, float, float, bool> fn{
+ "Not Equal",
+ [](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; }};
+ return &fn;
+ }
+ break;
+ case SOCK_INT:
+ switch (data->operation) {
+ case NODE_COMPARE_LESS_THAN: {
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Less Than",
+ [](int a, int b) { return a < b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_LESS_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Less Equal",
+ [](int a, int b) { return a <= b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_GREATER_THAN: {
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Greater Than",
+ [](int a, int b) { return a > b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_GREATER_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Greater Equal",
+ [](int a, int b) { return a >= b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Equal",
+ [](int a, int b) { return a == b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_NOT_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Not Equal",
+ [](int a, int b) { return a != b; }};
+ return &fn;
+ }
+ }
+ break;
+ case SOCK_VECTOR:
+ switch (data->operation) {
+ case NODE_COMPARE_LESS_THAN:
+ switch (data->mode) {
+ case NODE_COMPARE_MODE_AVERAGE: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Less Than - Average",
+ [](float3 a, float3 b) { return component_average(a) < component_average(b); }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DOT_PRODUCT: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Less Than - Dot Product",
+ [](float3 a, float3 b, float comp) { return float3::dot(a, b) < comp; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DIRECTION: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Less Than - Direction",
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_ELEMENT: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Less Than - Element-wise",
+ [](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_LENGTH: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Less Than - Length",
+ [](float3 a, float3 b) { return a.length() < b.length(); }};
+ return &fn;
+ }
+ }
+ break;
+ case NODE_COMPARE_LESS_EQUAL:
+ switch (data->mode) {
+ case NODE_COMPARE_MODE_AVERAGE: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Less Equal - Average",
+ [](float3 a, float3 b) { return component_average(a) <= component_average(b); }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DOT_PRODUCT: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Less Equal - Dot Product",
+ [](float3 a, float3 b, float comp) { return float3::dot(a, b) <= comp; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DIRECTION: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Less Equal - Direction",
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_ELEMENT: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Less Equal - Element-wise",
+ [](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_LENGTH: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Less Equal - Length",
+ [](float3 a, float3 b) { return a.length() <= b.length(); }};
+ return &fn;
+ }
+ }
+ break;
+ case NODE_COMPARE_GREATER_THAN:
+ switch (data->mode) {
+ case NODE_COMPARE_MODE_AVERAGE: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Greater Than - Average",
+ [](float3 a, float3 b) { return component_average(a) > component_average(b); }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DOT_PRODUCT: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Greater Than - Dot Product",
+ [](float3 a, float3 b, float comp) { return float3::dot(a, b) > comp; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DIRECTION: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Greater Than - Direction",
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_ELEMENT: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Greater Than - Element-wise",
+ [](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_LENGTH: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Greater Than - Length",
+ [](float3 a, float3 b) { return a.length() > b.length(); }};
+ return &fn;
+ }
+ }
+ break;
+ case NODE_COMPARE_GREATER_EQUAL:
+ switch (data->mode) {
+ case NODE_COMPARE_MODE_AVERAGE: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Greater Equal - Average",
+ [](float3 a, float3 b) { return component_average(a) >= component_average(b); }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DOT_PRODUCT: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Greater Equal - Dot Product",
+ [](float3 a, float3 b, float comp) { return float3::dot(a, b) >= comp; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DIRECTION: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Greater Equal - Direction",
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_ELEMENT: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Greater Equal - Element-wise",
+ [](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_LENGTH: {
+ static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
+ "Greater Equal - Length",
+ [](float3 a, float3 b) { return a.length() >= b.length(); }};
+ return &fn;
+ }
+ }
+ break;
+ case NODE_COMPARE_EQUAL:
+ switch (data->mode) {
+ case NODE_COMPARE_MODE_AVERAGE: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Equal - Average", [](float3 a, float3 b, float epsilon) {
+ return abs(component_average(a) - component_average(b)) <= epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DOT_PRODUCT: {
+ static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
+ "Equal - Dot Product", [](float3 a, float3 b, float comp, float epsilon) {
+ return abs(float3::dot(a, b) - comp) <= epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DIRECTION: {
+ static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
+ "Equal - Direction", [](float3 a, float3 b, float angle, float epsilon) {
+ return abs(angle_v3v3(a, b) - angle) <= epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_ELEMENT: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Equal - Element-wise", [](float3 a, float3 b, float epsilon) {
+ return abs(a.x - b.x) <= epsilon && abs(a.y - b.y) <= epsilon &&
+ abs(a.z - b.z) <= epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_LENGTH: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Equal - Length", [](float3 a, float3 b, float epsilon) {
+ return abs(a.length() - b.length()) <= epsilon;
+ }};
+ return &fn;
+ }
+ }
+ break;
+ case NODE_COMPARE_NOT_EQUAL:
+ switch (data->mode) {
+ case NODE_COMPARE_MODE_AVERAGE: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Not Equal - Average", [](float3 a, float3 b, float epsilon) {
+ return abs(component_average(a) - component_average(b)) > epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DOT_PRODUCT: {
+ static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
+ "Not Equal - Dot Product", [](float3 a, float3 b, float comp, float epsilon) {
+ return abs(float3::dot(a, b) - comp) >= epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_DIRECTION: {
+ static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
+ "Not Equal - Direction", [](float3 a, float3 b, float angle, float epsilon) {
+ return abs(angle_v3v3(a, b) - angle) > epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_ELEMENT: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Not Equal - Element-wise", [](float3 a, float3 b, float epsilon) {
+ return abs(a.x - b.x) > epsilon && abs(a.y - b.y) > epsilon &&
+ abs(a.z - b.z) > epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_MODE_LENGTH: {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
+ "Not Equal - Length", [](float3 a, float3 b, float epsilon) {
+ return abs(a.length() - b.length()) > epsilon;
+ }};
+ return &fn;
+ }
+ }
+ break;
+ }
+ break;
+ case SOCK_RGBA:
+ switch (data->operation) {
+ case NODE_COMPARE_EQUAL: {
+ static fn::CustomMF_SI_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, float, bool> fn{
+ "Equal", [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
+ return abs(a.r - b.r) <= epsilon && abs(a.g - b.g) <= epsilon &&
+ abs(a.b - b.b) <= epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_NOT_EQUAL: {
+ static fn::CustomMF_SI_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, float, bool> fn{
+ "Not Equal", [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
+ return abs(a.r - b.r) > epsilon && abs(a.g - b.g) > epsilon &&
+ abs(a.b - b.b) > epsilon;
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_COLOR_BRIGHTER: {
+ static fn::CustomMF_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, bool> fn{
+ "Brighter", [](ColorGeometry4f a, ColorGeometry4f b) {
+ return rgb_to_grayscale(a) > rgb_to_grayscale(b);
+ }};
+ return &fn;
+ }
+ case NODE_COMPARE_COLOR_DARKER: {
+ static fn::CustomMF_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, bool> fn{
+ "Darker", [](ColorGeometry4f a, ColorGeometry4f b) {
+ return rgb_to_grayscale(a) < rgb_to_grayscale(b);
+ }};
+ return &fn;
+ }
+ }
+ break;
+ case SOCK_STRING:
+ switch (data->operation) {
+ case NODE_COMPARE_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<std::string, std::string, bool> fn{
+ "Equal", [](std::string a, std::string b) { return a == b; }};
+ return &fn;
+ }
+ case NODE_COMPARE_NOT_EQUAL: {
+ static fn::CustomMF_SI_SI_SO<std::string, std::string, bool> fn{
+ "Not Equal", [](std::string a, std::string b) { return a != b; }};
+ return &fn;
+ }
+ }
+ break;
+ }
+ return nullptr;
+}
+
+static void fn_node_compare_build_multi_function(NodeMultiFunctionBuilder &builder)
+{
+ const fn::MultiFunction *fn = get_multi_function(builder.node());
+ builder.set_matching_fn(fn);
+}
+
+} // namespace blender::nodes::node_fn_compare_cc
+
+void register_node_type_fn_compare()
+{
+ namespace file_ns = blender::nodes::node_fn_compare_cc;
+
+ static bNodeType ntype;
+ fn_node_type_base(&ntype, FN_NODE_COMPARE, "Compare", NODE_CLASS_CONVERTER, 0);
+ ntype.declare = file_ns::fn_node_compare_declare;
+ node_type_label(&ntype, file_ns::node_compare_label);
+ node_type_update(&ntype, file_ns::node_compare_update);
+ node_type_init(&ntype, file_ns::node_compare_init);
+ node_type_storage(
+ &ntype, "NodeFunctionCompare", node_free_standard_storage, node_copy_standard_storage);
+ ntype.build_multi_function = file_ns::fn_node_compare_build_multi_function;
+ ntype.draw_buttons = file_ns::geo_node_compare_layout;
+ nodeRegisterType(&ntype);
+}