[Bf-blender-cvs] [400cb25fc77] master: UDIM: Support tile sets that do not start at 1001

Jesse Yurkovich noreply at git.blender.org
Wed Aug 18 06:55:40 CEST 2021


Commit: 400cb25fc77a4131033f69cf328a31cdcf81edb5
Author: Jesse Yurkovich
Date:   Tue Aug 17 21:42:28 2021 -0700
Branches: master
https://developer.blender.org/rB400cb25fc77a4131033f69cf328a31cdcf81edb5

UDIM: Support tile sets that do not start at 1001

Removes the artificial requirement that UDIM tile sets start at 1001.
Blender was already capable of handling sparse tile sets (non-contiguous
tiles) so the restriction around starting at 1001 was unnecessary in
general.

This required fixing a few UDIM-related python bugs around manually
updating the `tile_number` field on images as well. See the differential
for details. No script changes are necessary but they will now work,
correctly, in many more cases.

Differential Revision: https://developer.blender.org/D11859

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

M	intern/cycles/blender/blender_util.h
M	source/blender/blenkernel/BKE_image.h
M	source/blender/blenkernel/intern/image.c
M	source/blender/blenkernel/intern/image_gpu.c
M	source/blender/blenkernel/intern/image_save.c
M	source/blender/editors/space_image/image_ops.c
M	source/blender/editors/space_image/image_sequence.c
M	source/blender/makesrna/intern/rna_image.c

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

diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 82da3512269..d441575e8af 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -246,7 +246,11 @@ static inline string image_user_file_path(BL::ImageUser &iuser,
 
   string filepath_str = string(filepath);
   if (load_tiled && ima.source() == BL::Image::source_TILED) {
-    string_replace(filepath_str, "1001", "<UDIM>");
+    string udim;
+    if (ima.tiles.length() > 0) {
+      udim = to_string(ima.tiles[0].number());
+    }
+    string_replace(filepath_str, udim, "<UDIM>");
   }
   return filepath_str;
 }
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index ac73bd2b595..3cab1a6b755 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -308,6 +308,8 @@ void BKE_image_get_tile_label(struct Image *ima,
 
 struct ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *label);
 bool BKE_image_remove_tile(struct Image *ima, struct ImageTile *tile);
+void BKE_image_reassign_tile(struct Image *ima, struct ImageTile *tile, int new_tile_number);
+void BKE_image_sort_tiles(struct Image *ima);
 
 bool BKE_image_fill_tile(struct Image *ima,
                          struct ImageTile *tile,
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index ba54858ba84..d2ab54de697 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -670,24 +670,27 @@ bool BKE_image_has_opengl_texture(Image *ima)
   return false;
 }
 
+static int image_get_tile_number_from_iuser(Image *ima, const ImageUser *iuser)
+{
+  BLI_assert(ima != NULL && ima->tiles.first);
+  ImageTile *tile = ima->tiles.first;
+  return (iuser && iuser->tile) ? iuser->tile : tile->tile_number;
+}
+
 ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
 {
   if (ima == NULL) {
     return NULL;
   }
 
-  /* Verify valid tile range. */
-  if ((tile_number != 0) && (tile_number < 1001 || tile_number > IMA_UDIM_MAX)) {
-    return NULL;
-  }
-
-  /* Tile number 0 is a special case and refers to the first tile, typically
+  /* Tiles 0 and 1001 are a special case and refer to the first tile, typically
    * coming from non-UDIM-aware code. */
   if (ELEM(tile_number, 0, 1001)) {
     return ima->tiles.first;
   }
 
-  if (ima->source != IMA_SRC_TILED) {
+  /* Must have a tiled image and a valid tile number at this point. */
+  if (ima->source != IMA_SRC_TILED || tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
     return NULL;
   }
 
@@ -702,7 +705,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
 
 ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser)
 {
-  return BKE_image_get_tile(ima, (iuser && iuser->tile) ? iuser->tile : 1001);
+  return BKE_image_get_tile(ima, image_get_tile_number_from_iuser(ima, iuser));
 }
 
 int BKE_image_get_tile_from_pos(struct Image *ima,
@@ -3803,8 +3806,8 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
     return false;
   }
 
-  if (tile == ima->tiles.first) {
-    /* Can't remove first tile. */
+  if (BLI_listbase_is_single(&ima->tiles)) {
+    /* Can't remove the last remaining tile. */
     return false;
   }
 
@@ -3815,6 +3818,64 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
   return true;
 }
 
+void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number)
+{
+  if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+    return;
+  }
+
+  if (new_tile_number < 1001 || new_tile_number > IMA_UDIM_MAX) {
+    return;
+  }
+
+  const int old_tile_number = tile->tile_number;
+  tile->tile_number = new_tile_number;
+
+  if (BKE_image_is_multiview(ima)) {
+    const int totviews = BLI_listbase_count(&ima->views);
+    for (int i = 0; i < totviews; i++) {
+      ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number);
+      image_remove_ibuf(ima, i, old_tile_number);
+      image_assign_ibuf(ima, ibuf, i, new_tile_number);
+      IMB_freeImBuf(ibuf);
+    }
+  }
+  else {
+    ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number);
+    image_remove_ibuf(ima, 0, old_tile_number);
+    image_assign_ibuf(ima, ibuf, 0, new_tile_number);
+    IMB_freeImBuf(ibuf);
+  }
+
+  for (int eye = 0; eye < 2; eye++) {
+    /* Reallocate GPU tile array. */
+    if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != NULL) {
+      GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]);
+      ima->gputexture[TEXTARGET_2D_ARRAY][eye] = NULL;
+    }
+    if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != NULL) {
+      GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]);
+      ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = NULL;
+    }
+  }
+}
+
+static int tile_sort_cb(const void *a, const void *b)
+{
+  const ImageTile *tile_a = a;
+  const ImageTile *tile_b = b;
+  return (tile_a->tile_number > tile_b->tile_number) ? 1 : 0;
+}
+
+void BKE_image_sort_tiles(struct Image *ima)
+{
+  if (ima == NULL || ima->source != IMA_SRC_TILED) {
+    return;
+  }
+
+  BLI_listbase_sort(&ima->tiles, tile_sort_cb);
+}
+
 bool BKE_image_fill_tile(struct Image *ima,
                          ImageTile *tile,
                          int width,
@@ -4890,7 +4951,7 @@ static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry
     }
   }
   else if (ima->source == IMA_SRC_TILED) {
-    frame = (iuser && iuser->tile) ? iuser->tile : 1001;
+    frame = image_get_tile_number_from_iuser(ima, iuser);
   }
 
   *r_entry = frame;
