[Bf-blender-cvs] [44a1d84] bake-cycles: Cycles-Bake: better support for multiple materials referring to the same image

Dalai Felinto noreply at git.blender.org
Sat Apr 26 18:22:08 CEST 2014


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. @@




More information about the Bf-blender-cvs mailing list