Blender V2.61 - r43446

blender_object.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "light.h"
00020 #include "mesh.h"
00021 #include "object.h"
00022 #include "scene.h"
00023 
00024 #include "blender_sync.h"
00025 #include "blender_util.h"
00026 
00027 #include "util_foreach.h"
00028 
00029 CCL_NAMESPACE_BEGIN
00030 
00031 /* Utilities */
00032 
00033 bool BlenderSync::object_is_modified(BL::Object b_ob)
00034 {
00035     /* test if we can instance or if the object is modified */
00036     if(ccl::object_is_modified(b_ob, b_scene, preview)) {
00037         /* modifiers */
00038         return true;
00039     }
00040     else {
00041         /* object level material links */
00042         BL::Object::material_slots_iterator slot;
00043         for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
00044             if(slot->link() == BL::MaterialSlot::link_OBJECT)
00045                 return true;
00046     }
00047 
00048     return false;
00049 }
00050 
00051 bool BlenderSync::object_is_mesh(BL::Object b_ob)
00052 {
00053     BL::ID b_ob_data = b_ob.data();
00054 
00055     return (b_ob_data && (b_ob_data.is_a(&RNA_Mesh) ||
00056         b_ob_data.is_a(&RNA_Curve) || b_ob_data.is_a(&RNA_MetaBall)));
00057 }
00058 
00059 bool BlenderSync::object_is_light(BL::Object b_ob)
00060 {
00061     BL::ID b_ob_data = b_ob.data();
00062 
00063     return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
00064 }
00065 
00066 static uint object_ray_visibility(BL::Object b_ob)
00067 {
00068     PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
00069     uint flag = 0;
00070 
00071     flag |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
00072     flag |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
00073     flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
00074     flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
00075     flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0;
00076 
00077     return flag;
00078 }
00079 
00080 /* Light */
00081 
00082 void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
00083 {
00084     /* test if we need to sync */
00085     Light *light;
00086     ObjectKey key(b_parent, b_index, b_ob);
00087 
00088     if(!light_map.sync(&light, b_ob, b_parent, key))
00089         return;
00090     
00091     BL::Lamp b_lamp(b_ob.data());
00092 
00093     /* type */
00094     switch(b_lamp.type()) {
00095         case BL::Lamp::type_POINT: {
00096             BL::PointLamp b_point_lamp(b_lamp);
00097             light->size = b_point_lamp.shadow_soft_size();
00098             light->type = LIGHT_POINT;
00099             break;
00100         }
00101         case BL::Lamp::type_SPOT: {
00102             BL::SpotLamp b_spot_lamp(b_lamp);
00103             light->size = b_spot_lamp.shadow_soft_size();
00104             light->type = LIGHT_POINT;
00105             break;
00106         }
00107         case BL::Lamp::type_HEMI: {
00108             light->type = LIGHT_DISTANT;
00109             light->size = 0.0f;
00110             break;
00111         }
00112         case BL::Lamp::type_SUN: {
00113             BL::SunLamp b_sun_lamp(b_lamp);
00114             light->size = b_sun_lamp.shadow_soft_size();
00115             light->type = LIGHT_DISTANT;
00116             break;
00117         }
00118         case BL::Lamp::type_AREA: {
00119             BL::AreaLamp b_area_lamp(b_lamp);
00120             light->size = 1.0f;
00121             light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x);
00122             light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y);
00123             light->sizeu = b_area_lamp.size();
00124             if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
00125                 light->sizev = b_area_lamp.size_y();
00126             else
00127                 light->sizev = light->sizeu;
00128             light->type = LIGHT_AREA;
00129             break;
00130         }
00131     }
00132 
00133     /* location and (inverted!) direction */
00134     light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
00135     light->dir = -make_float3(tfm.x.z, tfm.y.z, tfm.z.z);
00136 
00137     /* shader */
00138     vector<uint> used_shaders;
00139 
00140     find_shader(b_lamp, used_shaders, scene->default_light);
00141 
00142     if(used_shaders.size() == 0)
00143         used_shaders.push_back(scene->default_light);
00144 
00145     light->shader = used_shaders[0];
00146 
00147     /* shadow */
00148     PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
00149     light->cast_shadow = get_boolean(clamp, "cast_shadow");
00150 
00151     /* tag */
00152     light->tag_update(scene);
00153 }
00154 
00155 /* Object */
00156 
00157 void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag)
00158 {
00159     /* light is handled separately */
00160     if(object_is_light(b_ob)) {
00161         sync_light(b_parent, b_index, b_ob, tfm);
00162         return;
00163     }
00164 
00165     /* only interested in object that we can create meshes from */
00166     if(!object_is_mesh(b_ob))
00167         return;
00168 
00169     /* test if we need to sync */
00170     ObjectKey key(b_parent, b_index, b_ob);
00171     Object *object;
00172     bool object_updated = false;
00173 
00174     if(object_map.sync(&object, b_ob, b_parent, key))
00175         object_updated = true;
00176     
00177     /* mesh sync */
00178     object->mesh = sync_mesh(b_ob, object_updated);
00179 
00180     /* object sync */
00181     if(object_updated || (object->mesh && object->mesh->need_update)) {
00182         object->name = b_ob.name().c_str();
00183         object->tfm = tfm;
00184 
00185         /* visibility flags for both parent */
00186         object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL;
00187         if(b_parent.ptr.data != b_ob.ptr.data)
00188             object->visibility &= object_ray_visibility(b_parent);
00189 
00190         /* camera flag is not actually used, instead is tested
00191            against render layer flags */
00192         if(object->visibility & PATH_RAY_CAMERA) {
00193             object->visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
00194             object->visibility &= ~PATH_RAY_CAMERA;
00195         }
00196 
00197         object->tag_update(scene);
00198     }
00199 }
00200 
00201 /* Object Loop */
00202 
00203 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
00204 {
00205     /* layer data */
00206     uint scene_layer = render_layers.front().scene_layer;
00207     
00208     /* prepare for sync */
00209     light_map.pre_sync();
00210     mesh_map.pre_sync();
00211     object_map.pre_sync();
00212     mesh_synced.clear();
00213 
00214     /* object loop */
00215     BL::Scene::objects_iterator b_ob;
00216 
00217     for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
00218         bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
00219         uint ob_layer = get_layer(b_ob->layers());
00220 
00221         if(!hide && (ob_layer & scene_layer)) {
00222             if(b_ob->is_duplicator()) {
00223                 /* dupli objects */
00224                 object_create_duplilist(*b_ob, b_scene);
00225 
00226                 BL::Object::dupli_list_iterator b_dup;
00227                 int b_index = 0;
00228 
00229                 for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
00230                     Transform tfm = get_transform(b_dup->matrix());
00231                     BL::Object b_dup_ob = b_dup->object();
00232                     bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
00233 
00234                     if(!(b_dup->hide() || dup_hide))
00235                         sync_object(*b_ob, b_index, b_dup_ob, tfm, ob_layer);
00236 
00237                     b_index++;
00238                 }
00239 
00240                 object_free_duplilist(*b_ob);
00241 
00242                 hide = true;
00243             }
00244 
00245             /* check if we should render or hide particle emitter */
00246             BL::Object::particle_systems_iterator b_psys;
00247             bool render_emitter = false;
00248 
00249             for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
00250                 if(b_psys->settings().use_render_emitter()) {
00251                     hide = false;
00252                     render_emitter = true;
00253                 }
00254                 else if(!render_emitter)
00255                     hide = true;
00256             }
00257 
00258             if(!hide) {
00259                 /* object itself */
00260                 Transform tfm = get_transform(b_ob->matrix_world());
00261                 sync_object(*b_ob, 0, *b_ob, tfm, ob_layer);
00262             }
00263         }
00264     }
00265 
00266     /* handle removed data and modified pointers */
00267     if(light_map.post_sync())
00268         scene->light_manager->tag_update(scene);
00269     if(mesh_map.post_sync())
00270         scene->mesh_manager->tag_update(scene);
00271     if(object_map.post_sync())
00272         scene->object_manager->tag_update(scene);
00273     mesh_synced.clear();
00274 }
00275 
00276 CCL_NAMESPACE_END
00277