Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-12-23 18:39:36 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-12-24 14:00:58 +0300
commit0b4fae7a51fb869c27d9407b8b5eadeb418d0bfc (patch)
treedfcaaa1048f91bbe766a8314325ea97c8493b534
parent58c697a9ecebdebfec2c50de49946908bd444070 (diff)
Cleanup: refactoring of bake code in preparation of vertex color baking
Split of internal/external image bake target code off into smaller functions and refactor associated data structures for clarity. Designed so that a vertex color bake target is easy to fit in. Also avoid passing in a huge number of arguments into the main baking function, pass a struct instead.
-rw-r--r--source/blender/editors/object/object_bake_api.c803
-rw-r--r--source/blender/render/RE_bake.h27
-rw-r--r--source/blender/render/intern/bake.c14
-rw-r--r--source/blender/render/intern/engine.c11
4 files changed, 421 insertions, 434 deletions
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 19097d95743..2dba883d866 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -25,6 +25,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "RNA_access.h"
@@ -74,22 +75,19 @@
static void bake_set_props(wmOperator *op, Scene *scene);
typedef struct BakeAPIRender {
- Object *ob;
+ /* Data to work on. */
Main *main;
Scene *scene;
ViewLayer *view_layer;
- ReportList *reports;
+ Object *ob;
ListBase selected_objects;
+ /* Baking settings. */
eScenePassType pass_type;
int pass_filter;
int margin;
- int save_mode;
-
bool is_clear;
- bool is_split_materials;
- bool is_automatic_name;
bool is_selected_to_active;
bool is_cage;
@@ -100,21 +98,26 @@ typedef struct BakeAPIRender {
char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
char custom_cage[MAX_NAME];
- char filepath[FILE_MAX];
+ /* Settings for external image saving. */
+ eBakeSaveMode save_mode;
+ char filepath[FILE_MAX];
+ bool is_automatic_name;
+ bool is_split_materials;
int width;
int height;
const char *identifier;
- int result;
- bool ready;
-
- /* callbacks */
+ /* Baking render session. */
Render *render;
+
+ /* Progress Callbacks. */
float *progress;
short *do_update;
- /* for redrawing */
+ /* Operator state. */
+ ReportList *reports;
+ int result;
ScrArea *area;
} BakeAPIRender;
@@ -299,15 +302,18 @@ static bool write_internal_bake_pixels(Image *image,
}
/* force OpenGL reload */
-static void refresh_images(BakeImages *bake_images)
+static void bake_targets_refresh(BakeTargets *targets)
{
- for (int i = 0; i < bake_images->size; i++) {
- Image *ima = bake_images->data[i].image;
- LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
- if (tile->ok == IMA_OK_LOADED) {
- BKE_image_free_gputextures(ima);
- DEG_id_tag_update(&ima->id, 0);
- break;
+ for (int i = 0; i < targets->num_images; i++) {
+ Image *ima = targets->images[i].image;
+
+ if (ima) {
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ if (tile->ok == IMA_OK_LOADED) {
+ BKE_image_free_gputextures(ima);
+ DEG_id_tag_update(&ima->id, 0);
+ break;
+ }
}
}
}
@@ -498,6 +504,7 @@ static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *rep
image->id.tag |= LIB_TAG_DOIT;
}
+
return true;
}
@@ -622,7 +629,7 @@ static bool bake_objects_check(Main *bmain,
}
/* it needs to be called after bake_objects_check since the image tagging happens there */
-static void bake_images_clear(Main *bmain, const bool is_tangent)
+static void bake_targets_clear(Main *bmain, const bool is_tangent)
{
Image *image;
for (image = bmain->images.first; image; image = image->id.next) {
@@ -632,110 +639,337 @@ static void bake_images_clear(Main *bmain, const bool is_tangent)
}
}
-static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
+/* create new mesh with edit mode changes and modifiers applied */
+static Mesh *bake_mesh_new_from_object(Object *object)
{
- const int tot_mat = ob->totcol;
- int tot_images = 0;
+ Mesh *me = BKE_mesh_new_from_object(NULL, object, false);
- /* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
+ if (me->flag & ME_AUTOSMOOTH) {
+ BKE_mesh_split_faces(me, true);
+ }
+
+ return me;
+}
+
+/* Image Bake Targets */
+
+static bool bake_targets_init_image_textures(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ ReportList *reports)
+{
+ int num_materials = ob->totcol;
+
+ if (num_materials == 0) {
+ if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
+ BKE_report(
+ reports, RPT_ERROR, "No active image found, add a material or bake to an external file");
+ return false;
+ }
+ else if (bkr->is_split_materials) {
+ BKE_report(
+ reports,
+ RPT_ERROR,
+ "No active image found, add a material or bake without the Split Materials option");
+ return false;
+ }
+ }
+
+ /* Overallocate in case there is more materials than images. */
+ targets->num_materials = num_materials;
+ targets->images = MEM_callocN(sizeof(BakeImage) * targets->num_materials, "BakeTargets.images");
+ targets->material_to_image = MEM_callocN(sizeof(int) * targets->num_materials,
+ "BakeTargets.material_to_image");
- for (int i = 0; i < tot_mat; i++) {
+ /* Error handling and tag (in case multiple materials share the same image). */
+ BKE_main_id_tag_idcode(bkr->main, ID_IM, LIB_TAG_DOIT, false);
+
+ for (int i = 0; i < num_materials; i++) {
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
/* Some materials have no image, we just ignore those cases. */
if (image == NULL) {
- bake_images->lookup[i] = -1;
+ targets->material_to_image[i] = -1;
}
else if (image->id.tag & LIB_TAG_DOIT) {
for (int j = 0; j < i; j++) {
- if (bake_images->data[j].image == image) {
- bake_images->lookup[i] = j;
+ if (targets->images[j].image == image) {
+ targets->material_to_image[i] = j;
break;
}
}
}
else {
- bake_images->lookup[i] = tot_images;
- bake_images->data[tot_images].image = image;
+ targets->material_to_image[i] = targets->num_images;
+ targets->images[targets->num_images].image = image;
image->id.tag |= LIB_TAG_DOIT;
- tot_images++;
+ targets->num_images++;
}
}
- bake_images->size = tot_images;
+ return true;
}
-/*
- * returns the total number of pixels
- */
-static size_t init_internal_images(BakeImages *bake_images, ReportList *reports)
+static bool bake_targets_init_internal(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ ReportList *reports)
{
- size_t tot_size = 0;
+ if (!bake_targets_init_image_textures(bkr, targets, ob, reports)) {
+ return false;
+ }
- for (int i = 0; i < bake_images->size; i++) {
- BakeImage *bk_image = &bake_images->data[i];
+ /* Saving to image datablocks. */
+ for (int i = 0; i < targets->num_images; i++) {
+ BakeImage *bk_image = &targets->images[i];
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
if (ibuf) {
bk_image->width = ibuf->x;
bk_image->height = ibuf->y;
- bk_image->offset = tot_size;
+ bk_image->offset = targets->num_pixels;
- tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
+ targets->num_pixels += (size_t)ibuf->x * (size_t)ibuf->y;
}
else {
BKE_image_release_ibuf(bk_image->image, ibuf, lock);
BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
- return 0;
+ return false;
}
BKE_image_release_ibuf(bk_image->image, ibuf, lock);
}
- return tot_size;
+
+ return true;
}
-/* create new mesh with edit mode changes and modifiers applied */
-static Mesh *bake_mesh_new_from_object(Object *object)
+static bool bake_targets_output_internal(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ BakePixel *pixel_array,
+ ReportList *reports)
{
- Mesh *me = BKE_mesh_new_from_object(NULL, object, false);
+ bool all_ok = true;
+
+ for (int i = 0; i < targets->num_images; i++) {
+ BakeImage *bk_image = &targets->images[i];
+ const bool ok = write_internal_bake_pixels(bk_image->image,
+ pixel_array + bk_image->offset,
+ targets->result +
+ bk_image->offset * targets->num_channels,
+ bk_image->width,
+ bk_image->height,
+ bkr->margin,
+ bkr->is_clear,
+ targets->is_noncolor);
+
+ /* might be read by UI to set active image for display */
+ bake_update_image(bkr->area, bk_image->image);
+
+ if (!ok) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Problem saving the bake map internally for object \"%s\"",
+ ob->id.name + 2);
+ all_ok = false;
+ }
+ else {
+ BKE_report(
+ reports, RPT_INFO, "Baking map saved to internal image, save it externally or pack it");
+ }
+ }
- if (me->flag & ME_AUTOSMOOTH) {
- BKE_mesh_split_faces(me, true);
+ return all_ok;
+}
+
+static bool bake_targets_init_external(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ ReportList *reports)
+{
+ if (!bake_targets_init_image_textures(bkr, targets, ob, reports)) {
+ return false;
}
- return me;
+ /* Saving to disk. */
+ for (int i = 0; i < targets->num_images; i++) {
+ BakeImage *bk_image = &targets->images[i];
+
+ bk_image->width = bkr->width;
+ bk_image->height = bkr->height;
+ bk_image->offset = targets->num_pixels;
+ bk_image->image = NULL;
+
+ targets->num_pixels += (size_t)bkr->width * (size_t)bkr->height;
+
+ if (!bkr->is_split_materials) {
+ break;
+ }
+ }
+
+ if (!bkr->is_split_materials) {
+ /* saving a single image */
+ for (int i = 0; i < targets->num_materials; i++) {
+ targets->material_to_image[i] = 0;
+ }
+ }
+
+ return true;
+}
+
+static bool bake_targets_output_external(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ Object *ob_eval,
+ Mesh *me,
+ BakePixel *pixel_array,
+ ReportList *reports)
+{
+ bool all_ok = true;
+
+ for (int i = 0; i < targets->num_images; i++) {
+ BakeImage *bk_image = &targets->images[i];
+
+ BakeData *bake = &bkr->scene->r.bake;
+ char name[FILE_MAX];
+
+ BKE_image_path_from_imtype(name,
+ bkr->filepath,
+ BKE_main_blendfile_path(bkr->main),
+ 0,
+ bake->im_format.imtype,
+ true,
+ false,
+ NULL);
+
+ if (bkr->is_automatic_name) {
+ BLI_path_suffix(name, FILE_MAX, ob->id.name + 2, "_");
+ BLI_path_suffix(name, FILE_MAX, bkr->identifier, "_");
+ }
+
+ if (bkr->is_split_materials) {
+ if (bk_image->image) {
+ BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
+ }
+ else {
+ if (ob_eval->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, ob_eval->mat[i]->id.name + 2, "_");
+ }
+ else if (me->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, me->mat[i]->id.name + 2, "_");
+ }
+ else {
+ /* if everything else fails, use the material index */
+ char tmp[5];
+ sprintf(tmp, "%d", i % 1000);
+ BLI_path_suffix(name, FILE_MAX, tmp, "_");
+ }
+ }
+ }
+
+ /* save it externally */
+ const bool ok = write_external_bake_pixels(name,
+ pixel_array + bk_image->offset,
+ targets->result +
+ bk_image->offset * targets->num_channels,
+ bk_image->width,
+ bk_image->height,
+ bkr->margin,
+ &bake->im_format,
+ targets->is_noncolor);
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
+ all_ok = false;
+ }
+ else {
+ BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
+ }
+
+ if (!bkr->is_split_materials) {
+ break;
+ }
+ }
+
+ return all_ok;
+}
+
+/* Bake Targets */
+
+static bool bake_targets_init(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ ReportList *reports)
+{
+ if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
+ if (!bake_targets_init_internal(bkr, targets, ob, reports)) {
+ return false;
+ }
+ }
+ else if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
+ if (!bake_targets_init_external(bkr, targets, ob, reports)) {
+ return false;
+ }
+ }
+
+ if (targets->num_pixels == 0) {
+ return false;
+ }
+
+ targets->is_noncolor = is_noncolor_pass(bkr->pass_type);
+ targets->num_channels = RE_pass_depth(bkr->pass_type);
+ targets->result = MEM_callocN(sizeof(float) * targets->num_channels * targets->num_pixels,
+ "bake return pixels");
+
+ return true;
+}
+
+static void bake_targets_populate_pixels(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Mesh *me,
+ BakePixel *pixel_array)
+{
+ RE_bake_pixels_populate(me, pixel_array, targets->num_pixels, targets, bkr->uv_layer);
+}
+
+static bool bake_targets_output(const BakeAPIRender *bkr,
+ BakeTargets *targets,
+ Object *ob,
+ Object *ob_eval,
+ Mesh *me,
+ BakePixel *pixel_array,
+ ReportList *reports)
+{
+ if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
+ return bake_targets_output_internal(bkr, targets, ob, pixel_array, reports);
+ }
+ else if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
+ return bake_targets_output_external(bkr, targets, ob, ob_eval, me, pixel_array, reports);
+ }
+
+ return false;
}
-static int bake(Render *re,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
+static void bake_targets_free(BakeTargets *targets)
+{
+ MEM_SAFE_FREE(targets->images);
+ MEM_SAFE_FREE(targets->material_to_image);
+ MEM_SAFE_FREE(targets->result);
+}
+
+/* Main Bake Logic */
+
+static int bake(const BakeAPIRender *bkr,
Object *ob_low,
- ListBase *selected_objects,
- ReportList *reports,
- const eScenePassType pass_type,
- const int pass_filter,
- const int margin,
- const eBakeSaveMode 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 float cage_extrusion,
- const float max_ray_distance,
- const int normal_space,
- const eBakeNormalSwizzle normal_swizzle[],
- const char *custom_cage,
- const char *filepath,
- const int width,
- const int height,
- const char *identifier,
- ScrArea *area,
- const char *uv_layer)
+ const ListBase *selected_objects,
+ ReportList *reports)
{
+ Render *re = bkr->render;
+ Main *bmain = bkr->main;
+ Scene *scene = bkr->scene;
+ ViewLayer *view_layer = bkr->view_layer;
+
/* We build a depsgraph for the baking,
* so we don't need to change the original data to adjust visibility and modifiers. */
Depsgraph *depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
@@ -757,19 +991,10 @@ static int bake(Render *re,
MultiresModifierData *mmd_low = NULL;
int mmd_flags_low = 0;
- float *result = NULL;
-
BakePixel *pixel_array_low = NULL;
BakePixel *pixel_array_high = NULL;
- const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
- const bool is_noncolor = is_noncolor_pass(pass_type);
- const int depth = RE_pass_depth(pass_type);
-
- BakeImages bake_images = {NULL};
-
- size_t num_pixels;
- int tot_materials;
+ BakeTargets targets = {NULL};
RE_bake_engine_set_engine_parameters(re, bmain, scene);
@@ -778,77 +1003,23 @@ static int bake(Render *re,
goto cleanup;
}
- tot_materials = ob_low->totcol;
-
- if (uv_layer && uv_layer[0] != '\0') {
+ if (bkr->uv_layer[0] != '\0') {
Mesh *me = (Mesh *)ob_low->data;
- if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
+ if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, bkr->uv_layer) == -1) {
BKE_reportf(reports,
RPT_ERROR,
"No UV layer named \"%s\" found in the object \"%s\"",
- uv_layer,
+ bkr->uv_layer,
ob_low->id.name + 2);
goto cleanup;
}
}
- if (tot_materials == 0) {
- if (is_save_internal) {
- BKE_report(
- reports, RPT_ERROR, "No active image found, add a material or bake to an external file");
-
- goto cleanup;
- }
- else if (is_split_materials) {
- BKE_report(
- reports,
- RPT_ERROR,
- "No active image found, add a material or bake without the Split Materials option");
-
- goto cleanup;
- }
- else {
- /* baking externally without splitting materials */
- tot_materials = 1;
- }
- }
-
- /* we overallocate in case there is more materials than images */
- bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials,
- "bake images dimensions (width, height, offset)");
- bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials,
- "bake images lookup (from material to BakeImage)");
-
- build_image_lookup(bmain, ob_low, &bake_images);
-
- if (is_save_internal) {
- num_pixels = init_internal_images(&bake_images, reports);
-
- if (num_pixels == 0) {
- goto cleanup;
- }
- }
- else {
- /* when saving externally always use the size specified in the UI */
-
- num_pixels = (size_t)width * (size_t)height * bake_images.size;
-
- for (int i = 0; i < bake_images.size; i++) {
- bake_images.data[i].width = width;
- bake_images.data[i].height = height;
- bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
- bake_images.data[i].image = NULL;
- }
-
- if (!is_split_materials) {
- /* saving a single image */
- for (int i = 0; i < tot_materials; i++) {
- bake_images.lookup[i] = 0;
- }
- }
+ if (!bake_targets_init(bkr, &targets, ob_low, reports)) {
+ goto cleanup;
}
- if (is_selected_to_active) {
+ if (bkr->is_selected_to_active) {
CollectionPointerLink *link;
tot_highpoly = 0;
@@ -862,8 +1033,8 @@ static int bake(Render *re,
tot_highpoly++;
}
- if (is_cage && custom_cage[0] != '\0') {
- ob_cage = BLI_findstring(&bmain->objects, custom_cage, offsetof(ID, name) + 2);
+ if (bkr->is_cage && bkr->custom_cage[0] != '\0') {
+ ob_cage = BLI_findstring(&bmain->objects, bkr->custom_cage, offsetof(ID, name) + 2);
if (ob_cage == NULL || ob_cage->type != OB_MESH) {
BKE_report(reports, RPT_ERROR, "No valid cage object");
@@ -877,13 +1048,12 @@ static int bake(Render *re,
}
}
- pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
- pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
- result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
+ pixel_array_low = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels, "bake pixels low poly");
+ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels, "bake pixels high poly");
/* for multires bake, use linear UV subdivision to match low res UVs */
- if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT &&
- !is_selected_to_active) {
+ if (bkr->pass_type == SCE_PASS_NORMAL && bkr->normal_space == R_BAKE_SPACE_TANGENT &&
+ !bkr->is_selected_to_active) {
mmd_low = (MultiresModifierData *)BKE_modifiers_findby_type(ob_low, eModifierType_Multires);
if (mmd_low) {
mmd_flags_low = mmd_low->flags;
@@ -899,12 +1069,12 @@ static int bake(Render *re,
me_low = bake_mesh_new_from_object(ob_low_eval);
/* populate the pixel array with the face data */
- if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) {
- RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ if ((bkr->is_selected_to_active && (ob_cage == NULL) && bkr->is_cage) == false) {
+ bake_targets_populate_pixels(bkr, &targets, me_low, pixel_array_low);
}
/* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh) */
- if (is_selected_to_active) {
+ if (bkr->is_selected_to_active) {
CollectionPointerLink *link;
int i = 0;
@@ -919,7 +1089,7 @@ static int bake(Render *re,
goto cleanup;
}
}
- else if (is_cage) {
+ else if (bkr->is_cage) {
bool is_changed = false;
ModifierData *md = ob_low_eval->modifiers.first;
@@ -952,7 +1122,7 @@ static int bake(Render *re,
}
me_cage = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
- RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ bake_targets_populate_pixels(bkr, &targets, me_cage, pixel_array_low);
}
highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
@@ -996,10 +1166,10 @@ static int bake(Render *re,
pixel_array_high,
highpoly,
tot_highpoly,
- num_pixels,
+ targets.num_pixels,
ob_cage != NULL,
- cage_extrusion,
- max_ray_distance,
+ bkr->cage_extrusion,
+ bkr->max_ray_distance,
ob_low_eval->obmat,
(ob_cage ? ob_cage->obmat : ob_low_eval->obmat),
me_cage)) {
@@ -1014,11 +1184,10 @@ static int bake(Render *re,
highpoly[i].ob,
i,
pixel_array_high,
- &bake_images,
- depth,
- pass_type,
- pass_filter,
- result);
+ &targets,
+ bkr->pass_type,
+ bkr->pass_filter,
+ targets.result);
if (!ok) {
BKE_reportf(
reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
@@ -1036,11 +1205,10 @@ static int bake(Render *re,
ob_low_eval,
0,
pixel_array_low,
- &bake_images,
- depth,
- pass_type,
- pass_filter,
- result);
+ &targets,
+ bkr->pass_type,
+ bkr->pass_filter,
+ targets.result);
}
else {
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
@@ -1050,30 +1218,38 @@ static int bake(Render *re,
/* normal space conversion
* the normals are expected to be in world space, +X +Y +Z */
- if (ok && pass_type == SCE_PASS_NORMAL) {
- switch (normal_space) {
+ if (ok && bkr->pass_type == SCE_PASS_NORMAL) {
+ switch (bkr->normal_space) {
case R_BAKE_SPACE_WORLD: {
/* Cycles internal format */
- if ((normal_swizzle[0] == R_BAKE_POSX) && (normal_swizzle[1] == R_BAKE_POSY) &&
- (normal_swizzle[2] == R_BAKE_POSZ)) {
+ if ((bkr->normal_swizzle[0] == R_BAKE_POSX) && (bkr->normal_swizzle[1] == R_BAKE_POSY) &&
+ (bkr->normal_swizzle[2] == R_BAKE_POSZ)) {
break;
}
- RE_bake_normal_world_to_world(pixel_array_low, num_pixels, depth, result, normal_swizzle);
+ RE_bake_normal_world_to_world(pixel_array_low,
+ targets.num_pixels,
+ targets.num_channels,
+ targets.result,
+ bkr->normal_swizzle);
break;
}
case R_BAKE_SPACE_OBJECT: {
- RE_bake_normal_world_to_object(
- pixel_array_low, num_pixels, depth, result, ob_low_eval, normal_swizzle);
+ RE_bake_normal_world_to_object(pixel_array_low,
+ targets.num_pixels,
+ targets.num_channels,
+ targets.result,
+ ob_low_eval,
+ bkr->normal_swizzle);
break;
}
case R_BAKE_SPACE_TANGENT: {
- if (is_selected_to_active) {
+ if (bkr->is_selected_to_active) {
RE_bake_normal_world_to_tangent(pixel_array_low,
- num_pixels,
- depth,
- result,
+ targets.num_pixels,
+ targets.num_channels,
+ targets.result,
me_low,
- normal_swizzle,
+ bkr->normal_swizzle,
ob_low_eval->obmat);
}
else {
@@ -1092,14 +1268,14 @@ static int bake(Render *re,
/* Evaluate modifiers again. */
me_nores = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
- RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ bake_targets_populate_pixels(bkr, &targets, me_nores, pixel_array_low);
RE_bake_normal_world_to_tangent(pixel_array_low,
- num_pixels,
- depth,
- result,
+ targets.num_pixels,
+ targets.num_channels,
+ targets.result,
me_nores,
- normal_swizzle,
+ bkr->normal_swizzle,
ob_low_eval->obmat);
BKE_id_free(NULL, &me_nores->id);
@@ -1120,104 +1296,16 @@ static int bake(Render *re,
}
else {
/* save the results */
- for (int i = 0; i < bake_images.size; i++) {
- BakeImage *bk_image = &bake_images.data[i];
-
- if (is_save_internal) {
- ok = write_internal_bake_pixels(bk_image->image,
- pixel_array_low + bk_image->offset,
- result + bk_image->offset * depth,
- bk_image->width,
- bk_image->height,
- margin,
- is_clear,
- is_noncolor);
-
- /* might be read by UI to set active image for display */
- bake_update_image(area, bk_image->image);
-
- if (!ok) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Problem saving the bake map internally for object \"%s\"",
- ob_low->id.name + 2);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- BKE_report(reports,
- RPT_INFO,
- "Baking map saved to internal image, save it externally or pack it");
- op_result = OPERATOR_FINISHED;
- }
- }
- /* save externally */
- else {
- BakeData *bake = &scene->r.bake;
- char name[FILE_MAX];
-
- BKE_image_path_from_imtype(name,
- filepath,
- BKE_main_blendfile_path(bmain),
- 0,
- bake->im_format.imtype,
- true,
- false,
- NULL);
-
- if (is_automatic_name) {
- BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
- BLI_path_suffix(name, FILE_MAX, identifier, "_");
- }
-
- if (is_split_materials) {
- if (bk_image->image) {
- BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
- }
- else {
- if (ob_low_eval->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, ob_low_eval->mat[i]->id.name + 2, "_");
- }
- else if (me_low->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
- }
- else {
- /* if everything else fails, use the material index */
- char tmp[5];
- sprintf(tmp, "%d", i % 1000);
- BLI_path_suffix(name, FILE_MAX, tmp, "_");
- }
- }
- }
-
- /* save it externally */
- ok = write_external_bake_pixels(name,
- pixel_array_low + bk_image->offset,
- result + bk_image->offset * depth,
- bk_image->width,
- bk_image->height,
- margin,
- &bake->im_format,
- is_noncolor);
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
- op_result = OPERATOR_FINISHED;
- }
-
- if (!is_split_materials) {
- break;
- }
- }
+ if (bake_targets_output(
+ bkr, &targets, ob_low, ob_low_eval, me_low, pixel_array_low, reports)) {
+ op_result = OPERATOR_FINISHED;
+ }
+ else {
+ op_result = OPERATOR_CANCELLED;
}
}
- if (is_save_internal) {
- refresh_images(&bake_images);
- }
+ bake_targets_refresh(&targets);
cleanup:
@@ -1242,17 +1330,7 @@ cleanup:
MEM_freeN(pixel_array_high);
}
- if (bake_images.data) {
- MEM_freeN(bake_images.data);
- }
-
- if (bake_images.lookup) {
- MEM_freeN(bake_images.lookup);
- }
-
- if (result) {
- MEM_freeN(result);
- }
+ bake_targets_free(&targets);
if (me_low != NULL) {
BKE_id_free(NULL, &me_low->id);
@@ -1267,9 +1345,10 @@ cleanup:
return op_result;
}
+/* Bake Operator */
+
static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
{
- bool is_save_internal;
bScreen *screen = CTX_wm_screen(C);
bkr->ob = CTX_data_active_object(C);
@@ -1282,11 +1361,11 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
bkr->margin = RNA_int_get(op->ptr, "margin");
- bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
- is_save_internal = (bkr->save_mode == R_BAKE_SAVE_INTERNAL);
+ bkr->save_mode = (eBakeSaveMode)RNA_enum_get(op->ptr, "save_mode");
bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
- bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
+ bkr->is_split_materials = (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) &&
+ RNA_boolean_get(op->ptr, "use_split_materials");
bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
@@ -1306,7 +1385,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
- if ((!is_save_internal) && bkr->is_automatic_name) {
+ if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL && bkr->is_automatic_name) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
}
@@ -1321,7 +1400,9 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
/* XXX hack to force saving to always be internal. Whether (and how) to support
* external saving will be addressed later */
- bkr->save_mode = R_BAKE_SAVE_INTERNAL;
+ if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
+ bkr->save_mode = R_BAKE_SAVE_INTERNAL;
+ }
}
static int bake_exec(bContext *C, wmOperator *op)
@@ -1358,72 +1439,20 @@ static int bake_exec(bContext *C, wmOperator *op)
if (bkr.is_clear) {
const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) &&
(bkr.normal_space == R_BAKE_SPACE_TANGENT));
- bake_images_clear(bkr.main, is_tangent);
+ bake_targets_clear(bkr.main, is_tangent);
}
RE_SetReports(re, bkr.reports);
if (bkr.is_selected_to_active) {
- result = bake(bkr.render,
- bkr.main,
- bkr.scene,
- bkr.view_layer,
- bkr.ob,
- &bkr.selected_objects,
- bkr.reports,
- bkr.pass_type,
- bkr.pass_filter,
- bkr.margin,
- bkr.save_mode,
- bkr.is_clear,
- bkr.is_split_materials,
- bkr.is_automatic_name,
- true,
- bkr.is_cage,
- bkr.cage_extrusion,
- bkr.max_ray_distance,
- bkr.normal_space,
- bkr.normal_swizzle,
- bkr.custom_cage,
- bkr.filepath,
- bkr.width,
- bkr.height,
- bkr.identifier,
- bkr.area,
- bkr.uv_layer);
+ result = bake(&bkr, bkr.ob, &bkr.selected_objects, bkr.reports);
}
else {
CollectionPointerLink *link;
- const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
+ bkr.is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
for (link = bkr.selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
- result = bake(bkr.render,
- bkr.main,
- bkr.scene,
- bkr.view_layer,
- ob_iter,
- NULL,
- bkr.reports,
- bkr.pass_type,
- bkr.pass_filter,
- bkr.margin,
- bkr.save_mode,
- is_clear,
- bkr.is_split_materials,
- bkr.is_automatic_name,
- false,
- bkr.is_cage,
- bkr.cage_extrusion,
- bkr.max_ray_distance,
- bkr.normal_space,
- bkr.normal_swizzle,
- bkr.custom_cage,
- bkr.filepath,
- bkr.width,
- bkr.height,
- bkr.identifier,
- bkr.area,
- bkr.uv_layer);
+ result = bake(&bkr, ob_iter, NULL, bkr.reports);
}
}
@@ -1463,70 +1492,18 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
if (bkr->is_clear) {
const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) &&
(bkr->normal_space == R_BAKE_SPACE_TANGENT));
- bake_images_clear(bkr->main, is_tangent);
+ bake_targets_clear(bkr->main, is_tangent);
}
if (bkr->is_selected_to_active) {
- bkr->result = bake(bkr->render,
- bkr->main,
- bkr->scene,
- bkr->view_layer,
- bkr->ob,
- &bkr->selected_objects,
- bkr->reports,
- bkr->pass_type,
- bkr->pass_filter,
- bkr->margin,
- bkr->save_mode,
- bkr->is_clear,
- bkr->is_split_materials,
- bkr->is_automatic_name,
- true,
- bkr->is_cage,
- bkr->cage_extrusion,
- bkr->max_ray_distance,
- bkr->normal_space,
- bkr->normal_swizzle,
- bkr->custom_cage,
- bkr->filepath,
- bkr->width,
- bkr->height,
- bkr->identifier,
- bkr->area,
- bkr->uv_layer);
+ bkr->result = bake(bkr, bkr->ob, &bkr->selected_objects, bkr->reports);
}
else {
CollectionPointerLink *link;
- const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
+ bkr->is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
for (link = bkr->selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
- bkr->result = bake(bkr->render,
- bkr->main,
- bkr->scene,
- bkr->view_layer,
- ob_iter,
- NULL,
- bkr->reports,
- bkr->pass_type,
- bkr->pass_filter,
- bkr->margin,
- bkr->save_mode,
- is_clear,
- bkr->is_split_materials,
- bkr->is_automatic_name,
- false,
- bkr->is_cage,
- bkr->cage_extrusion,
- bkr->max_ray_distance,
- bkr->normal_space,
- bkr->normal_swizzle,
- bkr->custom_cage,
- bkr->filepath,
- bkr->width,
- bkr->height,
- bkr->identifier,
- bkr->area,
- bkr->uv_layer);
+ bkr->result = bake(bkr, ob_iter, NULL, bkr->reports);
if (bkr->result == OPERATOR_CANCELLED) {
return;
diff --git a/source/blender/render/RE_bake.h b/source/blender/render/RE_bake.h
index 3ed41ede006..3463362adb1 100644
--- a/source/blender/render/RE_bake.h
+++ b/source/blender/render/RE_bake.h
@@ -39,11 +39,23 @@ typedef struct BakeImage {
size_t offset;
} BakeImage;
-typedef struct BakeImages {
- BakeImage *data; /* all the images of an object */
- int *lookup; /* lookup table from Material to BakeImage */
- int size;
-} BakeImages;
+typedef struct BakeTargets {
+ /* All images of the object. */
+ BakeImage *images;
+ int num_images;
+
+ /* Lookup table from Material number to BakeImage. */
+ int *material_to_image;
+ int num_materials;
+
+ /* Pixel buffer to bake to. */
+ float *result;
+ int num_pixels;
+ int num_channels;
+
+ /* Baking to non-color data image. */
+ bool is_noncolor;
+} BakeTargets;
typedef struct BakePixel {
int primitive_id, object_id;
@@ -70,8 +82,7 @@ bool RE_bake_engine(struct Render *re,
struct Object *object,
const int object_id,
const BakePixel pixel_array[],
- const BakeImages *bake_images,
- const int depth,
+ const BakeTargets *targets,
const eScenePassType pass_type,
const int pass_filter,
float result[]);
@@ -95,7 +106,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
void RE_bake_pixels_populate(struct Mesh *me,
struct BakePixel *pixel_array,
const size_t num_pixels,
- const struct BakeImages *bake_images,
+ const struct BakeTargets *targets,
const char *uv_layer);
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask);
diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c
index 6f5db4986f2..caf81870fac 100644
--- a/source/blender/render/intern/bake.c
+++ b/source/blender/render/intern/bake.c
@@ -691,7 +691,7 @@ static void bake_differentials(BakeDataZSpan *bd,
void RE_bake_pixels_populate(Mesh *me,
BakePixel pixel_array[],
const size_t num_pixels,
- const BakeImages *bake_images,
+ const BakeTargets *targets,
const char *uv_layer)
{
const MLoopUV *mloopuv;
@@ -709,7 +709,7 @@ void RE_bake_pixels_populate(Mesh *me,
BakeDataZSpan bd;
bd.pixel_array = pixel_array;
- bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan");
+ bd.zspan = MEM_callocN(sizeof(ZSpan) * targets->num_images, "bake zspan");
/* initialize all pixel arrays so we know which ones are 'blank' */
for (int i = 0; i < num_pixels; i++) {
@@ -717,8 +717,8 @@ void RE_bake_pixels_populate(Mesh *me,
pixel_array[i].object_id = 0;
}
- for (int i = 0; i < bake_images->size; i++) {
- zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height);
+ for (int i = 0; i < targets->num_images; i++) {
+ zbuf_alloc_span(&bd.zspan[i], targets->images[i].width, targets->images[i].height);
}
const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
@@ -731,13 +731,13 @@ void RE_bake_pixels_populate(Mesh *me,
const MPoly *mp = &me->mpoly[lt->poly];
float vec[3][2];
int mat_nr = mp->mat_nr;
- int image_id = bake_images->lookup[mat_nr];
+ int image_id = targets->material_to_image[mat_nr];
if (image_id < 0) {
continue;
}
- bd.bk_image = &bake_images->data[image_id];
+ bd.bk_image = &targets->images[image_id];
bd.primitive_id = i;
for (int a = 0; a < 3; a++) {
@@ -755,7 +755,7 @@ void RE_bake_pixels_populate(Mesh *me,
zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
}
- for (int i = 0; i < bake_images->size; i++) {
+ for (int i = 0; i < targets->num_images; i++) {
zbuf_free_span(&bd.zspan[i]);
}
diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c
index 5685911c42e..13faddfcd2f 100644
--- a/source/blender/render/intern/engine.c
+++ b/source/blender/render/intern/engine.c
@@ -663,8 +663,7 @@ bool RE_bake_engine(Render *re,
Object *object,
const int object_id,
const BakePixel pixel_array[],
- const BakeImages *bake_images,
- const int depth,
+ const BakeTargets *targets,
const eScenePassType pass_type,
const int pass_filter,
float result[])
@@ -707,14 +706,14 @@ bool RE_bake_engine(Render *re,
type->update(engine, re->main, engine->depsgraph);
}
- for (int i = 0; i < bake_images->size; i++) {
- const BakeImage *image = bake_images->data + i;
+ for (int i = 0; i < targets->num_images; i++) {
+ const BakeImage *image = targets->images + i;
engine->bake.pixels = pixel_array + image->offset;
- engine->bake.result = result + image->offset * depth;
+ engine->bake.result = result + image->offset * targets->num_channels;
engine->bake.width = image->width;
engine->bake.height = image->height;
- engine->bake.depth = depth;
+ engine->bake.depth = targets->num_channels;
engine->bake.object_id = object_id;
type->bake(