Example #1
0
/* Builds a bvh tree where nodes are the vertices of the given dm */
BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree;
	MVert *vert;
	bool vert_allocated;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
	BLI_rw_mutex_unlock(&cache_rwlock);

	vert = DM_get_vert_array(dm, &vert_allocated);

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
		if (tree == NULL) {
			tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, dm->getNumVerts(dm), NULL, -1);
			if (tree) {
				/* Save on cache for later use */
				/* printf("BVHTree built and saved on cache\n"); */
				bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTS);
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}

	/* Setup BVHTreeFromMesh */
	bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated);

	return data->tree;
}
Example #2
0
/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BMEditMesh *em = data->em_evil;
	const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
	BVHTree *tree;
	MVert *vert = NULL;
	MFace *face = NULL;
	bool vert_allocated = false, face_allocated = false;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
	BLI_rw_mutex_unlock(&cache_rwlock);

	if (em == NULL) {
		vert = DM_get_vert_array(dm, &vert_allocated);
		face = DM_get_tessface_array(dm, &face_allocated);
	}

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
		if (tree == NULL) {
			int numFaces;

			/* BMESH specific check that we have tessfaces,
			 * we _could_ tessellate here but rather not - campbell
			 *
			 * this assert checks we have tessfaces,
			 * if not caller should use DM_ensure_tessface() */
			if (em) {
				numFaces = em->tottri;
			}
			else {
				numFaces = dm->getNumTessFaces(dm);
				BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
			}

			tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, em, vert, face, numFaces, NULL, -1);
			if (tree) {
				/* Save on cache for later use */
				/* printf("BVHTree built and saved on cache\n"); */
				bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}

	/* Setup BVHTreeFromMesh */
	bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, em, vert, vert_allocated, face, face_allocated);

	return data->tree;
}
Example #3
0
rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_free)
{
	static rcti tiles_static[BLENDER_MAX_THREADS];
	const int allocation_step = BLENDER_MAX_THREADS;
	RenderPart *pa;
	int total_tiles = 0;
	rcti *tiles = tiles_static;
	int allocation_size = BLENDER_MAX_THREADS;

	BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);

	*r_needs_free = false;

	if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
		*total_tiles_r = 0;
		BLI_rw_mutex_unlock(&re->partsmutex);
		return NULL;
	}

	for (pa = re->parts.first; pa; pa = pa->next) {
		if (pa->status == PART_STATUS_IN_PROGRESS) {
			if (total_tiles >= allocation_size) {
				/* Just in case we're using crazy network rendering with more
				 * slaves as BLENDER_MAX_THREADS.
				 */
				if (tiles == tiles_static)
					tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles");
				else
					tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti));

				allocation_size += allocation_step;
				*r_needs_free = true;
			}

			tiles[total_tiles] = pa->disprect;

			if (pa->crop) {
				tiles[total_tiles].xmin += pa->crop;
				tiles[total_tiles].ymin += pa->crop;
				tiles[total_tiles].xmax -= pa->crop;
				tiles[total_tiles].ymax -= pa->crop;
			}

			total_tiles++;
		}
	}
	BLI_rw_mutex_unlock(&re->partsmutex);
	*total_tiles_r = total_tiles;
	return tiles;
}
Example #4
0
static void rna_SmokeModifier_velocity_grid_get(PointerRNA *ptr, float *values)
{
#ifdef WITH_SMOKE
	SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
	int length[RNA_MAX_ARRAY_DIMENSION];
	int size = rna_SmokeModifier_velocity_grid_get_length(ptr, length);
	float *vx, *vy, *vz;
	int i;

	BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);

	vx = smoke_get_velocity_x(sds->fluid);
	vy = smoke_get_velocity_y(sds->fluid);
	vz = smoke_get_velocity_z(sds->fluid);

	for (i = 0; i < size; i += 3) {
		*(values++) = *(vx++);
		*(values++) = *(vy++);
		*(values++) = *(vz++);
	}

	BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
	UNUSED_VARS(ptr, values);
#endif
}
Example #5
0
static void set_height_normalize_factor(struct Ocean *oc)
{
	float res = 1.0;
	float max_h = 0.0;

	int i, j;

	if (!oc->_do_disp_y) return;

	oc->normalize_factor = 1.0;

	BKE_simulate_ocean(oc, 0.0, 1.0, 0);

	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);

	for (i = 0; i < oc->_M; ++i) {
		for (j = 0; j < oc->_N; ++j) {
			if (max_h < fabsf(oc->_disp_y[i * oc->_N + j])) {
				max_h = fabsf(oc->_disp_y[i * oc->_N + j]);
			}
		}
	}

	BLI_rw_mutex_unlock(&oc->oceanmutex);

	if (max_h == 0.0f)
		max_h = 0.00001f;  /* just in case ... */

	res = 1.0f / (max_h);

	oc->normalize_factor = res;
}
Example #6
0
static void rna_SmokeModifier_color_grid_get(PointerRNA *ptr, float *values)
{
#ifdef WITH_SMOKE
	SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;

	BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);

	if (sds->flags & MOD_SMOKE_HIGHRES) {
		if (smoke_turbulence_has_colors(sds->wt))
			smoke_turbulence_get_rgba(sds->wt, values, 0);
		else
			smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, values, 0);
	}
	else {
		if (smoke_has_colors(sds->fluid))
			smoke_get_rgba(sds->fluid, values, 0);
		else
			smoke_get_rgba_from_density(sds->fluid, sds->active_color, values, 0);
	}

	BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
	UNUSED_VARS(ptr, values);
#endif
}
Example #7
0
/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being just a way to get
 * the raw data out to save in some image format.
 */
