Cycles: merge of changes from tomato branch.
[blender-staging.git] / intern / cycles / blender / blender_sync.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #include "background.h"
20 #include "film.h"
21 #include "../render/filter.h"
22 #include "graph.h"
23 #include "integrator.h"
24 #include "light.h"
25 #include "mesh.h"
26 #include "nodes.h"
27 #include "object.h"
28 #include "scene.h"
29 #include "shader.h"
30
31 #include "device.h"
32
33 #include "blender_sync.h"
34 #include "blender_util.h"
35
36 #include "util_debug.h"
37 #include "util_foreach.h"
38
39 CCL_NAMESPACE_BEGIN
40
41 /* Constructor */
42
43 BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
44 : b_engine(b_engine_),
45   b_data(b_data_), b_scene(b_scene_),
46   shader_map(&scene_->shaders),
47   object_map(&scene_->objects),
48   mesh_map(&scene_->meshes),
49   light_map(&scene_->lights),
50   particle_system_map(&scene_->particle_systems),
51   world_map(NULL),
52   world_recalc(false),
53   experimental(false),
54   progress(progress_)
55 {
56         scene = scene_;
57         preview = preview_;
58 }
59
60 BlenderSync::~BlenderSync()
61 {
62 }
63
64 /* Sync */
65
66 bool BlenderSync::sync_recalc()
67 {
68         /* sync recalc flags from blender to cycles. actual update is done separate,
69          * so we can do it later on if doing it immediate is not suitable */
70
71         BL::BlendData::materials_iterator b_mat;
72
73         for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat)
74                 if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated()))
75                         shader_map.set_recalc(*b_mat);
76
77         BL::BlendData::lamps_iterator b_lamp;
78
79         for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
80                 if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
81                         shader_map.set_recalc(*b_lamp);
82
83         BL::BlendData::objects_iterator b_ob;
84
85         for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
86                 if(b_ob->is_updated()) {
87                         object_map.set_recalc(*b_ob);
88                         light_map.set_recalc(*b_ob);
89                 }
90
91                 if(object_is_mesh(*b_ob)) {
92                         if(b_ob->is_updated_data() || b_ob->data().is_updated()) {
93                                 BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
94                                 mesh_map.set_recalc(key);
95                         }
96                 }
97                 else if(object_is_light(*b_ob)) {
98                         if(b_ob->is_updated_data() || b_ob->data().is_updated())
99                                 light_map.set_recalc(*b_ob);
100                 }
101                 
102                 if(b_ob->is_updated_data()) {
103                         BL::Object::particle_systems_iterator b_psys;
104                         for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
105                                 particle_system_map.set_recalc(*b_ob);
106                 }
107         }
108
109         BL::BlendData::meshes_iterator b_mesh;
110
111         for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh)
112                 if(b_mesh->is_updated())
113                         mesh_map.set_recalc(*b_mesh);
114
115         BL::BlendData::worlds_iterator b_world;
116
117         for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
118                 if(world_map == b_world->ptr.data &&
119                    (b_world->is_updated() || (b_world->node_tree() && b_world->node_tree().is_updated())))
120                 {
121                         world_recalc = true;
122                 }
123         }
124
125         bool recalc =
126                 shader_map.has_recalc() ||
127                 object_map.has_recalc() ||
128                 light_map.has_recalc() ||
129                 mesh_map.has_recalc() ||
130                 particle_system_map.has_recalc() ||
131                 BlendDataObjects_is_updated_get(&b_data.ptr) ||
132                 world_recalc;
133
134         return recalc;
135 }
136
137 void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const char *layer)
138 {
139         sync_render_layers(b_v3d, layer);
140         sync_integrator();
141         sync_film();
142         sync_shaders();
143         sync_objects(b_v3d);
144         sync_particle_systems();
145         sync_motion(b_v3d, b_override);
146 }
147
148 /* Integrator */
149
150 void BlenderSync::sync_integrator()
151 {
152         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
153
154         experimental = (RNA_enum_get(&cscene, "feature_set") != 0);
155
156         Integrator *integrator = scene->integrator;
157         Integrator previntegrator = *integrator;
158
159         integrator->min_bounce = get_int(cscene, "min_bounces");
160         integrator->max_bounce = get_int(cscene, "max_bounces");
161
162         integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
163         integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
164         integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
165
166         integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
167         integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
168         integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
169
170         integrator->no_caustics = get_boolean(cscene, "no_caustics");
171         integrator->filter_glossy = get_float(cscene, "blur_glossy");
172
173         integrator->seed = get_int(cscene, "seed");
174
175         integrator->layer_flag = render_layer.layer;
176
177         integrator->sample_clamp = get_float(cscene, "sample_clamp");
178 #ifdef __MOTION__
179         integrator->motion_blur = (!preview && r.use_motion_blur());
180 #endif
181
182         integrator->diffuse_samples = get_int(cscene, "diffuse_samples");
183         integrator->glossy_samples = get_int(cscene, "glossy_samples");
184         integrator->transmission_samples = get_int(cscene, "transmission_samples");
185         integrator->ao_samples = get_int(cscene, "ao_samples");
186         integrator->mesh_light_samples = get_int(cscene, "mesh_light_samples");
187         integrator->progressive = get_boolean(cscene, "progressive");
188
189         if(integrator->modified(previntegrator))
190                 integrator->tag_update(scene);
191 }
192
193 /* Film */
194
195 void BlenderSync::sync_film()
196 {
197         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
198
199         Film *film = scene->film;
200         Film prevfilm = *film;
201
202         film->exposure = get_float(cscene, "film_exposure");
203
204         if(film->modified(prevfilm))
205                 film->tag_update(scene);
206
207         Filter *filter = scene->filter;
208         Filter prevfilter = *filter;
209
210         filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
211         filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
212
213         if(filter->modified(prevfilter))
214                 filter->tag_update(scene);
215 }
216
217 /* Render Layer */
218
219 void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
220 {
221         string layername;
222
223         /* 3d view */
224         if(b_v3d) {
225                 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
226
227                 if(RNA_boolean_get(&cscene, "preview_active_layer")) {
228                         BL::RenderLayers layers(b_scene.render().ptr);
229                         layername = layers.active().name();
230                         layer = layername.c_str();
231                 }
232                 else {
233                         render_layer.use_localview = (b_v3d.local_view() ? true : false);
234                         render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview);
235                         render_layer.layer = render_layer.scene_layer;
236                         render_layer.holdout_layer = 0;
237                         render_layer.material_override = PointerRNA_NULL;
238                         render_layer.use_background = true;
239                         render_layer.use_viewport_visibility = true;
240                         render_layer.samples = 0;
241                         return;
242                 }
243         }
244
245         /* render layer */
246         BL::RenderSettings r = b_scene.render();
247         BL::RenderSettings::layers_iterator b_rlay;
248         bool first_layer = true;
249
250         for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
251                 if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
252                         render_layer.name = b_rlay->name();
253                         render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude());
254                         render_layer.layer = get_layer(b_rlay->layers());
255                         render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
256                         render_layer.layer |= render_layer.holdout_layer;
257                         render_layer.material_override = b_rlay->material_override();
258                         render_layer.use_background = b_rlay->use_sky();
259                         render_layer.use_viewport_visibility = false;
260                         render_layer.use_localview = false;
261                         render_layer.samples = b_rlay->samples();
262                 }
263
264                 first_layer = false;
265         }
266 }
267
268 /* Scene Parameters */
269
270 SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
271 {
272         SceneParams params;
273         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
274         int shadingsystem = RNA_enum_get(&cscene, "shading_system");
275
276         if(shadingsystem == 0)
277                 params.shadingsystem = SceneParams::SVM;
278         else if(shadingsystem == 1)
279                 params.shadingsystem = SceneParams::OSL;
280         
281         if(background)
282                 params.bvh_type = SceneParams::BVH_STATIC;
283         else
284                 params.bvh_type = (SceneParams::BVHType)RNA_enum_get(&cscene, "debug_bvh_type");
285
286         params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
287         params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false;
288
289         return params;
290 }
291
292 /* Session Parameters */
293
294 bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background)
295 {
296         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
297         return (background)? false: get_boolean(cscene, "preview_pause");
298 }
299
300 SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
301 {
302         SessionParams params;
303         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
304
305         /* feature set */
306         params.experimental = (RNA_enum_get(&cscene, "feature_set") != 0);
307
308         /* device type */
309         vector<DeviceInfo>& devices = Device::available_devices();
310         
311         /* device default CPU */
312         params.device = devices[0];
313
314         if(RNA_enum_get(&cscene, "device") != 0) {
315                 /* find GPU device with given id */
316                 PointerRNA systemptr = b_userpref.system().ptr;
317                 PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device");
318                 int device_id = b_userpref.system().compute_device();
319
320                 const char *id;
321
322                 if(RNA_property_enum_identifier(NULL, &systemptr, deviceprop, device_id, &id)) {
323                         foreach(DeviceInfo& info, devices)
324                                 if(info.id == id)
325                                         params.device = info;
326                 }
327         }
328
329         /* Background */
330         params.background = background;
331
332         /* samples */
333         if(get_boolean(cscene, "progressive")) {
334                 if(background) {
335                         params.samples = get_int(cscene, "samples");
336                 }
337                 else {
338                         params.samples = get_int(cscene, "preview_samples");
339                         if(params.samples == 0)
340                                 params.samples = INT_MAX;
341                 }
342         }
343         else {
344                 if(background) {
345                         params.samples = get_int(cscene, "aa_samples");
346                 }
347                 else {
348                         params.samples = get_int(cscene, "preview_aa_samples");
349                         if(params.samples == 0)
350                                 params.samples = INT_MAX;
351                 }
352         }
353
354         /* tiles */
355         if(params.device.type != DEVICE_CPU && !background) {
356                 /* currently GPU could be much slower than CPU when using tiles,
357                  * still need to be investigated, but meanwhile make it possible
358                  * to work in viewport smoothly
359                  */
360                 int debug_tile_size = get_int(cscene, "debug_tile_size");
361
362                 params.tile_size = make_int2(debug_tile_size, debug_tile_size);
363         }
364         else {
365                 int tile_x = b_engine.tile_x();
366                 int tile_y = b_engine.tile_y();
367
368                 params.tile_size = make_int2(tile_x, tile_y);
369         }
370
371         params.resolution = 1 << get_int(cscene, "resolution_divider");
372
373         /* other parameters */
374         params.threads = b_scene.render().threads();
375
376         params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");
377         params.reset_timeout = get_float(cscene, "debug_reset_timeout");
378         params.text_timeout = get_float(cscene, "debug_text_timeout");
379
380         if(background) {
381                 params.progressive = false;
382                 params.resolution = 1;
383         }
384         else
385                 params.progressive = true;
386         
387         return params;
388 }
389
390 CCL_NAMESPACE_END
391