Esempio n. 1
0
static int lattice_select_random_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;

	const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
	const int seed = RNA_int_get(op->ptr, "seed");
	const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);

	RNG *rng = BLI_rng_new_srandom(seed);

	int tot;
	BPoint *bp;

	tot = lt->pntsu * lt->pntsv * lt->pntsw;
	bp = lt->def;
	while (tot--) {
		if (!bp->hide) {
			if (BLI_rng_get_float(rng) < randfac) {
				bpoint_select_set(bp, select);
			}
		}
		bp++;
	}

	if (select == false) {
		lt->actbp = LT_ACTBP_NONE;
	}

	BLI_rng_free(rng);

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);

	return OPERATOR_FINISHED;
}
Esempio n. 2
0
/* Random metaball selection */
static int select_random_metaelems_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	MetaBall *mb = (MetaBall *)obedit->data;
	MetaElem *ml;
	const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
	const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
	const int seed = RNA_int_get(op->ptr, "seed");
	
	RNG *rng = BLI_rng_new_srandom(seed);

	for (ml = mb->editelems->first; ml; ml = ml->next) {
		if (BLI_rng_get_float(rng) < randfac) {
			if (select)
				ml->flag |= SELECT;
			else
				ml->flag &= ~SELECT;
		}
	}

	BLI_rng_free(rng);

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
	
	return OPERATOR_FINISHED;
}
Esempio n. 3
0
/* -------------------------- Effectors ------------------ */
void free_partdeflect(PartDeflect *pd)
{
	if (!pd)
		return;

	if (pd->tex)
		id_us_min(&pd->tex->id);

	if (pd->rng)
		BLI_rng_free(pd->rng);

	MEM_freeN(pd);
}
Esempio n. 4
0
/* -------------------------- Effectors ------------------ */
void free_partdeflect(PartDeflect *pd)
{
	if (!pd)
		return;

	if (pd->tex)
		pd->tex->id.us--;

	if (pd->rng)
		BLI_rng_free(pd->rng);

	MEM_freeN(pd);
}
Esempio n. 5
0
void BLI_jitter_init(float (*jitarr)[2], int num)
{
	float (*jit2)[2];
	float num_fl, num_fl_sqrt;
	float x, rad1, rad2, rad3;
	RNG *rng;
	int i;

	if (num == 0) {
		return;
	}

	num_fl = (float)num;
	num_fl_sqrt = sqrtf(num_fl);

	jit2 = MEM_mallocN(12 + (unsigned int)num * sizeof(float[2]), "initjit");
	rad1 = 1.0f        / num_fl_sqrt;
	rad2 = 1.0f        / num_fl;
	rad3 = num_fl_sqrt / num_fl;

	rng = BLI_rng_new(31415926 + (unsigned int)num);

	x = 0;
	for (i = 0; i < num; i++) {
		jitarr[i][0] =                 x + rad1 * (float)(0.5 - BLI_rng_get_double(rng));
		jitarr[i][1] = (float)i / num_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng));
		x += rad3;
		x -= floorf(x);
	}

	BLI_rng_free(rng);

	for (i = 0; i < 24; i++) {
		BLI_jitterate1(jitarr, jit2, num, rad1);
		BLI_jitterate1(jitarr, jit2, num, rad1);
		BLI_jitterate2(jitarr, jit2, num, rad2);
	}

	MEM_freeN(jit2);
	
	/* finally, move jittertab to be centered around (0, 0) */
	for (i = 0; i < num; i++) {
		jitarr[i][0] -= 0.5f;
		jitarr[i][1] -= 0.5f;
	}
}
Esempio n. 6
0
static bool object_rand_transverts(
        TransVertStore *tvs,
        const float offset, const float uniform, const float normal_factor,
        const unsigned int seed)
{
	bool use_normal = (normal_factor != 0.0f);
	struct RNG *rng;
	TransVert *tv;
	int a;

	if (!tvs || !(tvs->transverts)) {
		return false;
	}

	rng = BLI_rng_new(seed);

	tv = tvs->transverts;
	for (a = 0; a < tvs->transverts_tot; a++, tv++) {
		const float t = max_ff(0.0f, uniform + ((1.0f - uniform) * BLI_rng_get_float(rng)));
		float vec[3];
		BLI_rng_get_float_unit_v3(rng, vec);

		if (use_normal && (tv->flag & TX_VERT_USE_NORMAL)) {
			float no[3];

			/* avoid >90d rotation to align with normal */
			if (dot_v3v3(vec, tv->normal) < 0.0f) {
				negate_v3_v3(no, tv->normal);
			}
			else {
				copy_v3_v3(no, tv->normal);
			}

			interp_v3_v3v3_slerp_safe(vec, vec, no, normal_factor);
		}

		madd_v3_v3fl(tv->loc, vec, offset * t);
	}

	BLI_rng_free(rng);

	return true;
}
Esempio n. 7
0
/* modified copy from rayshade.c */
static void hammersley_create(float *out, int n, int seed, float amount)
{
	RNG *rng;
	double p, t, offs[2];
	int k, kk;

	rng = BLI_rng_new(31415926 + n + seed);
	offs[0] = BLI_rng_get_double(rng) + (double)amount;
	offs[1] = BLI_rng_get_double(rng) + (double)amount;
	BLI_rng_free(rng);

	for (k = 0; k < n; k++) {
		t = 0;
		for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
			if (kk & 1) /* kk mod 2 = 1 */
				t += p;

		out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
		out[2*k + 1] = fmod(t + offs[1], 1.0);
	}
}
Esempio n. 8
0
static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select)
{
	Nurb *nu;
	BezTriple *bezt;
	BPoint *bp;
	int a;

	RNG *rng = BLI_rng_new_srandom(seed);

	for (nu = editnurb->first; nu; nu = nu->next) {
		if (nu->type == CU_BEZIER) {
			bezt = nu->bezt;
			a = nu->pntsu;
			while (a--) {
				if (!bezt->hide) {
					if (BLI_rng_get_float(rng) < randfac) {
						select_beztriple(bezt, select, SELECT, VISIBLE);
					}
				}
				bezt++;
			}
		}
		else {
			bp = nu->bp;
			a = nu->pntsu * nu->pntsv;

			while (a--) {
				if (!bp->hide) {
					if (BLI_rng_get_float(rng) < randfac) {
						select_bpoint(bp, select, SELECT, VISIBLE);
					}
				}
				bp++;
			}
		}
	}

	BLI_rng_free(rng);
}
Esempio n. 9
0
Noise::Noise(long seed)
{
  /* Use Blender RNG for repeatable results across platforms. */
  RNG *rng = BLI_rng_new(seed);
  int i, j, k;

  for (i = 0; i < _NOISE_B; i++) {
    p[i] = i;
    g1[i] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;

    for (j = 0; j < 2; j++)
      g2[i][j] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
    normalize2(g2[i]);

    for (j = 0; j < 3; j++)
      g3[i][j] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
    normalize3(g3[i]);
  }

  while (--i) {
    k = p[i];
    p[i] = p[j = BLI_rng_get_int(rng) % _NOISE_B];
    p[j] = k;
  }

  for (i = 0; i < _NOISE_B + 2; i++) {
    p[_NOISE_B + i] = p[i];
    g1[_NOISE_B + i] = g1[i];

    for (j = 0; j < 2; j++)
      g2[_NOISE_B + i][j] = g2[i][j];

    for (j = 0; j < 3; j++)
      g3[_NOISE_B + i][j] = g3[i][j];
  }

  BLI_rng_free(rng);
}
Esempio n. 10
0
/* almost exact copy of BLI_jitter_init */
static void init_mv_jit(float *jit, int num, int seed2, float amount)
{
	RNG *rng;
	float *jit2, x, rad1, rad2, rad3;
	int i, num2;

	if (num==0) return;

	rad1= (float)(1.0f/sqrtf((float)num));
	rad2= (float)(1.0f/((float)num));
	rad3= (float)sqrtf((float)num)/((float)num);

	rng = BLI_rng_new(31415926 + num + seed2);
	x= 0;
	num2 = 2 * num;
	for (i=0; i<num2; i+=2) {

		jit[i] = x + amount*rad1*(0.5f - BLI_rng_get_float(rng));
		jit[i+1] = i/(2.0f*num) + amount*rad1*(0.5f - BLI_rng_get_float(rng));

		jit[i]-= (float)floor(jit[i]);
		jit[i+1]-= (float)floor(jit[i+1]);

		x+= rad3;
		x -= (float)floor(x);
	}

	jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");

	for (i=0 ; i<4 ; i++) {
		BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
		BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
		BLI_jitterate2((float (*)[2])jit, (float (*)[2])jit2, num, rad2);
	}
	MEM_freeN(jit2);
	BLI_rng_free(rng);
}
Esempio n. 11
0
/**
 * Maps distances to weights, with an optional "smoothing" mapping.
 */