void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
{
	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);

	i = abs(i) % oc->_M;
	j = abs(j) % oc->_N;

	ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f;

	if (oc->_do_chop) {
		ocr->disp[0] = oc->_disp_x[i * oc->_N + j];
		ocr->disp[2] = oc->_disp_z[i * oc->_N + j];
	}
	else {
		ocr->disp[0] = 0.0f;
		ocr->disp[2] = 0.0f;
	}

	if (oc->_do_normals) {
		ocr->normal[0] = oc->_N_x[i * oc->_N + j];
		ocr->normal[1] = oc->_N_y  /* oc->_N_y[i * oc->_N + j] (MEM01) */;
		ocr->normal[2] = oc->_N_z[i * oc->_N + j];

		normalize_v3(ocr->normal);
	}

	if (oc->_do_jacobian) {
		compute_eigenstuff(ocr, oc->_Jxx[i * oc->_N + j], oc->_Jzz[i * oc->_N + j], oc->_Jxz[i * oc->_N + j]);
	}

	BLI_rw_mutex_unlock(&oc->oceanmutex);
}
Example #8
0
static void rna_SmokeModifier_flame_grid_get(PointerRNA *ptr, float *values)
{
#ifdef WITH_SMOKE
	SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
	int length[RNA_MAX_ARRAY_DIMENSION];
	int size = rna_SmokeModifier_grid_get_length(ptr, length);
	float *flame;

	BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
	
	if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt)
		flame = smoke_turbulence_get_flame(sds->wt);
	else
		flame = smoke_get_flame(sds->fluid);
	
	if (flame)
		memcpy(values, flame, size * sizeof(float));
	else
		memset(values, 0, size * sizeof(float));

	BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
	UNUSED_VARS(ptr, values);
#endif
}
Example #9
0
static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values)
{
#ifdef WITH_SMOKE
	SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
	int length[RNA_MAX_ARRAY_DIMENSION];
	int size = rna_SmokeModifier_heat_grid_get_length(ptr, length);
	float *heat;

	BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);

	heat = smoke_get_heat(sds->fluid);

	if (heat != NULL) {
		/* scale heat values from -2.0-2.0 to -1.0-1.0. */
		for (int i = 0; i < size; i++) {
			values[i] = heat[i] * 0.5f;
		}
	}
	else {
		memset(values, 0, size * sizeof(float));
	}

	BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
	UNUSED_VARS(ptr, values);
#endif
}
Example #10
0
int RE_engine_render(Render *re, int do_all)
{
	RenderEngineType *type= RE_engines_find(re->r.engine);
	RenderEngine *engine;

	/* verify if we can render */
	if (!type->render)
		return 0;
	if ((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
		return 0;
	if (do_all && !(type->flag & RE_USE_POSTPROCESS))
		return 0;
	if (!do_all && (type->flag & RE_USE_POSTPROCESS))
		return 0;

	/* create render result */
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	if (re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
		if (re->result)
			render_result_free(re->result);
		re->result= render_result_new(re, &re->disprect, 0, 0);
	}
	BLI_rw_mutex_unlock(&re->resultmutex);
	
	if (re->result==NULL)
		return 1;

	/* set render info */
	re->i.cfra= re->scene->r.cfra;
	BLI_strncpy(re->i.scenename, re->scene->id.name+2, sizeof(re->i.scenename));
	re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;

	/* render */
	engine = RE_engine_create(type);
	engine->re= re;

	if (re->flag & R_ANIMATION)
		engine->flag |= RE_ENGINE_ANIMATION;
	if (re->r.scemode & R_PREVIEWBUTS)
		engine->flag |= RE_ENGINE_PREVIEW;
	engine->camera_override = re->camera_override;

	if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0)
		scene_update_for_newframe(re->main, re->scene, re->lay);

	if (type->update)
		type->update(engine, re->main, re->scene);
	if (type->render)
		type->render(engine, re->scene);

	render_result_free_list(&engine->fullresult, engine->fullresult.first);

	RE_engine_free(engine);

	if (BKE_reports_contain(re->reports, RPT_ERROR))
		G.afbreek = 1;
	
	return 1;
}
Example #11
0
void BKE_free_ocean_data(struct Ocean *oc)
{
	if (!oc) return;

	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE);

	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);
	}

	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);
}
Example #12
0
static void rna_SmokeModifier_density_grid_get(PointerRNA *ptr, float *values)
{
#ifdef WITH_SMOKE
	SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
	int length[RNA_MAX_ARRAY_DIMENSION];
	int size = rna_SmokeModifier_grid_get_length(ptr, length);
	float *density;

	BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
	
	if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt)
		density = smoke_turbulence_get_density(sds->wt);
	else
		density = smoke_get_density(sds->fluid);

	memcpy(values, density, size * sizeof(float));

	BLI_rw_mutex_unlock(sds->fluid_mutex);
#else
	(void)ptr;
	(void)values;
#endif
}
Example #13
0
/**
 * Builds a bvh tree where nodes are the looptri faces of the given dm
 *
 * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces
 */
BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BMEditMesh *em = data->em_evil;
	const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_LOOPTRI;
	BVHTree *tree;
	MVert *mvert = NULL;
	MLoop *mloop = NULL;
	const MLoopTri *looptri = NULL;
	bool vert_allocated = false;
	bool loop_allocated = false;
	bool looptri_allocated = false;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
	BLI_rw_mutex_unlock(&cache_rwlock);

	if (em == NULL) {
		MPoly *mpoly;
		bool poly_allocated = false;

		mvert = DM_get_vert_array(dm, &vert_allocated);
		mpoly = DM_get_poly_array(dm, &poly_allocated);

		mloop = DM_get_loop_array(dm, &loop_allocated);
		looptri = DM_get_looptri_array(
		        dm,
		        mvert,
		        mpoly, dm->getNumPolys(dm),
		        mloop, dm->getNumLoops(dm),
		        &looptri_allocated);

		if (poly_allocated) {
			MEM_freeN(mpoly);
		}

	}

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
		if (tree == NULL) {
			int looptri_num;

			/* BMESH specific check that we have tessfaces,
			 * we _could_ tessellate here but rather not - campbell
			 *
			 * this assert checks we have tessfaces,
			 * if not caller should use DM_ensure_tessface() */
			if (em) {
				looptri_num = em->tottri;
			}
			else {
				looptri_num = dm->getNumLoopTri(dm);
				BLI_assert(!(looptri_num == 0 && dm->getNumPolys(dm) != 0));
			}

			tree = bvhtree_from_mesh_looptri_create_tree(
			        epsilon, tree_type, axis, em,
			        mvert, mloop, looptri, looptri_num, NULL, -1);
			if (tree) {
				/* Save on cache for later use */
				/* printf("BVHTree built and saved on cache\n"); */
				bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}

	/* Setup BVHTreeFromMesh */
	bvhtree_from_mesh_looptri_setup_data(
	        data, tree, true, epsilon, em,
	        mvert, vert_allocated,
	        mloop, loop_allocated,
	        looptri, looptri_allocated);

	return data->tree;
}
Example #14
0
int RE_engine_render(Render *re, int do_all)
{
	RenderEngineType *type = RE_engines_find(re->r.engine);
	RenderEngine *engine;
	int persistent_data = re->r.mode & R_PERSISTENT_DATA;

	/* verify if we can render */
	if (!type->render)
		return 0;
	if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
		return 0;
	if (do_all && !(type->flag & RE_USE_POSTPROCESS))
		return 0;
	if (!do_all && (type->flag & RE_USE_POSTPROCESS))
		return 0;

	/* update animation here so any render layer animation is applied before
	 * creating the render result */
	if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
		unsigned int lay = re->lay;

		/* don't update layers excluded on all render layers */
		if (type->flag & RE_USE_EXCLUDE_LAYERS) {
			SceneRenderLayer *srl;
			unsigned int non_excluded_lay = 0;

			if (re->r.scemode & R_SINGLE_LAYER) {
				srl = BLI_findlink(&re->r.layers, re->r.actlay);
				if (srl)
					non_excluded_lay |= ~srl->lay_exclude;
			}
			else {
				for (srl = re->r.layers.first; srl; srl = srl->next)
					if (!(srl->layflag & SCE_LAY_DISABLE))
						non_excluded_lay |= ~srl->lay_exclude;
			}

			lay &= non_excluded_lay;
		}

		BKE_scene_update_for_newframe(re->main, re->scene, lay);
	}

	/* create render result */
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
		int savebuffers = RR_USE_MEM;

		if (re->result)
			render_result_free(re->result);

		if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
			savebuffers = RR_USE_EXR;
		re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
	}
	BLI_rw_mutex_unlock(&re->resultmutex);

	if (re->result == NULL)
		return 1;

	/* set render info */
	re->i.cfra = re->scene->r.cfra;
	BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
	re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;

	/* render */
	engine = re->engine;

	if (!engine) {
		engine = RE_engine_create(type);
		re->engine = engine;
	}

	engine->flag |= RE_ENGINE_RENDERING;

	/* TODO: actually link to a parent which shouldn't happen */
	engine->re = re;

	if (re->flag & R_ANIMATION)
		engine->flag |= RE_ENGINE_ANIMATION;
	if (re->r.scemode & R_BUTS_PREVIEW)
		engine->flag |= RE_ENGINE_PREVIEW;
	engine->camera_override = re->camera_override;

	engine->resolution_x = re->winx;
	engine->resolution_y = re->winy;

	RE_parts_init(re, FALSE);
	engine->tile_x = re->partx;
	engine->tile_y = re->party;

	if (re->result->do_exr_tile)
		render_result_exr_file_begin(re);

	if (type->update)
		type->update(engine, re->main, re->scene);
	
	if (type->render)
		type->render(engine, re->scene);

	engine->tile_x = 0;
	engine->tile_y = 0;
	engine->flag &= ~RE_ENGINE_RENDERING;

	render_result_free_list(&engine->fullresult, engine->fullresult.first);

	/* re->engine becomes zero if user changed active render engine during render */
	if (!persistent_data || !re->engine) {
		RE_engine_free(engine);
		re->engine = NULL;
	}

	if (re->result->do_exr_tile) {
		BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
		render_result_exr_file_end(re);
		BLI_rw_mutex_unlock(&re->resultmutex);
	}

	RE_parts_free(re);

	if (BKE_reports_contain(re->reports, RPT_ERROR))
		G.is_break = TRUE;
	
	return 1;
}
Example #15
0
/* Builds a bvh tree where nodes are the edges of the given dm */
BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree;
	MVert *vert;
	MEdge *edge;
	bool vert_allocated, edge_allocated;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
	BLI_rw_mutex_unlock(&cache_rwlock);

	vert = DM_get_vert_array(dm, &vert_allocated);
	edge = DM_get_edge_array(dm, &edge_allocated);

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
		if (tree == NULL) {
			int i;
			int numEdges = dm->getNumEdges(dm);

			if (vert != NULL && edge != NULL) {
				/* Create a bvh-tree of the given target */
				tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
				if (tree != NULL) {
					for (i = 0; i < numEdges; i++) {
						float co[4][3];
						copy_v3_v3(co[0], vert[edge[i].v1].co);
						copy_v3_v3(co[1], vert[edge[i].v2].co);

						BLI_bvhtree_insert(tree, i, co[0], 2);
					}
					BLI_bvhtree_balance(tree);

					/* Save on cache for later use */
					/* printf("BVHTree built and saved on cache\n"); */
					bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
				}
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}


	/* Setup BVHTreeFromMesh */
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if (data->tree) {
		data->cached = true;

		data->nearest_callback = mesh_edges_nearest_point;
		data->raycast_callback = mesh_edges_spherecast;

		data->vert = vert;
		data->vert_allocated = vert_allocated;
		data->edge = edge;
		data->edge_allocated = edge_allocated;

		data->sphere_radius = epsilon;
	}
	else {
		if (vert_allocated) {
			MEM_freeN(vert);
		}
		if (edge_allocated) {
			MEM_freeN(edge);
		}
	}
	return data->tree;
}
Example #16
0
/* Builds a bvh tree.. where nodes are the vertexs of the given mesh */
BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree;
	MVert *vert;
	bool vert_allocated;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
	BLI_rw_mutex_unlock(&cache_rwlock);

	vert = DM_get_vert_array(dm, &vert_allocated);

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
		if (tree == NULL) {
			int i;
			int numVerts = dm->getNumVerts(dm);

			if (vert != NULL) {
				tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);

				if (tree != NULL) {
					for (i = 0; i < numVerts; i++) {
						BLI_bvhtree_insert(tree, i, vert[i].co, 1);
					}

					BLI_bvhtree_balance(tree);

					/* Save on cache for later use */
//					printf("BVHTree built and saved on cache\n");
					bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTICES);
				}
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
//		printf("BVHTree is already build, using cached tree\n");
	}


	/* Setup BVHTreeFromMesh */
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if (data->tree) {
		data->cached = true;

		/* a NULL nearest callback works fine
		 * remember the min distance to point is the same as the min distance to BV of point */
		data->nearest_callback = NULL;
		data->raycast_callback = NULL;

		data->vert = vert;
		data->vert_allocated = vert_allocated;
		data->face = DM_get_tessface_array(dm, &data->face_allocated);

		data->sphere_radius = epsilon;
	}
	else {
		if (vert_allocated) {
			MEM_freeN(vert);
		}
	}

	return data->tree;
}
Example #17
0
static void sss_create_tree_mat(Render *re, Material *mat)
{
	SSSPoints *p;
	RenderResult *rr;
	ListBase points;
	float (*co)[3] = NULL, (*color)[3] = NULL, *area = NULL;
	int totpoint = 0, osa, osaflag, partsdone;

	if (re->test_break(re->tbh))
		return;
	
	points.first= points.last= NULL;

	/* TODO: this is getting a bit ugly, copying all those variables and
	 * setting them back, maybe we need to create our own Render? */

	/* do SSS preprocessing render */
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	rr= re->result;
	osa= re->osa;
	osaflag= re->r.mode & R_OSA;
	partsdone= re->i.partsdone;

	re->osa= 0;
	re->r.mode &= ~R_OSA;
	re->sss_points= &points;
	re->sss_mat= mat;
	re->i.partsdone = FALSE;

	if (!(re->r.scemode & R_PREVIEWBUTS))
		re->result= NULL;
	BLI_rw_mutex_unlock(&re->resultmutex);

	RE_TileProcessor(re);
	
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	if (!(re->r.scemode & R_PREVIEWBUTS)) {
		RE_FreeRenderResult(re->result);
		re->result= rr;
	}
	BLI_rw_mutex_unlock(&re->resultmutex);

	re->i.partsdone= partsdone;
	re->sss_mat= NULL;
	re->sss_points= NULL;
	re->osa= osa;
	if (osaflag) re->r.mode |= R_OSA;

	/* no points? no tree */
	if (!points.first)
		return;

	/* merge points together into a single buffer */
	if (!re->test_break(re->tbh)) {
		for (totpoint=0, p=points.first; p; p=p->next)
			totpoint += p->totpoint;
		
		co= MEM_mallocN(sizeof(*co)*totpoint, "SSSCo");
		color= MEM_mallocN(sizeof(*color)*totpoint, "SSSColor");
		area= MEM_mallocN(sizeof(*area)*totpoint, "SSSArea");

		for (totpoint=0, p=points.first; p; p=p->next) {
			memcpy(co+totpoint, p->co, sizeof(*co)*p->totpoint);
			memcpy(color+totpoint, p->color, sizeof(*color)*p->totpoint);
			memcpy(area+totpoint, p->area, sizeof(*area)*p->totpoint);
			totpoint += p->totpoint;
		}
	}

	/* free points */
	for (p=points.first; p; p=p->next) {
		MEM_freeN(p->co);
		MEM_freeN(p->color);
		MEM_freeN(p->area);
	}
	BLI_freelistN(&points);

	/* build tree */
	if (!re->test_break(re->tbh)) {
		SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData");
		float ior= mat->sss_ior, cfac= mat->sss_colfac;
		float *radius= mat->sss_radius;
		float fw= mat->sss_front, bw= mat->sss_back;
		float error = mat->sss_error;

		error= get_render_aosss_error(&re->r, error);
		if ((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f)
			error= 0.5f;
		
		sss->ss[0]= scatter_settings_new(mat->sss_col[0], radius[0], ior, cfac, fw, bw);
		sss->ss[1]= scatter_settings_new(mat->sss_col[1], radius[1], ior, cfac, fw, bw);
		sss->ss[2]= scatter_settings_new(mat->sss_col[2], radius[2], ior, cfac, fw, bw);
		sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error,
			co, color, area, totpoint);

		MEM_freeN(co);
		MEM_freeN(color);
		MEM_freeN(area);

		scatter_tree_build(sss->tree);

		BLI_ghash_insert(re->sss_hash, mat, sss);
	}
	else {
		if (co) MEM_freeN(co);
		if (color) MEM_freeN(color);
		if (area) MEM_freeN(area);
	}
}
Example #18
0
/* Builds a bvh tree.. where nodes are the faces of the given dm. */
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BMEditMesh *em = data->em_evil;
	const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
	BVHTree *tree;
	MVert *vert;
	MFace *face;
	bool vert_allocated = false, face_allocated = false;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
	BLI_rw_mutex_unlock(&cache_rwlock);

	if (em == NULL) {
		vert = DM_get_vert_array(dm, &vert_allocated);
		face = DM_get_tessface_array(dm, &face_allocated);
	}

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
		if (tree == NULL) {
			int i;
			int numFaces;

			/* BMESH specific check that we have tessfaces,
			 * we _could_ tessellate here but rather not - campbell
			 *
			 * this assert checks we have tessfaces,
			 * if not caller should use DM_ensure_tessface() */
			if (em) {
				numFaces = em->tottri;
			}
			else {
				numFaces = dm->getNumTessFaces(dm);
				BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
			}

			if (numFaces != 0) {
				/* Create a bvh-tree of the given target */
				// printf("%s: building BVH, total=%d\n", __func__, numFaces);
				tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
				if (tree != NULL) {
					if (em) {
						const struct BMLoop *(*looptris)[3] = (void *)em->looptris;

						/* avoid double-up on face searches for quads-ngons */
						bool insert_prev = false;
						BMFace *f_prev = NULL;

						/* data->em_evil is only set for snapping, and only for the mesh of the object
						 * which is currently open in edit mode. When set, the bvhtree should not contain
						 * faces that will interfere with snapping (e.g. faces that are hidden/selected
						 * or faces that have selected verts).*/

						/* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
						 * and/or selected. Even if the faces themselves are not selected for the snapped
						 * transform, having a vertex selected means the face (and thus it's tessellated
						 * triangles) will be moving and will not be a good snap targets.*/
						for (i = 0; i < em->tottri; i++) {
							const BMLoop **ltri = looptris[i];
							BMFace *f = ltri[0]->f;
							bool insert;

							/* Start with the assumption the triangle should be included for snapping. */
							if (f == f_prev) {
								insert = insert_prev;
							}
							else {
								if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
									/* Don't insert triangles tessellated from faces that are hidden
									 * or selected*/
									insert = false;
								}
								else {
									BMLoop *l_iter, *l_first;
									insert = true;
									l_iter = l_first = BM_FACE_FIRST_LOOP(f);
									do {
										if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
											/* Don't insert triangles tessellated from faces that have
											 * any selected verts.*/
											insert = false;
											break;
										}
									} while ((l_iter = l_iter->next) != l_first);
								}

								/* skip if face doesn't change */
								f_prev = f;
								insert_prev = insert;
							}

							if (insert) {
								/* No reason found to block hit-testing the triangle for snap,
								 * so insert it now.*/
								float co[3][3];
								copy_v3_v3(co[0], ltri[0]->v->co);
								copy_v3_v3(co[1], ltri[1]->v->co);
								copy_v3_v3(co[2], ltri[2]->v->co);

								BLI_bvhtree_insert(tree, i, co[0], 3);
							}
						}
					}
					else {
						if (vert != NULL && face != NULL) {
							for (i = 0; i < numFaces; i++) {
								float co[4][3];
								copy_v3_v3(co[0], vert[face[i].v1].co);
								copy_v3_v3(co[1], vert[face[i].v2].co);
								copy_v3_v3(co[2], vert[face[i].v3].co);
								if (face[i].v4)
									copy_v3_v3(co[3], vert[face[i].v4].co);

								BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
							}
						}
					}
					BLI_bvhtree_balance(tree);

					/* Save on cache for later use */
//					printf("BVHTree built and saved on cache\n");
					bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
				}
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
//		printf("BVHTree is already build, using cached tree\n");
	}


	/* Setup BVHTreeFromMesh */
	memset(data, 0, sizeof(*data));
	data->tree = tree;
	data->em_evil = em;

	if (data->tree) {
		data->cached = true;

		if (em) {
			data->nearest_callback = editmesh_faces_nearest_point;
			data->raycast_callback = editmesh_faces_spherecast;
		}
		else {
			data->nearest_callback = mesh_faces_nearest_point;
			data->raycast_callback = mesh_faces_spherecast;

			data->vert = vert;
			data->vert_allocated = vert_allocated;
			data->face = face;
			data->face_allocated = face_allocated;
		}

		data->sphere_radius = epsilon;
	}
	else {
		if (vert_allocated) {
			MEM_freeN(vert);
		}
		if (face_allocated) {
			MEM_freeN(face);
		}
	}

	return data->tree;

}
Example #19
0
void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
{
	int i0, i1, j0, j1;
	float frac_x, frac_z;
	float uu, vv;

	/* first wrap the texture so 0 <= (u, v) < 1 */
	u = fmodf(u, 1.0f);
	v = fmodf(v, 1.0f);

	if (u < 0) u += 1.0f;
	if (v < 0) v += 1.0f;

	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);

	uu = u * oc->_M;
	vv = v * oc->_N;

	i0 = (int)floor(uu);
	j0 = (int)floor(vv);

	i1 = (i0 + 1);
	j1 = (j0 + 1);

	frac_x = uu - i0;
	frac_z = vv - j0;

	i0 = i0 % oc->_M;
	j0 = j0 % oc->_N;

	i1 = i1 % oc->_M;
	j1 = j1 % oc->_N;


