Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_bake_api.c
| Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
| #include "ED_object.h" | #include "ED_object.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_uvedit.h" | #include "ED_uvedit.h" | ||||
| #include "GPU_draw.h" | #include "GPU_draw.h" | ||||
| #include "object_intern.h" | #include "object_intern.h" | ||||
| typedef struct BakeAPIProgress { | |||||
| Render *render; | |||||
| float *progress; | |||||
| short *do_update; | |||||
| float *result; | |||||
| int current_image; | |||||
| int num_pixels; | |||||
| BakeImages *bake_images; | |||||
| } BakeAPIProgress; | |||||
| typedef struct BakeAPIRender { | typedef struct BakeAPIRender { | ||||
| Object *ob; | Object *ob; | ||||
| Main *main; | Main *main; | ||||
| Scene *scene; | Scene *scene; | ||||
| ReportList *reports; | ReportList *reports; | ||||
| ListBase selected_objects; | ListBase selected_objects; | ||||
| Show All 20 Lines | typedef struct BakeAPIRender { | ||||
| int height; | int height; | ||||
| const char *identifier; | const char *identifier; | ||||
| int result; | int result; | ||||
| bool ready; | bool ready; | ||||
| /* callbacks */ | /* callbacks */ | ||||
| Render *render; | Render *render; | ||||
| float *progress; | BakeAPIProgress progress; | ||||
| short *do_update; | |||||
| /* for redrawing */ | /* for redrawing */ | ||||
| ScrArea *sa; | ScrArea *sa; | ||||
| } BakeAPIRender; | } BakeAPIRender; | ||||
| /* callbacks */ | /* callbacks */ | ||||
| static void bake_progress_update(void *bjv, float progress) | static void bake_progress_update(void *bkv, float progress) | ||||
| { | { | ||||
| BakeAPIRender *bj = bjv; | BakeAPIProgress *bkp = bkv; | ||||
| if (bj->progress && *bj->progress != progress) { | if (bkp->progress && *bkp->progress != progress) { | ||||
| *bj->progress = progress; | *bkp->progress = progress; | ||||
| /* make jobs timer to send notifier */ | /* make jobs timer to send notifier */ | ||||
| *(bj->do_update) = true; | *(bkp->do_update) = true; | ||||
| } | |||||
| } | } | ||||
| static void bake_display_update(void *bkv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) | |||||
sergey: I'd suggest dropping from the current patch. | |||||
| { | |||||
| BakeAPIProgress *bkp = bkv; | |||||
| printf("%s\n", __func__); | |||||
| *(bkp->do_update) = true; | |||||
| /* | |||||
| what we need to do: | |||||
| 1) See which image is being rendered (based on progress and numsamples) | |||||
| int pixel = progress * ... | |||||
| 2) Upon change of current image: | |||||
| 3) See if the image is being shown: | |||||
| * if not, see if the previous image is being shown | |||||
| * if it's shown then change the uv editor accordingly to show the new one | |||||
| 4) draw that image in particular | |||||
| */ | |||||
| } | } | ||||
| #if 0 | |||||
| //brb | |||||
| static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect) | |||||
| { | |||||
| RenderJob *rj = rjv; | |||||
| Image *ima = rj->image; | |||||
| ImBuf *ibuf; | |||||
| void *lock; | |||||
| /* only update if we are displaying the slot being rendered */ | |||||
| if (ima->render_slot != ima->last_render_slot) { | |||||
| rj->image_outdated = true; | |||||
| return; | |||||
| } | |||||
| else if (rj->image_outdated) { | |||||
| /* update entire render */ | |||||
| rj->image_outdated = false; | |||||
| BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); | |||||
| *(rj->do_update) = true; | |||||
| return; | |||||
| } | |||||
| if (rr == NULL) | |||||
| return; | |||||
| /* update part of render */ | |||||
| render_image_update_pass_and_layer(rj, rr, &rj->iuser); | |||||
| ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); | |||||
| if (ibuf) { | |||||
| /* Don't waste time on CPU side color management if | |||||
| * image will be displayed using GLSL. | |||||
| * | |||||
| * Need to update rect if Save Buffers enabled because in | |||||
| * this case GLSL doesn't have original float buffer to | |||||
| * operate with. | |||||
| */ | |||||
| if (rr->do_exr_tile || | |||||
| ibuf->channels == 1 || | |||||
| U.image_draw_method != IMAGE_DRAW_METHOD_GLSL) | |||||
| { | |||||
| image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect); | |||||
| } | |||||
| /* make jobs timer to send notifier */ | |||||
| *(rj->do_update) = true; | |||||
| } | |||||
| BKE_image_release_ibuf(ima, ibuf, lock); | |||||
| } | |||||
| #endif | |||||
| /* catch esc */ | /* catch esc */ | ||||
| static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | ||||
| { | { | ||||
| /* no running blender, remove handler and pass through */ | /* no running blender, remove handler and pass through */ | ||||
| if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE)) | if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE)) | ||||
| return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; | return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; | ||||
| /* running render */ | /* running render */ | ||||
| ▲ Show 20 Lines • Show All 385 Lines • ▼ Show 20 Lines | for (i = 0; i < bake_images->size; i++) { | ||||
| } | } | ||||
| BKE_image_release_ibuf(bk_image->image, ibuf, lock); | BKE_image_release_ibuf(bk_image->image, ibuf, lock); | ||||
| } | } | ||||
| return tot_size; | return tot_size; | ||||
| } | } | ||||
| static int bake( | static int bake( | ||||
| Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, | Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, | ||||
| const ScenePassType pass_type, const int margin, | BakeAPIProgress *progress, const ScenePassType pass_type, const int margin, | ||||
| const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials, | 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 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[], | const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[], | ||||
| const char *custom_cage, const char *filepath, const int width, const int height, | const char *custom_cage, const char *filepath, const int width, const int height, | ||||
| const char *identifier, ScrArea *sa, const char *uv_layer) | const char *identifier, ScrArea *sa, const char *uv_layer) | ||||
| { | { | ||||
| int op_result = OPERATOR_CANCELLED; | int op_result = OPERATOR_CANCELLED; | ||||
| bool ok = false; | bool ok = false; | ||||
| ▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | if (is_selected_to_active) { | ||||
| if (!RE_bake_pixels_populate_from_objects( | if (!RE_bake_pixels_populate_from_objects( | ||||
| me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL, | me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL, | ||||
| cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) | cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) | ||||
| { | { | ||||
| BKE_report(reports, RPT_ERROR, "Error handling selected objects"); | BKE_report(reports, RPT_ERROR, "Error handling selected objects"); | ||||
| goto cage_cleanup; | goto cage_cleanup; | ||||
| } | } | ||||
| if (progress) { | |||||
| progress->result = result; | |||||
| progress->bake_images = &bake_images; | |||||
| progress->num_pixels = num_pixels; | |||||
| } | |||||
| /* the baking itself */ | /* the baking itself */ | ||||
| for (i = 0; i < tot_highpoly; i++) { | for (i = 0; i < tot_highpoly; i++) { | ||||
| ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels, | ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels, | ||||
| depth, pass_type, result); | depth, pass_type, result); | ||||
| if (!ok) { | if (!ok) { | ||||
| BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2); | BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2); | ||||
| goto cage_cleanup; | goto cage_cleanup; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | if (bkr.is_clear) { | ||||
| const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT)); | const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT)); | ||||
| bake_images_clear(bkr.main, is_tangent); | bake_images_clear(bkr.main, is_tangent); | ||||
| } | } | ||||
| RE_SetReports(re, bkr.reports); | RE_SetReports(re, bkr.reports); | ||||
| if (bkr.is_selected_to_active) { | if (bkr.is_selected_to_active) { | ||||
| result = bake( | result = bake( | ||||
| bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, | bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, NULL, | ||||
| bkr.pass_type, bkr.margin, bkr.save_mode, | bkr.pass_type, bkr.margin, bkr.save_mode, | ||||
| bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage, | 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.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, | ||||
| bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, | bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, | ||||
| bkr.uv_layer); | bkr.uv_layer); | ||||
| } | } | ||||
| else { | else { | ||||
| CollectionPointerLink *link; | CollectionPointerLink *link; | ||||
| const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects); | const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects); | ||||
| for (link = bkr.selected_objects.first; link; link = link->next) { | for (link = bkr.selected_objects.first; link; link = link->next) { | ||||
| Object *ob_iter = link->ptr.data; | Object *ob_iter = link->ptr.data; | ||||
| result = bake( | result = bake( | ||||
| bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports, | bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports, NULL, | ||||
| bkr.pass_type, bkr.margin, bkr.save_mode, | bkr.pass_type, bkr.margin, bkr.save_mode, | ||||
| is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage, | is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage, | ||||
| bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, | bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, | ||||
| bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, | bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, | ||||
| bkr.uv_layer); | bkr.uv_layer); | ||||
| } | } | ||||
| } | } | ||||
| RE_SetReports(re, NULL); | RE_SetReports(re, NULL); | ||||
| BLI_freelistN(&bkr.selected_objects); | BLI_freelistN(&bkr.selected_objects); | ||||
| return result; | return result; | ||||
| } | } | ||||
| static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, float *progress) | static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, float *progress) | ||||
| { | { | ||||
| BakeAPIRender *bkr = (BakeAPIRender *)bkv; | BakeAPIRender *bkr = (BakeAPIRender *)bkv; | ||||
| /* setup new render */ | /* setup new render */ | ||||
| bkr->do_update = do_update; | bkr->progress.do_update = do_update; | ||||
| bkr->progress = progress; | bkr->progress.progress = progress; | ||||
| RE_SetReports(bkr->render, bkr->reports); | RE_SetReports(bkr->render, bkr->reports); | ||||
| if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) { | if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) { | ||||
| bkr->result = OPERATOR_CANCELLED; | bkr->result = OPERATOR_CANCELLED; | ||||
| return; | return; | ||||
| } | } | ||||
| if (bkr->is_clear) { | if (bkr->is_clear) { | ||||
| const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT)); | const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT)); | ||||
| bake_images_clear(bkr->main, is_tangent); | bake_images_clear(bkr->main, is_tangent); | ||||
| } | } | ||||
| if (bkr->is_selected_to_active) { | if (bkr->is_selected_to_active) { | ||||
| bkr->result = bake( | bkr->result = bake( | ||||
| bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, | bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, &bkr->progress, | ||||
| bkr->pass_type, bkr->margin, bkr->save_mode, | bkr->pass_type, bkr->margin, bkr->save_mode, | ||||
| bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage, | 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->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, | ||||
| bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa, | bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa, | ||||
| bkr->uv_layer); | bkr->uv_layer); | ||||
| } | } | ||||
| else { | else { | ||||
| CollectionPointerLink *link; | CollectionPointerLink *link; | ||||
| const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects); | const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects); | ||||
| for (link = bkr->selected_objects.first; link; link = link->next) { | for (link = bkr->selected_objects.first; link; link = link->next) { | ||||
| Object *ob_iter = link->ptr.data; | Object *ob_iter = link->ptr.data; | ||||
| bkr->result = bake( | bkr->result = bake( | ||||
| bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports, | bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports, &bkr->progress, | ||||
| bkr->pass_type, bkr->margin, bkr->save_mode, | bkr->pass_type, bkr->margin, bkr->save_mode, | ||||
| is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage, | is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage, | ||||
| bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, | bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, | ||||
| bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa, | bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa, | ||||
| bkr->uv_layer); | bkr->uv_layer); | ||||
| if (bkr->result == OPERATOR_CANCELLED) | if (bkr->result == OPERATOR_CANCELLED) | ||||
| return; | return; | ||||
| ▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | ||||
| bkr = MEM_callocN(sizeof(BakeAPIRender), "render bake"); | bkr = MEM_callocN(sizeof(BakeAPIRender), "render bake"); | ||||
| /* init bake render */ | /* init bake render */ | ||||
| bake_init_api_data(op, C, bkr); | bake_init_api_data(op, C, bkr); | ||||
| re = bkr->render; | re = bkr->render; | ||||
| /* setup new render */ | /* setup new render */ | ||||
| RE_test_break_cb(re, NULL, bake_break); | RE_test_break_cb(re, NULL, bake_break); | ||||
| RE_progress_cb(re, bkr, bake_progress_update); | RE_progress_cb(re, &bkr->progress, bake_progress_update); | ||||
| RE_display_update_cb(re, &bkr->progress, bake_display_update); | |||||
| /* setup job */ | /* setup job */ | ||||
| wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake", | wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake", | ||||
| WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE); | WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE); | ||||
| WM_jobs_customdata_set(wm_job, bkr, bake_freejob); | WM_jobs_customdata_set(wm_job, bkr, bake_freejob); | ||||
| WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ | WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ | ||||
| WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL); | WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL); | ||||
| ▲ Show 20 Lines • Show All 60 Lines • Show Last 20 Lines | |||||
I'd suggest dropping from the current patch.