[Bf-blender-cvs] [a1c99c0] bake-cycles: Cycles-Bake: internal saving and split image per material

Dalai Felinto noreply at git.blender.org
Wed Apr 23 02:48:10 CEST 2014


Commit: a1c99c0393f260b090db814cbc9c3ddc81fbe794
Author: Dalai Felinto
Date:   Wed Apr 16 14:20:15 2014 -0300
https://developer.blender.org/rBa1c99c0393f260b090db814cbc9c3ddc81fbe794

Cycles-Bake: internal saving and split image per material

We can now export more than one image (if there is more than one
material in the object), as well as automatically name the texture based
on the pass type.

This was a big refactor of the operator code, but things should be
stable now. use_automatic_name should probably be named use_prefix or
something.

Not working:
* use_clear (in fact it's always clearing, I need to copy only a few parts of the image, using a mask)
* image update - right now you need to click in the Image Editor to
  see/refresh the baked image

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

M	intern/cycles/blender/addon/ui.py
M	source/blender/editors/object/object_bake_api.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/RNA_enum_types.h
M	source/blender/makesrna/intern/rna_scene.c
M	source/blender/render/extern/include/RE_bake.h
M	source/blender/render/intern/source/bake_api.c

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

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 6e34026..bd4d213 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1250,6 +1250,7 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
         row = col.row()
 
         sub = row.column(align=True)
+        sub.active = cbk.save_mode == 'EXTERNAL'
         sub.prop(cbk, "width")
         sub.prop(cbk, "height")
 
@@ -1276,11 +1277,21 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
             row.prop(cbk, "normal_b", text="")
 
         col.separator()
-        col.label(text="Output File:")
-        col.prop(cbk, "filepath", text="")
+        col.label(text="Output:")
+        col.row().prop(cbk, "save_mode", expand=True)
 
-        col.separator()
-        col.template_image_settings(cbk.image_settings, color_management=False)
+        if cbk.save_mode == 'EXTERNAL':
+            row = col.row()
+            row.prop(cbk, "use_automatic_name")
+            row.prop(cbk, "use_split_materials")
+
+            col.separator()
+            col.prop(cbk, "filepath", text="")
+
+            col.separator()
+            col.template_image_settings(cbk.image_settings, color_management=False)
+        else:
+            col.prop(cbk, "use_clear")
 
 
 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 8e20271..86a2851 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -41,6 +41,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_defs.h"
+#include "DNA_material_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -89,6 +90,7 @@
 
 #include "ED_object.h"
 #include "ED_screen.h"
+#include "ED_uvedit.h"
 
 #include "RE_bake.h"
 
@@ -119,6 +121,45 @@ static int bake_break(void *UNUSED(rjv))
 	return 0;
 }
 
+static bool write_internal_bake_pixels(
+    Image *image, BakePixel pixel_array[], float *buffer,
+    const int width, const int height, const bool is_linear, const int margin)
+{
+	ImBuf *ibuf;
+	void *lock;
+	bool is_float;
+
+	ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+
+	if (!ibuf)
+		return false;
+
+	is_float = false;
+
+	/* populates the ImBuf */
+	if (is_float) {
+		IMB_buffer_float_from_float(
+		    ibuf->rect_float, buffer, ibuf->channels,
+		    IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
+		    ibuf->x, ibuf->y, ibuf->x, ibuf->y
+		    );
+	}
+	else {
+		IMB_buffer_byte_from_float(
+		    (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
+		    (is_linear ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB), IB_PROFILE_LINEAR_RGB,
+		    false, ibuf->x, ibuf->y, ibuf->x, ibuf->x
+		    );
+	}
+
+	/* margins */
+	RE_bake_margin(pixel_array, ibuf, margin, width, height);
+
+	ibuf->userflags |= IB_BITMAPDIRTY;
+	BKE_image_release_ibuf(image, ibuf, NULL);
+	return true;
+}
+
 static bool write_external_bake_pixels(
     const char *filepath, BakePixel pixel_array[], float *buffer,
     const int width, const int height, bool is_linear, const int margin,
@@ -180,6 +221,57 @@ static bool is_data_pass(ScenePassType pass_type)
 				 SCE_PASS_INDEXMA);
 }
 