#define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
                           interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
                           frac_z))
	{
		if (oc->_do_disp_y) {
			ocr->disp[1] = BILERP(oc->_disp_y);
		}

		if (oc->_do_normals) {
			ocr->normal[0] = BILERP(oc->_N_x);
			ocr->normal[1] = oc->_N_y /*BILERP(oc->_N_y) (MEM01)*/;
			ocr->normal[2] = BILERP(oc->_N_z);
		}

		if (oc->_do_chop) {
			ocr->disp[0] = BILERP(oc->_disp_x);
			ocr->disp[2] = BILERP(oc->_disp_z);
		}
		else {
			ocr->disp[0] = 0.0;
			ocr->disp[2] = 0.0;
		}

		if (oc->_do_jacobian) {
			compute_eigenstuff(ocr, BILERP(oc->_Jxx), BILERP(oc->_Jzz), BILERP(oc->_Jxz));
		}
	}
#undef BILERP

	BLI_rw_mutex_unlock(&oc->oceanmutex);
}
Example #20
0
/* use catmullrom interpolation rather than linear */
void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
{
	int i0, i1, i2, i3, j0, j1, j2, j3;
	float frac_x, frac_z;
	float uu, vv;

	/* first wrap the texture so 0 <= (u, v) < 1 */
	u = fmod(u, 1.0f);
	v = fmod(v, 1.0f);

	if (u < 0) u += 1.0f;
	if (v < 0) v += 1.0f;

	BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);

	uu = u * oc->_M;
	vv = v * oc->_N;

	i1 = (int)floor(uu);
	j1 = (int)floor(vv);

	i2 = (i1 + 1);
	j2 = (j1 + 1);

	frac_x = uu - i1;
	frac_z = vv - j1;

	i1 = i1 % oc->_M;
	j1 = j1 % oc->_N;

	i2 = i2 % oc->_M;
	j2 = j2 % oc->_N;

	i0 = (i1 - 1);
	i3 = (i2 + 1);
	i0 = i0 <   0 ? i0 + oc->_M : i0;
	i3 = i3 >= oc->_M ? i3 - oc->_M : i3;

	j0 = (j1 - 1);
	j3 = (j2 + 1);
	j0 = j0 <   0 ? j0 + oc->_N : j0;
	j3 = j3 >= oc->_N ? j3 - oc->_N : j3;

