Code refactor: minor node and node type utility functions and changes.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sun, 29 May 2016 09:20:10 +0000 (11:20 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sun, 29 May 2016 18:30:16 +0000 (20:30 +0200)
12 files changed:
intern/cycles/graph/node.cpp
intern/cycles/graph/node.h
intern/cycles/graph/node_type.cpp
intern/cycles/graph/node_type.h
intern/cycles/graph/node_xml.cpp
intern/cycles/render/background.cpp
intern/cycles/render/background.h
intern/cycles/render/camera.cpp
intern/cycles/render/camera.h
intern/cycles/render/film.cpp
intern/cycles/render/integrator.cpp
intern/cycles/render/integrator.h

index 98b66fb9a7a30bf0d5f64020b222c5900099ca89..941a66741c590197398b94df0b7d00197cc15655 100644 (file)
@@ -36,12 +36,8 @@ Node::Node(const NodeType *type_, ustring name_)
        }
 
        /* initialize default values */
-       typedef unordered_map<ustring, SocketType, ustringHash> map_type;
-       foreach(const map_type::value_type& it, type->inputs) {
-               const SocketType& socket = it.second;
-               const void *src = socket.default_value;
-               void *dst = ((char*)this) + socket.struct_offset;
-               memcpy(dst, src, socket.size());
+       foreach(const SocketType& socket, type->inputs) {
+               set_default_value(socket);
        }
 }
 
@@ -297,7 +293,8 @@ const array<Node*>& Node::get_node_array(const SocketType& input) const
        return get_socket_value<array<Node*> >(this, input);
 }
 
-/* default values */
+/* generic value operations */
+
 bool Node::has_default_value(const SocketType& input) const
 {
        const void *src = input.default_value;
@@ -305,6 +302,48 @@ bool Node::has_default_value(const SocketType& input) const
        return memcmp(dst, src, input.size()) == 0;
 }
 