+static int get_save_internal_status(wmOperator *op, Object *ob, BakeImage *images)
+{
+	int i;
+	int tot_mat = ob->totcol;
+	int tot_size = 0;
+
+	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) {
+			if (ob->mat[i]) {
+				BKE_reportf(op->reports, RPT_ERROR, "No valid image in material %d (%s)", i, ob->mat[i]->id.name + 2);
+			}
+			else if (((Mesh *) ob->data)->mat[i]){
+				BKE_reportf(op->reports, RPT_ERROR, "No valid image in material %d (%s)", i, ((Mesh *) ob->data)->mat[i]->id.name + 2);
+			}
+			else {
+				BKE_reportf(op->reports, RPT_ERROR, "No valid image in material %d", i);
+			}
+
+			return -1;
+		}
+
+		ibuf = BKE_image_acquire_ibuf(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;
+
+			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, ibuf, lock);
+	}
+
+	return tot_size;
+}
+
 static int bake_exec(bContext *C, wmOperator *op)
 {
 	Main *bmain = CTX_data_main(C);
@@ -212,18 +304,21 @@ static int bake_exec(bContext *C, wmOperator *op)
 	BakePixel *pixel_array_high = NULL;
 	BakePixel *pixel_array_render = NULL;
 
-	const int width = RNA_int_get(op->ptr, "width");
-	const int height = RNA_int_get(op->ptr, "height");
-	const int num_pixels = width * height;
 	const int depth = RE_pass_depth(pass_type);
 	const int margin = RNA_int_get(op->ptr, "margin");
-	const bool is_external = RNA_boolean_get(op->ptr, "is_save_external");
+	const bool is_save_internal = (RNA_enum_get(op->ptr, "save_mode") == R_BAKE_SAVE_INTERNAL);
+	const bool is_clear = RNA_boolean_get(op->ptr, "use_clear");
+	const bool is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
+	const bool is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
 	const bool is_linear = is_data_pass(pass_type);
 	const bool use_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
 	const float cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
+
 	bool is_cage;
 	bool is_tangent;
 
+	BakeImage *images;
+
 	int normal_space = RNA_enum_get(op->ptr, "normal_space");
 	BakeNormalSwizzle normal_swizzle[] = {
 		RNA_enum_get(op->ptr, "normal_r"),
@@ -237,6 +332,40 @@ static int bake_exec(bContext *C, wmOperator *op)
 	RNA_string_get(op->ptr, "cage", custom_cage);
 	RNA_string_get(op->ptr, "filepath", filepath);
 
+	int num_pixels;
+	int tot_images;
+	int i;
+
+	tot_images = ob_low->totcol;
+	is_tangent = pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT;
+
+	images = MEM_callocN(sizeof(BakeImage) * tot_images, "bake images dimensions (width, height, offset)");
+
+	if (is_save_internal) {
+		num_pixels = get_save_internal_status(op, ob_low, images);
+
+		if (num_pixels < 0) {
+			MEM_freeN(images);
+			return OPERATOR_CANCELLED;
+		}
+		else if (is_clear) {
+			RE_bake_ibuf_clear(images, tot_images, is_tangent);
+		}
+	}
+	else {
+		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;
+
+			num_pixels += images[i].width * images[i].height;
+		}
+
+		BLI_assert(num_pixels == tot_images * images[0].width * images[0].height);
+	}
+
 	if (use_selected_to_active) {
 		CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 		{
@@ -281,7 +410,6 @@ static int bake_exec(bContext *C, wmOperator *op)
 	result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
 
 	is_cage = ob_high && (ob_high->type == OB_MESH);
-	is_tangent = pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT;
 
 	/* high-poly to low-poly baking */
 	if (is_cage) {
@@ -327,7 +455,7 @@ static int bake_exec(bContext *C, wmOperator *op)
 		}
 
 		/* populate the pixel array with the face data */
-		RE_populate_bake_pixels(me_low, pixel_array_low, width, height);
+		RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, images);
 
 		/* triangulating it makes life so much easier ... */
 		tri_mod = ED_object_modifier_add(op->reports, bmain, scene, ob_high, "TmpTriangulate", eModifierType_Triangulate);
@@ -347,11 +475,11 @@ static int bake_exec(bContext *C, wmOperator *op)
 				BKE_libblock_free(bmain, me_low);
 
 				me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
-				RE_populate_bake_pixels(me_low, pixel_array_low, width, height);
+				RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, images);
 			}
 
 			/* need to make sure missed rays are masked out of the result */
-			RE_mask_bake_pixels(pixel_array_high, pixel_array_low, width, height);
+			RE_mask_bake_pixels(pixel_array_high, pixel_array_low, num_pixels);
 		}
 		else {
 			/* re-use the same BakePixel array */
@@ -382,7 +510,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, width, height);
+		RE_populate_bake_pixels(me_low, pixel_array_low, num_pixels, images);
 		pixel_array_render = pixel_array_low;
 
 		/* make sure low poly renders */
@@ -428,30 +556,82 @@ static int bake_exec(bContext *C, wmOperator *op)
 		op_result = OPERATOR_CANCELLED;
 	}
 	else {
-		/* save the result */
-		if (is_external) {
-			BakeData *bake = &scene->r.bake;
-			char name[FILE_MAX];
-
-			BKE_makepicstring_from_type(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false);
+		/* save the results */
+		for (i = 0; i < tot_images; i++) {
+			BakeImage *image = &images[i];
 
-			/* save it externally */
-			ok = write_external_bake_pixels(name, pixel_array_render, result, width, height, is_linear, margin, &bake->im_format);
+			if (is_save_internal) {
+				ok = write_internal_bake_pixels(image->image, pixel_array_render + image->offset, result + image->offset * depth, image->width, image->height, is_linear, margin);
 
-			if (!ok) {
-				BKE_reportf(op->reports, RPT_ERROR, "Problem saving baked map in \"%s\".", name);
-				op_result = OPERATOR_CANCELLED;
+				if (!ok) {
+					BKE_report(op->reports, RPT_ERROR, "Problem saving the bake map internally, make sure there is a Texture Image node in the current object material");
+					op_result = OPERATOR_CANCELLED;
+				}
+				else {
+					BKE_report(op->reports, RPT_INFO, "Baking map saved to internal image, save it externally or pack it");
+					op_resul

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list