Cycles / Sampling UI:
[blender.git] / intern / cycles / blender / blender_object.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 #include "camera.h"
18 #include "integrator.h"
19 #include "graph.h"
20 #include "light.h"
21 #include "mesh.h"
22 #include "object.h"
23 #include "scene.h"
24 #include "nodes.h"
25 #include "particles.h"
26 #include "shader.h"
27
28 #include "blender_sync.h"
29 #include "blender_util.h"
30
31 #include "util_foreach.h"
32 #include "util_hash.h"
33
34 CCL_NAMESPACE_BEGIN
35
36 /* Utilities */
37
38 bool BlenderSync::BKE_object_is_modified(BL::Object b_ob)
39 {
40         /* test if we can instance or if the object is modified */
41         if(ccl::BKE_object_is_modified(b_ob, b_scene, preview)) {
42                 /* modifiers */
43                 return true;
44         }
45         else {
46                 /* object level material links */
47                 BL::Object::material_slots_iterator slot;
48                 for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
49                         if(slot->link() == BL::MaterialSlot::link_OBJECT)
50                                 return true;
51         }
52
53         return false;
54 }
55
56 bool BlenderSync::object_is_mesh(BL::Object b_ob)
57 {
58         BL::ID b_ob_data = b_ob.data();
59
60         return (b_ob_data && (b_ob_data.is_a(&RNA_Mesh) ||
61                 b_ob_data.is_a(&RNA_Curve) || b_ob_data.is_a(&RNA_MetaBall)));
62 }
63
64 bool BlenderSync::object_is_light(BL::Object b_ob)
65 {
66         BL::ID b_ob_data = b_ob.data();
67
68         return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
69 }
70
71 static uint object_ray_visibility(BL::Object b_ob)
72 {
73         PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
74         uint flag = 0;
75
76         flag |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
77         flag |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
78         flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
79         flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
80         flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0;
81
82         return flag;
83 }
84
85 /* Light */
86
87 void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm)
88 {
89         /* test if we need to sync */
90         Light *light;
91         ObjectKey key(b_parent, persistent_id, b_ob);
92
93         if(!light_map.sync(&light, b_ob, b_parent, key))
94                 return;
95         
96         BL::Lamp b_lamp(b_ob.data());
97
98         /* type */
99         switch(b_lamp.type()) {
100                 case BL::Lamp::type_POINT: {
101                         BL::PointLamp b_point_lamp(b_lamp);
102                         light->size = b_point_lamp.shadow_soft_size();
103                         light->type = LIGHT_POINT;
104                         break;
105                 }
106                 case BL::Lamp::type_SPOT: {
107                         BL::SpotLamp b_spot_lamp(b_lamp);
108                         light->size = b_spot_lamp.shadow_soft_size();
109                         light->type = LIGHT_SPOT;
110                         light->spot_angle = b_spot_lamp.spot_size();
111                         light->spot_smooth = b_spot_lamp.spot_blend();
112                         break;
113                 }
114                 case BL::Lamp::type_HEMI: {
115                         light->type = LIGHT_DISTANT;
116                         light->size = 0.0f;
117                         break;
118                 }
119                 case BL::Lamp::type_SUN: {
120                         BL::SunLamp b_sun_lamp(b_lamp);
121                         light->size = b_sun_lamp.shadow_soft_size();
122                         light->type = LIGHT_DISTANT;
123                         break;
124                 }
125                 case BL::Lamp::type_AREA: {
126                         BL::AreaLamp b_area_lamp(b_lamp);
127                         light->size = 1.0f;
128                         light->axisu = transform_get_column(&tfm, 0);
129                         light->axisv = transform_get_column(&tfm, 1);
130                         light->sizeu = b_area_lamp.size();
131                         if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
132                                 light->sizev = b_area_lamp.size_y();
133                         else
134                                 light->sizev = light->sizeu;
135                         light->type = LIGHT_AREA;
136                         break;
137                 }
138         }
139
140         /* location and (inverted!) direction */
141         light->co = transform_get_column(&tfm, 3);
142         light->dir = -transform_get_column(&tfm, 2);
143
144         /* shader */
145         vector<uint> used_shaders;
146
147         find_shader(b_lamp, used_shaders, scene->default_light);
148
149         if(used_shaders.size() == 0)
150                 used_shaders.push_back(scene->default_light);
151
152         light->shader = used_shaders[0];
153
154         /* shadow */
155         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
156         PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
157         light->cast_shadow = get_boolean(clamp, "cast_shadow");
158         light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling");
159         
160         int samples = get_int(clamp, "samples");
161         if(get_boolean(cscene, "use_square_samples"))
162                 light->samples = samples * samples;
163         else
164                 light->samples = samples;
165
166         /* visibility */
167         uint visibility = object_ray_visibility(b_ob);
168         light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
169         light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
170         light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
171
172         /* tag */
173         light->tag_update(scene);
174 }
175
176 void BlenderSync::sync_background_light()
177 {
178         BL::World b_world = b_scene.world();
179
180         if(b_world) {
181                 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
182                 PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
183                 bool sample_as_light = get_boolean(cworld, "sample_as_light");
184
185                 if(sample_as_light) {
186                         /* test if we need to sync */
187                         Light *light;
188                         ObjectKey key(b_world, 0, b_world);
189
190                         if(light_map.sync(&light, b_world, b_world, key) ||
191                            world_recalc ||
192                            b_world.ptr.data != world_map)
193                         {
194                                 light->type = LIGHT_BACKGROUND;
195                                 light->map_resolution  = get_int(cworld, "sample_map_resolution");
196                                 light->shader = scene->default_background;
197                                 
198                                 int samples = get_int(cworld, "samples");
199                                 if(get_boolean(cscene, "use_square_samples"))
200                                         light->samples = samples * samples;
201                                 else
202                                         light->samples = samples;
203
204                                 light->tag_update(scene);
205                                 light_map.set_recalc(b_world);
206                         }
207                 }
208         }
209
210         world_map = b_world.ptr.data;
211         world_recalc = false;
212 }
213
214 /* Object */
215
216 Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, bool hide_tris)
217 {
218         BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
219         
220         /* light is handled separately */
221         if(object_is_light(b_ob)) {
222                 /* don't use lamps for excluded layers used as mask layer */
223                 if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer)))
224                         sync_light(b_parent, persistent_id, b_ob, tfm);
225
226                 return NULL;
227         }
228
229         /* only interested in object that we can create meshes from */
230         if(!object_is_mesh(b_ob))
231                 return NULL;
232
233         /* key to lookup object */
234         ObjectKey key(b_parent, persistent_id, b_ob);
235         Object *object;
236
237         /* motion vector case */
238         if(motion) {
239                 object = object_map.find(key);
240
241                 if(object) {
242                         if(tfm != object->tfm) {
243                                 if(motion == -1)
244                                         object->motion.pre = tfm;
245                                 else
246                                         object->motion.post = tfm;
247
248                                 object->use_motion = true;
249                         }
250
251                         /* mesh deformation blur not supported yet */
252                         if(!scene->integrator->motion_blur)
253                                 sync_mesh_motion(b_ob, object->mesh, motion);
254                 }
255
256                 return object;
257         }
258
259         /* test if we need to sync */
260         bool object_updated = false;
261
262         if(object_map.sync(&object, b_ob, b_parent, key))
263                 object_updated = true;
264         
265         bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
266         
267         /* mesh sync */
268         object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
269
270         /* sspecial case not tracked by object update flags */
271         if(use_holdout != object->use_holdout) {
272                 object->use_holdout = use_holdout;
273                 scene->object_manager->tag_update(scene);
274                 object_updated = true;
275         }
276
277         /* object sync
278          * transform comparison should not be needed, but duplis don't work perfect
279          * in the depsgraph and may not signal changes, so this is a workaround */
280         if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
281                 object->name = b_ob.name().c_str();
282                 object->pass_id = b_ob.pass_index();
283                 object->tfm = tfm;
284                 object->motion.pre = tfm;
285                 object->motion.post = tfm;
286                 object->use_motion = false;
287
288                 /* random number */
289                 object->random_id = hash_string(object->name.c_str());
290
291                 if(persistent_id) {
292                         for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++)
293                                 object->random_id = hash_int_2d(object->random_id, persistent_id[i]);
294                 }
295                 else
296                         object->random_id = hash_int_2d(object->random_id, 0);
297
298                 /* visibility flags for both parent */
299                 object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
300                 if(b_parent.ptr.data != b_ob.ptr.data) {
301                         object->visibility &= object_ray_visibility(b_parent);
302                         object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
303                 }
304
305                 /* make holdout objects on excluded layer invisible for non-camera rays */
306                 if(use_holdout && (layer_flag & render_layer.exclude_layer))
307                         object->visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
308
309                 /* camera flag is not actually used, instead is tested
310                  * against render layer flags */
311                 if(object->visibility & PATH_RAY_CAMERA) {
312                         object->visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
313                         object->visibility &= ~PATH_RAY_CAMERA;
314                 }
315
316                 if (b_dupli_ob) {
317                         object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f);
318                         object->dupli_uv = get_float2(b_dupli_ob.uv());
319                 }
320                 else {
321                         object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
322                         object->dupli_uv = make_float2(0.0f, 0.0f);
323                 }
324
325                 object->tag_update(scene);
326         }
327
328         return object;
329 }
330
331 static bool object_render_hide_original(BL::Object::type_enum ob_type, BL::Object::dupli_type_enum dupli_type)
332 {
333         /* metaball exception, they duplicate self */
334         if(ob_type == BL::Object::type_META)
335                 return false;
336
337         return (dupli_type == BL::Object::dupli_type_VERTS ||
338                 dupli_type == BL::Object::dupli_type_FACES ||
339                 dupli_type == BL::Object::dupli_type_FRAMES);
340 }
341
342 static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide, bool& hide_triangles)
343 {
344         /* check if we should render or hide particle emitter */
345         BL::Object::particle_systems_iterator b_psys;
346
347         bool hair_present = false;
348         bool show_emitter = false;
349         bool hide_as_dupli_parent = false;
350         bool hide_as_dupli_child_original = false;
351
352         for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
353                 if((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) &&
354                    (b_psys->settings().type()==BL::ParticleSettings::type_HAIR))
355                         hair_present = true;
356
357                 if(b_psys->settings().use_render_emitter())
358                         show_emitter = true;
359         }
360
361         /* duplicators hidden by default, except dupliframes which duplicate self */
362         if(b_ob.is_duplicator())
363                 if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES)
364                         hide_as_dupli_parent = true;
365
366         /* hide original object for duplis */
367         BL::Object parent = b_ob.parent();
368         if(parent && object_render_hide_original(b_ob.type(), parent.dupli_type()))
369                 if(parent_hide)
370                         hide_as_dupli_child_original = true;
371         
372         if(show_emitter) {
373                 hide_triangles = false;
374                 return false;
375         }
376         else if(hair_present) {
377                 hide_triangles = true;
378                 return hide_as_dupli_child_original;
379         }
380         else {
381                 hide_triangles = false;
382                 return (hide_as_dupli_parent || hide_as_dupli_child_original);
383         }
384 }
385
386 static bool object_render_hide_duplis(BL::Object b_ob)
387 {
388         BL::Object parent = b_ob.parent();
389
390         return (parent && object_render_hide_original(b_ob.type(), parent.dupli_type()));
391 }
392
393 /* Object Loop */
394
395 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
396 {
397         /* layer data */
398         uint scene_layer = render_layer.scene_layer;
399         
400         if(!motion) {
401                 /* prepare for sync */
402                 light_map.pre_sync();
403                 mesh_map.pre_sync();
404                 object_map.pre_sync();
405                 mesh_synced.clear();
406                 particle_system_map.pre_sync();
407         }
408
409         /* object loop */
410         BL::Scene::objects_iterator b_ob;
411         BL::Scene b_sce = b_scene;
412
413         /* global particle index counter */
414         int particle_id = 1;
415
416         bool cancel = false;
417
418         for(; b_sce && !cancel; b_sce = b_sce.background_set()) {
419                 for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end() && !cancel; ++b_ob) {
420                         bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
421                         uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob));
422                         hide = hide || !(ob_layer & scene_layer);
423
424                         if(!hide) {
425                                 progress.set_sync_status("Synchronizing object", (*b_ob).name());
426
427                                 if(b_ob->is_duplicator() && !object_render_hide_duplis(*b_ob)) {
428                                         /* dupli objects */
429                                         b_ob->dupli_list_create(b_scene, 2);
430
431                                         BL::Object::dupli_list_iterator b_dup;
432
433                                         for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
434                                                 Transform tfm = get_transform(b_dup->matrix());
435                                                 BL::Object b_dup_ob = b_dup->object();
436                                                 bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
437                                                 bool in_dupli_group = (b_dup->type() == BL::DupliObject::type_GROUP);
438                                                 bool hide_tris;
439
440                                                 if(!(b_dup->hide() || dup_hide || object_render_hide(b_dup_ob, false, in_dupli_group, hide_tris))) {
441                                                         /* the persistent_id allows us to match dupli objects
442                                                          * between frames and updates */
443                                                         BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();
444
445                                                         /* sync object and mesh or light data */
446                                                         Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion, hide_tris);
447
448                                                         /* sync possible particle data, note particle_id
449                                                          * starts counting at 1, first is dummy particle */
450                                                         if(!motion && object && sync_dupli_particle(*b_ob, *b_dup, object)) {
451                                                                 if(particle_id != object->particle_id) {
452                                                                         object->particle_id = particle_id;
453                                                                         scene->object_manager->tag_update(scene);
454                                                                 }
455
456                                                                 particle_id++;
457                                                         }
458
459                                                 }
460                                         }
461
462                                         b_ob->dupli_list_clear();
463                                 }
464
465                                 /* test if object needs to be hidden */
466                                 bool hide_tris;
467
468                                 if(!object_render_hide(*b_ob, true, true, hide_tris)) {
469                                         /* object itself */
470                                         Transform tfm = get_transform(b_ob->matrix_world());
471                                         sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion, hide_tris);
472                                 }
473                         }
474
475                         cancel = progress.get_cancel();
476                 }
477         }
478
479         progress.set_sync_status("");
480
481         if(!cancel && !motion) {
482                 sync_background_light();
483
484                 /* handle removed data and modified pointers */
485                 if(light_map.post_sync())
486                         scene->light_manager->tag_update(scene);
487                 if(mesh_map.post_sync())
488                         scene->mesh_manager->tag_update(scene);
489                 if(object_map.post_sync())
490                         scene->object_manager->tag_update(scene);
491                 if(particle_system_map.post_sync())
492                         scene->particle_system_manager->tag_update(scene);
493                 mesh_synced.clear();
494         }
495 }
496
497 void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override)
498 {
499         if(scene->need_motion() == Scene::MOTION_NONE)
500                 return;
501
502         /* get camera object here to deal with camera switch */
503         BL::Object b_cam = b_scene.camera();
504         if(b_override)
505                 b_cam = b_override;
506
507         Camera prevcam = *(scene->camera);
508         
509         /* go back and forth one frame */
510         int frame = b_scene.frame_current();
511
512         for(int motion = -1; motion <= 1; motion += 2) {
513                 b_scene.frame_set(frame + motion, 0.0f);
514
515                 /* camera object */
516                 if(b_cam)
517                         sync_camera_motion(b_cam, motion);
518
519                 /* mesh objects */
520                 sync_objects(b_v3d, motion);
521         }
522
523         b_scene.frame_set(frame, 0.0f);
524
525         /* tag camera for motion update */
526         if(scene->camera->motion_modified(prevcam))
527                 scene->camera->tag_update();
528 }
529
530 CCL_NAMESPACE_END
531