+void Node::set_default_value(const SocketType& socket)
+{
+       const void *src = socket.default_value;
+       void *dst = ((char*)this) + socket.struct_offset;
+       memcpy(dst, src, socket.size());
+}
+
+template<typename T>
+static void copy_array(const Node *node, const SocketType& socket, const Node *other, const SocketType& other_socket)
+{
+       const array<T>* src = (const array<T>*)(((char*)other) + other_socket.struct_offset);
+       array<T>* dst = (array<T>*)(((char*)node) + socket.struct_offset);
+       *dst = *src;
+}
+
+void Node::copy_value(const SocketType& socket, const Node& other, const SocketType& other_socket)
+{
+       assert(socket.type == other_socket.type);
+
+       if(socket.is_array()) {
+               switch(socket.type) {
+                       case SocketType::BOOLEAN_ARRAY: copy_array<bool>(this, socket, &other, other_socket); break;
+                       case SocketType::FLOAT_ARRAY: copy_array<float>(this, socket, &other, other_socket); break;
+                       case SocketType::INT_ARRAY: copy_array<int>(this, socket, &other, other_socket); break;
+                       case SocketType::COLOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+                       case SocketType::VECTOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+                       case SocketType::POINT_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+                       case SocketType::NORMAL_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+                       case SocketType::POINT2_ARRAY: copy_array<float2>(this, socket, &other, other_socket); break;
+                       case SocketType::STRING_ARRAY: copy_array<ustring>(this, socket, &other, other_socket); break;
+                       case SocketType::TRANSFORM_ARRAY: copy_array<Transform>(this, socket, &other, other_socket); break;
+                       case SocketType::NODE_ARRAY: copy_array<void*>(this, socket, &other, other_socket); break;
+                       default: assert(0); break;
+               }
+       }
+       else {
+               const void *src = ((char*)&other) + other_socket.struct_offset;
+               void *dst = ((char*)this) + socket.struct_offset;
+               memcpy(dst, src, socket.size());
+       }
+}
+
 template<typename T>
 static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket)
 {
@@ -313,48 +352,43 @@ static bool is_array_equal(const Node *node, const Node *other, const SocketType
        return *a == *b;
 }
 
-/* modified */
-bool Node::modified(const Node& other)
+bool Node::equals_value(const Node& other, const SocketType& socket) const
+{
+       if(socket.is_array()) {
+               switch(socket.type) {
+                       case SocketType::BOOLEAN_ARRAY: return is_array_equal<bool>(this, &other, socket);
+                       case SocketType::FLOAT_ARRAY: return is_array_equal<float>(this, &other, socket);
+                       case SocketType::INT_ARRAY: return is_array_equal<int>(this, &other, socket);
+                       case SocketType::COLOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
+                       case SocketType::VECTOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
+                       case SocketType::POINT_ARRAY: return is_array_equal<float3>(this, &other, socket);
+                       case SocketType::NORMAL_ARRAY: return is_array_equal<float3>(this, &other, socket);
+                       case SocketType::POINT2_ARRAY: return is_array_equal<float2>(this, &other, socket);
+                       case SocketType::STRING_ARRAY: return is_array_equal<ustring>(this, &other, socket);
+                       case SocketType::TRANSFORM_ARRAY: return is_array_equal<Transform>(this, &other, socket);
+                       case SocketType::NODE_ARRAY: return is_array_equal<void*>(this, &other, socket);
+                       default: assert(0); return true;
+               }
+       }
+       else {
+               const void *a = ((char*)this) + socket.struct_offset;
+               const void *b = ((char*)&other) + socket.struct_offset;
+               return (memcmp(a, b, socket.size()) == 0);
+       }
+}
+
+/* equals */
+
+bool Node::equals(const Node& other) const
 {
        assert(type == other.type);
 
-       typedef unordered_map<ustring, SocketType, ustringHash> map_type;
-       foreach(const map_type::value_type& it, type->inputs) {
-               const SocketType& socket = it.second;
-
-               if(socket.is_array()) {
-                       bool equal = true;
-
-                       switch(socket.type)
-                       {
-                               case SocketType::BOOLEAN_ARRAY: equal = is_array_equal<bool>(this, &other, socket); break;
-                               case SocketType::FLOAT_ARRAY: equal = is_array_equal<float>(this, &other, socket); break;
-                               case SocketType::INT_ARRAY: equal = is_array_equal<int>(this, &other, socket); break;
-                               case SocketType::COLOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
-                               case SocketType::VECTOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
-                               case SocketType::POINT_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
-                               case SocketType::NORMAL_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
-                               case SocketType::POINT2_ARRAY: equal = is_array_equal<float2>(this, &other, socket); break;
-                               case SocketType::STRING_ARRAY: equal = is_array_equal<ustring>(this, &other, socket); break;
-                               case SocketType::TRANSFORM_ARRAY: equal = is_array_equal<Transform>(this, &other, socket); break;
-                               case SocketType::NODE_ARRAY: equal = is_array_equal<void*>(this, &other, socket); break;
-                               default: assert(0); break;
-                       }
-
-                       if(!equal) {
-                               return true;
-                       }
-               }
-               else {
-                       const void *a = ((char*)this) + socket.struct_offset;
-                       const void *b = ((char*)&other) + socket.struct_offset;
-                       if(memcmp(a, b, socket.size()) != 0) {
-                               return true;
-                       }
-               }
+       foreach(const SocketType& socket, type->inputs) {
+               if(!equals_value(other, socket))
+                       return false;
        }
 
-       return false;
+       return true;
 }
 
 CCL_NAMESPACE_END
index de06df10265c551f62c49a9d627a722f917bc45b..bb84f982fb36523f92c9f379fff2ce592a8dbf05 100644 (file)
@@ -77,11 +77,14 @@ struct Node
        const array<Transform>& get_transform_array(const SocketType& input) const;
        const array<Node*>& get_node_array(const SocketType& input) const;
 
-       /* default values */
+       /* generic values operations */
        bool has_default_value(const SocketType& input) const;
+       void set_default_value(const SocketType& input);
+       bool equals_value(const Node& other, const SocketType& input) const;
+       void copy_value(const SocketType& input, const Node& other, const SocketType& other_input);
 
-       /* modified */
-       bool modified(const Node& other);
+       /* equals */
+       bool equals(const Node& other) const;
 
        ustring name;
        const NodeType *type;
index dc879655d7f8692e62a3672d952e1ab0644d7c40..7f68ae9c7c72a56e5e533af37f7d8ab0162aff64 100644 (file)
@@ -114,9 +114,15 @@ ustring SocketType::type_name(Type type)
        return names[(int)type];
 }
 
+bool SocketType::is_float3(Type type)
+{
+       return (type == COLOR || type == VECTOR || type == POINT || type == NORMAL);
+}
+
 /* Node Type */
 
-NodeType::NodeType()
+NodeType::NodeType(Type type_)
+: type(type_)
 {
 }
 
@@ -137,7 +143,7 @@ void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type ty
        socket.enum_values = enum_values;
        socket.node_type = node_type;
        socket.flags = flags | extra_flags;
-       inputs[name] = socket;
+       inputs.push_back(socket);
 }
 
 void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type type)
