[Bf-blender-cvs] [0b4fae7a51f] master: Cleanup: refactoring of bake code in preparation of vertex color baking

Brecht Van Lommel noreply at git.blender.org
Thu Dec 24 12:41:48 CET 2020


Commit: 0b4fae7a51fb869c27d9407b8b5eadeb418d0bfc
Author: Brecht Van Lommel
Date:   Wed Dec 23 16:39:36 2020 +0100
Branches: master
https://developer.blender.org/rB0b4fae7a51fb869c27d9407b8b5eadeb418d0bfc

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.

===================================================================

M	source/blender/editors/object/object_bake_api.c
M	source/blender/render/RE_bake.h
M	source/blender/render/intern/bake.c
M	source/blender/render/intern/engine.c

===================================================================

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;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list