示例#1
0
static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
{
	if (tex->imaflag & TEX_MIPMAP) {
		if ((ibuf->flags & IB_fields) == 0) {
			
			if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
				BLI_lock_thread(LOCK_IMAGE);
				if (ibuf->userflags & IB_MIPMAP_INVALID) {
					IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
					ibuf->userflags &= ~IB_MIPMAP_INVALID;
				}
				BLI_unlock_thread(LOCK_IMAGE);
			}
			if (ibuf->mipmap[0] == NULL) {
				BLI_lock_thread(LOCK_IMAGE);
				if (ibuf->mipmap[0] == NULL) 
					IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
				BLI_unlock_thread(LOCK_IMAGE);
			}
			/* if no mipmap could be made, fall back on non-mipmap render */
			if (ibuf->mipmap[0] == NULL) {
				tex->imaflag &= ~TEX_MIPMAP;
			}
		}
	}
	
}
void ViewerOperation::initImage()
{
	Image *ima = this->m_image;
	ImageUser iuser = *this->m_imageUser;
	void *lock;
	ImBuf *ibuf;

	/* make sure the image has the correct number of views */
	if (ima && BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) {
		BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser);
	}

	BLI_lock_thread(LOCK_DRAW_IMAGE);

	/* local changes to the original ImageUser */
	iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName);
	ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);

	if (!ibuf) {
		BLI_unlock_thread(LOCK_DRAW_IMAGE);
		return;
	}
	if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {

		imb_freerectImBuf(ibuf);
		imb_freerectfloatImBuf(ibuf);
		IMB_freezbuffloatImBuf(ibuf);
		ibuf->x = getWidth();
		ibuf->y = getHeight();
		/* zero size can happen if no image buffers exist to define a sensible resolution */
		if (ibuf->x > 0 && ibuf->y > 0)
			imb_addrectfloatImBuf(ibuf);
		ima->ok = IMA_OK_LOADED;

		ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
	}

	if (m_doDepthBuffer) {
		addzbuffloatImBuf(ibuf);
	}

	/* now we combine the input with ibuf */
	this->m_outputBuffer = ibuf->rect_float;

	/* needed for display buffer update */
	this->m_ibuf = ibuf;

	if (m_doDepthBuffer) {
		this->m_depthBuffer = ibuf->zbuf_float;
	}

	BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock);

	BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
