Bake-API: increase cage extrusion/ray distance limit
[blender.git] / source / blender / editors / object / object_bake_api.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2004 by Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s):
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/object/object_bake_api.c
29  *  \ingroup edobj
30  */
31
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_object_types.h"
36 #include "DNA_mesh_types.h"
37 #include "DNA_material_types.h"
38
39 #include "RNA_access.h"
40 #include "RNA_define.h"
41 #include "RNA_enum_types.h"
42
43 #include "BLI_listbase.h"
44 #include "BLI_string.h"
45 #include "BLI_fileops.h"
46 #include "BLI_math_geom.h"
47 #include "BLI_path_util.h"
48
49 #include "BKE_context.h"
50 #include "BKE_global.h"
51 #include "BKE_image.h"
52 #include "BKE_library.h"
53 #include "BKE_main.h"
54 #include "BKE_report.h"
55 #include "BKE_modifier.h"
56 #include "BKE_mesh.h"
57 #include "BKE_screen.h"
58
59 #include "RE_engine.h"
60 #include "RE_pipeline.h"
61
62 #include "IMB_imbuf_types.h"
63 #include "IMB_imbuf.h"
64 #include "IMB_colormanagement.h"
65
66 #include "WM_api.h"
67 #include "WM_types.h"
68
69 #include "ED_object.h"
70 #include "ED_screen.h"
71 #include "ED_uvedit.h"
72
73 #include "GPU_draw.h"
74
75 #include "object_intern.h"
76
77 /* catch esc */
78 static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
79 {
80         /* no running blender, remove handler and pass through */
81         if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE))
82                 return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
83
84         /* running render */
85         switch (event->type) {
86                 case ESCKEY:
87                 {
88                         G.is_break = true;
89                         return OPERATOR_RUNNING_MODAL;
90                 }
91         }
92         return OPERATOR_PASS_THROUGH;
93 }
94
95 /* for exec() when there is no render job
96  * note: this wont check for the escape key being pressed, but doing so isnt threadsafe */
97 static int bake_break(void *UNUSED(rjv))
98 {
99         if (G.is_break)
100                 return 1;
101         return 0;
102 }
103
104
105 static void bake_update_image(ScrArea *sa, Image *image)
106 {
107         if (sa && sa->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
108                 SpaceImage *sima = sa->spacedata.first;
109                 if (sima)
110                         sima->image = image;
111         }
112 }
113
114 static bool write_internal_bake_pixels(
115         Image *image, BakePixel pixel_array[], float *buffer,
116         const int width, const int height, const int margin,
117         const bool is_clear, const bool is_noncolor)
118 {
119         ImBuf *ibuf;
120         void *lock;
121         bool is_float;
122         char *mask_buffer = NULL;
123         const int num_pixels = width * height;
124
125         ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
126
127         if (!ibuf)
128                 return false;
129
130         if (margin > 0 || !is_clear) {
131                 mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
132                 RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
133         }
134
135         is_float = (ibuf->flags & IB_rectfloat);
136
137         /* colormanagement conversions */
138         if (!is_noncolor) {
139                 const char *from_colorspace;
140                 const char *to_colorspace;
141
142                 from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
143
144                 if (is_float)
145                         to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
146                 else
147                         to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
148
149                 if (from_colorspace != to_colorspace)
150                         IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
151         }
152
153         /* populates the ImBuf */
154         if (is_clear) {
155                 if (is_float) {
156                         IMB_buffer_float_from_float(
157                                 ibuf->rect_float, buffer, ibuf->channels,
158                                 IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
159                                 ibuf->x, ibuf->y, ibuf->x, ibuf->y);
160                 }
161                 else {
162                         IMB_buffer_byte_from_float(
163                                 (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
164                                 IB_PROFILE_SRGB, IB_PROFILE_SRGB,
165                                 false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
166                 }
167         }
168         else {
169                 if (is_float) {
170                         IMB_buffer_float_from_float_mask(
171                                 ibuf->rect_float, buffer, ibuf->channels,
172                                 ibuf->x, ibuf->y, ibuf->x, ibuf->y, mask_buffer);
173                 }
174                 else {
175                         IMB_buffer_byte_from_float_mask(
176                                 (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
177                                 false, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
178                 }
179         }
180
181         /* margins */
182         if (margin > 0)
183                 RE_bake_margin(ibuf, mask_buffer, margin);
184
185         ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
186
187         if (ibuf->rect_float)
188                 ibuf->userflags |= IB_RECT_INVALID;
189
190         /* force mipmap recalc */
191         if (ibuf->mipmap[0]) {
192                 ibuf->userflags |= IB_MIPMAP_INVALID;
193                 imb_freemipmapImBuf(ibuf);
194         }
195
196         BKE_image_release_ibuf(image, ibuf, NULL);
197
198         if (mask_buffer)
199                 MEM_freeN(mask_buffer);
200
201         return true;
202 }
203
204 /* force OpenGL reload */
205 static void reset_images_gpu(BakeImages *bake_images)
206 {
207         int i;
208         for (i = 0; i < bake_images->size; i++) {
209                 Image *ima = bake_images->data[i].image;
210                 if (ima->ok == IMA_OK_LOADED) {
211                         GPU_free_image(ima);
212                 }
213         }
214 }
215
216 static bool write_external_bake_pixels(
217         const char *filepath, BakePixel pixel_array[], float *buffer,
218         const int width, const int height, const int margin,
219         ImageFormatData *im_format, const bool is_noncolor)
220 {
221         ImBuf *ibuf = NULL;
222         bool ok = false;
223         bool is_float;
224
225         is_float = im_format->depth > 8;
226
227         /* create a new ImBuf */
228         ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect));
229
230         if (!ibuf)
231                 return false;
232
233         /* populates the ImBuf */
234         if (is_float) {
235                 IMB_buffer_float_from_float(
236                         ibuf->rect_float, buffer, ibuf->channels,
237                         IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
238                         ibuf->x, ibuf->y, ibuf->x, ibuf->y);
239         }
240         else {
241                 if (!is_noncolor) {
242                         const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
243                         const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
244                         IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
245                 }
246
247                 IMB_buffer_byte_from_float(
248                         (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
249                         IB_PROFILE_SRGB, IB_PROFILE_SRGB,
250                         false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
251         }
252
253         /* margins */
254         if (margin > 0) {
255                 char *mask_buffer = NULL;
256                 const int num_pixels = width * height;
257
258                 mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
259                 RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
260                 RE_bake_margin(ibuf, mask_buffer, margin);
261
262                 if (mask_buffer)
263                         MEM_freeN(mask_buffer);
264         }
265
266         if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
267 #ifndef WIN32
268                 chmod(filepath, S_IRUSR | S_IWUSR);
269 #endif
270                 //printf("%s saving bake map: '%s'\n", __func__, filepath);
271         }
272
273         /* garbage collection */
274         IMB_freeImBuf(ibuf);
275
276         return ok;
277 }
278
279 static bool is_noncolor_pass(ScenePassType pass_type)
280 {
281         return ELEM7(pass_type,
282                      SCE_PASS_Z,
283                      SCE_PASS_NORMAL,
284                      SCE_PASS_VECTOR,
285                      SCE_PASS_INDEXOB,
286                      SCE_PASS_UV,
287                      SCE_PASS_RAYHITS,
288                      SCE_PASS_INDEXMA);
289 }
290
291 /* if all is good tag image and return true */
292 static bool bake_object_check(Object *ob, ReportList *reports)
293 {
294         Image *image;
295         void *lock;
296         int i;
297
298         if (ob->type != OB_MESH) {
299                 BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
300                 return false;
301         }
302         else {
303                 Mesh *me = (Mesh *)ob->data;
304
305                 if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
306                         BKE_reportf(reports, RPT_ERROR,
307                                     "No active UV layer found in the object \"%s\"", ob->id.name + 2);
308                         return false;
309                 }
310         }
311
312         for (i = 0; i < ob->totcol; i++) {
313                 ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
314
315                 if (image) {
316                         ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
317
318                         if (ibuf) {
319                                 BKE_image_release_ibuf(image, ibuf, lock);
320                         }
321                         else {
322                                 BKE_reportf(reports, RPT_ERROR,
323                                             "Uninitialized image \"%s\" from object \"%s\"",
324                                             image->id.name + 2, ob->id.name + 2);
325
326                                 BKE_image_release_ibuf(image, ibuf, lock);
327                                 return false;
328                         }
329                 }
330                 else {
331                         if (ob->mat[i]) {
332                                 BKE_reportf(reports, RPT_ERROR,
333                                             "No active image found in material \"%s\" (%d) for object \"%s\"",
334                                             ob->mat[i]->id.name + 2, i, ob->id.name + 2);
335                         }
336                         else if (((Mesh *) ob->data)->mat[i]) {
337                                 BKE_reportf(reports, RPT_ERROR,
338                                             "No active image found in material \"%s\" (%d) for object \"%s\"",
339                                             ((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2);
340                         }
341                         else {
342                                 BKE_reportf(reports, RPT_ERROR,
343                                             "No active image found in material (%d) for object \"%s\"",
344                                             i, ob->id.name + 2);
345                         }
346                         return false;
347                 }
348
349                 image->id.flag |= LIB_DOIT;
350         }
351         return true;
352 }
353
354 /* before even getting in the bake function we check for some basic errors */
355 static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objects,
356                                ReportList *reports, const bool is_selected_to_active)
357 {
358         CollectionPointerLink *link;
359
360         /* error handling and tag (in case multiple materials share the same image) */
361         BKE_main_id_tag_idcode(bmain, ID_IM, false);
362
363         if (is_selected_to_active) {
364                 int tot_objects = 0;
365
366                 if (!bake_object_check(ob, reports))
367                         return false;
368
369                 for (link = selected_objects->first; link; link = link->next) {
370                         Object *ob_iter = (Object *)link->ptr.data;
371
372                         if (ob_iter == ob)
373                                 continue;
374
375                         if (ob_iter->type != OB_MESH) {
376                                 BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob_iter->id.name + 2);
377                                 return false;
378                         }
379                         tot_objects += 1;
380                 }
381
382                 if (tot_objects == 0) {
383                         BKE_report(reports, RPT_ERROR, "No valid selected objects");
384                         return false;
385                 }
386         }
387         else {
388                 if (BLI_listbase_is_empty(selected_objects)) {
389                         BKE_report(reports, RPT_ERROR, "No valid selected objects");
390                         return false;
391                 }
392
393                 for (link = selected_objects->first; link; link = link->next) {
394                         if (!bake_object_check(link->ptr.data, reports))
395                                 return false;
396                 }
397         }
398         return true;
399 }
400
401 /* it needs to be called after bake_objects_check since the image tagging happens there */
402 static void bake_images_clear(Main *bmain, const bool is_tangent)
403 {
404         Image *image;
405         for (image = bmain->image.first; image; image = image->id.next) {
406                 if ((image->id.flag & LIB_DOIT) != 0) {
407                         RE_bake_ibuf_clear(image, is_tangent);
408                 }
409         }
410 }
411
412 static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
413 {
414         const int tot_mat = ob->totcol;
415         int i, j;
416         int tot_images = 0;
417
418         /* error handling and tag (in case multiple materials share the same image) */
419         BKE_main_id_tag_idcode(bmain, ID_IM, false);
420
421         for (i = 0; i < tot_mat; i++) {
422                 Image *image;
423                 ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
424
425                 if ((image->id.flag & LIB_DOIT)) {
426                         for (j = 0; j < i; j++) {
427                                 if (bake_images->data[j].image == image) {
428                                         bake_images->lookup[i] = j;
429                                         break;
430                                 }
431                         }
432                 }
433                 else {
434                         bake_images->lookup[i] = tot_images;
435                         bake_images->data[tot_images].image = image;
436                         image->id.flag |= LIB_DOIT;
437                         tot_images++;
438                 }
439         }
440
441         bake_images->size = tot_images;
442 }
443
444 /*
445  * returns the total number of pixels
446  */
447 static int initialize_internal_images(BakeImages *bake_images, ReportList *reports)
448 {
449         int i;
450         int tot_size = 0;
451
452         for (i = 0; i < bake_images->size; i++) {
453                 ImBuf *ibuf;
454                 void *lock;
455
456                 BakeImage *bk_image = &bake_images->data[i];
457                 ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
458
459                 if (ibuf) {
460                         bk_image->width = ibuf->x;
461                         bk_image->height = ibuf->y;
462                         bk_image->offset = tot_size;
463
464                         tot_size += ibuf->x * ibuf->y;
465                 }
466                 else {
467                         BKE_image_release_ibuf(bk_image->image, ibuf, lock);
468                         BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
469                         return 0;
470                 }
471                 BKE_image_release_ibuf(bk_image->image, ibuf, lock);
472         }
473         return tot_size;
474 }
475
476 typedef struct BakeAPIRender {
477         Object *ob;
478         Main *main;
479         Scene *scene;
480         ReportList *reports;
481         ListBase selected_objects;
482
483         ScenePassType pass_type;
484         int margin;
485
486         int save_mode;
487
488         bool is_clear;
489         bool is_split_materials;
490         bool is_automatic_name;
491         bool is_selected_to_active;
492         bool is_cage;
493
494         float cage_extrusion;
495         int normal_space;
496         BakeNormalSwizzle normal_swizzle[3];
497
498         char custom_cage[MAX_NAME];
499         char filepath[FILE_MAX];
500
501         int width;
502         int height;
503         const char *identifier;
504
505         int result;
506         bool ready;
507
508         /* for redrawing */
509         ScrArea *sa;
510 } BakeAPIRender;
511
512 static int bake(
513         Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
514         const ScenePassType pass_type, const int margin,
515         const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
516         const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
517         const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[],
518         const char *custom_cage, const char *filepath, const int width, const int height,
519         const char *identifier, ScrArea *sa)
520 {
521         int op_result = OPERATOR_CANCELLED;
522         bool ok = false;
523
524         Object *ob_cage = NULL;
525
526         BakeHighPolyData *highpoly = NULL;
527         int tot_highpoly;
528
529         char restrict_flag_low = ob_low->restrictflag;
530         char restrict_flag_cage;
531
532         Mesh *me_low = NULL;
533         Mesh *me_cage = NULL;
534         Render *re;
535
536         float *result = NULL;
537
538         BakePixel *pixel_array_low = NULL;
539
540         const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
541         const bool is_noncolor = is_noncolor_pass(pass_type);
542         const int depth = RE_pass_depth(pass_type);
543
544         BakeImages bake_images = {NULL};
545
546         int num_pixels;
547         int tot_materials;
548         int i;
549
550         re = RE_NewRender(scene->id.name);
551         RE_SetReports(re, NULL);
552
553         tot_materials = ob_low->totcol;
554
555         if (tot_materials == 0) {
556                 if (is_save_internal) {
557                         BKE_report(reports, RPT_ERROR,
558                                    "No active image found, add a material or bake to an external file");
559
560                         goto cleanup;
561                 }
562                 else if (is_split_materials) {
563                         BKE_report(reports, RPT_ERROR,
564                                    "No active image found, add a material or bake without the Split Materials option");
565
566                         goto cleanup;
567                 }
568                 else {
569                         /* baking externally without splitting materials */
570                         tot_materials = 1;
571                 }
572         }
573
574         /* we overallocate in case there is more materials than images */
575         bake_images.data = MEM_callocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
576         bake_images.lookup = MEM_callocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");
577
578         build_image_lookup(bmain, ob_low, &bake_images);
579
580         if (is_save_internal) {
581                 num_pixels = initialize_internal_images(&bake_images, reports);
582
583                 if (num_pixels == 0) {
584                         goto cleanup;
585                 }
586         }
587         else {
588                 /* when saving extenally always use the size specified in the UI */
589
590                 num_pixels = width * height * bake_images.size;
591
592                 for (i = 0; i < bake_images.size; i++) {
593                         bake_images.data[i].width = width;
594                         bake_images.data[i].height = height;
595                         bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
596                         bake_images.data[i].image = NULL;
597                 }
598
599                 if (!is_split_materials) {
600                         /* saving a single image */
601                         for (i = 0; i < tot_materials; i++)
602                                 bake_images.lookup[i] = 0;
603                 }
604         }
605
606         if (is_selected_to_active) {
607                 CollectionPointerLink *link;
608                 tot_highpoly = 0;
609
610                 for (link = selected_objects->first; link; link = link->next) {
611                         Object *ob_iter = link->ptr.data;
612
613                         if (ob_iter == ob_low)
614                                 continue;
615
616                         tot_highpoly ++;
617                 }
618
619                 if (is_cage && custom_cage[0] != '\0') {
620                         ob_cage = BLI_findstring(&bmain->object, custom_cage, offsetof(ID, name) + 2);
621
622                         if (ob_cage == NULL || ob_cage->type != OB_MESH) {
623                                 BKE_report(reports, RPT_ERROR, "No valid cage object");
624                                 goto cleanup;
625                         }
626                         else {
627                                 restrict_flag_cage = ob_cage->restrictflag;
628                         }
629                 }
630         }
631
632         RE_bake_engine_set_engine_parameters(re, bmain, scene);
633
634         /* blender_test_break uses this global */
635         G.is_break = false;
636
637         RE_test_break_cb(re, NULL, bake_break);
638
639         pixel_array_low = MEM_callocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
640         result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
641
642         /* get the mesh as it arrives in the renderer */
643         me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
644
645         /* populate the pixel array with the face data */
646         if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
647                 RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images);
648         /* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh)  */
649
650         if (is_selected_to_active) {
651                 CollectionPointerLink *link;
652                 ModifierData *md, *nmd;
653                 ListBase modifiers_tmp, modifiers_original;
654                 int i = 0;
655
656                 /* prepare cage mesh */
657                 if (ob_cage) {
658                         me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 1, 0);
659                         if (me_low->totface != me_cage->totface) {
660                                 BKE_report(reports, RPT_ERROR,
661                                            "Invalid cage object, the cage mesh must have the same number "
662                                            "of faces as the active object");
663                                 goto cleanup;
664                         }
665                 }
666                 else if (is_cage) {
667                         modifiers_original = ob_low->modifiers;
668                         BLI_listbase_clear(&modifiers_tmp);
669
670                         for (md = ob_low->modifiers.first; md; md = md->next) {
671                                 /* Edge Split cannot be applied in the cage,
672                                  * the cage is supposed to have interpolated normals
673                                  * between the faces unless the geometry is physically
674                                  * split. So we create a copy of the low poly mesh without
675                                  * the eventual edge split.*/
676
677                                 if (md->type == eModifierType_EdgeSplit)
678                                         continue;
679
680                                 nmd = modifier_new(md->type);
681                                 BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
682                                 modifier_copyData(md, nmd);
683                                 BLI_addtail(&modifiers_tmp, nmd);
684                         }
685
686                         /* temporarily replace the modifiers */
687                         ob_low->modifiers = modifiers_tmp;
688
689                         /* get the cage mesh as it arrives in the renderer */
690                         me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
691                         RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images);
692                 }
693
694                 highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
695
696                 /* populate highpoly array */
697                 for (link = selected_objects->first; link; link = link->next) {
698                         TriangulateModifierData *tmd;
699                         Object *ob_iter = link->ptr.data;
700
701                         if (ob_iter == ob_low)
702                                 continue;
703
704                         /* initialize highpoly_data */
705                         highpoly[i].ob = ob_iter;
706                         highpoly[i].me = NULL;
707                         highpoly[i].tri_mod = NULL;
708                         highpoly[i].restrict_flag = ob_iter->restrictflag;
709                         highpoly[i].pixel_array = MEM_callocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
710
711
712                         /* triangulating so BVH returns the primitive_id that will be used for rendering */
713                         highpoly[i].tri_mod = ED_object_modifier_add(
714                                 reports, bmain, scene, highpoly[i].ob,
715                                 "TmpTriangulate", eModifierType_Triangulate);
716                         tmd = (TriangulateModifierData *)highpoly[i].tri_mod;
717                         tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
718                         tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;
719
720                         highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 1, 0);
721                         highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
722
723                         /* lowpoly to highpoly transformation matrix */
724                         copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
725                         invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
726
727                         /* rotation */
728                         normalize_m4_m4(highpoly[i].rotmat, highpoly[i].imat);
729                         zero_v3(highpoly[i].rotmat[3]);
730                         if (is_negative_m4(highpoly[i].rotmat))
731                                 negate_m3(highpoly[i].rotmat);
732
733                         i++;
734                 }
735
736                 BLI_assert(i == tot_highpoly);
737
738                 ob_low->restrictflag |= OB_RESTRICT_RENDER;
739
740                 /* populate the pixel arrays with the corresponding face data for each high poly object */
741                 if (!RE_bake_pixels_populate_from_objects(
742                             me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
743                             cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) {
744                         BKE_report(reports, RPT_ERROR, "Error handling selected objects");
745                         goto cleanup;
746                 }
747
748                 /* the baking itself */
749                 for (i = 0; i < tot_highpoly; i++) {
750                         if (RE_bake_has_engine(re)) {
751                                 ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels,
752                                                     depth, pass_type, result);
753                         }
754                         else {
755                                 BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
756                                 goto cleanup;
757                         }
758
759                         if (!ok)
760                                 break;
761                 }
762
763                 /* reverting data back */
764                 if (ob_cage) {
765                         ob_cage->restrictflag |= OB_RESTRICT_RENDER;
766                 }
767                 else if (is_cage) {
768                         ob_low->modifiers = modifiers_original;
769
770                         while ((md = BLI_pophead(&modifiers_tmp))) {
771                                 modifier_free(md);
772                         }
773                 }
774         }
775         else {
776                 /* make sure low poly renders */
777                 ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
778
779                 if (RE_bake_has_engine(re)) {
780                         ok = RE_bake_engine(re, ob_low, pixel_array_low, num_pixels, depth, pass_type, result);
781                 }
782                 else {
783                         BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
784                         goto cleanup;
785                 }
786         }
787
788         /* normal space conversion
789          * the normals are expected to be in world space, +X +Y +Z */
790         if (ok && pass_type == SCE_PASS_NORMAL) {
791                 switch (normal_space) {
792                         case R_BAKE_SPACE_WORLD:
793                         {
794                                 /* Cycles internal format */
795                                 if ((normal_swizzle[0] == R_BAKE_POSX) &&
796                                     (normal_swizzle[1] == R_BAKE_POSY) &&
797                                     (normal_swizzle[2] == R_BAKE_POSZ))
798                                 {
799                                         break;
800                                 }
801                                 else {
802                                         RE_bake_normal_world_to_world(pixel_array_low, num_pixels,  depth, result, normal_swizzle);
803                                 }
804                                 break;
805                         }
806                         case R_BAKE_SPACE_OBJECT:
807                         {
808                                 RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low, normal_swizzle);
809                                 break;
810                         }
811                         case R_BAKE_SPACE_TANGENT:
812                         {
813                                 if (is_selected_to_active) {
814                                         RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low->obmat);
815                                 }
816                                 else {
817                                         /* from multiresolution */
818                                         Mesh *me_nores = NULL;
819                                         ModifierData *md = NULL;
820                                         int mode;
821
822                                         md = modifiers_findByType(ob_low, eModifierType_Multires);
823
824                                         if (md) {
825                                                 mode = md->mode;
826                                                 md->mode &= ~eModifierMode_Render;
827                                         }
828
829                                         me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
830                                         RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images);
831
832                                         RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
833                                         BKE_libblock_free(bmain, me_nores);
834
835                                         if (md)
836                                                 md->mode = mode;
837                                 }
838                                 break;
839                         }
840                         default:
841                                 break;
842                 }
843         }
844
845         if (!ok) {
846                 BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
847                 op_result = OPERATOR_CANCELLED;
848         }
849         else {
850                 /* save the results */
851                 for (i = 0; i < bake_images.size; i++) {
852                         BakeImage *bk_image = &bake_images.data[i];
853
854                         if (is_save_internal) {
855                                 ok = write_internal_bake_pixels(
856                                          bk_image->image,
857                                          pixel_array_low + bk_image->offset,
858                                          result + bk_image->offset * depth,
859                                          bk_image->width, bk_image->height,
860                                          margin, is_clear, is_noncolor);
861
862                                 /* might be read by UI to set active image for display */
863                                 bake_update_image(sa, bk_image->image);
864
865                                 if (!ok) {
866                                         BKE_reportf(reports, RPT_ERROR,
867                                                    "Problem saving the bake map internally for object \"%s\"", ob_low->id.name + 2);
868                                         op_result = OPERATOR_CANCELLED;
869                                 }
870                                 else {
871                                         BKE_report(reports, RPT_INFO,
872                                                    "Baking map saved to internal image, save it externally or pack it");
873                                         op_result = OPERATOR_FINISHED;
874                                 }
875                         }
876                         /* save externally */
877                         else {
878                                 BakeData *bake = &scene->r.bake;
879                                 char name[FILE_MAX];
880
881                                 BKE_makepicstring_from_type(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false);
882
883                                 if (is_automatic_name) {
884                                         BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
885                                         BLI_path_suffix(name, FILE_MAX, identifier, "_");
886                                 }
887
888                                 if (is_split_materials) {
889                                         if (bk_image->image) {
890                                                 BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
891                                         }
892                                         else {
893                                                 if (ob_low->mat[i]) {
894                                                         BLI_path_suffix(name, FILE_MAX, ob_low->mat[i]->id.name + 2, "_");
895                                                 }
896                                                 else if (me_low->mat[i]) {
897                                                         BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
898                                                 }
899                                                 else {
900                                                         /* if everything else fails, use the material index */
901                                                         char tmp[4];
902                                                         sprintf(tmp, "%d", i % 1000);
903                                                         BLI_path_suffix(name, FILE_MAX, tmp, "_");
904                                                 }
905                                         }
906                                 }
907
908                                 /* save it externally */
909                                 ok = write_external_bake_pixels(
910                                         name,
911                                         pixel_array_low + bk_image->offset,
912                                         result + bk_image->offset * depth,
913                                         bk_image->width, bk_image->height,
914                                         margin, &bake->im_format, is_noncolor);
915
916                                 if (!ok) {
917                                         BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
918                                         op_result = OPERATOR_CANCELLED;
919                                 }
920                                 else {
921                                         BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
922                                         op_result = OPERATOR_FINISHED;
923                                 }
924
925                                 if (!is_split_materials) {
926                                         break;
927                                 }
928                         }
929                 }
930         }
931
932         if (is_save_internal)
933                 reset_images_gpu(&bake_images);
934
935 cleanup:
936
937         if (highpoly) {
938                 int i;
939                 for (i = 0; i < tot_highpoly; i++) {
940                         highpoly[i].ob->restrictflag = highpoly[i].restrict_flag;
941
942                         if (highpoly[i].pixel_array)
943                                 MEM_freeN(highpoly[i].pixel_array);
944
945                         if (highpoly[i].tri_mod)
946                                 ED_object_modifier_remove(reports, bmain, highpoly[i].ob, highpoly[i].tri_mod);
947
948                         if (highpoly[i].me)
949                                 BKE_libblock_free(bmain, highpoly[i].me);
950                 }
951                 MEM_freeN(highpoly);
952         }
953
954         ob_low->restrictflag = restrict_flag_low;
955
956         if (ob_cage)
957                 ob_cage->restrictflag = restrict_flag_cage;
958
959         if (pixel_array_low)
960                 MEM_freeN(pixel_array_low);
961
962         if (bake_images.data)
963                 MEM_freeN(bake_images.data);
964
965         if (bake_images.lookup)
966                 MEM_freeN(bake_images.lookup);
967
968         if (result)
969                 MEM_freeN(result);
970
971         if (me_low)
972                 BKE_libblock_free(bmain, me_low);
973
974         if (me_cage)
975                 BKE_libblock_free(bmain, me_cage);
976
977         return op_result;
978 }
979
980 static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
981 {
982         bool is_save_internal;
983         bScreen *sc = CTX_wm_screen(C);
984
985         bkr->ob = CTX_data_active_object(C);
986         bkr->main = CTX_data_main(C);
987         bkr->scene = CTX_data_scene(C);
988         bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
989
990         bkr->pass_type = RNA_enum_get(op->ptr, "type");
991         bkr->margin = RNA_int_get(op->ptr, "margin");
992
993         bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
994         is_save_internal = (bkr->save_mode == R_BAKE_SAVE_INTERNAL);
995
996         bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
997         bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
998         bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
999         bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
1000         bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
1001         bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
1002
1003         bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
1004         bkr->normal_swizzle[0] = RNA_enum_get(op->ptr, "normal_r");
1005         bkr->normal_swizzle[1] = RNA_enum_get(op->ptr, "normal_g");
1006         bkr->normal_swizzle[2] = RNA_enum_get(op->ptr, "normal_b");
1007
1008         bkr->width = RNA_int_get(op->ptr, "width");
1009         bkr->height = RNA_int_get(op->ptr, "height");
1010         bkr->identifier = "";
1011
1012         RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
1013
1014         if ((!is_save_internal) && bkr->is_automatic_name) {
1015                 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
1016                 RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
1017         }
1018
1019         CTX_data_selected_objects(C, &bkr->selected_objects);
1020
1021         bkr->reports = op->reports;
1022
1023         bkr->result = OPERATOR_CANCELLED;
1024
1025         /* XXX hack to force saving to always be internal. Whether (and how) to support
1026          * external saving will be addressed later */
1027         bkr->save_mode = R_BAKE_SAVE_INTERNAL;
1028 }
1029
1030 static int bake_exec(bContext *C, wmOperator *op)
1031 {
1032         int result = OPERATOR_CANCELLED;
1033         BakeAPIRender bkr = {NULL};
1034
1035         bake_init_api_data(op, C, &bkr);
1036
1037         if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active))
1038                 return OPERATOR_CANCELLED;
1039
1040         if (bkr.is_clear) {
1041                 const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT));
1042                 bake_images_clear(bkr.main, is_tangent);
1043         }
1044
1045         if (bkr.is_selected_to_active) {
1046                 result = bake(
1047                         bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
1048                         bkr.pass_type, bkr.margin, bkr.save_mode,
1049                         bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
1050                         bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
1051                         bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa);
1052         }
1053         else {
1054                 CollectionPointerLink *link;
1055                 const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
1056                 for (link = bkr.selected_objects.first; link; link = link->next) {
1057                         Object *ob_iter = link->ptr.data;
1058                         result = bake(
1059                                 bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
1060                                 bkr.pass_type, bkr.margin, bkr.save_mode,
1061                                 is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
1062                                 bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
1063                                 bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa);
1064                 }
1065         }
1066
1067         BLI_freelistN(&bkr.selected_objects);
1068         return result;
1069 }
1070
1071 static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_update), float *UNUSED(progress))
1072 {
1073         BakeAPIRender *bkr = (BakeAPIRender *)bkv;
1074
1075         if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
1076                 bkr->result = OPERATOR_CANCELLED;
1077                 return;
1078         }
1079
1080         if (bkr->is_clear) {
1081                 const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT));
1082                 bake_images_clear(bkr->main, is_tangent);
1083         }
1084
1085         if (bkr->is_selected_to_active) {
1086                 bkr->result = bake(
1087                         bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
1088                         bkr->pass_type, bkr->margin, bkr->save_mode,
1089                         bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
1090                         bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
1091                         bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa);
1092         }
1093         else {
1094                 CollectionPointerLink *link;
1095                 const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
1096                 for (link = bkr->selected_objects.first; link; link = link->next) {
1097                         Object *ob_iter = link->ptr.data;
1098                         bkr->result = bake(
1099                                 bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
1100                                 bkr->pass_type, bkr->margin, bkr->save_mode,
1101                                 is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
1102                                 bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
1103                                 bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa);
1104
1105                         if (bkr->result == OPERATOR_CANCELLED)
1106                                 return;
1107                 }
1108         }
1109 }
1110
1111 static void bake_freejob(void *bkv)
1112 {
1113         BakeAPIRender *bkr = (BakeAPIRender *)bkv;
1114
1115         BLI_freelistN(&bkr->selected_objects);
1116         MEM_freeN(bkr);
1117
1118         G.is_rendering = false;
1119 }
1120
1121 static void bake_set_props(wmOperator *op, Scene *scene)
1122 {
1123         PropertyRNA *prop;
1124         BakeData *bake = &scene->r.bake;
1125
1126         prop = RNA_struct_find_property(op->ptr, "filepath");
1127         if (!RNA_property_is_set(op->ptr, prop)) {
1128                 RNA_property_string_set(op->ptr, prop, bake->filepath);
1129         }
1130
1131         prop =  RNA_struct_find_property(op->ptr, "width");
1132         if (!RNA_property_is_set(op->ptr, prop)) {
1133                 RNA_property_int_set(op->ptr, prop, bake->width);
1134         }
1135
1136         prop =  RNA_struct_find_property(op->ptr, "height");
1137         if (!RNA_property_is_set(op->ptr, prop)) {
1138                 RNA_property_int_set(op->ptr, prop, bake->width);
1139         }
1140
1141         prop = RNA_struct_find_property(op->ptr, "margin");
1142         if (!RNA_property_is_set(op->ptr, prop)) {
1143                 RNA_property_int_set(op->ptr, prop, bake->margin);
1144         }
1145
1146         prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
1147         if (!RNA_property_is_set(op->ptr, prop)) {
1148                 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE));
1149         }
1150
1151         prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
1152         if (!RNA_property_is_set(op->ptr, prop)) {
1153                 RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
1154         }
1155
1156         prop = RNA_struct_find_property(op->ptr, "cage_object");
1157         if (!RNA_property_is_set(op->ptr, prop)) {
1158                 RNA_property_string_set(op->ptr, prop, bake->cage);
1159         }
1160
1161         prop = RNA_struct_find_property(op->ptr, "normal_space");
1162         if (!RNA_property_is_set(op->ptr, prop)) {
1163                 RNA_property_enum_set(op->ptr, prop, bake->normal_space);
1164         }
1165
1166         prop = RNA_struct_find_property(op->ptr, "normal_r");
1167         if (!RNA_property_is_set(op->ptr, prop)) {
1168                 RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
1169         }
1170
1171         prop = RNA_struct_find_property(op->ptr, "normal_g");
1172         if (!RNA_property_is_set(op->ptr, prop)) {
1173                 RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
1174         }
1175
1176         prop = RNA_struct_find_property(op->ptr, "normal_b");
1177         if (!RNA_property_is_set(op->ptr, prop)) {
1178                 RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
1179         }
1180
1181         prop = RNA_struct_find_property(op->ptr, "save_mode");
1182         if (!RNA_property_is_set(op->ptr, prop)) {
1183                 RNA_property_enum_set(op->ptr, prop, bake->save_mode);
1184         }
1185
1186         prop = RNA_struct_find_property(op->ptr, "use_clear");
1187         if (!RNA_property_is_set(op->ptr, prop)) {
1188                 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR));
1189         }
1190
1191         prop = RNA_struct_find_property(op->ptr, "use_cage");
1192         if (!RNA_property_is_set(op->ptr, prop)) {
1193                 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE));
1194         }
1195
1196         prop = RNA_struct_find_property(op->ptr, "use_split_materials");
1197         if (!RNA_property_is_set(op->ptr, prop)) {
1198                 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT));
1199         }
1200
1201         prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
1202         if (!RNA_property_is_set(op->ptr, prop)) {
1203                 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME));
1204         }
1205 }
1206
1207 static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1208 {
1209         wmJob *wm_job;
1210         BakeAPIRender *bkr;
1211         Scene *scene = CTX_data_scene(C);
1212
1213         bake_set_props(op, scene);
1214
1215         /* only one render job at a time */
1216         if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
1217                 return OPERATOR_CANCELLED;
1218
1219         bkr = MEM_callocN(sizeof(BakeAPIRender), "render bake");
1220
1221         /* init bake render */
1222         bake_init_api_data(op, C, bkr);
1223
1224         /* setup job */
1225         wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake",
1226                              WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE);
1227         WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
1228         WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
1229         WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);
1230
1231         G.is_break = false;
1232         G.is_rendering = true;
1233
1234         WM_jobs_start(CTX_wm_manager(C), wm_job);
1235
1236         WM_cursor_wait(0);
1237
1238         /* add modal handler for ESC */
1239         WM_event_add_modal_handler(C, op);
1240
1241         WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
1242         return OPERATOR_RUNNING_MODAL;
1243 }
1244
1245 void OBJECT_OT_bake(wmOperatorType *ot)
1246 {
1247         /* identifiers */
1248         ot->name = "Bake";
1249         ot->description = "Bake image textures of selected objects";
1250         ot->idname = "OBJECT_OT_bake";
1251
1252         /* api callbacks */
1253         ot->exec = bake_exec;
1254         ot->modal = bake_modal;
1255         ot->invoke = bake_invoke;
1256         ot->poll = ED_operator_object_active_editable_mesh;
1257
1258         RNA_def_enum(ot->srna, "type", render_pass_type_items, SCE_PASS_COMBINED, "Type",
1259                      "Type of pass to bake, some of them may not be supported by the current render engine");
1260         RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path",
1261                                  "Image filepath to use when saving externally");
1262         RNA_def_int(ot->srna, "width", 512, 1, INT_MAX, "Width",
1263                     "Horizontal dimension of the baking map (external only)", 64, 4096);
1264         RNA_def_int(ot->srna, "height", 512, 1, INT_MAX, "Height",
1265                     "Vertical dimension of the baking map (external only)", 64, 4096);
1266         RNA_def_int(ot->srna, "margin", 16, 0, INT_MAX, "Margin",
1267                     "Extends the baked result as a post process filter", 0, 64);
1268         RNA_def_boolean(ot->srna, "use_selected_to_active", false, "Selected to Active",
1269                         "Bake shading on the surface of selected objects to the active object");
1270         RNA_def_float(ot->srna, "cage_extrusion", 0.0f, 0.0f, FLT_MAX, "Cage Extrusion",
1271                       "Distance to use for the inward ray cast when using selected to active", 0.0f, 1.0f);
1272         RNA_def_string(ot->srna, "cage_object", NULL, MAX_NAME, "Cage Object",
1273                        "Object to use as cage, instead of calculating the cage from the active object with cage extrusion");
1274         RNA_def_enum(ot->srna, "normal_space", normal_space_items, R_BAKE_SPACE_TANGENT, "Normal Space",
1275                      "Choose normal space for baking");
1276         RNA_def_enum(ot->srna, "normal_r", normal_swizzle_items, R_BAKE_POSX, "R", "Axis to bake in red channel");
1277         RNA_def_enum(ot->srna, "normal_g", normal_swizzle_items, R_BAKE_POSY, "G", "Axis to bake in green channel");
1278         RNA_def_enum(ot->srna, "normal_b", normal_swizzle_items, R_BAKE_POSZ, "B", "Axis to bake in blue channel");
1279         RNA_def_enum(ot->srna, "save_mode", bake_save_mode_items, R_BAKE_SAVE_INTERNAL, "Save Mode",
1280                      "Choose how to save the baking map");
1281         RNA_def_boolean(ot->srna, "use_clear", false, "Clear",
1282                         "Clear Images before baking (only for internal saving)");
1283         RNA_def_boolean(ot->srna, "use_cage", false, "Cage",
1284                         "Cast rays to active object from a cage");
1285         RNA_def_boolean(ot->srna, "use_split_materials", false, "Split Materials",
1286                         "Split baked maps per material, using material name in output file (external only)");
1287         RNA_def_boolean(ot->srna, "use_automatic_name", false, "Automatic Name",
1288                         "Automatically name the output file with the pass type");
1289 }