Blender Internal Render in viewport
authorTon Roosendaal <ton@blender.org>
Tue, 16 Apr 2013 17:39:20 +0000 (17:39 +0000)
committerTon Roosendaal <ton@blender.org>
Tue, 16 Apr 2013 17:39:20 +0000 (17:39 +0000)
Because of our release soon, feature has been added behind the Debug Menu.
CTRL+ALT+D and set it to -1. Or commandline --debug-value -1.

When debug set to -1, you can put the viewport to 'render' mode, just like
for Cycles. Notes for testers: (and please no bugs in tracker for this :)

- It renders without AA, MBlur, Panorama, Sequence, Composite
- Only active render layer gets rendered. Select another layer will re-render.
- But yes: it works for FreeStyle renders!
- Also does great for local view.
- BI is not well suited for incremental renders on view changes. This only
  works for non-raytrace scenes, or zoom in ortho or camera mode, or for
  Material changes. In most cases a full re-render is being done.
- ESC works to stop the preview render.
- Borders render as well. (CTRL+B)
- Force a refresh with arrow key left/right. A lot of settings don't trigger
  re-render yet.

Tech notes:

- FreeStyle is adding a lot of temp objects/meshes in the Main database. This
caused DepsGraph to trigger changes (and redraws). I've prepended the names
for these temp objects with char number 27 (ESC), and made these names be
ignored for tag update checking.

- Fixed some bugs that were noticable with such excessive re-renders, like
  for opening file window, quit during renders.

23 files changed:
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenlib/BLI_math_matrix.h
source/blender/blenlib/intern/math_matrix.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_render.h
source/blender/editors/render/render_intern.h
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_preview.c
source/blender/editors/render/render_update.c
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
source/blender/render/extern/include/RE_engine.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/envmap.h
source/blender/render/intern/include/initrender.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/render_result.c
source/blender/windowmanager/intern/wm_init_exit.c

index 3a531cf32aec15ccd25b234a0647bcc031cf5e71..0a4a15cca09dbe2ae1c5d1e256e45d94e7deeda2 100644 (file)
@@ -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;
                }
index 97cd6a6086247e60759705821b4addaddd6be3fe..9c5d3c5b93c6ebff9718084fb37a58477d8c5237 100644 (file)
@@ -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]);
index f116c9b844346b9ef16716bafa80d50b6a2e3ed6..1ec63f11c3d79f6b7cc86fa4896c43de5d4fe954 100644 (file)
@@ -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];
index fdbf2927464b66285778558ebd0d8cb8b6b56834..e7e8d6f3b996bb0cc4627152e3163a19ab05f715 100644 (file)
@@ -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);
                        }
index 39e2c28a61a6d04d2bb84e0896bbeac076431171..c1ddd9a629402819f7f09fd46bd894afa342cac6 100644 (file)
@@ -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
index 88c0060193394e6aa73040b90977e7c433650eb0..edd61bfc5c32362cdbf7072dca8deba2a5fe0091 100644 (file)
@@ -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);
index 6832cd5baa058736742ec3095e58b46c5255d353..f599fa1bde8cdf6d30eaed119cea7fcf13f745d5 100644 (file)
 #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"
 #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);
+       }
+}
index 0caf4a7351f70f134a6a409b9195c52097ec0ab2..7ef84b9d6eb51093d995cb0307ba750fc986b438 100644 (file)
@@ -93,7 +93,6 @@
 
 #include "RE_pipeline.h"
 
-
 #include "WM_api.h"
 #include "WM_types.h"
 
index f19ea08f381b0e87a7fc113455261ec4ce27c7bb..5653d14e5901c4aa9fb473395224a5c9777737c4 100644 (file)
@@ -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;
+       
+}
index 35344f2c5a40afc2fc6d084cae4e96c264c8aa53..2739d41a73d778319414806395f1a8f22c9e39db 100644 (file)
@@ -149,6 +149,8 @@ void ED_spacetypes_init(void)
                        type->dropboxes();
        }
        
+       /* register internal render callbacks */
+       ED_render_internal_init();
 }
 
 /* called in wm.c */
index b227d32d98788e5dda24876f8259d4aa417ad518..7552e09ebbd19ae834de9498668af4907d16077b 100644 (file)
@@ -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)
index 0bd990ad03ad598907d45cb8dc12f760e3f2b56f..dd75e4d0dd54d74f6599f45c736497afeaf498d4 100644 (file)
@@ -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;
 }
index cb35b0045f7561d47dceed76eea61ab5ba328213..7c1bc4d12d695275dc4742dcaabe0be21b1cd21a 100644 (file)
@@ -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;
index 961062964436d5381efba45b9c3167033cd2ffe8..9a8b1620f71745e8a68b3c064123053e196fd5e3 100644 (file)
@@ -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);
index a6c6d46e2e9049327a007fb2144f84a3e6d62dcf..79233a5d6256e0a6b2ce3a8413cbcb2862c108e4 100644 (file)
@@ -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__ */
 
index 73dc29c8feb5de6bf62ce80143ec9746b86709f5..69706ecc933e3722bc6ca5f874628390c13c494d 100644 (file)
@@ -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__ */
index f3cd60d80314253a030108713ecf214d80b68f29..eb2f1cb58266979ef17de1658d318f37625bcc55 100644 (file)
@@ -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 */
index 76179b25871d09990fabfc70771efd32d36fbd16..d83df4e78b08df548f16744db2c0996d80e5cb0b 100644 (file)
@@ -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);
index c5872c52e0f77f4a10abc55f5e212b092516a749..6423bfa94866cf9e3f74b2a03416fe93ffd30907 100644 (file)
@@ -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);
index 90528fddc85e0f6b8820577c752ae2bc599e675a..7ce5d9f72de4bd382ce9b12e0612916156be7526 100644 (file)
@@ -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;
 }
 
index da756447f96842801dfad30c0ecd19027aa8719d..7f2c3b5ad04e3155563abeebb51865ef28ac49c4 100644 (file)
@@ -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;
index 0fee1e41e32970d066933102fbd5f354f1f32d6c..f719e09769d32cd3f4fdef985ddef46b290b0ced 100644 (file)
@@ -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);
        
index 9810d1ecf728ad032b332b6b4a65c0a859130f94..31f2b412a7f0353cf7fa3a0e03e6960d0ad98163 100644 (file)
@@ -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();