htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit 6e50b71038e29f34cf3da1c9fda874daea997af1
parent c6d6772a4922c273c7b7dd05d3ec3b7251dcdf3d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 10 Jul 2018 16:50:48 +0200

Implement the htrdr_sky_fetch_raw_property function

Diffstat:
Msrc/htrdr_draw_sw.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/htrdr_sky.c | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/htrdr_sky.h | 15+++++++++------
Msrc/htrdr_transmission.c | 2+-
4 files changed, 140 insertions(+), 31 deletions(-)

diff --git a/src/htrdr_draw_sw.c b/src/htrdr_draw_sw.c @@ -15,22 +15,30 @@ struct scattering_context { struct ssp_rng* rng; + const struct htrdr_sky* sky + double wavelength; double Ts; /* Sampled optical thickness */ double traversal_dst; /* Distance traversed along the ray */ }; static const struct scattering_context SCATTERING_CONTEXT_NULL = { - NULL, 0, 0, 0, 0 + NULL, NULL, 0, 0, 0, 0, 0 }; struct transmissivity_context { struct ssp_rng* rng; + const struct htrdr_sky* sky; + double wavelength; + double Ts; /* Sampled optical thickness */ double Tmin; /* Minimal optical thickness */ double traversal_dst; /* Distance traversed along the ray */ + + + int prop_mask; /* Mask of htrdr_sky_property_flag */ }; static const struct transmissivity_context TRANSMISSION_CONTEXT_NULL = { - NULL, 0, 0; + NULL, NULL, 0, 0, 0, 0, 0 }; /******************************************************************************* @@ -53,7 +61,7 @@ scattering_hit_filter (void)range; vox_data = hit->voxel.data; - ks_max = vox_data[HTRDR_Ks_MAX]; + ks_max = vox_data[HTRDR_Ks_MAX/*TODO*/]; for(;;) { dst = hit->distance[1] - ctx->traversal_dst; @@ -67,7 +75,7 @@ scattering_hit_filter break; /* A real/null collision occurs before `dst' */ - } else { + else { double pos[3]; double proba_s; double ks; @@ -82,7 +90,14 @@ scattering_hit_filter pos[1] = org[1] + dst * dir[1]; pos[2] = org[2] + dst * dir[2]; - ks = fetch_ks(ctx->medium, x); /* TODO */ + /* TODO use a per wavelength getter that will precompute the interpolated + * cross sections for a wavelength to improve the fetch efficiency */ + ks = htrdr_sky_fetch_raw_property + (ctx->sky, + HTRDR_SKY_Ks, + HTRDR_SKY_PARTICLE | HTRDR_SKY_GAZ, + ctx->wavelength, + pos); /* Handle the case that ks_max is not *really* the max */ proba_s = ks / ks_max; @@ -149,7 +164,12 @@ transmissivty_hit_filter x[1] = org[1] + dst * dir[1]; x[2] = org[2] + dst * dir[2]; - k = fetch_k(ctx->medium, x); /* TODO */ + k = htrdr_sky_fetch_raw_property + (ctx->sky, + ctx->prop_mask, + HTRDR_SKY_PARTICLE | HTRDR_SKY_GAZ, + ctx->wavelength, + x); /* Handle the case that k_max is not *really* the max */ proba = (k - k_min) / (k_max - k_min); @@ -170,6 +190,8 @@ static double transmissivity (struct htrdr* htrdr, struct ssp_rng* rng, + const int prop_mask, /* Combination of htrdr_sky_property_flag */ + const double wavelength, const double pos[3], const double dir[3], const double range[2], @@ -184,7 +206,8 @@ transmissivity float ray_dir[3]; float ray_range[2]; - ASSERT(htrdr && rng && pos && dir && range); + ASSERT(htrdr && rng && prop_mask && pos && dir && range); + ASSERT(prop_mask & HTRDR_SKY_PROP_Kext); /* Find the first intersection with a surface */ f3_set_d3(ray_pos, pos); @@ -196,7 +219,10 @@ transmissivity if(!S3D_HIT_NONE(&s3d_hit)) return 0; transmissivity_ctx->rng = rng; + transmissivity_ctx->sky = htrdr->sky; + transmissivity_ctx->wavelength = wavelength; transmissivity_ctx->Ts = ssp_ran_exp(rng, 1); /* Sample an optical thickness */ + transmissivity_ctx->prop_mask = prop_mask; /* Compute the transmissivity */ SVX(octree_trace_ray(htrdr->clouds, pos, dir, range, NULL, @@ -246,23 +272,28 @@ radiance_sw ASSERT(htrdr && rng && pos && dir); + /* Fetch sun properties */ sun_solid_angle = htrdr_sun_get_solid_angle(htrdr->sun); + L_sun = htrdr_sun_get_radiance(htrdr->sun, wavelength); + d3_set(pos, pos_in); d3_set(dir, dir_in); - /* Check that the sun is directly visible */ - f3_set_d3(ray_pos, pos); - f3_set_d3(ray_dir, sun_dir); - f2(ray_range, 0, FLT_MAX); - S3D(scene_view_trace - (htrdr->s3d_scn, ray_pos, ray_dir, ray_range, NULL, &s3d_hit)); - - /* Add the direct contribution of the sun */ - if(!S3D_HIT_NONE(&s3d_hit)) { - d3(range, 0, FLT_MAX); - L_sun = htrdr_sun_get_luminance(htrdr->sun, sun_dir, wavelength); - Tr = transmissivity(htrdr, rng, pos, sun_dir, range); - w = L_sun * Tr; + /* Add the directly contribution of the sun */ + if(htrdr_sun_is_dir_in_solar_cone(sun, dir)) { + f3_set_d3(ray_pos, pos); + f3_set_d3(ray_dir, dir); + f2(ray_range, 0, FLT_MAX); + S3D(scene_view_trace + (htrdr->s3d_scn, ray_pos, ray_dir, ray_range, NULL, &s3d_hit)); + + /* Add the direct contribution of the sun */ + if(!S3D_HIT_NONE(&s3d_hit)) { + d3(range, 0, FLT_MAX); + Tr = transmissivity + (htrdr, rng, HTRDR_SKY_PROP_Kext, wavelength , pos, dir, range); + w = L_sun * Tr; + } } /* Radiative random walk */ @@ -279,9 +310,13 @@ radiance_sw &s3d_hit_prev, &s3d_hit)); /* Sample an optical thicknes */ - scattering_ctx->rng = rng; scattering_ctx->Ts = ssp_ran_exp(rng, 1); + /* Setup the remaining scattering context fields */ + scattering_ctx->rng = rng; + scattering_ctx->sky = htrdr->sky; + scattering_ctx->wavelength = wavelength; + /* Define if a scattering event occurs */ d2(range, 0, s3d_hit.distance); SVX(octree_trace_ray(htrdr->clouds, pos, dir, range, NULL, @@ -304,13 +339,15 @@ radiance_sw /* Define the absorption transmissivity from the current position to the * next position */ d2(range, 0, scattering_ctx->traversal_dst); - Tr_abs = transmissivity_absorption(htrdr, rng, pos, dir, range); + Tr_abs = transmissivity + (htrdr, rng, HTRDR_SKY_PROP_Ka, wavelength, pos, dir, range); if(Tr_abs <= 0) break; /* Define the transmissivity from the new position to the sun */ d2(range, 0, FLT_MAX); htrdr_sun_sample_dir(htrdr->sun, rng, pos_next, sun_dir); - Tr = transmissivity(htrdr, rng, pos_next, sun_dir, range); + Tr = transmissivity + (htrdr, rng, HTRDR_SKY_PROP_Kext, wavelength, pos_next, sun_dir, range); /* Scattering at a surface */ if(SVX_HIT_NONE(&svx_hit)) { diff --git a/src/htrdr_sky.c b/src/htrdr_sky.c @@ -71,6 +71,8 @@ struct octree_data { struct htrdr_sky { struct svx_tree* clouds; + struct svx_tree_desc cloud_desc; + struct htcp* htcp; struct htmie* htmie; @@ -354,6 +356,9 @@ setup_clouds(struct htrdr_sky* sky) goto error; } + /* Fetch the octree descriptor for future use */ + SVX(tree_get_desc(sky->clouds, &sky->cloud_desc)); + exit: return res; error: @@ -453,6 +458,70 @@ htrdr_sky_ref_put(struct htrdr_sky* sky) ref_put(&sky->ref, release_sky); } +double +htrdr_sky_fetch_raw_property + (const struct htrdr_sky* sky, + const int prop_mask, /* Combination of htrdr_sky_property_flag */ + const int comp_mask_in, /* Combination of htrdr_sky_component_flag */ + const double wavelength, + const double pos[3]) +{ + size_t ivox[3]; + int comp_mask = comp_mask_in; + double k_particle = 0; + double k_gaz = 0; + ASSERT(sky && pos && wavelength > 0); + ASSERT(prop_mask & HTRDR_SKY_PROP_Kext); + ASSERT(components_mask & HTRDR_SKY_COMP_ALL); + + /* Is the position outside the clouds? */ + if(pos[0] < sky->cloud_desc.lower[0] + || pos[1] < sky->cloud_desc.lower[1] + || pos[2] < sky->cloud_desc.lower[2] + || pos[0] > sky->cloud_desc.upper[0] + || pos[1] > sky->cloud_desc.upper[1] + || pos[2] > sky->cloud_desc.upper[2]) { + comp_mask &= ~HTRDR_SKY_COMP_PARTICLE; /* No particle */ + } + + /* Compute the index of the voxel to fetch */ + ivox[0] = (size_t)((pos[0] - sky->cloud_desc.lower[0])/sky->htcp_desc.vxsz_x); + ivox[1] = (size_t)((pos[1] - sky->cloud_desc.lower[1])/sky->htcp_desc.vxsz_y); + if(!sky->htcp_desc.irregular_z) { + /* The voxels along the Z dimension have the same size */ + ivox[2] = (size_t)((pos[2] - sky->cloud_desc.lower[2])/sky->htcp_desc.vxsz_z[0]); + } else { + /* Irregular voxel size along the Z dimension. Compute the index Z position + * in the svx2htcp_z Look Up Table and use the LUT to define the voxel + * index into the HTCP descripptor */ + const struct split* splits = darray_split_cdata_get(&sky->svx2htcp_z); + const size_t n = darray_split_size_get(&sky->svx2htcp_z); + const double sz = sky->cloud_desc.upper[2] - sky->cloud_desc.lower[2]; + const double vxsz_lut = sz / (double)n; + const size_t ilut = (size_t)((pos[2] - sky->cloud_desc.lower[2])/vxsz_lut); + ivox[2] = splits[ilut].index + (pos[2] >= splits[ilut].height); + } + + if(comp_mask & HTRDR_SKY_COMP_PARTICLE) { + double ql = 0; /* Droplet density In kg.m^-3 */ + double ca = 0; /* Massic absorption cross section in m^2.kg^-1 */ + double cs = 0; /* Massic scattering cross section in m^2.kg^-1 */ + + ql = htcp_desc_RCT_at(&sky->htcp_desc, ivox[0], ivox[1], ivox[2], 0); + if(prop_mask & HTRDR_SKY_PROP_Ks) { + cs = htmie_fetch_xsection_scattering + (sky->htmie, wavelength, HTMIE_FILTER_LINEAR); + } + if(prop_mask & HTRDR_SKY_PROP_Ka) { + ca = htmie_fetch_xsection_absorption + (sky->htmie, wavelength, HTMIE_FILTER_LINEAR); + } + k_particle = ql*(ca + cs); + } + if(comp_mask & HTRDR_SKY_COMP_GAZ) { /* TODO not implemented yet */ } + return k_particle + k_gaz; +} + struct svx_tree* htrdr_sky_get_svx_tree(struct htrdr_sky* sky) { @@ -567,7 +636,7 @@ htrdr_sky_fetch_svx_voxel_property ASSERT((unsigned)prop < HTRDR_SKY_SVX_PROPS_COUNT__); (void)sky, (void)wavelength; - if(components_mask != (HTRDR_SKY_GAZ|HTRDR_SKY_PARTICLE)) { + if(components_mask != HTRDR_SKY_COMP_ALL) { FATAL("Unsupported sky component\n"); } pdbl = voxel->data; diff --git a/src/htrdr_sky.h b/src/htrdr_sky.h @@ -19,9 +19,10 @@ #include <rsys/rsys.h> /* Raw sky properties */ -enum htrdr_sky_property { - HTRDR_SKY_Ks, /* Scattering coefficient */ - HTRDR_SKY_Ka /* Absorption coefficient */ +enum htrdr_sky_property_flag { + HTRDR_SKY_PROP_Ks = BIT(0), /* Scattering coefficient */ + HTRDR_SKY_PROP_Ka = BIT(1), /* Absorption coefficient */ + HTRDR_SKY_PROP_Kext = HTRDR_SKY_PROP_Ks | HTRDR_SKY_PROP_Ka }; /* Property of the sky computed by region and managed by Star-VoXel */ @@ -29,12 +30,14 @@ enum htrdr_sky_svx_property { HTRDR_SKY_SVX_Kext_MIN, HTRDR_SKY_SVX_Kext_MAX, HTRDR_SKY_SVX_PROPS_COUNT__ + }; /* Component of the sky for which the properties are queried */ enum htrdr_sky_component_flag { - HTRDR_SKY_GAZ = BIT(0), - HTRDR_SKY_PARTICLE = BIT(1) + HTRDR_SKY_COMP_GAZ = BIT(0), + HTRDR_SKY_COMP_PARTICLE = BIT(1), + HTRDR_SKY_COMP_ALL = HTRDR_SKY_COMP_GAZ | HTRDR_SKY_COMP_PARTICLE }; /* Forward declaration */ @@ -61,7 +64,7 @@ htrdr_sky_ref_put extern LOCAL_SYM double htrdr_sky_fetch_raw_property (const struct htrdr_sky* sky, - const enum htrdr_sky_property prop, + const int prop_mask, /* Combination of htrdr_sky_property_flag */ const int components_mask, /* Combination of htrdr_sky_component_flag */ const double wavelength, const double pos[3]); diff --git a/src/htrdr_transmission.c b/src/htrdr_transmission.c @@ -55,7 +55,7 @@ discard_hit const double range[2], void* context) { - const int comp = HTRDR_SKY_GAZ | HTRDR_SKY_PARTICLE; + const int comp = HTRDR_SKY_COMP_GAZ | HTRDR_SKY_COMP_PARTICLE; struct transmit_context* ctx = context; double dst; double k_ext_min;