solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit 1ea3bc6169e29f052e3f886e81174a9c57bb7c15
parent bafc434eebc83049b19e330ded71a4745680f058
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  7 Apr 2017 12:43:56 +0200

Handle the optional normal map in the solstice materials

Diffstat:
Msrc/solstice_material.c | 172++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 162 insertions(+), 10 deletions(-)

diff --git a/src/solstice_material.c b/src/solstice_material.c @@ -20,6 +20,10 @@ #include <rsys/image.h> #include <solstice/ssol.h> +struct dielectric_param { + struct ssol_image* normal_map; +}; + struct matte_param { double reflectivity; struct ssol_image* normal_map; @@ -28,6 +32,11 @@ struct matte_param { struct mirror_param { double reflectivity; double roughness; + struct ssol_image* normal_map; +}; + +struct thin_dielectric_param { + struct ssol_image* normal_map; }; /******************************************************************************* @@ -43,7 +52,7 @@ perturb_normal double N[3]; ASSERT(frag && normal_map && normal); - SSOL(image_sample(normal_map, SSOL_FILTER_NEAREST, SSOL_ADDRESS_CLAMP, + SSOL(image_sample(normal_map, SSOL_FILTER_LINEAR, SSOL_ADDRESS_CLAMP, SSOL_ADDRESS_CLAMP, frag->uv, N)); d3_set(basis+0, frag->dPdu); @@ -70,6 +79,27 @@ mtl_get_normal } static void +dielectric_get_normal + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const struct ssol_surface_fragment* frag, + double* val) +{ + const struct dielectric_param* param = ssol_param_buffer_get(buf); + (void)dev, (void)buf, (void)wavelength; + perturb_normal(frag, param->normal_map, val); +} + +static void +dielectric_param_release(void* mem) +{ + struct dielectric_param* param = mem; + ASSERT(param); + if(param->normal_map) SSOL(image_ref_put(param->normal_map)); +} + +static void matte_get_reflectivity (struct ssol_device* dev, struct ssol_param_buffer* buf, @@ -96,6 +126,14 @@ matte_get_normal } static void +matte_param_release(void* mem) +{ + struct matte_param* param = mem; + ASSERT(param); + if(param->normal_map) SSOL(image_ref_put(param->normal_map)); +} + +static void mirror_get_reflectivity (struct ssol_device* dev, struct ssol_param_buffer* buf, @@ -122,9 +160,43 @@ mirror_get_roughness } static void -matte_param_release(void* mem) +mirror_get_normal + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const struct ssol_surface_fragment* frag, + double* val) { - struct matte_param* param = mem; + const struct mirror_param* param = ssol_param_buffer_get(buf); + (void)dev, (void)wavelength; + perturb_normal(frag, param->normal_map, val); +} + +static void +mirror_param_release(void* mem) +{ + struct mirror_param* param = mem; + ASSERT(param); + if(param->normal_map) SSOL(image_ref_put(param->normal_map)); +} + +static void +thin_dielectric_get_normal + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const struct ssol_surface_fragment* frag, + double* val) +{ + const struct thin_dielectric_param* param = ssol_param_buffer_get(buf); + (void)dev, (void)buf, (void)wavelength; + perturb_normal(frag, param->normal_map, val); +} + +static void +thin_dielectric_param_release(void* mem) +{ + struct thin_dielectric_param* param = mem; ASSERT(param); if(param->normal_map) SSOL(image_ref_put(param->normal_map)); } @@ -209,7 +281,9 @@ create_material_dielectric struct ssol_medium ssol_medium_i; struct ssol_medium ssol_medium_t; struct ssol_dielectric_shader shader = SSOL_DIELECTRIC_SHADER_NULL; + struct ssol_image* img = NULL; struct ssol_material* mtl = NULL; + struct ssol_param_buffer* pbuf = NULL; res_T res = RES_OK; ASSERT(solstice && dielectric && out_mtl); @@ -222,7 +296,36 @@ create_material_dielectric medium_i = solparser_get_medium(solstice->parser, dielectric->medium_i); medium_t = solparser_get_medium(solstice->parser, dielectric->medium_t); - shader.normal = mtl_get_normal; + + if(!SOLPARSER_ID_IS_VALID(dielectric->normal_map)) { + shader.normal = mtl_get_normal; + } else { + const struct solparser_image* image; + struct dielectric_param* param = NULL; + + image = solparser_get_image(solstice->parser, dielectric->normal_map); + res = load_image(solstice, str_cget(&image->filename), &img); + if(res != RES_OK) goto error; + + res = ssol_param_buffer_create + (solstice->ssol, sizeof(struct dielectric_param), &pbuf); + if(res != RES_OK) { + fprintf(stderr, "Could not create the Solstice Solver parameter buffer.\n"); + goto error; + } + + param = ssol_param_buffer_allocate(pbuf, sizeof(struct dielectric_param), + ALIGNOF(struct dielectric_param), dielectric_param_release); + if(!param) { + fprintf(stderr, "Could not allocate the dielectric parameter.\n"); + res = RES_MEM_ERR; + goto error; + } + param->normal_map = img; + shader.normal = dielectric_get_normal; + SSOL(material_set_param_buffer(mtl, pbuf)); + } + ssol_medium_i.refractive_index = medium_i->refractive_index; ssol_medium_i.absorptivity = medium_i->absorptivity; ssol_medium_t.refractive_index = medium_t->refractive_index; @@ -230,10 +333,12 @@ create_material_dielectric SSOL(dielectric_setup(mtl, &shader, &ssol_medium_i, &ssol_medium_t)); exit: + if(pbuf) SSOL(param_buffer_ref_put(pbuf)); *out_mtl = mtl; return res; error: if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; + if(img) SSOL(image_ref_put(img)); goto exit; } @@ -275,7 +380,6 @@ create_material_matte param->reflectivity = matte->reflectivity; if(!SOLPARSER_ID_IS_VALID(matte->normal_map)) { - param->normal_map = NULL; shader.normal = mtl_get_normal; } else { const struct solparser_image* image; @@ -296,7 +400,7 @@ exit: return res; error: if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; - if(img) SSOL(image_ref_put(img)), img = NULL; + if(img) SSOL(image_ref_put(img)); goto exit; } @@ -306,6 +410,7 @@ create_material_mirror const struct solparser_material_mirror* mirror, struct ssol_material** out_mtl) { + struct ssol_image* img = NULL; struct ssol_mirror_shader shader = SSOL_MIRROR_SHADER_NULL; struct ssol_material* mtl = NULL; struct ssol_param_buffer* pbuf = NULL; @@ -326,17 +431,28 @@ create_material_mirror goto error; } - param = ssol_param_buffer_allocate - (pbuf, sizeof(struct mirror_param), ALIGNOF(struct mirror_param), NULL); + param = ssol_param_buffer_allocate(pbuf, sizeof(struct mirror_param), + ALIGNOF(struct mirror_param), mirror_param_release); if(!param) { fprintf(stderr, "Could not allocate the mirror parameters.\n"); res = RES_MEM_ERR; goto error; } + memset(param, 0, sizeof(struct mirror_param)); param->reflectivity = mirror->reflectivity; param->roughness = mirror->roughness; - shader.normal = mtl_get_normal; + if(!SOLPARSER_ID_IS_VALID(mirror->normal_map)) { + shader.normal = mtl_get_normal; + } else { + const struct solparser_image* image; + image = solparser_get_image(solstice->parser, mirror->normal_map); + res = load_image(solstice, str_cget(&image->filename), &img); + if(res != RES_OK) goto error; + param->normal_map = img; + shader.normal = mirror_get_normal; + } + shader.reflectivity = mirror_get_reflectivity; shader.roughness = mirror_get_roughness; SSOL(mirror_setup(mtl, &shader)); @@ -348,6 +464,7 @@ exit: return res; error: if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; + if(img) SSOL(image_ref_put(img)); goto exit; } @@ -357,12 +474,14 @@ create_material_thin_dielectric const struct solparser_material_thin_dielectric* thin, struct ssol_material** out_mtl) { + struct ssol_image* img = NULL; struct ssol_thin_dielectric_shader shader = SSOL_THIN_DIELECTRIC_SHADER_NULL; const struct solparser_medium* medium_i; const struct solparser_medium* medium_t; struct ssol_medium ssol_medium_i; struct ssol_medium ssol_medium_t; struct ssol_material* mtl = NULL; + struct ssol_param_buffer* pbuf = NULL; res_T res = RES_OK; ASSERT(solstice && thin && out_mtl); @@ -373,9 +492,40 @@ create_material_thin_dielectric goto error; } - shader.normal = mtl_get_normal; medium_i = solparser_get_medium(solstice->parser, thin->medium_i); medium_t = solparser_get_medium(solstice->parser, thin->medium_t); + + if(!SOLPARSER_ID_IS_VALID(thin->normal_map)) { + shader.normal = mtl_get_normal; + } else { + const struct solparser_image* image; + struct dielectric_param* param = NULL; + + image = solparser_get_image(solstice->parser, thin->normal_map); + res = load_image(solstice, str_cget(&image->filename), &img); + if(res != RES_OK) goto error; + + res = ssol_param_buffer_create + (solstice->ssol, sizeof(struct thin_dielectric_param), &pbuf); + if(res != RES_OK) { + fprintf(stderr, "Could not create the Solsitce Solver parameter buffer.\n"); + goto error; + } + + param = ssol_param_buffer_allocate(pbuf, + sizeof(struct thin_dielectric_param), + ALIGNOF(struct thin_dielectric_param), + thin_dielectric_param_release); + if(!param) { + fprintf(stderr, "Could not allocate the thin dielectric parameter.\n"); + res = RES_MEM_ERR; + goto error; + } + param->normal_map = img; + shader.normal = thin_dielectric_get_normal; + SSOL(material_set_param_buffer(mtl, pbuf)); + } + ssol_medium_i.refractive_index = medium_i->refractive_index; ssol_medium_t.refractive_index = medium_t->refractive_index; ssol_medium_i.absorptivity = medium_i->absorptivity; @@ -384,10 +534,12 @@ create_material_thin_dielectric (mtl, &shader, &ssol_medium_i, &ssol_medium_t, thin->thickness)); exit: + if(pbuf) SSOL(param_buffer_ref_put(pbuf)); *out_mtl = mtl; return res; error: if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; + if(img) SSOL(image_ref_put(img)); goto exit; }