Cycles: svn merge -r36352:36495 https://svn.blender.org/svnroot/bf-blender/trunk...
[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(slot = b_ob.material_slots.begin(); 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 /* Light */
67
68 void BlenderSync::sync_light(BL::Object b_ob, Transform& tfm)
69 {
70         /* test if we need to sync */
71         Light *light;
72
73         /* todo: account for instancing */
74         if(!light_map.sync(&light, b_ob))
75                 return;
76
77         /* location */
78         light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
79
80         /* shader */
81         BL::Lamp b_lamp(b_ob.data());
82         vector<uint> used_shaders;
83
84         find_shader(b_lamp, used_shaders);
85
86         if(used_shaders.size() == 0)
87                 used_shaders.push_back(scene->default_light);
88
89         light->shader = used_shaders[0];
90
91         /* tag */
92         light->tag_update(scene);
93 }
94
95 /* Object */
96
97 void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
98 {
99         /* light is handled separately */
100         if(object_is_light(b_ob)) {
101                 sync_light(b_ob, tfm);
102                 return;
103         }
104
105         /* only interested in object that we can create meshes from */
106         if(!object_is_mesh(b_ob))
107                 return;
108
109         /* test if we need to sync */
110         ObjectKey key(b_parent, b_index, b_ob);
111         Object *object;
112         bool object_updated = false;
113
114         /* object sync */
115         if(object_map.sync(&object, b_ob, key)) {
116                 object->name = b_ob.name();
117                 object->tfm = tfm;
118                 object->tag_update(scene);
119                 object_updated = true;
120         }
121
122         /* mesh sync */
123         object->mesh = sync_mesh(b_ob, object_updated);
124 }
125
126 /* Object Loop */
127
128 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
129 {
130         /* layer data */
131         uint layer;
132         
133         if(b_v3d)
134                 layer = get_layer(b_v3d.layers());
135         else
136                 layer = get_layer(b_scene.layers());
137         
138         /* prepare for sync */
139         light_map.pre_sync();
140         mesh_map.pre_sync();
141         object_map.pre_sync();
142
143         /* object loop */
144         BL::Scene::objects_iterator b_ob;
145
146         for(b_ob = b_scene.objects.begin(); b_ob != b_scene.objects.end(); ++b_ob) {
147                 bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
148
149                 if(!hide && get_layer(b_ob->layers()) & layer) {
150                         if(b_ob->is_duplicator()) {
151                                 /* dupli objects */
152                                 object_create_duplilist(*b_ob, b_scene);
153
154                                 BL::Object::dupli_list_iterator b_dup;
155                                 int b_index = 0;
156
157                                 for(b_dup = b_ob->dupli_list.begin(); b_dup != b_ob->dupli_list.end(); ++b_dup) {
158                                         Transform tfm = get_transform(b_dup->matrix());
159                                         sync_object(*b_ob, b_index, b_dup->object(), tfm);
160                                         b_index++;
161                                 }
162
163                                 object_free_duplilist(*b_ob);
164                         }
165                         else {
166                                 /* object itself */
167                                 Transform tfm = get_transform(b_ob->matrix_world());
168                                 sync_object(*b_ob, 0, *b_ob, tfm);
169                         }
170                 }
171         }
172
173         /* handle removed data and modified pointers */
174         if(light_map.post_sync())
175                 scene->light_manager->tag_update(scene);
176         if(mesh_map.post_sync())
177                 scene->mesh_manager->tag_update(scene);
178         if(object_map.post_sync())
179                 scene->object_manager->tag_update(scene);
180 }
181
182 CCL_NAMESPACE_END
183