Ejemplo n.º 1
0
void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel),
                    void *update_cb_data)
{
	/* note: some of these values remain uninitialized unless certain options
	 * are enabled, take care that BKE_ocean_eval_ij() initializes a member
	 * before use - campbell */
	OceanResult ocr;

	ImageFormatData imf = {0};

	int f, i = 0, x, y, cancel = 0;
	float progress;

	ImBuf *ibuf_foam, *ibuf_disp, *ibuf_normal;
	float *prev_foam;
	int res_x = och->resolution_x;
	int res_y = och->resolution_y;
	char string[FILE_MAX];

	if (!o) return;

	if (o->_do_jacobian) prev_foam = MEM_callocN(res_x * res_y * sizeof(float), "previous frame foam bake data");
	else prev_foam = NULL;

	BLI_srand(0);

	/* setup image format */
	imf.imtype = R_IMF_IMTYPE_OPENEXR;
	imf.depth =  R_IMF_CHAN_DEPTH_16;
	imf.exr_codec = R_IMF_EXR_CODEC_ZIP;

	for (f = och->start, i = 0; f <= och->end; f++, i++) {

		/* create a new imbuf to store image for this frame */
		ibuf_foam = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
		ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
		ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);

		BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount);

		/* add new foam */
		for (y = 0; y < res_y; y++) {
			for (x = 0; x < res_x; x++) {

				BKE_ocean_eval_ij(o, &ocr, x, y);

				/* add to the image */
				rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp);

				if (o->_do_jacobian) {
					/* TODO, cleanup unused code - campbell */

					float /*r, */ /* UNUSED */ pr = 0.0f, foam_result;
					float neg_disp, neg_eplus;

					ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, och->foam_coverage);

					/* accumulate previous value for this cell */
					if (i > 0) {
						pr = prev_foam[res_x * y + x];
					}

					/* r = BLI_frand(); */ /* UNUSED */ /* randomly reduce foam */

					/* pr = pr * och->foam_fade; */		/* overall fade */

					/* remember ocean coord sys is Y up!
					 * break up the foam where height (Y) is low (wave valley), and X and Z displacement is greatest
					 */

#if 0
					vec[0] = ocr.disp[0];
					vec[1] = ocr.disp[2];
					hor_stretch = len_v2(vec);
					CLAMP(hor_stretch, 0.0, 1.0);
#endif

					neg_disp = ocr.disp[1] < 0.0f ? 1.0f + ocr.disp[1] : 1.0f;
					neg_disp = neg_disp < 0.0f ? 0.0f : neg_disp;

					/* foam, 'ocr.Eplus' only initialized with do_jacobian */
					neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2] : 1.0f;
					neg_eplus = neg_eplus < 0.0f ? 0.0f : neg_eplus;

#if 0
					if (ocr.disp[1] < 0.0 || r > och->foam_fade)
						pr *= och->foam_fade;


					pr = pr * (1.0 - hor_stretch) * ocr.disp[1];
					pr = pr * neg_disp * neg_eplus;