static void do_map(Object *ob, float *weights, const int nidx, const float min_d, const float max_d, short mode)
{
	const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */
	unsigned int i = nidx;
	if (max_d == min_d) {
		while (i-- > 0) {
			weights[i] = (weights[i] >= max_d) ? 1.0f : 0.0f; /* "Step" behavior... */
		}
	}
	else if (max_d > min_d) {
		while (i-- > 0) {
			if     (weights[i] >= max_d) weights[i] = 1.0f;  /* most likely case first */
			else if (weights[i] <= min_d) weights[i] = 0.0f;
			else weights[i] = (weights[i] - min_d) * range_inv;
		}
	}
	else {
		while (i-- > 0) {
			if     (weights[i] <= max_d) weights[i] = 1.0f;  /* most likely case first */
			else if (weights[i] >= min_d) weights[i] = 0.0f;
			else weights[i] = (weights[i] - min_d) * range_inv;
		}
	}

	if (!ELEM(mode, MOD_WVG_MAPPING_NONE, MOD_WVG_MAPPING_CURVE)) {
		RNG *rng = NULL;

		if (mode == MOD_WVG_MAPPING_RANDOM)
			rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2));

		weightvg_do_map(nidx, weights, mode, NULL, rng);

		if (rng)
			BLI_rng_free(rng);
	}
}
Esempio n. 12
0
void BKE_brush_system_exit(void)
{
	BLI_rng_free(brush_rng);
}
Esempio n. 13
0
static void createFacepa(ExplodeModifierData *emd,
                         ParticleSystemModifierData *psmd,
                         DerivedMesh *dm)
{
	ParticleSystem *psys = psmd->psys;
	MFace *fa = NULL, *mface = NULL;
	MVert *mvert = NULL;
	ParticleData *pa;
	KDTree *tree;
	RNG *rng;
	float center[3], co[3];
	int *facepa = NULL, *vertpa = NULL, totvert = 0, totface = 0, totpart = 0;
	int i, p, v1, v2, v3, v4 = 0;

	mvert = dm->getVertArray(dm);
	mface = dm->getTessFaceArray(dm);
	totface = dm->getNumTessFaces(dm);
	totvert = dm->getNumVerts(dm);
	totpart = psmd->psys->totpart;

	rng = BLI_rng_new_srandom(psys->seed);

	if (emd->facepa)
		MEM_freeN(emd->facepa);

	facepa = emd->facepa = MEM_callocN(sizeof(int) * totface, "explode_facepa");

	vertpa = MEM_callocN(sizeof(int) * totvert, "explode_vertpa");

	/* initialize all faces & verts to no particle */
	for (i = 0; i < totface; i++)
		facepa[i] = totpart;

	for (i = 0; i < totvert; i++)
		vertpa[i] = totpart;

	/* set protected verts */
	if (emd->vgroup) {
		MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
		if (dvert) {
			const int defgrp_index = emd->vgroup - 1;
			for (i = 0; i < totvert; i++, dvert++) {
				float val = BLI_rng_get_float(rng);
				val = (1.0f - emd->protect) * val + emd->protect * 0.5f;
				if (val < defvert_find_weight(dvert, defgrp_index))
					vertpa[i] = -1;
			}
		}
	}

	/* make tree of emitter locations */
	tree = BLI_kdtree_new(totpart);
	for (p = 0, pa = psys->particles; p < totpart; p++, pa++) {
		psys_particle_on_emitter(psmd, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, NULL, NULL, NULL, NULL, NULL);
		BLI_kdtree_insert(tree, p, co);
	}
	BLI_kdtree_balance(tree);

	/* set face-particle-indexes to nearest particle to face center */
	for (i = 0, fa = mface; i < totface; i++, fa++) {
		add_v3_v3v3(center, mvert[fa->v1].co, mvert[fa->v2].co);
		add_v3_v3(center, mvert[fa->v3].co);
		if (fa->v4) {
			add_v3_v3(center, mvert[fa->v4].co);
			mul_v3_fl(center, 0.25);
		}
		else
			mul_v3_fl(center, 1.0f / 3.0f);

		p = BLI_kdtree_find_nearest(tree, center, NULL);

		v1 = vertpa[fa->v1];
		v2 = vertpa[fa->v2];
		v3 = vertpa[fa->v3];
		if (fa->v4)
			v4 = vertpa[fa->v4];

		if (v1 >= 0 && v2 >= 0 && v3 >= 0 && (fa->v4 == 0 || v4 >= 0))
			facepa[i] = p;

		if (v1 >= 0) vertpa[fa->v1] = p;
		if (v2 >= 0) vertpa[fa->v2] = p;
		if (v3 >= 0) vertpa[fa->v3] = p;
		if (fa->v4 && v4 >= 0) vertpa[fa->v4] = p;
	}

	if (vertpa) MEM_freeN(vertpa);
	BLI_kdtree_free(tree);

	BLI_rng_free(rng);
}
Esempio n. 14
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
	DerivedMesh *dm = derivedData;
	MDeformVert *dvert = NULL;
	MDeformWeight **dw = NULL;
	float *org_w; /* Array original weights. */
	float *new_w; /* Array new weights. */
	int numVerts;
	int defgrp_index;
	int i;
	/* Flags. */
	int do_add  = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0;
	int do_rem  = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0;
	/* Only do weight-preview in Object, Sculpt and Pose modes! */
