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