#endif

					if (pr < 1.0f)
						pr *= pr;

					pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f);

					/* A full clamping should not be needed! */
					foam_result = min_ff(pr + ocr.foam, 1.0f);

					prev_foam[res_x * y + x] = foam_result;

					/*foam_result = min_ff(foam_result, 1.0f); */

					value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result);
				}

				if (o->_do_normals) {
					rgb_to_rgba_unit_alpha(&ibuf_normal->rect_float[4 * (res_x * y + x)], ocr.normal);
				}
			}
		}

		/* write the images */
		cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_DISPLACE);
		if (0 == BKE_imbuf_write(ibuf_disp, string, &imf))
			printf("Cannot save Displacement File Output to %s\n", string);

		if (o->_do_jacobian) {
			cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_FOAM);
			if (0 == BKE_imbuf_write(ibuf_foam, string, &imf))
				printf("Cannot save Foam File Output to %s\n", string);
		}

		if (o->_do_normals) {
			cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_NORMAL);
			if (0 == BKE_imbuf_write(ibuf_normal, string, &imf))
				printf("Cannot save Normal File Output to %s\n", string);
		}

		IMB_freeImBuf(ibuf_disp);
		IMB_freeImBuf(ibuf_foam);
		IMB_freeImBuf(ibuf_normal);

		progress = (f - och->start) / (float)och->duration;

		update_cb(update_cb_data, progress, &cancel);

		if (cancel) {
			if (prev_foam) MEM_freeN(prev_foam);
			return;
		}
	}

	if (prev_foam) MEM_freeN(prev_foam);
	och->baked = 1;
}
Ejemplo n.º 2
0
static DerivedMesh *doOcean(ModifierData *md, Object *ob,
                            DerivedMesh *derivedData,
                            int UNUSED(useRenderParams))
{
	OceanModifierData *omd = (OceanModifierData *) md;

	DerivedMesh *dm = NULL;
	OceanResult ocr;

	MVert *mverts, *mv;
	MLoop *mloops;

	int i, j;

	int num_verts;
	int num_faces;

	int cfra;

	/* use cached & inverted value for speed
	 * expanded this would read...
	 *
	 * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
#define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)

	const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);

	/* can happen in when size is small, avoid bad array lookups later and quit now */
	if (!finite(size_co_inv)) {
		return derivedData;
	}

	/* update modifier */
	if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
		omd->ocean = BKE_ocean_add();
	if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
		init_ocean_modifier(omd);
	if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
		clear_cache_data(omd);

	omd->refresh = 0;

	/* do ocean simulation */
	if (omd->cached == true) {
		if (!omd->oceancache) init_cache_data(ob, omd);
		BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
	}
	else {
		simulate_ocean_modifier(omd);
	}

	if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
		dm = generate_ocean_geometry(omd);
		DM_ensure_normals(dm);
	}
	else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
		dm = CDDM_copy(derivedData);
	}

	cfra = md->scene->r.cfra;
	CLAMP(cfra, omd->bakestart, omd->bakeend);
	cfra -= omd->bakestart; /* shift to 0 based */

	num_verts = dm->getNumVerts(dm);
	num_faces = dm->getNumPolys(dm);

	mverts = dm->getVertArray(dm);
	mloops = dm->getLoopArray(dm);

	/* add vcols before displacement - allows lookup based on position */

	if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
		int cdlayer = CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL);

		if (cdlayer < MAX_MCOL) {
			MLoopCol *mloopcols = CustomData_add_layer_named(&dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL,
			                                                 num_faces * 4, omd->foamlayername);

			if (mloopcols) { /* unlikely to fail */
				MLoopCol *mlcol;
				MPoly *mpolys = dm->getPolyArray(dm);
				MPoly *mp;

				float foam;

				for (i = 0, mp = mpolys; i < num_faces; i++, mp++) {
					j = mp->totloop - 1;

					/* highly unlikely */
					if (j <= 0) continue;

					do {
						const float *co = mverts[mloops[mp->loopstart + j].v].co;
						const float u = OCEAN_CO(size_co_inv, co[0]);
						const float v = OCEAN_CO(size_co_inv, co[1]);

						if (omd->oceancache && omd->cached == true) {
							BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
							foam = ocr.foam;
							CLAMP(foam, 0.0f, 1.0f);
						}
						else {
							BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
							foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
						}

						mlcol = &mloopcols[mp->loopstart + j];
						mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
						/* This needs to be set (render engine uses) */
						mlcol->a = 255;
					} while (j--);
				}
			}
		}
	}


	/* displace the geometry */

	/* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
	for (i = 0, mv = mverts; i < num_verts; i++, mv++) {
		const float u = OCEAN_CO(size_co_inv, mv->co[0]);
		const float v = OCEAN_CO(size_co_inv, mv->co[1]);

		if (omd->oceancache && omd->cached == true)
			BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
		else
			BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);

		mv->co[2] += ocr.disp[1];

		if (omd->chop_amount > 0.0f) {
			mv->co[0] += ocr.disp[0];
			mv->co[1] += ocr.disp[2];
		}
	}

#undef OCEAN_CO

	return dm;
}
Ejemplo n.º 3
0
/* ***** actual texture sampling ***** */
int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
{
	OceanTex *ot = tex->ot;
	ModifierData *md;
	OceanModifierData *omd;

	texres->tin = 0.0f;

	if ( !(ot) ||
	     !(ot->object) ||
	     !(md  = (ModifierData *)modifiers_findByType(ot->object, eModifierType_Ocean)) ||
	     !(omd = (OceanModifierData *)md)->ocean)
	{
		return 0;
	}
	else {
		const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
		int cfra = R.r.cfra;
		int retval = TEX_INT;

		OceanResult ocr;
		const float u = 0.5f + 0.5f * texvec[0];
		const float v = 0.5f + 0.5f * texvec[1];

		if (omd->oceancache && omd->cached == true) {

			CLAMP(cfra, omd->bakestart, omd->bakeend);
			cfra -= omd->bakestart;	/* shift to 0 based */

			BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);

		}
		else {	/* non-cached */

			if (G.is_rendering)
				BKE_ocean_eval_uv_catrom(omd->ocean, &ocr, u, v);
			else
				BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);

			ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
		}

		switch (ot->output) {
			case TEX_OCN_DISPLACEMENT:
				/* XYZ displacement */
				texres->tr = 0.5f + 0.5f * ocr.disp[0];
				texres->tg = 0.5f + 0.5f * ocr.disp[2];
				texres->tb = 0.5f + 0.5f * ocr.disp[1];

				texres->tr = MAX2(0.0f, texres->tr);
				texres->tg = MAX2(0.0f, texres->tg);
				texres->tb = MAX2(0.0f, texres->tb);

				BRICONTRGB;

				retval = TEX_RGB;
				break;

			case TEX_OCN_EMINUS:
				/* -ve eigenvectors ? */
				texres->tr = ocr.Eminus[0];
				texres->tg = ocr.Eminus[2];
				texres->tb = ocr.Eminus[1];
				retval = TEX_RGB;
				break;

			case TEX_OCN_EPLUS:
				/* -ve eigenvectors ? */
				texres->tr = ocr.Eplus[0];
				texres->tg = ocr.Eplus[2];
				texres->tb = ocr.Eplus[1];
				retval = TEX_RGB;
				break;

			case TEX_OCN_JPLUS:
				texres->tin = ocr.Jplus;
				retval = TEX_INT;
				break;

			case TEX_OCN_FOAM:

				texres->tin = ocr.foam;

				BRICONT;

				retval = TEX_INT;
				break;
		}

		/* if normals needed */

		if (texres->nor && do_normals) {
			normalize_v3_v3(texres->nor, ocr.normal);
			retval |= TEX_NOR;
		}

		texres->ta = 1.0f;

		return retval;
	}
}