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