#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], \
                                m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \
                         catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], \
                                m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \
                         catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], \
                                m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \
                         catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], \
                                m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \
                         frac_z)

	{
		if (oc->_do_disp_y) {
			ocr->disp[1] = INTERP(oc->_disp_y);
		}
		if (oc->_do_normals) {
			ocr->normal[0] = INTERP(oc->_N_x);
			ocr->normal[1] = oc->_N_y /*INTERP(oc->_N_y) (MEM01)*/;
			ocr->normal[2] = INTERP(oc->_N_z);
		}
		if (oc->_do_chop) {
			ocr->disp[0] = INTERP(oc->_disp_x);
			ocr->disp[2] = INTERP(oc->_disp_z);
		}
		else {
			ocr->disp[0] = 0.0;
			ocr->disp[2] = 0.0;
		}

		if (oc->_do_jacobian) {
			compute_eigenstuff(ocr, INTERP(oc->_Jxx), INTERP(oc->_Jzz), INTERP(oc->_Jxz));
		}
	}
#undef INTERP

	BLI_rw_mutex_unlock(&oc->oceanmutex);

}
Example #21
0
void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount)
{
	int i, j;

	scale *= o->normalize_factor;

	BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);

	/* compute a new htilda */
#pragma omp parallel for private(i, j)
	for (i = 0; i < o->_M; ++i) {
		/* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */
		for (j = 0; j <= o->_N / 2; ++j) {
			fftw_complex exp_param1;
			fftw_complex exp_param2;
			fftw_complex conj_param;


			init_complex(exp_param1, 0.0, omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
			init_complex(exp_param2, 0.0, -omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
			exp_complex(exp_param1, exp_param1);
			exp_complex(exp_param2, exp_param2);
			conj_complex(conj_param, o->_h0_minus[i * o->_N + j]);

			mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1);
			mul_complex_c(exp_param2, conj_param, exp_param2);

			add_comlex_c(o->_htilda[i * (1 + o->_N / 2) + j], exp_param1, exp_param2);
			mul_complex_f(o->_fft_in[i * (1 + o->_N / 2) + j], o->_htilda[i * (1 + o->_N / 2) + j], scale);
		}
	}

#pragma omp parallel sections private(i, j)
	{

#pragma omp section
		{
			if (o->_do_disp_y) {
				/* y displacement */
				fftw_execute(o->_disp_y_plan);
			}
		} /* section 1 */

#pragma omp section
		{
			if (o->_do_chop) {
				/* x displacement */
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;
						fftw_complex minus_i;

						init_complex(minus_i, 0.0, -1.0);
						init_complex(mul_param, -scale, 0);
						mul_complex_f(mul_param, mul_param, chop_amount);
						mul_complex_c(mul_param, mul_param, minus_i);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param,
						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
						               0.0f :
						               o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
						init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_disp_x_plan);
			}
		} /* section 2 */

#pragma omp section
		{
			if (o->_do_chop) {
				/* z displacement */
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;
						fftw_complex minus_i;

						init_complex(minus_i, 0.0, -1.0);
						init_complex(mul_param, -scale, 0);
						mul_complex_f(mul_param, mul_param, chop_amount);
						mul_complex_c(mul_param, mul_param, minus_i);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param,
						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
						               0.0f :
						               o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
						init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_disp_z_plan);
			}
		} /* section 3 */

