Cycles: add "From Dupli" option for texture coordinate node. This gets the
[blender.git] / intern / cycles / blender / blender_util.h
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 #ifndef __BLENDER_UTIL_H__
20 #define __BLENDER_UTIL_H__
21
22 #include "util_map.h"
23 #include "util_path.h"
24 #include "util_set.h"
25 #include "util_transform.h"
26 #include "util_types.h"
27 #include "util_vector.h"
28
29 /* Hacks to hook into Blender API
30  * todo: clean this up ... */
31
32 extern "C" {
33
34 struct RenderEngine;
35 struct RenderResult;
36
37 ID *rna_Object_to_mesh(void *_self, void *reports, void *scene, int apply_modifiers, int settings);
38 void rna_Main_meshes_remove(void *bmain, void *reports, void *mesh);
39 void rna_Object_create_duplilist(void *ob, void *reports, void *sce, int settings);
40 void rna_Object_free_duplilist(void *ob);
41 void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
42 void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
43 struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h, const char *layername);
44 void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result);
45 void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result, int cancel);
46 int RE_engine_test_break(struct RenderEngine *engine);
47 void RE_engine_update_stats(struct RenderEngine *engine, const char *stats, const char *info);
48 void RE_engine_update_progress(struct RenderEngine *engine, float progress);
49 void engine_tag_redraw(void *engine);
50 void engine_tag_update(void *engine);
51 int rna_Object_is_modified(void *ob, void *scene, int settings);
52 int rna_Object_is_deform_modified(void *ob, void *scene, int settings);
53 void BLI_timestr(double _time, char *str);
54 void rna_ColorRamp_eval(void *coba, float position, float color[4]);
55 void rna_Scene_frame_set(void *scene, int frame, float subframe);
56 void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
57 void BKE_image_user_file_path(void *iuser, void *ima, char *path);
58 }
59
60 CCL_NAMESPACE_BEGIN
61
62 static inline BL::Mesh object_to_mesh(BL::Object self, BL::Scene scene, bool apply_modifiers, bool render)
63 {
64         ID *data = rna_Object_to_mesh(self.ptr.data, NULL, scene.ptr.data, apply_modifiers, (render)? 2: 1);
65         PointerRNA ptr;
66         RNA_id_pointer_create(data, &ptr);
67         return BL::Mesh(ptr);
68 }
69
70 static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size)
71 {
72         for(int i = 0; i < size; i++) {
73                 float color[4];
74
75                 rna_ColorRamp_eval(ramp.ptr.data, i/(float)(size-1), color);
76                 data[i] = make_float4(color[0], color[1], color[2], color[3]);
77         }
78 }
79
80 static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh)
81 {
82         rna_Main_meshes_remove(data.ptr.data, NULL, mesh.ptr.data);
83 }
84
85 static inline void object_create_duplilist(BL::Object self, BL::Scene scene)
86 {
87         rna_Object_create_duplilist(self.ptr.data, NULL, scene.ptr.data, 2);
88 }
89
90 static inline void object_free_duplilist(BL::Object self)
91 {
92         rna_Object_free_duplilist(self.ptr.data);
93 }
94
95 static inline bool BKE_object_is_modified(BL::Object self, BL::Scene scene, bool preview)
96 {
97         return rna_Object_is_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false;
98 }
99
100 static inline bool BKE_object_is_deform_modified(BL::Object self, BL::Scene scene, bool preview)
101 {
102         return rna_Object_is_deform_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false;
103 }
104
105 static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, int cfra)
106 {
107         char filepath[1024];
108         BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
109         BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
110         return string(filepath);
111 }
112
113 static inline void scene_frame_set(BL::Scene scene, int frame)
114 {
115         rna_Scene_frame_set(scene.ptr.data, frame, 0.0f);
116 }
117
118 /* Utilities */
119
120 static inline Transform get_transform(BL::Array<float, 16> array)
121 {
122         Transform tfm;
123
124         /* we assume both types to be just 16 floats, and transpose because blender
125          * use column major matrix order while we use row major */
126         memcpy(&tfm, &array, sizeof(float)*16);
127         tfm = transform_transpose(tfm);
128
129         return tfm;
130 }
131
132 static inline float2 get_float2(BL::Array<float, 2> array)
133 {
134         return make_float2(array[0], array[1]);
135 }
136
137 static inline float3 get_float3(BL::Array<float, 2> array)
138 {
139         return make_float3(array[0], array[1], 0.0f);
140 }
141
142 static inline float3 get_float3(BL::Array<float, 3> array)
143 {
144         return make_float3(array[0], array[1], array[2]);
145 }
146
147 static inline float3 get_float3(BL::Array<float, 4> array)
148 {
149         return make_float3(array[0], array[1], array[2]);
150 }
151
152 static inline float4 get_float4(BL::Array<float, 4> array)
153 {
154         return make_float4(array[0], array[1], array[2], array[3]);
155 }
156
157 static inline int4 get_int4(BL::Array<int, 4> array)
158 {
159         return make_int4(array[0], array[1], array[2], array[3]);
160 }
161
162 static inline uint get_layer(BL::Array<int, 20> array)
163 {
164         uint layer = 0;
165
166         for(uint i = 0; i < 20; i++)
167                 if(array[i])
168                         layer |= (1 << i);
169         
170         return layer;
171 }
172
173 static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_array, bool use_local, bool is_light = false)
174 {
175         uint layer = 0;
176
177         for(uint i = 0; i < 20; i++)
178                 if(array[i])
179                         layer |= (1 << i);
180
181         if(is_light) {
182                 /* consider lamps on all local view layers */
183                 for(uint i = 0; i < 8; i++)
184                         layer |= (1 << (20+i));
185         }
186         else {
187                 for(uint i = 0; i < 8; i++)
188                         if(local_array[i])
189                                 layer |= (1 << (20+i));
190         }
191
192         /* we don't have spare bits for localview (normally 20-28) because
193          * PATH_RAY_LAYER_SHIFT uses 20-32. So - check if we have localview and if
194          * so, shift local view bits down to 1-8, since this is done for the view
195          * port only - it should be OK and not conflict with render layers. */
196         if(use_local)
197                 layer >>= 20;
198
199         return layer;
200 }
201
202 #if 0
203 static inline float3 get_float3(PointerRNA& ptr, const char *name)
204 {
205         float3 f;
206         RNA_float_get_array(&ptr, name, &f.x);
207         return f;
208 }
209 #endif
210
211 static inline bool get_boolean(PointerRNA& ptr, const char *name)
212 {
213         return RNA_boolean_get(&ptr, name)? true: false;
214 }
215
216 static inline float get_float(PointerRNA& ptr, const char *name)
217 {
218         return RNA_float_get(&ptr, name);
219 }
220
221 static inline int get_int(PointerRNA& ptr, const char *name)
222 {
223         return RNA_int_get(&ptr, name);
224 }
225
226 static inline int get_enum(PointerRNA& ptr, const char *name)
227 {
228         return RNA_enum_get(&ptr, name);
229 }
230
231 static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
232 {
233         PropertyRNA *prop = RNA_struct_find_property(&ptr, name);
234         const char *identifier = "";
235         int value = RNA_property_enum_get(&ptr, prop);
236
237         RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
238
239         return string(identifier);
240 }
241
242 /* Relative Paths */
243
244 static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path)
245 {
246         if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
247                 string dirname;
248                 
249                 if(b_id.library())
250                         dirname = blender_absolute_path(b_data, b_id.library(), b_id.library().filepath());
251                 else
252                         dirname = b_data.filepath();
253
254                 return path_join(path_dirname(dirname), path.substr(2));
255         }
256
257         return path;
258 }
259
260 /* ID Map
261  *
262  * Utility class to keep in sync with blender data.
263  * Used for objects, meshes, lights and shaders. */
264
265 template<typename K, typename T>
266 class id_map {
267 public:
268         id_map(vector<T*> *scene_data_)
269         {
270                 scene_data = scene_data_;
271         }
272
273         T *find(BL::ID id)
274         {
275                 return find(id.ptr.id.data);
276         }
277
278         T *find(const K& key)
279         {
280                 if(b_map.find(key) != b_map.end()) {
281                         T *data = b_map[key];
282                         return data;
283                 }
284
285                 return NULL;
286         }
287
288         void set_recalc(BL::ID id)
289         {
290                 b_recalc.insert(id.ptr.data);
291         }
292
293         bool has_recalc()
294         {
295                 return !(b_recalc.empty());
296         }
297
298         void pre_sync()
299         {
300                 used_set.clear();
301         }
302
303         bool sync(T **r_data, BL::ID id)
304         {
305                 return sync(r_data, id, id, id.ptr.id.data);
306         }
307
308         bool sync(T **r_data, BL::ID id, BL::ID parent, const K& key)
309         {
310                 T *data = find(key);
311                 bool recalc;
312
313                 if(!data) {
314                         /* add data if it didn't exist yet */
315                         data = new T();
316                         scene_data->push_back(data);
317                         b_map[key] = data;
318                         recalc = true;
319                 }
320                 else {
321                         recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
322                         if(parent.ptr.data)
323                                 recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
324                 }
325
326                 used(data);
327
328                 *r_data = data;
329                 return recalc;
330         }
331
332         void used(T *data)
333         {
334                 /* tag data as still in use */
335                 used_set.insert(data);
336         }
337
338         void set_default(T *data)
339         {
340                 b_map[NULL] = data;
341         }
342
343         bool post_sync(bool do_delete = true)
344         {
345                 /* remove unused data */
346                 vector<T*> new_scene_data;
347                 typename vector<T*>::iterator it;
348                 bool deleted = false;
349
350                 for(it = scene_data->begin(); it != scene_data->end(); it++) {
351                         T *data = *it;
352
353                         if(do_delete && used_set.find(data) == used_set.end()) {
354                                 delete data;
355                                 deleted = true;
356                         }
357                         else
358                                 new_scene_data.push_back(data);
359                 }
360
361                 *scene_data = new_scene_data;
362
363                 /* update mapping */
364                 map<K, T*> new_map;
365                 typedef pair<const K, T*> TMapPair;
366                 typename map<K, T*>::iterator jt;
367
368                 for(jt = b_map.begin(); jt != b_map.end(); jt++) {
369                         TMapPair& pair = *jt;
370
371                         if(used_set.find(pair.second) != used_set.end())
372                                 new_map[pair.first] = pair.second;
373                 }
374
375                 used_set.clear();
376                 b_recalc.clear();
377                 b_map = new_map;
378
379                 return deleted;
380         }
381
382 protected:
383         vector<T*> *scene_data;
384         map<K, T*> b_map;
385         set<T*> used_set;
386         set<void*> b_recalc;
387 };
388
389 /* Object Key */
390
391 struct ObjectKey {
392         void *parent;
393         int index;
394         void *ob;
395
396         ObjectKey(void *parent_, int index_, void *ob_)
397         : parent(parent_), index(index_), ob(ob_) {}
398
399         bool operator<(const ObjectKey& k) const
400         { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); }
401 };
402
403 struct ParticleSystemKey {
404         void *ob;
405         void *psys;
406
407         ParticleSystemKey(void *ob_, void *psys_)
408         : ob(ob_), psys(psys_) {}
409
410         bool operator<(const ParticleSystemKey& k) const
411         { return (ob < k.ob && psys < k.psys); }
412 };
413
414 CCL_NAMESPACE_END
415
416 #endif /* __BLENDER_UTIL_H__ */
417