Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/render/intern/source/volume_precache.c')
-rw-r--r--source/blender/render/intern/source/volume_precache.c172
1 files changed, 86 insertions, 86 deletions
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 8ef35828be9..8e79f309814 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -76,18 +76,18 @@ extern struct Render R;
static int intersect_outside_volume(RayObject *tree, Isect *isect, float *offset, int limit, int depth)
{
if (limit == 0) return depth;
-
+
if (RE_rayobject_raycast(tree, isect)) {
-
+
isect->start[0] = isect->start[0] + isect->dist*isect->dir[0];
isect->start[1] = isect->start[1] + isect->dist*isect->dir[1];
isect->start[2] = isect->start[2] + isect->dist*isect->dir[2];
-
+
isect->dist = FLT_MAX;
isect->skip = RE_SKIP_VLR_NEIGHBOUR;
isect->orig.face= isect->hit.face;
isect->orig.ob= isect->hit.ob;
-
+
return intersect_outside_volume(tree, isect, offset, limit-1, depth+1);
}
else {
@@ -101,14 +101,14 @@ static int point_inside_obi(RayObject *tree, ObjectInstanceRen *obi, const float
Isect isect= {{0}};
float dir[3] = {0.0f, 0.0f, 1.0f};
int final_depth=0, depth=0, limit=20;
-
+
/* set up the isect */
copy_v3_v3(isect.start, co);
copy_v3_v3(isect.dir, dir);
isect.mode= RE_RAY_MIRROR;
isect.last_hit= NULL;
isect.lay= -1;
-
+
isect.dist = FLT_MAX;
isect.orig.face= NULL;
isect.orig.ob = NULL;
@@ -116,7 +116,7 @@ static int point_inside_obi(RayObject *tree, ObjectInstanceRen *obi, const float
RE_instance_rotate_ray(obi, &isect);
final_depth = intersect_outside_volume(tree, &isect, dir, limit, depth);
RE_instance_rotate_ray_restore(obi, &isect);
-
+
/* even number of intersections: point is outside
* odd number: point is inside */
if (final_depth % 2 == 0) return 0;
@@ -131,37 +131,37 @@ void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float bbmin[3], float
VertRen *ver= NULL;
float co[3];
int a;
-
+
if (vp->bbmin != NULL && vp->bbmax != NULL) {
copy_v3_v3(bbmin, vp->bbmin);
copy_v3_v3(bbmax, vp->bbmax);
return;
}
-
+
vp->bbmin = MEM_callocN(sizeof(float)*3, "volume precache min boundbox corner");
vp->bbmax = MEM_callocN(sizeof(float)*3, "volume precache max boundbox corner");
-
+
INIT_MINMAX(bbmin, bbmax);
-
+
for (a=0; a<obr->totvert; a++) {
if ((a & 255)==0) ver= obr->vertnodes[a>>8].vert;
else ver++;
-
+
copy_v3_v3(co, ver->co);
-
+
/* transformed object instance in camera space */
if (obi->flag & R_TRANSFORMED)
mul_m4_v3(obi->mat, co);
-
+
/* convert to global space */
mul_m4_v3(re->viewinv, co);
-
+
minmax_v3v3_v3(vp->bbmin, vp->bbmax, co);
}
-
+
copy_v3_v3(bbmin, vp->bbmin);
copy_v3_v3(bbmax, vp->bbmax);
-
+
}
/* *** light cache filtering *** */
@@ -171,34 +171,34 @@ static float get_avg_surrounds(float *cache, int *res, int xx, int yy, int zz)
int x, y, z, x_, y_, z_;
int added=0;
float tot=0.0f;
-
+
for (z=-1; z <= 1; z++) {
z_ = zz+z;
if (z_ >= 0 && z_ <= res[2]-1) {
-
+
for (y=-1; y <= 1; y++) {
y_ = yy+y;
if (y_ >= 0 && y_ <= res[1]-1) {
-
+
for (x=-1; x <= 1; x++) {
x_ = xx+x;
if (x_ >= 0 && x_ <= res[0]-1) {
const int64_t i = BLI_VOXEL_INDEX(x_, y_, z_, res);
-
+
if (cache[i] > 0.0f) {
tot += cache[i];
added++;
}
-
+
}
}
}
}
}
}
-
+
if (added > 0) tot /= added;
-
+
return tot;
}
@@ -215,7 +215,7 @@ static void lightcache_filter(VolumePrecache *vp)
for (x=0; x < vp->res[0]; x++) {
/* trigger for outside mesh */
const int64_t i = BLI_VOXEL_INDEX(x, y, z, vp->res);
-
+
if (vp->data_r[i] < -0.f)
vp->data_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
if (vp->data_g[i] < -0.f)
@@ -233,15 +233,15 @@ static void lightcache_filter2(VolumePrecache *vp)
int x, y, z;
float *new_r, *new_g, *new_b;
int field_size = vp->res[0]*vp->res[1]*vp->res[2]*sizeof(float);
-
+
new_r = MEM_mallocN(field_size, "temp buffer for light cache filter r channel");
new_g = MEM_mallocN(field_size, "temp buffer for light cache filter g channel");
new_b = MEM_mallocN(field_size, "temp buffer for light cache filter b channel");
-
+
memcpy(new_r, vp->data_r, field_size);
memcpy(new_g, vp->data_g, field_size);
memcpy(new_b, vp->data_b, field_size);
-
+
for (z=0; z < vp->res[2]; z++) {
for (y=0; y < vp->res[1]; y++) {
for (x=0; x < vp->res[0]; x++) {
@@ -256,11 +256,11 @@ static void lightcache_filter2(VolumePrecache *vp)
}
}
}
-
+
SWAP(float *, vp->data_r, new_r);
SWAP(float *, vp->data_g, new_g);
SWAP(float *, vp->data_b, new_b);
-
+
if (new_r) { MEM_freeN(new_r); new_r=NULL; }
if (new_g) { MEM_freeN(new_g); new_g=NULL; }
if (new_b) { MEM_freeN(new_b); new_b=NULL; }
@@ -286,7 +286,7 @@ BLI_INLINE int64_t v_I_pad(int x, int y, int z, const int *n)
}
BLI_INLINE int64_t lc_to_ms_I(int x, int y, int z, const int *n)
-{
+{
/* converting light cache index to multiple scattering index */
return ((int64_t)(x - 1) * ((int64_t)n[1] * (int64_t)n[2]) +
(int64_t)(y - 1) * ((int64_t)n[2]) +
@@ -301,12 +301,12 @@ static float total_ss_energy(Render *re, int do_test_break, VolumePrecache *vp)
int x, y, z;
const int *res = vp->res;
float energy=0.f;
-
+
for (z=0; z < res[2]; z++) {
for (y=0; y < res[1]; y++) {
for (x=0; x < res[0]; x++) {
const int64_t i = BLI_VOXEL_INDEX(x, y, z, res);
-
+
if (vp->data_r[i] > 0.f) energy += vp->data_r[i];
if (vp->data_g[i] > 0.f) energy += vp->data_g[i];
if (vp->data_b[i] > 0.f) energy += vp->data_b[i];
@@ -315,7 +315,7 @@ static float total_ss_energy(Render *re, int do_test_break, VolumePrecache *vp)
if (do_test_break && re->test_break(re->tbh)) break;
}
-
+
return energy;
}
@@ -323,12 +323,12 @@ static float total_ms_energy(Render *re, int do_test_break, float *sr, float *sg
{
int x, y, z;
float energy=0.f;
-
+
for (z=1;z<=res[2];z++) {
for (y=1;y<=res[1];y++) {
for (x=1;x<=res[0];x++) {
const int64_t i = ms_I(x, y, z, res);
-
+
if (sr[i] > 0.f) energy += sr[i];
if (sg[i] > 0.f) energy += sg[i];
if (sb[i] > 0.f) energy += sb[i];
@@ -337,7 +337,7 @@ static float total_ms_energy(Render *re, int do_test_break, float *sr, float *sg
if (do_test_break && re->test_break(re->tbh)) break;
}
-
+
return energy;
}
@@ -350,7 +350,7 @@ static void ms_diffuse(Render *re, int do_test_break, const float *x0, float *x,
const float dt = VOL_MS_TIMESTEP;
int64_t size = (int64_t)n[0] * (int64_t)n[1] * (int64_t)n[2];
const float a = dt * diff * size;
-
+
for (l=0; l<20; l++) {
for (k=1; k<=n[2]; k++) {
for (j=1; j<=n[1]; j++) {
@@ -379,7 +379,7 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
const int simframes = (int)(ma->vol.ms_spread * (float)max_iii(vp->res[0], vp->res[1], vp->res[2]));
const int shade_type = ma->vol.shade_type;
float fac = ma->vol.ms_intensity;
-
+
int x, y, z, m;
const int *n = vp->res;
const int size = (n[0]+2)*(n[1]+2)*(n[2]+2);
@@ -398,9 +398,9 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
float *sb=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
total = (float)(n[0]*n[1]*n[2]*simframes);
-
+
energy_ss = total_ss_energy(re, do_test_break, vp);
-
+
/* Scattering as diffusion pass */
for (m=0; m<simframes; m++) {
/* add sources */
@@ -409,7 +409,7 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
for (x=1; x<=n[0]; x++) {
const int64_t i = lc_to_ms_I(x, y, z, n); //lc index
const int64_t j = ms_I(x, y, z, n); //ms index
-
+
time= PIL_check_seconds_timer();
c++;
if (vp->data_r[i] > 0.0f)
@@ -418,7 +418,7 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
sg[j] += vp->data_g[i];
if (vp->data_b[i] > 0.0f)
sb[j] += vp->data_b[i];
-
+
/* Displays progress every second */
if (time-lasttime>1.0) {
char str[64];
@@ -445,14 +445,14 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
ms_diffuse(re, do_test_break, sr0, sr, diff, n);
ms_diffuse(re, do_test_break, sg0, sg, diff, n);
ms_diffuse(re, do_test_break, sb0, sb, diff, n);
-
+
if (re->test_break(re->tbh)) break;
}
-
+
/* normalization factor to conserve energy */
energy_ms = total_ms_energy(re, do_test_break, sr, sg, sb, n);
fac *= (energy_ss / energy_ms);
-
+
/* blend multiple scattering back in the light cache */
if (shade_type == MA_VOL_SHADE_SHADEDPLUSMULTIPLE) {
/* conserve energy - half single, half multiple */
@@ -468,7 +468,7 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
for (x=1;x<=n[0];x++) {
const int64_t i = lc_to_ms_I(x, y, z, n); //lc index
const int64_t j = ms_I(x, y, z, n); //ms index
-
+
vp->data_r[i] = origf * vp->data_r[i] + fac * sr[j];
vp->data_g[i] = origf * vp->data_g[i] + fac * sg[j];
vp->data_b[i] = origf * vp->data_b[i] + fac * sb[j];
@@ -532,7 +532,7 @@ static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UN
if (re->test_break && re->test_break(re->tbh))
return;
-
+
//printf("thread id %d\n", threadid);
res[0]= pa->res[0];
@@ -541,17 +541,17 @@ static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UN
for (z= pa->minz; z < pa->maxz; z++) {
co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
-
+
for (y= pa->miny; y < pa->maxy; y++) {
co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
-
+
for (x=pa->minx; x < pa->maxx; x++) {
int64_t i;
co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
-
+
if (re->test_break && re->test_break(re->tbh))
break;
-
+
/* convert from world->camera space for shading */
mul_v3_m4v3(cco, pa->viewmat, co);
@@ -564,15 +564,15 @@ static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UN
obi->volume_precache->data_b[i] = -1.0f;
continue;
}
-
+
copy_v3_v3(view, cco);
normalize_v3(view);
vol_get_scattering(shi, scatter_col, cco, view);
-
+
obi->volume_precache->data_r[i] = scatter_col[0];
obi->volume_precache->data_g[i] = scatter_col[1];
obi->volume_precache->data_b[i] = scatter_col[2];
-
+
}
}
}
@@ -599,7 +599,7 @@ static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UN
static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi)
{
- memset(shi, 0, sizeof(ShadeInput));
+ memset(shi, 0, sizeof(ShadeInput));
shi->depth= 1;
shi->mask= 1;
shi->mat = ma;
@@ -627,26 +627,26 @@ static void precache_launch_parts(Render *re, RayObject *tree, ShadeInput *shi,
int minz, maxz;
int totthread = re->r.threads;
int parts[3];
-
+
if (!vp) return;
/* currently we just subdivide the box, number of threads per side */
parts[0] = parts[1] = parts[2] = totthread;
res = vp->res;
-
+
/* setup task scheduler */
memset(&state, 0, sizeof(state));
state.doneparts = 0;
state.totparts = parts[0]*parts[1]*parts[2];
state.lasttime = PIL_check_seconds_timer();
-
+
task_scheduler = BLI_task_scheduler_create(totthread);
task_pool = BLI_task_pool_create(task_scheduler, &state);
/* using boundbox in worldspace */
global_bounds_obi(re, obi, bbmin, bbmax);
sub_v3_v3v3(voxel, bbmax, bbmin);
-
+
voxel[0] /= (float)res[0];
voxel[1] /= (float)res[1];
voxel[2] /= (float)res[2];
@@ -656,38 +656,38 @@ static void precache_launch_parts(Render *re, RayObject *tree, ShadeInput *shi,
minx = x * sizex;
maxx = minx + sizex;
maxx = (maxx>res[0])?res[0]:maxx;
-
+
for (y=0; y < parts[1]; y++) {
sizey = ceil(res[1] / (float)parts[1]);
miny = y * sizey;
maxy = miny + sizey;
maxy = (maxy>res[1])?res[1]:maxy;
-
+
for (z=0; z < parts[2]; z++) {
VolPrecachePart *pa= MEM_callocN(sizeof(VolPrecachePart), "new precache part");
-
+
sizez = ceil(res[2] / (float)parts[2]);
minz = z * sizez;
maxz = minz + sizez;
maxz = (maxz>res[2])?res[2]:maxz;
-
+
pa->re = re;
pa->num = i;
pa->tree = tree;
pa->shi = shi;
pa->obi = obi;
copy_m4_m4(pa->viewmat, re->viewmat);
-
+
copy_v3_v3(pa->bbmin, bbmin);
copy_v3_v3(pa->voxel, voxel);
copy_v3_v3_int(pa->res, res);
-
+
pa->minx = minx; pa->maxx = maxx;
pa->miny = miny; pa->maxy = maxy;
pa->minz = minz; pa->maxz = maxz;
-
+
BLI_task_pool_push(task_pool, vol_precache_part, pa, true, TASK_PRIORITY_HIGH);
-
+
i++;
}
}
@@ -706,23 +706,23 @@ static int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen
{
float dim[3], div;
float bbmin[3], bbmax[3];
-
+
/* bound box in global space */
global_bounds_obi(re, obi, bbmin, bbmax);
sub_v3_v3v3(dim, bbmax, bbmin);
-
+
div = max_fff(dim[0], dim[1], dim[2]);
dim[0] /= div;
dim[1] /= div;
dim[2] /= div;
-
+
vp->res[0] = ceil(dim[0] * res);
vp->res[1] = ceil(dim[1] * res);
vp->res[2] = ceil(dim[2] * res);
-
+
if ((vp->res[0] < 1) || (vp->res[1] < 1) || (vp->res[2] < 1))
return 0;
-
+
return 1;
}
@@ -736,17 +736,17 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
VolumePrecache *vp;
RayObject *tree;
ShadeInput shi;
-
+
R = *re;
- /* create a raytree with just the faces of the instanced ObjectRen,
+ /* create a raytree with just the faces of the instanced ObjectRen,
* used for checking if the cached point is inside or outside. */
tree = makeraytree_object(&R, obi);
if (!tree) return;
vp = MEM_callocN(sizeof(VolumePrecache), "volume light cache");
obi->volume_precache = vp;
-
+
if (!precache_resolution(re, vp, obi, ma->vol.precache_resolution)) {
MEM_freeN(vp);
vp = NULL;
@@ -763,7 +763,7 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
/* Need a shadeinput to calculate scattering */
precache_setup_shadeinput(re, obi, ma, &shi);
-
+
precache_launch_parts(re, tree, &shi, obi);
if (tree) {
@@ -772,12 +772,12 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
//RE_rayobject_free(tree);
//tree= NULL;
}
-
+
if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) {
/* this should be before the filtering */
multiple_scattering_diffusion(re, obi->volume_precache, ma);
}
-
+
lightcache_filter(obi->volume_precache);
}
@@ -812,7 +812,7 @@ void volume_precache(Render *re)
break;
}
}
-
+
re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
@@ -820,7 +820,7 @@ void volume_precache(Render *re)
void free_volume_precache(Render *re)
{
ObjectInstanceRen *obi;
-
+
for (obi= re->instancetable.first; obi; obi= obi->next) {
if (obi->volume_precache != NULL) {
MEM_freeN(obi->volume_precache->data_r);
@@ -832,7 +832,7 @@ void free_volume_precache(Render *re)
obi->volume_precache = NULL;
}
}
-
+
BLI_freelistN(&re->volumes);
}
@@ -840,16 +840,16 @@ int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, const
{
RayObject *tree;
int inside=0;
-
+
tree = makeraytree_object(re, obi);
if (!tree) return 0;
-
+
inside = point_inside_obi(tree, obi, co);
-
+
//TODO: makeraytree_object creates a tree and saves it on OBI, if we free this tree we should also clear other pointers to it
//RE_rayobject_free(tree);
//tree= NULL;
-
+
return inside;
}