diff options
Diffstat (limited to 'source/blender/render/intern/source/pipeline.c')
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 357 |
1 files changed, 240 insertions, 117 deletions
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 44c6a6f008f..e9dd3d36596 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -58,6 +58,7 @@ #include "BLI_blenlib.h" #include "BLI_rand.h" #include "BLI_threads.h" +#include "BLI_utildefines.h" #include "PIL_time.h" #include "IMB_imbuf.h" @@ -120,24 +121,24 @@ Render R; /* ********* alloc and free ******** */ +static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports, const char *name_override); static volatile int g_break= 0; -static int thread_break(void *unused) +static int thread_break(void *UNUSED(arg)) { return g_break; } /* default callbacks, set in each new render */ -static void result_nothing(void *unused, RenderResult *rr) {} -static void result_rcti_nothing(void *unused, RenderResult *rr, volatile struct rcti *rect) {} -static void stats_nothing(void *unused, RenderStats *rs) {} -static void float_nothing(void *unused, float val) {} -static void print_error(void *unused, char *str) {printf("ERROR: %s\n", str);} -static int default_break(void *unused) {return G.afbreek == 1;} +static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr)) {} +static void result_rcti_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) {} +static void stats_nothing(void *UNUSED(arg), RenderStats *UNUSED(rs)) {} +static void float_nothing(void *UNUSED(arg), float UNUSED(val)) {} +static void print_error(void *UNUSED(arg), const char *str) {printf("ERROR: %s\n", str);} +static int default_break(void *UNUSED(arg)) {return G.afbreek == 1;} -static void stats_background(void *unused, RenderStats *rs) +static void stats_background(void *UNUSED(arg), RenderStats *rs) { - char str[400], *spos= str; uintptr_t mem_in_use, mmap_in_use, peak_memory; float megs_used_memory, mmap_used_memory, megs_peak_memory; @@ -149,24 +150,24 @@ static void stats_background(void *unused, RenderStats *rs) mmap_used_memory= (mmap_in_use)/(1024.0*1024.0); megs_peak_memory = (peak_memory)/(1024.0*1024.0); - spos+= sprintf(spos, "Fra:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->cfra, + fprintf(stdout, "Fra:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->cfra, megs_used_memory, mmap_used_memory, megs_peak_memory); - + if(rs->curfield) - spos+= sprintf(spos, "Field %d ", rs->curfield); + fprintf(stdout, "Field %d ", rs->curfield); if(rs->curblur) - spos+= sprintf(spos, "Blur %d ", rs->curblur); - + fprintf(stdout, "Blur %d ", rs->curblur); + if(rs->infostr) { - spos+= sprintf(spos, "| %s", rs->infostr); + fprintf(stdout, "| %s", rs->infostr); } else { if(rs->tothalo) - spos+= sprintf(spos, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->tothalo, rs->totlamp); - else - spos+= sprintf(spos, "Sce: %s Ve:%d Fa:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->totlamp); + fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->tothalo, rs->totlamp); + else + fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->totlamp); } - printf("%s\n", str); + fflush(stdout); } void RE_FreeRenderResult(RenderResult *res) @@ -277,7 +278,7 @@ static void pop_render_result(Render *re) /* NOTE: OpenEXR only supports 32 chars for layer+pass names In blender we now use max 10 chars for pass, max 20 for layer */ -static char *get_pass_name(int passtype, int channel) +static const char *get_pass_name(int passtype, int channel) { if(passtype == SCE_PASS_COMBINED) { @@ -448,24 +449,29 @@ static int passtype_from_name(char *str) return 0; } -static void render_unique_exr_name(Render *re, char *str, int sample) +static void scene_unique_exr_name(Scene *scene, char *str, int sample) { char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE]; - BLI_strncpy(di, G.sce, FILE_MAX); + BLI_strncpy(di, G.main->name, FILE_MAX); BLI_splitdirstring(di, fi); if(sample==0) - sprintf(name, "%s_%s.exr", fi, re->scene->id.name+2); + sprintf(name, "%s_%s.exr", fi, scene->id.name+2); else - sprintf(name, "%s_%s%d.exr", fi, re->scene->id.name+2, sample); + sprintf(name, "%s_%s%d.exr", fi, scene->id.name+2, sample); BLI_make_file_string("/", str, btempdir, name); } +static void render_unique_exr_name(Render *re, char *str, int sample) +{ + scene_unique_exr_name(re->scene, str, sample); +} + static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) { - char *typestr= get_pass_name(passtype, 0); + const char *typestr= get_pass_name(passtype, 0); RenderPass *rpass= MEM_callocN(sizeof(RenderPass), typestr); int rectsize= rr->rectx*rr->recty*channels; @@ -802,7 +808,7 @@ static char *make_pass_name(RenderPass *rpass, int chan) /* filename already made absolute */ /* called from within UI, saves both rendered result as a file-read result */ -void RE_WriteRenderResult(RenderResult *rr, char *filename, int compress) +void RE_WriteRenderResult(RenderResult *rr, const char *filename, int compress) { RenderLayer *rl; RenderPass *rpass; @@ -861,7 +867,7 @@ static void *ml_addlayer_cb(void *base, char *str) BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); return rl; } -static void ml_addpass_cb(void *base, void *lay, char *str, float *rect, int totchan, char *chan_id) +static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id) { RenderLayer *rl= lay; RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass"); @@ -919,7 +925,7 @@ static void renderresult_add_names(RenderResult *rr) } /* called for reading temp files, and for external engines */ -static int read_render_result_from_file(char *filename, RenderResult *rr) +static int read_render_result_from_file(const char *filename, RenderResult *rr) { RenderLayer *rl; RenderPass *rpass; @@ -1158,6 +1164,18 @@ Render *RE_NewRender(const char *name) BLI_rw_mutex_init(&re->resultmutex); } + RE_InitRenderCB(re); + + /* init some variables */ + re->ycor= 1.0f; + + return re; +} + +/* called for new renders and when finishing rendering so + * we calways have valid callbacks on a render */ +void RE_InitRenderCB(Render *re) +{ /* set default empty callbacks */ re->display_init= result_nothing; re->display_clear= result_nothing; @@ -1171,11 +1189,6 @@ Render *RE_NewRender(const char *name) re->stats_draw= stats_nothing; /* clear callback handles */ re->dih= re->dch= re->ddh= re->sdh= re->prh= re->tbh= re->erh= NULL; - - /* init some variables */ - re->ycor= 1.0f; - - return re; } /* only call this while you know it will remove the link too */ @@ -1235,6 +1248,9 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * return; } + if((re->r.mode & (R_OSA))==0) + re->r.scemode &= ~R_FULL_SAMPLE; + #ifdef WITH_OPENEXR if(re->r.scemode & R_FULL_SAMPLE) re->r.scemode |= R_EXR_TILE_FILE; /* enable automatic */ @@ -1387,7 +1403,7 @@ void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle)) re->test_break= f; re->tbh= handle; } -void RE_error_cb(Render *re, void *handle, void (*f)(void *handle, char *str)) +void RE_error_cb(Render *re, void *handle, void (*f)(void *handle, const char *str)) { re->error= f; re->erh= handle; @@ -1398,7 +1414,7 @@ void RE_error_cb(Render *re, void *handle, void (*f)(void *handle, char *str)) /* object is considered fully prepared on correct time etc */ /* includes lights */ -void RE_AddObject(Render *re, Object *ob) +void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob)) { } @@ -1478,14 +1494,15 @@ static void *do_part_thread(void *pa_v) float panorama_pixel_rot(Render *re) { float psize, phi, xfac; + float borderfac= (float)(re->disprect.xmax - re->disprect.xmin) / (float)re->winx; /* size of 1 pixel mapped to viewplane coords */ - psize= (re->viewplane.xmax-re->viewplane.xmin)/(float)re->winx; + psize= (re->viewplane.xmax-re->viewplane.xmin)/(float)(re->winx); /* angle of a pixel */ phi= atan(psize/re->clipsta); /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */ - xfac= ((re->viewplane.xmax-re->viewplane.xmin))/(float)re->xparts; + xfac= borderfac*((re->viewplane.xmax-re->viewplane.xmin))/(float)re->xparts; xfac= atan(0.5f*xfac/re->clipsta); /* and how much the same viewplane angle is wrapped */ psize= 0.5f*phi*((float)re->partx); @@ -1518,8 +1535,8 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane) float phi= panorama_pixel_rot(re); R.panodxp= (re->winx - (best->disprect.xmin + best->disprect.xmax) )/2; - R.panodxv= ((viewplane->xmax-viewplane->xmin)*R.panodxp)/(float)R.winx; - + R.panodxv= ((viewplane->xmax-viewplane->xmin)*R.panodxp)/(float)(re->winx); + /* shift viewplane */ R.viewplane.xmin = viewplane->xmin + R.panodxv; R.viewplane.xmax = viewplane->xmax + R.panodxv; @@ -1537,8 +1554,10 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane) static RenderPart *find_next_part(Render *re, int minx) { RenderPart *pa, *best= NULL; - int centx=re->winx/2, centy=re->winy/2, tot=1; - int mindist, distx, disty; + + /* long long int's needed because of overflow [#24414] */ + long long int centx=re->winx/2, centy=re->winy/2, tot=1; + long long int mindist= (long long int)re->winx * (long long int)re->winy; /* find center of rendered parts, image center counts for 1 too */ for(pa= re->parts.first; pa; pa= pa->next) { @@ -1552,12 +1571,11 @@ static RenderPart *find_next_part(Render *re, int minx) centy/=tot; /* closest of the non-rendering parts */ - mindist= re->winx*re->winy; for(pa= re->parts.first; pa; pa= pa->next) { if(pa->ready==0 && pa->nr==0) { - distx= centx - (pa->disprect.xmin+pa->disprect.xmax)/2; - disty= centy - (pa->disprect.ymin+pa->disprect.ymax)/2; - distx= (int)sqrt(distx*distx + disty*disty); + long long int distx= centx - (pa->disprect.xmin+pa->disprect.xmax)/2; + long long int disty= centy - (pa->disprect.ymin+pa->disprect.ymax)/2; + distx= (long long int)sqrt(distx*distx + disty*disty); if(distx<mindist) { if(re->r.mode & R_PANORAMA) { if(pa->disprect.xmin==minx) { @@ -1964,7 +1982,7 @@ static void do_render_fields_3d(Render *re) /* first field, we have to call camera routine for correct aspect and subpixel offset */ RE_SetCamera(re, re->scene->camera); - if(re->r.mode & R_MBLUR) + if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0) do_render_blur_3d(re); else do_render_3d(re); @@ -1984,7 +2002,7 @@ static void do_render_fields_3d(Render *re) re->field_offs = 0.5f; } RE_SetCamera(re, re->scene->camera); - if(re->r.mode & R_MBLUR) + if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0) do_render_blur_3d(re); else do_render_3d(re); @@ -2032,7 +2050,7 @@ static void load_backbuffer(Render *re) char name[256]; strcpy(name, re->r.backbuf); - BLI_path_abs(name, G.sce); + BLI_path_abs(name, re->main->name); BLI_path_frame(name, re->r.cfra, 0); if(re->backbuf) { @@ -2041,7 +2059,7 @@ static void load_backbuffer(Render *re) BKE_image_signal(re->backbuf, NULL, IMA_SIGNAL_RELOAD); } - re->backbuf= BKE_add_image_file(name, re->r.cfra); + re->backbuf= BKE_add_image_file(name); ibuf= BKE_image_get_ibuf(re->backbuf, NULL); if(ibuf==NULL) { // error() doesnt work with render window open @@ -2074,7 +2092,7 @@ static void do_render_fields_blur_3d(Render *re) if(re->r.mode & R_FIELDS) do_render_fields_3d(re); - else if(re->r.mode & R_MBLUR) + else if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0) do_render_blur_3d(re); else do_render_3d(re); @@ -2188,6 +2206,7 @@ static void ntree_render_scenes(Render *re) { bNode *node; int cfra= re->scene->r.cfra; + int restore_scene= 0; if(re->scene->nodetree==NULL) return; @@ -2199,12 +2218,19 @@ static void ntree_render_scenes(Render *re) if(node->type==CMP_NODE_R_LAYERS) { if(node->id && node->id != (ID *)re->scene) { if(node->id->flag & LIB_DOIT) { - render_scene(re, (Scene *)node->id, cfra); + Scene *scene = (Scene*)node->id; + + render_scene(re, scene, cfra); + restore_scene= (scene != re->scene); node->id->flag &= ~LIB_DOIT; } } } } + + /* restore scene if we rendered another last */ + if(restore_scene) + set_scene_bg(re->main, re->scene); } /* helper call to detect if theres a composite with render-result node */ @@ -2226,7 +2252,7 @@ static int composite_needs_render(Scene *sce) } /* bad call... need to think over proper method still */ -static void render_composit_stats(void *unused, char *str) +static void render_composit_stats(void *UNUSED(arg), char *str) { R.i.infostr= str; R.stats_draw(R.sdh, &R.i); @@ -2312,10 +2338,17 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) BLI_rw_mutex_unlock(&re->resultmutex); } -void RE_MergeFullSample(Render *re, Scene *sce, bNodeTree *ntree) +/* called externally, via compositor */ +void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree) { Scene *scene; bNode *node; + + /* default start situation */ + G.afbreek= 0; + + re->main= bmain; + re->scene= sce; /* first call RE_ReadRenderResult on every renderlayer scene. this creates Render structs */ @@ -2451,8 +2484,9 @@ static void do_render_seq(Render * re) { static int recurs_depth = 0; struct ImBuf *ibuf; - RenderResult *rr = re->result; + RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */ int cfra = re->r.cfra; + SeqRenderData context; re->i.cfra= cfra; @@ -2463,9 +2497,15 @@ static void do_render_seq(Render * re) recurs_depth++; - ibuf= give_ibuf_seq(re->main, re->scene, rr->rectx, rr->recty, cfra, 0, 100.0); + context = seq_new_render_data(re->main, re->scene, + re->result->rectx, re->result->recty, + 100); + + ibuf = give_ibuf_seq(context, cfra, 0); recurs_depth--; + + rr = re->result; BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); @@ -2507,6 +2547,12 @@ static void do_render_seq(Render * re) /* if (R.rectz) freeN(R.rectz); */ /* R.rectz = BLI_dupallocN(ibuf->zbuf); */ /* } */ + + /* Same things as above, old rectf can hang around from previous render. */ + if(rr->rectf) { + MEM_freeN(rr->rectf); + rr->rectf= NULL; + } } if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ @@ -2528,6 +2574,9 @@ static void do_render_seq(Render * re) } BLI_rw_mutex_unlock(&re->resultmutex); + + /* just in case this flag went missing at some point */ + re->r.scemode |= R_DOSEQ; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -2573,61 +2622,108 @@ static void do_render_all_options(Render *re) } } -static int is_rendering_allowed(Render *re) +static int check_valid_camera(Scene *scene) +{ + int check_comp= 1; + + if (scene->camera == NULL) + scene->camera= scene_find_camera(scene); + + if(scene->r.scemode&R_DOSEQ) { + if(scene->ed) { + Sequence *seq= scene->ed->seqbase.first; + + check_comp= 0; + + while(seq) { + if(seq->type == SEQ_SCENE) { + if(!seq->scene_camera) { + if(!seq->scene->camera && !scene_find_camera(seq->scene)) { + if(seq->scene == scene) { + /* for current scene camera could be unneeded due to compisite nodes */ + check_comp= 1; + } else { + /* for other scenes camera is necessary */ + return 0; + } + } + } + } + + seq= seq->next; + } + } + } + + if(check_comp) { /* no sequencer or sequencer depends on compositor */ + if(scene->r.scemode&R_DOCOMP && scene->use_nodes) { + bNode *node= scene->nodetree->nodes.first; + + while(node) { + if(node->type == CMP_NODE_R_LAYERS) { + Scene *sce= node->id ? (Scene*)node->id : scene; + + if(!sce->camera && !scene_find_camera(sce)) { + /* all render layers nodes need camera */ + return 0; + } + } + + node= node->next; + } + } else return scene->camera != NULL; + } + + return 1; +} + +int RE_is_rendering_allowed(Scene *scene, void *erh, void (*error)(void *handle, const char *str)) { SceneRenderLayer *srl; /* forbidden combinations */ - if(re->r.mode & R_PANORAMA) { - if(re->r.mode & R_BORDER) { - re->error(re->erh, "No border supported for Panorama"); - return 0; - } - if(re->r.mode & R_ORTHO) { - re->error(re->erh, "No Ortho render possible for Panorama"); + if(scene->r.mode & R_PANORAMA) { + if(scene->r.mode & R_ORTHO) { + error(erh, "No Ortho render possible for Panorama"); return 0; } } - if(re->r.mode & R_BORDER) { - if(re->r.border.xmax <= re->r.border.xmin || - re->r.border.ymax <= re->r.border.ymin) { - re->error(re->erh, "No border area selected."); + if(scene->r.mode & R_BORDER) { + if(scene->r.border.xmax <= scene->r.border.xmin || + scene->r.border.ymax <= scene->r.border.ymin) { + error(erh, "No border area selected."); return 0; } } - if(re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) { + if(scene->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) { char str[FILE_MAX]; - render_unique_exr_name(re, str, 0); + scene_unique_exr_name(scene, str, 0); if (BLI_is_writable(str)==0) { - re->error(re->erh, "Can not save render buffers, check the temp default path"); + error(erh, "Can not save render buffers, check the temp default path"); return 0; } - /* no osa + fullsample won't work... */ - if(re->osa==0) - re->r.scemode &= ~R_FULL_SAMPLE; - /* no fullsample and edge */ - if((re->r.scemode & R_FULL_SAMPLE) && (re->r.mode & R_EDGE)) { - re->error(re->erh, "Full Sample doesn't support Edge Enhance"); + if((scene->r.scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) { + error(erh, "Full Sample doesn't support Edge Enhance"); return 0; } } else - re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ + scene->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ - if(re->r.scemode & R_DOCOMP) { - if(re->scene->use_nodes) { - bNodeTree *ntree= re->scene->nodetree; + if(scene->r.scemode & R_DOCOMP) { + if(scene->use_nodes) { + bNodeTree *ntree= scene->nodetree; bNode *node; if(ntree==NULL) { - re->error(re->erh, "No Nodetree in Scene"); + error(erh, "No Nodetree in Scene"); return 0; } @@ -2635,49 +2731,60 @@ static int is_rendering_allowed(Render *re) if(node->type==CMP_NODE_COMPOSITE) break; - if(node==NULL) { - re->error(re->erh, "No Render Output Node in Scene"); + error(erh, "No Render Output Node in Scene"); return 0; } + + if(scene->r.scemode & R_FULL_SAMPLE) { + if(composite_needs_render(scene)==0) { + error(erh, "Full Sample AA not supported without 3d rendering"); + return 0; + } + } } } /* check valid camera, without camera render is OK (compo, seq) */ - if(re->scene->camera==NULL) - re->scene->camera= scene_find_camera(re->scene); - - if(!(re->r.scemode & (R_DOSEQ|R_DOCOMP))) { - if(re->scene->camera==NULL) { - re->error(re->erh, "No camera"); - return 0; - } + if(!check_valid_camera(scene)) { + error(erh, "No camera"); + return 0; } /* layer flag tests */ - if(re->r.scemode & R_SINGLE_LAYER) { - srl= BLI_findlink(&re->scene->r.layers, re->r.actlay); + if(scene->r.scemode & R_SINGLE_LAYER) { + srl= BLI_findlink(&scene->r.layers, scene->r.actlay); /* force layer to be enabled */ srl->layflag &= ~SCE_LAY_DISABLE; } - for(srl= re->scene->r.layers.first; srl; srl= srl->next) + for(srl= scene->r.layers.first; srl; srl= srl->next) if(!(srl->layflag & SCE_LAY_DISABLE)) break; if(srl==NULL) { - re->error(re->erh, "All RenderLayers are disabled"); + error(erh, "All RenderLayers are disabled"); return 0; } /* renderer */ - if(!ELEM(re->r.renderer, R_INTERN, R_YAFRAY)) { - re->error(re->erh, "Unknown render engine set"); + if(!ELEM(scene->r.renderer, R_INTERN, R_YAFRAY)) { + error(erh, "Unknown render engine set"); return 0; } + return 1; } -static void update_physics_cache(Render *re, Scene *scene, int anim_init) +static void validate_render_settings(Render *re) +{ + if(re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) { + /* no osa + fullsample won't work... */ + if(re->r.osa==0) + re->r.scemode &= ~R_FULL_SAMPLE; + } else re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ +} + +static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)) { PTCacheBaker baker; @@ -2692,7 +2799,7 @@ static void update_physics_cache(Render *re, Scene *scene, int anim_init) baker.break_data = re->tbh; baker.progressbar = NULL; - BKE_ptcache_make_cache(&baker); + BKE_ptcache_bake(&baker); } /* evaluating scene options for general Blender render */ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, unsigned int lay, int anim, int anim_init) @@ -2753,10 +2860,9 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc /* initstate makes new result, have to send changed tags around */ ntreeCompositTagRender(re->scene); - - if(!is_rendering_allowed(re)) - return 0; - + + validate_render_settings(re); + re->display_init(re->dih, re->result); re->display_clear(re->dch, re->result); @@ -2764,7 +2870,7 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc } /* general Blender frame render call */ -void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, unsigned int lay, int frame) +void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, unsigned int lay, int frame, const short write_still) { /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */ G.rendering= 1; @@ -2774,13 +2880,27 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr if(render_initialize_from_main(re, bmain, scene, srl, lay, 0, 0)) { MEM_reset_peak_memory(); do_render_all_options(re); + + if(write_still && !G.afbreek) { + if(BKE_imtype_is_movie(scene->r.imtype)) { + /* operator checks this but incase its called from elsewhere */ + printf("Error: cant write single images with a movie format!\n"); + } + else { + char name[FILE_MAX]; + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, FALSE); + + /* reports only used for Movie */ + do_write_image_or_movie(re, scene, NULL, NULL, name); + } + } } - + /* UGLY WARNING */ G.rendering= 0; } -static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports) +static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports, const char *name_override) { char name[FILE_MAX]; RenderResult rres; @@ -2804,7 +2924,10 @@ static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, R printf("Append frame %d", scene->r.cfra); } else { - BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); + if(name_override) + BLI_strncpy(name, name_override, sizeof(name)); + else + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE); if(re->r.imtype==R_MULTILAYER) { if(re->result) { @@ -2813,7 +2936,7 @@ static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, R } } else { - ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0); + ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0); /* if not exists, BKE_write_ibuf makes one */ ibuf->rect= (unsigned int *)rres.rect32; @@ -2894,7 +3017,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, unsigned int lay, int do_render_all_options(re); if(re->test_break(re->tbh) == 0) { - if(!do_write_image_or_movie(re, scene, mh, reports)) + if(!do_write_image_or_movie(re, scene, mh, reports, NULL)) G.afbreek= 1; } } else { @@ -2931,7 +3054,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, unsigned int lay, int /* Touch/NoOverwrite options are only valid for image's */ if(BKE_imtype_is_movie(scene->r.imtype) == 0) { if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) - BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE); if(scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { printf("skipping existing frame \"%s\"\n", name); @@ -2949,7 +3072,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, unsigned int lay, int if(re->test_break(re->tbh) == 0) { if(!G.afbreek) - if(!do_write_image_or_movie(re, scene, mh, reports)) + if(!do_write_image_or_movie(re, scene, mh, reports, NULL)) G.afbreek= 1; } else @@ -3140,7 +3263,7 @@ int RE_engine_test_break(RenderEngine *engine) return re->test_break(re->tbh); } -void RE_engine_update_stats(RenderEngine *engine, char *stats, char *info) +void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) { Render *re= engine->re; @@ -3153,7 +3276,7 @@ void RE_engine_update_stats(RenderEngine *engine, char *stats, char *info) /* loads in image into a result, size must match * x/y offsets are only used on a partial copy when dimensions dont match */ -void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, char *filename) +void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y) { ImBuf *ibuf = IMB_loadiffname(filename, IB_rect); @@ -3164,15 +3287,15 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, char *file memcpy(layer->rectf, ibuf->rect_float, sizeof(float)*4*layer->rectx*layer->recty); } else { - if ((ibuf->x >= layer->rectx) && (ibuf->y >= layer->recty)) { + if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) { ImBuf *ibuf_clip; if(ibuf->rect_float==NULL) IMB_float_from_rect(ibuf); - ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat, 0); + ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat); if(ibuf_clip) { - IMB_rectcpy(ibuf_clip, ibuf, 0,0, 0,0, layer->rectx, layer->recty); + IMB_rectcpy(ibuf_clip, ibuf, 0,0, x,y, layer->rectx, layer->recty); memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float)*4*layer->rectx*layer->recty); IMB_freeImBuf(ibuf_clip); @@ -3193,7 +3316,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, char *file } } -void RE_result_load_from_file(RenderResult *result, ReportList *reports, char *filename) +void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename) { if(!read_render_result_from_file(filename, result)) { BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename); |