Cycles: svn merge -r41266:41467 ^/trunk/blender
[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         switch(b_lamp.type()) {
95                 case BL::Lamp::type_POINT: {
96                         BL::PointLamp b_point_lamp(b_lamp);
97                         light->size = b_point_lamp.shadow_soft_size();
98                         light->type = LIGHT_POINT;
99                         break;
100                 }
101                 case BL::Lamp::type_SPOT: {
102                         BL::SpotLamp b_spot_lamp(b_lamp);
103                         light->size = b_spot_lamp.shadow_soft_size();
104                         light->type = LIGHT_POINT;
105                         break;
106                 }
107                 case BL::Lamp::type_HEMI: {
108                         light->type = LIGHT_DISTANT;
109                         light->size = 0.0f;
110                         break;
111                 }
112                 case BL::Lamp::type_SUN: {
113                         BL::SunLamp b_sun_lamp(b_lamp);
114                         light->size = b_sun_lamp.shadow_soft_size();
115                         light->type = LIGHT_DISTANT;
116                         break;
117                 }
118                 case BL::Lamp::type_AREA: {
119                         BL::AreaLamp b_area_lamp(b_lamp);
120                         light->size = 1.0f;
121                         light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x);
122                         light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y);
123                         light->sizeu = b_area_lamp.size();
124                         if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
125                                 light->sizev = b_area_lamp.size_y();
126                         else
127                                 light->sizev = light->sizeu;
128                         light->type = LIGHT_AREA;
129                         break;
130                 }
131         }
132
133         /* location and (inverted!) direction */
134         light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
135         light->dir = -make_float3(tfm.x.z, tfm.y.z, tfm.z.z);
136
137         /* shader */
138         vector<uint> used_shaders;
139
140         find_shader(b_lamp, used_shaders);
141
142         if(used_shaders.size() == 0)
143                 used_shaders.push_back(scene->default_light);
144
145         light->shader = used_shaders[0];
146
147         /* shadow */
148         PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
149         light->cast_shadow = get_boolean(clamp, "cast_shadow");
150
151         /* tag */
152         light->tag_update(scene);
153 }
154
155 /* Object */
156
157 void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint visibility)
158 {
159         /* light is handled separately */
160         if(object_is_light(b_ob)) {
161                 sync_light(b_parent, b_index, b_ob, tfm);
162                 return;
163         }
164
165         /* only interested in object that we can create meshes from */
166         if(!object_is_mesh(b_ob))
167                 return;
168
169         /* test if we need to sync */
170         ObjectKey key(b_parent, b_index, b_ob);
171         Object *object;
172         bool object_updated = false;
173
174         /* object sync */
175         if(object_map.sync(&object, b_ob, b_parent, key)) {
176                 object->name = b_ob.name().c_str();
177                 object->tfm = tfm;
178                 
179                 object->visibility = object_ray_visibility(b_ob) & visibility;
180                 if(b_parent.ptr.data != b_ob.ptr.data)
181                         object->visibility &= object_ray_visibility(b_parent);
182
183                 object->tag_update(scene);
184                 object_updated = true;
185         }
186
187         /* mesh sync */
188         object->mesh = sync_mesh(b_ob, object_updated);
189 }
190
191 /* Object Loop */
192
193 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
194 {
195         /* layer data */
196         uint scene_layer = render_layer.scene_layer;
197         uint layer = render_layer.layer;
198         
199         /* prepare for sync */
200         light_map.pre_sync();
201         mesh_map.pre_sync();
202         object_map.pre_sync();
203         mesh_synced.clear();
204
205         /* object loop */
206         BL::Scene::objects_iterator b_ob;
207
208         for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
209                 bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
210                 uint ob_layer = get_layer(b_ob->layers());
211
212                 if(!hide && (ob_layer & scene_layer)) {
213                         uint visibility = PATH_RAY_ALL;
214                         
215                         if(!(ob_layer & layer))
216                                 visibility &= ~PATH_RAY_CAMERA;
217
218                         if(b_ob->is_duplicator()) {
219                                 /* dupli objects */
220                                 object_create_duplilist(*b_ob, b_scene);
221
222                                 BL::Object::dupli_list_iterator b_dup;
223                                 int b_index = 0;
224
225                                 for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
226                                         Transform tfm = get_transform(b_dup->matrix());
227                                         sync_object(*b_ob, b_index, b_dup->object(), tfm, visibility);
228                                         b_index++;
229                                 }
230
231                                 object_free_duplilist(*b_ob);
232                         }
233                         else {
234                                 /* object itself */
235                                 Transform tfm = get_transform(b_ob->matrix_world());
236                                 sync_object(*b_ob, 0, *b_ob, tfm, visibility);
237                         }
238                 }
239         }
240
241         /* handle removed data and modified pointers */
242         if(light_map.post_sync())
243                 scene->light_manager->tag_update(scene);
244         if(mesh_map.post_sync())
245                 scene->mesh_manager->tag_update(scene);
246         if(object_map.post_sync())
247                 scene->object_manager->tag_update(scene);
248         mesh_synced.clear();
249 }
250
251 CCL_NAMESPACE_END
252