@@ -151,7 +157,29 @@ void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type t
        socket.enum_values = NULL;
        socket.node_type = NULL;
        socket.flags = SocketType::LINKABLE;
-       outputs[name] = socket;
+       outputs.push_back(socket);
+}
+
+const SocketType *NodeType::find_input(ustring name) const
+{
+       foreach(const SocketType& socket, inputs) {
+               if(socket.name == name) {
+                       return &socket;
+               }
+       }
+
+       return NULL;
+}
+
+const SocketType *NodeType::find_output(ustring name) const
+{
+       foreach(const SocketType& socket, outputs) {
+               if(socket.name == name) {
+                       return &socket;
+               }
+       }
+
+       return NULL;
 }
 
 /* Node Type Registry */
@@ -162,7 +190,7 @@ unordered_map<ustring, NodeType, ustringHash>& NodeType::types()
        return _types;
 }
 
-NodeType *NodeType::add(const char *name_, CreateFunc create_)
+NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_)
 {
        ustring name(name_);
 
@@ -172,7 +200,7 @@ NodeType *NodeType::add(const char *name_, CreateFunc create_)
                return NULL;
        }
 
-       types()[name] = NodeType();
+       types()[name] = NodeType(type_);
 
        NodeType *type = &types()[name];
        type->name = name;
index 82ddd29da333ac5a6b2a4b1aabc86e29abd8c49e..20816f634cd18725d8952d9ac4cc49203c00c370 100644 (file)
@@ -21,6 +21,7 @@
 #include "util_map.h"
 #include "util_param.h"
 #include "util_string.h"
+#include "util_vector.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -94,13 +95,19 @@ struct SocketType
        static size_t max_size();
        static ustring type_name(Type type);
        static void *zero_default_value();
+       static bool is_float3(Type type);
 };
 
 /* Node Type */
 
 struct NodeType
 {
-       explicit NodeType();
+       enum Type {
+               NONE,
+               SHADER
+       };
+
+       explicit NodeType(Type type = NONE);
        ~NodeType();
 
        void register_input(ustring name, ustring ui_name, SocketType::Type type,
@@ -110,15 +117,18 @@ struct NodeType
                                                int flags = 0, int extra_flags = 0);
        void register_output(ustring name, ustring ui_name, SocketType::Type type);
 
+       const SocketType *find_input(ustring name) const;
+       const SocketType *find_output(ustring name) const;
+
        typedef Node *(*CreateFunc)(const NodeType *type);
-       typedef unordered_map<ustring, SocketType, ustringHash> SocketMap;
 
        ustring name;
-       SocketMap inputs;
-       SocketMap outputs;
+       Type type;
+       std::vector<SocketType> inputs;
+       std::vector<SocketType> outputs;
        CreateFunc create;
 
-       static NodeType *add(const char *name, CreateFunc create);
+       static NodeType *add(const char *name, CreateFunc create, Type type = NONE);
        static const NodeType *find(ustring name);
        static unordered_map<ustring, NodeType, ustringHash>& types();
 };