#pragma omp section
		{
			if (o->_do_jacobian) {
				/* Jxx */
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;

						/* init_complex(mul_param, -scale, 0); */
						init_complex(mul_param, -1, 0);

						mul_complex_f(mul_param, mul_param, chop_amount);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param,
						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
						               0.0f :
						               o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
						init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_Jxx_plan);

				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j < o->_N; ++j) {
						o->_Jxx[i * o->_N + j] += 1.0;
					}
				}
			}
		} /* section 4 */

#pragma omp section
		{
			if (o->_do_jacobian) {
				/* Jzz */
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;

						/* init_complex(mul_param, -scale, 0); */
						init_complex(mul_param, -1, 0);

						mul_complex_f(mul_param, mul_param, chop_amount);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param,
						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
						               0.0f :
						               o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
						init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_Jzz_plan);
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j < o->_N; ++j) {
						o->_Jzz[i * o->_N + j] += 1.0;
					}
				}
			}
		} /* section 5 */

#pragma omp section
		{
			if (o->_do_jacobian) {
				/* Jxz */
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;

						/* init_complex(mul_param, -scale, 0); */
						init_complex(mul_param, -1, 0);

						mul_complex_f(mul_param, mul_param, chop_amount);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param,
						              ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
						               0.0f :
						               o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
						init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_Jxz_plan);
			}
		} /* section 6 */

#pragma omp section
		{
			/* fft normals */
			if (o->_do_normals) {
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;

						init_complex(mul_param, 0.0, -1.0);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param, o->_kx[i]);
						init_complex(o->_fft_in_nx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_N_x_plan);

			}
		} /* section 7 */

