2 * Copyright 2011, Blender Foundation.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "background.h"
26 #include "blender_sync.h"
27 #include "blender_util.h"
29 #include "util_debug.h"
33 typedef map<void*, ShaderNode*> PtrNodeMap;
34 typedef pair<ShaderNode*, std::string> SocketPair;
35 typedef map<void*, SocketPair> PtrSockMap;
39 void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders)
41 Shader *shader = shader_map.find(id);
43 for(size_t i = 0; i < scene->shaders.size(); i++) {
44 if(scene->shaders[i] == shader) {
45 used_shaders.push_back(i);
53 static BL::NodeSocket get_node_input(BL::Node *b_group_node, BL::NodeSocket b_in)
57 BL::NodeTree b_ntree = BL::NodeGroup(*b_group_node).node_tree();
58 BL::NodeTree::links_iterator b_link;
60 for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
61 if(b_link->to_socket().ptr.data == b_in.ptr.data) {
62 BL::Node::inputs_iterator b_gin;
64 for(b_group_node->inputs.begin(b_gin); b_gin != b_group_node->inputs.end(); ++b_gin)
65 if(b_gin->group_socket().ptr.data == b_link->from_socket().ptr.data)
75 static BL::NodeSocket get_node_output(BL::Node b_node, const string& name)
77 BL::Node::outputs_iterator b_out;
79 for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
80 if(b_out->name() == name)
88 static float3 get_node_output_rgba(BL::Node b_node, const string& name)
90 BL::NodeSocketRGBA sock(get_node_output(b_node, name));
91 return get_float3(sock.default_value());
94 static float get_node_output_value(BL::Node b_node, const string& name)
96 BL::NodeSocketFloatNone sock(get_node_output(b_node, name));
97 return sock.default_value();
100 static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping b_mapping)
105 mapping->translation = get_float3(b_mapping.location());
106 mapping->rotation = get_float3(b_mapping.rotation());
107 mapping->scale = get_float3(b_mapping.scale());
109 mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
110 mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
111 mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
114 static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_mapping)
119 mapping->translation = get_float3(b_mapping.location());
120 mapping->rotation = get_float3(b_mapping.rotation());
121 mapping->scale = get_float3(b_mapping.scale());
124 static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *b_group_node, BL::ShaderNode b_node)
126 ShaderNode *node = NULL;
128 switch(b_node.type()) {
130 case BL::ShaderNode::type_CURVE_RGB: break;
131 case BL::ShaderNode::type_CURVE_VEC: break;
132 case BL::ShaderNode::type_GEOMETRY: break;
133 case BL::ShaderNode::type_INVERT: break;
134 case BL::ShaderNode::type_MATERIAL: break;
135 case BL::ShaderNode::type_MATERIAL_EXT: break;
136 case BL::ShaderNode::type_NORMAL: break;
137 case BL::ShaderNode::type_OUTPUT: break;
138 case BL::ShaderNode::type_SCRIPT: break;
139 case BL::ShaderNode::type_SQUEEZE: break;
140 case BL::ShaderNode::type_TEXTURE: break;
141 case BL::ShaderNode::type_VALTORGB: break;
142 /* handled outside this function */
143 case BL::ShaderNode::type_GROUP: break;
144 /* existing blender nodes */
145 case BL::ShaderNode::type_RGB: {
146 ColorNode *color = new ColorNode();
147 color->value = get_node_output_rgba(b_node, "Color");
151 case BL::ShaderNode::type_VALUE: {
152 ValueNode *value = new ValueNode();
153 value->value = get_node_output_value(b_node, "Value");
157 case BL::ShaderNode::type_CAMERA: {
158 node = new CameraNode();
161 case BL::ShaderNode::type_MIX_RGB: {
162 BL::ShaderNodeMixRGB b_mix_node(b_node);
163 MixNode *mix = new MixNode();
164 mix->type = MixNode::type_enum[b_mix_node.blend_type()];
168 case BL::ShaderNode::type_SEPRGB: {
169 node = new SeparateRGBNode();
172 case BL::ShaderNode::type_COMBRGB: {
173 node = new CombineRGBNode();
176 case BL::ShaderNode::type_HUE_SAT: {
177 node = new HSVNode();
180 case BL::ShaderNode::type_RGBTOBW: {
181 node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
184 case BL::ShaderNode::type_MATH: {
185 BL::ShaderNodeMath b_math_node(b_node);
186 MathNode *math = new MathNode();
187 math->type = MathNode::type_enum[b_math_node.operation()];
191 case BL::ShaderNode::type_VECT_MATH: {
192 BL::ShaderNodeVectorMath b_vector_math_node(b_node);
193 VectorMathNode *vmath = new VectorMathNode();
194 vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
198 case BL::ShaderNode::type_MAPPING: {
199 BL::ShaderNodeMapping b_mapping_node(b_node);
200 MappingNode *mapping = new MappingNode();
202 get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
209 case BL::ShaderNode::type_OUTPUT_MATERIAL:
210 case BL::ShaderNode::type_OUTPUT_WORLD:
211 case BL::ShaderNode::type_OUTPUT_LAMP: {
212 node = graph->output();
215 case BL::ShaderNode::type_FRESNEL: {
216 node = new FresnelNode();
219 case BL::ShaderNode::type_LAYER_WEIGHT: {
220 node = new LayerWeightNode();
223 case BL::ShaderNode::type_ADD_SHADER: {
224 node = new AddClosureNode();
227 case BL::ShaderNode::type_MIX_SHADER: {
228 node = new MixClosureNode();
231 case BL::ShaderNode::type_ATTRIBUTE: {
232 BL::ShaderNodeAttribute b_attr_node(b_node);
233 AttributeNode *attr = new AttributeNode();
234 attr->attribute = b_attr_node.attribute_name();
238 case BL::ShaderNode::type_BACKGROUND: {
239 node = new BackgroundNode();
242 case BL::ShaderNode::type_HOLDOUT: {
243 node = new HoldoutNode();
246 case BL::ShaderNode::type_BSDF_DIFFUSE: {
247 node = new DiffuseBsdfNode();
250 case BL::ShaderNode::type_BSDF_GLOSSY: {
251 BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
252 GlossyBsdfNode *glossy = new GlossyBsdfNode();
254 switch(b_glossy_node.distribution()) {
255 case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
256 glossy->distribution = ustring("Sharp");
258 case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
259 glossy->distribution = ustring("Beckmann");
261 case BL::ShaderNodeBsdfGlossy::distribution_GGX:
262 glossy->distribution = ustring("GGX");
268 case BL::ShaderNode::type_BSDF_GLASS: {
269 BL::ShaderNodeBsdfGlass b_glass_node(b_node);
270 GlassBsdfNode *glass = new GlassBsdfNode();
271 switch(b_glass_node.distribution()) {
272 case BL::ShaderNodeBsdfGlass::distribution_SHARP:
273 glass->distribution = ustring("Sharp");
275 case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
276 glass->distribution = ustring("Beckmann");
278 case BL::ShaderNodeBsdfGlass::distribution_GGX:
279 glass->distribution = ustring("GGX");
285 case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
286 node = new TranslucentBsdfNode();
289 case BL::ShaderNode::type_BSDF_TRANSPARENT: {
290 node = new TransparentBsdfNode();
293 case BL::ShaderNode::type_BSDF_VELVET: {
294 node = new VelvetBsdfNode();
297 case BL::ShaderNode::type_EMISSION: {
298 node = new EmissionNode();
301 case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
302 node = new IsotropicVolumeNode();
305 case BL::ShaderNode::type_VOLUME_TRANSPARENT: {
306 node = new TransparentVolumeNode();
309 case BL::ShaderNode::type_NEW_GEOMETRY: {
310 node = new GeometryNode();
313 case BL::ShaderNode::type_LIGHT_PATH: {
314 node = new LightPathNode();
317 case BL::ShaderNode::type_TEX_IMAGE: {
318 BL::ShaderNodeTexImage b_image_node(b_node);
319 BL::Image b_image(b_image_node.image());
320 ImageTextureNode *image = new ImageTextureNode();
321 /* todo: handle generated/builtin images */
323 image->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
324 image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
325 get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
329 case BL::ShaderNode::type_TEX_ENVIRONMENT: {
330 BL::ShaderNodeTexEnvironment b_env_node(b_node);
331 BL::Image b_image(b_env_node.image());
332 EnvironmentTextureNode *env = new EnvironmentTextureNode();
334 env->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
335 env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
336 get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
340 case BL::ShaderNode::type_TEX_GRADIENT: {
341 BL::ShaderNodeTexGradient b_gradient_node(b_node);
342 GradientTextureNode *gradient = new GradientTextureNode();
343 gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
344 get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
348 case BL::ShaderNode::type_TEX_VORONOI: {
349 BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
350 VoronoiTextureNode *voronoi = new VoronoiTextureNode();
351 voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
352 get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
356 case BL::ShaderNode::type_TEX_MAGIC: {
357 BL::ShaderNodeTexMagic b_magic_node(b_node);
358 MagicTextureNode *magic = new MagicTextureNode();
359 magic->depth = b_magic_node.turbulence_depth();
360 get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
364 case BL::ShaderNode::type_TEX_WAVE: {
365 BL::ShaderNodeTexWave b_wave_node(b_node);
366 WaveTextureNode *wave = new WaveTextureNode();
367 wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
368 get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
372 case BL::ShaderNode::type_TEX_NOISE: {
373 BL::ShaderNodeTexNoise b_noise_node(b_node);
374 NoiseTextureNode *noise = new NoiseTextureNode();
375 get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
379 case BL::ShaderNode::type_TEX_MUSGRAVE: {
380 BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
381 MusgraveTextureNode *musgrave = new MusgraveTextureNode();
382 musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
383 get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
387 case BL::ShaderNode::type_TEX_COORD: {
388 node = new TextureCoordinateNode();;
391 case BL::ShaderNode::type_TEX_SKY: {
392 BL::ShaderNodeTexSky b_sky_node(b_node);
393 SkyTextureNode *sky = new SkyTextureNode();
394 sky->sun_direction = get_float3(b_sky_node.sun_direction());
395 sky->turbidity = b_sky_node.turbidity();
396 get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
402 if(node && node != graph->output())
408 static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL::NodeSocket b_socket)
410 BL::Node::inputs_iterator b_input;
411 BL::Node::outputs_iterator b_output;
412 string name = b_socket.name();
414 int counter = 0, total = 0;
417 for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
418 if(b_input->name() == name) {
424 if(b_input->ptr.data == b_socket.ptr.data)
429 /* find in outputs */
434 for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
435 if(b_output->name() == name) {
441 if(b_output->ptr.data == b_socket.ptr.data)
446 /* rename if needed */
451 name = string_printf("%s%d", name.c_str(), counter);
453 return SocketPair(node_map[b_node.ptr.data], name);
456 static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::Node *b_group_node, PtrSockMap& sockets_map)
459 BL::ShaderNodeTree::nodes_iterator b_node;
461 map<void*, PtrSockMap> node_groups;
463 for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
464 if(b_node->is_a(&RNA_NodeGroup)) {
465 BL::NodeGroup b_gnode(*b_node);
466 BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree());
468 node_groups[b_node->ptr.data] = PtrSockMap();
469 add_nodes(b_data, graph, b_group_ntree, &b_gnode, node_groups[b_node->ptr.data]);
472 ShaderNode *node = add_node(b_data, graph, b_group_node, BL::ShaderNode(*b_node));
475 BL::Node::inputs_iterator b_input;
476 BL::Node::outputs_iterator b_output;
478 node_map[b_node->ptr.data] = node;
480 for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
481 SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input);
482 ShaderInput *input = pair.first->input(pair.second.c_str());
483 BL::NodeSocket sock(get_node_input(b_group_node, *b_input));
487 /* copy values for non linked inputs */
488 switch(input->type) {
489 case SHADER_SOCKET_FLOAT: {
490 BL::NodeSocketFloatNone value_sock(sock);
491 input->set(value_sock.default_value());
494 case SHADER_SOCKET_COLOR: {
495 BL::NodeSocketRGBA rgba_sock(sock);
496 input->set(get_float3(rgba_sock.default_value()));
499 case SHADER_SOCKET_NORMAL:
500 case SHADER_SOCKET_POINT:
501 case SHADER_SOCKET_VECTOR: {
502 BL::NodeSocketVectorNone vec_sock(sock);
503 input->set(get_float3(vec_sock.default_value()));
506 case SHADER_SOCKET_CLOSURE:
515 BL::NodeTree::links_iterator b_link;
517 for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
518 /* get blender link data */
519 BL::Node b_from_node = b_link->from_node();
520 BL::Node b_to_node = b_link->to_node();
522 BL::NodeSocket b_from_sock = b_link->from_socket();
523 BL::NodeSocket b_to_sock = b_link->to_socket();
525 /* if link with group socket, add to map so we can connect it later */
528 sockets_map[b_from_sock.ptr.data] =
529 node_socket_map_pair(node_map, b_to_node, b_to_sock);
533 else if(!b_to_node) {
534 sockets_map[b_to_sock.ptr.data] =
535 node_socket_map_pair(node_map, b_from_node, b_from_sock);
541 SocketPair from_pair, to_pair;
544 if(b_from_node.is_a(&RNA_NodeGroup)) {
546 BL::NodeSocket group_sock = b_from_sock.group_socket();
547 from_pair = node_groups[b_from_node.ptr.data][group_sock.ptr.data];
551 from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
555 if(b_to_node.is_a(&RNA_NodeGroup)) {
557 BL::NodeSocket group_sock = b_to_sock.group_socket();
558 to_pair = node_groups[b_to_node.ptr.data][group_sock.ptr.data];
562 to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
565 /* in case of groups there may not actually be a node inside the group
566 that the group socket connects to, so from_node or to_node may be NULL */
567 if(from_pair.first && to_pair.first) {
568 ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
569 ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
571 graph->connect(output, input);
578 void BlenderSync::sync_materials()
580 shader_map.set_default(scene->shaders[scene->default_surface]);
583 BL::BlendData::materials_iterator b_mat;
585 for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
588 /* test if we need to sync */
589 if(shader_map.sync(&shader, *b_mat)) {
590 ShaderGraph *graph = new ShaderGraph();
592 shader->name = b_mat->name().c_str();
595 if(b_mat->use_nodes() && b_mat->node_tree()) {
596 PtrSockMap sock_to_node;
597 BL::ShaderNodeTree b_ntree(b_mat->node_tree());
599 add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
602 ShaderNode *closure, *out;
604 closure = graph->add(new DiffuseBsdfNode());
605 closure->input("Color")->value = get_float3(b_mat->diffuse_color());
606 out = graph->output();
608 graph->connect(closure->output("BSDF"), out->input("Surface"));
612 PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
613 shader->sample_as_light = get_boolean(cmat, "sample_as_light");
614 shader->homogeneous_volume = get_boolean(cmat, "homogeneous_volume");
616 shader->set_graph(graph);
617 shader->tag_update(scene);
624 void BlenderSync::sync_world()
626 Background *background = scene->background;
627 Background prevbackground = *background;
629 BL::World b_world = b_scene.world();
631 if(world_recalc || b_world.ptr.data != world_map) {
632 Shader *shader = scene->shaders[scene->default_background];
633 ShaderGraph *graph = new ShaderGraph();
636 if(b_world && b_world.use_nodes() && b_world.node_tree()) {
637 PtrSockMap sock_to_node;
638 BL::ShaderNodeTree b_ntree(b_world.node_tree());
640 add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
643 ShaderNode *closure, *out;
645 closure = graph->add(new BackgroundNode());
646 closure->input("Color")->value = get_float3(b_world.horizon_color());
647 out = graph->output();
649 graph->connect(closure->output("Background"), out->input("Surface"));
652 shader->set_graph(graph);
653 shader->tag_update(scene);
656 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
657 background->transparent = get_boolean(cscene, "film_transparent");
659 if(background->modified(prevbackground))
660 background->tag_update(scene);
662 world_map = b_world.ptr.data;
663 world_recalc = false;
668 void BlenderSync::sync_lamps()
670 shader_map.set_default(scene->shaders[scene->default_light]);
673 BL::BlendData::lamps_iterator b_lamp;
675 for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
678 /* test if we need to sync */
679 if(shader_map.sync(&shader, *b_lamp)) {
680 ShaderGraph *graph = new ShaderGraph();
683 if(b_lamp->use_nodes() && b_lamp->node_tree()) {
684 shader->name = b_lamp->name().c_str();
686 PtrSockMap sock_to_node;
687 BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
689 add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
692 ShaderNode *closure, *out;
693 float strength = 1.0f;
695 if(b_lamp->type() == BL::Lamp::type_POINT ||
696 b_lamp->type() == BL::Lamp::type_SPOT ||
697 b_lamp->type() == BL::Lamp::type_AREA)
700 closure = graph->add(new EmissionNode());
701 closure->input("Color")->value = get_float3(b_lamp->color());
702 closure->input("Strength")->value.x = strength;
703 out = graph->output();
705 graph->connect(closure->output("Emission"), out->input("Surface"));
708 shader->set_graph(graph);
709 shader->tag_update(scene);
714 void BlenderSync::sync_shaders()
716 shader_map.pre_sync();
722 /* false = don't delete unused shaders, not supported */
723 shader_map.post_sync(false);