34405c3ea1affb32b2f5d9beff1631ebe59e0f73
[blender-staging.git] / intern / cycles / blender / blender_util.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __BLENDER_UTIL_H__
18 #define __BLENDER_UTIL_H__
19
20 #include "util_map.h"
21 #include "util_path.h"
22 #include "util_set.h"
23 #include "util_transform.h"
24 #include "util_types.h"
25 #include "util_vector.h"
26
27 /* Hacks to hook into Blender API
28  * todo: clean this up ... */
29
30 extern "C" {
31 size_t BLI_timecode_string_from_time_simple(char *str, size_t maxlen, double time_seconds);
32 void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
33 void BKE_image_user_file_path(void *iuser, void *ima, char *path);
34 unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
35 float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
36 }
37
38 CCL_NAMESPACE_BEGIN
39
40 void python_thread_state_save(void **python_thread_state);
41 void python_thread_state_restore(void **python_thread_state);
42
43 static inline BL::Mesh object_to_mesh(BL::BlendData& data,
44                                       BL::Object& object,
45                                       BL::Scene& scene,
46                                       bool apply_modifiers,
47                                       bool render,
48                                       bool calc_undeformed,
49                                       bool subdivision)
50 {
51         BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
52         if((bool)me) {
53                 if(me.use_auto_smooth()) {
54                         me.calc_normals_split();
55                 }
56                 if(!subdivision) {
57                         me.calc_tessface(true);
58                 }
59         }
60         return me;
61 }
62
63 static inline void colorramp_to_array(BL::ColorRamp& ramp,
64                                       array<float3>& ramp_color,
65                                       array<float>& ramp_alpha,
66                                       int size)
67 {
68         ramp_color.resize(size);
69         ramp_alpha.resize(size);
70
71         for(int i = 0; i < size; i++) {
72                 float color[4];
73
74                 ramp.evaluate((float)i/(float)(size-1), color);
75                 ramp_color[i] = make_float3(color[0], color[1], color[2]);
76                 ramp_alpha[i] = color[3];
77         }
78 }
79
80 static inline void curvemap_minmax_curve(/*const*/ BL::CurveMap& curve,
81                                          float *min_x,
82                                          float *max_x)
83 {
84         *min_x = min(*min_x, curve.points[0].location()[0]);
85         *max_x = max(*max_x, curve.points[curve.points.length() - 1].location()[0]);
86 }
87
88 static inline void curvemapping_minmax(/*const*/ BL::CurveMapping& cumap,
89                                        bool rgb_curve,
90                                        float *min_x,
91                                        float *max_x)
92 {
93         /* const int num_curves = cumap.curves.length(); */  /* Gives linking error so far. */
94         const int num_curves = rgb_curve? 4: 3;
95         *min_x = FLT_MAX;
96         *max_x = -FLT_MAX;
97         for(int i = 0; i < num_curves; ++i) {
98                 BL::CurveMap map(cumap.curves[i]);
99                 curvemap_minmax_curve(map, min_x, max_x);
100         }
101 }
102
103 static inline void curvemapping_to_array(BL::CurveMapping& cumap,
104                                          array<float>& data,
105                                          int size)
106 {
107         cumap.update();
108         BL::CurveMap curve = cumap.curves[0];
109         data.resize(size);
110         for(int i = 0; i < size; i++) {
111                 float t = (float)i/(float)(size-1);
112                 data[i] = curve.evaluate(t);
113         }
114 }
115
116 static inline void curvemapping_color_to_array(BL::CurveMapping& cumap,
117                                                array<float3>& data,
118                                                int size,
119                                                bool rgb_curve)
120 {
121         float min_x = 0.0f, max_x = 1.0f;
122
123         /* TODO(sergey): There is no easy way to automatically guess what is
124          * the range to be used here for the case when mapping is applied on
125          * top of another mapping (i.e. R curve applied on top of common
126          * one).
127          *
128          * Using largest possible range form all curves works correct for the
129          * cases like vector curves and should be good enough heuristic for
130          * the color curves as well.
131          *
132          * There might be some better estimations here tho.
133          */
134         curvemapping_minmax(cumap, rgb_curve, &min_x, &max_x);
135
136         const float range_x = max_x - min_x;
137
138         cumap.update();
139
140         BL::CurveMap mapR = cumap.curves[0];
141         BL::CurveMap mapG = cumap.curves[1];
142         BL::CurveMap mapB = cumap.curves[2];
143
144         data.resize(size);
145
146         if(rgb_curve) {
147                 BL::CurveMap mapI = cumap.curves[3];
148
149                 for(int i = 0; i < size; i++) {
150                         float t = min_x + (float)i/(float)(size-1) * range_x;
151
152                         data[i][0] = mapR.evaluate(mapI.evaluate(t));
153                         data[i][1] = mapG.evaluate(mapI.evaluate(t));
154                         data[i][2] = mapB.evaluate(mapI.evaluate(t));
155                 }
156         }
157         else {
158                 for(int i = 0; i < size; i++) {
159                         float t = min_x + (float)i/(float)(size-1) * range_x;
160
161                         data[i][0] = mapR.evaluate(t);
162                         data[i][1] = mapG.evaluate(t);
163                         data[i][2] = mapB.evaluate(t);
164                 }
165         }
166 }
167
168 static inline bool BKE_object_is_modified(BL::Object& self,
169                                           BL::Scene& scene,
170                                           bool preview)
171 {
172         return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
173 }
174
175 static inline bool BKE_object_is_deform_modified(BL::Object& self,
176                                                  BL::Scene& scene,
177                                                  bool preview)
178 {
179         return self.is_deform_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
180 }
181
182 static inline int render_resolution_x(BL::RenderSettings& b_render)
183 {
184         return b_render.resolution_x()*b_render.resolution_percentage()/100;
185 }
186
187 static inline int render_resolution_y(BL::RenderSettings& b_render)
188 {
189         return b_render.resolution_y()*b_render.resolution_percentage()/100;
190 }
191
192 static inline string image_user_file_path(BL::ImageUser& iuser,
193                                           BL::Image& ima,
194                                           int cfra)
195 {
196         char filepath[1024];
197         BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
198         BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
199         return string(filepath);
200 }
201
202 static inline int image_user_frame_number(BL::ImageUser& iuser, int cfra)
203 {
204         BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
205         return iuser.frame_current();
206 }
207
208 static inline unsigned char *image_get_pixels_for_frame(BL::Image& image,
209                                                         int frame)
210 {
211         return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
212 }
213
214 static inline float *image_get_float_pixels_for_frame(BL::Image& image,
215                                                       int frame)
216 {
217         return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
218 }
219
220 /* Utilities */
221
222 static inline Transform get_transform(const BL::Array<float, 16>& array)
223 {
224         Transform tfm;
225
226         /* we assume both types to be just 16 floats, and transpose because blender
227          * use column major matrix order while we use row major */
228         memcpy(&tfm, &array, sizeof(float)*16);
229         tfm = transform_transpose(tfm);
230
231         return tfm;
232 }
233
234 static inline float2 get_float2(const BL::Array<float, 2>& array)
235 {
236         return make_float2(array[0], array[1]);
237 }
238
239 static inline float3 get_float3(const BL::Array<float, 2>& array)
240 {
241         return make_float3(array[0], array[1], 0.0f);
242 }
243
244 static inline float3 get_float3(const BL::Array<float, 3>& array)
245 {
246         return make_float3(array[0], array[1], array[2]);
247 }
248
249 static inline float3 get_float3(const BL::Array<float, 4>& array)
250 {
251         return make_float3(array[0], array[1], array[2]);
252 }
253
254 static inline float4 get_float4(const BL::Array<float, 4>& array)
255 {
256         return make_float4(array[0], array[1], array[2], array[3]);
257 }
258
259 static inline int3 get_int3(const BL::Array<int, 3>& array)
260 {
261         return make_int3(array[0], array[1], array[2]);
262 }
263
264 static inline int4 get_int4(const BL::Array<int, 4>& array)
265 {
266         return make_int4(array[0], array[1], array[2], array[3]);
267 }
268
269 static inline uint get_layer(const BL::Array<int, 20>& array)
270 {
271         uint layer = 0;
272
273         for(uint i = 0; i < 20; i++)
274                 if(array[i])
275                         layer |= (1 << i);
276         
277         return layer;
278 }
279
280 static inline uint get_layer(const BL::Array<int, 20>& array,
281                              const BL::Array<int, 8>& local_array,
282                              bool is_light = false,
283                              uint scene_layers = (1 << 20) - 1)
284 {
285         uint layer = 0;
286
287         for(uint i = 0; i < 20; i++)
288                 if(array[i])
289                         layer |= (1 << i);
290
291         if(is_light) {
292                 /* Consider light is visible if it was visible without layer
293                  * override, which matches behavior of Blender Internal.
294                  */
295                 if(layer & scene_layers) {
296                         for(uint i = 0; i < 8; i++)
297                                 layer |= (1 << (20+i));
298                 }
299         }
300         else {
301                 for(uint i = 0; i < 8; i++)
302                         if(local_array[i])
303                                 layer |= (1 << (20+i));
304         }
305
306         return layer;
307 }
308
309 static inline float3 get_float3(PointerRNA& ptr, const char *name)
310 {
311         float3 f;
312         RNA_float_get_array(&ptr, name, &f.x);
313         return f;
314 }
315
316 static inline void set_float3(PointerRNA& ptr, const char *name, float3 value)
317 {
318         RNA_float_set_array(&ptr, name, &value.x);
319 }
320
321 static inline float4 get_float4(PointerRNA& ptr, const char *name)
322 {
323         float4 f;
324         RNA_float_get_array(&ptr, name, &f.x);
325         return f;
326 }
327
328 static inline void set_float4(PointerRNA& ptr, const char *name, float4 value)
329 {
330         RNA_float_set_array(&ptr, name, &value.x);
331 }
332
333 static inline bool get_boolean(PointerRNA& ptr, const char *name)
334 {
335         return RNA_boolean_get(&ptr, name)? true: false;
336 }
337
338 static inline void set_boolean(PointerRNA& ptr, const char *name, bool value)
339 {
340         RNA_boolean_set(&ptr, name, (int)value);
341 }
342
343 static inline float get_float(PointerRNA& ptr, const char *name)
344 {
345         return RNA_float_get(&ptr, name);
346 }
347
348 static inline void set_float(PointerRNA& ptr, const char *name, float value)
349 {
350         RNA_float_set(&ptr, name, value);
351 }
352
353 static inline int get_int(PointerRNA& ptr, const char *name)
354 {
355         return RNA_int_get(&ptr, name);
356 }
357
358 static inline void set_int(PointerRNA& ptr, const char *name, int value)
359 {
360         RNA_int_set(&ptr, name, value);
361 }
362
363 /* Get a RNA enum value with sanity check: if the RNA value is above num_values
364  * the function will return a fallback default value.
365  *
366  * NOTE: This function assumes that RNA enum values are a continuous sequence
367  * from 0 to num_values-1. Be careful to use it with enums where some values are
368  * deprecated!
369  */
370 static inline int get_enum(PointerRNA& ptr,
371                            const char *name,
372                            int num_values = -1,
373                            int default_value = -1)
374 {
375         int value = RNA_enum_get(&ptr, name);
376         if(num_values != -1 && value >= num_values) {
377                 assert(default_value != -1);
378                 value = default_value;
379         }
380         return value;
381 }
382
383 static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
384 {
385         PropertyRNA *prop = RNA_struct_find_property(&ptr, name);
386         const char *identifier = "";
387         int value = RNA_property_enum_get(&ptr, prop);
388
389         RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
390
391         return string(identifier);
392 }
393
394 static inline void set_enum(PointerRNA& ptr, const char *name, int value)
395 {
396         RNA_enum_set(&ptr, name, value);
397 }
398
399 static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier)
400 {
401         RNA_enum_set_identifier(NULL, &ptr, name, identifier.c_str());
402 }
403
404 static inline string get_string(PointerRNA& ptr, const char *name)
405 {
406         char cstrbuf[1024];
407         char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
408         string str(cstr);
409         if(cstr != cstrbuf)
410                 MEM_freeN(cstr);
411         
412         return str;
413 }
414
415 static inline void set_string(PointerRNA& ptr, const char *name, const string &value)
416 {
417         RNA_string_set(&ptr, name, value.c_str());
418 }
419
420 /* Relative Paths */
421
422 static inline string blender_absolute_path(BL::BlendData& b_data,
423                                            BL::ID& b_id,
424                                            const string& path)
425 {
426         if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
427                 string dirname;
428                 
429                 if(b_id.library()) {
430                         BL::ID b_library_id(b_id.library());
431                         dirname = blender_absolute_path(b_data,
432                                                         b_library_id,
433                                                         b_id.library().filepath());
434                 }
435                 else
436                         dirname = b_data.filepath();
437
438                 return path_join(path_dirname(dirname), path.substr(2));
439         }
440
441         return path;
442 }
443
444 /* Texture Space */
445
446 static inline void mesh_texture_space(BL::Mesh& b_mesh,
447                                       float3& loc,
448                                       float3& size)
449 {
450         loc = get_float3(b_mesh.texspace_location());
451         size = get_float3(b_mesh.texspace_size());
452
453         if(size.x != 0.0f) size.x = 0.5f/size.x;
454         if(size.y != 0.0f) size.y = 0.5f/size.y;
455         if(size.z != 0.0f) size.z = 0.5f/size.z;
456
457         loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
458 }
459
460 /* object used for motion blur */
461 static inline bool object_use_motion(BL::Object& b_parent, BL::Object& b_ob)
462 {
463         PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
464         bool use_motion = get_boolean(cobject, "use_motion_blur");
465         /* If motion blur is enabled for the object we also check
466          * whether it's enabled for the parent object as well.
467          *
468          * This way we can control motion blur from the dupligroup
469          * duplicator much easier.
470          */
471         if(use_motion && b_parent.ptr.data != b_ob.ptr.data) {
472                 PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
473                 use_motion &= get_boolean(parent_cobject, "use_motion_blur");
474         }
475         return use_motion;
476 }
477
478 /* object motion steps */
479 static inline uint object_motion_steps(BL::Object& b_ob)
480 {
481         PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
482         uint steps = get_int(cobject, "motion_steps");
483
484         /* use uneven number of steps so we get one keyframe at the current frame,
485          * and ue 2^(steps - 1) so objects with more/fewer steps still have samples
486          * at the same times, to avoid sampling at many different times */
487         return (2 << (steps - 1)) + 1;
488 }
489
490 /* object uses deformation motion blur */
491 static inline bool object_use_deform_motion(BL::Object& b_parent,
492                                             BL::Object& b_ob)
493 {
494         PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
495         bool use_deform_motion = get_boolean(cobject, "use_deform_motion");
496         /* If motion blur is enabled for the object we also check
497          * whether it's enabled for the parent object as well.
498          *
499          * This way we can control motion blur from the dupligroup
500          * duplicator much easier.
501          */
502         if(use_deform_motion && b_parent.ptr.data != b_ob.ptr.data) {
503                 PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
504                 use_deform_motion &= get_boolean(parent_cobject, "use_deform_motion");
505         }
506         return use_deform_motion;
507 }
508
509 static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
510 {
511         BL::Object::modifiers_iterator b_mod;
512
513         for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
514                 if(b_mod->is_a(&RNA_SmokeModifier)) {
515                         BL::SmokeModifier b_smd(*b_mod);
516
517                         if(b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN)
518                                 return b_smd.domain_settings();
519                 }
520         }
521         
522         return BL::SmokeDomainSettings(PointerRNA_NULL);
523 }
524
525 static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
526 {
527         BL::Object::modifiers_iterator b_mod;
528
529         for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
530                 if(b_mod->is_a(&RNA_FluidSimulationModifier)) {
531                         BL::FluidSimulationModifier b_fmd(*b_mod);
532                         BL::FluidSettings fss = b_fmd.settings();
533
534                         if(fss.type() == BL::FluidSettings::type_DOMAIN)
535                                 return (BL::DomainFluidSettings)b_fmd.settings();
536                 }
537         }
538
539         return BL::DomainFluidSettings(PointerRNA_NULL);
540 }
541
542 /* ID Map
543  *
544  * Utility class to keep in sync with blender data.
545  * Used for objects, meshes, lights and shaders. */
546
547 template<typename K, typename T>
548 class id_map {
549 public:
550         id_map(vector<T*> *scene_data_)
551         {
552                 scene_data = scene_data_;
553         }
554
555         T *find(const BL::ID& id)
556         {
557                 return find(id.ptr.id.data);
558         }
559
560         T *find(const K& key)
561         {
562                 if(b_map.find(key) != b_map.end()) {
563                         T *data = b_map[key];
564                         return data;
565                 }
566
567                 return NULL;
568         }
569
570         void set_recalc(const BL::ID& id)
571         {
572                 b_recalc.insert(id.ptr.data);
573         }
574
575         bool has_recalc()
576         {
577                 return !(b_recalc.empty());
578         }
579
580         void pre_sync()
581         {
582                 used_set.clear();
583         }
584
585         bool sync(T **r_data, const BL::ID& id)
586         {
587                 return sync(r_data, id, id, id.ptr.id.data);
588         }
589
590         bool sync(T **r_data, const BL::ID& id, const BL::ID& parent, const K& key)
591         {
592                 T *data = find(key);
593                 bool recalc;
594
595                 if(!data) {
596                         /* add data if it didn't exist yet */
597                         data = new T();
598                         scene_data->push_back(data);
599                         b_map[key] = data;
600                         recalc = true;
601                 }
602                 else {
603                         recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
604                         if(parent.ptr.data)
605                                 recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
606                 }
607
608                 used(data);
609
610                 *r_data = data;
611                 return recalc;
612         }
613
614         bool is_used(const K& key)
615         {
616                 T *data = find(key);
617                 return (data) ? used_set.find(data) != used_set.end() : false;
618         }
619
620         void used(T *data)
621         {
622                 /* tag data as still in use */
623                 used_set.insert(data);
624         }
625
626         void set_default(T *data)
627         {
628                 b_map[NULL] = data;
629         }
630
631         bool post_sync(bool do_delete = true)
632         {
633                 /* remove unused data */
634                 vector<T*> new_scene_data;
635                 typename vector<T*>::iterator it;
636                 bool deleted = false;
637
638                 for(it = scene_data->begin(); it != scene_data->end(); it++) {
639                         T *data = *it;
640
641                         if(do_delete && used_set.find(data) == used_set.end()) {
642                                 delete data;
643                                 deleted = true;
644                         }
645                         else
646                                 new_scene_data.push_back(data);
647                 }
648
649                 *scene_data = new_scene_data;
650
651                 /* update mapping */
652                 map<K, T*> new_map;
653                 typedef pair<const K, T*> TMapPair;
654                 typename map<K, T*>::iterator jt;
655
656                 for(jt = b_map.begin(); jt != b_map.end(); jt++) {
657                         TMapPair& pair = *jt;
658
659                         if(used_set.find(pair.second) != used_set.end())
660                                 new_map[pair.first] = pair.second;
661                 }
662
663                 used_set.clear();
664                 b_recalc.clear();
665                 b_map = new_map;
666
667                 return deleted;
668         }
669
670 protected:
671         vector<T*> *scene_data;
672         map<K, T*> b_map;
673         set<T*> used_set;
674         set<void*> b_recalc;
675 };
676
677 /* Object Key */
678
679 enum { OBJECT_PERSISTENT_ID_SIZE = 8 };
680
681 struct ObjectKey {
682         void *parent;
683         int id[OBJECT_PERSISTENT_ID_SIZE];
684         void *ob;
685
686         ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_)
687         : parent(parent_), ob(ob_)
688         {
689                 if(id_)
690                         memcpy(id, id_, sizeof(id));
691                 else
692                         memset(id, 0, sizeof(id));
693         }
694
695         bool operator<(const ObjectKey& k) const
696         {
697                 if(ob < k.ob) {
698                         return true;
699                 }
700                 else if(ob == k.ob) {
701                         if(parent < k.parent)
702                                 return true;
703                         else if(parent == k.parent)
704                                 return memcmp(id, k.id, sizeof(id)) < 0;
705                 }
706
707                 return false;
708         }
709 };
710
711 /* Particle System Key */
712
713 struct ParticleSystemKey {
714         void *ob;
715         int id[OBJECT_PERSISTENT_ID_SIZE];
716
717         ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
718         : ob(ob_)
719         {
720                 if(id_)
721                         memcpy(id, id_, sizeof(id));
722                 else
723                         memset(id, 0, sizeof(id));
724         }
725
726         bool operator<(const ParticleSystemKey& k) const
727         {
728                 /* first id is particle index, we don't compare that */
729                 if(ob < k.ob)
730                         return true;
731                 else if(ob == k.ob)
732                         return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0;
733
734                 return false;
735         }
736 };
737
738 CCL_NAMESPACE_END
739
740 #endif /* __BLENDER_UTIL_H__ */
741