示例#3
0
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
{
    char name[FILE_MAX];
    int quality, rectx, recty;
    int size = rendersize_to_number(proxy_render_size);
    ImBuf *scaleibuf;

    get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);

    rectx = ibuf->x * size / 100.0f;
    recty = ibuf->y * size / 100.0f;

    scaleibuf = IMB_dupImBuf(ibuf);

    IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);

    quality = clip->proxy.quality;
    scaleibuf->ftype = JPG | quality;

    /* unsupported feature only confuses other s/w */
    if (scaleibuf->planes == 32)
        scaleibuf->planes = 24;

    BLI_lock_thread(LOCK_MOVIECLIP);

    BLI_make_existing_file(name);
    if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
        perror(name);

    BLI_unlock_thread(LOCK_MOVIECLIP);

    IMB_freeImBuf(scaleibuf);
}
void ViewerBaseOperation::initImage()
{
	Image *anImage = this->m_image;
	ImBuf *ibuf = BKE_image_acquire_ibuf(anImage, this->m_imageUser, &this->m_lock);
	
	if (!ibuf) return;
	if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {
		BLI_lock_thread(LOCK_DRAW_IMAGE);

		imb_freerectImBuf(ibuf);
		imb_freerectfloatImBuf(ibuf);
		IMB_freezbuffloatImBuf(ibuf);
		ibuf->x = getWidth();
		ibuf->y = getHeight();
		imb_addrectImBuf(ibuf);
		imb_addrectfloatImBuf(ibuf);
		anImage->ok = IMA_OK_LOADED;

		BLI_unlock_thread(LOCK_DRAW_IMAGE);
	}
	
	/* now we combine the input with ibuf */
	this->m_outputBuffer = ibuf->rect_float;
	this->m_outputBufferDisplay = (unsigned char *)ibuf->rect;
	
	BKE_image_release_ibuf(this->m_image, this->m_lock);
}
示例#5
0
static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag,
                                               int postprocess_flag, int cache_flag)
{
	ImBuf *ibuf = NULL;
	int framenr = user->framenr;
	bool need_postprocess = false;

	/* cache isn't threadsafe itself and also loading of movies
	 * can't happen from concurent threads that's why we use lock here */
	BLI_lock_thread(LOCK_MOVIECLIP);

	/* try to obtain cached postprocessed frame first */
	if (need_postprocessed_frame(user, postprocess_flag)) {
		ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);

		if (!ibuf)
			need_postprocess = true;
	}

	if (!ibuf)
		ibuf = get_imbuf_cache(clip, user, flag);

	if (!ibuf) {
		bool use_sequence = false;

		/* undistorted proxies for movies should be read as image sequence */
		use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
		               (user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);

		if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
			ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
		}
		else {
			ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
		}

		if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
			put_imbuf_cache(clip, user, ibuf, flag, true);
	}

	if (ibuf) {
		clip->lastframe = framenr;
		real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);

		/* postprocess frame and put to cache if needed*/
		if (need_postprocess) {
			ImBuf *tmpibuf = ibuf;
			ibuf = postprocess_frame(clip, user, tmpibuf, postprocess_flag);
			IMB_freeImBuf(tmpibuf);
			if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
				put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
			}
		}
	}

	BLI_unlock_thread(LOCK_MOVIECLIP);

	return ibuf;
}
static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname)
{
	RenderLayer *rlp, *rl;
	RenderPass *rpassp;
	int offs, partx, party;
	
	BLI_lock_thread(LOCK_IMAGE);
	
	for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
		rl = RE_GetRenderLayer(rr, rlp->name);

		/* should never happen but prevents crash if it does */
		BLI_assert(rl);
		if (UNLIKELY(rl == NULL)) {
			continue;
		}

		if (rrpart->crop) { /* filters add pixel extra */
			offs = (rrpart->crop + rrpart->crop * rrpart->rectx);
		}
		else {
			offs = 0;
		}

		/* passes are allocated in sync */
		for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
			const int xstride = rpassp->channels;
			int a;
			char passname[EXR_PASS_MAXNAME];

			for (a = 0; a < xstride; a++) {
				set_pass_name(passname, rpassp->passtype, a, rpassp->view);

				IMB_exr_set_channel(rl->exrhandle, rlp->name, passname,
				                    xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
			}
		}
		
	}

	party = rrpart->tilerect.ymin + rrpart->crop;
	partx = rrpart->tilerect.xmin + rrpart->crop;

	for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
		rl = RE_GetRenderLayer(rr, rlp->name);

		/* should never happen but prevents crash if it does */
		BLI_assert(rl);
		if (UNLIKELY(rl == NULL)) {
			continue;
		}

		IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname);
	}

	BLI_unlock_thread(LOCK_IMAGE);
}
示例#7
0
static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
{
	int dx, part;
	
	/* after lock we test cube[1], if set the other thread has done it fine */
	BLI_lock_thread(LOCK_IMAGE);
	if (env->cube[1] == NULL) {

		BKE_texture_envmap_free_data(env);
	
		dx = ibuf->y;
		dx /= 2;
		if (3 * dx == ibuf->x) {
			env->type = ENV_CUBE;
			env->ok = ENV_OSA;
		}
		else if (ibuf->x == ibuf->y) {
			env->type = ENV_PLANE;
			env->ok = ENV_OSA;
		}
		else {
			printf("Incorrect envmap size\n");
			env->ok = 0;
			env->ima->ok = 0;
		}
		
		if (env->ok) {
			if (env->type == ENV_CUBE) {
				for (part = 0; part < 6; part++) {
					env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect | IB_rectfloat);
				}
				IMB_float_from_rect(ibuf);
				
				IMB_rectcpy(env->cube[0], ibuf, 
				            0, 0, 0, 0, dx, dx);
				IMB_rectcpy(env->cube[1], ibuf, 
				            0, 0, dx, 0, dx, dx);
				IMB_rectcpy(env->cube[2], ibuf, 
				            0, 0, 2 * dx, 0, dx, dx);
				IMB_rectcpy(env->cube[3], ibuf, 
				            0, 0, 0, dx, dx, dx);
				IMB_rectcpy(env->cube[4], ibuf, 
				            0, 0, dx, dx, dx, dx);
				IMB_rectcpy(env->cube[5], ibuf, 
				            0, 0, 2 * dx, dx, dx, dx);
				
			}
			else { /* ENV_PLANE */
				env->cube[1] = IMB_dupImBuf(ibuf);
				IMB_float_from_rect(env->cube[1]);
			}
		}
	}
	BLI_unlock_thread(LOCK_IMAGE);
}
int ntreeTexExecTree(
        bNodeTree *nodes,
        TexResult *texres,
        float co[3],
        float dxt[3], float dyt[3],
        int osatex,
        const short thread,
        Tex *UNUSED(tex),
        short which_output,
        int cfra,
        int preview,
        ShadeInput *shi,
        MTex *mtex)
{
	TexCallData data;
	float *nor = texres->nor;
	int retval = TEX_INT;
	bNodeThreadStack *nts = NULL;
	bNodeTreeExec *exec = nodes->execdata;

	data.co = co;
	data.dxt = dxt;
	data.dyt = dyt;
	data.osatex = osatex;
	data.target = texres;
	data.do_preview = preview;
	data.do_manage = (shi) ? shi->do_manage : true;
	data.thread = thread;
	data.which_output = which_output;
	data.cfra = cfra;
	data.mtex = mtex;
	data.shi = shi;
	
	/* ensure execdata is only initialized once */
	if (!exec) {
		BLI_lock_thread(LOCK_NODES);
		if (!nodes->execdata)
			ntreeTexBeginExecTree(nodes);
		BLI_unlock_thread(LOCK_NODES);

		exec = nodes->execdata;
	}
	
	nts = ntreeGetThreadStack(exec, thread);
	ntreeExecThreadNodes(exec, nts, &data, thread);
	ntreeReleaseThreadStack(nts);

	if (texres->nor) retval |= TEX_NOR;
	retval |= TEX_RGB;
	/* confusing stuff; the texture output node sets this to NULL to indicate no normal socket was set
	 * however, the texture code checks this for other reasons (namely, a normal is required for material) */
	texres->nor = nor;

	return retval;
}
void CompositorOperation::deinitExecution()
{
	if (!this->m_active)
		return;

	if (!isBreaked()) {
		Render *re = RE_GetRender(this->m_sceneName);
		RenderResult *rr = RE_AcquireResultWrite(re);

		if (rr) {
			if (rr->rectf != NULL) {
				MEM_freeN(rr->rectf);
			}
			rr->rectf = this->m_outputBuffer;
			if (rr->rectz != NULL) {
				MEM_freeN(rr->rectz);
			}
			rr->rectz = this->m_depthBuffer;
		}
		else {
			if (this->m_outputBuffer) {
				MEM_freeN(this->m_outputBuffer);
			}
			if (this->m_depthBuffer) {
				MEM_freeN(this->m_depthBuffer);
			}
		}

		if (re) {
			RE_ReleaseResult(re);
			re = NULL;
		}

		BLI_lock_thread(LOCK_DRAW_IMAGE);
		BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
		BLI_unlock_thread(LOCK_DRAW_IMAGE);
	}
	else {
		if (this->m_outputBuffer) {
			MEM_freeN(this->m_outputBuffer);
		}
		if (this->m_depthBuffer) {
			MEM_freeN(this->m_depthBuffer);
		}
	}

	this->m_outputBuffer = NULL;
	this->m_depthBuffer = NULL;
	this->m_imageInput = NULL;
	this->m_alphaInput = NULL;
	this->m_depthInput = NULL;
}
示例#10
0
int runSimulationCallback(void *data, int status, int frame) {
	//elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data;
	//printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG
	int state = 0;
	if(status==FLUIDSIM_CBSTATUS_NEWFRAME) {
		BLI_lock_thread(LOCK_CUSTOM1);
		globalBakeFrame = frame-1;
		BLI_unlock_thread(LOCK_CUSTOM1);
	}
	
	//if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; }
		
	BLI_lock_thread(LOCK_CUSTOM1);
	state = globalBakeState;
	BLI_unlock_thread(LOCK_CUSTOM1);
	
	if(state!=0) {
		return FLUIDSIM_CBRET_ABORT;
	}
	
	return FLUIDSIM_CBRET_CONTINUE;
}
示例#11
0
void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area, int totpoint)
{
	SSSPoints *p;
	
	if (totpoint > 0) {
		p= MEM_callocN(sizeof(SSSPoints), "SSSPoints");

		p->co= co;
		p->color= color;
		p->area= area;
		p->totpoint= totpoint;

		BLI_lock_thread(LOCK_CUSTOM1);
		BLI_addtail(re->sss_points, p);
		BLI_unlock_thread(LOCK_CUSTOM1);
	}
}
示例#12
0
// run simulation in seperate thread
static void *fluidsimSimulateThread(void *unused) { // *ptr) {
	//char* fnameCfgPath = (char*)(ptr);
	int ret=0;
	
	ret = elbeemSimulate();
	BLI_lock_thread(LOCK_CUSTOM1);
	if(globalBakeState==0) {
		if(ret==0) {
			// if no error, set to normal exit
			globalBakeState = 1;
		} else {
			// simulation failed, display error
			globalBakeState = -2;
		}
	}
	BLI_unlock_thread(LOCK_CUSTOM1);
	return NULL;
}
示例#13
0
/* only for Blender internal */
bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
{
	ShaderCallData scd;
	/**
	 * \note: preserve material from ShadeInput for material id, nodetree execs change it
	 * fix for bug "[#28012] Mat ID messy with shader nodes"
	 */
	Material *mat = shi->mat;
	bNodeThreadStack *nts = NULL;
	bNodeTreeExec *exec = ntree->execdata;
	int compat;
	
	/* convert caller data to struct */
	scd.shi = shi;
	scd.shr = shr;
	
	/* each material node has own local shaderesult, with optional copying */
	memset(shr, 0, sizeof(ShadeResult));
	
	/* ensure execdata is only initialized once */
	if (!exec) {
		BLI_lock_thread(LOCK_NODES);
		if (!ntree->execdata)
			ntree->execdata = ntreeShaderBeginExecTree(ntree);
		BLI_unlock_thread(LOCK_NODES);

		exec = ntree->execdata;
	}
	
	nts = ntreeGetThreadStack(exec, shi->thread);
	compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
	ntreeReleaseThreadStack(nts);
	
	// \note: set material back to preserved material
	shi->mat = mat;
		
	/* better not allow negative for now */
	if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f;
	if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f;
	if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f;
	
	/* if compat is zero, it has been using non-compatible nodes */
	return compat;
}
示例#14
0
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(in), short UNUSED(thread))
{
	float x = p->co[0];
	float y = p->co[1];
	Image *ima= (Image *)node->id;
	ImageUser *iuser= (ImageUser *)node->storage;
	
	if( ima ) {
		ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser);
		if( ibuf ) {
			float xsize, ysize;
			float xoff, yoff;
			int px, py;
			
			float *result;

			xsize = ibuf->x / 2;
			ysize = ibuf->y / 2;
			xoff = yoff = -1;
					
			px = (int)( (x-xoff) * xsize );
			py = (int)( (y-yoff) * ysize );
		
			if( (!xsize) || (!ysize) ) return;
			
			if( !ibuf->rect_float ) {
				BLI_lock_thread(LOCK_IMAGE);
				if( !ibuf->rect_float )
					IMB_float_from_rect(ibuf);
				BLI_unlock_thread(LOCK_IMAGE);
			}
			
			while( px < 0 ) px += ibuf->x;
			while( py < 0 ) py += ibuf->y;
			while( px >= ibuf->x ) px -= ibuf->x;
			while( py >= ibuf->y ) py -= ibuf->y;
			
			result = ibuf->rect_float + py*ibuf->x*4 + px*4;
			QUATCOPY( out, result );
		}
	}
}
示例#15
0
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
{
	char name[FILE_MAX];
	int quality, rectx, recty;
	int size = rendersize_to_number(proxy_render_size);
	ImBuf *scaleibuf;

	get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);

	rectx = ibuf->x * size / 100.0f;
	recty = ibuf->y * size / 100.0f;

	scaleibuf = IMB_dupImBuf(ibuf);

	if (threaded)
		IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
	else
		IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);

	quality = clip->proxy.quality;
	scaleibuf->ftype = JPG | quality;

	/* unsupported feature only confuses other s/w */
	if (scaleibuf->planes == 32)
		scaleibuf->planes = 24;

	/* TODO: currently the most weak part of multithreaded proxies,
	 *       could be solved in a way that thread only prepares memory
	 *       buffer and write to disk happens separately
	 */
	BLI_lock_thread(LOCK_MOVIECLIP);

	BLI_make_existing_file(name);
	if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
		perror(name);

	BLI_unlock_thread(LOCK_MOVIECLIP);

	IMB_freeImBuf(scaleibuf);
}
void ViewerOperation::initImage()
{
	Image *ima = this->m_image;
	void *lock;
	ImBuf *ibuf = BKE_image_acquire_ibuf(ima, this->m_imageUser, &lock);

	if (!ibuf) return;
	BLI_lock_thread(LOCK_DRAW_IMAGE);
	if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {

		imb_freerectImBuf(ibuf);
		imb_freerectfloatImBuf(ibuf);
		IMB_freezbuffloatImBuf(ibuf);
		ibuf->x = getWidth();
		ibuf->y = getHeight();
		imb_addrectfloatImBuf(ibuf);
		ima->ok = IMA_OK_LOADED;

		ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
	}

	if (m_doDepthBuffer) {
		addzbuffloatImBuf(ibuf);
	}
	BLI_unlock_thread(LOCK_DRAW_IMAGE);

	/* now we combine the input with ibuf */
	this->m_outputBuffer = ibuf->rect_float;

	/* needed for display buffer update */
	this->m_ibuf = ibuf;

	if (m_doDepthBuffer) {
		this->m_depthBuffer = ibuf->zbuf_float;
	}

	BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock);
}
示例#17
0
static void screen_opengl_views_setup(OGLRender *oglrender)
{
	RenderResult *rr;
	RenderView *rv;
	SceneRenderView *srv;
	bool is_multiview;
	View3D *v3d = oglrender->v3d;

	RenderData *rd = &oglrender->scene->r;

	rr = RE_AcquireResultWrite(oglrender->re);

	is_multiview = screen_opengl_is_multiview(oglrender);

	if (!is_multiview) {
		/* we only have one view when multiview is off */
		rv = rr->views.first;

		if (rv == NULL) {
			rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
			BLI_addtail(&rr->views, rv);
		}

		while (rv->next) {
			RenderView *rv_del = rv->next;
			BLI_remlink(&rr->views, rv_del);

			if (rv_del->rectf)
				MEM_freeN(rv_del->rectf);

			if (rv_del->rectz)
				MEM_freeN(rv_del->rectz);

			MEM_freeN(rv_del);
		}
	}
	else {
		if (!oglrender->is_sequencer)
			RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d));

		/* remove all the views that are not needed */
		rv = rr->views.last;
		while (rv) {
			srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name));
			if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
				if (rv->rectf == NULL)
					rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect");
				rv = rv->prev;
			}
			else {
				RenderView *rv_del = rv;
				rv  = rv_del->prev;

				BLI_remlink(&rr->views, rv_del);

				if (rv_del->rectf)
					MEM_freeN(rv_del->rectf);

				if (rv_del->rectz)
					MEM_freeN(rv_del->rectz);

				MEM_freeN(rv_del);
			}
		}

		/* create all the views that are needed */
		for (srv = rd->views.first; srv; srv = srv->next) {
			if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
				continue;

			rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name));

			if (rv == NULL) {
				rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
				BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
				BLI_addtail(&rr->views, rv);
			}
		}
	}

	for (rv = rr->views.first; rv; rv = rv->next) {
		if (rv->rectf == NULL) {
			rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect");
		}
	}

	BLI_lock_thread(LOCK_DRAW_IMAGE);
	if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) {
		oglrender->ima->flag |= IMA_IS_STEREO;
	}
	else {
		oglrender->ima->flag &= ~IMA_IS_STEREO;
		oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
	}
	BLI_unlock_thread(LOCK_DRAW_IMAGE);

	RE_ReleaseResult(oglrender->re);
}
示例#18
0
/* already have tested for tface and ima and zspan */
static void shade_tface(BakeShade *bs)
{
	VlakRen *vlr = bs->vlr;
	ObjectInstanceRen *obi = bs->obi;
	ObjectRen *obr = obi->obr;
	MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
	Image *ima = tface->tpage;
	float vec[4][2];
	int a, i1, i2, i3;
	
	/* check valid zspan */
	if (ima != bs->ima) {
		BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);

		bs->ima = ima;
		bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA);
		/* note, these calls only free/fill contents of zspan struct, not zspan itself */
		zbuf_free_span(bs->zspan);
		zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
	}

	bs->rectx = bs->ibuf->x;
	bs->recty = bs->ibuf->y;
	bs->rect = bs->ibuf->rect;
	bs->rect_colorspace = bs->ibuf->rect_colorspace;
	bs->rect_float = bs->ibuf->rect_float;
	bs->vcol = NULL;
	bs->quad = 0;
	bs->rect_mask = NULL;
	bs->displacement_buffer = NULL;

	if (bs->use_mask || bs->use_displacement_buffer) {
		BakeImBufuserData *userdata = bs->ibuf->userdata;
		if (userdata == NULL) {
			BLI_lock_thread(LOCK_CUSTOM1);
			userdata = bs->ibuf->userdata;
			if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */
				userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeImBufuserData");

			if (bs->use_mask) {
				if (userdata->mask_buffer == NULL) {
					userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask");
				}
			}

			if (bs->use_displacement_buffer) {
				if (userdata->displacement_buffer == NULL) {
					userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp");
				}
			}

			bs->ibuf->userdata = userdata;

			BLI_unlock_thread(LOCK_CUSTOM1);
		}

		bs->rect_mask = userdata->mask_buffer;
		bs->displacement_buffer = userdata->displacement_buffer;
	}
	
	/* get pixel level vertex coordinates */
	for (a = 0; a < 4; a++) {
		/* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
		 * where a pixel gets in between 2 faces or the middle of a quad,
		 * camera aligned quads also have this problem but they are less common.
		 * Add a small offset to the UVs, fixes bug #18685 - Campbell */
		vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f);
		vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f);
	}

	/* UV indices have to be corrected for possible quad->tria splits */
	i1 = 0; i2 = 1; i3 = 2;
	vlr_set_uv_indices(vlr, &i1, &i2, &i3);
	bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
	zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
	
	if (vlr->v4) {
		bs->quad = 1;
		bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
		zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
	}
}
示例#19
0
static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth)
{
	ListBase threads;
	OcclusionBuildThread othreads[BLENDER_MAX_THREADS];
	OccNode *child, tmpnode;
	/* OccFace *face; */
	int a, b, totthread = 0, offset[TOTCHILD], count[TOTCHILD];

	/* add a new node */
	node->occlusion = 1.0f;

	/* leaf node with only children */
	if (end - begin <= TOTCHILD) {
		for (a = begin, b = 0; a < end; a++, b++) {
			/* face= &tree->face[a]; */
			node->child[b].face = a;
			node->childflag |= (1 << b);
		}
	}
	else {
		/* order faces */
		occ_build_8_split(tree, begin, end, offset, count);

		if (depth == 1 && tree->dothreadedbuild)
			BLI_init_threads(&threads, exec_occ_build, tree->totbuildthread);

		for (b = 0; b < TOTCHILD; b++) {
			if (count[b] == 0) {
				node->child[b].node = NULL;
			}
			else if (count[b] == 1) {
				/* face= &tree->face[offset[b]]; */
				node->child[b].face = offset[b];
				node->childflag |= (1 << b);
			}
			else {
				if (tree->dothreadedbuild)
					BLI_lock_thread(LOCK_CUSTOM1);

				child = BLI_memarena_alloc(tree->arena, sizeof(OccNode));
				node->child[b].node = child;

				/* keep track of maximum depth for stack */
				if (depth >= tree->maxdepth)
					tree->maxdepth = depth + 1;

				if (tree->dothreadedbuild)
					BLI_unlock_thread(LOCK_CUSTOM1);

				if (depth == 1 && tree->dothreadedbuild) {
					othreads[totthread].tree = tree;
					othreads[totthread].node = child;
					othreads[totthread].begin = offset[b];
					othreads[totthread].end = offset[b] + count[b];
					othreads[totthread].depth = depth + 1;
					BLI_insert_thread(&threads, &othreads[totthread]);
					totthread++;
				}
				else
					occ_build_recursive(tree, child, offset[b], offset[b] + count[b], depth + 1);
			}
		}

		if (depth == 1 && tree->dothreadedbuild)
			BLI_end_threads(&threads);
	}

	/* combine area, position and sh */
	for (b = 0; b < TOTCHILD; b++) {
		if (node->childflag & (1 << b)) {
			child = &tmpnode;
			occ_node_from_face(tree->face + node->child[b].face, &tmpnode);
		}
		else {
			child = node->child[b].node;
		}

		if (child) {
			node->area += child->area;
			sh_add(node->sh, node->sh, child->sh);
			madd_v3_v3fl(node->co, child->co, child->area);
		}
	}

	if (node->area != 0.0f)
		mul_v3_fl(node->co, 1.0f / node->area);

	/* compute maximum distance from center */
	node->dco = 0.0f;
	if (node->area > 0.0f)
		occ_build_dco(tree, node, node->co, &node->dco);
}
示例#20
0
文件: ocean.c 项目: akonneker/blensor
void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp,
                    float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals,
                    short do_jacobian, int seed)
{
	RNG *rng;
	int i, j, ii;

	BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);

	o->_M = M;
	o->_N = N;
	o->_V = V;
	o->_l = l;
	o->_A = A;
	o->_w = w;
	o->_damp_reflections = 1.0f - damp;
	o->_wind_alignment = alignment;
	o->_depth = depth;
	o->_Lx = Lx;
	o->_Lz = Lz;
	o->_wx = cos(w);
	o->_wz = -sin(w); /* wave direction */
	o->_L = V * V / GRAVITY;  /* largest wave for a given velocity V */
	o->time = time;

	o->_do_disp_y = do_height_field;
	o->_do_normals = do_normals;
	o->_do_chop = do_chop;
	o->_do_jacobian = do_jacobian;

	o->_k = (float *) MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k");
	o->_h0 = (fftw_complex *) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0");
	o->_h0_minus = (fftw_complex *) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus");
	o->_kx = (float *) MEM_mallocN(o->_M * sizeof(float), "ocean_kx");
	o->_kz = (float *) MEM_mallocN(o->_N * sizeof(float), "ocean_kz");

	/* make this robust in the face of erroneous usage */
	if (o->_Lx == 0.0f)
		o->_Lx = 0.001f;

	if (o->_Lz == 0.0f)
		o->_Lz = 0.001f;

	/* the +ve components and DC */
	for (i = 0; i <= o->_M / 2; ++i)
		o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx;

	/* the -ve components */
	for (i = o->_M - 1, ii = 0; i > o->_M / 2; --i, ++ii)
		o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx;

	/* the +ve components and DC */
	for (i = 0; i <= o->_N / 2; ++i)
		o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz;

	/* the -ve components */
	for (i = o->_N - 1, ii = 0; i > o->_N / 2; --i, ++ii)
		o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz;

	/* pre-calculate the k matrix */
	for (i = 0; i < o->_M; ++i)
		for (j = 0; j <= o->_N / 2; ++j)
			o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);

	/*srand(seed);*/
	rng = BLI_rng_new(seed);

	for (i = 0; i < o->_M; ++i) {
		for (j = 0; j < o->_N; ++j) {
			float r1 = gaussRand(rng);
			float r2 = gaussRand(rng);

			fftw_complex r1r2;
			init_complex(r1r2, r1, r2);
			mul_complex_f(o->_h0[i * o->_N + j], r1r2, (float)(sqrt(Ph(o, o->_kx[i], o->_kz[j]) / 2.0f)));
			mul_complex_f(o->_h0_minus[i * o->_N + j], r1r2, (float)(sqrt(Ph(o, -o->_kx[i], -o->_kz[j]) / 2.0f)));
		}
	}

	o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
	o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");

	BLI_lock_thread(LOCK_FFTW);

	if (o->_do_disp_y) {
		o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
		o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE);
	}

	if (o->_do_normals) {
		o->_fft_in_nx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nx");
		o->_fft_in_nz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nz");

		o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
		/* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
		o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");

		o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
		o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE);
	}

	if (o->_do_chop) {
		o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x");
		o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z");

		o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
		o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");

		o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE);
		o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE);
	}
	if (o->_do_jacobian) {
		o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
		                                             "ocean_fft_in_jxx");
		o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
		                                             "ocean_fft_in_jzz");
		o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
		                                             "ocean_fft_in_jxz");

		o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
		o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
		o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");

		o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE);
		o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE);
		o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE);
	}

	BLI_unlock_thread(LOCK_FFTW);

	BLI_rw_mutex_unlock(&o->oceanmutex);

	set_height_normalize_factor(o);

	BLI_rng_free(rng);
}
示例#21
0
void draw_image_main(const bContext *C, ARegion *ar)
{
	SpaceImage *sima = CTX_wm_space_image(C);
	Scene *scene = CTX_data_scene(C);
	Image *ima;
	ImBuf *ibuf;
	float zoomx, zoomy;
	bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer;
	void *lock;

	/* XXX can we do this in refresh? */
#if 0
	what_image(sima);
	
	if (sima->image) {
		ED_image_get_aspect(sima->image, &xuser_asp, &yuser_asp);
		
		/* UGLY hack? until now iusers worked fine... but for flipbook viewer we need this */
		if (sima->image->type == IMA_TYPE_COMPOSITE) {
			ImageUser *iuser = ntree_get_active_iuser(scene->nodetree);
			if (iuser) {
				BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
				sima->iuser = *iuser;
			}
		}
		/* and we check for spare */
		ibuf = ED_space_image_buffer(sima);
	}
#endif

	/* retrieve the image and information about it */
	ima = ED_space_image(sima);
	ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);

	show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
	show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
	show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
	show_stereo3d = (ima && (ima->flag & IMA_IS_STEREO) && (sima->iuser.flag & IMA_SHOW_STEREO));
	show_multilayer = ima && BKE_image_is_multilayer(ima);

	if (show_viewer) {
		/* use locked draw for drawing viewer image buffer since the compositor
		 * is running in separated thread and compositor could free this buffers.
		 * other images are not modifying in such a way so they does not require
		 * lock (sergey)
		 */
		BLI_lock_thread(LOCK_DRAW_IMAGE);
	}

	if (show_stereo3d) {
		if (show_multilayer)
			/* update multiindex and pass for the current eye */
			BKE_image_multilayer_index(ima->rr, &sima->iuser);
		else
			BKE_image_multiview_index(ima, &sima->iuser);
	}

	ibuf = ED_space_image_acquire_buffer(sima, &lock);

	/* draw the image or grid */
	if (ibuf == NULL)
		ED_region_grid_draw(ar, zoomx, zoomy);
	else if (sima->flag & SI_DRAW_TILE)
		draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy);
	else if (ima && (ima->tpageflag & IMA_TILES))
		draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
	else
		draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);

	/* paint helpers */
	if (show_paint)
		draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);

	/* XXX integrate this code */