@@ -4955,7 +5016,7 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry,
   }
   else if (ima->source == IMA_SRC_TILED) {
     if (ELEM(ima->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER)) {
-      entry = (iuser && iuser->tile) ? iuser->tile : 1001;
+      entry = image_get_tile_number_from_iuser(ima, iuser);
       ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
 
       if ((ima->type == IMA_TYPE_IMAGE) && ibuf != NULL) {
@@ -5507,7 +5568,7 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
       index = iuser ? iuser->framenr : ima->lastframe;
     }
     else {
-      index = (iuser && iuser->tile) ? iuser->tile : 1001;
+      index = image_get_tile_number_from_iuser(ima, iuser);
     }
 
     BLI_path_sequence_decode(filepath, head, tail, &numlen);
diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c
index bb7495437bb..d179dd40c33 100644
--- a/source/blender/blenkernel/intern/image_gpu.c
+++ b/source/blender/blenkernel/intern/image_gpu.c
@@ -108,8 +108,9 @@ static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multivi
   float array_w = GPU_texture_width(tilearray);
   float array_h = GPU_texture_height(tilearray);
 
+  /* Determine maximum tile number. */
+  BKE_image_sort_tiles(ima);
   ImageTile *last_tile = (ImageTile *)ima->tiles.last;
-  /* Tiles are sorted by number. */
   int max_tile = last_tile->tile_number - 1001;
 
   /* create image */
diff --git a/source/blender/blenkernel/intern/image_save.c b/source/blender/blenkernel/intern/image_save.c
index 360bad3e786..be86da05b57 100644
--- a/source/blender/blenkernel/intern/image_save.c
+++ b/source/blender/blenkernel/intern/image_save.c
@@ -404,11 +404,12 @@ bool BKE_image_save(
 
   if (ima->source == IMA_SRC_TILED) {
     /* Verify filepath for tiles images. */
-    if (BLI_path_sequence_decode(opts->filepath, NULL, NULL, NULL) != 1001) {
+    ImageTile *first_tile = ima->tiles.first;
+    if (BLI_path_sequence_decode(opts->filepath, NULL, NULL, NULL) != first_tile->tile_number) {
       BKE_reportf(reports,
                   RPT_ERROR,
-                  "When saving a tiled image, the path '%s' must contain the UDIM tag 1001",
-                  opts->filepath);
+                  "When saving a tiled image, the path '%s' must contain the UDIM tile number %d",
+                  opts->filepath, first_tile->tile_number);
       return false;
     }
 
@@ -430,9 +431,14 @@ bool BKE_image_save(
     BLI_path_sequence_decode(filepath, head, tail, &numlen);
 
     /* Save all other tiles. */
-    LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
-      /* Tile 1001 was already saved before the loop. */
-      if (tile->tile_number == 1001 || !ok) {
+    int index;
+    LISTBASE_FOREACH_INDEX (ImageTile *, tile, &ima->tiles, index) {
+      /* First tile was already saved before the loop. */
+      if (index == 0) {
+        continue;
+      }
+
+      if (!ok) {
         continue;
       }
 
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 999d2956fef..29c1452b988 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1289,8 +1289,10 @@ static Image *image_open_single(Main *bmain,
     }
 
     if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) {
-      if (range->udim_tiles.first && range->offset == 1001) {
+      if (range->udim_tiles.first) {
         ima->source = IMA_SRC_TILED;
+        ImageTile *first_tile = ima->tiles.first;
+        first_tile->tile_number = range->offset;
         LISTBASE_FOREACH (LinkData *, node, &range->udim_tiles) {
           BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL);
         }
@@ -1806,10 +1808,13 @@ static int image_save_options_init(Main *bmain,
       }
 
       /* append UDIM numbering if not present */
-      if (ima->source == IMA_SRC_TILED &&
-          (BLI_path_sequence_decode(ima->filepath, NULL, NULL, NULL) != 1001)) {
+      if (ima->source == IMA_SRC_TILED) {
+        char udim[6];
+        ImageTile *tile = ima->tiles.first;
+        BLI_snprintf(udim, sizeof(udim), ".%d", tile->tile_number);
+
         int len = strlen(opts->filepath);
-        STR_CONCAT(opts->filepath, len, ".1001");
+        STR_CONCAT(opts->filepath, len, udim);
       }
     }
 
@@ -3868,9 +3873,9 @@ static void tile_fill_init(PointerRNA *ptr, Image *ima, ImageTile *tile)
 
   /* Acquire ibuf to 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list