示例#1
0
static int screencast_exec(bContext *C, wmOperator *op)
{
    wmWindowManager *wm = CTX_wm_manager(C);
    wmWindow *win = CTX_wm_window(C);
    bScreen *screen = CTX_wm_screen(C);
    wmJob *wm_job;
    ScreenshotJob *sj;

    /* if called again, stop the running job */
    if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
        WM_jobs_stop(wm, screen, screenshot_startjob);

    wm_job = WM_jobs_get(wm, win, screen, "Screencast", 0, WM_JOB_TYPE_SCREENCAST);
    sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job");

    /* setup sj */
    if (RNA_boolean_get(op->ptr, "full")) {
        sj->x = 0;
        sj->y = 0;
        sj->dumpsx = WM_window_pixels_x(win);
        sj->dumpsy = WM_window_pixels_y(win);
    }
    else {
        ScrArea *curarea = CTX_wm_area(C);
        sj->x = curarea->totrct.xmin;
        sj->y = curarea->totrct.ymin;
        sj->dumpsx = curarea->totrct.xmax - sj->x;
        sj->dumpsy = curarea->totrct.ymax - sj->y;
    }
    sj->bmain = CTX_data_main(C);
    sj->scene = CTX_data_scene(C);
    sj->wm = wm;

    BKE_reports_init(&sj->reports, RPT_PRINT);

    /* setup job */
    WM_jobs_customdata_set(wm_job, sj, screenshot_freejob);
    WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST);
    WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob);

    WM_jobs_start(sj->wm, wm_job);

    screencast_cursor_toggle(sj->wm, 1);

    WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen);

    return OPERATOR_FINISHED;
}
void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method)
{
	Object *ob = CTX_data_active_object(C);
	wmJob *wm_job;
	ShaderPreview *sp;
	Scene *scene = CTX_data_scene(C);
	short id_type = GS(id->name);
	bool use_new_shading = BKE_scene_use_new_shading_nodes(scene);

	/* Only texture node preview is supported with Cycles. */
	if (use_new_shading && method == PR_NODE_RENDER && id_type != ID_TE) {
		return;
	}

	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview",
	                    WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
	sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");

	/* customdata for preview thread */
	sp->scene = scene;
	sp->owner = owner;
	sp->sizex = sizex;
	sp->sizey = sizey;
	sp->pr_method = method;
	sp->id = id;
	sp->parent = parent;
	sp->slot = slot;

	/* hardcoded preview .blend for cycles/internal, this should be solved
	 * once with custom preview .blend path for external engines */
	if ((method != PR_NODE_RENDER) && id_type != ID_TE && use_new_shading) {
		sp->pr_main = G_pr_main_cycles;
	}
	else {
		sp->pr_main = G_pr_main;
	}

	if (ob && ob->totcol) copy_v4_v4(sp->col, ob->col);
	else sp->col[0] = sp->col[1] = sp->col[2] = sp->col[3] = 1.0f;
	
	/* setup job */
	WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
	WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
	WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
	
	WM_jobs_start(CTX_wm_manager(C), wm_job);
}
示例#3
0
static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
	wmJob *wm_job;
	BakeAPIRender *bkr;
	Render *re;
	Scene *scene = CTX_data_scene(C);

	bake_set_props(op, scene);

	/* only one render job at a time */
	if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
		return OPERATOR_CANCELLED;

	bkr = MEM_mallocN(sizeof(BakeAPIRender), "render bake");

	/* init bake render */
	bake_init_api_data(op, C, bkr);
	re = bkr->render;

	/* setup new render */
	RE_test_break_cb(re, NULL, bake_break);
	RE_progress_cb(re, bkr, bake_progress_update);

	/* setup job */
	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake",
	                     WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE);
	WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
	WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
	WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);

	G.is_break = false;
	G.is_rendering = true;

	WM_jobs_start(CTX_wm_manager(C), wm_job);

	WM_cursor_wait(0);

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
	return OPERATOR_RUNNING_MODAL;
}
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;
	copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
	
	/* 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;

}
示例#5
0
void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
{
	/* first, get the preview job, if it exists */
	wmJob *wm_job;
	PreviewJob *pj;
	ScrArea *sa = CTX_wm_area(C);
	PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
	                     WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);

	pj = WM_jobs_customdata_get(wm_job);

	if (!pj) {
		pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");

		pj->mutex = BLI_mutex_alloc();
		pj->scene = CTX_data_scene(C);

		WM_jobs_customdata_set(wm_job, pj, free_preview_job);
		WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
		WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
	}

	/* attempt to lock mutex of job here */

	audiojob->sound = seq->sound;

	BLI_mutex_lock(pj->mutex);
	BLI_addtail(&pj->previews, audiojob);
	pj->total++;
	BLI_mutex_unlock(pj->mutex);

	if (!WM_jobs_is_running(wm_job)) {
		G.is_break = false;
		WM_jobs_start(CTX_wm_manager(C), wm_job);
	}

	ED_area_tag_redraw(sa);
}
示例#6
0
static void render_view3d_do(RenderEngine *engine, const bContext *C)
{
	wmJob *wm_job;
	RenderPreview *rp;
	Scene *scene = CTX_data_scene(C);
	
	if (CTX_wm_window(C) == NULL)
		return;
	if (!render_view3d_flag_changed(engine, C))
		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");
	rp->job = wm_job;

	/* 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->resolution_divider = START_RESOLUTION_DIVIDER;
	copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
	
	/* clear info text */
	engine->text[0] = '\0';
	
	/* 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;
}
示例#7
0
文件: clip_ops.c 项目: pawkoz/dyplom
static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
{
	wmJob *wm_job;
	ProxyJob *pj;
	Scene *scene = CTX_data_scene(C);
	ScrArea *sa = CTX_wm_area(C);
	SpaceClip *sc = CTX_wm_space_clip(C);
	MovieClip *clip = ED_space_clip_get_clip(sc);

	if ((clip->flag & MCLIP_USE_PROXY) == 0)
		return OPERATOR_CANCELLED;

	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
	                     WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_BUILD_PROXY);

	pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
	pj->scene = scene;
	pj->main = CTX_data_main(C);
	pj->clip = clip;
	pj->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;

	if (clip->anim) {
		pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag,
		                                                   clip->proxy.build_size_flag, clip->proxy.quality,
		                                                   true, NULL);
	}

	WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
	WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
	WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);

	G.is_break = false;
	WM_jobs_start(CTX_wm_manager(C), wm_job);

	ED_area_tag_redraw(sa);

	return OPERATOR_FINISHED;
}
示例#8
0
void thumbnails_start(FileList *filelist, const bContext *C)
{
	wmJob *wm_job;
	ThumbnailJob *tj;
	int idx;

	/* prepare job data */
	tj = MEM_callocN(sizeof(*tj), __func__);
	tj->filelist = filelist;
	for (idx = 0; idx < filelist->numfiles; idx++) {
		if (!filelist->filelist[idx].path) {
			continue;
		}
		if (!filelist->filelist[idx].image) {
			if (filelist->filelist[idx].flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
			                                     FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))
			{
				FileImage *limg = MEM_callocN(sizeof(*limg), __func__);
				BLI_strncpy(limg->path, filelist->filelist[idx].path, sizeof(limg->path));
				limg->index = idx;
				limg->flags = filelist->filelist[idx].flags;
				BLI_addtail(&tj->loadimages, limg);
			}
		}
	}

	BKE_reports_init(&tj->reports, RPT_PRINT);

	/* setup job */
	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), filelist, "Thumbnails",
	                     0, WM_JOB_TYPE_FILESEL_THUMBNAIL);
	WM_jobs_customdata_set(wm_job, tj, thumbnails_free);
	WM_jobs_timer(wm_job, 0.5, NC_WINDOW, NC_WINDOW);
	WM_jobs_callbacks(wm_job, thumbnails_startjob, NULL, thumbnails_update, thumbnails_endjob);

	/* start the job */
	WM_jobs_start(CTX_wm_manager(C), wm_job);
}
示例#9
0
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
int get_material(Main *bmain, bContext *C, Scene *scene, bNodeTree *ntree, const char *address, int32_t mat_id)
{
    /* Setup job */
    wmJob           *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Get LDB Material", WM_JOB_PROGRESS, WM_JOB_TYPE_RENDER);
    GetMaterialJob  *mj     = MEM_callocN(sizeof(GetMaterialJob), "get LDB mat job");

    mj->C       = C;
    mj->bmain   = bmain;
    mj->ntree   = ntree;
    mj->mat_id  = mat_id;
    strcpy(mj->address, address);

    WM_jobs_customdata_set(wm_job, mj, get_material_data_free);
    WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_RENDER_RESULT, 0);
    WM_jobs_callbacks(wm_job, get_material_startjob, NULL, NULL, get_material_endjob);

    WM_jobs_start(CTX_wm_manager(C), wm_job);

    WM_cursor_wait(0);
    WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);

    return 1;
} /* get_material() */
示例#10
0
static int screencast_exec(bContext *C, wmOperator *op)
{
	bScreen *screen = CTX_wm_screen(C);
	wmJob *steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen, "Screencast", 0);
	ScreenshotJob *sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job");

	/* setup sj */
	if (RNA_boolean_get(op->ptr, "full")) {
		wmWindow *win = CTX_wm_window(C);
		sj->x = 0;
		sj->y = 0;
		sj->dumpsx = win->sizex;
		sj->dumpsy = win->sizey;
	} 
	else {
		ScrArea *curarea = CTX_wm_area(C);
		sj->x = curarea->totrct.xmin;
		sj->y = curarea->totrct.ymin;
		sj->dumpsx = curarea->totrct.xmax - sj->x;
		sj->dumpsy = curarea->totrct.ymax - sj->y;
	}
	sj->bmain = CTX_data_main(C);
	sj->scene = CTX_data_scene(C);

	BKE_reports_init(&sj->reports, RPT_PRINT);

	/* setup job */
	WM_jobs_customdata(steve, sj, screenshot_freejob);
	WM_jobs_timer(steve, 0.1, 0, NC_SCREEN | ND_SCREENCAST);
	WM_jobs_callbacks(steve, screenshot_startjob, NULL, screenshot_updatejob, NULL);
	
	WM_jobs_start(CTX_wm_manager(C), steve);
	
	WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen);
	
	return OPERATOR_FINISHED;
}
示例#11
0
int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain)
{
	Scene *scene= CTX_data_scene(C);
	int i;
	FluidsimSettings *domainSettings;

	char debugStrBuffer[256];
	
	int gridlevels = 0;
	const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
	const char *suffixConfig = FLUID_SUFFIX_CONFIG;
	const char *suffixSurface = FLUID_SUFFIX_SURFACE;

	char targetDir[FILE_MAXDIR+FILE_MAXFILE];  // store & modify output settings
	char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
	int  outStringsChanged = 0;             // modified? copy back before baking

	float domainMat[4][4];
	float invDomMat[4][4];

	int noFrames;
	int origFrame = scene->r.cfra;
	
	FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels), "fluid domain animation channels");
	ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
	FluidsimModifierData *fluidmd = NULL;
	Mesh *mesh = NULL;
	
	wmJob *steve;
	FluidBakeJob *fb;
	elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings");
	
	steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation", WM_JOB_PROGRESS);
	fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
	
	if(getenv(strEnvName)) {
		int dlevel = atoi(getenv(strEnvName));
		elbeemSetDebugLevel(dlevel);
		snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); 
		elbeemDebugOut(debugStrBuffer);
	}
	
	/* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */;
	noFrames = scene->r.efra - 0;
	if(noFrames<=0) {
		BKE_report(reports, RPT_ERROR, "No frames to export - check your animation range settings.");
		fluidbake_free_data(channels, fobjects, fsset, fb);
		return 0;
	}
	
	/* check scene for sane object/modifier settings */
	if (!fluid_validate_scene(reports, scene, fsDomain)) {
		fluidbake_free_data(channels, fobjects, fsset, fb);
		return 0;
	}
	
	/* these both have to be valid, otherwise we wouldnt be here */
	fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
	domainSettings = fluidmd->fss;
	mesh = fsDomain->data;
	
	domainSettings->bakeStart = 1;
	domainSettings->bakeEnd = scene->r.efra;
	
	// calculate bounding box
	fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
	
	// reset last valid frame
	domainSettings->lastgoodframe = -1;
	
	/* rough check of settings... */
	if(domainSettings->previewresxyz > domainSettings->resolutionxyz) {
		snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz ,  domainSettings->resolutionxyz); 
		elbeemDebugOut(debugStrBuffer);
		domainSettings->previewresxyz = domainSettings->resolutionxyz;
	}
	// set adaptive coarsening according to resolutionxyz
	// this should do as an approximation, with in/outflow
	// doing this more accurate would be overkill
	// perhaps add manual setting?
	if(domainSettings->maxRefine <0) {
		if(domainSettings->resolutionxyz>128) {
			gridlevels = 2;
		} else
		if(domainSettings->resolutionxyz>64) {
			gridlevels = 1;
		} else {
			gridlevels = 0;
		}
	} else {
		gridlevels = domainSettings->maxRefine;
	}
	snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); 
	elbeemDebugOut(debugStrBuffer);
	
	
	
	/* ******** prepare output file paths ******** */
	outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer);
	channels->length = scene->r.efra;
	channels->aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
	
	/* ******** initialise and allocate animation channels ******** */
	fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);

	/* reset to original current frame */
	scene->r.cfra = origFrame;
	ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
	
	
	/* ---- XXX: No Time animation curve for now, leaving this code here for reference 
	 
	{ int timeIcu[1] = { FLUIDSIM_TIME };
		float timeDef[1] = { 1. };

		// time channel is a bit special, init by hand...
		timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex");
		for(i=0; i<=scene->r.efra; i++) {
			timeAtIndex[i] = (float)(i-startFrame);
		}
		fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
		// time channel is a multiplicator for 
		if(channelDomainTime) {
			for(i=0; i<allchannelSize; i++) { 
				channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0]; 
				if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.;
			}
		}
		timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe");
		timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1
		if(channelDomainTime) {
			for(i=2; i<=allchannelSize; i++) {
				timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0];
			}
		fsset->} else {
			for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
		}

	} // domain channel init
	*/
		
	/* ******** init domain object's matrix ******** */
	copy_m4_m4(domainMat, fsDomain->obmat);
	if(!invert_m4_m4(invDomMat, domainMat)) {
		snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); 
		elbeemDebugOut(debugStrBuffer);
		BKE_report(reports, RPT_ERROR, "Invalid object matrix."); 

		fluidbake_free_data(channels, fobjects, fsset, fb);
		return 0;
	}

	/* ********  start writing / exporting ******** */
	// use .tmp, dont overwrite/delete original file
	BLI_snprintf(targetFile, sizeof(targetFile), "%s%s.tmp", targetDir, suffixConfig);
	
	// make sure these directories exist as well
	if(outStringsChanged) {
		BLI_make_existing_file(targetFile);
	}

	/* ******** export domain to elbeem ******** */
	elbeemResetSettings(fsset);
	fsset->version = 1;

	// setup global settings
	copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
	copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
	
	// simulate with 50^3
	fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
	fsset->previewresxyz = (int)domainSettings->previewresxyz;

	fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
	fsset->viscosity = get_fluid_viscosity(domainSettings);
	get_fluid_gravity(fsset->gravity, scene, domainSettings);

	// simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
	fsset->animStart = domainSettings->animStart;
	fsset->aniFrameTime = channels->aniFrameTime;
	fsset->noOfFrames = noFrames; // is otherwise subtracted in parser

	BLI_snprintf(targetFile, sizeof(targetFile), "%s%s", targetDir, suffixSurface);

	// defaults for compressibility and adaptive grids
	fsset->gstar = domainSettings->gstar;
	fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
	fsset->generateParticles = domainSettings->generateParticles; 
	fsset->numTracerParticles = domainSettings->generateTracers; 
	fsset->surfaceSmoothing = domainSettings->surfaceSmoothing; 
	fsset->surfaceSubdivs = domainSettings->surfaceSubdivs; 
	fsset->farFieldSize = domainSettings->farFieldSize; 
	BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath));

	// domain channels
	fsset->channelSizeFrameTime = 
	fsset->channelSizeViscosity = 
	fsset->channelSizeGravity = channels->length;
	fsset->channelFrameTime = channels->DomainTime;
	fsset->channelViscosity = channels->DomainViscosity;
	fsset->channelGravity = channels->DomainGravity;
	
	fsset->runsimCallback = &runSimulationCallback;
	fsset->runsimUserData = fb;

	if (domainSettings->typeFlags & OB_FSBND_NOSLIP)		fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
	else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP)	fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
	else if (domainSettings->typeFlags&OB_FSBND_FREESLIP)	fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
	fsset->domainobsPartslip = domainSettings->partSlipValue;
	fsset->generateVertexVectors = (domainSettings->domainNovecgen==0);

	// init blender domain transform matrix
	{ int j; 
	for(i=0; i<4; i++) {
		for(j=0; j<4; j++) {
			fsset->surfaceTrafo[i*4+j] = invDomMat[j][i];
		}
	} }

	/* ******** init solver with settings ******** */
	elbeemInit();
	elbeemAddDomain(fsset);
	
	/* ******** export all fluid objects to elbeem ******** */
	export_fluid_objects(fobjects, scene, channels->length);
	
	/* custom data for fluid bake job */
	fb->settings = fsset;
	
	/* setup job */
	WM_jobs_customdata(steve, fb, fluidbake_free);
	WM_jobs_timer(steve, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
	WM_jobs_callbacks(steve, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
	
	WM_jobs_start(CTX_wm_manager(C), steve);

	/* ******** free stored animation data ******** */
	fluidbake_free_data(channels, fobjects, NULL, NULL);

	// elbeemFree();
	return 1;
}
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene = CTX_data_scene(C);
	SceneRenderLayer *srl = NULL;
	View3D *v3d = CTX_wm_view3d(C);
	Render *re;
	wmJob *wm_job;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const short is_animation = RNA_boolean_get(op->ptr, "animation");
	const short is_write_still = RNA_boolean_get(op->ptr, "write_still");
	struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	const char *name;
	Object *active_object = CTX_data_active_object(C);
	
	/* only one render job at a time */
	if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
		return OPERATOR_CANCELLED;

	if (!RE_is_rendering_allowed(scene, camera_override, op->reports)) {
		return OPERATOR_CANCELLED;
	}

	if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
		return OPERATOR_CANCELLED;
	}
	
	/* stop all running jobs, except screen one. currently previews frustrate Render */
	WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));

	/* get main */
	if (G.debug_value == 101) {
		/* thread-safety experiment, copy main from the undo buffer */
		mainp = BKE_undo_get_main(&scene);
	}
	else
		mainp = CTX_data_main(C);

	/* cancel animation playback */
	if (ED_screen_animation_playing(CTX_wm_manager(C)))
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush multires changes (for sculpt) */
	multires_force_render_update(active_object);

	/* flush changes from dynamic topology sculpt */
	sculptsession_bm_to_me_for_render(active_object);

	/* cleanup sequencer caches before starting user triggered render.
	 * otherwise, invalidated cache entries can make their way into
	 * the output rendering. We can't put that into RE_BlenderFrame,
	 * since sequence rendering can call that recursively... (peter) */
	BKE_sequencer_cache_cleanup();

	/* get editmode results */
	ED_object_editmode_load(CTX_data_edit_object(C));

	// store spare
	// get view3d layer, local layer, make this nice api call to render
	// store spare

	/* ensure at least 1 area shows result */
	render_view_open(C, event->x, event->y);

	jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
	
	/* custom scene and single layer re-render */
	screen_render_scene_layer_set(op, mainp, &scene, &srl);

	if (RNA_struct_property_is_set(op->ptr, "layer"))
		jobflag |= WM_JOB_SUSPEND;

	/* job custom data */
	rj = MEM_callocN(sizeof(RenderJob), "render job");
	rj->main = mainp;
	rj->scene = scene;
	rj->win = CTX_wm_window(C);
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay = scene->lay;
	rj->anim = is_animation;
	rj->write_still = is_write_still && !is_animation;
	rj->iuser.scene = scene;
	rj->iuser.ok = 1;
	rj->reports = op->reports;

	if (v3d) {
		rj->lay = v3d->lay;

		if (v3d->localvd)
			rj->lay |= v3d->localvd->lay;
	}

	/* setup job */
	if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
	else name = "Render";

	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
	WM_jobs_customdata_set(wm_job, rj, render_freejob);
	WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);

	/* get a render result image, and make sure it is empty */
	ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	BKE_image_backup_render(rj->scene, ima);
	rj->image = ima;

	/* setup new render */
	re = RE_NewRender(scene->id.name);
	RE_test_break_cb(re, rj, render_breakjob);
	RE_draw_lock_cb(re, rj, render_drawlock);
	RE_display_draw_cb(re, rj, image_rect_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re = re;
	G.is_break = FALSE;

	/* store actual owner of job, so modal operator could check for it,
	 * the reason of this is that active scene could change when rendering
	 * several layers from compositor [#31800]
	 */
	op->customdata = scene;

	WM_jobs_start(CTX_wm_manager(C), wm_job);

	WM_cursor_wait(0);
	WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);

	/* we set G.is_rendering here already instead of only in the job, this ensure
	 * main loop or other scene updates are disabled in time, since they may
	 * have started before the job thread */
	G.is_rendering = TRUE;

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	return OPERATOR_RUNNING_MODAL;
}
示例#13
0
/* hardcoded to event TIMERJOBS */
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
{
	wmJob *wm_job, *wm_jobnext;
	float total_progress = 0.f;
	float jobs_progress = 0;

	for (wm_job = wm->jobs.first; wm_job; wm_job = wm_jobnext) {
		wm_jobnext = wm_job->next;

		if (wm_job->wt == wt) {

			/* running threads */
			if (wm_job->threads.first) {

				/* let threads get temporary lock over main thread if needed */
				wm_job_main_thread_yield(wm_job);

				/* always call note and update when ready */
				if (wm_job->do_update || wm_job->ready) {
					if (wm_job->update)
						wm_job->update(wm_job->run_customdata);
					if (wm_job->note)
						WM_event_add_notifier(C, wm_job->note, NULL);

					if (wm_job->flag & WM_JOB_PROGRESS)
						WM_event_add_notifier(C, NC_WM | ND_JOB, NULL);
					wm_job->do_update = false;
				}

				if (wm_job->ready) {
					if (wm_job->endjob)
						wm_job->endjob(wm_job->run_customdata);

					/* free own data */
					wm_job->run_free(wm_job->run_customdata);
					wm_job->run_customdata = NULL;
					wm_job->run_free = NULL;

					// if (wm_job->stop) printf("job ready but stopped %s\n", wm_job->name);
					// else printf("job finished %s\n", wm_job->name);

					if (G.debug & G_DEBUG_JOBS) {
						printf("Job '%s' finished in %f seconds\n", wm_job->name,
						       PIL_check_seconds_timer() - wm_job->start_time);
					}

					wm_job->running = false;

					WM_job_main_thread_lock_release(wm_job);
					BLI_threadpool_end(&wm_job->threads);
					WM_job_main_thread_lock_acquire(wm_job);

					if (wm_job->endnote)
						WM_event_add_notifier(C, wm_job->endnote, NULL);

					WM_event_add_notifier(C, NC_WM | ND_JOB, NULL);

					/* new job added for wm_job? */
					if (wm_job->customdata) {
						// printf("job restarted with new data %s\n", wm_job->name);
						WM_jobs_start(wm, wm_job);
					}
					else {
						WM_event_remove_timer(wm, wm_job->win, wm_job->wt);
						wm_job->wt = NULL;

						/* remove wm_job */
						wm_job_free(wm, wm_job);
					}
				}
				else if (wm_job->flag & WM_JOB_PROGRESS) {
					/* accumulate global progress for running jobs */
					jobs_progress++;
					total_progress += wm_job->progress;
				}
			}
			else if (wm_job->suspended) {
				WM_jobs_start(wm, wm_job);
			}
		}
		else if (wm_job->threads.first && !wm_job->ready) {
			if (wm_job->flag & WM_JOB_PROGRESS) {
				/* accumulate global progress for running jobs */
				jobs_progress++;
				total_progress += wm_job->progress;
			}
		}
	}


	/* if there are running jobs, set the global progress indicator */
	if (jobs_progress > 0) {
		wmWindow *win;
		float progress = total_progress / (float)jobs_progress;

		for (win = wm->windows.first; win; win = win->next)
			WM_progress_set(win, progress);
	}
	else {
		wmWindow *win;

		for (win = wm->windows.first; win; win = win->next)
			WM_progress_clear(win);
	}

}
示例#14
0
void ED_preview_shader_job(const bContext *C,
                           void *owner,
                           ID *id,
                           ID *parent,
                           MTex *slot,
                           int sizex,
                           int sizey,
                           int method)
{
  Object *ob = CTX_data_active_object(C);
  wmJob *wm_job;
  ShaderPreview *sp;
  Scene *scene = CTX_data_scene(C);
  short id_type = GS(id->name);

  /* Use workspace render only for buttons Window,
   * since the other previews are related to the datablock. */

  if (!check_engine_supports_preview(scene)) {
    return;
  }

  /* Only texture node preview is supported with Cycles. */
  if (method == PR_NODE_RENDER && id_type != ID_TE) {
    return;
  }

  ED_preview_ensure_dbase();

  wm_job = WM_jobs_get(CTX_wm_manager(C),
                       CTX_wm_window(C),
                       owner,
                       "Shader Preview",
                       WM_JOB_EXCL_RENDER,
                       WM_JOB_TYPE_RENDER_PREVIEW);
  sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");

  /* customdata for preview thread */
  sp->scene = scene;
  sp->depsgraph = CTX_data_depsgraph(C);
  sp->owner = owner;
  sp->sizex = sizex;
  sp->sizey = sizey;
  sp->pr_method = method;
  sp->id = id;
  sp->id_copy = duplicate_ids(id);
  sp->own_id_copy = true;
  sp->parent = parent;
  sp->slot = slot;
  sp->bmain = CTX_data_main(C);
  Material *ma = NULL;

  /* hardcoded preview .blend for Eevee + Cycles, this should be solved
   * once with custom preview .blend path for external engines */

  /* grease pencil use its own preview file */
  if (GS(id->name) == ID_MA) {
    ma = (Material *)id;
  }

  if ((ma == NULL) || (ma->gp_style == NULL)) {
    sp->pr_main = G_pr_main;
  }
  else {
    sp->pr_main = G_pr_main_grease_pencil;
  }

  if (ob && ob->totcol) {
    copy_v4_v4(sp->color, ob->color);
  }
  else {
    ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
  }

  /* setup job */
  WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
  WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
  WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);

  WM_jobs_start(CTX_wm_manager(C), wm_job);
}
示例#15
0
static int ocean_bake_exec(bContext *C, wmOperator *op)
{
	Object *ob = ED_object_active_context(C);
	OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
	Scene *scene = CTX_data_scene(C);
	OceanCache *och;
	struct Ocean *ocean;
	int f, cfra, i=0;
	int free= RNA_boolean_get(op->ptr, "free");
	
	wmJob *steve;
	OceanBakeJob *oj;
	
	if (!omd)
		return OPERATOR_CANCELLED;
	
	if (free) {
		omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
		WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
		return OPERATOR_FINISHED;
	}

	och = BKE_init_ocean_cache(omd->cachepath, modifier_path_relbase(ob),
	                           omd->bakestart, omd->bakeend, omd->wave_scale,
	                           omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
	
	och->time = MEM_mallocN(och->duration*sizeof(float), "foam bake time");
	
	cfra = scene->r.cfra;
	
	/* precalculate time variable before baking */
	for (f=omd->bakestart; f<=omd->bakeend; f++) {
		/* from physics_fluid.c:
		 
		 * XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation,
		 * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
		 * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
		 * This doesn't work with drivers:
		 * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
		 */
		
		/* Modifying the global scene isn't nice, but we can do it in 
		 * this part of the process before a threaded job is created */
		
		//scene->r.cfra = f;
		//ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
		
		/* ok, this doesn't work with drivers, but is way faster. 
		 * let's use this for now and hope nobody wants to drive the time value... */
		BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
		
		och->time[i] = omd->time;
		i++;
	}
	
	/* make a copy of ocean to use for baking - threadsafety */
	ocean = BKE_add_ocean();
	init_ocean_modifier_bake(ocean, omd);
	
	/*
	 BKE_bake_ocean(ocean, och);
	
	omd->oceancache = och;
	omd->cached = TRUE;
	
	scene->r.cfra = cfra;
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
	*/
	
	/* job stuff */
	
	scene->r.cfra = cfra;
	
	/* setup job */
	steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", WM_JOB_PROGRESS);
	oj= MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
	oj->ocean = ocean;
	oj->och = och;
	oj->omd = omd;
	
	WM_jobs_customdata(steve, oj, oceanbake_free);
	WM_jobs_timer(steve, 0.1, NC_OBJECT|ND_MODIFIER, NC_OBJECT|ND_MODIFIER);
	WM_jobs_callbacks(steve, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
	
	WM_jobs_start(CTX_wm_manager(C), steve);
	
	
	
	return OPERATOR_FINISHED;
}
示例#16
0
/* hardcoded to event TIMERJOBS */
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
{
	wmJob *steve= wm->jobs.first, *stevenext;
	float total_progress= 0.f;
	float jobs_progress=0;
	
	
	for(; steve; steve= stevenext) {
		stevenext= steve->next;
		
		if(steve->wt==wt) {
			
			/* running threads */
			if(steve->threads.first) {
				
				/* always call note and update when ready */
				if(steve->do_update || steve->ready) {
					if(steve->update)
						steve->update(steve->run_customdata);
					if(steve->note)
						WM_event_add_notifier(C, steve->note, NULL);

					if (steve->flag & WM_JOB_PROGRESS)
						WM_event_add_notifier(C, NC_WM|ND_JOB, NULL);
					steve->do_update= 0;
				}	
				
				if(steve->ready) {
					if(steve->endjob)
						steve->endjob(steve->run_customdata);

					/* free own data */
					steve->run_free(steve->run_customdata);
					steve->run_customdata= NULL;
					steve->run_free= NULL;
					
					// if(steve->stop) printf("job ready but stopped %s\n", steve->name);
					// else printf("job finished %s\n", steve->name);

					steve->running= 0;
					BLI_end_threads(&steve->threads);
					
					if(steve->endnote)
						WM_event_add_notifier(C, steve->endnote, NULL);
					
					WM_event_add_notifier(C, NC_WM|ND_JOB, NULL);
					
					/* new job added for steve? */
					if(steve->customdata) {
						// printf("job restarted with new data %s\n", steve->name);
						WM_jobs_start(wm, steve);
					}
					else {
						WM_event_remove_timer(wm, steve->win, steve->wt);
						steve->wt= NULL;
						
						/* remove steve */
						BLI_remlink(&wm->jobs, steve);
						MEM_freeN(steve);
					}
				} else if (steve->flag & WM_JOB_PROGRESS) {
					/* accumulate global progress for running jobs */
					jobs_progress++;
					total_progress += steve->progress;
				}
			}
			else if(steve->suspended) {
				WM_jobs_start(wm, steve);
			}
		}
	}
	
	/* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */
	if(wm->winactive) {
		/* if there are running jobs, set the global progress indicator */
		if (jobs_progress > 0) {
			float progress = total_progress / (float)jobs_progress;
			WM_progress_set(wm->winactive, progress);
		} else {
			WM_progress_clear(wm->winactive);
		}
	}
}
示例#17
0
static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job)
{
	Scene *scene= CTX_data_scene(C);
	int i;
	FluidsimSettings *domainSettings;

	char debugStrBuffer[256];
	
	int gridlevels = 0;
	const char *relbase= modifier_path_relbase(fsDomain);
	const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
	const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
	const char *suffixSurface = FLUID_SUFFIX_SURFACE;

	char targetDir[FILE_MAX];  // store & modify output settings
	char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
	int  outStringsChanged = 0;             // modified? copy back before baking

	float domainMat[4][4];
	float invDomMat[4][4];

	int noFrames;
	int origFrame = scene->r.cfra;
	
	FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels), "fluid domain animation channels");
	ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
	FluidsimModifierData *fluidmd = NULL;
	Mesh *mesh = NULL;

	FluidBakeJob *fb;
	elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings");

	fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
	
	if (getenv(strEnvName)) {
		int dlevel = atoi(getenv(strEnvName));
		elbeemSetDebugLevel(dlevel);
		BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n", strEnvName);
		elbeemDebugOut(debugStrBuffer);
	}
	
	/* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */;
	noFrames = scene->r.efra - 0;
	if (noFrames<=0) {
		BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)");
		fluidbake_free_data(channels, fobjects, fsset, fb);
		return 0;
	}
	
	/* check scene for sane object/modifier settings */
	if (!fluid_validate_scene(reports, scene, fsDomain)) {
		fluidbake_free_data(channels, fobjects, fsset, fb);
		return 0;
	}
	
	/* these both have to be valid, otherwise we wouldn't be here */
	fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
	domainSettings = fluidmd->fss;
	mesh = fsDomain->data;
	
	domainSettings->bakeStart = 1;
	domainSettings->bakeEnd = scene->r.efra;
	
	// calculate bounding box
	fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
	
	// reset last valid frame
	domainSettings->lastgoodframe = -1;

	/* delete old baked files */
	fluidsim_delete_until_lastframe(domainSettings, relbase);
	
	/* rough check of settings... */
	if (domainSettings->previewresxyz > domainSettings->resolutionxyz) {
		BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz,  domainSettings->resolutionxyz);
		elbeemDebugOut(debugStrBuffer);
		domainSettings->previewresxyz = domainSettings->resolutionxyz;
	}
	// set adaptive coarsening according to resolutionxyz
	// this should do as an approximation, with in/outflow
	// doing this more accurate would be overkill
	// perhaps add manual setting?
	if (domainSettings->maxRefine <0) {
		if (domainSettings->resolutionxyz>128) {
			gridlevels = 2;
		}
		else if (domainSettings->resolutionxyz > 64) {
			gridlevels = 1;
		}
		else {
			gridlevels = 0;
		}
	}
	else {
		gridlevels = domainSettings->maxRefine;
	}
	BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name, gridlevels);
	elbeemDebugOut(debugStrBuffer);
	
	
	
	/* ******** prepare output file paths ******** */
	outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer);
	channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
	channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames;
	
	/* ******** initialize and allocate animation channels ******** */
	fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);

	/* reset to original current frame */
	scene->r.cfra = origFrame;
	ED_update_for_newframe(CTX_data_main(C), scene, 1);
		
	/* ******** init domain object's matrix ******** */
	copy_m4_m4(domainMat, fsDomain->obmat);
	if (!invert_m4_m4(invDomMat, domainMat)) {
		BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n");
		elbeemDebugOut(debugStrBuffer);
		BKE_report(reports, RPT_ERROR, "Invalid object matrix"); 

		fluidbake_free_data(channels, fobjects, fsset, fb);
		return 0;
	}

	/* ********  start writing / exporting ******** */
	// use .tmp, don't overwrite/delete original file
	BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
	
	// make sure these directories exist as well
	if (outStringsChanged) {
		BLI_make_existing_file(targetFile);
	}

	/* ******** export domain to elbeem ******** */
	elbeemResetSettings(fsset);
	fsset->version = 1;
	fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) : domainSettings->threads;
	// setup global settings
	copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
	copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
	
	// simulate with 50^3
	fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
	fsset->previewresxyz = (int)domainSettings->previewresxyz;

	fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
	fsset->viscosity = get_fluid_viscosity(domainSettings);
	get_fluid_gravity(fsset->gravity, scene, domainSettings);

	// simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
	fsset->animStart = domainSettings->animStart;
	fsset->aniFrameTime = channels->aniFrameTime;
	fsset->noOfFrames = noFrames; // is otherwise subtracted in parser

	BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixSurface);

	// defaults for compressibility and adaptive grids
	fsset->gstar = domainSettings->gstar;
	fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
	fsset->generateParticles = domainSettings->generateParticles; 
	fsset->numTracerParticles = domainSettings->generateTracers; 
	fsset->surfaceSmoothing = domainSettings->surfaceSmoothing; 
	fsset->surfaceSubdivs = domainSettings->surfaceSubdivs; 
	fsset->farFieldSize = domainSettings->farFieldSize; 
	BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath));

	// domain channels
	fsset->channelSizeFrameTime = 
	fsset->channelSizeViscosity = 
	fsset->channelSizeGravity = channels->length;
	fsset->channelFrameTime = channels->DomainTime;
	fsset->channelViscosity = channels->DomainViscosity;
	fsset->channelGravity = channels->DomainGravity;
	
	fsset->runsimCallback = &runSimulationCallback;
	fsset->runsimUserData = fb;

	if (domainSettings->typeFlags & OB_FSBND_NOSLIP)		fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
	else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP)	fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
	else if (domainSettings->typeFlags&OB_FSBND_FREESLIP)	fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
	fsset->domainobsPartslip = domainSettings->partSlipValue;

	/* use domainobsType also for surface generation flag (bit: >=64) */
	if (domainSettings->typeFlags & OB_FSSG_NOOBS)
		fsset->mFsSurfGenSetting = FLUIDSIM_FSSG_NOOBS;
	else
		fsset->mFsSurfGenSetting = 0; // "normal" mode

	fsset->generateVertexVectors = (domainSettings->domainNovecgen==0);

	// init blender domain transform matrix
	{ int j;
	for (i=0; i<4; i++) {
		for (j=0; j<4; j++) {
			fsset->surfaceTrafo[i*4+j] = invDomMat[j][i];
		}
	} }

	/* ******** init solver with settings ******** */
	elbeemInit();
	elbeemAddDomain(fsset);
	
	/* ******** export all fluid objects to elbeem ******** */
	export_fluid_objects(fobjects, scene, channels->length);
	
	/* custom data for fluid bake job */
	fb->settings = fsset;
	
	if (do_job) {
		wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation",
		                            WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_FLUID);

		/* setup job */
		WM_jobs_customdata_set(wm_job, fb, fluidbake_free);
		WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
		WM_jobs_callbacks(wm_job, fluidbake_startjob, NULL, NULL, fluidbake_endjob);

		WM_jobs_start(CTX_wm_manager(C), wm_job);
	}
	else {
		short dummy_stop = 0, dummy_do_update = 0;
		float dummy_progress = 0.0f;

		/* blocking, use with exec() */
		fluidbake_startjob((void *)fb, &dummy_stop, &dummy_do_update, &dummy_progress);
		fluidbake_endjob((void *)fb);
		fluidbake_free((void *)fb);
	}

	/* ******** free stored animation data ******** */
	fluidbake_free_data(channels, fobjects, NULL, NULL);

	// elbeemFree();
	return 1;
}
示例#18
0
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene= CTX_data_scene(C);
	SceneRenderLayer *srl=NULL;
	bScreen *screen= CTX_wm_screen(C);
	View3D *v3d= CTX_wm_view3d(C);
	Render *re;
	wmJob *steve;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const short is_animation= RNA_boolean_get(op->ptr, "animation");
	const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
	struct Object *camera_override= v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	
	/* only one render job at a time */
	if(WM_jobs_test(CTX_wm_manager(C), scene))
		return OPERATOR_CANCELLED;

	if(!RE_is_rendering_allowed(scene, camera_override, op->reports)) {
		return OPERATOR_CANCELLED;
	}

	if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
		return OPERATOR_CANCELLED;
	}	
	
	/* stop all running jobs, currently previews frustrate Render */
	WM_jobs_stop_all(CTX_wm_manager(C));

	/* get main */
	if(G.rt == 101) {
		/* thread-safety experiment, copy main from the undo buffer */
		mainp= BKE_undo_get_main(&scene);
	}
	else
		mainp= CTX_data_main(C);

	/* cancel animation playback */
	if (screen->animtimer)
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush multires changes (for sculpt) */
	multires_force_render_update(CTX_data_active_object(C));

	/* cleanup sequencer caches before starting user triggered render.
	   otherwise, invalidated cache entries can make their way into
	   the output rendering. We can't put that into RE_BlenderFrame,
	   since sequence rendering can call that recursively... (peter) */
	seq_stripelem_cache_cleanup();

	/* get editmode results */
	ED_object_exit_editmode(C, 0);	/* 0 = does not exit editmode */

	// store spare
	// get view3d layer, local layer, make this nice api call to render
	// store spare

	/* ensure at least 1 area shows result */
	render_view_open(C, event->x, event->y);

	jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
	
	/* single layer re-render */
	if(RNA_property_is_set(op->ptr, "layer")) {
		SceneRenderLayer *rl;
		Scene *scn;
		char scene_name[MAX_ID_NAME-2], rl_name[RE_MAXNAME];

		RNA_string_get(op->ptr, "layer", rl_name);
		RNA_string_get(op->ptr, "scene", scene_name);

		scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
		rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
		
		if (scn && rl) {
			/* camera switch wont have updated */
			scn->r.cfra= scene->r.cfra;
			scene_camera_switch_update(scn);

			scene = scn;
			srl = rl;
		}
		jobflag |= WM_JOB_SUSPEND;
	}

	/* job custom data */
	rj= MEM_callocN(sizeof(RenderJob), "render job");
	rj->main= mainp;
	rj->scene= scene;
	rj->win= CTX_wm_window(C);
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay = (v3d)? v3d->lay: scene->lay;
	rj->anim= is_animation;
	rj->write_still= is_write_still && !is_animation;
	rj->iuser.scene= scene;
	rj->iuser.ok= 1;
	rj->reports= op->reports;

	/* setup job */
	steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", jobflag);
	WM_jobs_customdata(steve, rj, render_freejob);
	WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);

	/* get a render result image, and make sure it is empty */
	ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	BKE_image_backup_render(rj->scene, ima);
	rj->image= ima;

	/* setup new render */
	re= RE_NewRender(scene->id.name);
	RE_test_break_cb(re, rj, render_breakjob);
	RE_draw_lock_cb(re, rj, render_drawlock);
	RE_display_draw_cb(re, rj, image_rect_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re= re;
	G.afbreek= 0;

	WM_jobs_start(CTX_wm_manager(C), steve);

	WM_cursor_wait(0);
	WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);

	/* we set G.rendering here already instead of only in the job, this ensure
	   main loop or other scene updates are disabled in time, since they may
	   have started before the job thread */
	G.rendering = 1;

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	return OPERATOR_RUNNING_MODAL;
}
示例#19
0
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene = CTX_data_scene(C);
	SceneRenderLayer *srl = NULL;
	Render *re;
	wmJob *wm_job;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const bool is_animation = RNA_boolean_get(op->ptr, "animation");
	const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
	const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
	View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
	struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	const char *name;
	ScrArea *sa;
	
	/* only one render job at a time */
	if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
		return OPERATOR_CANCELLED;

	if (RE_force_single_renderlayer(scene))
		WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);

	if (!RE_is_rendering_allowed(scene, camera_override, op->reports)) {
		return OPERATOR_CANCELLED;
	}

	if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
		return OPERATOR_CANCELLED;
	}
	
	/* stop all running jobs, except screen one. currently previews frustrate Render */
	WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));

	/* get main */
	if (G.debug_value == 101) {
		/* thread-safety experiment, copy main from the undo buffer */
		mainp = BKE_undo_get_main(&scene);
	}
	else
		mainp = CTX_data_main(C);

	/* cancel animation playback */
	if (ED_screen_animation_playing(CTX_wm_manager(C)))
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush sculpt and editmode changes */
	ED_editors_flush_edits(C, true);

	/* cleanup sequencer caches before starting user triggered render.
	 * otherwise, invalidated cache entries can make their way into
	 * the output rendering. We can't put that into RE_BlenderFrame,
	 * since sequence rendering can call that recursively... (peter) */
	BKE_sequencer_cache_cleanup();

	// store spare
	// get view3d layer, local layer, make this nice api call to render
	// store spare

	/* ensure at least 1 area shows result */
	sa = render_view_open(C, event->x, event->y);

	jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
	
	/* custom scene and single layer re-render */
	screen_render_scene_layer_set(op, mainp, &scene, &srl);

	if (RNA_struct_property_is_set(op->ptr, "layer"))
		jobflag |= WM_JOB_SUSPEND;

	/* job custom data */
	rj = MEM_callocN(sizeof(RenderJob), "render job");
	rj->main = mainp;
	rj->scene = scene;
	rj->current_scene = rj->scene;
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay_override = 0;
	rj->anim = is_animation;
	rj->write_still = is_write_still && !is_animation;
	rj->iuser.scene = scene;
	rj->iuser.ok = 1;
	rj->reports = op->reports;
	rj->orig_layer = 0;
	rj->last_layer = 0;
	rj->sa = sa;

	BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings);
	BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings);

	if (sa) {
		SpaceImage *sima = sa->spacedata.first;
		rj->orig_layer = sima->iuser.layer;
	}

	if (v3d) {
		if (scene->lay != v3d->lay) {
			rj->lay_override = v3d->lay;
			rj->v3d_override = true;
		}
		else if (camera_override && camera_override != scene->camera)
			rj->v3d_override = true;

		if (v3d->localvd)
			rj->lay_override |= v3d->localvd->lay;
	}

	/* Lock the user interface depending on render settings. */
	if (scene->r.use_lock_interface) {
		int renderlay = rj->lay_override ? rj->lay_override : scene->lay;

		WM_set_locked_interface(CTX_wm_manager(C), true);

		/* Set flag interface need to be unlocked.
		 *
		 * This is so because we don't have copy of render settings
		 * accessible from render job and copy is needed in case
		 * of non-locked rendering, so we wouldn't try to unlock
		 * anything if option was initially unset but then was
		 * enabled during rendering.
		 */
		rj->interface_locked = true;

		/* Clean memory used by viewport? */
		clean_viewport_memory(rj->main, scene, renderlay);
	}

	/* setup job */
	if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
	else name = "Render";

	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
	WM_jobs_customdata_set(wm_job, rj, render_freejob);
	WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);

	/* get a render result image, and make sure it is empty */
	ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	BKE_image_backup_render(rj->scene, ima);
	rj->image = ima;

	/* setup new render */
	re = RE_NewRender(scene->id.name);
	RE_test_break_cb(re, rj, render_breakjob);
	RE_draw_lock_cb(re, rj, render_drawlock);
	RE_display_update_cb(re, rj, image_rect_update);
	RE_current_scene_update_cb(re, rj, current_scene_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re = re;
	G.is_break = false;

	/* store actual owner of job, so modal operator could check for it,
	 * the reason of this is that active scene could change when rendering
	 * several layers from compositor [#31800]
	 */
	op->customdata = scene;

	WM_jobs_start(CTX_wm_manager(C), wm_job);

	WM_cursor_wait(0);
	WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);

	/* we set G.is_rendering here already instead of only in the job, this ensure
	 * main loop or other scene updates are disabled in time, since they may
	 * have started before the job thread */
	G.is_rendering = true;

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	return OPERATOR_RUNNING_MODAL;
}