Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_bake_api.c
| Show First 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | static bool write_internal_bake_pixels( | ||||
| Image *image, BakePixel pixel_array[], float *buffer, | Image *image, BakePixel pixel_array[], float *buffer, | ||||
| const int width, const int height, const int margin, | const int width, const int height, const int margin, | ||||
| const bool is_clear, const bool is_noncolor) | const bool is_clear, const bool is_noncolor) | ||||
| { | { | ||||
| ImBuf *ibuf; | ImBuf *ibuf; | ||||
| void *lock; | void *lock; | ||||
| bool is_float; | bool is_float; | ||||
| char *mask_buffer = NULL; | char *mask_buffer = NULL; | ||||
| const int num_pixels = width * height; | const size_t num_pixels = width * height; | ||||
campbellbarton: Dont think this is correct, since `width * height` are int's and will overflow before the… | |||||
| ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); | ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); | ||||
| if (!ibuf) | if (!ibuf) | ||||
| return false; | return false; | ||||
| if (margin > 0 || !is_clear) { | if (margin > 0 || !is_clear) { | ||||
| mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); | mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | IMB_buffer_byte_from_float( | ||||
| (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, | (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, | ||||
| IB_PROFILE_SRGB, IB_PROFILE_SRGB, | IB_PROFILE_SRGB, IB_PROFILE_SRGB, | ||||
| false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); | false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); | ||||
| } | } | ||||
| /* margins */ | /* margins */ | ||||
| if (margin > 0) { | if (margin > 0) { | ||||
| char *mask_buffer = NULL; | char *mask_buffer = NULL; | ||||
| const int num_pixels = width * height; | const size_t num_pixels = width * height; | ||||
| mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); | mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); | ||||
| RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); | RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); | ||||
| RE_bake_margin(ibuf, mask_buffer, margin); | RE_bake_margin(ibuf, mask_buffer, margin); | ||||
| if (mask_buffer) | if (mask_buffer) | ||||
| MEM_freeN(mask_buffer); | MEM_freeN(mask_buffer); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images) | ||||
| } | } | ||||
| bake_images->size = tot_images; | bake_images->size = tot_images; | ||||
| } | } | ||||
| /* | /* | ||||
| * returns the total number of pixels | * returns the total number of pixels | ||||
| */ | */ | ||||
| static int initialize_internal_images(BakeImages *bake_images, ReportList *reports) | static size_t initialize_internal_images(BakeImages *bake_images, ReportList *reports) | ||||
| { | { | ||||
| int i; | int i; | ||||
| int tot_size = 0; | size_t tot_size = 0; | ||||
| for (i = 0; i < bake_images->size; i++) { | for (i = 0; i < bake_images->size; i++) { | ||||
| ImBuf *ibuf; | ImBuf *ibuf; | ||||
| void *lock; | void *lock; | ||||
| BakeImage *bk_image = &bake_images->data[i]; | BakeImage *bk_image = &bake_images->data[i]; | ||||
| ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock); | ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock); | ||||
| Show All 9 Lines | else { | ||||
| BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2); | BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| BKE_image_release_ibuf(bk_image->image, ibuf, lock); | BKE_image_release_ibuf(bk_image->image, ibuf, lock); | ||||
| } | } | ||||
| return tot_size; | return tot_size; | ||||
| } | } | ||||
| /* returns the image dimensions for single-images baking sessions, or an optimal dimension (the closest we can get to the square root) */ | |||||
| static void calculate_buffer_dimension(int *width, int *height, const size_t num_pixels, BakeImages *bake_images) | |||||
| { | |||||
| if (bake_images->size == 1) { | |||||
| *width = bake_images->data[0].width; | |||||
| *height = bake_images->data[0].height; | |||||
| } | |||||
| else { | |||||
| int max_dividend = floor(sqrt(num_pixels)); | |||||
| BLI_assert(max_dividend > 0); | |||||
| while (true) { | |||||
| if ((num_pixels % max_dividend) == 0) { | |||||
| *width = max_dividend; | |||||
| *height = num_pixels / max_dividend; | |||||
| break; | |||||
| } | |||||
| max_dividend--; | |||||
| } | |||||
| } | |||||
| } | |||||
| static int bake( | static int bake( | ||||
| Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, | Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, | ||||
| const ScenePassType pass_type, const int margin, | const ScenePassType pass_type, const int margin, | ||||
| const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials, | const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials, | ||||
| const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage, | const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage, | ||||
| const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[], | const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[], | ||||
| const char *custom_cage, const char *filepath, const int width, const int height, | const char *custom_cage, const char *filepath, const int width, const int height, | ||||
| const char *identifier, ScrArea *sa, const char *uv_layer) | const char *identifier, ScrArea *sa, const char *uv_layer) | ||||
| Show All 17 Lines | static int bake( | ||||
| BakePixel *pixel_array_low = NULL; | BakePixel *pixel_array_low = NULL; | ||||
| const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL); | const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL); | ||||
| const bool is_noncolor = is_noncolor_pass(pass_type); | const bool is_noncolor = is_noncolor_pass(pass_type); | ||||
| const int depth = RE_pass_depth(pass_type); | const int depth = RE_pass_depth(pass_type); | ||||
| BakeImages bake_images = {NULL}; | BakeImages bake_images = {NULL}; | ||||
| int num_pixels; | size_t num_pixels; | ||||
| int tot_materials; | int tot_materials; | ||||
| int i; | int i; | ||||
| int buffer_width, buffer_height; | |||||
| RE_bake_engine_set_engine_parameters(re, bmain, scene); | RE_bake_engine_set_engine_parameters(re, bmain, scene); | ||||
| if (!RE_bake_has_engine(re)) { | if (!RE_bake_has_engine(re)) { | ||||
| BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); | BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); | ||||
| goto cleanup; | goto cleanup; | ||||
| } | } | ||||
| tot_materials = ob_low->totcol; | tot_materials = ob_low->totcol; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | else { | ||||
| if (!is_split_materials) { | if (!is_split_materials) { | ||||
| /* saving a single image */ | /* saving a single image */ | ||||
| for (i = 0; i < tot_materials; i++) | for (i = 0; i < tot_materials; i++) | ||||
| bake_images.lookup[i] = 0; | bake_images.lookup[i] = 0; | ||||
| } | } | ||||
| } | } | ||||
| calculate_buffer_dimension(&buffer_width, &buffer_height, num_pixels, &bake_images); | |||||
| if (is_selected_to_active) { | if (is_selected_to_active) { | ||||
| CollectionPointerLink *link; | CollectionPointerLink *link; | ||||
| tot_highpoly = 0; | tot_highpoly = 0; | ||||
| for (link = selected_objects->first; link; link = link->next) { | for (link = selected_objects->first; link; link = link->next) { | ||||
| Object *ob_iter = link->ptr.data; | Object *ob_iter = link->ptr.data; | ||||
| if (ob_iter == ob_low) | if (ob_iter == ob_low) | ||||
| ▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | if (!RE_bake_pixels_populate_from_objects( | ||||
| cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) | cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) | ||||
| { | { | ||||
| BKE_report(reports, RPT_ERROR, "Error handling selected objects"); | BKE_report(reports, RPT_ERROR, "Error handling selected objects"); | ||||
| goto cage_cleanup; | goto cage_cleanup; | ||||
| } | } | ||||
| /* the baking itself */ | /* the baking itself */ | ||||
| for (i = 0; i < tot_highpoly; i++) { | for (i = 0; i < tot_highpoly; i++) { | ||||
| ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels, | ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, buffer_width, buffer_height, | ||||
| depth, pass_type, result); | depth, pass_type, result); | ||||
| if (!ok) { | if (!ok) { | ||||
| BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2); | BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2); | ||||
| goto cage_cleanup; | goto cage_cleanup; | ||||
| } | } | ||||
| } | } | ||||
| cage_cleanup: | cage_cleanup: | ||||
| Show All 10 Lines | if (!ok) { | ||||
| goto cleanup; | goto cleanup; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* make sure low poly renders */ | /* make sure low poly renders */ | ||||
| ob_low->restrictflag &= ~OB_RESTRICT_RENDER; | ob_low->restrictflag &= ~OB_RESTRICT_RENDER; | ||||
| if (RE_bake_has_engine(re)) { | if (RE_bake_has_engine(re)) { | ||||
| ok = RE_bake_engine(re, ob_low, pixel_array_low, num_pixels, depth, pass_type, result); | ok = RE_bake_engine(re, ob_low, pixel_array_low, buffer_width, buffer_height, depth, pass_type, result); | ||||
| } | } | ||||
| else { | else { | ||||
| BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); | BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); | ||||
| goto cleanup; | goto cleanup; | ||||
| } | } | ||||
| } | } | ||||
| /* normal space conversion | /* normal space conversion | ||||
| ▲ Show 20 Lines • Show All 533 Lines • Show Last 20 Lines | |||||
Dont think this is correct, since width * height are int's and will overflow before the assignment.
Should be (size_t)width * (size_t)height