#if 0
	if (ibuf) {
		float xoffs = 0.0f, yoffs = 0.0f;
		
		if (image_preview_active(sa, &xim, &yim)) {
			xoffs = scene->r.disprect.xmin;
			yoffs = scene->r.disprect.ymin;
			glColor3ub(0, 0, 0);
			calc_image_view(sima, 'f');
			myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
			glRectf(0.0f, 0.0f, 1.0f, 1.0f);
			glLoadIdentity();
		}
	}
#endif

	ED_space_image_release_buffer(sima, ibuf, lock);

	if (show_viewer) {
		BLI_unlock_thread(LOCK_DRAW_IMAGE);
	}

	/* render info */
	if (ima && show_render)
		draw_render_info(C, sima->iuser.scene, ima, ar, zoomx, zoomy);
}
示例#22
0
static int get_next_bake_face(BakeShade *bs)
{
	ObjectRen *obr;
	VlakRen *vlr;
	MTFace *tface;
	static int v = 0, vdone = false;
	static ObjectInstanceRen *obi = NULL;

	if (bs == NULL) {
		vlr = NULL;
		v = vdone = false;
		obi = R.instancetable.first;
		return 0;
	}
	
	BLI_lock_thread(LOCK_CUSTOM1);

	for (; obi; obi = obi->next, v = 0) {
		obr = obi->obr;

		for (; v < obr->totvlak; v++) {
			vlr = RE_findOrAddVlak(obr, v);

			if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
				if (R.r.bake_flag & R_BAKE_VCOL) {
					/* Gather face data for vertex color bake */
					Mesh *me;
					int *origindex, vcollayer;
					CustomDataLayer *cdl;

					if (obr->ob->type != OB_MESH)
						continue;
					me = obr->ob->data;

					origindex = RE_vlakren_get_origindex(obr, vlr, 0);
					if (origindex == NULL)
						continue;
					if (*origindex >= me->totpoly) {
						/* Small hack for Array modifier, which gives false
						 * original indices - z0r */
						continue;
					}
#if 0
					/* Only shade selected faces. */
					if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
						continue;
#endif

					vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
					if (vcollayer == -1)
						continue;

					cdl = &me->ldata.layers[vcollayer];
					bs->mpoly = me->mpoly + *origindex;
					bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart;
					bs->mloop = me->mloop + bs->mpoly->loopstart;

					/* Tag mesh for reevaluation. */
					me->id.flag |= LIB_DOIT;
				}
				else {
					Image *ima = NULL;
					ImBuf *ibuf = NULL;
					const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
					const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
					const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
					const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
					const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
					const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};

					tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);

					if (!tface || !tface->tpage)
						continue;

					ima = tface->tpage;
					ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA);

					if (ibuf == NULL)
						continue;

					if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
						BKE_image_release_ibuf(ima, ibuf, NULL);
						continue;
					}

					if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) {
						BKE_image_release_ibuf(ima, ibuf, NULL);
						continue;
					}
					
					if (ima->flag & IMA_USED_FOR_RENDER) {
						ima->id.flag &= ~LIB_DOIT;
						BKE_image_release_ibuf(ima, ibuf, NULL);
						continue;
					}
					
					/* find the image for the first time? */
					if (ima->id.flag & LIB_DOIT) {
						ima->id.flag &= ~LIB_DOIT;
						
						/* we either fill in float or char, this ensures things go fine */
						if (ibuf->rect_float)
							imb_freerectImBuf(ibuf);
						/* clear image */
						if (R.r.bake_flag & R_BAKE_CLEAR) {
							if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
								IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
							else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE))
								IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
							else
								IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
						}
						/* might be read by UI to set active image for display */
						R.bakebuf = ima;
					}

					/* Tag image for redraw. */
					ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
					BKE_image_release_ibuf(ima, ibuf, NULL);
				}

				bs->obi = obi;
				bs->vlr = vlr;
				bs->vdone++;  /* only for error message if nothing was rendered */
				v++;
				BLI_unlock_thread(LOCK_CUSTOM1);
				return 1;
			}
		}
	}
	
	BLI_unlock_thread(LOCK_CUSTOM1);
	return 0;
}
示例#23
0
int fluidsimBake(bContext *C, ReportList *reports, Object *ob)
{
	Scene *scene= CTX_data_scene(C);
	FILE *fileCfg;
	int i;
	Object *fsDomain = NULL;
	FluidsimSettings *domainSettings;
	Object *obit = NULL; /* object iterator */
	Base *base;
	int origFrame = scene->r.cfra;
	char debugStrBuffer[256];
	int dirExist = 0;
	int gridlevels = 0;
	int simAborted = 0; // was the simulation aborted by user?
	int  doExportOnly = 0;
	char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY";
	const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
	//char *channelNames[3] = { "translation","rotation","scale" };

	char *suffixConfig = "fluidsim.cfg";
	char *suffixSurface = "fluidsurface";
	char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings
	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
	int  haveSomeFluid = 0;                 // check if any fluid objects are set

	// config vars, inited before either export or run...
	double calcViscosity = 0.0;
	int noFrames;
	double aniFrameTime;
	float aniFrlen;
	int   channelObjCount;
	float *bbStart = NULL;
	float *bbSize = NULL;
	float domainMat[4][4];
	float invDomMat[4][4];
	// channel data
	int   allchannelSize; // fixed by no. of frames
	int   startFrame = 1;  // dont use scene->r.sfra here, always start with frame 1
	// easy frame -> sim time calc
	float *timeAtFrame=NULL, *timeAtIndex=NULL;
	// domain
	float *channelDomainTime = NULL;
	float *channelDomainViscosity = NULL; 
	float *channelDomainGravity = NULL;
	// objects (currently max. 256 objs)
	float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
	float *channelObjInivel[256];    // initial velocities
	float *channelObjActive[256];    // obj active channel
	
	/* fluid control channels */
	float *channelAttractforceStrength[256];
	float *channelAttractforceRadius[256];
	float *channelVelocityforceStrength[256];
	float *channelVelocityforceRadius[256];
	FluidsimModifierData *fluidmd = NULL;
	Mesh *mesh = NULL;
	
	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);
	}
	if(getenv(exportEnvStr)) {
		doExportOnly = atoi(getenv(exportEnvStr));
		snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr); 
		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.");
		return 0;
	}

	/* no object pointer, find in selected ones.. */
	if(!ob) {
		for(base=scene->base.first; base; base= base->next) {
			if ((base)->flag & SELECT) 
			{
				FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
				
				if(fluidmdtmp && (base->object->type==OB_MESH)) 
				{
					if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) 
					{
						ob = base->object;
						break;
					}
				}
			}
		}
		// no domains found?
		if(!ob) return 0;
	}
	
	channelObjCount = 0;
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		if( fluidmdtmp && 
			(obit->type==OB_MESH) &&
			(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
			(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) 
		{
			channelObjCount++;
		}
	}
	
	if (channelObjCount>=255) {
		BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects.");
		return 0;
	}

	/* check if there's another domain... */
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		if( fluidmdtmp &&(obit->type==OB_MESH)) 
		{
			if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) 
			{
				if(obit != ob) 
				{
					BKE_report(reports, RPT_ERROR, "There should be only one domain object.");
					return 0;
				}
			}
		}
	}
	
	// check if theres any fluid
	// abort baking if not...
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		if( fluidmdtmp && 
			(obit->type==OB_MESH) && 
			((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) ||
			(fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) ))
		{
			haveSomeFluid = 1;
			break;
		}
	}
	if(!haveSomeFluid) {
		BKE_report(reports, RPT_ERROR, "No fluid objects in scene.");
		return 0;
	}
	
	/* these both have to be valid, otherwise we wouldnt be here */
	/* dont use ob here after...*/
	fsDomain = ob;
	fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
	domainSettings = fluidmd->fss;
	ob = NULL;
	mesh = fsDomain->data;
	
	// 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 names...
	strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
	strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
	BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no 

	strcpy(targetFile, targetDir);
	strcat(targetFile, suffixConfig);
	if(!doExportOnly) { strcat(targetFile,".tmp"); }  // dont overwrite/delete original file
	// make sure all directories exist
	// as the bobjs use the same dir, this only needs to be checked
	// for the cfg output
	BLI_make_existing_file(targetFile);

	// check selected directory
	// simply try to open cfg file for writing to test validity of settings
	fileCfg = fopen(targetFile, "w");
	if(fileCfg) { 
		dirExist = 1; fclose(fileCfg); 
		// remove cfg dummy from  directory test
		if(!doExportOnly) { BLI_delete(targetFile, 0,0); }
	}

	if((strlen(targetDir)<1) || (!dirExist)) {
		char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE];
		// invalid dir, reset to current/previous
		strcpy(blendDir, G.sce);
		BLI_splitdirstring(blendDir, blendFile);
		if(strlen(blendFile)>6){
			int len = strlen(blendFile);
			if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&&
					(blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){
				blendFile[len-6] = '\0';
			}
		}
		// todo... strip .blend ?
		snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);

		snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
		elbeemDebugOut(debugStrBuffer);
		outStringsChanged=1;
	}

	// check if modified output dir is ok
	if(outStringsChanged) {
		char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256];
		int  selection=0;
		strcpy(dispmsg,"Output settings set to: '");
		strcat(dispmsg, newSurfdataPath);
		strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");

		// ask user if thats what he/she wants...
		selection = pupmenu(dispmsg);
		if(selection<1) return 0; // 0 from menu, or -1 aborted
		strcpy(targetDir, newSurfdataPath);
		strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
		BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no 
	}
	
	// --------------------------------------------------------------------------------------------
	// dump data for start frame 
	// CHECK more reasonable to number frames according to blender?
	// dump data for frame 0
	scene->r.cfra = startFrame;
	ED_update_for_newframe(C, 1);
	
	// init common export vars for both file export and run
	for(i=0; i<256; i++) {
		channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL;
		channelObjInivel[i] = NULL;
		channelObjActive[i] = NULL;
		channelAttractforceStrength[i] = NULL;
		channelAttractforceRadius[i] = NULL;
		channelVelocityforceStrength[i] = NULL;
		channelVelocityforceRadius[i] = NULL;
	}
	allchannelSize = scene->r.efra; // always use till last frame
	aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
	// blender specific - scale according to map old/new settings in anim panel:
	aniFrlen = scene->r.framelen;
	if(domainSettings->viscosityMode==1) {
		/* manual mode, visc=value/(10^-vexp) */
		calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue;
	} else {
		calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
	}

	bbStart = domainSettings->bbStart;
	bbSize = domainSettings->bbSize;

	// always init
	{ int timeIcu[1] = { FLUIDSIM_TIME };
		float timeDef[1] = { 1. };
		int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z };
		float gravDef[3];
		int viscIcu[1] = { FLUIDSIM_VISC };
		float viscDef[1] = { 1. };

		gravDef[0] = domainSettings->gravx;
		gravDef[1] = domainSettings->gravy;
		gravDef[2] = domainSettings->gravz;

		// 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 aniFrameTime
		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];
			}
		} else {
			for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
		}

		fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
		if(channelDomainViscosity) {
			for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; }
		}
		fluidsimInitChannel(scene, &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC );
	} // domain channel init
	
	// init obj movement channels
	channelObjCount=0;
	for(base=scene->base.first; base; base= base->next) 
	{
		FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
		obit = base->object;
		
		if( fluidmdtmp && 
			(obit->type==OB_MESH) &&
			(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
			(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) {

			//  cant use fluidsimInitChannel for obj channels right now, due
			//  to the special DXXX channels, and the rotation specialities
			IpoCurve *icuex[3][3];
			//IpoCurve *par_icuex[3][3];
#if 0
			int icuIds[3][3] = { 
				{OB_LOC_X,  OB_LOC_Y,  OB_LOC_Z},
				{OB_ROT_X,  OB_ROT_Y,  OB_ROT_Z},
				{OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z} 
			};
			int icudIds[3][3] = { 
				{OB_DLOC_X,  OB_DLOC_Y,  OB_DLOC_Z},
				{OB_DROT_X,  OB_DROT_Y,  OB_DROT_Z},
				{OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z} 
			};
#endif
			// relative ipos
			IpoCurve *icudex[3][3];
			//IpoCurve *par_icudex[3][3];
			int j,k;
			float vals[3] = {0.0,0.0,0.0}; 
			int o = channelObjCount;
			int   inivelIcu[3] =  { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z };
			float inivelDefs[3];
			int   activeIcu[1] =  { FLUIDSIM_ACTIVE };
			float activeDefs[1] = { 1 }; // default to on

			inivelDefs[0] = fluidmdtmp->fss->iniVelx;
			inivelDefs[1] = fluidmdtmp->fss->iniVely;
			inivelDefs[2] = fluidmdtmp->fss->iniVelz;

			// check & init loc,rot,size
			for(j=0; j<3; j++) {
				for(k=0; k<3; k++) {
					// XXX prevent invalid memory access until this works
					icuex[j][k]= NULL;
					icudex[j][k]= NULL;

					// XXX icuex[j][k]  = find_ipocurve(obit->ipo, icuIds[j][k] );
					// XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] );
					// XXX lines below were already disabled!
					//if(obit->parent) {
						//par_icuex[j][k]  = find_ipocurve(obit->parent->ipo, icuIds[j][k] );
						//par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] );
					//}
				}
			}

			for(j=0; j<3; j++) {
				channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel");
				for(i=1; i<=allchannelSize; i++) {

					for(k=0; k<3; k++) {
						if(icuex[j][k]) { 
							// IPO exists, use it ...
							// XXX calc_icu(icuex[j][k], aniFrlen*((float)i) );
							vals[k] = icuex[j][k]->curval; 
							if(obit->parent) {
								// add parent transform, multiply scaling, add trafo&rot
								//calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
								//if(j==2) { vals[k] *= par_icuex[j][k]->curval; }
								//else { vals[k] += par_icuex[j][k]->curval; }
							}
						} else {
							// use defaults from static values
							float setval=0.0;
							if(j==0) { 
								setval = obit->loc[k];
								if(obit->parent){ setval += obit->parent->loc[k]; }
							} else if(j==1) { 
								setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI );
								if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); }
							} else { 
								setval = obit->size[k]; 
								if(obit->parent){ setval *= obit->parent->size[k]; }
							}
							vals[k] = setval;
						}
						if(icudex[j][k]) { 
							// XXX calc_icu(icudex[j][k], aniFrlen*((float)i) );
							//vals[k] += icudex[j][k]->curval; 
							// add transform, multiply scaling, add trafo&rot
							if(j==2) { vals[k] *= icudex[j][k]->curval; }
							else { vals[k] += icudex[j][k]->curval; }
							if(obit->parent) {
								// add parent transform, multiply scaling, add trafo&rot
								//calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
								//if(j==2) { vals[k] *= par_icudex[j][k]->curval; }
								//else { vals[k] += par_icudex[j][k]->curval; }
							}
						} 
					} // k

					for(k=0; k<3; k++) {
						float set = vals[k];
						if(j==1) { // rot is downscaled by 10 for ipo !?
							set = 360.0 - (10.0*set);
						}
						channelObjMove[o][j][(i-1)*4 + k] = set;
					} // k
					channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i];
				}
			}
			
			{
				int   attrFSIcu[1] =  { FLUIDSIM_ATTR_FORCE_STR };
				int   attrFRIcu[1] =  { FLUIDSIM_ATTR_FORCE_RADIUS };
				int   velFSIcu[1] =  { FLUIDSIM_VEL_FORCE_STR };
				int   velFRIcu[1] =  { FLUIDSIM_VEL_FORCE_RADIUS };

				float attrFSDefs[1];
				float attrFRDefs[1];
				float velFSDefs[1];
				float velFRDefs[1];
				
				attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength;
				attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius;
				velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength;
				velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius;
				
				fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
				fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
				fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
				fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
			}
			
			fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC );
			fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
		

			channelObjCount++;

		}
	}

	// init trafo matrix
	Mat4CpyMat4(domainMat, fsDomain->obmat);
	if(!Mat4Invert(invDomMat, domainMat)) {
		snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); 
		elbeemDebugOut(debugStrBuffer);
		BKE_report(reports, RPT_ERROR, "Invalid object matrix."); 
		// FIXME add fatal msg
		FS_FREE_CHANNELS;
		return 0;
	}

	// --------------------------------------------------------------------------------------------
	// start writing / exporting
	strcpy(targetFile, targetDir);
	strcat(targetFile, suffixConfig);
	if(!doExportOnly) { strcat(targetFile,".tmp"); }  // dont overwrite/delete original file
	// make sure these directories exist as well
	if(outStringsChanged) {
		BLI_make_existing_file(targetFile);
	}

	if(!doExportOnly) {
		ListBase threads;

		// perform simulation with El'Beem api and threads
		elbeemSimulationSettings fsset;
		elbeemResetSettings(&fsset);
		fsset.version = 1;

		// setup global settings
		for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i];
		for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i];
		
		// simulate with 50^3
		fsset.resolutionxyz = (int)domainSettings->resolutionxyz;
		fsset.previewresxyz = (int)domainSettings->previewresxyz;
		// 10cm water domain
		fsset.realsize = domainSettings->realsize;
		fsset.viscosity = calcViscosity;
		// earth gravity
		fsset.gravity[0] = domainSettings->gravx;
		fsset.gravity[1] = domainSettings->gravy;
		fsset.gravity[2] = domainSettings->gravz;
		// simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
		fsset.animStart = domainSettings->animStart;
		fsset.aniFrameTime = aniFrameTime;
		fsset.noOfFrames = noFrames; // is otherwise subtracted in parser
		strcpy(targetFile, targetDir);
		strcat(targetFile, 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; 
		strcpy( fsset.outputPath, targetFile);

		// domain channels
		fsset.channelSizeFrameTime = 
		fsset.channelSizeViscosity = 
		fsset.channelSizeGravity =  allchannelSize;
		fsset.channelFrameTime = channelDomainTime;
		fsset.channelViscosity = channelDomainViscosity;
		fsset.channelGravity = channelDomainGravity;

		fsset.runsimCallback = &runSimulationCallback;
		fsset.runsimUserData = &fsset;

		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 trafo matrix
 		// fprintf(stderr,"elbeemInit - mpTrafo:\n");
		{ int j; 
		for(i=0; i<4; i++) {
			for(j=0; j<4; j++) {
				fsset.surfaceTrafo[i*4+j] = invDomMat[j][i];
 				// fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) );
			}
		} }

	  // init solver with settings
		elbeemInit();
		elbeemAddDomain(&fsset);
		
		// init objects
		channelObjCount = 0;
		for(base=scene->base.first; base; base= base->next) {
			FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
			obit = base->object;
			//{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
			if( fluidmdtmp &&  // if has to match 3 places! // CHECKMATCH
				(obit->type==OB_MESH) &&
				(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&
				(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE)) 
			{
				float *verts=NULL;
				int *tris=NULL;
				int numVerts=0, numTris=0;
				int o = channelObjCount;
				int	deform = (fluidmdtmp->fss->domainNovecgen); // misused value
				// todo - use blenderInitElbeemMesh
				int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp);
				
				elbeemMesh fsmesh;
				elbeemResetMesh( &fsmesh );
				fsmesh.type = fluidmdtmp->fss->type;
				// get name of object for debugging solver
				fsmesh.name = obit->id.name; 

				initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
				fsmesh.numVertices   = numVerts;
				fsmesh.numTriangles  = numTris;
				fsmesh.vertices      = verts;
				fsmesh.triangles     = tris;

				fsmesh.channelSizeTranslation  = 
				fsmesh.channelSizeRotation     = 
				fsmesh.channelSizeScale        = 
				fsmesh.channelSizeInitialVel   = 
				fsmesh.channelSizeActive       = allchannelSize;

				fsmesh.channelTranslation      = channelObjMove[o][0];
				fsmesh.channelRotation         = channelObjMove[o][1];
				fsmesh.channelScale            = channelObjMove[o][2];
				fsmesh.channelActive           = channelObjActive[o];
				if( (fsmesh.type == OB_FLUIDSIM_FLUID) ||
				(fsmesh.type == OB_FLUIDSIM_INFLOW)) {
					fsmesh.channelInitialVel       = channelObjInivel[o];
					fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
				} 

				if(     (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP))   fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
				else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
				else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
				fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue;
				fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType;
				fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value
				
				if(fsmesh.type == OB_FLUIDSIM_CONTROL)
				{
					// control fluids will get exported as whole
					deform = 1;
					
					fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart;
					fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd;
					fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality;
					fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE);
					
					fsmesh.channelSizeAttractforceRadius = 
					fsmesh.channelSizeVelocityforceStrength = 
					fsmesh.channelSizeVelocityforceRadius = 
					fsmesh.channelSizeAttractforceStrength = allchannelSize;
					
					fsmesh.channelAttractforceStrength = channelAttractforceStrength[o];
					fsmesh.channelAttractforceRadius = channelAttractforceRadius[o];
					fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o];
					fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o];
				}
				else 
				{
					// set channels to 0
					fsmesh.channelAttractforceStrength =
					fsmesh.channelAttractforceRadius = 
					fsmesh.channelVelocityforceStrength = 
					fsmesh.channelVelocityforceRadius = NULL; 
				}

				// animated meshes
				if(deform) {
					fsmesh.channelSizeVertices = allchannelSize;
					fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex);
					scene->r.cfra = startFrame;
					ED_update_for_newframe(C, 1);
					// remove channels
					fsmesh.channelTranslation      = 
					fsmesh.channelRotation         = 
					fsmesh.channelScale            = NULL; 
				} 

				elbeemAddMesh(&fsmesh);

				if(verts) MEM_freeN(verts);
				if(tris) MEM_freeN(tris);
				if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices);
				channelObjCount++;
			} // valid mesh
		} // objects
		//domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again
		
		// set to neutral, -1 means user abort, -2 means init error
		globalBakeState = 0;
		globalBakeFrame = 0;
		BLI_init_threads(&threads, fluidsimSimulateThread, 1);
		BLI_insert_thread(&threads, targetFile);
		
		{
			int done = 0;
			float noFramesf = (float)noFrames;
			float percentdone = 0.0;
			int lastRedraw = -1;
			
			g_break= 0;
			G.afbreek= 0;	/* blender_test_break uses this global */
			
			start_progress_bar();

			while(done==0) {
				char busy_mess[80];
				
				waitcursor(1);
				
				// lukep we add progress bar as an interim mesure
				percentdone = globalBakeFrame / noFramesf;
				sprintf(busy_mess, "baking fluids %d / %d       |||", globalBakeFrame, (int) noFramesf);
				progress_bar(percentdone, busy_mess );
				
				// longer delay to prevent frequent redrawing
				PIL_sleep_ms(2000);
				
				BLI_lock_thread(LOCK_CUSTOM1);
				if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort
				BLI_unlock_thread(LOCK_CUSTOM1);

				if (!G.background) {
					g_break= blender_test_break();
					
					if(g_break)
					{
						// abort...
						BLI_lock_thread(LOCK_CUSTOM1);
						
						if(domainSettings)
							domainSettings->lastgoodframe = startFrame+globalBakeFrame;
						
						done = -1;
						globalBakeFrame = 0;
						globalBakeState = -1;
						simAborted = 1;
						BLI_unlock_thread(LOCK_CUSTOM1);
						break;
					}
				} 

				// redraw the 3D for showing progress once in a while...
				if(lastRedraw!=globalBakeFrame) {
#if 0					
					ScrArea *sa;
					scene->r.cfra = startFrame+globalBakeFrame;
					lastRedraw = globalBakeFrame;
					ED_update_for_newframe(C, 1);
					sa= G.curscreen->areabase.first;
					while(sa) {
						if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); }
						sa= sa->next;	
					} 
					screen_swapbuffers();
#endif
				} // redraw
			}
			end_progress_bar();
		}
		BLI_end_threads(&threads);
	} // El'Beem API init, thread creation 
	// --------------------------------------------------------------------------------------------
	else
	{ // write config file to be run with command line simulator
		BKE_report(reports, RPT_WARNING, "Config file export not supported.");
	} // config file export done!

	// --------------------------------------------------------------------------------------------
	FS_FREE_CHANNELS;

	// go back to "current" blender time
	waitcursor(0);
	
	if(globalBakeState >= 0)
	{
		if(domainSettings)
			domainSettings->lastgoodframe = startFrame+globalBakeFrame;
	}
	
	scene->r.cfra = origFrame;
	ED_update_for_newframe(C, 1);

	if(!simAborted) {
		char elbeemerr[256];

		// check if some error occurred
		if(globalBakeState==-2) {
			elbeemGetErrorString(elbeemerr);
			BKE_reportf(reports, RPT_ERROR, "Failed to initialize [Msg: %s]", elbeemerr);
			return 0;
		} // init error
	}
	
	// elbeemFree();
	return 1;
}
static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
                                int clip_index,
                                int frame,
                                libmv_InputMode input_mode,
                                int downscale,
                                const libmv_Region *region,
                                const libmv_FrameTransform *transform)
{
	ImBuf *ibuf, *orig_ibuf, *final_ibuf;
	int64_t transform_key = 0;

	if (transform != NULL) {
		transform_key = libmv_frameAccessorgetTransformKey(transform);
	}

	/* First try to get fully processed image from the cache. */
	ibuf = accesscache_get(accessor,
	                       clip_index,
	                       frame,
	                       input_mode,
	                       downscale,
	                       transform_key);
	if (ibuf != NULL) {
		return ibuf;
	}

	/* And now we do postprocessing of the original frame. */
	orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);

	if (orig_ibuf == NULL) {
		return NULL;
	}

	if (region != NULL) {
		int width = region->max[0] - region->min[0],
		    height = region->max[1] - region->min[1];

		/* If the requested region goes outside of the actual frame we still
		 * return the requested region size, but only fill it's partially with
		 * the data we can.
		 */
		int clamped_origin_x = max_ii((int)region->min[0], 0),
		    clamped_origin_y = max_ii((int)region->min[1], 0);
		int dst_offset_x = clamped_origin_x - (int)region->min[0],
		    dst_offset_y = clamped_origin_y - (int)region->min[1];
		int clamped_width = width - dst_offset_x,
		    clamped_height = height - dst_offset_y;
		clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x);
		clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y);

		final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat);

		if (orig_ibuf->rect_float != NULL) {
			IMB_rectcpy(final_ibuf, orig_ibuf,
			            dst_offset_x, dst_offset_y,
			            clamped_origin_x, clamped_origin_y,
			            clamped_width, clamped_height);
		}
		else {
			int y;
			/* TODO(sergey): We don't do any color space or alpha conversion
			 * here. Probably Libmv is better to work in the linear space,
			 * but keep sRGB space here for compatibility for now.
			 */
			for (y = 0; y < clamped_height; ++y) {
				int x;
				for (x = 0; x < clamped_width; ++x) {
					int src_x = x + clamped_origin_x,
					    src_y = y + clamped_origin_y;
					int dst_x = x + dst_offset_x,
					    dst_y = y + dst_offset_y;
					int dst_index = (dst_y * width + dst_x) * 4,
					    src_index = (src_y * orig_ibuf->x + src_x) * 4;
					rgba_uchar_to_float(final_ibuf->rect_float + dst_index,
					                    (unsigned char *)orig_ibuf->rect +
					                                     src_index);
				}
			}
		}
	}
	else {
		/* Libmv only works with float images,
		 *
		 * This would likely make it so loads of float buffers are being stored
		 * in the cache which is nice on the one hand (faster re-use of the
		 * frames) but on the other hand it bumps the memory usage up.
		 */
		BLI_lock_thread(LOCK_MOVIECLIP);
		IMB_float_from_rect(orig_ibuf);
		BLI_unlock_thread(LOCK_MOVIECLIP);
		final_ibuf = orig_ibuf;
	}

	if (downscale > 0) {
		if (final_ibuf == orig_ibuf) {
			final_ibuf = IMB_dupImBuf(orig_ibuf);
		}
		IMB_scaleImBuf(final_ibuf,
		               ibuf->x / (1 << downscale),
		               ibuf->y / (1 << downscale));
	}

	if (transform != NULL) {
		libmv_FloatImage input_image, output_image;
		ibuf_to_float_image(final_ibuf, &input_image);
		libmv_frameAccessorgetTransformRun(transform,
		                                   &input_image,
		                                   &output_image);
		if (final_ibuf != orig_ibuf) {
			IMB_freeImBuf(final_ibuf);
		}
		final_ibuf = float_image_to_ibuf(&output_image);
		libmv_floatImageDestroy(&output_image);
	}

	if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
		BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
		/* pass */
	}
	else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
		if (final_ibuf->channels != 1) {
			ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
			if (final_ibuf != orig_ibuf) {
				/* We dereference original frame later. */
				IMB_freeImBuf(final_ibuf);
			}
			final_ibuf = grayscale_ibuf;
		}
	}

	/* it's possible processing still didn't happen at this point,
	 * but we really need a copy of the buffer to be transformed
	 * and to be put to the cache.
	 */
	if (final_ibuf == orig_ibuf) {
		final_ibuf = IMB_dupImBuf(orig_ibuf);
	}

	IMB_freeImBuf(orig_ibuf);

	/* We put postprocessed frame to the cache always for now,
	 * not the smartest thing in the world, but who cares at this point.
	 */

	/* TODO(sergey): Disable cache for now, because we don't store region
	 * in the cache key and can't check whether cached version is usable for
	 * us or not.
	 *
	 * Need to think better about what to cache and when.
	 */
	if (false) {
		accesscache_put(accessor,
		                clip_index,
		                frame,
		                input_mode,
		                downscale,
		                transform_key,
		                final_ibuf);
	}

	return final_ibuf;
}
示例#25
0
文件: ocean.c 项目: akonneker/blensor
void BKE_free_ocean_data(struct Ocean *oc)
{
	if (!oc) return;

	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE);

	BLI_lock_thread(LOCK_FFTW);

	if (oc->_do_disp_y) {
		fftw_destroy_plan(oc->_disp_y_plan);
		MEM_freeN(oc->_disp_y);
	}

	if (oc->_do_normals) {
		MEM_freeN(oc->_fft_in_nx);
		MEM_freeN(oc->_fft_in_nz);
		fftw_destroy_plan(oc->_N_x_plan);
		fftw_destroy_plan(oc->_N_z_plan);
		MEM_freeN(oc->_N_x);
		/*fftwf_free(oc->_N_y); (MEM01)*/
		MEM_freeN(oc->_N_z);
	}

	if (oc->_do_chop) {
		MEM_freeN(oc->_fft_in_x);
		MEM_freeN(oc->_fft_in_z);
		fftw_destroy_plan(oc->_disp_x_plan);
		fftw_destroy_plan(oc->_disp_z_plan);
		MEM_freeN(oc->_disp_x);
		MEM_freeN(oc->_disp_z);
	}

	if (oc->_do_jacobian) {
		MEM_freeN(oc->_fft_in_jxx);
		MEM_freeN(oc->_fft_in_jzz);
		MEM_freeN(oc->_fft_in_jxz);
		fftw_destroy_plan(oc->_Jxx_plan);
		fftw_destroy_plan(oc->_Jzz_plan);
		fftw_destroy_plan(oc->_Jxz_plan);
		MEM_freeN(oc->_Jxx);
		MEM_freeN(oc->_Jzz);
		MEM_freeN(oc->_Jxz);
	}

	BLI_unlock_thread(LOCK_FFTW);

	if (oc->_fft_in)
		MEM_freeN(oc->_fft_in);

	/* check that ocean data has been initialized */
	if (oc->_htilda) {
		MEM_freeN(oc->_htilda);
		MEM_freeN(oc->_k);
		MEM_freeN(oc->_h0);
		MEM_freeN(oc->_h0_minus);
		MEM_freeN(oc->_kx);
		MEM_freeN(oc->_kz);
	}

	BLI_rw_mutex_unlock(&oc->oceanmutex);
}