[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [42707] trunk/blender: Generalized node groups for Cycles.

Lukas Toenne lukas.toenne at googlemail.com
Sun Dec 18 16:34:12 CET 2011


Revision: 42707
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=42707
Author:   lukastoenne
Date:     2011-12-18 15:34:06 +0000 (Sun, 18 Dec 2011)
Log Message:
-----------
Generalized node groups for Cycles.

This allows group nodes inside other group nodes in cycles and makes the
code more generic for all possible cases, like direct group
input-to-output links and unused group sockets.

Previous code tried to connect external nodes and internal group sockets
by following links until a "real" node input/output. This quickly
becomes complicated in corner cases as described above and can lead to
unexpected behavior when the group socket is of a different type than
the internal/external sockets, but that conversion is skipped.

The new code uses the concept of "proxy nodes" similar to what the new
compositor does. Each group socket is replaced with a proxy node with a
single input and output, to which other nodes in the same tree and
internal nodes can link to. After all groups have been expanded in the
graph, these proxy nodes are removed again, adding converter nodes if
necessary.

Modified Paths:
--------------
    trunk/blender/intern/cycles/blender/blender_shader.cpp
    trunk/blender/intern/cycles/render/graph.cpp
    trunk/blender/intern/cycles/render/graph.h
    trunk/blender/intern/cycles/render/nodes.cpp
    trunk/blender/intern/cycles/render/nodes.h
    trunk/blender/source/blender/makesrna/intern/rna_nodetree.c

Modified: trunk/blender/intern/cycles/blender/blender_shader.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_shader.cpp	2011-12-18 12:54:50 UTC (rev 42706)
+++ trunk/blender/intern/cycles/blender/blender_shader.cpp	2011-12-18 15:34:06 UTC (rev 42707)
@@ -50,28 +50,6 @@
 
 /* Graph */
 
-static BL::NodeSocket get_node_input(BL::Node *b_group_node, BL::NodeSocket b_in)
-{
-	if(b_group_node) {
-
-		BL::NodeTree b_ntree = BL::NodeGroup(*b_group_node).node_tree();
-		BL::NodeTree::links_iterator b_link;
-
-		for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
-			if(b_link->to_socket().ptr.data == b_in.ptr.data) {
-				BL::Node::inputs_iterator b_gin;
-
-				for(b_group_node->inputs.begin(b_gin); b_gin != b_group_node->inputs.end(); ++b_gin)
-					if(b_gin->group_socket().ptr.data == b_link->from_socket().ptr.data)
-						return *b_gin;
-
-			}
-		}
-	}
-
-	return b_in;
-}
-
 static BL::NodeSocket get_node_output(BL::Node b_node, const string& name)
 {
 	BL::Node::outputs_iterator b_out;
@@ -121,7 +99,7 @@
 	mapping->scale = get_float3(b_mapping.scale());
 }
 
-static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *b_group_node, BL::ShaderNode b_node)
+static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNode b_node)
 {
 	ShaderNode *node = NULL;
 
@@ -470,59 +448,115 @@
 	return SocketPair(node_map[b_node.ptr.data], name);
 }
 