#if 0
	int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
#endif

	/* Get number of verts. */
	numVerts = dm->getNumVerts(dm);

	/* Check if we can just return the original mesh.
	 * Must have verts and therefore verts assigned to vgroups to do anything useful!
	 */
	if ((numVerts == 0) || (ob->defbase.first == NULL))
		return dm;

	/* Get vgroup idx from its name. */
	defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);
	if (defgrp_index == -1)
		return dm;

	dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts);
	/* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
	if (!dvert) {
		/* If this modifier is not allowed to add vertices, just return. */
		if (!do_add)
			return dm;
		/* Else, add a valid data layer! */
		dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC,
		                                   NULL, numVerts, wmd->defgrp_name);
		/* Ultimate security check. */
		if (!dvert)
			return dm;
	}

	/* Get org weights, assuming 0.0 for vertices not in given vgroup. */
	org_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, org_w");
	new_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, new_w");
	dw = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGEdit Modifier, dw");
	for (i = 0; i < numVerts; i++) {
		dw[i] = defvert_find_index(&dvert[i], defgrp_index);
		if (dw[i]) {
			org_w[i] = new_w[i] = dw[i]->weight;
		}
		else {
			org_w[i] = new_w[i] = wmd->default_weight;
		}
	}

	/* Do mapping. */
	if (wmd->falloff_type != MOD_WVG_MAPPING_NONE) {
		RNG *rng = NULL;

		if (wmd->falloff_type == MOD_WVG_MAPPING_RANDOM)
			rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2));

		weightvg_do_map(numVerts, new_w, wmd->falloff_type, wmd->cmap_curve, rng);

		if (rng)
			BLI_rng_free(rng);
	}

	/* Do masking. */
	weightvg_do_mask(numVerts, NULL, org_w, new_w, ob, dm, wmd->mask_constant,
	                 wmd->mask_defgrp_name, wmd->modifier.scene, wmd->mask_texture,
	                 wmd->mask_tex_use_channel, wmd->mask_tex_mapping,
	                 wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);

	/* Update/add/remove from vgroup. */
	weightvg_update_vg(dvert, defgrp_index, dw, numVerts, NULL, org_w, do_add, wmd->add_threshold,
	                   do_rem, wmd->rem_threshold);

	/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
	if (do_prev)
		DM_update_weight_mcol(ob, dm, 0, org_w, 0, NULL);