#pragma omp section
		{
			if (o->_do_normals) {
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j <= o->_N / 2; ++j) {
						fftw_complex mul_param;

						init_complex(mul_param, 0.0, -1.0);
						mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
						mul_complex_f(mul_param, mul_param, o->_kz[i]);
						init_complex(o->_fft_in_nz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
					}
				}
				fftw_execute(o->_N_z_plan);

#if 0
				for (i = 0; i < o->_M; ++i) {
					for (j = 0; j < o->_N; ++j) {
						o->_N_y[i * o->_N + j] = 1.0f / scale;
					}
				}
				(MEM01)
#endif
				o->_N_y = 1.0f / scale;
			}
		} /* section 8 */

	} /* omp sections */

	BLI_rw_mutex_unlock(&o->oceanmutex);
}
Example #22
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)
{
	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);*/
	BLI_srand(seed);

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

			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");

	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_rw_mutex_unlock(&o->oceanmutex);

	set_height_normalize_factor(o);

}
Example #23
0
bool RE_bake_engine(
        Render *re, Object *object, const BakePixel pixel_array[],
        const size_t num_pixels, const int depth,
        const ScenePassType pass_type, float result[])
{
	RenderEngineType *type = RE_engines_find(re->r.engine);
	RenderEngine *engine;
	bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;

	/* set render info */
	re->i.cfra = re->scene->r.cfra;
	BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
	re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;

	/* render */
	engine = re->engine;

	if (!engine) {
		engine = RE_engine_create(type);
		re->engine = engine;
	}

	engine->flag |= RE_ENGINE_RENDERING;

	/* TODO: actually link to a parent which shouldn't happen */
	engine->re = re;

	engine->resolution_x = re->winx;
	engine->resolution_y = re->winy;

	RE_parts_init(re, false);
	engine->tile_x = re->r.tilex;
	engine->tile_y = re->r.tiley;

	/* update is only called so we create the engine.session */
	if (type->update)
		type->update(engine, re->main, re->scene);

	if (type->bake)
		type->bake(engine, re->scene, object, pass_type, pixel_array, num_pixels, depth, result);

	engine->tile_x = 0;
	engine->tile_y = 0;
	engine->flag &= ~RE_ENGINE_RENDERING;

	BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);

	/* re->engine becomes zero if user changed active render engine during render */
	if (!persistent_data || !re->engine) {
		RE_engine_free(engine);
		re->engine = NULL;
	}

	RE_parts_free(re);
	BLI_rw_mutex_unlock(&re->partsmutex);

	if (BKE_reports_contain(re->reports, RPT_ERROR))
		G.is_break = true;

	return true;
}
Example #24
0
int RE_engine_render(Render *re, int do_all)
{
	RenderEngineType *type = RE_engines_find(re->r.engine);
	RenderEngine *engine;
	bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;

	/* verify if we can render */
	if (!type->render)
		return 0;
	if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
		return 0;
	if (do_all && !(type->flag & RE_USE_POSTPROCESS))
		return 0;
	if (!do_all && (type->flag & RE_USE_POSTPROCESS))
		return 0;

	/* Lock drawing in UI during data phase. */
	if (re->draw_lock) {
		re->draw_lock(re->dlh, 1);
	}

	/* update animation here so any render layer animation is applied before
	 * creating the render result */
	if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
		unsigned int lay = re->lay;

		/* don't update layers excluded on all render layers */
		if (type->flag & RE_USE_EXCLUDE_LAYERS) {
			SceneRenderLayer *srl;
			unsigned int non_excluded_lay = 0;

			if (re->r.scemode & R_SINGLE_LAYER) {
				srl = BLI_findlink(&re->r.layers, re->r.actlay);
				if (srl) {
					non_excluded_lay |= ~srl->lay_exclude;

					/* in this case we must update all because animation for
					 * the scene has not been updated yet, and so may not be
					 * up to date until after BKE_scene_update_for_newframe */
					if (render_layer_exclude_animated(re->scene, srl))
						non_excluded_lay |= ~0;
				}
			}
			else {
				for (srl = re->r.layers.first; srl; srl = srl->next) {
					if (!(srl->layflag & SCE_LAY_DISABLE)) {
						non_excluded_lay |= ~srl->lay_exclude;

						if (render_layer_exclude_animated(re->scene, srl))
							non_excluded_lay |= ~0;
					}
				}
			}

			lay &= non_excluded_lay;
		}

		BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true);
		render_update_anim_renderdata(re, &re->scene->r);
	}

	/* create render result */
	BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
	if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
		int savebuffers = RR_USE_MEM;

		if (re->result)
			render_result_free(re->result);

		if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
			savebuffers = RR_USE_EXR;
		re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
	}
	BLI_rw_mutex_unlock(&re->resultmutex);

	if (re->result == NULL) {
		/* Clear UI drawing locks. */
		if (re->draw_lock) {
			re->draw_lock(re->dlh, 0);
		}
		return 1;
	}

	/* set render info */
	re->i.cfra = re->scene->r.cfra;
	BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
	re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;

	/* render */
	engine = re->engine;

	if (!engine) {
		engine = RE_engine_create(type);
		re->engine = engine;
	}

	engine->flag |= RE_ENGINE_RENDERING;

	/* TODO: actually link to a parent which shouldn't happen */
	engine->re = re;

	if (re->flag & R_ANIMATION)
		engine->flag |= RE_ENGINE_ANIMATION;
	if (re->r.scemode & R_BUTS_PREVIEW)
		engine->flag |= RE_ENGINE_PREVIEW;
	engine->camera_override = re->camera_override;
	engine->layer_override = re->layer_override;

	engine->resolution_x = re->winx;
	engine->resolution_y = re->winy;

	RE_parts_init(re, false);
	engine->tile_x = re->partx;
	engine->tile_y = re->party;

	if (re->result->do_exr_tile)
		render_result_exr_file_begin(re);

	if (type->update)
		type->update(engine, re->main, re->scene);

	/* Clear UI drawing locks. */
	if (re->draw_lock) {
		re->draw_lock(re->dlh, 0);
	}

	if (type->render)
		type->render(engine, re->scene);

	engine->tile_x = 0;
	engine->tile_y = 0;
	engine->flag &= ~RE_ENGINE_RENDERING;

	render_result_free_list(&engine->fullresult, engine->fullresult.first);

	BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);

	/* re->engine becomes zero if user changed active render engine during render */
	if (!persistent_data || !re->engine) {
		RE_engine_free(engine);
		re->engine = NULL;
	}

	if (re->result->do_exr_tile) {
		BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
		render_result_exr_file_end(re);
		BLI_rw_mutex_unlock(&re->resultmutex);
	}

	if (re->r.scemode & R_EXR_CACHE_FILE) {
		BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
		render_result_exr_file_cache_write(re);
		BLI_rw_mutex_unlock(&re->resultmutex);
	}

	RE_parts_free(re);
	BLI_rw_mutex_unlock(&re->partsmutex);

	if (BKE_reports_contain(re->reports, RPT_ERROR))
		G.is_break = true;
	