-static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::Node *b_group_node, PtrSockMap& sockets_map)
+static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type)
 {
+	switch (b_type) {
+	case BL::NodeSocket::type_VALUE:
+		return SHADER_SOCKET_FLOAT;
+	case BL::NodeSocket::type_VECTOR:
+		return SHADER_SOCKET_VECTOR;
+	case BL::NodeSocket::type_RGBA:
+		return SHADER_SOCKET_COLOR;
+	case BL::NodeSocket::type_SHADER:
+		return SHADER_SOCKET_CLOSURE;
+	
+	case BL::NodeSocket::type_BOOLEAN:
+	case BL::NodeSocket::type_MESH:
+	case BL::NodeSocket::type_INT:
+	default:
+		return SHADER_SOCKET_FLOAT;
+	}
+}
+
+static void set_default_value(ShaderInput *input, BL::NodeSocket sock)
+{
+	/* copy values for non linked inputs */
+	switch(input->type) {
+	case SHADER_SOCKET_FLOAT: {
+		BL::NodeSocketFloatNone value_sock(sock);
+		input->set(value_sock.default_value());
+		break;
+	}
+	case SHADER_SOCKET_COLOR: {
+		BL::NodeSocketRGBA rgba_sock(sock);
+		input->set(get_float3(rgba_sock.default_value()));
+		break;
+	}
+	case SHADER_SOCKET_NORMAL:
+	case SHADER_SOCKET_POINT:
+	case SHADER_SOCKET_VECTOR: {
+		BL::NodeSocketVectorNone vec_sock(sock);
+		input->set(get_float3(vec_sock.default_value()));
+		break;
+	}
+	case SHADER_SOCKET_CLOSURE:
+		break;
+	}
+}
+
+static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map)
+{
 	/* add nodes */
 	BL::ShaderNodeTree::nodes_iterator b_node;
 	PtrNodeMap node_map;
-	map<void*, PtrSockMap> node_groups;
+	PtrSockMap proxy_map;
 
 	for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
 		if(b_node->is_a(&RNA_NodeGroup)) {
+			/* add proxy converter nodes for inputs and outputs */
 			BL::NodeGroup b_gnode(*b_node);
 			BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree());
-
-			node_groups[b_node->ptr.data] = PtrSockMap();
-			add_nodes(b_data, graph, b_group_ntree, &b_gnode, node_groups[b_node->ptr.data]);
+			BL::Node::inputs_iterator b_input;
+			BL::Node::outputs_iterator b_output;
+			
+			PtrSockMap group_sockmap;
+			
+			for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+				ShaderSocketType extern_type = convert_socket_type(b_input->type());
+				ShaderSocketType intern_type = convert_socket_type(b_input->group_socket().type());
+				ShaderNode *proxy = graph->add(new ProxyNode(extern_type, intern_type));
+				
+				/* map the external node socket to the proxy node socket */
+				proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
+				/* map the internal group socket to the proxy node socket */
+				group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
+				
+				/* default input values of the group node */
+				set_default_value(proxy->inputs[0], *b_input);
+			}
+			
+			for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
+				ShaderSocketType extern_type = convert_socket_type(b_output->type());
+				ShaderSocketType intern_type = convert_socket_type(b_output->group_socket().type());
+				ShaderNode *proxy = graph->add(new ProxyNode(intern_type, extern_type));
+				
+				/* map the external node socket to the proxy node socket */
+				proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
+				/* map the internal group socket to the proxy node socket */
+				group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
+				
+				/* default input values of internal, unlinked group outputs */
+				set_default_value(proxy->inputs[0], b_output->group_socket());
+			}
+			
+			add_nodes(b_data, graph, b_group_ntree, group_sockmap);
 		}
 		else {
-			ShaderNode *node = add_node(b_data, graph, b_group_node, BL::ShaderNode(*b_node));
-
+			ShaderNode *node = add_node(b_data, graph, BL::ShaderNode(*b_node));
+			
 			if(node) {
 				BL::Node::inputs_iterator b_input;
-				BL::Node::outputs_iterator b_output;
-
+				
 				node_map[b_node->ptr.data] = node;
-
+				
 				for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
 					SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input);
 					ShaderInput *input = pair.first->input(pair.second.c_str());
-					BL::NodeSocket sock(get_node_input(b_group_node, *b_input));
-
+					
 					assert(input);
-
+					
 					/* copy values for non linked inputs */
-					switch(input->type) {
-						case SHADER_SOCKET_FLOAT: {
-							BL::NodeSocketFloatNone value_sock(sock);
-							input->set(value_sock.default_value());
-							break;
-						}
-						case SHADER_SOCKET_COLOR: {
-							BL::NodeSocketRGBA rgba_sock(sock);
-							input->set(get_float3(rgba_sock.default_value()));
-							break;
-						}
-						case SHADER_SOCKET_NORMAL:
-						case SHADER_SOCKET_POINT:
-						case SHADER_SOCKET_VECTOR: {
-							BL::NodeSocketVectorNone vec_sock(sock);
-							input->set(get_float3(vec_sock.default_value()));
-							break;
-						}
-						case SHADER_SOCKET_CLOSURE:
-							break;
-					}
+					set_default_value(input, *b_input);
 				}
 			}
 		}
