Cycles: fix a few more msvc issues with empty scenes and ustring setting.
[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 "light.h"
20 #include "mesh.h"
21 #include "object.h"
22 #include "scene.h"
23
24 #include "blender_sync.h"
25 #include "blender_util.h"
26
27 #include "util_foreach.h"
28
29 CCL_NAMESPACE_BEGIN
30
31 /* Utilities */
32
33 bool BlenderSync::object_is_modified(BL::Object b_ob)
34 {
35         /* test if we can instance or if the object is modified */
36         if(ccl::object_is_modified(b_ob, b_scene, preview)) {
37                 /* modifiers */
38                 return true;
39         }
40         else {
41                 /* object level material links */
42                 BL::Object::material_slots_iterator slot;
43                 for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
44                         if(slot->link() == BL::MaterialSlot::link_OBJECT)
45                                 return true;
46         }
47
48         return false;
49 }
50
51 bool BlenderSync::object_is_mesh(BL::Object b_ob)
52 {
53         BL::ID b_ob_data = b_ob.data();
54
55         return (b_ob_data && (b_ob_data.is_a(&RNA_Mesh) ||
56                 b_ob_data.is_a(&RNA_Curve) || b_ob_data.is_a(&RNA_MetaBall)));
57 }
58
59 bool BlenderSync::object_is_light(BL::Object b_ob)
60 {
61         BL::ID b_ob_data = b_ob.data();
62
63         return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
64 }
65
66 static uint object_ray_visibility(BL::Object b_ob)
67 {
68         PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
69         uint flag = 0;
70
71         flag |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
72         flag |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
73         flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
74         flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
75         flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0;
76
77         return flag;
78 }
79
80 /* Light */
81
82 void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
83 {
84         /* test if we need to sync */
85         Light *light;
86         ObjectKey key(b_parent, b_index, b_ob);
87
88         if(!light_map.sync(&light, b_ob, b_parent, key))
89                 return;
90         
91         BL::Lamp b_lamp(b_ob.data());
92
93         /* type */
94 #if 0
95         switch(b_lamp.type()) {
96                 case BL::Lamp::type_POINT: {
97                         BL::PointLamp b_point_lamp(b_lamp);
98                         light->size = b_point_lamp.shadow_soft_size();
99 #endif
100                         light->type = LIGHT_POINT;
101 #if 0
102                         break;
103                 }
104                 case BL::Lamp::type_SPOT: {
105                         BL::SpotLamp b_spot_lamp(b_lamp);
106                         light->size = b_spot_lamp.shadow_soft_size();
107                         light->type = LIGHT_POINT;
108                         break;
109                 }
110                 case BL::Lamp::type_HEMI: {
111                         light->type = LIGHT_DISTANT;
112                         light->size = 0.0f;
113                         break;
114                 }
115                 case BL::Lamp::type_SUN: {
116                         BL::SunLamp b_sun_lamp(b_lamp);
117                         light->size = b_sun_lamp.shadow_soft_size();
118                         light->type = LIGHT_DISTANT;
119                         break;
120                 }
121                 case BL::Lamp::type_AREA: {
122                         BL::AreaLamp b_area_lamp(b_lamp);
123                         light->size = 1.0f;
124                         light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x);
125                         light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y);
126                         light->sizeu = b_area_lamp.size();
127                         if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
128                                 light->sizev = b_area_lamp.size_y();
129                         else
130                                 light->sizev = light->sizeu;
131                         light->type = LIGHT_AREA;
132                         break;
133                 }
134         }
135 #endif
136
137         /* location */
138         light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
139         light->dir = make_float3(tfm.x.z, tfm.y.z, tfm.z.z);
140
141         /* shader */
142         vector<uint> used_shaders;
143
144         find_shader(b_lamp, used_shaders);
145
146         if(used_shaders.size() == 0)
147                 used_shaders.push_back(scene->default_light);
148
149         light->shader = used_shaders[0];
150
151         /* shadow */
152         //PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
153         //light->cast_shadow = get_boolean(clamp, "cast_shadow");
154
155         /* tag */
156         light->tag_update(scene);
157 }
158
159 /* Object */
160
161 void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint visibility)
162 {
163         /* light is handled separately */
164         if(object_is_light(b_ob)) {
165                 sync_light(b_parent, b_index, b_ob, tfm);
166                 return;
167         }
168
169         /* only interested in object that we can create meshes from */
170         if(!object_is_mesh(b_ob))
171                 return;
172
173         /* test if we need to sync */
174         ObjectKey key(b_parent, b_index, b_ob);
175         Object *object;
176         bool object_updated = false;
177
178         /* object sync */
179         if(object_map.sync(&object, b_ob, b_parent, key)) {
180                 object->name = b_ob.name().c_str();
181                 object->tfm = tfm;
182                 
183                 object->visibility = object_ray_visibility(b_ob) & visibility;
184                 if(b_parent.ptr.data != b_ob.ptr.data)
185                         object->visibility &= object_ray_visibility(b_parent);
186
187                 object->tag_update(scene);
188                 object_updated = true;
189         }
190
191         /* mesh sync */
192         object->mesh = sync_mesh(b_ob, object_updated);
193 }
194
195 /* Object Loop */
196
197 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
198 {
199         /* layer data */
200         uint scene_layer = render_layer.scene_layer;
201         uint layer = render_layer.layer;
202         
203         /* prepare for sync */
204         light_map.pre_sync();
205         mesh_map.pre_sync();
206         object_map.pre_sync();
207         mesh_synced.clear();
208
209         /* object loop */
210         BL::Scene::objects_iterator b_ob;
211
212         for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
213                 bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
214                 uint ob_layer = get_layer(b_ob->layers());
215
216                 if(!hide && (ob_layer & scene_layer)) {
217                         uint visibility = PATH_RAY_ALL;
218                         
219                         if(!(ob_layer & layer))
220                                 visibility &= ~PATH_RAY_CAMERA;
221
222                         if(b_ob->is_duplicator()) {
223                                 /* dupli objects */
224                                 object_create_duplilist(*b_ob, b_scene);
225
226                                 BL::Object::dupli_list_iterator b_dup;
227                                 int b_index = 0;
228
229                                 for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
230                                         Transform tfm = get_transform(b_dup->matrix());
231                                         sync_object(*b_ob, b_index, b_dup->object(), tfm, visibility);
232                                         b_index++;
233                                 }
234
235                                 object_free_duplilist(*b_ob);
236                         }
237                         else {
238                                 /* object itself */
239                                 Transform tfm = get_transform(b_ob->matrix_world());
240                                 sync_object(*b_ob, 0, *b_ob, tfm, visibility);
241                         }
242                 }
243         }
244
245         /* handle removed data and modified pointers */
246         if(light_map.post_sync())
247                 scene->light_manager->tag_update(scene);
248         if(mesh_map.post_sync())
249                 scene->mesh_manager->tag_update(scene);
250         if(object_map.post_sync())
251                 scene->object_manager->tag_update(scene);
252         mesh_synced.clear();
253 }
254
255 CCL_NAMESPACE_END
256