#endif

	/* Freeing stuff. */
	MEM_freeN(org_w);
	MEM_freeN(new_w);
	MEM_freeN(dw);

	/* Return the vgroup-modified mesh. */
	return dm;
}
static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd)
{
	Scene *scene = CTX_data_scene(C);
	bAction *act;
	FCurve *fcu;
	PointerRNA ptr;
	PropertyRNA *prop = NULL;
	int nbr_gaps = 0, i;
	
	if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
		return;
	
	/* gap_duration and gap_randomness are in frames, but we need seconds!!! */
	gtd->gap_duration = FRA2TIME(gtd->gap_duration);
	gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
	
	/* Enable path! */
	cu->flag |= CU_PATH;
	cu->pathlen = gtd->frame_range;
	
	/* Get RNA pointer to read/write path time values */
	RNA_id_pointer_create((ID *)cu, &ptr);
	prop = RNA_struct_find_property(&ptr, "eval_time");
	
	/* Ensure we have an F-Curve to add keyframes to */
	act = verify_adt_action((ID *)cu, true);
	fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true);
	
	if (G.debug & G_DEBUG) {
		printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
		for (i = 0; i < gtd->num_points; i++) {
			printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
		}
	}
	
	if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
		float cfra;
		
		/* Linear extrapolation! */
		fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
		
		cu->ctime = 0.0f;
		cfra = (float)gtd->start_frame;
		insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
		
		cu->ctime = cu->pathlen;
		if (gtd->realtime) {
			cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
		}
		else {
			cfra = (float)gtd->end_frame;
		}
		insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
	}
	else {
		/* Use actual recorded timing! */
		RNG *rng = BLI_rng_new(0);
		float time_range;
		
		/* CustomGaps specific */
		float tot_gaps_time = 0.0f;
		
		/* Pre-process gaps, in case we don't want to keep their original timing */
		if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
			gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
		}
		
		if (gtd->realtime) {
			time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
		}
		else {
			time_range = (float)(gtd->end_frame - gtd->start_frame);
		}
		
		if (G.debug & G_DEBUG) {
			printf("GP Stroke Path Conversion: Starting keying!\n");
		}
		
		gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
		                                       nbr_gaps, tot_gaps_time);
		
		BLI_rng_free(rng);
	}
	
	/* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
	calchandles_fcurve(fcu);
	
	if (G.debug & G_DEBUG) {
		printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
		for (i = 0; i < gtd->num_points; i++) {
			printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
		}
		printf("\n\n");
	}
	
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
	
	/* send updates */
	DAG_id_tag_update(&cu->id, 0);
}
Esempio n. 16
0
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);
}