@@ -539,54 +573,34 @@
 		BL::NodeSocket b_from_sock = b_link->from_socket();
 		BL::NodeSocket b_to_sock = b_link->to_socket();
 
-		/* if link with group socket, add to map so we can connect it later */
-		if(b_group_node) {
-			if(!b_from_node) {
-				sockets_map[b_from_sock.ptr.data] =
-					node_socket_map_pair(node_map, b_to_node, b_to_sock);
+		SocketPair from_pair, to_pair;
 
-				continue;
-			}
-			else if(!b_to_node) {
-				sockets_map[b_to_sock.ptr.data] =
-					node_socket_map_pair(node_map, b_from_node, b_from_sock);
+		/* links without a node pointer are connections to group inputs/outputs */
 
-				continue;
-			}
-		}
-
-		SocketPair from_pair, to_pair;
-
 		/* from sock */
-		if(b_from_node.is_a(&RNA_NodeGroup)) {
-			/* group node */
-			BL::NodeSocket group_sock = b_from_sock.group_socket();
-			from_pair = node_groups[b_from_node.ptr.data][group_sock.ptr.data];
+		if(b_from_node) {
+			if (b_from_node.is_a(&RNA_NodeGroup))
+				from_pair = proxy_map[b_from_sock.ptr.data];
+			else
+				from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
 		}
-		else {
-			/* regular node */
-			from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
-		}
+		else
+			from_pair = sockets_map[b_from_sock.ptr.data];
 
 		/* to sock */
-		if(b_to_node.is_a(&RNA_NodeGroup)) {
-			/* group node */
-			BL::NodeSocket group_sock = b_to_sock.group_socket();
-			to_pair = node_groups[b_to_node.ptr.data][group_sock.ptr.data];
+		if(b_to_node) {
+			if (b_to_node.is_a(&RNA_NodeGroup))
+				to_pair = proxy_map[b_to_sock.ptr.data];
+			else
+				to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
 		}
-		else {
-			/* regular node */
-			to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
-		}
+		else
+			to_pair = sockets_map[b_to_sock.ptr.data];
 
-		/* in case of groups there may not actually be a node inside the group
-		   that the group socket connects to, so from_node or to_node may be NULL */
-		if(from_pair.first && to_pair.first) {
-			ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
-			ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
+		ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
+		ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
 
-			graph->connect(output, input);
-		}
+		graph->connect(output, input);
 	}
 }
 
@@ -613,7 +627,7 @@
 				PtrSockMap sock_to_node;
 				BL::ShaderNodeTree b_ntree(b_mat->node_tree());
 
-				add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
+				add_nodes(b_data, graph, b_ntree, sock_to_node);
 			}
 			else {
 				ShaderNode *closure, *out;
@@ -654,7 +668,7 @@
 			PtrSockMap sock_to_node;
 			BL::ShaderNodeTree b_ntree(b_world.node_tree());
 
-			add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
+			add_nodes(b_data, graph, b_ntree, sock_to_node);
 		}
 		else if(b_world) {
 			ShaderNode *closure, *out;
@@ -703,7 +717,7 @@
 				PtrSockMap sock_to_node;
 				BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
 
-				add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
+				add_nodes(b_data, graph, b_ntree, sock_to_node);
 			}
 			else {
 				ShaderNode *closure, *out;

Modified: trunk/blender/intern/cycles/render/graph.cpp
===================================================================
--- trunk/blender/intern/cycles/render/graph.cpp	2011-12-18 12:54:50 UTC (rev 42706)
+++ trunk/blender/intern/cycles/render/graph.cpp	2011-12-18 15:34:06 UTC (rev 42707)
@@ -292,6 +292,42 @@
 	}
 }
 
+void ShaderGraph::remove_proxy_nodes(vector<bool>& removed)
+{
+	foreach(ShaderNode *node, nodes) {
+		ProxyNode *proxy = dynamic_cast<ProxyNode*>(node);
+		if (proxy) {
+			ShaderInput *input = proxy->inputs[0];
+			ShaderOutput *output = proxy->outputs[0];
+			
+			/* temp. copy of the output links list.

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list