Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object/object_bake_api.c')
-rw-r--r--source/blender/editors/object/object_bake_api.c182
1 files changed, 143 insertions, 39 deletions
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 2c4f7a8e107..fd95d6129ad 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -76,6 +76,8 @@
#include "object_intern.h"
+/* prototypes */
+static void bake_set_props(wmOperator *op, Scene *scene);
typedef struct BakeAPIRender {
Object *ob;
@@ -85,6 +87,7 @@ typedef struct BakeAPIRender {
ListBase selected_objects;
ScenePassType pass_type;
+ int pass_filter;
int margin;
int save_mode;
@@ -421,11 +424,72 @@ static bool bake_object_check(Object *ob, ReportList *reports)
return false;
}
- image->id.flag |= LIB_DOIT;
+ image->id.tag |= LIB_TAG_DOIT;
}
return true;
}
+static bool bake_pass_filter_check(ScenePassType pass_type, const int pass_filter, ReportList *reports)
+{
+ switch (pass_type) {
+ case SCE_PASS_COMBINED:
+ if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) {
+ return true;
+ }
+
+ if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
+ {
+ if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0))
+ {
+ return true;
+ }
+
+ if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) {
+ BKE_report(reports, RPT_ERROR,
+ "Combined bake pass Ambient Occlusion contribution requires an enabled light pass "
+ "(bake the Ambient Occlusion pass type instead)");
+ }
+ else {
+ BKE_report(reports, RPT_ERROR,
+ "Combined bake pass requires Emit, or a light pass with "
+ "Direct or Indirect contributions enabled");
+ }
+
+ return false;
+ }
+ else {
+ BKE_report(reports, RPT_ERROR,
+ "Combined bake pass requires Emit, or a light pass with "
+ "Direct or Indirect contributions enabled");
+ return false;
+ }
+ break;
+ case SCE_PASS_DIFFUSE_COLOR:
+ case SCE_PASS_GLOSSY_COLOR:
+ case SCE_PASS_TRANSM_COLOR:
+ case SCE_PASS_SUBSURFACE_COLOR:
+ if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
+ {
+ return true;
+ }
+ else {
+ BKE_report(reports, RPT_ERROR,
+ "Bake pass requires Direct, Indirect, or Color contributions to be enabled");
+ return false;
+ }
+ break;
+ default:
+ return true;
+ break;
+ }
+}
+
/* before even getting in the bake function we check for some basic errors */
static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objects,
ReportList *reports, const bool is_selected_to_active)
@@ -433,7 +497,7 @@ static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objec
CollectionPointerLink *link;
/* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, false);
+ BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
if (is_selected_to_active) {
int tot_objects = 0;
@@ -478,7 +542,7 @@ static void bake_images_clear(Main *bmain, const bool is_tangent)
{
Image *image;
for (image = bmain->image.first; image; image = image->id.next) {
- if ((image->id.flag & LIB_DOIT) != 0) {
+ if ((image->id.tag & LIB_TAG_DOIT) != 0) {
RE_bake_ibuf_clear(image, is_tangent);
}
}
@@ -491,13 +555,13 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
int tot_images = 0;
/* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, false);
+ BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
for (i = 0; i < tot_mat; i++) {
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
- if ((image->id.flag & LIB_DOIT)) {
+ if ((image->id.tag & LIB_TAG_DOIT)) {
for (j = 0; j < i; j++) {
if (bake_images->data[j].image == image) {
bake_images->lookup[i] = j;
@@ -508,7 +572,7 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
else {
bake_images->lookup[i] = tot_images;
bake_images->data[tot_images].image = image;
- image->id.flag |= LIB_DOIT;
+ image->id.tag |= LIB_TAG_DOIT;
tot_images++;
}
}
@@ -548,9 +612,21 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
return tot_size;
}
+/* create new mesh with edit mode changes and modifiers applied */
+static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
+{
+ if (ob->mode & OB_MODE_EDIT)
+ ED_object_editmode_load(ob);
+
+ Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
+ BKE_mesh_split_faces(me);
+
+ return me;
+}
+
static int bake(
Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
- const ScenePassType pass_type, const int margin,
+ const ScenePassType pass_type, const int pass_filter, const int margin,
const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[],
@@ -571,6 +647,9 @@ static int bake(
Mesh *me_low = NULL;
Mesh *me_cage = NULL;
+ MultiresModifierData *mmd_low = NULL;
+ int mmd_flags_low = 0;
+
float *result = NULL;
BakePixel *pixel_array_low = NULL;
@@ -584,7 +663,6 @@ static int bake(
size_t num_pixels;
int tot_materials;
- int i;
RE_bake_engine_set_engine_parameters(re, bmain, scene);
@@ -641,7 +719,7 @@ static int bake(
num_pixels = (size_t)width * (size_t)height * bake_images.size;
- for (i = 0; i < bake_images.size; i++) {
+ for (int i = 0; i < bake_images.size; i++) {
bake_images.data[i].width = width;
bake_images.data[i].height = height;
bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
@@ -650,8 +728,9 @@ static int bake(
if (!is_split_materials) {
/* saving a single image */
- for (i = 0; i < tot_materials; i++)
+ for (int i = 0; i < tot_materials; i++) {
bake_images.lookup[i] = 0;
+ }
}
}
@@ -686,10 +765,17 @@ static int bake(
pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
+ /* for multires bake, use linear UV subdivision to match low res UVs */
+ if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT && !is_selected_to_active) {
+ mmd_low = (MultiresModifierData *) modifiers_findByType(ob_low, eModifierType_Multires);
+ if (mmd_low) {
+ mmd_flags_low = mmd_low->flags;
+ mmd_low->flags |= eMultiresModifierFlag_PlainUv;
+ }
+ }
+
/* get the mesh as it arrives in the renderer */
- me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
- BKE_mesh_split_faces(me_low);
- BKE_mesh_tessface_ensure(me_low);
+ me_low = bake_mesh_new_from_object(bmain, scene, ob_low);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -704,10 +790,8 @@ static int bake(
/* prepare cage mesh */
if (ob_cage) {
- me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0);
- BKE_mesh_split_faces(me_cage);
- BKE_mesh_tessface_ensure(me_cage);
- if (me_low->totface != me_cage->totface) {
+ me_cage = bake_mesh_new_from_object(bmain, scene, ob_cage);
+ if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number "
"of faces as the active object");
@@ -738,9 +822,7 @@ static int bake(
ob_low->modifiers = modifiers_tmp;
/* get the cage mesh as it arrives in the renderer */
- me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
- BKE_mesh_split_faces(me_cage);
- BKE_mesh_tessface_ensure(me_cage);
+ me_cage = bake_mesh_new_from_object(bmain, scene, ob_low);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -766,10 +848,8 @@ static int bake(
tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;
- highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0);
+ highpoly[i].me = bake_mesh_new_from_object(bmain, scene, highpoly[i].ob);
highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
- BKE_mesh_split_faces(highpoly[i].me);
- BKE_mesh_tessface_ensure(highpoly[i].me);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -796,7 +876,7 @@ static int bake(
/* the baking itself */
for (i = 0; i < tot_highpoly; i++) {
ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high,
- num_pixels, depth, pass_type, result);
+ num_pixels, depth, pass_type, pass_filter, result);
if (!ok) {
BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
goto cage_cleanup;
@@ -822,7 +902,7 @@ cage_cleanup:
ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
if (RE_bake_has_engine(re)) {
- ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result);
+ ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
}
else {
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
@@ -871,9 +951,7 @@ cage_cleanup:
md->mode &= ~eModifierMode_Render;
}
- me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
- BKE_mesh_split_faces(me_nores);
- BKE_mesh_tessface_ensure(me_nores);
+ me_nores = bake_mesh_new_from_object(bmain, scene, ob_low);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
@@ -895,7 +973,7 @@ cage_cleanup:
}
else {
/* save the results */
- for (i = 0; i < bake_images.size; i++) {
+ for (int i = 0; i < bake_images.size; i++) {
BakeImage *bk_image = &bake_images.data[i];
if (is_save_internal) {
@@ -997,6 +1075,9 @@ cleanup:
ob_low->restrictflag = restrict_flag_low;
+ if (mmd_low)
+ mmd_low->flags = mmd_flags_low;
+
if (ob_cage)
ob_cage->restrictflag = restrict_flag_cage;
@@ -1035,6 +1116,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
bkr->pass_type = RNA_enum_get(op->ptr, "type");
+ bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
bkr->margin = RNA_int_get(op->ptr, "margin");
bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
@@ -1083,6 +1165,9 @@ static int bake_exec(bContext *C, wmOperator *op)
Render *re;
int result = OPERATOR_CANCELLED;
BakeAPIRender bkr = {NULL};
+ Scene *scene = CTX_data_scene(C);
+
+ bake_set_props(op, scene);
bake_init_api_data(op, C, &bkr);
re = bkr.render;
@@ -1090,6 +1175,10 @@ static int bake_exec(bContext *C, wmOperator *op)
/* setup new render */
RE_test_break_cb(re, NULL, bake_break);
+ if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) {
+ goto finally;
+ }
+
if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
goto finally;
}
@@ -1104,7 +1193,7 @@ static int bake_exec(bContext *C, wmOperator *op)
if (bkr.is_selected_to_active) {
result = bake(
bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
- bkr.pass_type, bkr.margin, bkr.save_mode,
+ bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa,
@@ -1117,7 +1206,7 @@ static int bake_exec(bContext *C, wmOperator *op)
Object *ob_iter = link->ptr.data;
result = bake(
bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
- bkr.pass_type, bkr.margin, bkr.save_mode,
+ bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa,
@@ -1143,6 +1232,11 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
RE_SetReports(bkr->render, bkr->reports);
+ if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) {
+ bkr->result = OPERATOR_CANCELLED;
+ return;
+ }
+
if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
bkr->result = OPERATOR_CANCELLED;
return;
@@ -1156,7 +1250,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
if (bkr->is_selected_to_active) {
bkr->result = bake(
bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
- bkr->pass_type, bkr->margin, bkr->save_mode,
+ bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa,
@@ -1169,7 +1263,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
Object *ob_iter = link->ptr.data;
bkr->result = bake(
bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
- bkr->pass_type, bkr->margin, bkr->save_mode,
+ bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa,
@@ -1277,6 +1371,11 @@ static void bake_set_props(wmOperator *op, Scene *scene)
if (!RNA_property_is_set(op->ptr, prop)) {
RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
}
+
+ prop = RNA_struct_find_property(op->ptr, "pass_filter");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->pass_filter);
+ }
}
static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -1325,6 +1424,8 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
void OBJECT_OT_bake(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Bake";
ot->description = "Bake image textures of selected objects";
@@ -1336,8 +1437,11 @@ void OBJECT_OT_bake(wmOperatorType *ot)
ot->invoke = bake_invoke;
ot->poll = ED_operator_object_active_editable_mesh;
- RNA_def_enum(ot->srna, "type", render_pass_type_items, SCE_PASS_COMBINED, "Type",
+ RNA_def_enum(ot->srna, "type", rna_enum_bake_pass_type_items, SCE_PASS_COMBINED, "Type",
"Type of pass to bake, some of them may not be supported by the current render engine");
+ prop = RNA_def_enum(ot->srna, "pass_filter", rna_enum_bake_pass_filter_type_items, R_BAKE_PASS_FILTER_NONE, "Pass Filter",
+ "Filter to combined, diffuse, glossy, transmission and subsurface passes");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path",
"Image filepath to use when saving externally");
RNA_def_int(ot->srna, "width", 512, 1, INT_MAX, "Width",
@@ -1352,12 +1456,12 @@ void OBJECT_OT_bake(wmOperatorType *ot)
"Distance to use for the inward ray cast when using selected to active", 0.0f, 1.0f);
RNA_def_string(ot->srna, "cage_object", NULL, MAX_NAME, "Cage Object",
"Object to use as cage, instead of calculating the cage from the active object with cage extrusion");
- RNA_def_enum(ot->srna, "normal_space", normal_space_items, R_BAKE_SPACE_TANGENT, "Normal Space",
+ RNA_def_enum(ot->srna, "normal_space", rna_enum_normal_space_items, R_BAKE_SPACE_TANGENT, "Normal Space",
"Choose normal space for baking");
- RNA_def_enum(ot->srna, "normal_r", normal_swizzle_items, R_BAKE_POSX, "R", "Axis to bake in red channel");
- RNA_def_enum(ot->srna, "normal_g", normal_swizzle_items, R_BAKE_POSY, "G", "Axis to bake in green channel");
- RNA_def_enum(ot->srna, "normal_b", normal_swizzle_items, R_BAKE_POSZ, "B", "Axis to bake in blue channel");
- RNA_def_enum(ot->srna, "save_mode", bake_save_mode_items, R_BAKE_SAVE_INTERNAL, "Save Mode",
+ RNA_def_enum(ot->srna, "normal_r", rna_enum_normal_swizzle_items, R_BAKE_POSX, "R", "Axis to bake in red channel");
+ RNA_def_enum(ot->srna, "normal_g", rna_enum_normal_swizzle_items, R_BAKE_POSY, "G", "Axis to bake in green channel");
+ RNA_def_enum(ot->srna, "normal_b", rna_enum_normal_swizzle_items, R_BAKE_POSZ, "B", "Axis to bake in blue channel");
+ RNA_def_enum(ot->srna, "save_mode", rna_enum_bake_save_mode_items, R_BAKE_SAVE_INTERNAL, "Save Mode",
"Choose how to save the baking map");
RNA_def_boolean(ot->srna, "use_clear", false, "Clear",
"Clear Images before baking (only for internal saving)");