Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_bake_api.c
| Show All 15 Lines | |||||
| #include "RNA_define.h" | #include "RNA_define.h" | ||||
| #include "RNA_enum_types.h" | #include "RNA_enum_types.h" | ||||
| #include "BLI_fileops.h" | #include "BLI_fileops.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_path_util.h" | #include "BLI_path_util.h" | ||||
| #include "BLI_string.h" | #include "BLI_string.h" | ||||
| #include "BKE_attribute.h" | |||||
| #include "BKE_callbacks.h" | #include "BKE_callbacks.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_image.h" | #include "BKE_image.h" | ||||
| #include "BKE_image_format.h" | #include "BKE_image_format.h" | ||||
| #include "BKE_layer.h" | #include "BKE_layer.h" | ||||
| #include "BKE_lib_id.h" | #include "BKE_lib_id.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| ▲ Show 20 Lines • Show All 410 Lines • ▼ Show 20 Lines | static bool bake_object_check(ViewLayer *view_layer, | ||||
| Mesh *me = (Mesh *)ob->data; | Mesh *me = (Mesh *)ob->data; | ||||
| if (me->totpoly == 0) { | if (me->totpoly == 0) { | ||||
| BKE_reportf(reports, RPT_ERROR, "No faces found in the object \"%s\"", ob->id.name + 2); | BKE_reportf(reports, RPT_ERROR, "No faces found in the object \"%s\"", ob->id.name + 2); | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (target == R_BAKE_TARGET_VERTEX_COLORS) { | if (target == R_BAKE_TARGET_VERTEX_COLORS) { | ||||
| if (BKE_id_attributes_active_color_get(&me->id) == NULL) { | |||||
| BKE_reportf(reports, | |||||
| RPT_ERROR, | |||||
| "Mesh does not have an active color attribute \"%s\"", | |||||
| me->id.name + 2); | |||||
| return false; | |||||
| } | |||||
| const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); | const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); | ||||
| const bool mcol_valid = (mcol != NULL); | const bool mcol_valid = (mcol != NULL); | ||||
| const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); | const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); | ||||
| if (mloopcol == NULL && !mcol_valid) { | if (mloopcol == NULL && !mcol_valid) { | ||||
| BKE_reportf(reports, | |||||
| RPT_ERROR, | |||||
| "No vertex colors layer found in the object \"%s\"", | |||||
| ob->id.name + 2); | |||||
| return false; | |||||
| } | } | ||||
brecht: Remove this `CustomData_get_layer` code, it doesn't do anything. | |||||
| } | } | ||||
| else if (target == R_BAKE_TARGET_IMAGE_TEXTURES) { | else if (target == R_BAKE_TARGET_IMAGE_TEXTURES) { | ||||
| if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) { | if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) { | ||||
| BKE_reportf( | BKE_reportf( | ||||
| reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2); | reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2); | ||||
| return false; | return false; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 465 Lines • ▼ Show 20 Lines | static bool bake_targets_output_external(const BakeAPIRender *bkr, | ||||
| return all_ok; | return all_ok; | ||||
| } | } | ||||
| /* Vertex Color Bake Targets */ | /* Vertex Color Bake Targets */ | ||||
| static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, ReportList *reports) | static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, ReportList *reports) | ||||
| { | { | ||||
| if (ob->type != OB_MESH) { | if (ob->type != OB_MESH) { | ||||
| BKE_report( | BKE_report(reports, RPT_ERROR, "Color attribute baking is only supported for mesh objects"); | ||||
| reports, RPT_ERROR, "Vertex color baking not support with object types other than mesh"); | |||||
| return false; | return false; | ||||
| } | } | ||||
| Mesh *me = ob->data; | Mesh *me = ob->data; | ||||
| const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); | if (BKE_id_attributes_active_color_get(&me->id) == NULL) { | ||||
| const bool mcol_valid = (mcol != NULL); | BKE_report(reports, RPT_ERROR, "No active color attribute to bake to"); | ||||
| const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); | |||||
| if (mloopcol == NULL && !mcol_valid) { | |||||
| BKE_report(reports, RPT_ERROR, "No vertex colors layer found to bake to"); | |||||
| return false; | return false; | ||||
| } | } | ||||
| targets->images = MEM_callocN(sizeof(BakeImage), "BakeTargets.images"); | targets->images = MEM_callocN(sizeof(BakeImage), "BakeTargets.images"); | ||||
| targets->images_num = 1; | targets->images_num = 1; | ||||
| targets->material_to_image = MEM_callocN(sizeof(int) * ob->totcol, | targets->material_to_image = MEM_callocN(sizeof(int) * ob->totcol, | ||||
| "BakeTargets.material_to_image"); | "BakeTargets.material_to_image"); | ||||
| Show All 32 Lines | for (int j = 0; j < mpoly_orig->totloop; ++j, ++mloop_orig) { | ||||
| if (mloop_orig->v == vert_orig) { | if (mloop_orig->v == vert_orig) { | ||||
| return mpoly_orig->loopstart + j; | return mpoly_orig->loopstart + j; | ||||
| } | } | ||||
| } | } | ||||
| return ORIGINDEX_NONE; | return ORIGINDEX_NONE; | ||||
| } | } | ||||
| static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets, | static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, | ||||
| Object *ob, | Object *ob, | ||||
| Mesh *me_eval, | Mesh *me_eval, | ||||
| BakePixel *pixel_array) | BakePixel *pixel_array) | ||||
| { | { | ||||
| Mesh *me = ob->data; | Mesh *me = ob->data; | ||||
| const int pixels_num = targets->pixels_num; | const int pixels_num = targets->pixels_num; | ||||
| /* Initialize blank pixels. */ | /* Initialize blank pixels. */ | ||||
| for (int i = 0; i < pixels_num; i++) { | for (int i = 0; i < pixels_num; i++) { | ||||
| BakePixel *pixel = &pixel_array[i]; | BakePixel *pixel = &pixel_array[i]; | ||||
| ▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | static void bake_result_add_to_rgba(float rgba[4], const float *result, const int channels_num) | ||||
| else { | else { | ||||
| rgba[0] += result[0]; | rgba[0] += result[0]; | ||||
| rgba[1] += result[0]; | rgba[1] += result[0]; | ||||
| rgba[2] += result[0]; | rgba[2] += result[0]; | ||||
| rgba[3] += 1.0f; | rgba[3] += 1.0f; | ||||
| } | } | ||||
| } | } | ||||
| static void convert_float_color_to_byte_color(const MPropCol *float_colors, | |||||
| const int num, | |||||
| const bool is_noncolor, | |||||
| MLoopCol *byte_colors) | |||||
| { | |||||
| if (is_noncolor) { | |||||
| for (int i = 0; i < num; i++) { | |||||
| unit_float_to_uchar_clamp_v4(&byte_colors->r, float_colors[i].color); | |||||
| } | |||||
| } | |||||
| else { | |||||
| for (int i = 0; i < num; i++) { | |||||
| linearrgb_to_srgb_uchar4(&byte_colors[i].r, float_colors[i].color); | |||||
| } | |||||
| } | |||||
| } | |||||
| static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) | static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) | ||||
| { | { | ||||
| Mesh *me = ob->data; | Mesh *me = ob->data; | ||||
| MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); | CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id); | ||||
| const bool mcol_valid = (mcol != NULL); | BLI_assert(active_color_layer != NULL); | ||||
| MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); | const eAttrDomain domain = BKE_id_attribute_domain(&me->id, active_color_layer); | ||||
| const int channels_num = targets->channels_num; | const int channels_num = targets->channels_num; | ||||
| const bool is_noncolor = targets->is_noncolor; | |||||
| const float *result = targets->result; | const float *result = targets->result; | ||||
| if (mcol_valid) { | if (domain == ATTR_DOMAIN_POINT) { | ||||
| const int totvert = me->totvert; | const int totvert = me->totvert; | ||||
| const int totloop = me->totloop; | const int totloop = me->totloop; | ||||
| MPropCol *mcol = active_color_layer->type == CD_PROP_COLOR ? | |||||
| active_color_layer->data : | |||||
| MEM_malloc_arrayN(totvert, sizeof(MPropCol), __func__); | |||||
| /* Accumulate float vertex colors in scene linear color space. */ | /* Accumulate float vertex colors in scene linear color space. */ | ||||
| int *num_loops_for_vertex = MEM_callocN(sizeof(int) * me->totvert, "num_loops_for_vertex"); | int *num_loops_for_vertex = MEM_callocN(sizeof(int) * me->totvert, "num_loops_for_vertex"); | ||||
| memset(mcol, 0, sizeof(MPropCol) * me->totvert); | memset(mcol, 0, sizeof(MPropCol) * me->totvert); | ||||
| MLoop *mloop = me->mloop; | MLoop *mloop = me->mloop; | ||||
| for (int i = 0; i < totloop; i++, mloop++) { | for (int i = 0; i < totloop; i++, mloop++) { | ||||
| const int v = mloop->v; | const int v = mloop->v; | ||||
| bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num); | bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num); | ||||
| num_loops_for_vertex[v]++; | num_loops_for_vertex[v]++; | ||||
| } | } | ||||
| /* Normalize for number of loops. */ | /* Normalize for number of loops. */ | ||||
| for (int i = 0; i < totvert; i++) { | for (int i = 0; i < totvert; i++) { | ||||
| if (num_loops_for_vertex[i] > 0) { | if (num_loops_for_vertex[i] > 0) { | ||||
| mul_v4_fl(mcol[i].color, 1.0f / num_loops_for_vertex[i]); | mul_v4_fl(mcol[i].color, 1.0f / num_loops_for_vertex[i]); | ||||
| } | } | ||||
| } | } | ||||
| MEM_SAFE_FREE(num_loops_for_vertex); | if (mcol != active_color_layer->data) { | ||||
| convert_float_color_to_byte_color(mcol, totvert, is_noncolor, active_color_layer->data); | |||||
| MEM_freeN(mcol); | |||||
| } | } | ||||
| else { | |||||
| /* Byte loop colors in sRGB colors space. */ | |||||
| MLoop *mloop = me->mloop; | |||||
| const int totloop = me->totloop; | |||||
| const bool is_noncolor = targets->is_noncolor; | |||||
| for (int i = 0; i < totloop; i++, mloop++, mloopcol++) { | MEM_SAFE_FREE(num_loops_for_vertex); | ||||
| float rgba[4]; | |||||
| zero_v4(rgba); | |||||
| bake_result_add_to_rgba(rgba, &result[i * channels_num], channels_num); | |||||
| if (is_noncolor) { | |||||
| unit_float_to_uchar_clamp_v4(&mloopcol->r, rgba); | |||||
| } | } | ||||
| else { | else if (domain == ATTR_DOMAIN_CORNER) { | ||||
| linearrgb_to_srgb_uchar4(&mloopcol->r, rgba); | switch (active_color_layer->type) { | ||||
| case CD_PROP_COLOR: { | |||||
| MPropCol *colors = active_color_layer->data; | |||||
| for (int i = 0; i < me->totloop; i++) { | |||||
| zero_v4(colors[i].color); | |||||
| bake_result_add_to_rgba(colors[i].color, &result[i * channels_num], channels_num); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case CD_PROP_BYTE_COLOR: { | |||||
| MLoopCol *colors = active_color_layer->data; | |||||
| for (int i = 0; i < me->totloop; i++) { | |||||
| MPropCol color; | |||||
| zero_v4(color.color); | |||||
| bake_result_add_to_rgba(color.color, &result[i * channels_num], channels_num); | |||||
| convert_float_color_to_byte_color(&color, 1, is_noncolor, &colors[i]); | |||||
| } | } | ||||
| break; | |||||
| } | |||||
| default: | |||||
| BLI_assert_unreachable(); | |||||
| } | } | ||||
| } | } | ||||
| DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); | DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); | ||||
| return true; | return true; | ||||
| } | } | ||||
| Show All 37 Lines | |||||
| static void bake_targets_populate_pixels(const BakeAPIRender *bkr, | static void bake_targets_populate_pixels(const BakeAPIRender *bkr, | ||||
| BakeTargets *targets, | BakeTargets *targets, | ||||
| Object *ob, | Object *ob, | ||||
| Mesh *me_eval, | Mesh *me_eval, | ||||
| BakePixel *pixel_array) | BakePixel *pixel_array) | ||||
| { | { | ||||
| if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) { | if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) { | ||||
| bake_targets_populate_pixels_vertex_colors(targets, ob, me_eval, pixel_array); | bake_targets_populate_pixels_color_attributes(targets, ob, me_eval, pixel_array); | ||||
| } | } | ||||
| else { | else { | ||||
| RE_bake_pixels_populate(me_eval, pixel_array, targets->pixels_num, targets, bkr->uv_layer); | RE_bake_pixels_populate(me_eval, pixel_array, targets->pixels_num, targets, bkr->uv_layer); | ||||
| } | } | ||||
| } | } | ||||
| static bool bake_targets_output(const BakeAPIRender *bkr, | static bool bake_targets_output(const BakeAPIRender *bkr, | ||||
| BakeTargets *targets, | BakeTargets *targets, | ||||
| ▲ Show 20 Lines • Show All 941 Lines • Show Last 20 Lines | |||||
Remove this CustomData_get_layer code, it doesn't do anything.