diff options
23 files changed, 565 insertions, 51 deletions
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 3a531cf32ae..0a4a15cca09 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2341,7 +2341,8 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time) /* we tag based on first ID type character to avoid * looping over all ID's in case there are no tags */ - if (id && bmain->id_tag_update[id->name[0]]) { + /* XXX very weak... added check for '27' to ignore freestyle added objects */ + if (id && id->name[2] > 27 && bmain->id_tag_update[id->name[0]]) { updated = 1; break; } diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 97cd6a60862..9c5d3c5b93c 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -122,6 +122,8 @@ void mul_v4d_m4v4d(double r[4], float M[4][4], double v[4]); void transpose_m3(float R[3][3]); void transpose_m4(float R[4][4]); +int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit); + void normalize_m3(float R[3][3]); void normalize_m3_m3(float R[3][3], float A[3][3]); void normalize_m4(float R[4][4]); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index f116c9b8443..1ec63f11c3d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -722,6 +722,16 @@ void transpose_m4(float mat[4][4]) mat[3][2] = t; } +int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit) +{ + if (compare_v4v4(mat1[0], mat2[0], limit)) + if (compare_v4v4(mat1[1], mat2[1], limit)) + if (compare_v4v4(mat1[2], mat2[2], limit)) + if (compare_v4v4(mat1[3], mat2[3], limit)) + return 1; + return 0; +} + void orthogonalize_m3(float mat[3][3], int axis) { float size[3]; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fdbf2927464..e7e8d6f3b99 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6209,9 +6209,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc) v3d->properties_storage = NULL; v3d->defmaterial = NULL; - /* render can be quite heavy, set to wire on load */ + /* render can be quite heavy, set to solid on load */ if (v3d->drawtype == OB_RENDER) - v3d->drawtype = OB_WIRE; + v3d->drawtype = OB_SOLID; blo_do_versions_view3d_split_250(v3d, &sl->regionbase); } diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index 39e2c28a61a..c1ddd9a6294 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -38,6 +38,8 @@ struct Render; struct RenderInfo; struct Scene; struct ScrArea; +struct RegionView3D; +struct RenderEngine; /* render_ops.c */ @@ -85,4 +87,6 @@ void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *s void ED_render_clear_mtex_copybuf(void); +void ED_render_internal_init(void); + #endif diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index 88c00601933..edd61bfc5c3 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -83,6 +83,8 @@ void TEXTURE_OT_envmap_clear_all(struct wmOperatorType *ot); /* render_internal.c */ void RENDER_OT_render(struct wmOperatorType *ot); +void render_view3d(struct RenderEngine *engine, const struct bContext *C); +void render_view3d_draw(struct RenderEngine *engine, const struct bContext *C); /* render_opengl.c uses this */ void image_buffer_rect_update(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, volatile struct rcti *renrect); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 6832cd5baa0..f599fa1bde8 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -42,9 +42,11 @@ #include "BLF_translation.h" #include "DNA_scene_types.h" +#include "DNA_view3d_types.h" #include "BKE_blender.h" #include "BKE_context.h" +#include "BKE_freestyle.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_library.h" @@ -59,14 +61,23 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_screen.h" #include "ED_object.h" +#include "ED_render.h" +#include "ED_screen.h" +#include "ED_view3d.h" #include "RE_pipeline.h" +#include "RE_engine.h" + #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_extensions.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -681,3 +692,352 @@ void RENDER_OT_render(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } + +/* ************** preview for 3d viewport ***************** */ + +#define PR_UPDATE_VIEW 1 +#define PR_UPDATE_RENDERSIZE 2 +#define PR_UPDATE_MATERIAL 4 + +typedef struct RenderPreview { + /* from wmJob */ + void *owner; + short *stop, *do_update; + + Scene *scene; + ScrArea *sa; + ARegion *ar; + View3D *v3d; + RegionView3D *rv3d; + Main *bmain; + RenderEngine *engine; + + int keep_data; +} RenderPreview; + +static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rcti *disprect) +{ + /* copied code from view3d_draw.c */ + rctf viewborder; + int draw_border; + + if (rv3d->persp == RV3D_CAMOB) + draw_border = (scene->r.mode & R_BORDER) != 0; + else + draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + + if (draw_border) { + if (rv3d->persp == RV3D_CAMOB) { + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + + disprect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + disprect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + disprect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + disprect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + disprect->xmin = v3d->render_border.xmin * ar->winx; + disprect->xmax = v3d->render_border.xmax * ar->winx; + disprect->ymin = v3d->render_border.ymin * ar->winy; + disprect->ymax = v3d->render_border.ymax * ar->winy; + } + + return 1; + } + + BLI_rcti_init(disprect, 0, 0, 0, 0); + return 0; +} + +/* returns 1 if OK */ +static int render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d, rctf *viewplane, RenderEngine *engine, float *clipsta, float *clipend, int *ortho) +{ + + if (ar->winx < 4 || ar->winy < 4) return 0; + + *ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, viewplane, clipsta, clipend); + + engine->resolution_x = ar->winx; + engine->resolution_y = ar->winy; + + return 1; +} + +/* called by renderer, checks job value */ +static int render_view3d_break(void *rpv) +{ + RenderPreview *rp = rpv; + + if (G.is_break) + return 1; + + /* during render, rv3d->engine can get freed */ + if (rp->rv3d->render_engine == NULL) + *rp->stop = 1; + + return *(rp->stop); +} + +static void render_view3d_draw_update(void *rpv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) +{ + RenderPreview *rp = rpv; + + *(rp->do_update) = TRUE; +} + +static void render_view3d_renderinfo_cb(void *rjp, RenderStats *rs) +{ + RenderPreview *rp = rjp; + + /* during render, rv3d->engine can get freed */ + if (rp->rv3d->render_engine == NULL) + *rp->stop = 1; + else if (rp->engine->text) { + make_renderinfo_string(rs, rp->scene, rp->engine->text); + + /* make jobs timer to send notifier */ + *(rp->do_update) = TRUE; + } +} + + +static void render_view3d_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress)) +{ + RenderPreview *rp = customdata; + Render *re; + RenderStats *rstats; + RenderData rdata; + rctf viewplane; + rcti cliprct; + float clipsta, clipend; + int orth, restore = 0; + char name[32]; + + G.is_break = FALSE; + + if (0 == render_view3d_get_rects(rp->ar, rp->v3d, rp->rv3d, &viewplane, rp->engine, &clipsta, &clipend, &orth)) + return; + + rp->stop = stop; + rp->do_update = do_update; + +// printf("Enter previewrender\n"); + + /* ok, are we rendering all over? */ + sprintf(name, "View3dPreview %p", (void *)rp->ar); + re= rp->engine->re = RE_GetRender(name); + + if (rp->engine->re == NULL) { + + re = rp->engine->re= RE_NewRender(name); + + rp->keep_data = 0; + } + + /* set this always, rp is different for each job */ + RE_test_break_cb(re, rp, render_view3d_break); + RE_display_draw_cb(re, rp, render_view3d_draw_update); + RE_stats_draw_cb(re, rp, render_view3d_renderinfo_cb); + + rstats= RE_GetStats(re); + + if (rp->keep_data == 0 || rstats->convertdone == 0 || (rp->keep_data & PR_UPDATE_RENDERSIZE)) { + /* no osa, blur, seq, layers, etc for preview render */ + rdata = rp->scene->r; + rdata.mode &= ~(R_OSA | R_MBLUR | R_BORDER | R_PANORAMA); + rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE); + rdata.scemode |= R_PREVIEWBUTS; + + /* we do use layers, but only active */ + rdata.scemode |= R_SINGLE_LAYER; + + /* initalize always */ + if (render_view3d_disprect(rp->scene, rp->ar, rp->v3d, rp->rv3d, &cliprct)) { + rdata.mode |= R_BORDER; + RE_InitState(re, NULL, &rdata, NULL, rp->sa->winx, rp->sa->winy, &cliprct); + } + else + RE_InitState(re, NULL, &rdata, NULL, rp->sa->winx, rp->sa->winy, NULL); + } + + if (orth) + RE_SetOrtho(re, &viewplane, clipsta, clipend); + else + RE_SetWindow(re, &viewplane, clipsta, clipend); + + /* database free can crash on a empty Render... */ + if (rp->keep_data == 0 && rstats->convertdone) + RE_Database_Free(re); + + if (rstats->convertdone == 0) { + unsigned int lay = rp->scene->lay; + + /* allow localview render for objects with lights in normal layers */ + if (rp->v3d->lay & 0xFF000000) + lay |= rp->v3d->lay; + else lay = rp->v3d->lay; + + RE_SetView(re, rp->rv3d->viewmat); + + RE_Database_FromScene(re, rp->bmain, rp->scene, lay, 0); // 0= dont use camera view +// printf("dbase update\n"); + } + else { +// printf("dbase rotate\n"); + RE_DataBase_IncrementalView(re, rp->rv3d->viewmat, 0); + restore = 1; + } + + RE_DataBase_ApplyWindow(re); + + /* OK, can we enter render code? */ + if (rstats->convertdone) { + RE_TileProcessor(re); +// printf("tile processor\n"); + + if (restore) + RE_DataBase_IncrementalView(re, rp->rv3d->viewmat, 1); + + rp->engine->flag &= ~RE_ENGINE_DO_UPDATE; + } + +// printf("done\n\n"); +} + +static void render_view3d_free(void *customdata) +{ + RenderPreview *rp = customdata; + + MEM_freeN(rp); +} + +static void render_view3d_do(RenderEngine *engine, const bContext *C, int keep_data) +{ + wmJob *wm_job; + RenderPreview *rp; + Scene *scene = CTX_data_scene(C); + + if (CTX_wm_window(C) == NULL) { + engine->flag |= RE_ENGINE_DO_UPDATE; + + return; + } + + wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_region(C), "Render Preview", + WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW); + rp = MEM_callocN(sizeof(RenderPreview), "render preview"); + + /* customdata for preview thread */ + rp->scene = scene; + rp->engine = engine; + rp->sa = CTX_wm_area(C); + rp->ar = CTX_wm_region(C); + rp->v3d = rp->sa->spacedata.first; + rp->rv3d = CTX_wm_region_view3d(C); + rp->bmain = CTX_data_main(C); + rp->keep_data = keep_data; + + /* dont alloc in threads */ + if (engine->text == NULL) + engine->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext"); + + /* setup job */ + WM_jobs_customdata_set(wm_job, rp, render_view3d_free); + WM_jobs_timer(wm_job, 0.1, NC_SPACE|ND_SPACE_VIEW3D, NC_SPACE|ND_SPACE_VIEW3D); + WM_jobs_callbacks(wm_job, render_view3d_startjob, NULL, NULL, NULL); + + WM_jobs_start(CTX_wm_manager(C), wm_job); + + engine->flag &= ~RE_ENGINE_DO_UPDATE; + +} + +/* callback for render engine , on changes */ +void render_view3d(RenderEngine *engine, const bContext *C) +{ + render_view3d_do(engine, C, 0); +} + +static int render_view3d_changed(RenderEngine *engine, const bContext *C) +{ + ARegion *ar = CTX_wm_region(C); + Render *re; + int update = 0; + char name[32]; + + sprintf(name, "View3dPreview %p", (void *)ar); + re = RE_GetRender(name); + + if (re) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + rctf viewplane, viewplane1; + rcti disprect, disprect1; + float mat[4][4]; + float clipsta, clipend; + int orth; + + if (engine->update_flag == RE_ENGINE_UPDATE_MA) + update |= PR_UPDATE_MATERIAL; + engine->update_flag = 0; + + if (engine->resolution_x != ar->winx || engine->resolution_y != ar->winy) + update |= PR_UPDATE_RENDERSIZE; + + /* view updating fails on raytrace */ + RE_GetView(re, mat); + if (compare_m4m4(mat, rv3d->viewmat, 0.00001f) == 0) { + if ((scene->r.mode & R_RAYTRACE)==0) + update |= PR_UPDATE_VIEW; + else + engine->flag |= RE_ENGINE_DO_UPDATE; + } + + render_view3d_get_rects(ar, v3d, rv3d, &viewplane, engine, &clipsta, &clipend, &orth); + RE_GetViewPlane(re, &viewplane1, &disprect1); + + if (BLI_rctf_compare(&viewplane, &viewplane1, 0.00001f) == 0) + update |= PR_UPDATE_VIEW; + + render_view3d_disprect(scene, ar, v3d, rv3d, &disprect); + if (BLI_rcti_compare(&disprect, &disprect1) == 0) + update |= PR_UPDATE_RENDERSIZE; + + if (update) + engine->flag |= RE_ENGINE_DO_UPDATE; +// if (update) +// printf("changed ma %d res %d view %d\n", update & PR_UPDATE_MATERIAL, update & PR_UPDATE_RENDERSIZE, update & PR_UPDATE_VIEW); + + } + + return update; +} + +void render_view3d_draw(RenderEngine *engine, const bContext *C) +{ + Render *re = engine->re; + RenderResult rres; + int keep_data = render_view3d_changed(engine, C); + + if (engine->flag & RE_ENGINE_DO_UPDATE) + render_view3d_do(engine, C, keep_data); + + if (re == NULL) return; + + RE_AcquireResultImage(re, &rres); + RE_ReleaseResultImage(re); + + if (rres.rectf) { + unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"); + + RE_ResultGet32(re, (unsigned int *)rect_byte); + + glEnable(GL_BLEND); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, rect_byte); + glDisable(GL_BLEND); + + MEM_freeN(rect_byte); + } +} diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 0caf4a7351f..7ef84b9d6eb 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -93,7 +93,6 @@ #include "RE_pipeline.h" - #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index f19ea08f381..5653d14e590 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -116,6 +116,7 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) engine = rv3d->render_engine; if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) { + CTX_wm_screen_set(C, sc); CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); @@ -177,6 +178,32 @@ void ED_render_engine_changed(Main *bmain) * editor level updates when the ID changes. when these ID blocks are in * * the dependency graph, we can get rid of the manual dependency checks */ +static void render_engine_flag_changed(Main *bmain, int update_flag) +{ + bScreen *sc; + ScrArea *sa; + ARegion *ar; + + for (sc = bmain->screen.first; sc; sc = sc->id.next) { + for (sa = sc->areabase.first; sa; sa = sa->next) { + if (sa->spacetype != SPACE_VIEW3D) + continue; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + RegionView3D *rv3d; + + if (ar->regiontype != RGN_TYPE_WINDOW) + continue; + + rv3d = ar->regiondata; + if (rv3d->render_engine) + rv3d->render_engine->update_flag |= update_flag; + + } + } + } +} + static int mtex_use_tex(MTex **mtex, int tot, Tex *tex) { int a; @@ -472,6 +499,7 @@ void ED_render_id_flush_update(Main *bmain, ID *id) switch (GS(id->name)) { case ID_MA: material_changed(bmain, (Material *)id); + render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_MA); break; case ID_TE: texture_changed(bmain, (Tex *)id); @@ -487,9 +515,21 @@ void ED_render_id_flush_update(Main *bmain, ID *id) break; case ID_SCE: scene_changed(bmain, (Scene *)id); + render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER); break; default: + render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER); break; } + } + +void ED_render_internal_init(void) +{ + RenderEngineType *ret = RE_engines_find("BLENDER_RENDER"); + + ret->view_update = render_view3d; + ret->view_draw = render_view3d_draw; + +} diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 35344f2c5a4..2739d41a73d 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -149,6 +149,8 @@ void ED_spacetypes_init(void) type->dropboxes(); } + /* register internal render callbacks */ + ED_render_internal_init(); } /* called in wm.c */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index b227d32d987..7552e09ebbd 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -199,7 +199,8 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera sms.to_camera = true; /* restore view3d values in end */ } - if (C && U.smooth_viewtx) { + /* skip smooth viewing for render engine draw */ + if (C && U.smooth_viewtx && v3d->drawtype != OB_RENDER) { bool changed = false; /* zero means no difference */ if (oldcamera != camera) diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 0bd990ad03a..dd75e4d0dd5 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -478,9 +478,11 @@ Object *BlenderStrokeRenderer::NewMesh() const char name[MAX_ID_NAME]; unsigned int mesh_id = get_stroke_mesh_id(); - BLI_snprintf(name, MAX_ID_NAME, "0%08xOB", mesh_id); + /* XXX this is for later review, for now we start names with 27 (DEL) + to allow ignoring them in DAG_ids_check_recalc() */ + BLI_snprintf(name, MAX_ID_NAME, "%c0%08xOB", 27, mesh_id); ob = BKE_object_add_only_object(G.main, OB_MESH, name); - BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id); + BLI_snprintf(name, MAX_ID_NAME, "%c0%08xME", 27, mesh_id); ob->data = BKE_mesh_add(G.main, name); ob->lay = 1; @@ -491,7 +493,7 @@ Object *BlenderStrokeRenderer::NewMesh() const #else (void)base; #endif - ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + ob->recalc = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; return ob; } diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index cb35b0045f7..7c1bc4d12d6 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -66,6 +66,10 @@ struct Scene; #define RE_ENGINE_HIGHLIGHT_TILES 32 #define RE_ENGINE_USED_FOR_VIEWPORT 64 +/* RenderEngine.update_flag, used by internal now */ +#define RE_ENGINE_UPDATE_MA 1 +#define RE_ENGINE_UPDATE_OTHER 2 + extern ListBase R_engines; typedef struct RenderEngineType { @@ -92,7 +96,7 @@ typedef struct RenderEngine { RenderEngineType *type; void *py_instance; - int flag; + int flag, update_flag; struct Object *camera_override; int tile_x; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 96106296443..9a8b1620f71 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -197,12 +197,18 @@ void RE_SetPixelSize(struct Render *re, float pixsize); /* option to set viewmatrix before making dbase */ void RE_SetView(struct Render *re, float mat[4][4]); +/* get current view and window transform */ +void RE_GetView(struct Render *re, float mat[4][4]); +void RE_GetViewPlane(struct Render *re, rctf *viewplane, rcti *disprect); + /* make or free the dbase */ void RE_Database_FromScene(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, int use_camera_view); void RE_Database_Free(struct Render *re); /* project dbase again, when viewplane/perspective changed */ void RE_DataBase_ApplyWindow(struct Render *re); +/* rotate scene again, for incremental render */ +void RE_DataBase_IncrementalView(struct Render *re, float viewmat[4][4], int restore); /* override the scene setting for amount threads, commandline */ void RE_set_max_threads(int threads); diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h index a6c6d46e2e9..79233a5d625 100644 --- a/source/blender/render/intern/include/envmap.h +++ b/source/blender/render/intern/include/envmap.h @@ -48,6 +48,7 @@ struct ImagePool; void make_envmaps(struct Render *re); int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool); +void env_rotate_scene(struct Render *re, float mat[4][4], int mode); #endif /* __ENVMAP_H__ */ diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 73dc29c8feb..69706ecc933 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -40,9 +40,9 @@ struct Object; void free_sample_tables(Render *re); void make_sample_tables(Render *re); -void RE_parts_clamp(Render *re); void RE_parts_init(Render *re, int do_crop); void RE_parts_free(Render *re); +void RE_parts_clamp(Render *re); #endif /* __INITRENDER_H__ */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index f3cd60d8031..eb2f1cb5826 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -166,6 +166,7 @@ struct Render float grvec[3]; /* for world */ float imat[3][3]; /* copy of viewinv */ float viewmat[4][4], viewinv[4][4]; + float viewmat_orig[4][4]; /* for incremental render */ float winmat[4][4]; /* clippping */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 76179b25871..d83df4e78b0 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4851,10 +4851,11 @@ void RE_Database_Free(Render *re) /* free orco */ free_mesh_orco_hash(re); - end_render_materials(re->main); - end_render_textures(re); - - free_pointdensities(re); + if (re->main) { + end_render_materials(re->main); + end_render_textures(re); + free_pointdensities(re); + } free_camera_inside_volumes(re); @@ -5202,14 +5203,17 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view) { Scene *sce; + Object *camera; float mat[4][4]; float amb[3]; - Object *camera= RE_GetCamera(re); re->main= bmain; re->scene= scene; re->lay= lay; + /* scene needs to be set to get camera */ + camera= RE_GetCamera(re); + /* per second, per object, stats print this */ re->i.infostr= "Preparing Scene data"; re->i.cfra= scene->r.cfra; @@ -5246,6 +5250,9 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l camera->recalc= OB_RECALC_OB; /* force correct matrix for scaled cameras */ } + /* store for incremental render, viewmat rotates dbase */ + copy_m4_m4(re->viewmat_orig, re->viewmat); + init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ if (re->r.mode & R_RAYTRACE) { init_render_qmcsampler(re); @@ -5354,6 +5361,23 @@ void RE_DataBase_ApplyWindow(Render *re) project_renderdata(re, projectverto, 0, 0, 0); } +/* exported call to rotate render data again, when viewmat changed */ +void RE_DataBase_IncrementalView(Render *re, float viewmat[4][4], int restore) +{ + float oldviewinv[4][4], tmat[4][4]; + + invert_m4_m4(oldviewinv, re->viewmat_orig); + + /* we have to correct for the already rotated vertexcoords */ + mult_m4_m4m4(tmat, viewmat, oldviewinv); + + copy_m4_m4(re->viewmat, viewmat); + invert_m4_m4(re->viewinv, re->viewmat); + + env_rotate_scene(re, tmat, !restore); +} + + void RE_DataBase_GetView(Render *re, float mat[4][4]) { copy_m4_m4(mat, re->viewmat); diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index c5872c52e0f..6423bfa9486 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -246,10 +246,26 @@ static void envmap_transmatrix(float mat[4][4], int part) NULL, NULL, NULL, NULL, NULL, NULL); } +/* ------------------------------------------------------------------------- */ + +static void env_set_imats(Render *re) +{ + Base *base; + float mat[4][4]; + + base = re->scene->base.first; + while (base) { + mult_m4_m4m4(mat, re->viewmat, base->object->obmat); + invert_m4_m4(base->object->imat, mat); + + base = base->next; + } + +} /* ------------------------------------------------------------------------- */ -static void env_rotate_scene(Render *re, float mat[4][4], int mode) +void env_rotate_scene(Render *re, float mat[4][4], int mode) { GroupObject *go; ObjectRen *obr; @@ -328,6 +344,10 @@ static void env_rotate_scene(Render *re, float mat[4][4], int mode) } } + if (mode) { + init_render_world(re); + env_set_imats(re); + } } /* ------------------------------------------------------------------------- */ @@ -395,23 +415,6 @@ static void env_showobjects(Render *re) /* ------------------------------------------------------------------------- */ -static void env_set_imats(Render *re) -{ - Base *base; - float mat[4][4]; - - base = re->scene->base.first; - while (base) { - mult_m4_m4m4(mat, re->viewmat, base->object->obmat); - invert_m4_m4(base->object->imat, mat); - - base = base->next; - } - -} - -/* ------------------------------------------------------------------------- */ - static void render_envmap(Render *re, EnvMap *env) { /* only the cubemap and planar map is implemented */ @@ -454,11 +457,9 @@ static void render_envmap(Render *re, EnvMap *env) invert_m4_m4(env->imat, tmat); env_rotate_scene(envre, tmat, 1); - init_render_world(envre); project_renderdata(envre, projectverto, 0, 0, 1); env_layerflags(envre, env->notlay); env_hideobject(envre, env->object); - env_set_imats(envre); if (re->test_break(re->tbh) == 0) { RE_TileProcessor(envre); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 90528fddc85..7ce5d9f72de 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -116,6 +116,18 @@ RenderEngineType *RE_engines_find(const char *idname) if (!type) type = &internal_render_type; + /* XXX Hack to make this a debug-only option, remove section to make it available default */ + if (type == &internal_render_type) { + static RenderEngineType rtype; + + if (type->view_update == NULL) + rtype = internal_render_type; + else if (G.debug_value != -1) { + type = &rtype; + } + } + /* XXX end hack */ + return type; } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index da756447f96..7f2c3b5ad04 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -328,6 +328,9 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr) rr->have_combined = (re->result->rectf != NULL); rr->layers = re->result->layers; + + rr->xof = re->disprect.xmin; + rr->yof = re->disprect.ymin; } } } @@ -402,7 +405,10 @@ void RE_FreeRender(Render *re) BLI_rw_mutex_end(&re->resultmutex); - free_renderdata_tables(re); + /* main dbase can already be invalid now, some database-free code checks it */ + re->main = NULL; + + RE_Database_Free(re); /* view render can still have full database */ free_sample_tables(re); render_result_free(re->result); @@ -564,13 +570,9 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->r.scemode & R_PREVIEWBUTS) { - if (re->result && re->result->rectx == re->rectx && re->result->recty == re->recty) { - /* pass */ - } - else { - render_result_free(re->result); - re->result = NULL; - } + /* always fresh, freestyle layers need it */ + render_result_free(re->result); + re->result = NULL; } else { @@ -580,6 +582,9 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * re->result->rectx = re->rectx; re->result->recty = re->recty; } + + /* ensure renderdatabase can use part settings correct */ + RE_parts_clamp(re); BLI_rw_mutex_unlock(&re->resultmutex); @@ -627,6 +632,22 @@ void RE_SetView(Render *re, float mat[4][4]) invert_m4_m4(re->viewinv, re->viewmat); } +void RE_GetViewPlane(Render *re, rctf *viewplane, rcti *disprect) +{ + *viewplane = re->viewplane; + + /* make disprect zero when no border render, is needed to detect changes in 3d view render */ + if (re->r.mode & R_BORDER) + *disprect = re->disprect; + else + BLI_rcti_init(disprect, 0, 0, 0, 0); +} + +void RE_GetView(Render *re, float mat[4][4]) +{ + copy_m4_m4(mat, re->viewmat); +} + /* image and movie output has to move to either imbuf or kernel */ void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)) { @@ -1035,18 +1056,37 @@ static void threaded_tile_processor(Render *re) re->viewplane = viewplane; /* restore viewplane, modified by pano render */ } +#ifdef WITH_FREESTYLE +static void add_freestyle(Render *re); +static void free_all_freestyle_renders(Scene *scene); +#endif + /* currently only called by preview renders and envmap */ void RE_TileProcessor(Render *re) { threaded_tile_processor(re); -} - -/* ************ This part uses API, for rendering Blender scenes ********** */ + + re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime; + re->stats_draw(re->sdh, &re->i); #ifdef WITH_FREESTYLE -static void add_freestyle(Render *re); + /* Freestyle */ + if (re->r.mode & R_EDGE_FRS) { + if (!re->test_break(re->tbh)) { + add_freestyle(re); + + free_all_freestyle_renders(re->scene); + + re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime; + re->stats_draw(re->sdh, &re->i); + } + } #endif +} + +/* ************ This part uses API, for rendering Blender scenes ********** */ + static void do_render_3d(Render *re) { float cfra; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 0fee1e41e32..f719e09769d 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -569,6 +569,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf } /* border render; calculate offset for use in compositor. compo is centralized coords */ + /* XXX obsolete? I now use it for drawing border render offset (ton) */ rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 9810d1ecf72..31f2b412a7f 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -438,6 +438,10 @@ void WM_exit_ext(bContext *C, const short do_python) BKE_mball_cubeTable_free(); + /* render code might still access databases */ + RE_FreeAllRender(); + RE_engines_exit(); + ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */ if (C && wm) @@ -468,9 +472,6 @@ void WM_exit_ext(bContext *C, const short do_python) ANIM_keyingset_infos_exit(); - RE_FreeAllRender(); - RE_engines_exit(); - // free_txt_data(); |