Commit: 44a1d847cc8953d7be40617b61a76f6f065981c5
Author: Dalai Felinto
Date:   Sat Apr 26 13:21:43 2014 -0300
https://developer.blender.org/rB44a1d847cc8953d7be40617b61a76f6f065981c5

Cycles-Bake: better support for multiple materials referring to the same image

This brings performance gain, as well as a bugfix where the margin would 
advance over one of the images

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

M       source/blender/editors/object/object_bake_api.c
M       source/blender/render/extern/include/RE_bake.h
M       source/blender/render/intern/source/bake_api.c

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

diff --git a/source/blender/editors/object/object_bake_api.c 
b/source/blender/editors/object/object_bake_api.c
index 077e8e8..7efb76a 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -263,17 +263,17 @@ static bool is_data_pass(ScenePassType pass_type)
                     SCE_PASS_INDEXMA);
 }
 
-static int get_save_internal_status(wmOperator *op, Object *ob, BakeImage 
*images)
+static bool build_image_lookup(wmOperator *op, Main *bmain, Object *ob, 
BakeImages *images)
 {
-       int i;
+       int i, j;
+       int tot_images = 0;
        int tot_mat = ob->totcol;
-       int tot_size = 0;
+
+       /* error handling and tag (in case multiple materials share the same 
image) */
+       BKE_main_id_tag_idcode(bmain, ID_IM, false);
 
        for (i = 0; i < tot_mat; i++) {
-               ImBuf *ibuf;
-               void *lock;
                Image *image;
-
                ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
 
                if (!image) {
@@ -289,31 +289,60 @@ static int get_save_internal_status(wmOperator *op, 
Object *ob, BakeImage *image
                                BKE_reportf(op->reports, RPT_ERROR,
                                            "No active image found in material 
%d", i);
                        }
+                       return false;
+               }
 
-                       return -1;
+               if ((image->id.flag & LIB_DOIT)) {
+                       for (j = 0; j < i; j++) {
+                               if (images->data[j].image == image) {
+                                       images->lookup[i] = j;
+                                       break;
+                               }
+                       }
+               }
+               else {
+                       images->lookup[i] = tot_images;
+                       images->data[tot_images].image = image;
+                       image->id.flag |= LIB_DOIT;
+                       tot_images++;
                }
+       }
+
+       images->size = tot_images;
+       return true;
+}
 
-               ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+/*
+ * returns the total number of pixels
+ */
+static int initialize_internal_images(wmOperator *op, BakeImages *images)
+{
+       int i;
+       int tot_size = 0;
+
+       for (i = 0; i < images->size; i++) {
+               ImBuf *ibuf;
+               void *lock;
+
+               BakeImage *image = &images->data[i];
+               ibuf = BKE_image_acquire_ibuf(image->image, NULL, &lock);
 
                if (ibuf) {
                        int num_pixels = ibuf->x * ibuf->y;
 
-                       images[i].width = ibuf->x;
-                       images[i].height = ibuf->y;
-                       images[i].offset = tot_size;
-                       images[i].image = image;
+                       image->width = ibuf->x;
+                       image->height = ibuf->y;
+                       image->offset = tot_size;
 
                        tot_size += num_pixels;
                }
                else {
-                       BKE_image_release_ibuf(image, ibuf, lock);
-                       BKE_reportf(op->reports, RPT_ERROR, "Not inialized 
image in material '%d' (%s)", i, ob->mat[i]->id.name + 2);
-                       return -1;
+                       BKE_image_release_ibuf(image->image, ibuf, lock);
+                       BKE_reportf(op->reports, RPT_ERROR, "Not initialized 
image %s", image->image->id.name + 2);
+                       return 0;
                }
-
-               BKE_image_release_ibuf(image, ibuf, lock);
+               BKE_image_release_ibuf(image->image, ibuf, lock);
        }
-
        return tot_size;
 }
 
@@ -356,7 +385,7 @@ static int bake_exec(bContext *C, wmOperator *op)
        bool is_highpoly = false;
        bool is_tangent;
 
-       BakeImage *images;
+       BakeImages images;
 
        int normal_space = RNA_enum_get(op->ptr, "normal_space");
        BakeNormalSwizzle normal_swizzle[] = {
@@ -369,16 +398,16 @@ static int bake_exec(bContext *C, wmOperator *op)
        char filepath[FILE_MAX];
 
        int num_pixels;
-       int tot_images;
+       int tot_materials;
        int i;
 
        RNA_string_get(op->ptr, "cage", custom_cage);
        RNA_string_get(op->ptr, "filepath", filepath);
 
        is_tangent = pass_type == SCE_PASS_NORMAL && normal_space == 
R_BAKE_SPACE_TANGENT;
-       tot_images = ob_low->totcol;
+       tot_materials = ob_low->totcol;
 
-       if (tot_images == 0) {
+       if (tot_materials == 0) {
                if (is_save_internal) {
                        BKE_report(op->reports, RPT_ERROR,
                                           "No active image found. Add a 
material or bake to an external file");
@@ -391,34 +420,42 @@ static int bake_exec(bContext *C, wmOperator *op)
                }
                else {
                        /* baking externally without splitting materials */
-                       tot_images = 1;
+                       int tot_images = 1;
                }
        }
 
-       images = MEM_callocN(sizeof(BakeImage) * tot_images, "bake images 
dimensions (width, height, offset)");
+       /* we overallocate in case there is more materials than images */
+       images.data = MEM_callocN(sizeof(BakeImage) * tot_materials, "bake 
images dimensions (width, height, offset)");
+       images.lookup = MEM_callocN(sizeof(int) * tot_materials, "bake images 
lookup (from material to BakeImage)");
+
+       if(!build_image_lookup(op, bmain, ob_low, &images))
+               goto cleanup;
 
        if (is_save_internal) {
-               num_pixels = get_save_internal_status(op, ob_low, images);
+               num_pixels = initialize_internal_images(op, &images);
 
-               if (num_pixels <= 0) {
+               if (num_pixels == 0) {
                        goto cleanup;
                }
-               else if (is_clear) {
-                       RE_bake_ibuf_clear(images, tot_images, is_tangent);
+
+               if (is_clear) {
+                       RE_bake_ibuf_clear(&images, is_tangent);
                }
        }
        else {
+#if 0
                num_pixels = 0;
                for (i = 0; i < tot_images; i++) {
-                       images[i].width = RNA_int_get(op->ptr, "width");
-                       images[i].height = RNA_int_get(op->ptr, "height");
-                       images[i].offset = (is_split_materials ? num_pixels : 
0);
-                       images[i].image = NULL;
+                       images.data[i].width = RNA_int_get(op->ptr, "width");
+                       images.data[i].height = RNA_int_get(op->ptr, "height");
+                       images.data[i].offset = (is_split_materials ? 
num_pixels : 0);
+                       images.data[i].image = NULL;
 
-                       num_pixels += images[i].width * images[i].height;
+                       num_pixels += images.data[i].width * 
images.data[i].height;
                }
 
-               BLI_assert(num_pixels == tot_images * images[0].width * 
images[0].height);
+               BLI_assert(num_pixels == tot_images * images.data[0].width * 
images.data[0].height);
+#endif
        }
 
        if (use_selected_to_active) {
@@ -543,7 +580,7 @@ static int bake_exec(bContext *C, wmOperator *op)
                BLI_assert(i == tot_highpoly);
 
                /* populate the pixel array with the face data */
-               RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, 
images);
+               RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, 
&images);
 
                ob_low->restrictflag |= OB_RESTRICT_RENDER;
 
@@ -578,7 +615,7 @@ static int bake_exec(bContext *C, wmOperator *op)
                me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 
1, 0);
 
                /* populate the pixel array with the face data */
-               RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, 
images);
+               RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, 
&images);
 
                /* make sure low poly renders */
                ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
@@ -628,7 +665,7 @@ static int bake_exec(bContext *C, wmOperator *op)
                                        }
 
                                        me_nores = 
BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
-                                       RE_populate_bake_pixels(me_nores, 
pixel_array_low, num_pixels, images);
+                                       RE_populate_bake_pixels(me_nores, 
pixel_array_low, num_pixels, &images);
 
                                        
RE_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, 
me_nores, normal_swizzle);
                                        BKE_libblock_free(bmain, me_nores);
@@ -649,8 +686,8 @@ static int bake_exec(bContext *C, wmOperator *op)
        }
        else {
                /* save the results */
-               for (i = 0; i < tot_images; i++) {
-                       BakeImage *image = &images[i];
+               for (i = 0; i < images.size; i++) {
+                       BakeImage *image = &images.data[i];
 
                        if (is_save_internal) {
                                ok = write_internal_bake_pixels(image->image, 
pixel_array_low + image->offset, result + image->offset * depth, image->width, 
image->height, is_linear, margin, is_clear);
@@ -746,8 +783,11 @@ cleanup:
        if (pixel_array_low)
                MEM_freeN(pixel_array_low);
 
-       if (images)
-               MEM_freeN(images);
+       if (images.data)
+               MEM_freeN(images.data);
+
+       if (images.lookup)
+               MEM_freeN(images.lookup);
 
        if (result)
                MEM_freeN(result);
diff --git a/source/blender/render/extern/include/RE_bake.h 
b/source/blender/render/extern/include/RE_bake.h
index 933a41e..206f53a 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -42,6 +42,12 @@ typedef struct BakeImage {
        int 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 BakePixel {
        int primitive_id;
        float uv[2];
@@ -71,7 +77,7 @@ void RE_populate_bake_pixels_from_objects(struct Mesh 
*me_low, BakePixel pixel_a
                                           BakeHighPolyData highpoly[], const 
int tot_highpoly, const int num_pixels,
                                           const float cage_extrusion);
 
-void RE_populate_bake_pixels(struct Mesh *me, struct BakePixel *pixel_array, 
const int num_pixels, const struct BakeImage *images);
+void RE_populate_bake_pixels(struct Mesh *me, struct BakePixel *pixel_array, 
const int num_pixels, const struct BakeImages *images);
 
 void RE_bake_mask_fill(const BakePixel pixel_array[], const int num_pixels, 
char *mask);
 
@@ -81,6 +87,6 @@ void RE_normal_world_to_object(const BakePixel pixel_array[], 
const int num_pixe
 void RE_normal_world_to_tangent(const BakePixel pixel_array[], const int 
num_pixels, const int depth, float result[], struct Mesh *me, const 
BakeNormalSwizzle normal_swizzle[3]);
 void RE_normal_world_to_world(const BakePixel pixel_array[], const int 
num_pixels, const int depth, float result[], const BakeNormalSwizzle 
normal_swizzle[3]);
 
-void RE_bake_ibuf_clear(struct BakeImage *images, const int tot_mat, const 
bool is_tangent);
+void RE_bake_ibuf_clear(struct BakeImages *images, const bool is_tangent);
 
 #endif
diff --git a/source/blender/render/intern/source/bake_api.c 
b/source/blender/render/intern/source/bake_api.c
index 64f46f2..a7ca762 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -81,8 +81,7 @@ extern struct Render R;
 typedef struct BakeDataZSpan {
        BakePixel *pixel_array;
        int primitive_id;
-       int mat_nr;
-       const BakeImage *images;
+       BakeImage *image;
        ZSpan *zspan;
 } BakeDataZSpan;
 
@@ -108,9 +107,9 @@ static void store_bake_pixel(void *handle, int x, int y, 
float u, float v)
 {
        BakeDataZSpan *bd = (BakeDataZSpan *)handle;
        BakePixel *pixel;
-       const int mat_nr = bd->mat_nr;
-       const int width = bd->images[mat_nr].width;
-       const int offset = bd->images[mat_nr].offset;
+
+       const int width = bd->image->width;
+       const int offset = bd->image->offset;
        const int i = offset + y * width + x;
 
        pixel = &bd->pixel_array[i];
@@ -431,10 +430,10 @@ cleanup:
        MEM_free

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to