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 1595ac1b3ceebfa9f82c2afed6774b7e70f8580c
parent 76ee9602ac9bd4a80d119c629372c05cc869a72f
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue,  4 Apr 2017 11:40:14 +0200

Partially handle the normal map in the matte material

Diffstat:
Msrc/solstice_material.c | 123++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 119 insertions(+), 4 deletions(-)

diff --git a/src/solstice_material.c b/src/solstice_material.c @@ -16,10 +16,12 @@ #include "solstice.h" #include "solstice_c.h" +#include <rsys/image.h> #include <solstice/ssol.h> struct matte_param { double reflectivity; + struct ssol_image* normal_map; }; struct mirror_param { @@ -66,6 +68,28 @@ matte_get_reflectivity } static void +matte_get_normal + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const double P[3], + const double Ng[3], + const double Ns[3], + const double uv[2], + const double w[3], + double* val) +{ + double N[3]; + const struct matte_param* param = ssol_param_buffer_get(buf); + (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; + SSOL(image_sample(param->normal_map, SSOL_FILTER_LINEAR, + SSOL_ADDRESS_CLAMP, SSOL_ADDRESS_CLAMP, uv, N)); + + /* TODO Transform in world space */ + d3_set(val, N); +} + +static void mirror_get_reflectivity (struct ssol_device* dev, struct ssol_param_buffer* buf, @@ -99,6 +123,83 @@ mirror_get_roughness *val = param->roughness; } +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 res_T +load_image + (struct solstice* solstice, + const char* filename, + struct ssol_image** out_ssol_img) +{ + struct ssol_image* ssol_img = NULL; + struct ssol_image_layout layout; + struct image img; + char* mem; + size_t x, y; + res_T res = RES_OK; + ASSERT(solstice && filename && out_ssol_img); + + image_init(solstice->allocator, &img); + + res = image_read_ppm(&img, filename); + if(res != RES_OK) { + fprintf(stderr, "Could not load the PPM image `%s'.\n", filename); + goto error; + } + + res = ssol_image_create(solstice->ssol, &ssol_img); + if(res != RES_OK) { + fprintf(stderr, "Could not create the Solstice Solver image.\n"); + goto error; + } + + res = ssol_image_setup(ssol_img, img.width, img.height, SSOL_PIXEL_DOUBLE3); + if(res != RES_OK) { + fprintf(stderr, "Could not setup the Solstice Solver image.\n"); + goto error; + } + + SSOL(image_get_layout(ssol_img, &layout)); + SSOL(image_map(ssol_img, &mem)); + + FOR_EACH(y, 0, layout.height) { + char* dst_row = mem + layout.offset + y * layout.row_pitch; + const char* src_row = img.pixels + y * img.pitch; + + FOR_EACH(x, 0, layout.width) { + char* dst = dst_row + x*ssol_sizeof_pixel_format(layout.pixel_format); + const char* src = src_row + x*sizeof_image_format(img.format); + switch(img.format) { + case IMAGE_RGB8: + ((double*)dst)[0] = ((double)((uint8_t*)src)[0] + 0.5) / UINT8_MAX; + ((double*)dst)[1] = ((double)((uint8_t*)src)[1] + 0.5) / UINT8_MAX; + ((double*)dst)[2] = ((double)((uint8_t*)src)[2] + 0.5) / UINT8_MAX; + break; + case IMAGE_RGB16: + ((double*)dst)[0] = ((double)((uint16_t*)src)[0] + 0.5) / UINT16_MAX; + ((double*)dst)[1] = ((double)((uint16_t*)src)[1] + 0.5) / UINT16_MAX; + ((double*)dst)[2] = ((double)((uint16_t*)src)[2] + 0.5) / UINT16_MAX; + break; + default: FATAL("Unreachable code.\n"); break; + } + } + } + +exit: + image_release(&img); + *out_ssol_img = ssol_img; + return res; +error: + if(ssol_img) SSOL(image_ref_put(ssol_img)); + goto exit; +} + static res_T create_material_dielectric (struct solstice* solstice, @@ -145,6 +246,7 @@ create_material_matte struct ssol_material** out_mtl) { struct ssol_matte_shader shader = SSOL_MATTE_SHADER_NULL; + struct ssol_image* img = NULL; struct ssol_material* mtl = NULL; struct ssol_param_buffer* pbuf = NULL; struct matte_param* param; @@ -164,16 +266,28 @@ create_material_matte goto error; } - param = ssol_param_buffer_allocate - (pbuf, sizeof(struct matte_param), ALIGNOF(struct matte_param)); + param = ssol_param_buffer_allocate(pbuf, sizeof(struct matte_param), + ALIGNOF(struct matte_param), matte_param_release); if(!param) { fprintf(stderr, "Could not allocate the matte parameter.\n"); res = RES_MEM_ERR; goto error; } + memset(param, 0, sizeof(struct matte_param)); + 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; + image = solparser_get_image(solstice->parser, matte->normal_map); + res = load_image(solstice, str_cget(&image->filename), &img); + if(res != RES_OK) goto error; + param->normal_map = img; + shader.normal = matte_get_normal; + } - shader.normal = mtl_get_normal; shader.reflectivity = matte_get_reflectivity; SSOL(matte_setup(mtl, &shader)); SSOL(material_set_param_buffer(mtl, pbuf)); @@ -184,6 +298,7 @@ exit: return res; error: if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; + if(img) SSOL(image_ref_put(img)), img = NULL; goto exit; } @@ -214,7 +329,7 @@ create_material_mirror } param = ssol_param_buffer_allocate - (pbuf, sizeof(struct mirror_param), ALIGNOF(struct mirror_param)); + (pbuf, sizeof(struct mirror_param), ALIGNOF(struct mirror_param), NULL); if(!param) { fprintf(stderr, "Could not allocate the mirror parameters.\n"); res = RES_MEM_ERR;