diff options
Diffstat (limited to 'source/blender/render/intern/source/volume_precache.c')
-rw-r--r-- | source/blender/render/intern/source/volume_precache.c | 172 |
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; } |