Blender V5.0
object_bake_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2004 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cmath>
10#include <sys/stat.h>
11
12#include "MEM_guardedalloc.h"
13
14#include "DNA_material_types.h"
15#include "DNA_mesh_types.h"
16#include "DNA_meshdata_types.h"
17#include "DNA_object_types.h"
18
19#include "RNA_access.hh"
20#include "RNA_define.hh"
21#include "RNA_enum_types.hh"
22
23#include "BLI_listbase.h"
24#include "BLI_math_geom.h"
25#include "BLI_path_utils.hh"
26#include "BLI_string_ref.hh"
27#include "BLI_string_utf8.h"
28
29#include "BLT_translation.hh"
30
31#include "BKE_attribute.hh"
32#include "BKE_callbacks.hh"
33#include "BKE_context.hh"
34#include "BKE_editmesh.hh"
35#include "BKE_global.hh"
36#include "BKE_image.hh"
37#include "BKE_image_format.hh"
38#include "BKE_layer.hh"
39#include "BKE_lib_id.hh"
40#include "BKE_main.hh"
41#include "BKE_material.hh"
42#include "BKE_mesh.hh"
43#include "BKE_modifier.hh"
44#include "BKE_node.hh"
45#include "BKE_object.hh"
46#include "BKE_report.hh"
47#include "BKE_scene.hh"
48#include "BKE_screen.hh"
49
50#include "DEG_depsgraph.hh"
53
54#include "RE_engine.h"
55#include "RE_pipeline.h"
56
58#include "IMB_imbuf.hh"
59#include "IMB_imbuf_types.hh"
60
61#include "WM_api.hh"
62#include "WM_types.hh"
63
64#include "ED_mesh.hh"
65#include "ED_object.hh"
66#include "ED_screen.hh"
67#include "ED_uvedit.hh"
68
69#include "object_intern.hh"
70
71namespace blender::ed::object {
72
73/* prototypes */
74static void bake_set_props(wmOperator *op, Scene *scene);
75
77 /* Data to work on. */
83
84 /* Baking settings. */
86
89 int margin;
91
94 bool is_cage;
95
100
101 std::string uv_layer;
103
104 /* Settings for external image saving. */
109 int width;
111 const char *identifier;
112
113 /* Baking render session. */
115
116 /* Progress Callbacks. */
117 float *progress;
119
120 /* Operator state. */
124};
125
126/* callbacks */
127
128static void bake_progress_update(void *bjv, float progress)
129{
130 BakeAPIRender *bj = static_cast<BakeAPIRender *>(bjv);
131
132 if (bj->progress && *bj->progress != progress) {
133 *bj->progress = progress;
134
135 /* make jobs timer to send notifier */
136 *(bj->do_update) = true;
137 }
138}
139
141static wmOperatorStatus bake_modal(bContext *C, wmOperator * /*op*/, const wmEvent *event)
142{
143 /* no running blender, remove handler and pass through */
146 }
147
148 /* running render */
149 switch (event->type) {
150 case EVT_ESCKEY: {
151 G.is_break = true;
153 }
154 default: {
155 break;
156 }
157 }
159}
160
165static bool bake_break(void * /*rjv*/)
166{
167 if (G.is_break) {
168 return true;
169 }
170 return false;
171}
172
173static void bake_update_image(ScrArea *area, Image *image)
174{
175 if (area && area->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
176 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
177 if (sima) {
178 sima->image = image;
179 }
180 }
181}
182
183/* Bias almost-flat normals in tangent space to be flat to avoid artifacts in byte textures.
184 * For some types of normal baking, especially bevels, you can end up with a small amount
185 * of noise in the result. Since the border between pixel value 127 and 128 is exactly 0.5,
186 * the tiniest amount of deviation will flip between those two, and increasing samples won't
187 * help - you always end up with visible "dents" in the resulting normal map.
188 * Therefore, this function snaps values that are less than half a quantization level away
189 * from 0.5 to 0.5, so that they consistently become pixel value 128.
190 * This only makes sense for byte textures of course, and is not used when baking to float
191 * textures (which includes 16-bit formats). Also, it's only applied to the first two channels,
192 * since on flat surfaces the Z channel will be close enough to 1.0 to reliably end up on 255.
193 */
195 float *rect, int channels, int width, int height, int stride)
196{
197 BLI_assert(channels >= 3);
198
199 for (int y = 0; y < height; y++) {
200 float *pixels = rect + size_t(stride) * y * channels;
201 for (int x = 0; x < width; x++, pixels += channels) {
202 if (fabsf(pixels[0] - 0.5f) < 1.0f / 255.0f) {
203 pixels[0] = 0.5f + 1e-5f;
204 }
205 if (fabsf(pixels[1] - 0.5f) < 1.0f / 255.0f) {
206 pixels[1] = 0.5f + 1e-5f;
207 }
208 }
209 }
210}
211
213 const int image_tile_number,
214 BakePixel pixel_array[],
215 float *buffer,
216 const int width,
217 const int height,
218 const int margin,
219 const char margin_type,
220 const bool is_clear,
221 const bool is_noncolor,
222 const bool is_tangent_normal,
223 Mesh const *mesh_eval,
224 const StringRef uv_layer,
225 const float uv_offset[2])
226{
227 ImBuf *ibuf;
228 void *lock;
229 bool is_float;
230 char *mask_buffer = nullptr;
231 const size_t pixels_num = size_t(width) * size_t(height);
232
233 ImageUser iuser;
234 BKE_imageuser_default(&iuser);
235 iuser.tile = image_tile_number;
236 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
237
238 if (!ibuf) {
239 return false;
240 }
241
242 if (margin > 0 || !is_clear) {
243 mask_buffer = MEM_calloc_arrayN<char>(pixels_num, "Bake Mask");
244 RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer);
245 }
246
247 is_float = (ibuf->float_buffer.data != nullptr);
248
249 /* colormanagement conversions */
250 if (!is_noncolor) {
251 const char *from_colorspace;
252 const char *to_colorspace;
253
255
256 if (is_float) {
257 to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
258 }
259 else {
260 to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
261 }
262
263 if (from_colorspace != to_colorspace) {
265 buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
266 }
267 }
268 else if (!is_float && is_tangent_normal) {
269 /* bias neutral values when converting tangent-space normal maps to byte textures */
270 bias_tangent_normal_pixels(buffer, ibuf->channels, ibuf->x, ibuf->y, ibuf->x);
271 }
272
273 /* populates the ImBuf */
274 if (is_clear) {
275 if (is_float) {
277 buffer,
278 ibuf->channels,
281 false,
282 ibuf->x,
283 ibuf->y,
284 ibuf->x,
285 ibuf->x);
286 }
287 else {
289 buffer,
290 ibuf->channels,
291 ibuf->dither,
294 false,
295 ibuf->x,
296 ibuf->y,
297 ibuf->x,
298 ibuf->x);
299 }
300 }
301 else {
302 if (is_float) {
304 buffer,
305 ibuf->channels,
306 ibuf->x,
307 ibuf->y,
308 ibuf->x,
309 ibuf->x,
310 mask_buffer);
311 }
312 else {
314 buffer,
315 ibuf->channels,
316 ibuf->dither,
317 false,
318 ibuf->x,
319 ibuf->y,
320 ibuf->x,
321 ibuf->x,
322 mask_buffer);
323 }
324 }
325
326 /* margins */
327 if (margin > 0) {
328 RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer, uv_offset);
329 }
330
332 BKE_image_mark_dirty(image, ibuf);
333
334 if (ibuf->float_buffer.data) {
335 ibuf->userflags |= IB_RECT_INVALID;
336 }
337
338 BKE_image_release_ibuf(image, ibuf, nullptr);
339
340 if (mask_buffer) {
341 MEM_freeN(mask_buffer);
342 }
343
344 return true;
345}
346
347/* force OpenGL reload */
349{
350 for (int i = 0; i < targets->images_num; i++) {
351 Image *ima = targets->images[i].image;
352
353 if (ima) {
356 DEG_id_tag_update(&ima->id, 0);
357 }
358 }
359}
360
361static bool write_external_bake_pixels(const char *filepath,
362 BakePixel pixel_array[],
363 float *buffer,
364 const int width,
365 const int height,
366 const int margin,
367 const int margin_type,
368 ImageFormatData const *im_format,
369 const bool is_noncolor,
370 const bool is_tangent_normal,
371 Mesh const *mesh_eval,
372 const StringRef uv_layer,
373 const float uv_offset[2])
374{
375 ImBuf *ibuf = nullptr;
376 bool ok = false;
377 bool is_float;
378
379 is_float = im_format->depth > 8;
380
381 /* create a new ImBuf */
382 ibuf = IMB_allocImBuf(
383 width, height, im_format->planes, (is_float ? IB_float_data : IB_byte_data));
384
385 if (!ibuf) {
386 return false;
387 }
388
389 /* populates the ImBuf */
390 if (is_float) {
392 buffer,
393 ibuf->channels,
396 false,
397 ibuf->x,
398 ibuf->y,
399 ibuf->x,
400 ibuf->x);
401 }
402 else {
403 if (!is_noncolor) {
404 const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(
406 const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
408 buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
409 }
410 else if (is_tangent_normal) {
411 /* bias neutral values when converting tangent-space normal maps to byte textures */
412 bias_tangent_normal_pixels(buffer, ibuf->channels, ibuf->x, ibuf->y, ibuf->x);
413 }
414
416 buffer,
417 ibuf->channels,
418 ibuf->dither,
421 false,
422 ibuf->x,
423 ibuf->y,
424 ibuf->x,
425 ibuf->x);
426 }
427
428 /* margins */
429 if (margin > 0) {
430 char *mask_buffer = nullptr;
431 const size_t pixels_num = size_t(width) * size_t(height);
432
433 mask_buffer = MEM_calloc_arrayN<char>(pixels_num, "Bake Mask");
434 RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer);
435 RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer, uv_offset);
436
437 if (mask_buffer) {
438 MEM_freeN(mask_buffer);
439 }
440 }
441
442 if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
443#ifndef WIN32
444 chmod(filepath, S_IRUSR | S_IWUSR);
445#endif
446 // printf("%s saving bake map: '%s'\n", __func__, filepath);
447 }
448
449 /* garbage collection */
450 IMB_freeImBuf(ibuf);
451
452 return ok;
453}
454
455static bool is_noncolor_pass(eScenePassType pass_type)
456{
457 return ELEM(pass_type,
465}
466
467/* if all is good tag image and return true */
468static bool bake_object_check(const Scene *scene,
469 ViewLayer *view_layer,
470 Object *ob,
471 const eBakeTarget target,
472 ReportList *reports)
473{
474 BKE_view_layer_synced_ensure(scene, view_layer);
475 Base *base = BKE_view_layer_base_find(view_layer, ob);
476
477 if (base == nullptr) {
478 BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2);
479 return false;
480 }
481
482 if (!(base->flag & BASE_ENABLED_RENDER)) {
483 BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", ob->id.name + 2);
484 return false;
485 }
486
487 if (ob->type != OB_MESH) {
488 BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
489 return false;
490 }
491
492 Mesh *mesh = (Mesh *)ob->data;
493
494 if (mesh->faces_num == 0) {
495 BKE_reportf(reports, RPT_ERROR, "No faces found in the object \"%s\"", ob->id.name + 2);
496 return false;
497 }
498
499 if (target == R_BAKE_TARGET_VERTEX_COLORS) {
500 if (!BKE_id_attributes_color_find(&mesh->id, mesh->active_color_attribute)) {
501 BKE_reportf(reports,
502 RPT_ERROR,
503 "Mesh does not have an active color attribute \"%s\"",
504 mesh->id.name + 2);
505 return false;
506 }
507 }
508 else if (target == R_BAKE_TARGET_IMAGE_TEXTURES) {
509 if (CustomData_get_active_layer_index(&mesh->corner_data, CD_PROP_FLOAT2) == -1) {
511 reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2);
512 return false;
513 }
514
515 for (int i = 0; i < ob->totcol; i++) {
516 const bNodeTree *ntree = nullptr;
517 const bNode *node = nullptr;
518 const int mat_nr = i + 1;
519 Image *image;
520 ED_object_get_active_image(ob, mat_nr, &image, nullptr, &node, &ntree);
521
522 /* Don't bake to unselected images. */
523 if (node && !(node->flag & NODE_SELECT)) {
524 image = nullptr;
525 }
526
527 if (image) {
528
529 if (node) {
530 if (bke::node_is_connected_to_output(*ntree, *node)) {
531 /* we don't return false since this may be a false positive
532 * this can't be RPT_ERROR though, otherwise it prevents
533 * multiple highpoly objects to be baked at once */
534 BKE_reportf(reports,
535 RPT_INFO,
536 "Circular dependency for image \"%s\" from object \"%s\"",
537 image->id.name + 2,
538 ob->id.name + 2);
539 }
540 }
541
542 LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
543 ImageUser iuser;
544 BKE_imageuser_default(&iuser);
545 iuser.tile = tile->tile_number;
546
547 void *lock;
548 ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
549
550 if (ibuf) {
551 BKE_image_release_ibuf(image, ibuf, lock);
552 }
553 else {
554 BKE_reportf(reports,
555 RPT_ERROR,
556 "Uninitialized image \"%s\" from object \"%s\"",
557 image->id.name + 2,
558 ob->id.name + 2);
559
560 BKE_image_release_ibuf(image, ibuf, lock);
561 return false;
562 }
563 }
564 }
565 else {
566 Material *mat = BKE_object_material_get(ob, mat_nr);
567 if (mat != nullptr) {
568 BKE_reportf(reports,
569 RPT_INFO,
570 "No active and selected image texture node found in material \"%s\" (%d) "
571 "for object \"%s\"",
572 mat->id.name + 2,
573 i,
574 ob->id.name + 2);
575 }
576 else {
577 BKE_reportf(reports,
578 RPT_INFO,
579 "No active image found in material slot (%d) for object \"%s\"",
580 i,
581 ob->id.name + 2);
582 }
583 continue;
584 }
585
586 image->id.tag |= ID_TAG_DOIT;
587 }
588 }
589
590 return true;
591}
592
594 const int pass_filter,
595 ReportList *reports)
596{
597 switch (pass_type) {
599 if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) {
600 return true;
601 }
602
603 if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
604 ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
605 {
606 if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) ||
607 ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) ||
608 ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) ||
609 ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0))
610 {
611 return true;
612 }
613
614 BKE_report(reports,
615 RPT_ERROR,
616 "Combined bake pass requires Emission, or a light pass with "
617 "Direct or Indirect contributions enabled");
618
619 return false;
620 }
621 BKE_report(reports,
622 RPT_ERROR,
623 "Combined bake pass requires Emission, or a light pass with "
624 "Direct or Indirect contributions enabled");
625 return false;
630 if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) ||
631 ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
632 ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
633 {
634 return true;
635 }
636 else {
637 BKE_report(reports,
638 RPT_ERROR,
639 "Bake pass requires Direct, Indirect, or Color contributions to be enabled");
640 return false;
641 }
642 break;
643 default:
644 return true;
645 break;
646 }
647}
648
649/* before even getting in the bake function we check for some basic errors */
650static bool bake_objects_check(Main *bmain,
651 const Scene *scene,
652 ViewLayer *view_layer,
653 Object *ob,
654 Span<PointerRNA> selected_objects,
655 ReportList *reports,
656 const bool is_selected_to_active,
657 const eBakeTarget target)
658{
659 /* error handling and tag (in case multiple materials share the same image) */
661
662 if (is_selected_to_active) {
663 int tot_objects = 0;
664
665 if (!bake_object_check(scene, view_layer, ob, target, reports)) {
666 return false;
667 }
668
669 for (const PointerRNA &ptr : selected_objects) {
670 Object *ob_iter = (Object *)ptr.data;
671 if (ob_iter == ob) {
672 continue;
673 }
674
675 if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVES_LEGACY, OB_SURF, OB_MBALL) == false) {
676 BKE_reportf(reports,
677 RPT_ERROR,
678 "Object \"%s\" is not a mesh or cannot be converted to a mesh (Curve, Text, "
679 "Surface or Metaball)",
680 ob_iter->id.name + 2);
681 return false;
682 }
683 tot_objects += 1;
684 }
685
686 if (tot_objects == 0) {
687 BKE_report(reports, RPT_ERROR, "No valid selected objects");
688 return false;
689 }
690 }
691 else {
692 if (selected_objects.is_empty()) {
693 BKE_report(reports, RPT_ERROR, "No valid selected objects");
694 return false;
695 }
696
697 for (const PointerRNA &ptr : selected_objects) {
698 if (!bake_object_check(scene, view_layer, static_cast<Object *>(ptr.data), target, reports))
699 {
700 return false;
701 }
702 }
703 }
704 return true;
705}
706
707/* it needs to be called after bake_objects_check since the image tagging happens there */
708static void bake_targets_clear(Main *bmain, const bool is_tangent)
709{
710 LISTBASE_FOREACH (Image *, image, &bmain->images) {
711 if ((image->id.tag & ID_TAG_DOIT) != 0) {
712 RE_bake_ibuf_clear(image, is_tangent);
713 }
714 }
715}
716
717/* create new mesh with edit mode changes and modifiers applied */
719 Object *object,
720 const bool preserve_origindex)
721{
722 Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, false, preserve_origindex, true);
723
724 if (mesh->normals_domain() == bke::MeshNormalDomain::Corner) {
726 }
727
728 return mesh;
729}
730
731/* Image Bake Targets */
732
734 BakeTargets *targets,
735 Object *ob,
736 ReportList *reports)
737{
738 int materials_num = ob->totcol;
739
740 if (materials_num == 0) {
741 if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
743 reports, RPT_ERROR, "No active image found, add a material or bake to an external file");
744 return false;
745 }
746 if (bkr->is_split_materials) {
748 reports,
749 RPT_ERROR,
750 "No active image found, add a material or bake without the Split Materials option");
751 return false;
752 }
753 }
754
755 /* Allocate material mapping. */
756 targets->materials_num = materials_num;
757 targets->material_to_image = MEM_calloc_arrayN<Image *>(targets->materials_num, __func__);
758
759 /* Error handling and tag (in case multiple materials share the same image). */
761
762 targets->images = nullptr;
763
764 for (int i = 0; i < materials_num; i++) {
765 Image *image;
766 const bNode *node = nullptr;
767 ED_object_get_active_image(ob, i + 1, &image, nullptr, &node, nullptr);
768
769 /* Don't bake to unselected images. */
770 if (node && !(node->flag & NODE_SELECT)) {
771 image = nullptr;
772 }
773
774 targets->material_to_image[i] = image;
775
776 /* Some materials have no image, we just ignore those cases.
777 * Also setup each image only once. */
778 if (image && !(image->id.tag & ID_TAG_DOIT)) {
779 LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
780 /* Add bake image. */
781 targets->images = static_cast<BakeImage *>(
782 MEM_recallocN(targets->images, sizeof(BakeImage) * (targets->images_num + 1)));
783 targets->images[targets->images_num].image = image;
784 targets->images[targets->images_num].tile_number = tile->tile_number;
785 targets->images_num++;
786 }
787
788 image->id.tag |= ID_TAG_DOIT;
789 }
790 }
791
792 return true;
793}
794
796 BakeTargets *targets,
797 Object *ob,
798 ReportList *reports)
799{
800 if (!bake_targets_init_image_textures(bkr, targets, ob, reports)) {
801 return false;
802 }
803
804 /* Saving to image datablocks. */
805 for (int i = 0; i < targets->images_num; i++) {
806 BakeImage *bk_image = &targets->images[i];
807
808 ImageUser iuser;
809 BKE_imageuser_default(&iuser);
810 iuser.tile = bk_image->tile_number;
811
812 void *lock;
813 ImBuf *ibuf = BKE_image_acquire_ibuf(bk_image->image, &iuser, &lock);
814
815 if (ibuf) {
816 bk_image->width = ibuf->x;
817 bk_image->height = ibuf->y;
818 bk_image->offset = targets->pixels_num;
819 BKE_image_get_tile_uv(bk_image->image, bk_image->tile_number, bk_image->uv_offset);
820
821 targets->pixels_num += size_t(ibuf->x) * size_t(ibuf->y);
822 }
823 else {
824 BKE_image_release_ibuf(bk_image->image, ibuf, lock);
825 BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
826 return false;
827 }
828 BKE_image_release_ibuf(bk_image->image, ibuf, lock);
829 }
830
831 return true;
832}
833
835 BakeTargets *targets,
836 Object *ob,
837 BakePixel *pixel_array,
838 ReportList *reports,
839 Mesh *mesh_eval)
840{
841 bool all_ok = true;
842 const bool is_tangent_normal = (bkr->pass_type == SCE_PASS_NORMAL) &&
844
845 for (int i = 0; i < targets->images_num; i++) {
846 BakeImage *bk_image = &targets->images[i];
847 const bool ok = write_internal_bake_pixels(bk_image->image,
848 bk_image->tile_number,
849 pixel_array + bk_image->offset,
850 targets->result +
851 bk_image->offset * targets->channels_num,
852 bk_image->width,
853 bk_image->height,
854 bkr->margin,
855 bkr->margin_type,
856 bkr->is_clear,
857 targets->is_noncolor,
858 is_tangent_normal,
859 mesh_eval,
860 bkr->uv_layer,
861 bk_image->uv_offset);
862
863 /* might be read by UI to set active image for display */
864 bake_update_image(bkr->area, bk_image->image);
865
866 if (!ok) {
867 BKE_reportf(reports,
868 RPT_ERROR,
869 "Problem saving the bake map internally for object \"%s\"",
870 ob->id.name + 2);
871 all_ok = false;
872 }
873 else {
875 reports, RPT_INFO, "Baking map saved to internal image, save it externally or pack it");
876 }
877 }
878
879 return all_ok;
880}
881
883 BakeTargets *targets,
884 Object *ob,
885 ReportList *reports)
886{
887 if (!bake_targets_init_image_textures(bkr, targets, ob, reports)) {
888 return false;
889 }
890
891 /* Saving to disk. */
892 for (int i = 0; i < targets->images_num; i++) {
893 BakeImage *bk_image = &targets->images[i];
894
895 bk_image->width = bkr->width;
896 bk_image->height = bkr->height;
897 bk_image->offset = targets->pixels_num;
898
899 targets->pixels_num += size_t(bkr->width) * size_t(bkr->height);
900
901 if (!bkr->is_split_materials) {
902 break;
903 }
904 }
905
906 if (!bkr->is_split_materials) {
907 /* saving a single image */
908 for (int i = 0; i < targets->materials_num; i++) {
909 targets->material_to_image[i] = targets->images[0].image;
910 }
911 }
912
913 return true;
914}
915
917 BakeTargets *targets,
918 Object *ob,
919 Object *ob_eval,
920 Mesh *mesh_eval,
921 BakePixel *pixel_array,
922 ReportList *reports)
923{
924 bool all_ok = true;
925 const bool is_tangent_normal = (bkr->pass_type == SCE_PASS_NORMAL) &&
927
928 for (int i = 0; i < targets->images_num; i++) {
929 BakeImage *bk_image = &targets->images[i];
930
931 BakeData *bake = &bkr->scene->r.bake;
932 char filepath[FILE_MAX];
933
935 filepath,
936 bkr->filepath,
938 nullptr,
939 0,
940 bake->im_format.imtype,
941 true,
942 false,
943 nullptr);
944 BLI_assert_msg(errors.is_empty(),
945 "Path parsing errors should only occur when a variable map is provided.");
946 UNUSED_VARS_NDEBUG(errors);
947
948 if (bkr->is_automatic_name) {
949 BLI_path_suffix(filepath, FILE_MAX, ob->id.name + 2, "_");
950 BLI_path_suffix(filepath, FILE_MAX, bkr->identifier, "_");
951 }
952
953 if (bkr->is_split_materials) {
954 if (ob_eval->mat[i]) {
955 BLI_path_suffix(filepath, FILE_MAX, ob_eval->mat[i]->id.name + 2, "_");
956 }
957 else if (mesh_eval->mat[i]) {
958 BLI_path_suffix(filepath, FILE_MAX, mesh_eval->mat[i]->id.name + 2, "_");
959 }
960 else {
961 /* if everything else fails, use the material index */
962 char tmp[5];
963 SNPRINTF_UTF8(tmp, "%d", i % 1000);
964 BLI_path_suffix(filepath, FILE_MAX, tmp, "_");
965 }
966 }
967
968 if (bk_image->tile_number) {
969 char tmp[12];
970 SNPRINTF_UTF8(tmp, "%d", bk_image->tile_number);
971 BLI_path_suffix(filepath, FILE_MAX, tmp, "_");
972 }
973
974 /* save it externally */
975 const bool ok = write_external_bake_pixels(filepath,
976 pixel_array + bk_image->offset,
977 targets->result +
978 bk_image->offset * targets->channels_num,
979 bk_image->width,
980 bk_image->height,
981 bkr->margin,
982 bkr->margin_type,
983 &bake->im_format,
984 targets->is_noncolor,
985 is_tangent_normal,
986 mesh_eval,
987 bkr->uv_layer,
988 bk_image->uv_offset);
989
990 if (!ok) {
991 BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", filepath);
992 all_ok = false;
993 }
994 else {
995 BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", filepath);
996 }
997
998 if (!bkr->is_split_materials) {
999 break;
1000 }
1001 }
1002
1003 return all_ok;
1004}
1005
1006/* Vertex Color Bake Targets */
1007
1009 BakeTargets *targets,
1010 Object *ob,
1011 ReportList *reports)
1012{
1013 if (ob->type != OB_MESH) {
1014 BKE_report(reports, RPT_ERROR, "Color attribute baking is only supported for mesh objects");
1015 return false;
1016 }
1017
1018 Mesh *mesh = static_cast<Mesh *>(ob->data);
1019 if (!BKE_id_attributes_color_find(&mesh->id, mesh->active_color_attribute)) {
1020 BKE_report(reports, RPT_ERROR, "No active color attribute to bake to");
1021 return false;
1022 }
1023
1024 /* Ensure mesh and editmesh topology are in sync. */
1025 editmode_load(bmain, ob);
1026
1027 targets->images = MEM_callocN<BakeImage>(__func__);
1028 targets->images_num = 1;
1029
1030 targets->material_to_image = MEM_calloc_arrayN<Image *>(ob->totcol, __func__);
1031 targets->materials_num = ob->totcol;
1032
1033 BakeImage *bk_image = &targets->images[0];
1034 bk_image->width = std::ceil(std::sqrt(mesh->corners_num));
1035 bk_image->height = bk_image->width;
1036 bk_image->offset = 0;
1037 bk_image->image = nullptr;
1038
1039 targets->pixels_num = bk_image->width * bk_image->height;
1040
1041 return true;
1042}
1043
1044static int find_original_loop(const OffsetIndices<int> orig_faces,
1045 const Span<int> orig_corner_verts,
1046 const int *vert_origindex,
1047 const int *poly_origindex,
1048 const int poly_eval,
1049 const int vert_eval)
1050{
1051 /* Get original vertex and face index. There is currently no loop mapping
1052 * in modifier stack evaluation. */
1053 const int vert_orig = vert_origindex[vert_eval];
1054 const int poly_orig_index = poly_origindex[poly_eval];
1055
1056 if (vert_orig == ORIGINDEX_NONE || poly_orig_index == ORIGINDEX_NONE) {
1057 return ORIGINDEX_NONE;
1058 }
1059
1060 /* Find matching loop with original vertex in original face. */
1061 const IndexRange orig_face = orig_faces[poly_orig_index];
1062 const int *poly_verts_orig = &orig_corner_verts[orig_face.start()];
1063 for (int j = 0; j < orig_face.size(); ++j) {
1064 if (poly_verts_orig[j] == vert_orig) {
1065 return orig_face.start() + j;
1066 }
1067 }
1068
1069 return ORIGINDEX_NONE;
1070}
1071
1073 Object *ob,
1074 Mesh *mesh_eval,
1075 BakePixel *pixel_array)
1076{
1077 Mesh *mesh = static_cast<Mesh *>(ob->data);
1078 const int pixels_num = targets->pixels_num;
1079
1080 /* Initialize blank pixels. */
1081 for (int i = 0; i < pixels_num; i++) {
1082 BakePixel *pixel = &pixel_array[i];
1083
1084 pixel->primitive_id = -1;
1085 pixel->object_id = 0;
1086 pixel->seed = 0;
1087 pixel->du_dx = 0.0f;
1088 pixel->du_dy = 0.0f;
1089 pixel->dv_dx = 0.0f;
1090 pixel->dv_dy = 0.0f;
1091 pixel->uv[0] = 0.0f;
1092 pixel->uv[1] = 0.0f;
1093 }
1094
1095 /* Populate through adjacent triangles, first triangle wins. */
1096 const int corner_tris_num = poly_to_tri_count(mesh_eval->faces_num, mesh_eval->corners_num);
1097 int3 *corner_tris = MEM_malloc_arrayN<int3>(corner_tris_num, __func__);
1098
1099 const Span<int> corner_verts = mesh_eval->corner_verts();
1100 bke::mesh::corner_tris_calc(mesh_eval->vert_positions(),
1101 mesh_eval->faces(),
1102 corner_verts,
1103 {corner_tris, corner_tris_num});
1104 const Span<int> tri_faces = mesh_eval->corner_tri_faces();
1105
1106 /* For mapping back to original mesh in case there are modifiers. */
1107 const int *vert_origindex = static_cast<const int *>(
1109 const int *poly_origindex = static_cast<const int *>(
1111 const OffsetIndices orig_faces = mesh->faces();
1112 const Span<int> orig_corner_verts = mesh->corner_verts();
1113
1114 for (int i = 0; i < corner_tris_num; i++) {
1115 const int3 &tri = corner_tris[i];
1116 const int face_i = tri_faces[i];
1117
1118 for (int j = 0; j < 3; j++) {
1119 uint l = tri[j];
1120 const int v = corner_verts[l];
1121
1122 /* Map back to original loop if there are modifiers. */
1123 if (vert_origindex != nullptr && poly_origindex != nullptr) {
1125 orig_faces, orig_corner_verts, vert_origindex, poly_origindex, face_i, v);
1126 if (l == ORIGINDEX_NONE || l >= mesh->corners_num) {
1127 continue;
1128 }
1129 }
1130
1131 BakePixel *pixel = &pixel_array[l];
1132
1133 if (pixel->primitive_id != -1) {
1134 continue;
1135 }
1136
1137 pixel->primitive_id = i;
1138
1139 /* Seed is the vertex, so that sampling noise is coherent for the same
1140 * vertex, but different corners can still have different normals,
1141 * materials and UVs. */
1142 pixel->seed = v;
1143
1144 /* Barycentric coordinates. */
1145 if (j == 0) {
1146 pixel->uv[0] = 1.0f;
1147 pixel->uv[1] = 0.0f;
1148 }
1149 else if (j == 1) {
1150 pixel->uv[0] = 0.0f;
1151 pixel->uv[1] = 1.0f;
1152 }
1153 else if (j == 2) {
1154 pixel->uv[0] = 0.0f;
1155 pixel->uv[1] = 0.0f;
1156 }
1157 }
1158 }
1159
1160 MEM_freeN(corner_tris);
1161}
1162
1163static void bake_result_add_to_rgba(float rgba[4], const float *result, const int channels_num)
1164{
1165 if (channels_num == 4) {
1166 add_v4_v4(rgba, result);
1167 }
1168 else if (channels_num == 3) {
1169 add_v3_v3(rgba, result);
1170 rgba[3] += 1.0f;
1171 }
1172 else {
1173 rgba[0] += result[0];
1174 rgba[1] += result[0];
1175 rgba[2] += result[0];
1176 rgba[3] += 1.0f;
1177 }
1178}
1179
1180static void convert_float_color_to_byte_color(const MPropCol *float_colors,
1181 const int num,
1182 const bool is_noncolor,
1183 MLoopCol *byte_colors)
1184{
1185 if (is_noncolor) {
1186 for (int i = 0; i < num; i++) {
1187 unit_float_to_uchar_clamp_v4(&byte_colors->r, float_colors[i].color);
1188 }
1189 }
1190 else {
1191 for (int i = 0; i < num; i++) {
1192 linearrgb_to_srgb_uchar4(&byte_colors[i].r, float_colors[i].color);
1193 }
1194 }
1195}
1196
1198{
1199 Mesh *mesh = static_cast<Mesh *>(ob->data);
1200 const CustomDataLayer *active_color_layer = BKE_id_attributes_color_find(
1201 &mesh->id, mesh->active_color_attribute);
1202 BLI_assert(active_color_layer != nullptr);
1204 const bke::AttrDomain domain = BKE_attribute_domain(owner, active_color_layer);
1205
1206 const int channels_num = targets->channels_num;
1207 const bool is_noncolor = targets->is_noncolor;
1208 const float *result = targets->result;
1209
1210 if (domain == bke::AttrDomain::Point) {
1211 const int totvert = mesh->verts_num;
1212 const int totloop = mesh->corners_num;
1213
1214 MPropCol *mcol = MEM_calloc_arrayN<MPropCol>(totvert, __func__);
1215
1216 /* Accumulate float vertex colors in scene linear color space. */
1217 int *num_loops_for_vertex = MEM_calloc_arrayN<int>(mesh->verts_num, "num_loops_for_vertex");
1218
1219 const Span<int> corner_verts = mesh->corner_verts();
1220 for (int i = 0; i < totloop; i++) {
1221 const int v = corner_verts[i];
1222 bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num);
1223 num_loops_for_vertex[v]++;
1224 }
1225
1226 /* Normalize for number of loops. */
1227 for (int i = 0; i < totvert; i++) {
1228 if (num_loops_for_vertex[i] > 0) {
1229 mul_v4_fl(mcol[i].color, 1.0f / num_loops_for_vertex[i]);
1230 }
1231 }
1232
1233 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
1234 /* Copy to bmesh. */
1235 const int active_color_offset = CustomData_get_offset_named(
1236 &em->bm->vdata, eCustomDataType(active_color_layer->type), active_color_layer->name);
1237 BMVert *v;
1238 BMIter viter;
1239 int i = 0;
1240 BM_ITER_MESH (v, &viter, em->bm, BM_VERTS_OF_MESH) {
1241 void *data = BM_ELEM_CD_GET_VOID_P(v, active_color_offset);
1242 if (active_color_layer->type == CD_PROP_COLOR) {
1243 memcpy(data, &mcol[i], sizeof(MPropCol));
1244 }
1245 else {
1247 &mcol[i], 1, is_noncolor, static_cast<MLoopCol *>(data));
1248 }
1249 i++;
1250 }
1251 }
1252 else {
1253 /* Copy to mesh. */
1254 if (active_color_layer->type == CD_PROP_COLOR) {
1255 memcpy(active_color_layer->data, mcol, sizeof(MPropCol) * mesh->verts_num);
1256 }
1257 else {
1259 mcol, totvert, is_noncolor, static_cast<MLoopCol *>(active_color_layer->data));
1260 }
1261 }
1262
1263 MEM_freeN(mcol);
1264
1265 MEM_SAFE_FREE(num_loops_for_vertex);
1266 }
1267 else if (domain == bke::AttrDomain::Corner) {
1268 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
1269 /* Copy to bmesh. */
1270 const int active_color_offset = CustomData_get_offset_named(
1271 &em->bm->ldata, eCustomDataType(active_color_layer->type), active_color_layer->name);
1272 BMFace *f;
1273 BMIter fiter;
1274 int i = 0;
1275 BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
1276 BMLoop *l;
1277 BMIter liter;
1278 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
1280 zero_v4(color.color);
1281 bake_result_add_to_rgba(color.color, &result[i * channels_num], channels_num);
1282 i++;
1283
1284 void *data = BM_ELEM_CD_GET_VOID_P(l, active_color_offset);
1285 if (active_color_layer->type == CD_PROP_COLOR) {
1286 memcpy(data, &color, sizeof(MPropCol));
1287 }
1288 else {
1290 &color, 1, is_noncolor, static_cast<MLoopCol *>(data));
1291 }
1292 }
1293 }
1294 }
1295 else {
1296 /* Copy to mesh. */
1297 if (active_color_layer->type == CD_PROP_COLOR) {
1298 MPropCol *colors = static_cast<MPropCol *>(active_color_layer->data);
1299 for (int i = 0; i < mesh->corners_num; i++) {
1300 zero_v4(colors[i].color);
1301 bake_result_add_to_rgba(colors[i].color, &result[i * channels_num], channels_num);
1302 }
1303 }
1304 else {
1305 MLoopCol *colors = static_cast<MLoopCol *>(active_color_layer->data);
1306 for (int i = 0; i < mesh->corners_num; i++) {
1308 zero_v4(color.color);
1309 bake_result_add_to_rgba(color.color, &result[i * channels_num], channels_num);
1310 convert_float_color_to_byte_color(&color, 1, is_noncolor, &colors[i]);
1311 }
1312 }
1313 }
1314 }
1315
1317
1318 return true;
1319}
1320
1321/* Bake Targets */
1322
1323static bool bake_targets_init(const BakeAPIRender *bkr,
1324 BakeTargets *targets,
1325 Object *ob,
1326 Object *ob_eval,
1327 ReportList *reports)
1328{
1330 if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
1331 if (!bake_targets_init_internal(bkr, targets, ob_eval, reports)) {
1332 return false;
1333 }
1334 }
1335 else if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
1336 if (!bake_targets_init_external(bkr, targets, ob_eval, reports)) {
1337 return false;
1338 }
1339 }
1340 }
1341 else if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) {
1342 if (!bake_targets_init_vertex_colors(bkr->main, targets, ob, reports)) {
1343 return false;
1344 }
1345 }
1346
1347 if (targets->pixels_num == 0) {
1348 return false;
1349 }
1350
1351 targets->is_noncolor = is_noncolor_pass(bkr->pass_type);
1352 targets->channels_num = RE_pass_depth(bkr->pass_type);
1353 targets->result = MEM_calloc_arrayN<float>(targets->channels_num * targets->pixels_num,
1354 "bake return pixels");
1355
1356 return true;
1357}
1358
1360 BakeTargets *targets,
1361 Object *ob,
1362 Mesh *mesh_eval,
1363 BakePixel *pixel_array)
1364{
1365 if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) {
1366 bake_targets_populate_pixels_color_attributes(targets, ob, mesh_eval, pixel_array);
1367 }
1368 else {
1369 RE_bake_pixels_populate(mesh_eval, pixel_array, targets->pixels_num, targets, bkr->uv_layer);
1370 }
1371}
1372
1373static bool bake_targets_output(const BakeAPIRender *bkr,
1374 BakeTargets *targets,
1375 Object *ob,
1376 Object *ob_eval,
1377 Mesh *mesh_eval,
1378 BakePixel *pixel_array,
1379 ReportList *reports)
1380{
1382 if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
1383 return bake_targets_output_internal(bkr, targets, ob, pixel_array, reports, mesh_eval);
1384 }
1385 if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
1387 bkr, targets, ob, ob_eval, mesh_eval, pixel_array, reports);
1388 }
1389 }
1390 else if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) {
1391 return bake_targets_output_vertex_colors(targets, ob);
1392 }
1393
1394 return false;
1395}
1396
1397static void bake_targets_free(BakeTargets *targets)
1398{
1399 MEM_SAFE_FREE(targets->images);
1401 MEM_SAFE_FREE(targets->result);
1402}
1403
1404/* Main Bake Logic */
1405
1407 Object *ob_low,
1408 const Span<PointerRNA> selected_objects,
1409 ReportList *reports)
1410{
1411 Render *re = bkr->render;
1412 Main *bmain = bkr->main;
1413 Scene *scene = bkr->scene;
1414 ViewLayer *view_layer = bkr->view_layer;
1415
1416 /* We build a depsgraph for the baking,
1417 * so we don't need to change the original data to adjust visibility and modifiers. */
1418 Depsgraph *depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
1419
1420 /* Ensure meshes are generated even for objects with animated visibility, see: #107426. */
1422
1424
1426 bool ok = false;
1427
1428 Object *ob_cage = nullptr;
1429 Object *ob_cage_eval = nullptr;
1430 Object *ob_low_eval = nullptr;
1431
1432 BakeHighPolyData *highpoly = nullptr;
1433 int highpoly_num = 0;
1434
1435 Mesh *me_low_eval = nullptr;
1436 Mesh *me_cage_eval = nullptr;
1437
1438 MultiresModifierData *mmd_low = nullptr;
1439 int mmd_flags_low = 0;
1440
1441 BakePixel *pixel_array_low = nullptr;
1442 BakePixel *pixel_array_high = nullptr;
1443
1444 BakeTargets targets = {nullptr};
1445
1446 const bool preserve_origindex = (bkr->target == R_BAKE_TARGET_VERTEX_COLORS);
1447 const bool check_valid_uv_map = (bkr->target == R_BAKE_TARGET_IMAGE_TEXTURES);
1448
1449 RE_bake_engine_set_engine_parameters(re, bmain, scene);
1450
1451 if (!RE_bake_has_engine(re)) {
1452 BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
1453 goto cleanup;
1454 }
1455
1456 if (!bkr->uv_layer.empty()) {
1457 Mesh *mesh = (Mesh *)ob_low->data;
1458 const bke::AttributeAccessor attributes = mesh->attributes();
1459 const std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(
1460 bkr->uv_layer);
1462 BKE_reportf(reports,
1463 RPT_ERROR,
1464 "No UV layer named \"%s\" found in the object \"%s\"",
1465 bkr->uv_layer.c_str(),
1466 ob_low->id.name + 2);
1467 goto cleanup;
1468 }
1469 }
1470
1471 if (bkr->is_selected_to_active) {
1472 highpoly_num = 0;
1473
1474 for (const PointerRNA &ptr : selected_objects) {
1475 Object *ob_iter = static_cast<Object *>(ptr.data);
1476
1477 if (ob_iter == ob_low) {
1478 continue;
1479 }
1480
1481 highpoly_num++;
1482 }
1483
1484 if (bkr->is_cage && bkr->custom_cage[0] != '\0') {
1485 ob_cage = static_cast<Object *>(
1486 BLI_findstring(&bmain->objects, bkr->custom_cage, offsetof(ID, name) + 2));
1487
1488 if (ob_cage == nullptr || ob_cage->type != OB_MESH) {
1489 BKE_report(reports, RPT_ERROR, "No valid cage object");
1490 goto cleanup;
1491 }
1492 else {
1493 ob_cage_eval = DEG_get_evaluated(depsgraph, ob_cage);
1494 if (ob_cage_eval->id.orig_id != &ob_cage->id) {
1495 BKE_reportf(reports,
1496 RPT_ERROR,
1497 "Cage object \"%s\" not found in evaluated scene, it may be hidden",
1498 ob_cage->id.name + 2);
1499 goto cleanup;
1500 }
1501 ob_cage_eval->visibility_flag |= OB_HIDE_RENDER;
1504 }
1505 }
1506 }
1507
1508 /* for multires bake, use linear UV subdivision to match low res UVs */
1511 {
1513 if (mmd_low) {
1514 mmd_flags_low = mmd_low->flags;
1516 }
1517 }
1518
1519 /* Make sure depsgraph is up to date. */
1521 ob_low_eval = DEG_get_evaluated(depsgraph, ob_low);
1522
1523 /* get the mesh as it arrives in the renderer */
1524 me_low_eval = bake_mesh_new_from_object(depsgraph, ob_low_eval, preserve_origindex);
1525
1526 /* Initialize bake targets. */
1527 if (!bake_targets_init(bkr, &targets, ob_low, ob_low_eval, reports)) {
1528 goto cleanup;
1529 }
1530
1531 /* Populate the pixel array with the face data. Except if we use a cage, then
1532 * it is populated later with the cage mesh (smoothed version of the mesh). */
1533 pixel_array_low = MEM_malloc_arrayN<BakePixel>(targets.pixels_num, "bake pixels low poly");
1534 if ((bkr->is_selected_to_active && (ob_cage == nullptr) && bkr->is_cage) == false) {
1535 if (check_valid_uv_map && !CustomData_has_layer(&me_low_eval->corner_data, CD_PROP_FLOAT2)) {
1536 BKE_reportf(reports,
1537 RPT_ERROR,
1538 "No UV map found in the evaluated object \"%s\"",
1539 ob_low->id.name + 2);
1540 goto cleanup;
1541 }
1542 bake_targets_populate_pixels(bkr, &targets, ob_low, me_low_eval, pixel_array_low);
1543 }
1544
1545 if (bkr->is_selected_to_active) {
1546 int i = 0;
1547
1548 /* prepare cage mesh */
1549 if (ob_cage) {
1550 me_cage_eval = bake_mesh_new_from_object(depsgraph, ob_cage_eval, preserve_origindex);
1551 if ((me_low_eval->faces_num != me_cage_eval->faces_num) ||
1552 (me_low_eval->corners_num != me_cage_eval->corners_num))
1553 {
1554 BKE_report(reports,
1555 RPT_ERROR,
1556 "Invalid cage object, the cage mesh must have the same number "
1557 "of faces as the active object");
1558 goto cleanup;
1559 }
1560 }
1561 else if (bkr->is_cage) {
1562 bool is_changed = false;
1563
1564 ModifierData *md = static_cast<ModifierData *>(ob_low_eval->modifiers.first);
1565 while (md) {
1566 ModifierData *md_next = md->next;
1567
1568 /* Edge Split cannot be applied in the cage,
1569 * the cage is supposed to have interpolated normals
1570 * between the faces unless the geometry is physically
1571 * split. So we create a copy of the low poly mesh without
1572 * the eventual edge split. */
1573
1574 if (md->type == eModifierType_EdgeSplit) {
1575 BLI_remlink(&ob_low_eval->modifiers, md);
1577 is_changed = true;
1578 }
1579 md = md_next;
1580 }
1581
1582 if (is_changed) {
1583 /* Make sure object is evaluated with the new modifier settings.
1584 *
1585 * NOTE: Since the dependency graph was fully evaluated prior to bake, and we only made
1586 * single modification to this object all the possible dependencies for evaluation are
1587 * already up to date. This means we can do a cheap single object update
1588 * (as an opposite of full depsgraph update). */
1589 BKE_object_eval_reset(ob_low_eval);
1590 BKE_object_handle_data_update(depsgraph, scene, ob_low_eval);
1591 }
1592
1593 me_cage_eval = BKE_mesh_new_from_object(
1594 nullptr, ob_low_eval, false, preserve_origindex, true);
1595 if (check_valid_uv_map && !CustomData_has_layer(&me_cage_eval->corner_data, CD_PROP_FLOAT2))
1596 {
1597 BKE_reportf(reports,
1598 RPT_ERROR,
1599 "No UV map found in the evaluated object \"%s\"",
1600 ob_low->id.name + 2);
1601 goto cleanup;
1602 }
1603 bake_targets_populate_pixels(bkr, &targets, ob_low, me_cage_eval, pixel_array_low);
1604 }
1605
1606 highpoly = MEM_calloc_arrayN<BakeHighPolyData>(highpoly_num, "bake high poly objects");
1607
1608 /* populate highpoly array */
1609 for (const PointerRNA &ptr : selected_objects) {
1610 Object *ob_iter = static_cast<Object *>(ptr.data);
1611
1612 if (ob_iter == ob_low) {
1613 continue;
1614 }
1615
1616 Object *ob_eval = DEG_get_evaluated(depsgraph, ob_iter);
1617 if (ob_eval->id.orig_id != &ob_iter->id) {
1618 BKE_reportf(reports,
1619 RPT_ERROR,
1620 "Object \"%s\" not found in evaluated scene, it may be hidden",
1621 ob_iter->id.name + 2);
1622 goto cleanup;
1623 }
1624
1625 ob_eval->visibility_flag &= ~OB_HIDE_RENDER;
1627
1628 Mesh *mesh_eval = BKE_mesh_new_from_object(nullptr, ob_eval, false, false, true);
1629
1630 /* Initialize `highpoly` data. */
1631 highpoly[i].ob = ob_iter;
1632 highpoly[i].ob_eval = ob_eval;
1633 highpoly[i].mesh = mesh_eval;
1634
1635 /* Low-poly to high-poly transformation matrix. */
1636 copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->object_to_world().ptr());
1637 invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
1638
1639 highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->object_to_world().ptr());
1640 i++;
1641
1642 /* NOTE(@ideasman42): While ideally this should never happen,
1643 * it's possible the `visibility_flag` assignment in this function
1644 * is overridden by animated visibility, see: #107426.
1645 *
1646 * There is also the potential that scripts called from depsgraph callbacks
1647 * change this value too, so we can't guarantee the mesh will be available.
1648 * Use an error here instead of a warning so users don't accidentally perform
1649 * a bake which seems to succeed with invalid results.
1650 * If visibility could be forced/overridden - it would help avoid the problem. */
1651 if (UNLIKELY(mesh_eval == nullptr)) {
1653 reports,
1654 RPT_ERROR,
1655 "Failed to access mesh from object \"%s\", ensure it's visible while rendering",
1656 ob_iter->id.name + 2);
1657 goto cleanup;
1658 }
1659 }
1660
1661 BLI_assert(i == highpoly_num);
1662
1663 if (ob_cage != nullptr) {
1664 ob_cage_eval->visibility_flag |= OB_HIDE_RENDER;
1667 }
1668 ob_low_eval->visibility_flag |= OB_HIDE_RENDER;
1670
1671 /* populate the pixel arrays with the corresponding face data for each high poly object */
1672 pixel_array_high = MEM_malloc_arrayN<BakePixel>(targets.pixels_num, "bake pixels high poly");
1673
1675 me_low_eval,
1676 pixel_array_low,
1677 pixel_array_high,
1678 highpoly,
1679 highpoly_num,
1680 targets.pixels_num,
1681 ob_cage != nullptr,
1682 bkr->cage_extrusion,
1683 bkr->max_ray_distance,
1684 ob_low_eval->object_to_world().ptr(),
1685 (ob_cage ? ob_cage->object_to_world().ptr() : ob_low_eval->object_to_world().ptr()),
1686 me_cage_eval))
1687 {
1688 BKE_report(reports, RPT_ERROR, "Error handling selected objects");
1689 goto cleanup;
1690 }
1691
1692 /* the baking itself */
1693 for (i = 0; i < highpoly_num; i++) {
1694 ok = RE_bake_engine(re,
1695 depsgraph,
1696 highpoly[i].ob_eval,
1697 i,
1698 pixel_array_high,
1699 &targets,
1700 bkr->pass_type,
1701 bkr->pass_filter,
1702 targets.result);
1703 if (!ok) {
1705 reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
1706 goto cleanup;
1707 }
1708 }
1709 }
1710 else {
1711 /* If low poly is not renderable it should have failed long ago. */
1712 BLI_assert((ob_low_eval->visibility_flag & OB_HIDE_RENDER) == 0);
1713
1714 if (RE_bake_has_engine(re)) {
1715 ok = RE_bake_engine(re,
1716 depsgraph,
1717 ob_low_eval,
1718 0,
1719 pixel_array_low,
1720 &targets,
1721 bkr->pass_type,
1722 bkr->pass_filter,
1723 targets.result);
1724 }
1725 else {
1726 BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
1727 goto cleanup;
1728 }
1729 }
1730
1731 /* normal space conversion
1732 * the normals are expected to be in world space, +X +Y +Z */
1733 if (ok && bkr->pass_type == SCE_PASS_NORMAL) {
1734 switch (bkr->normal_space) {
1735 case R_BAKE_SPACE_WORLD: {
1736 /* Cycles internal format */
1737 if ((bkr->normal_swizzle[0] == R_BAKE_POSX) && (bkr->normal_swizzle[1] == R_BAKE_POSY) &&
1738 (bkr->normal_swizzle[2] == R_BAKE_POSZ))
1739 {
1740 break;
1741 }
1742 RE_bake_normal_world_to_world(pixel_array_low,
1743 targets.pixels_num,
1744 targets.channels_num,
1745 targets.result,
1746 bkr->normal_swizzle);
1747 break;
1748 }
1749 case R_BAKE_SPACE_OBJECT: {
1750 RE_bake_normal_world_to_object(pixel_array_low,
1751 targets.pixels_num,
1752 targets.channels_num,
1753 targets.result,
1754 ob_low_eval,
1755 bkr->normal_swizzle);
1756 break;
1757 }
1758 case R_BAKE_SPACE_TANGENT: {
1759 if (bkr->is_selected_to_active) {
1760 RE_bake_normal_world_to_tangent(pixel_array_low,
1761 targets.pixels_num,
1762 targets.channels_num,
1763 targets.result,
1764 me_low_eval,
1765 bkr->normal_swizzle,
1766 ob_low_eval->object_to_world().ptr());
1767 }
1768 else {
1769 /* From multi-resolution. */
1770 Mesh *me_nores = nullptr;
1771 ModifierData *md = nullptr;
1772 int mode;
1773
1774 BKE_object_eval_reset(ob_low_eval);
1776
1777 if (md) {
1778 mode = md->mode;
1780
1781 /* Evaluate modifiers again. */
1782 me_nores = BKE_mesh_new_from_object(nullptr, ob_low_eval, false, false, true);
1783 if (check_valid_uv_map &&
1785 {
1786 BKE_reportf(reports,
1787 RPT_ERROR,
1788 "No UV map found in the evaluated object \"%s\"",
1789 ob_low->id.name + 2);
1790 BKE_id_free(nullptr, &me_nores->id);
1791 goto cleanup;
1792 }
1793 bake_targets_populate_pixels(bkr, &targets, ob_low, me_nores, pixel_array_low);
1794 }
1795
1796 RE_bake_normal_world_to_tangent(pixel_array_low,
1797 targets.pixels_num,
1798 targets.channels_num,
1799 targets.result,
1800 (me_nores) ? me_nores : me_low_eval,
1801 bkr->normal_swizzle,
1802 ob_low_eval->object_to_world().ptr());
1803
1804 if (md) {
1805 BKE_id_free(nullptr, &me_nores->id);
1806 md->mode = mode;
1807 }
1808 }
1809 break;
1810 }
1811 default:
1812 break;
1813 }
1814 }
1815
1816 if (!ok) {
1817 BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
1818 op_result = OPERATOR_CANCELLED;
1819 }
1820 else {
1821 /* save the results */
1823 bkr, &targets, ob_low, ob_low_eval, me_low_eval, pixel_array_low, reports))
1824 {
1825 op_result = OPERATOR_FINISHED;
1826 }
1827 else {
1828 op_result = OPERATOR_CANCELLED;
1829 }
1830 }
1831
1832 bake_targets_refresh(&targets);
1833
1834cleanup:
1835
1836 if (highpoly) {
1837 for (int i = 0; i < highpoly_num; i++) {
1838 if (highpoly[i].mesh != nullptr) {
1839 BKE_id_free(nullptr, &highpoly[i].mesh->id);
1840 }
1841 }
1842 MEM_freeN(highpoly);
1843 }
1844
1845 if (mmd_low) {
1846 mmd_low->flags = mmd_flags_low;
1847 }
1848
1849 if (pixel_array_low) {
1850 MEM_freeN(pixel_array_low);
1851 }
1852
1853 if (pixel_array_high) {
1854 MEM_freeN(pixel_array_high);
1855 }
1856
1857 bake_targets_free(&targets);
1858
1859 if (me_low_eval != nullptr) {
1860 BKE_id_free(nullptr, &me_low_eval->id);
1861 }
1862
1863 if (me_cage_eval != nullptr) {
1864 BKE_id_free(nullptr, &me_cage_eval->id);
1865 }
1866
1868
1869 return op_result;
1870}
1871
1872/* Bake Operator */
1873
1875{
1876 bScreen *screen = CTX_wm_screen(C);
1877
1878 bkr->ob = CTX_data_active_object(C);
1879 bkr->main = CTX_data_main(C);
1881 bkr->scene = CTX_data_scene(C);
1882 bkr->area = screen ? BKE_screen_find_big_area(screen, SPACE_IMAGE, 10) : nullptr;
1883
1884 bkr->pass_type = eScenePassType(RNA_enum_get(op->ptr, "type"));
1885 bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
1886 bkr->margin = RNA_int_get(op->ptr, "margin");
1887 bkr->margin_type = eBakeMarginType(RNA_enum_get(op->ptr, "margin_type"));
1888
1889 bkr->save_mode = (eBakeSaveMode)RNA_enum_get(op->ptr, "save_mode");
1890 bkr->target = (eBakeTarget)RNA_enum_get(op->ptr, "target");
1891
1892 bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
1895 RNA_boolean_get(op->ptr, "use_split_materials");
1896 bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
1897 bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
1898 bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
1899 bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
1900 bkr->max_ray_distance = RNA_float_get(op->ptr, "max_ray_distance");
1901
1902 bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
1903 bkr->normal_swizzle[0] = eBakeNormalSwizzle(RNA_enum_get(op->ptr, "normal_r"));
1904 bkr->normal_swizzle[1] = eBakeNormalSwizzle(RNA_enum_get(op->ptr, "normal_g"));
1905 bkr->normal_swizzle[2] = eBakeNormalSwizzle(RNA_enum_get(op->ptr, "normal_b"));
1906
1907 bkr->width = RNA_int_get(op->ptr, "width");
1908 bkr->height = RNA_int_get(op->ptr, "height");
1909 bkr->identifier = "";
1910
1911 bkr->uv_layer = RNA_string_get(op->ptr, "uv_layer");
1912
1913 RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
1914
1915 if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL && bkr->is_automatic_name) {
1916 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
1917 RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
1918 }
1919
1921
1922 bkr->reports = op->reports;
1923
1925
1926 bkr->render = RE_NewSceneRender(bkr->scene);
1927
1928 /* XXX hack to force saving to always be internal. Whether (and how) to support
1929 * external saving will be addressed later */
1930 if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
1932 }
1933
1934 if (((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT)) ||
1935 bkr->pass_type == SCE_PASS_UV)
1936 {
1938 }
1939}
1940
1942{
1943 Render *re;
1945 BakeAPIRender bkr = {nullptr};
1946 Scene *scene = CTX_data_scene(C);
1947
1948 G.is_break = false;
1949 G.is_rendering = true;
1950
1951 bake_set_props(op, scene);
1952
1953 bake_init_api_data(op, C, &bkr);
1954 re = bkr.render;
1955
1956 /* setup new render */
1957 RE_test_break_cb(re, nullptr, bake_break);
1958
1960 G.is_rendering = false;
1961 return result;
1962 }
1963
1964 if (!bake_objects_check(bkr.main,
1965 bkr.scene,
1966 bkr.view_layer,
1967 bkr.ob,
1968 bkr.selected_objects,
1969 bkr.reports,
1971 bkr.target))
1972 {
1973 G.is_rendering = false;
1974 return result;
1975 }
1976
1977 if (bkr.is_clear) {
1978 const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) &&
1980 bake_targets_clear(bkr.main, is_tangent);
1981 }
1982
1983 RE_SetReports(re, bkr.reports);
1984
1985 if (bkr.is_selected_to_active) {
1986 result = bake(&bkr, bkr.ob, bkr.selected_objects, bkr.reports);
1987 }
1988 else {
1989 bkr.is_clear = bkr.is_clear && bkr.selected_objects.size() == 1;
1990 for (const PointerRNA &ptr : bkr.selected_objects) {
1991 Object *ob_iter = static_cast<Object *>(ptr.data);
1992 result = bake(&bkr, ob_iter, {}, bkr.reports);
1993 }
1994 }
1995
1996 RE_SetReports(re, nullptr);
1997
1998 G.is_rendering = false;
1999 return result;
2000}
2001
2002static void bake_startjob(void *bkv, wmJobWorkerStatus *worker_status)
2003{
2004 BakeAPIRender *bkr = (BakeAPIRender *)bkv;
2005
2006 /* setup new render */
2007 bkr->do_update = &worker_status->do_update;
2008 bkr->progress = &worker_status->progress;
2009
2010 RE_SetReports(bkr->render, bkr->reports);
2011
2012 if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) {
2014 return;
2015 }
2016
2017 if (!bake_objects_check(bkr->main,
2018 bkr->scene,
2019 bkr->view_layer,
2020 bkr->ob,
2021 bkr->selected_objects,
2022 bkr->reports,
2024 bkr->target))
2025 {
2027 return;
2028 }
2029
2030 if (bkr->is_clear) {
2031 const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) &&
2033 bake_targets_clear(bkr->main, is_tangent);
2034 }
2035
2036 if (bkr->is_selected_to_active) {
2037 bkr->result = bake(bkr, bkr->ob, bkr->selected_objects, bkr->reports);
2038 }
2039 else {
2040 bkr->is_clear = bkr->is_clear && bkr->selected_objects.size() == 1;
2041 for (const PointerRNA &ptr : bkr->selected_objects) {
2042 Object *ob_iter = static_cast<Object *>(ptr.data);
2043 bkr->result = bake(bkr, ob_iter, {}, bkr->reports);
2044
2045 if (bkr->result == OPERATOR_CANCELLED) {
2046 return;
2047 }
2048 }
2049 }
2050
2051 RE_SetReports(bkr->render, nullptr);
2052}
2053
2054static void bake_job_complete(void *bkv)
2055{
2056 BakeAPIRender *bkr = (BakeAPIRender *)bkv;
2058}
2059static void bake_job_canceled(void *bkv)
2060{
2061 BakeAPIRender *bkr = (BakeAPIRender *)bkv;
2063}
2064
2065static void bake_freejob(void *bkv)
2066{
2067 BakeAPIRender *bkr = (BakeAPIRender *)bkv;
2068
2069 MEM_delete(bkr);
2070
2071 G.is_rendering = false;
2072}
2073
2074static void bake_set_props(wmOperator *op, Scene *scene)
2075{
2076 PropertyRNA *prop;
2077 BakeData *bake = &scene->r.bake;
2078
2079 prop = RNA_struct_find_property(op->ptr, "filepath");
2080 if (!RNA_property_is_set(op->ptr, prop)) {
2081 RNA_property_string_set(op->ptr, prop, bake->filepath);
2082 }
2083
2084 prop = RNA_struct_find_property(op->ptr, "width");
2085 if (!RNA_property_is_set(op->ptr, prop)) {
2086 RNA_property_int_set(op->ptr, prop, bake->width);
2087 }
2088
2089 prop = RNA_struct_find_property(op->ptr, "height");
2090 if (!RNA_property_is_set(op->ptr, prop)) {
2091 RNA_property_int_set(op->ptr, prop, bake->width);
2092 }
2093
2094 prop = RNA_struct_find_property(op->ptr, "margin");
2095 if (!RNA_property_is_set(op->ptr, prop)) {
2096 RNA_property_int_set(op->ptr, prop, bake->margin);
2097 }
2098
2099 prop = RNA_struct_find_property(op->ptr, "margin_type");
2100 if (!RNA_property_is_set(op->ptr, prop)) {
2101 RNA_property_enum_set(op->ptr, prop, bake->margin_type);
2102 }
2103
2104 prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
2105 if (!RNA_property_is_set(op->ptr, prop)) {
2106 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
2107 }
2108
2109 prop = RNA_struct_find_property(op->ptr, "max_ray_distance");
2110 if (!RNA_property_is_set(op->ptr, prop)) {
2111 RNA_property_float_set(op->ptr, prop, bake->max_ray_distance);
2112 }
2113
2114 prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
2115 if (!RNA_property_is_set(op->ptr, prop)) {
2116 RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
2117 }
2118
2119 prop = RNA_struct_find_property(op->ptr, "cage_object");
2120 if (!RNA_property_is_set(op->ptr, prop)) {
2122 op->ptr, prop, (bake->cage_object) ? bake->cage_object->id.name + 2 : "");
2123 }
2124
2125 prop = RNA_struct_find_property(op->ptr, "normal_space");
2126 if (!RNA_property_is_set(op->ptr, prop)) {
2127 RNA_property_enum_set(op->ptr, prop, bake->normal_space);
2128 }
2129
2130 prop = RNA_struct_find_property(op->ptr, "normal_r");
2131 if (!RNA_property_is_set(op->ptr, prop)) {
2132 RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
2133 }
2134
2135 prop = RNA_struct_find_property(op->ptr, "normal_g");
2136 if (!RNA_property_is_set(op->ptr, prop)) {
2137 RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
2138 }
2139
2140 prop = RNA_struct_find_property(op->ptr, "normal_b");
2141 if (!RNA_property_is_set(op->ptr, prop)) {
2142 RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
2143 }
2144
2145 prop = RNA_struct_find_property(op->ptr, "target");
2146 if (!RNA_property_is_set(op->ptr, prop)) {
2147 RNA_property_enum_set(op->ptr, prop, bake->target);
2148 }
2149
2150 prop = RNA_struct_find_property(op->ptr, "save_mode");
2151 if (!RNA_property_is_set(op->ptr, prop)) {
2152 RNA_property_enum_set(op->ptr, prop, bake->save_mode);
2153 }
2154
2155 prop = RNA_struct_find_property(op->ptr, "use_clear");
2156 if (!RNA_property_is_set(op->ptr, prop)) {
2157 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
2158 }
2159
2160 prop = RNA_struct_find_property(op->ptr, "use_cage");
2161 if (!RNA_property_is_set(op->ptr, prop)) {
2162 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
2163 }
2164
2165 prop = RNA_struct_find_property(op->ptr, "use_split_materials");
2166 if (!RNA_property_is_set(op->ptr, prop)) {
2167 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
2168 }
2169
2170 prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
2171 if (!RNA_property_is_set(op->ptr, prop)) {
2172 RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
2173 }
2174
2175 prop = RNA_struct_find_property(op->ptr, "pass_filter");
2176 if (!RNA_property_is_set(op->ptr, prop)) {
2177 RNA_property_enum_set(op->ptr, prop, bake->pass_filter);
2178 }
2179}
2180
2182{
2183 wmJob *wm_job;
2184 Render *re;
2185 Scene *scene = CTX_data_scene(C);
2186
2187 bake_set_props(op, scene);
2188
2189 /* only one render job at a time */
2191 return OPERATOR_CANCELLED;
2192 }
2193
2194 BakeAPIRender *bkr = MEM_new<BakeAPIRender>(__func__);
2195
2196 /* init bake render */
2197 bake_init_api_data(op, C, bkr);
2199 re = bkr->render;
2200
2201 /* setup new render */
2202 RE_test_break_cb(re, nullptr, bake_break);
2204
2205 /* setup job */
2206 wm_job = WM_jobs_get(CTX_wm_manager(C),
2208 scene,
2209 "Baking texture...",
2213 /* TODO: only draw bake image, can we enforce this. */
2215 wm_job, 0.5, (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) ? NC_GEOM | ND_DATA : NC_IMAGE, 0);
2217 wm_job, bake_startjob, nullptr, nullptr, nullptr, bake_job_complete, bake_job_canceled);
2218
2219 G.is_break = false;
2220 G.is_rendering = true;
2221
2222 WM_jobs_start(CTX_wm_manager(C), wm_job);
2223
2224 WM_cursor_wait(false);
2225
2226 /* add modal handler for ESC */
2228
2231}
2232
2234{
2235 PropertyRNA *prop;
2236
2237 /* identifiers */
2238 ot->name = "Bake";
2239 ot->description = "Bake image textures of selected objects";
2240 ot->idname = "OBJECT_OT_bake";
2241
2242 /* API callbacks. */
2243 ot->exec = bake_exec;
2244 ot->modal = bake_modal;
2245 ot->invoke = bake_invoke;
2247
2249 ot->srna,
2250 "type",
2253 "Type",
2254 "Type of pass to bake, some of them may not be supported by the current render engine");
2255 RNA_def_enum_flag(ot->srna,
2256 "pass_filter",
2259 "Pass Filter",
2260 "Filter to combined, diffuse, glossy, transmission and subsurface passes");
2262 "filepath",
2263 nullptr,
2264 FILE_MAX,
2265 "File Path",
2266 "Image filepath to use when saving externally");
2267 RNA_def_int(ot->srna,
2268 "width",
2269 512,
2270 1,
2271 INT_MAX,
2272 "Width",
2273 "Horizontal dimension of the baking map (external only)",
2274 64,
2275 4096);
2276 RNA_def_int(ot->srna,
2277 "height",
2278 512,
2279 1,
2280 INT_MAX,
2281 "Height",
2282 "Vertical dimension of the baking map (external only)",
2283 64,
2284 4096);
2285 RNA_def_int(ot->srna,
2286 "margin",
2287 16,
2288 0,
2289 INT_MAX,
2290 "Margin",
2291 "Extends the baked result as a post process filter",
2292 0,
2293 64);
2294 RNA_def_enum(ot->srna,
2295 "margin_type",
2298 "Margin Type",
2299 "Which algorithm to use to generate the margin");
2300 RNA_def_boolean(ot->srna,
2301 "use_selected_to_active",
2302 false,
2303 "Selected to Active",
2304 "Bake shading on the surface of selected objects to the active object");
2305 RNA_def_float(ot->srna,
2306 "max_ray_distance",
2307 0.0f,
2308 0.0f,
2309 FLT_MAX,
2310 "Max Ray Distance",
2311 "The maximum ray distance for matching points between the active and selected "
2312 "objects. If zero, there is no limit",
2313 0.0f,
2314 1.0f);
2315 RNA_def_float(ot->srna,
2316 "cage_extrusion",
2317 0.0f,
2318 0.0f,
2319 FLT_MAX,
2320 "Cage Extrusion",
2321 "Inflate the active object by the specified distance for baking. This helps "
2322 "matching to points nearer to the outside of the selected object meshes",
2323 0.0f,
2324 1.0f);
2325 RNA_def_string(ot->srna,
2326 "cage_object",
2327 nullptr,
2328 MAX_NAME,
2329 "Cage Object",
2330 "Object to use as cage, instead of calculating the cage from the active object "
2331 "with cage extrusion");
2332 RNA_def_enum(ot->srna,
2333 "normal_space",
2336 "Normal Space",
2337 "Choose normal space for baking");
2338 prop = RNA_def_enum(ot->srna,
2339 "normal_r",
2342 "R",
2343 "Axis to bake in red channel");
2345 prop = RNA_def_enum(ot->srna,
2346 "normal_g",
2349 "G",
2350 "Axis to bake in green channel");
2352 prop = RNA_def_enum(ot->srna,
2353 "normal_b",
2356 "B",
2357 "Axis to bake in blue channel");
2359 RNA_def_enum(ot->srna,
2360 "target",
2363 "Target",
2364 "Where to output the baked map");
2365 RNA_def_enum(ot->srna,
2366 "save_mode",
2369 "Save Mode",
2370 "Where to save baked image textures");
2371 RNA_def_boolean(ot->srna,
2372 "use_clear",
2373 false,
2374 "Clear",
2375 "Clear images before baking (only for internal saving)");
2376 RNA_def_boolean(ot->srna, "use_cage", false, "Cage", "Cast rays to active object from a cage");
2378 ot->srna,
2379 "use_split_materials",
2380 false,
2381 "Split Materials",
2382 "Split baked maps per material, using material name in output file (external only)");
2383 RNA_def_boolean(ot->srna,
2384 "use_automatic_name",
2385 false,
2386 "Automatic Name",
2387 "Automatically name the output file with the pass type");
2388 RNA_def_string(ot->srna,
2389 "uv_layer",
2390 nullptr,
2392 "UV Layer",
2393 "UV layer to override active");
2394}
2395
2396} // namespace blender::ed::object
blender::bke::AttrDomain BKE_attribute_domain(const AttributeOwner &owner, const struct CustomDataLayer *layer)
const struct CustomDataLayer * BKE_id_attributes_color_find(const struct ID *id, blender::StringRef name)
void BKE_callback_exec_id(Main *bmain, ID *id, eCbEvent evt)
Definition callbacks.cc:43
@ BKE_CB_EVT_OBJECT_BAKE_CANCEL
@ BKE_CB_EVT_OBJECT_BAKE_COMPLETE
@ BKE_CB_EVT_OBJECT_BAKE_PRE
bScreen * CTX_wm_screen(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
bool CTX_data_selected_objects(const bContext *C, blender::Vector< PointerRNA > *list)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
#define ORIGINDEX_NONE
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
int CustomData_get_active_layer_index(const CustomData *data, eCustomDataType type)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_mark_dirty(Image *image, ImBuf *ibuf)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_get_tile_uv(const Image *ima, const int tile_number, float r_uv[2])
void BKE_imageuser_default(ImageUser *iuser)
void BKE_image_free_gputextures(Image *ima)
Definition image_gpu.cc:581
bool BKE_imbuf_write(ImBuf *ibuf, const char *filepath, const ImageFormatData *imf)
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
blender::Vector< blender::bke::path_templates::Error > BKE_image_path_from_imtype(char *filepath, const char *base, const char *relbase, const blender::bke::path_templates::VariableMap *template_variables, int frame, char imtype, bool use_ext, bool use_frames, const char *suffix)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
void BKE_main_id_tag_idcode(Main *mainvar, short type, int tag, bool value)
Definition lib_id.cc:1217
void BKE_id_free(Main *bmain, void *idv)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
General operations, lookup, etc. for materials.
Material * BKE_object_material_get(Object *ob, short act)
Mesh * BKE_mesh_new_from_object(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers, bool preserve_origindex, bool ensure_subdivision)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_modifier_free(ModifierData *md)
General operations, lookup, etc. for blender objects.
void BKE_object_eval_reset(Object *ob_eval)
void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2621
ScrArea * BKE_screen_find_big_area(const bScreen *screen, int spacetype, short min)
Definition screen.cc:944
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4])
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool is_negative_m4(const float mat[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void zero_v4(float r[4])
MINLINE void add_v3_v3(float r[3], const float a[3])
ATTR_WARN_UNUSED_RESULT const size_t num
bool bool BLI_path_suffix(char *path, size_t path_maxncpy, const char *suffix, const char *sep) ATTR_NONNULL(1
#define FILE_MAX
#define SNPRINTF_UTF8(dst, format,...)
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define UNLIKELY(x)
#define ELEM(...)
#define BLT_I18NCONTEXT_COLOR
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_disable_visibility_optimization(Depsgraph *depsgraph)
Definition depsgraph.cc:349
@ DAG_EVAL_RENDER
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:278
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:306
void DEG_graph_build_from_view_layer(Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_IM
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
#define MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX
#define MAX_NAME
Definition DNA_defs.h:50
@ BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT
@ BASE_ENABLED_RENDER
@ eModifierMode_Render
@ eModifierType_EdgeSplit
@ eModifierType_Multires
@ SUBSURF_UV_SMOOTH_NONE
@ NODE_SELECT
Object is a sort of wrapper for general info.
@ OB_HIDE_RENDER
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_MESH
@ OB_CURVES_LEGACY
struct Scene Scene
eBakeTarget
@ R_BAKE_TARGET_VERTEX_COLORS
@ R_BAKE_TARGET_IMAGE_TEXTURES
eBakeNormalSwizzle
@ R_BAKE_POSY
@ R_BAKE_POSZ
@ R_BAKE_POSX
@ R_BAKE_SPACE_WORLD
@ R_BAKE_SPACE_TANGENT
@ R_BAKE_SPACE_OBJECT
eBakeMarginType
@ R_BAKE_EXTEND
@ R_BAKE_SPLIT_MAT
@ R_BAKE_AUTO_NAME
@ R_BAKE_TO_ACTIVE
@ R_BAKE_CAGE
@ R_BAKE_CLEAR
eBakeSaveMode
@ R_BAKE_SAVE_EXTERNAL
@ R_BAKE_SAVE_INTERNAL
@ R_BAKE_PASS_FILTER_DIFFUSE
@ R_BAKE_PASS_FILTER_NONE
@ R_BAKE_PASS_FILTER_COLOR
@ R_BAKE_PASS_FILTER_SUBSURFACE
@ R_BAKE_PASS_FILTER_INDIRECT
@ R_BAKE_PASS_FILTER_DIRECT
@ R_BAKE_PASS_FILTER_GLOSSY
@ R_BAKE_PASS_FILTER_EMIT
@ R_BAKE_PASS_FILTER_TRANSM
eScenePassType
@ SCE_PASS_NORMAL
@ SCE_PASS_DIFFUSE_COLOR
@ SCE_PASS_POSITION
@ SCE_PASS_UV
@ SCE_PASS_SUBSURFACE_COLOR
@ SCE_PASS_GLOSSY_COLOR
@ SCE_PASS_INDEXMA
@ SCE_PASS_INDEXOB
@ SCE_PASS_COMBINED
@ SCE_PASS_VECTOR
@ SCE_PASS_TRANSM_COLOR
@ SCE_PASS_DEPTH
@ SPACE_IMAGE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
struct wmOperator wmOperator
void ED_mesh_split_faces(Mesh *mesh)
bool ED_operator_object_active_editable_mesh(bContext *C)
bool ED_object_get_active_image(Object *ob, int mat_nr, Image **r_ima, ImageUser **r_iuser, const bNode **r_node, const bNodeTree **r_ntree)
const char * IMB_colormanagement_get_rect_colorspace(const ImBuf *ibuf)
void IMB_colormanagement_transform_float(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
@ COLOR_ROLE_SCENE_LINEAR
const char * IMB_colormanagement_role_colorspace_name_get(int role)
const char * IMB_colormanagement_get_float_colorspace(const ImBuf *ibuf)
void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, int channels_from, int width, int height, int stride_to, int stride_from, char *mask)
void IMB_buffer_byte_from_float(unsigned char *rect_to, const float *rect_from, int channels_from, float dither, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from, int start_y=0)
Definition conversion.cc:71
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
void IMB_buffer_byte_from_float_mask(unsigned char *rect_to, const float *rect_from, int channels_from, float dither, bool predivide, int width, int height, int stride_to, int stride_from, char *mask)
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
@ IB_RECT_INVALID
@ IB_DISPLAY_BUFFER_INVALID
#define IB_PROFILE_SRGB
#define IB_PROFILE_LINEAR_RGB
@ IB_float_data
@ IB_byte_data
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
@ WM_JOB_TYPE_OBJECT_BAKE
Definition WM_api.hh:1785
@ WM_JOB_EXCL_RENDER
Definition WM_api.hh:1765
@ WM_JOB_PROGRESS
Definition WM_api.hh:1766
@ WM_JOB_PRIORITY
Definition WM_api.hh:1760
#define NC_GEOM
Definition WM_types.hh:393
#define ND_RENDER_RESULT
Definition WM_types.hh:446
#define ND_DATA
Definition WM_types.hh:509
#define NC_SCENE
Definition WM_types.hh:378
#define NC_IMAGE
Definition WM_types.hh:384
volatile int lock
void RE_bake_pixels_populate(Mesh *mesh, BakePixel pixel_array[], const size_t pixels_num, const BakeTargets *targets, const blender::StringRef uv_layer)
Definition bake.cc:711
void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[], const size_t pixels_num, const int depth, float result[], Mesh *mesh, const eBakeNormalSwizzle normal_swizzle[3], const float mat[4][4])
Definition bake.cc:847
void RE_bake_margin(ImBuf *ibuf, char *mask, const int margin, const char margin_type, const Mesh *mesh, const blender::StringRef uv_layer, const float uv_offset[2])
Definition bake.cc:141
int RE_pass_depth(const eScenePassType pass_type)
Definition bake.cc:1053
void RE_bake_ibuf_clear(Image *image, const bool is_tangent)
Definition bake.cc:1028
void RE_bake_normal_world_to_world(const BakePixel pixel_array[], const size_t pixels_num, const int depth, float result[], const eBakeNormalSwizzle normal_swizzle[3])
Definition bake.cc:1004
void RE_bake_normal_world_to_object(const BakePixel pixel_array[], const size_t pixels_num, const int depth, float result[], Object *ob, const eBakeNormalSwizzle normal_swizzle[3])
Definition bake.cc:972
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t pixels_num, char *mask)
Definition bake.cc:126
bool RE_bake_pixels_populate_from_objects(Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], BakeHighPolyData highpoly[], const int highpoly_num, const size_t pixels_num, const bool is_custom_cage, const float cage_extrusion, const float max_ray_distance, const float mat_low[4][4], const float mat_cage[4][4], Mesh *me_cage)
Definition bake.cc:545
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_FACE
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static AttributeOwner from_id(ID *id)
Definition attribute.cc:44
int64_t size() const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr bool is_empty() const
Definition BLI_span.hh:260
bool is_empty() const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
#define offsetof(t, d)
bool RE_bake_engine(Render *re, Depsgraph *depsgraph, Object *object, const int object_id, const BakePixel pixel_array[], const BakeTargets *targets, const eScenePassType pass_type, const int pass_filter, float result[])
bool RE_bake_has_engine(const Render *re)
void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
const ccl_global KernelWorkTile * tile
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define unit_float_to_uchar_clamp_v4(v1, v2)
#define G(x, y, z)
void corner_tris_calc(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, MutableSpan< int3 > corner_tris)
bool node_is_connected_to_output(const bNodeTree &ntree, const bNode &node)
static void convert_float_color_to_byte_color(const MPropCol *float_colors, const int num, const bool is_noncolor, MLoopCol *byte_colors)
static bool bake_objects_check(Main *bmain, const Scene *scene, ViewLayer *view_layer, Object *ob, Span< PointerRNA > selected_objects, ReportList *reports, const bool is_selected_to_active, const eBakeTarget target)
static Mesh * bake_mesh_new_from_object(Depsgraph *depsgraph, Object *object, const bool preserve_origindex)
static bool bake_targets_init(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, Object *ob_eval, ReportList *reports)
static void bake_startjob(void *bkv, wmJobWorkerStatus *worker_status)
static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, Object *ob, Mesh *mesh_eval, BakePixel *pixel_array)
static void bake_targets_refresh(BakeTargets *targets)
static bool write_external_bake_pixels(const char *filepath, BakePixel pixel_array[], float *buffer, const int width, const int height, const int margin, const int margin_type, ImageFormatData const *im_format, const bool is_noncolor, const bool is_tangent_normal, Mesh const *mesh_eval, const StringRef uv_layer, const float uv_offset[2])
static void bake_job_complete(void *bkv)
static int find_original_loop(const OffsetIndices< int > orig_faces, const Span< int > orig_corner_verts, const int *vert_origindex, const int *poly_origindex, const int poly_eval, const int vert_eval)
void OBJECT_OT_bake(wmOperatorType *ot)
static bool bake_object_check(const Scene *scene, ViewLayer *view_layer, Object *ob, const eBakeTarget target, ReportList *reports)
static bool bake_break(void *)
static void bake_job_canceled(void *bkv)
static wmOperatorStatus bake_modal(bContext *C, wmOperator *, const wmEvent *event)
static bool bake_targets_output_internal(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, BakePixel *pixel_array, ReportList *reports, Mesh *mesh_eval)
static void bake_update_image(ScrArea *area, Image *image)
static wmOperatorStatus bake_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void bake_targets_populate_pixels(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, Mesh *mesh_eval, BakePixel *pixel_array)
static bool write_internal_bake_pixels(Image *image, const int image_tile_number, BakePixel pixel_array[], float *buffer, const int width, const int height, const int margin, const char margin_type, const bool is_clear, const bool is_noncolor, const bool is_tangent_normal, Mesh const *mesh_eval, const StringRef uv_layer, const float uv_offset[2])
static wmOperatorStatus bake(const BakeAPIRender *bkr, Object *ob_low, const Span< PointerRNA > selected_objects, ReportList *reports)
static void bake_freejob(void *bkv)
static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
static void bias_tangent_normal_pixels(float *rect, int channels, int width, int height, int stride)
static bool bake_pass_filter_check(eScenePassType pass_type, const int pass_filter, ReportList *reports)
static bool bake_targets_init_image_textures(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, ReportList *reports)
static bool bake_targets_output(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, Object *ob_eval, Mesh *mesh_eval, BakePixel *pixel_array, ReportList *reports)
static void bake_targets_free(BakeTargets *targets)
static bool bake_targets_init_vertex_colors(Main *bmain, BakeTargets *targets, Object *ob, ReportList *reports)
static bool bake_targets_init_internal(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, ReportList *reports)
static bool bake_targets_init_external(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, ReportList *reports)
static void bake_progress_update(void *bjv, float progress)
static void bake_set_props(wmOperator *op, Scene *scene)
static void bake_targets_clear(Main *bmain, const bool is_tangent)
static bool bake_targets_output_external(const BakeAPIRender *bkr, BakeTargets *targets, Object *ob, Object *ob_eval, Mesh *mesh_eval, BakePixel *pixel_array, ReportList *reports)
bool editmode_load(Main *bmain, Object *obedit)
static bool is_noncolor_pass(eScenePassType pass_type)
static void bake_result_add_to_rgba(float rgba[4], const float *result, const int channels_num)
static wmOperatorStatus bake_exec(bContext *C, wmOperator *op)
VecBase< int32_t, 3 > int3
const char * name
#define fabsf
bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
int RNA_int_get(PointerRNA *ptr, const char *name)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_string_file_path(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_bake_pass_type_items[]
Definition rna_render.cc:27
const EnumPropertyItem rna_enum_normal_swizzle_items[]
Definition rna_scene.cc:430
const EnumPropertyItem rna_enum_bake_pass_filter_type_items[]
Definition rna_scene.cc:561
const EnumPropertyItem rna_enum_bake_save_mode_items[]
Definition rna_scene.cc:464
const EnumPropertyItem rna_enum_bake_margin_type_items[]
Definition rna_scene.cc:440
const EnumPropertyItem rna_enum_bake_target_items[]
Definition rna_scene.cc:450
const EnumPropertyItem rna_enum_normal_space_items[]
Definition rna_scene.cc:424
void RE_progress_cb(Render *re, void *handle, void(*f)(void *handle, float))
void RE_test_break_cb(Render *re, void *handle, bool(*f)(void *handle))
Render * RE_NewSceneRender(const Scene *scene)
void RE_SetReports(Render *re, ReportList *reports)
#define FLT_MAX
Definition stdcycles.h:14
struct Mesh * mesh
Definition RE_bake.h:63
struct Object * ob
Definition RE_bake.h:61
struct Object * ob_eval
Definition RE_bake.h:62
bool is_flip_object
Definition RE_bake.h:64
int height
Definition RE_bake.h:27
int tile_number
Definition RE_bake.h:24
size_t offset
Definition RE_bake.h:28
struct Image * image
Definition RE_bake.h:23
float uv_offset[2]
Definition RE_bake.h:25
int width
Definition RE_bake.h:26
float dv_dx
Definition RE_bake.h:57
float du_dx
Definition RE_bake.h:56
int seed
Definition RE_bake.h:54
float du_dy
Definition RE_bake.h:56
float uv[2]
Definition RE_bake.h:55
float dv_dy
Definition RE_bake.h:57
int object_id
Definition RE_bake.h:53
int primitive_id
Definition RE_bake.h:53
struct Image ** material_to_image
Definition RE_bake.h:40
float * result
Definition RE_bake.h:44
bool is_noncolor
Definition RE_bake.h:49
int pixels_num
Definition RE_bake.h:45
int materials_num
Definition RE_bake.h:41
int channels_num
Definition RE_bake.h:46
int images_num
Definition RE_bake.h:37
BakeImage * images
Definition RE_bake.h:36
short flag
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
char name[258]
Definition DNA_ID.h:432
struct ID * orig_id
Definition DNA_ID.h:501
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
ListBase tiles
void * first
unsigned char r
ListBase images
Definition BKE_main.hh:286
ListBase objects
Definition BKE_main.hh:280
int corners_num
struct Material ** mat
CustomData corner_data
CustomData face_data
CustomData vert_data
int faces_num
struct ModifierData * next
short base_flag
ListBase modifiers
struct Material ** mat
short visibility_flag
struct BakeData bake
struct RenderData r
ListBase spacedata
struct Image * image
wmEventType type
Definition WM_types.hh:757
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_cursor_wait(bool val)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_ESCKEY
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:376
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:211
void WM_jobs_callbacks_ex(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *), void(*completed)(void *), void(*canceled)(void *))
Definition wm_jobs.cc:397
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:247
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:360