2 * Copyright 2011, Blender Foundation.
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.
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.
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.
24 #include "blender_sync.h"
25 #include "blender_util.h"
27 #include "util_foreach.h"
33 bool BlenderSync::object_is_modified(BL::Object b_ob)
35 /* test if we can instance or if the object is modified */
36 if(ccl::object_is_modified(b_ob, b_scene, preview)) {
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)
51 bool BlenderSync::object_is_mesh(BL::Object b_ob)
53 BL::ID b_ob_data = b_ob.data();
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)));
59 bool BlenderSync::object_is_light(BL::Object b_ob)
61 BL::ID b_ob_data = b_ob.data();
63 return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
66 static uint object_ray_visibility(BL::Object b_ob)
68 PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
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;
82 void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
84 /* test if we need to sync */
86 ObjectKey key(b_parent, b_index, b_ob);
88 if(!light_map.sync(&light, b_ob, b_parent, key))
91 BL::Lamp b_lamp(b_ob.data());
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;
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;
107 case BL::Lamp::type_HEMI: {
108 light->type = LIGHT_DISTANT;
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;
118 case BL::Lamp::type_AREA: {
119 BL::AreaLamp b_area_lamp(b_lamp);
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();
127 light->sizev = light->sizeu;
128 light->type = LIGHT_AREA;
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);
138 vector<uint> used_shaders;
140 find_shader(b_lamp, used_shaders, scene->default_light);
142 if(used_shaders.size() == 0)
143 used_shaders.push_back(scene->default_light);
145 light->shader = used_shaders[0];
148 PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
149 light->cast_shadow = get_boolean(clamp, "cast_shadow");
152 light->tag_update(scene);
157 void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag)
159 /* light is handled separately */
160 if(object_is_light(b_ob)) {
161 sync_light(b_parent, b_index, b_ob, tfm);
165 /* only interested in object that we can create meshes from */
166 if(!object_is_mesh(b_ob))
169 /* test if we need to sync */
170 ObjectKey key(b_parent, b_index, b_ob);
172 bool object_updated = false;
174 if(object_map.sync(&object, b_ob, b_parent, key))
175 object_updated = true;
178 object->mesh = sync_mesh(b_ob, object_updated);
181 if(object_updated || (object->mesh && object->mesh->need_update)) {
182 object->name = b_ob.name().c_str();
185 /* visibility flags for both parent */
186 object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL;
187 if(b_parent.ptr.data != b_ob.ptr.data)
188 object->visibility &= object_ray_visibility(b_parent);
190 /* camera flag is not actually used, instead is tested
191 against render layer flags */
192 if(object->visibility & PATH_RAY_CAMERA) {
193 object->visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
194 object->visibility &= ~PATH_RAY_CAMERA;
197 object->tag_update(scene);
203 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
206 uint scene_layer = render_layers.front().scene_layer;
208 /* prepare for sync */
209 light_map.pre_sync();
211 object_map.pre_sync();
215 BL::Scene::objects_iterator b_ob;
217 for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
218 bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
219 uint ob_layer = get_layer(b_ob->layers());
221 if(!hide && (ob_layer & scene_layer)) {
222 if(b_ob->is_duplicator()) {
224 object_create_duplilist(*b_ob, b_scene);
226 BL::Object::dupli_list_iterator b_dup;
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, ob_layer);
235 object_free_duplilist(*b_ob);
240 /* check if we should render or hide particle emitter */
241 BL::Object::particle_systems_iterator b_psys;
242 bool render_emitter = false;
244 for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
245 if(b_psys->settings().use_render_emitter()) {
247 render_emitter = true;
249 else if(!render_emitter)
255 Transform tfm = get_transform(b_ob->matrix_world());
256 sync_object(*b_ob, 0, *b_ob, tfm, ob_layer);
261 /* handle removed data and modified pointers */
262 if(light_map.post_sync())
263 scene->light_manager->tag_update(scene);
264 if(mesh_map.post_sync())
265 scene->mesh_manager->tag_update(scene);
266 if(object_map.post_sync())
267 scene->object_manager->tag_update(scene);