#ifdef WITH_FREESTYLE
	if (re->r.mode & R_EDGE_FRS)
		RE_RenderFreestyleExternal(re);
#endif

	return 1;
}
Example #25
0
static void init_frame_smoke(VoxelData *vd, int cfra)
{
#ifdef WITH_SMOKE
	Object *ob;
	ModifierData *md;
	
	vd->dataset = NULL;
	if (vd->object == NULL) return;
	ob = vd->object;
	
	/* draw code for smoke */
	if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke))) {
		SmokeModifierData *smd = (SmokeModifierData *)md;
		SmokeDomainSettings *sds = smd->domain;
		
		if (sds && sds->fluid) {
			BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);

			if (!sds->fluid) {
				BLI_rw_mutex_unlock(sds->fluid_mutex);
				return;
			}

			if (cfra < sds->point_cache[0]->startframe)
				;  /* don't show smoke before simulation starts, this could be made an option in the future */
			else if (vd->smoked_type == TEX_VD_SMOKEHEAT) {
				size_t totRes;
				size_t i;
				float *heat;

				if (!smoke_has_heat(sds->fluid)) {
					BLI_rw_mutex_unlock(sds->fluid_mutex);
					return;
				}

				copy_v3_v3_int(vd->resol, sds->res);
				totRes = vd_resol_size(vd);
				vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data");
				/* get heat data */
				heat = smoke_get_heat(sds->fluid);

				/* scale heat values from -2.0-2.0 to 0.0-1.0 */
				for (i = 0; i < totRes; i++) {
					vd->dataset[i] = (heat[i] + 2.0f) / 4.0f;
				}
			}
			else if (vd->smoked_type == TEX_VD_SMOKEVEL) {
				size_t totRes;
				size_t i;
				float *xvel, *yvel, *zvel;

				copy_v3_v3_int(vd->resol, sds->res);
				totRes = vd_resol_size(vd);
				vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data");
				/* get velocity data */
				xvel = smoke_get_velocity_x(sds->fluid);
				yvel = smoke_get_velocity_y(sds->fluid);
				zvel = smoke_get_velocity_z(sds->fluid);

				/* map velocities between 0 and 0.3f */
				for (i = 0; i < totRes; i++) {
					vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f;
				}

			}
			else if (vd->smoked_type == TEX_VD_SMOKEFLAME) {
				size_t totRes;
				float *flame;

				if (sds->flags & MOD_SMOKE_HIGHRES) {
					if (!smoke_turbulence_has_fuel(sds->wt)) {
						BLI_rw_mutex_unlock(sds->fluid_mutex);
						return;
					}
					smoke_turbulence_get_res(sds->wt, vd->resol);
					flame = smoke_turbulence_get_flame(sds->wt);
				}
				else {
					if (!smoke_has_fuel(sds->fluid)) {
						BLI_rw_mutex_unlock(sds->fluid_mutex);
						return;
					}
					copy_v3_v3_int(vd->resol, sds->res);
					flame = smoke_get_flame(sds->fluid);
				}

				/* always store copy, as smoke internal data can change */
				totRes = vd_resol_size(vd);
				vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data");
				memcpy(vd->dataset, flame, sizeof(float)*totRes);
			}
			else {
				size_t totCells;
				int depth = 4;
				vd->data_type = TEX_VD_RGBA_PREMUL;

				/* data resolution */
				if (sds->flags & MOD_SMOKE_HIGHRES) {
					smoke_turbulence_get_res(sds->wt, vd->resol);
				}
				else {
					copy_v3_v3_int(vd->resol, sds->res);
				}

				/* TODO: is_vd_res_ok(rvd) doesnt check this resolution */
				totCells = vd_resol_size(vd) * depth;
				/* always store copy, as smoke internal data can change */
				vd->dataset = MEM_mapallocN(sizeof(float) * totCells, "smoke data");

				if (sds->flags & MOD_SMOKE_HIGHRES) {
					if (smoke_turbulence_has_colors(sds->wt)) {
						smoke_turbulence_get_rgba(sds->wt, vd->dataset, 1);
					}
					else {
						smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, vd->dataset, 1);
					}
				}
				else {
					if (smoke_has_colors(sds->fluid)) {
						smoke_get_rgba(sds->fluid, vd->dataset, 1);
					}
					else {
						smoke_get_rgba_from_density(sds->fluid, sds->active_color, vd->dataset, 1);
					}
				}
			}  /* end of fluid condition */

			BLI_rw_mutex_unlock(sds->fluid_mutex);
		}
	}
	
	vd->ok = 1;

#else // WITH_SMOKE
	(void)vd;
	(void)cfra;

	vd->dataset = NULL;
#endif
}