index a6040405c302beb348782127a90b1f0d6868ac29..022de7cf32a36f6d7ada615234d671d6055b9498 100644 (file)
@@ -58,9 +58,7 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
                node->name = ustring(name_attr.value());
        }
 
-       foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
-               const SocketType& socket = it.second;
-
+       foreach(const SocketType& socket, node->type->inputs) {
                if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
                        continue;
                }
@@ -257,9 +255,7 @@ pugi::xml_node xml_write_node(Node *node, pugi::xml_node xml_root)
 
        xml_node.append_attribute("name") = node->name.c_str();
 
-       foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
-               const SocketType& socket = it.second;
-
+       foreach(const SocketType& socket, node->type->inputs) {
                if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
                        continue;
                }
index 6f8d1d1d461ad79d7751a065e5132544f19315e3..20536b74e87d8f8a45f37d3559c3d7d75cb13291 100644 (file)
@@ -116,6 +116,11 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
 {
 }
 
+bool Background::modified(const Background& background)
+{
+       return !Node::equals(background);
+}
+
 void Background::tag_update(Scene *scene)
 {
        scene->integrator->tag_update(scene);
index 843655b00a14b2b281b19cf561d3241e89a828dc..8029c6a9e80a3f4a92745849e9755b8639fff980 100644 (file)
@@ -50,6 +50,7 @@ public:
        void device_update(Device *device, DeviceScene *dscene, Scene *scene);
        void device_free(Device *device, DeviceScene *dscene);
 
+       bool modified(const Background& background);
        void tag_update(Scene *scene);
 };
 
index 250357d3c9f121c6fe6cc5b1cc71f973e97fa235..2310798be2ec292527fbf160eb52ccdd69039f4a 100644 (file)
@@ -482,6 +482,11 @@ void Camera::device_free(Device * /*device*/,
        scene->lookup_tables->remove_table(&shutter_table_offset);
 }
 
+bool Camera::modified(const Camera& cam)
+{
+       return !Node::equals(cam);
+}
+
 bool Camera::motion_modified(const Camera& cam)
 {
        return !((motion == cam.motion) &&
index 9069cc6d53da964b1bbac018ca8cb9daf1506058..141ef9cccef078d03c1448e4006c3298c0b215a1 100644 (file)
@@ -181,6 +181,7 @@ public:
        void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
        void device_free(Device *device, DeviceScene *dscene, Scene *scene);
 
+       bool modified(const Camera& cam);
        bool motion_modified(const Camera& cam);
        void tag_update();
 
index 12dce6ad999dbc3cba973c4b655d70b8c6fdf99a..e10a938e1eb2ed085ed7d1f60039444ef1f903ef 100644 (file)
@@ -465,7 +465,7 @@ void Film::device_free(Device * /*device*/,
 
 bool Film::modified(const Film& film)
 {
-       return Node::modified(film) || !Pass::equals(passes, film.passes);
+       return !Node::equals(film) || !Pass::equals(passes, film.passes);
 }
 
 void Film::tag_passes_update(Scene *scene, const array<Pass>& passes_)
index 41e2571dc247a45c365b1aca3dad467cffeb418d..2a10eb474a49b8f6c37b6ee2b65c4b0612acba42 100644 (file)
@@ -204,6 +204,11 @@ void Integrator::device_free(Device *device, DeviceScene *dscene)
        dscene->sobol_directions.clear();
 }
 
+bool Integrator::modified(const Integrator& integrator)
+{
+       return !Node::equals(integrator);
+}
+
 void Integrator::tag_update(Scene *scene)
 {
        foreach(Shader *shader, scene->shaders) {
index a5cfb0c78634a6c4f590f5b90a321f668dc15591..39eaaf246d40e3d1ee48a65b7c3184d6880003d4 100644 (file)
@@ -86,6 +86,7 @@ public:
        void device_update(Device *device, DeviceScene *dscene, Scene *scene);
        void device_free(Device *device, DeviceScene *dscene);
 
+       bool modified(const Integrator& integrator);
        void tag_update(Scene *scene);
 };