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 5ac5ef5f26fad0e5ecd9784f351b23f37d9a2fe8
parent 703e7105ddc3590b68d4848496edab1ec380ebd4
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 21 Apr 2017 12:10:26 +0200

Merge remote-tracking branch 'origin/develop' into feature_new_shapes

Diffstat:
Mcmake/parser/CMakeLists.txt | 7++++++-
Mdoc/input | 33+++++++++++++++++++++++----------
Msrc/parser/solparser.c | 53++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/parser/solparser.h | 44+++++++++++++++++++++++++++++---------------
Msrc/parser/solparser_c.h | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Asrc/parser/solparser_image.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/parser/solparser_image.h | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/solparser_material.c | 137++++++++++++++++++-------------------------------------------------------------
Msrc/parser/solparser_material.h | 53++++++++++++++++++++++++++++++++++++++++++++++-------
Asrc/parser/solparser_medium.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/parser/solparser_medium.h | 29+++++++++++++++++++++++++++++
Msrc/parser/solparser_spectrum.c | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/parser/solparser_spectrum.h | 39+++++++++++++++++++++++++++++++++++++++
Msrc/parser/solparser_sun.h | 25++++++-------------------
Msrc/parser/test_solparser2.c | 11+++++++----
Msrc/parser/test_solparser8.c | 16+++++++---------
Asrc/parser/test_solparser_normal_map.c | 335+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/parser/test_solparser_spectrum.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/yaml/test_ko_0.yaml | 21++++++++++++++++++++-
Msrc/parser/yaml/test_ok_0.yaml | 7++++++-
Msrc/parser/yaml/test_ok_2.yaml | 13+++++++++++++
Msrc/parser/yaml/test_ok_7.yaml | 13+++++++++++++
Msrc/solstice_draw.c | 43++++++++++++++++++++++++++-----------------
Msrc/solstice_material.c | 335++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/solstice_object.c | 18++++++++++++++++--
Msrc/solstice_solve.c | 26+++++++++++---------------
Msrc/solstice_sun.c | 8+++++---
Msrc/test_solstice_simulation.c | 4++--
28 files changed, 1534 insertions(+), 291 deletions(-)

diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt @@ -32,8 +32,10 @@ include_directories( set(SOLPARSER_FILES_SRC solparser.c solparser_entity.c + solparser_image.c solparser_geometry.c solparser_material.c + solparser_medium.c solparser_pivot.c solparser_sun.c solparser_spectrum.c) @@ -42,7 +44,9 @@ set(SOLPARSER_FILES_INC solparser_c.h solparser_entity.h solparser_geometry.h + solparser_image.h solparser_material.h + solparser_medium.h solparser_pivot.h solparser_shape.h solparser_sun.h @@ -103,8 +107,9 @@ if(NOT NO_TEST) new_test(test_solparser6) new_test(test_solparser7) new_test(test_solparser8) + new_test(test_solparser_normal_map) + new_test(test_solparser_spectrum) rcmake_copy_runtime_libraries(test_solparser) endif() - diff --git a/doc/input b/doc/input @@ -89,9 +89,11 @@ [ - <item> ... ] <item> ::= - <geometry> + <entity> + | <geometry> | <material> - | <entity> + | <medium> + | <spectrum> | <template> #---------------------------------------- @@ -224,7 +226,7 @@ #---------------------------------------- <material> ::= - <material-descriptor> | <double-sided-material> + material: <material-descriptor> | <double-sided-material> <double-sided-material> ::= front: <material-descriptor> @@ -235,17 +237,20 @@ <dielectric> ::= dielectric: - medium_i: <dielectric-medium> - medium_t: <dielectric-medium> + medium_i: <medium-descriptor> + medium_t: <medium-descriptor> +[ <normal-map> ] <matte> ::= matte: reflectivity: REAL # in [0, 1] +[ <normal-map> ] <mirror> ::= mirror: reflectivity: REAL # in [0, 1] roughness: REAL # in [0, 1] +[ <normal-map> ] <virtual> ::= virtual: EMPTY-STRING @@ -253,12 +258,20 @@ <thin-dielectric> ::= thin_dielectric: thickness: REAL # in [0, INF) - medium_i: <dielectric-medium> - medium_t: <dielectric-medium> + medium_i: <medium-descriptor> + medium_t: <medium-descriptor> +[ <normal-map> ] -<dielectric-medium> ::= - refractive_index: REAL # in ]0, INF) - absorptivity: REAL # in [0, INF) +<normal-map> ::= + normal_map: { path: PATH } + +#---------------------------------------- +<medium> ::= + medium: <medium-descriptor> + +<medium-descriptor> ::= + refractive_index: REAL # in ]0, INF) + absorptivity: REAL # in [0, INF) #---------------------------------------- <entity> ::= diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -114,9 +114,10 @@ parse_item const yaml_node_t* item) { /* Temporary dummy variables */ - struct solparser_material_double_sided_id mtl2; struct solparser_entity_id entity; struct solparser_geometry_id geometry; + struct solparser_material_double_sided_id mtl2; + struct solparser_medium_id medium; struct solparser_sun* sun; yaml_node_t* key; @@ -147,21 +148,22 @@ parse_item goto error; } + /* The parsing of the templates/spectraa is deferred to their explicit use */ if(!strcmp((char*)key->data.scalar.value, "material")) { res = parse_material(parser, doc, val, &mtl2); + } else if(!strcmp((char*)key->data.scalar.value, "medium")) { + res = parse_medium(parser, doc, val, &medium); } else if(!strcmp((char*)key->data.scalar.value, "entity")) { res = parse_entity(parser, doc, val, &parser->str2entities, &entity); if(res == RES_OK) { res = flush_deferred_target_aliases(parser, item, entity); } - } else if(!strcmp((char*)key->data.scalar.value, "template")) { - /* The parsing of the template data is deferred to its explicit used in the - * definition of an entity. If the parsing of the template becomes a - * bottleneck, parse the data only once here and cache them for reuse. */ + } else if(!strcmp((char*)key->data.scalar.value, "template")) { /* Deferred */ } else if(!strcmp((char*)key->data.scalar.value, "geometry")) { res = parse_geometry(parser, doc, val, &geometry); } else if(!strcmp((char*)key->data.scalar.value, "sun")) { res = parse_sun(parser, doc, val, &sun); + } else if(!strcmp((char*)key->data.scalar.value, "spectrum")) { /* Deferred */ } else { log_err(parser, key, "unknown item `%s'.\n", key->data.scalar.value); res = RES_BAD_ARG; @@ -186,14 +188,18 @@ parser_clear(struct solparser* parser) /* Materials */ htable_yaml2sols_clear(&parser->yaml2mtls); + darray_image_clear(&parser->images); darray_material_clear(&parser->mtls); darray_material2_clear(&parser->mtls2); - darray_medium_clear(&parser->mediums); darray_dielectric_clear(&parser->dielectrics); darray_matte_clear(&parser->mattes); darray_mirror_clear(&parser->mirrors); darray_thin_dielectric_clear(&parser->thin_dielectrics); + /* Mediums */ + htable_yaml2sols_clear(&parser->yaml2mediums); + darray_medium_clear(&parser->mediums); + /* Deferred targeted anchors */ darray_tgtalias_clear(&parser->tgtaliases); @@ -227,6 +233,7 @@ parser_clear(struct solparser* parser) darray_anchor_clear(&parser->anchors); darray_x_pivot_clear(&parser->x_pivots); darray_zx_pivot_clear(&parser->zx_pivots); + darray_spectrum_clear(&parser->spectra); } static void @@ -241,14 +248,18 @@ parser_release(ref_T* ref) /* Materials */ htable_yaml2sols_release(&parser->yaml2mtls); + darray_image_release(&parser->images); darray_material_release(&parser->mtls); darray_material2_release(&parser->mtls2); - darray_medium_release(&parser->mediums); darray_dielectric_release(&parser->dielectrics); darray_matte_release(&parser->mattes); darray_mirror_release(&parser->mirrors); darray_thin_dielectric_release(&parser->thin_dielectrics); + /* Mediums */ + htable_yaml2sols_release(&parser->yaml2mediums); + darray_medium_release(&parser->mediums); + /* Deferred targeted anchors */ darray_tgtalias_release(&parser->tgtaliases); @@ -281,6 +292,7 @@ parser_release(ref_T* ref) darray_anchor_release(&parser->anchors); darray_x_pivot_release(&parser->x_pivots); darray_zx_pivot_release(&parser->zx_pivots); + darray_spectrum_release(&parser->spectra); MEM_RM(parser->allocator, parser); } @@ -570,14 +582,18 @@ solparser_create /* Materials */ htable_yaml2sols_init(mem_allocator, &parser->yaml2mtls); + darray_image_init(mem_allocator, &parser->images); darray_material_init(mem_allocator, &parser->mtls); darray_material2_init(mem_allocator, &parser->mtls2); - darray_medium_init(mem_allocator, &parser->mediums); darray_dielectric_init(mem_allocator, &parser->dielectrics); darray_matte_init(mem_allocator, &parser->mattes); darray_mirror_init(mem_allocator, &parser->mirrors); darray_thin_dielectric_init(mem_allocator, &parser->thin_dielectrics); + /* Mediums */ + htable_yaml2sols_init(mem_allocator, &parser->yaml2mediums); + darray_medium_init(mem_allocator, &parser->mediums); + /* Deferred targeted anchors */ darray_tgtalias_init(mem_allocator, &parser->tgtaliases); @@ -606,10 +622,11 @@ solparser_create htable_str2sols_init(mem_allocator, &parser->str2entities); darray_entity_init(mem_allocator, &parser->entities); - /* Anchors and pivot(2)s */ + /* Miscellaneous */ darray_anchor_init(mem_allocator, &parser->anchors); darray_x_pivot_init(mem_allocator, &parser->x_pivots); darray_zx_pivot_init(mem_allocator, &parser->zx_pivots); + darray_spectrum_init(mem_allocator, &parser->spectra); exit: *out_parser = parser; @@ -885,6 +902,15 @@ solparser_get_entity return darray_entity_cdata_get(&parser->entities) + entity.i; } +const struct solparser_image* +solparser_get_image + (const struct solparser* parser, + const struct solparser_image_id image) +{ + ASSERT(parser && image.i < darray_image_size_get(&parser->images)); + return darray_image_cdata_get(&parser->images) + image.i; +} + const struct solparser_geometry* solparser_get_geometry (const struct solparser* parser, @@ -1086,6 +1112,15 @@ solparser_get_shape_stl return darray_impgeom_cdata_get(&parser->stls) + impgeom.i; } +const struct solparser_spectrum* +solparser_get_spectrum + (const struct solparser* parser, + const struct solparser_spectrum_id spectrum) +{ + ASSERT(parser && spectrum.i < darray_spectrum_size_get(&parser->spectra)); + return darray_spectrum_cdata_get(&parser->spectra) + spectrum.i; +} + const struct solparser_sun* solparser_get_sun(const struct solparser* parser) { diff --git a/src/parser/solparser.h b/src/parser/solparser.h @@ -17,11 +17,15 @@ #define SOLPARSER_H #include "solparser_entity.h" +#include "solparser_spectrum.h" #include <rsys/rsys.h> +#include <stddef.h> struct mem_allocator; struct solparser; +#define SOLPARSER_ID_IS_VALID(Id) ((Id).i != SIZE_MAX) + struct solparser_entity_iterator { struct htable_str2sols_iterator it__; /* Internal data */ }; @@ -87,16 +91,16 @@ solparser_get_entity (const struct solparser* parser, const struct solparser_entity_id entity); +extern LOCAL_SYM const struct solparser_image* +solparser_get_image + (const struct solparser* parser, + const struct solparser_image_id image); + extern LOCAL_SYM const struct solparser_geometry* solparser_get_geometry (const struct solparser* parser, const struct solparser_geometry_id geom); -extern LOCAL_SYM const struct solparser_medium* -solparser_get_medium - (const struct solparser* parser, - const struct solparser_medium_id medium); - extern LOCAL_SYM const struct solparser_material* solparser_get_material (const struct solparser* parser, @@ -127,21 +131,16 @@ solparser_get_material_thin_dielectric (const struct solparser* parser, const struct solparser_material_thin_dielectric_id thin_dielectric); +extern LOCAL_SYM const struct solparser_medium* +solparser_get_medium + (const struct solparser* parser, + const struct solparser_medium_id medium); + extern LOCAL_SYM const struct solparser_object* solparser_get_object (const struct solparser* parser, const struct solparser_object_id obj); -extern LOCAL_SYM const struct solparser_x_pivot* -solparser_get_x_pivot - (const struct solparser* parser, - const struct solparser_pivot_id x_pivot); - -extern LOCAL_SYM const struct solparser_zx_pivot* -solparser_get_zx_pivot - (const struct solparser* parser, - const struct solparser_pivot_id zx_pivot); - extern LOCAL_SYM const struct solparser_shape* solparser_get_shape (const struct solparser* parser, @@ -201,6 +200,21 @@ extern LOCAL_SYM const struct solparser_sun* solparser_get_sun (const struct solparser* parser); +extern LOCAL_SYM const struct solparser_x_pivot* +solparser_get_x_pivot + (const struct solparser* parser, + const struct solparser_pivot_id x_pivot); + +extern LOCAL_SYM const struct solparser_zx_pivot* +solparser_get_zx_pivot + (const struct solparser* parser, + const struct solparser_pivot_id zx_pivot); + +extern LOCAL_SYM const struct solparser_spectrum* +solparser_get_spectrum + (const struct solparser* parser, + const struct solparser_spectrum_id spectrum); + /******************************************************************************* * Entity interator ******************************************************************************/ diff --git a/src/parser/solparser_c.h b/src/parser/solparser_c.h @@ -18,9 +18,12 @@ #include "solparser.h" #include "solparser_entity.h" +#include "solparser_image.h" #include "solparser_material.h" +#include "solparser_medium.h" #include "solparser_pivot.h" #include "solparser_shape.h" +#include "solparser_spectrum.h" #include "solparser_sun.h" #include <rsys/dynamic_array.h> @@ -48,21 +51,25 @@ struct target_alias { /* Declare the array of dielectric materials */ #define DARRAY_NAME dielectric #define DARRAY_DATA struct solparser_material_dielectric +#define DARRAY_FUNCTOR_INIT solparser_material_dielectric_init #include <rsys/dynamic_array.h> /* Declare the array of matte materials */ #define DARRAY_NAME matte #define DARRAY_DATA struct solparser_material_matte +#define DARRAY_FUNCTOR_INIT solparser_material_matte_init #include <rsys/dynamic_array.h> /* Declare the array of mirror materials */ #define DARRAY_NAME mirror #define DARRAY_DATA struct solparser_material_mirror +#define DARRAY_FUNCTOR_INIT solparser_material_mirror_init #include <rsys/dynamic_array.h> /* Declare the array of thin_dielectric materials */ #define DARRAY_NAME thin_dielectric #define DARRAY_DATA struct solparser_material_thin_dielectric +#define DARRAY_FUNCTOR_INIT solparser_material_thin_dielectric_init #include <rsys/dynamic_array.h> /* Declare the array of materials */ @@ -90,6 +97,15 @@ struct target_alias { #define DARRAY_DATA struct solparser_shape_cylinder #include <rsys/dynamic_array.h> +/* Declare the array of images */ +#define DARRAY_NAME image +#define DARRAY_DATA struct solparser_image +#define DARRAY_FUNCTOR_INIT solparser_image_init +#define DARRAY_FUNCTOR_RELEASE solparser_image_release +#define DARRAY_FUNCTOR_COPY solparser_image_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_image_copy_and_release +#include <rsys/dynamic_array.h> + /* Declare the array of imported geometries */ #define DARRAY_NAME impgeom #define DARRAY_DATA struct solparser_shape_imported_geometry @@ -188,6 +204,15 @@ struct target_alias { #define DARRAY_FUNCTOR_INIT solparser_zx_pivot_init #include <rsys/dynamic_array.h> +/* Declare the array of spectra */ +#define DARRAY_NAME spectrum +#define DARRAY_DATA struct solparser_spectrum +#define DARRAY_FUNCTOR_INIT solparser_spectrum_init +#define DARRAY_FUNCTOR_RELEASE solparser_spectrum_release +#define DARRAY_FUNCTOR_COPY solparser_spectrum_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_spectrum_copy_and_release +#include <rsys/dynamic_array.h> + /* Declare the hash table that maps the address of a YAML node to the id of its * in memory representation. */ #define HTABLE_NAME yaml2sols @@ -200,16 +225,20 @@ struct solparser { struct str stream_name; int parser_is_init; - /* Materia data */ + /* Material */ struct htable_yaml2sols yaml2mtls; /* Cache of materials */ + struct darray_image images; struct darray_material mtls; struct darray_material2 mtls2; /* Double sided materials */ - struct darray_medium mediums; struct darray_dielectric dielectrics; struct darray_matte mattes; struct darray_mirror mirrors; struct darray_thin_dielectric thin_dielectrics; + /* Medium */ + struct htable_yaml2sols yaml2mediums; /* Cache of mediums */ + struct darray_medium mediums; + /* Use to deferred the setup of the anchor targeted by a pivot */ struct darray_tgtalias tgtaliases; @@ -243,6 +272,7 @@ struct solparser { struct darray_anchor anchors; struct darray_x_pivot x_pivots; struct darray_zx_pivot zx_pivots; + struct darray_spectrum spectra; ref_T ref; struct mem_allocator* allocator; @@ -339,13 +369,6 @@ parse_transform * Main parsing functions ******************************************************************************/ extern LOCAL_SYM res_T -parse_material - (struct solparser* parser, - yaml_document_t* doc, - yaml_node_t* mtl, - struct solparser_material_double_sided_id* out_imtl2); - -extern LOCAL_SYM res_T parse_entity (struct solparser* parser, yaml_document_t* doc, @@ -354,6 +377,13 @@ parse_entity struct solparser_entity_id* out_isolent); extern LOCAL_SYM res_T +parse_image + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* image, + struct solparser_image_id* out_img); + +extern LOCAL_SYM res_T parse_focals_description (struct solparser* parser, yaml_document_t* doc, @@ -368,18 +398,25 @@ parse_geometry struct solparser_geometry_id* out_isolgeom); extern LOCAL_SYM res_T -parse_x_pivot +parse_material (struct solparser* parser, yaml_document_t* doc, - const yaml_node_t* x_pivot, - struct solparser_pivot_id* out_isolpivot); + yaml_node_t* mtl, + struct solparser_material_double_sided_id* out_imtl2); extern LOCAL_SYM res_T -parse_zx_pivot +parse_medium (struct solparser* parser, yaml_document_t* doc, - const yaml_node_t* zx_pivot, - struct solparser_pivot_id* out_isolpivot); + yaml_node_t* medium, + struct solparser_medium_id* out_imedium); + +extern LOCAL_SYM res_T +parse_spectrum + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* spectrum, + struct solparser_spectrum_id* out_ispectrum); extern LOCAL_SYM res_T parse_sun @@ -389,10 +426,17 @@ parse_sun struct solparser_sun** out_solsun); extern LOCAL_SYM res_T -parse_spectrum +parse_x_pivot (struct solparser* parser, yaml_document_t* doc, - const yaml_node_t* spectrum, - struct darray_spectrum_data* data); + const yaml_node_t* x_pivot, + struct solparser_pivot_id* out_isolpivot); + +extern LOCAL_SYM res_T +parse_zx_pivot + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* zx_pivot, + struct solparser_pivot_id* out_isolpivot); #endif /* SOLPARSER_C_H */ diff --git a/src/parser/solparser_image.c b/src/parser/solparser_image.c @@ -0,0 +1,107 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "solparser_c.h" + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +parse_image + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* img, + struct solparser_image_id* out_iimg) +{ + enum { PATH }; + struct solparser_image* solimg = NULL; + size_t isolimg = SIZE_MAX; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(parser && doc && img &&out_iimg); + + if(img->type != YAML_MAPPING_NODE) { + log_err(parser, img, "expect a mapping of image parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Allocate an image */ + isolimg = darray_image_size_get(&parser->images); + res = darray_image_resize(&parser->images, isolimg + 1); + if(res != RES_OK) { + log_err(parser, img, "could not allocate the image.\n"); + goto error; + } + solimg = darray_image_data_get(&parser->images) + isolimg; + + n = img->data.mapping.pairs.top - img->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, img->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, img->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect image parameters.\n"); + goto error; + } + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the image parameter `"Name"' is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "path")) { + SETUP_MASK(PATH, "path"); + res = parse_string(parser, val, &solimg->filename); + } else { + log_err(parser, key, "unknown image parameter `%s'.\n", + key->data.scalar.value); + res = RES_BAD_ARG; + goto error; + } + if(res != RES_OK) { + log_node(parser, key); + goto error; + } + #undef SETUP_MASK + } + + #define CHECK_PARAM(Flag, Name) \ + if(!(mask & BIT(Flag))) { \ + log_err(parser, img, \ + "the image parameter `"Name"' is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(PATH, "path"); + #undef CHECK_PARAM + +exit: + out_iimg->i = isolimg; + return res; +error: + if(solimg) { + darray_image_pop_back(&parser->images); + isolimg = SIZE_MAX; + } + goto exit; +} + diff --git a/src/parser/solparser_image.h b/src/parser/solparser_image.h @@ -0,0 +1,62 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SOLPARSER_IMAGE_H +#define SOLPARSER_IMAGE_H + +#include <rsys/str.h> + +struct solparser_image { + struct str filename; +}; + +struct solparser_image_id { size_t i; }; + +static INLINE void +solparser_image_init + (struct mem_allocator* allocator, + struct solparser_image* img) +{ + ASSERT(img); + str_init(allocator, &img->filename); +} + +static INLINE void +solparser_image_release(struct solparser_image* img) +{ + ASSERT(img); + str_release(&img->filename); +} + +static INLINE res_T +solparser_image_copy + (struct solparser_image* dst, + const struct solparser_image* src) +{ + ASSERT(dst && src); + return str_copy(&dst->filename, &src->filename); +} + +static INLINE res_T +solparser_image_copy_and_release + (struct solparser_image* dst, + struct solparser_image* src) +{ + ASSERT(dst && src); + return str_copy_and_release(&dst->filename, &src->filename); +} + +#endif /* SOLPARSER_IMAGE_H */ + diff --git a/src/parser/solparser_material.c b/src/parser/solparser_material.c @@ -22,105 +22,13 @@ * Helper functions ******************************************************************************/ static res_T -parse_medium - (struct solparser* parser, - yaml_document_t* doc, - const yaml_node_t* medium, - struct solparser_medium_id* out_imedium) -{ - enum { ABSORPTIVITY, REFRACTIVE_INDEX }; - struct solparser_medium* mdm = NULL; - size_t imedium = SIZE_MAX; - int mask = 0; /* Register the parsed attributes */ - intptr_t i, n; - res_T res = RES_OK; - ASSERT(doc && medium && out_imedium); - - if(medium->type != YAML_MAPPING_NODE) { - log_err(parser, medium, "expect a mapping of medium attributes.\n"); - res = RES_BAD_ARG; - goto error; - } - - /* Allocate the medium */ - imedium = darray_medium_size_get(&parser->mediums); - res = darray_medium_resize(&parser->mediums, imedium + 1); - if(res != RES_OK) { - log_err(parser, medium, "could not allocate the medium.\n"); - res = RES_BAD_ARG; - goto error; - } - mdm = darray_medium_data_get(&parser->mediums) + imedium; - - n = medium->data.mapping.pairs.top - medium->data.mapping.pairs.start; - FOR_EACH(i, 0, n) { - yaml_node_t* key; - yaml_node_t* val; - - key = yaml_document_get_node(doc, medium->data.mapping.pairs.start[i].key); - val = yaml_document_get_node(doc, medium->data.mapping.pairs.start[i].value); - if(key->type != YAML_SCALAR_NODE) { - log_err(parser, key, "expect a medium parameter.\n"); - res = RES_BAD_ARG; - goto error; - } - #define SETUP_MASK(Flag, Name) { \ - if(mask & BIT(Flag)) { \ - log_err(parser, key,"the "Name" of the medium is already defined.\n");\ - res = RES_BAD_ARG; \ - goto error; \ - } \ - mask |= BIT(Flag); \ - } (void)0 - if(!strcmp((char*)key->data.scalar.value, "absorptivity")) { - SETUP_MASK(ABSORPTIVITY, "absorptivity"); - res = parse_real(parser, val, 0, DBL_MAX, &mdm->absorptivity); - } else if(!strcmp((char*)key->data.scalar.value, "refractive_index")) { - SETUP_MASK(REFRACTIVE_INDEX, "refractive_index"); - res = parse_real - (parser, val, nextafter(0, 1), DBL_MAX, &mdm->refractive_index); - } else { - log_err(parser, key, "unknown medium parameter `%s'.\n", - key->data.scalar.value); - res = RES_BAD_ARG; - goto error; - } - if(res != RES_OK) { - log_node(parser, key); - goto error; - } - #undef SETUP_MASK - } - - #define CHECK_PARAM(Flag, Name) \ - if(!(mask & BIT(Flag))) { \ - log_err(parser, medium, "the "Name" of the medium is missing.\n"); \ - res = RES_BAD_ARG; \ - goto error; \ - } (void)0 - CHECK_PARAM(ABSORPTIVITY, "absorptivity"); - CHECK_PARAM(REFRACTIVE_INDEX, "refractive_index"); - #undef CHECK_PARAM - -exit: - out_imedium->i = imedium; - return res; -error: - if(imedium) { - darray_medium_pop_back(&parser->mediums); - imedium = SIZE_MAX; - } - goto exit; -} - -static res_T parse_material_dielectric (struct solparser* parser, yaml_document_t* doc, const yaml_node_t* dielec, struct solparser_material_dielectric_id* out_imtl) { - enum { MEDIUM_I, MEDIUM_T }; + enum { MEDIUM_I, MEDIUM_T, NORMAL_MAP }; struct solparser_material_dielectric* mtl = NULL; size_t imtl = SIZE_MAX; int mask = 0; /* Register the parsed attributes */ @@ -166,7 +74,10 @@ parse_material_dielectric } \ mask |= BIT(Flag); \ } (void)0 - if(!strcmp((char*)key->data.scalar.value, "medium_i")) { + if(!strcmp((char*)key->data.scalar.value, "normal_map")) { + SETUP_MASK(NORMAL_MAP, "normal_map"); + res = parse_image(parser, doc, val, &mtl->normal_map); + } else if(!strcmp((char*)key->data.scalar.value, "medium_i")) { SETUP_MASK(MEDIUM_I, "medium_i"); res = parse_medium(parser, doc, val, &mtl->medium_i); } else if(!strcmp((char*)key->data.scalar.value, "medium_t")) { @@ -214,7 +125,7 @@ parse_material_matte const yaml_node_t* matte, struct solparser_material_matte_id* out_imtl) { - enum { REFLECTIVITY }; + enum { NORMAL_MAP, REFLECTIVITY }; struct solparser_material_matte* mtl = NULL; size_t imtl = SIZE_MAX; intptr_t i, n; @@ -250,13 +161,20 @@ parse_material_matte goto error; } - if(!strcmp((char*)key->data.scalar.value, "reflectivity")) { - if(mask & BIT(REFLECTIVITY)) { - log_err(parser, key, "the matte reflectivity is already defined.\n"); - res = RES_BAD_ARG; - goto error; - } - mask |= BIT(REFLECTIVITY); + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the "Name" of the matte material is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "normal_map")) { + SETUP_MASK(NORMAL_MAP, "normal_map"); + res = parse_image(parser, doc, val, &mtl->normal_map); + } else if(!strcmp((char*)key->data.scalar.value, "reflectivity")) { + SETUP_MASK(REFLECTIVITY, "reflectivity"); res = parse_real(parser, val, 0, 1, &mtl->reflectivity); } else { log_err(parser, key, "unknown matte parameter `%s'.\n", @@ -268,6 +186,7 @@ parse_material_matte log_node(parser, key); goto error; } + #undef SETUP_MASK } if(!(mask & BIT(REFLECTIVITY))) { @@ -294,7 +213,7 @@ parse_material_mirror const yaml_node_t* mirror, struct solparser_material_mirror_id* out_imtl) { - enum { REFLECTIVITY, ROUGHNESS }; + enum { NORMAL_MAP, REFLECTIVITY, ROUGHNESS }; struct solparser_material_mirror* mtl = NULL; size_t imtl = SIZE_MAX; int mask = 0; /* Register the parsed attributes */ @@ -340,7 +259,10 @@ parse_material_mirror } \ mask |= BIT(Flag); \ } (void)0 - if(!strcmp((char*)key->data.scalar.value, "reflectivity")) { + if(!strcmp((char*)key->data.scalar.value, "normal_map")) { + SETUP_MASK(NORMAL_MAP, "normal_map"); + res = parse_image(parser, doc, val, &mtl->normal_map); + } else if(!strcmp((char*)key->data.scalar.value, "reflectivity")) { SETUP_MASK(REFLECTIVITY, "reflectivity"); res = parse_real(parser, val, 0, 1, &mtl->reflectivity); } else if(!strcmp((char*)key->data.scalar.value, "roughness")) { @@ -387,7 +309,7 @@ parse_material_thin_dielectric yaml_node_t* thin, struct solparser_material_thin_dielectric_id* out_imtl) { - enum { MEDIUM_I, MEDIUM_T, THICKNESS }; + enum { MEDIUM_I, MEDIUM_T, NORMAL_MAP, THICKNESS }; struct solparser_material_thin_dielectric* mtl = NULL; size_t imtl = SIZE_MAX; int mask = 0; /* Register the parsed attributes */ @@ -434,7 +356,10 @@ parse_material_thin_dielectric } \ mask |= BIT(Flag); \ } (void)0 - if(!strcmp((char*)key->data.scalar.value, "medium_i")) { + if(!strcmp((char*)key->data.scalar.value, "normal_map")) { + SETUP_MASK(NORMAL_MAP, "normal_map"); + res = parse_image(parser, doc, val, &mtl->normal_map); + } else if(!strcmp((char*)key->data.scalar.value, "medium_i")) { SETUP_MASK(MEDIUM_I, "medium_i"); res = parse_medium(parser, doc, val, &mtl->medium_i); } else if(!strcmp((char*)key->data.scalar.value, "medium_t")) { diff --git a/src/parser/solparser_material.h b/src/parser/solparser_material.h @@ -16,6 +16,8 @@ #ifndef SOLPARSER_MATERIAL_H #define SOLPARSER_MATERIAL_H +#include "solparser_image.h" +#include "solparser_medium.h" #include <stddef.h> enum solparser_material_type { @@ -26,41 +28,78 @@ enum solparser_material_type { SOLPARSER_MATERIAL_VIRTUAL }; -struct solparser_medium { - double refractive_index; - double absorptivity; -}; - -struct solparser_medium_id { size_t i; }; - struct solparser_material_dielectric { struct solparser_medium_id medium_i; /* Medium the material "looks at" */ struct solparser_medium_id medium_t; /* Opposite medium */ + struct solparser_image_id normal_map; }; struct solparser_material_dielectric_id { size_t i; }; +static INLINE void +solparser_material_dielectric_init + (struct mem_allocator* allocator, + struct solparser_material_dielectric* dielectric) +{ + ASSERT(dielectric); + (void)allocator; + dielectric->normal_map.i = SIZE_MAX; +} + struct solparser_material_matte { double reflectivity; /* In [0, 1] */ + struct solparser_image_id normal_map; }; struct solparser_material_matte_id { size_t i; }; +static INLINE void +solparser_material_matte_init + (struct mem_allocator* allocator, + struct solparser_material_matte* matte) +{ + ASSERT(matte); + (void)allocator; + matte->normal_map.i = SIZE_MAX; +} + struct solparser_material_mirror { double roughness; /* In [0, 1] */ double reflectivity; /* In [0, 1] */ + struct solparser_image_id normal_map; }; struct solparser_material_mirror_id { size_t i; }; +static INLINE void +solparser_material_mirror_init + (struct mem_allocator* allocator, + struct solparser_material_mirror* mirror) +{ + ASSERT(mirror); + (void)allocator; + mirror->normal_map.i = SIZE_MAX; +} + struct solparser_material_thin_dielectric { struct solparser_medium_id medium_i; /* Outside medium */ struct solparser_medium_id medium_t; /* Medium of the slab */ + struct solparser_image_id normal_map; double thickness; }; struct solparser_material_thin_dielectric_id { size_t i; }; +static INLINE void +solparser_material_thin_dielectric_init + (struct mem_allocator* allocator, + struct solparser_material_thin_dielectric* thin) +{ + ASSERT(thin); + (void)allocator; + thin->normal_map.i = SIZE_MAX; +} + struct solparser_material { enum solparser_material_type type; union { diff --git a/src/parser/solparser_medium.c b/src/parser/solparser_medium.c @@ -0,0 +1,131 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#define _POSIX_C_SOURCE 200112L /* nextafter support */ + +#include "solparser_c.h" +#include <math.h> /* nextafter */ + +/******************************************************************************* + * Local function + ******************************************************************************/ +res_T +parse_medium + (struct solparser* parser, + yaml_document_t* doc, + yaml_node_t* medium, + struct solparser_medium_id* out_imedium) +{ + enum { ABSORPTIVITY, REFRACTIVE_INDEX }; + struct solparser_medium* mdm = NULL; + size_t* pimedium = NULL; + size_t imedium = SIZE_MAX; + int mask = 0; /* Register the parsed attributes */ + intptr_t i, n; + res_T res = RES_OK; + ASSERT(doc && medium && out_imedium); + + if(medium->type != YAML_MAPPING_NODE) { + log_err(parser, medium, "expect a mapping of medium attributes.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Check whether or not the YAML medium alias an already created Solstice + * medium */ + pimedium = htable_yaml2sols_find(&parser->yaml2mediums, &medium); + if(pimedium) { + imedium = *pimedium; + goto exit; + } + + /* Allocate the medium */ + imedium = darray_medium_size_get(&parser->mediums); + res = darray_medium_resize(&parser->mediums, imedium + 1); + if(res != RES_OK) { + log_err(parser, medium, "could not allocate the medium.\n"); + res = RES_BAD_ARG; + goto error; + } + mdm = darray_medium_data_get(&parser->mediums) + imedium; + + n = medium->data.mapping.pairs.top - medium->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, medium->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, medium->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect a medium parameter.\n"); + res = RES_BAD_ARG; + goto error; + } + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key,"the "Name" of the medium is already defined.\n");\ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "absorptivity")) { + SETUP_MASK(ABSORPTIVITY, "absorptivity"); + res = parse_real(parser, val, 0, DBL_MAX, &mdm->absorptivity); + } else if(!strcmp((char*)key->data.scalar.value, "refractive_index")) { + SETUP_MASK(REFRACTIVE_INDEX, "refractive_index"); + res = parse_real + (parser, val, nextafter(0, 1), DBL_MAX, &mdm->refractive_index); + } else { + log_err(parser, key, "unknown medium parameter `%s'.\n", + key->data.scalar.value); + res = RES_BAD_ARG; + goto error; + } + if(res != RES_OK) { + log_node(parser, key); + goto error; + } + #undef SETUP_MASK + } + + #define CHECK_PARAM(Flag, Name) \ + if(!(mask & BIT(Flag))) { \ + log_err(parser, medium, "the "Name" of the medium is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(ABSORPTIVITY, "absorptivity"); + CHECK_PARAM(REFRACTIVE_INDEX, "refractive_index"); + #undef CHECK_PARAM + + /* Cache the medium */ + res = htable_yaml2sols_set(&parser->yaml2mediums, &medium, &imedium); + if(res != RES_OK) { + log_err(parser, medium, "could not register the medium.\n"); + goto error; + } + +exit: + out_imedium->i = imedium; + return res; +error: + if(imedium) { + darray_medium_pop_back(&parser->mediums); + imedium = SIZE_MAX; + } + goto exit; +} + diff --git a/src/parser/solparser_medium.h b/src/parser/solparser_medium.h @@ -0,0 +1,29 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SOLPARSER_MEDIUM_H +#define SOLPARSER_MEDIUM_H + +#include <stddef.h> + +struct solparser_medium { + double refractive_index; + double absorptivity; +}; + +struct solparser_medium_id { size_t i; }; + +#endif /* SOLPARSER_MEDIUM_H */ + diff --git a/src/parser/solparser_spectrum.c b/src/parser/solparser_spectrum.c @@ -13,17 +13,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_C_SOURCE 200112L /* nextafter support */ + #include "solparser_c.h" /******************************************************************************* * Helper functions ******************************************************************************/ +static int +cmp_spectrum_data(const void* op0, const void* op1) +{ + const struct solparser_spectrum_data* a = op0; + const struct solparser_spectrum_data* b = op1; + ASSERT(a && b); + if(a->wavelength < b->wavelength) return -1; + if(a->wavelength > b->wavelength) return 1; + return 0; +} + static res_T parse_spectrum_data (struct solparser* parser, yaml_document_t* doc, const yaml_node_t* sdata, - double* last_wl, struct solparser_spectrum_data* spectrum_data) { enum { DATA, WAVELENGTH }; @@ -65,16 +77,8 @@ parse_spectrum_data res = parse_real(parser, val, 0, DBL_MAX, &spectrum_data->data); } else if(!strcmp((char*)key->data.scalar.value, "wavelength")) { SETUP_MASK(WAVELENGTH, "wavelength"); - res = parse_real(parser, val, nextafter(*last_wl, DBL_MAX), DBL_MAX, + res = parse_real(parser, val, nextafter(0, DBL_MAX), DBL_MAX, &spectrum_data->wavelength); - if(*last_wl >= spectrum_data->wavelength) { - ASSERT(res != RES_OK); - log_err(parser, key, - "spectrum with non-increasing wavelengths (%g after %g).\n", - spectrum_data->wavelength, - *last_wl); - } - *last_wl = spectrum_data->wavelength; } else { log_err(parser, key, "unknown spectrum data parameter `%s'.\n", key->data.scalar.value); @@ -112,12 +116,13 @@ parse_spectrum (struct solparser* parser, yaml_document_t* doc, const yaml_node_t* spectrum, - struct darray_spectrum_data* data) + struct solparser_spectrum_id* out_ispectrum) { + struct solparser_spectrum* spec; + size_t ispec = SIZE_MAX; intptr_t i, n; res_T res = RES_OK; - double last_wl = 0; - ASSERT(doc && spectrum && data); + ASSERT(doc && spectrum && out_ispectrum); if(spectrum->type != YAML_SEQUENCE_NODE) { log_err(parser, spectrum, "expect a list of spectrum data.\n"); @@ -125,8 +130,17 @@ parse_spectrum goto error; } + /* Allocate the spectrum */ + ispec = darray_spectrum_size_get(&parser->spectra); + res = darray_spectrum_resize(&parser->spectra, ispec + 1); + if(res != RES_OK) { + log_err(parser, spectrum, "could not allocate the spectrum.\n"); + goto error; + } + spec = darray_spectrum_data_get(&parser->spectra) + ispec; + n = spectrum->data.sequence.items.top - spectrum->data.sequence.items.start; - res = darray_spectrum_data_resize(data, (size_t)n); + res = darray_spectrum_data_resize(&spec->data, (size_t)n); if(res != RES_OK) { log_err(parser, spectrum, "could not allocate the list of spectrum data.\n"); goto error; @@ -137,15 +151,41 @@ parse_spectrum struct solparser_spectrum_data* spectrum_data; sdata = yaml_document_get_node(doc, spectrum->data.sequence.items.start[i]); - spectrum_data = darray_spectrum_data_data_get(data) + i; - res = parse_spectrum_data(parser, doc, sdata, &last_wl, spectrum_data); + spectrum_data = darray_spectrum_data_data_get(&spec->data) + i; + res = parse_spectrum_data(parser, doc, sdata, spectrum_data); if(res != RES_OK) goto error; } + if(n == 1) goto exit; + + qsort + (darray_spectrum_data_data_get(&spec->data), + darray_spectrum_data_size_get(&spec->data), + sizeof(struct solparser_spectrum_data), + cmp_spectrum_data); + + FOR_EACH(i, 1, n) { + const struct solparser_spectrum_data* a; + const struct solparser_spectrum_data* b; + a = darray_spectrum_data_cdata_get(&spec->data) + i - 1; + b = darray_spectrum_data_cdata_get(&spec->data) + i; + ASSERT(cmp_spectrum_data(a, b) <= 0); + if(a->wavelength == b->wavelength) { + log_err(parser, spectrum, + "duplicated spectrum entry for the wavelength %g\n", a->wavelength); + res = RES_BAD_ARG; + goto error; + } + } + exit: + out_ispectrum->i = ispec; return res; error: - darray_spectrum_data_clear(data); + if(spec) { + darray_spectrum_pop_back(&parser->spectra); + ispec = SIZE_MAX; + } goto exit; } diff --git a/src/parser/solparser_spectrum.h b/src/parser/solparser_spectrum.h @@ -27,5 +27,44 @@ struct solparser_spectrum_data { #define DARRAY_DATA struct solparser_spectrum_data #include <rsys/dynamic_array.h> +struct solparser_spectrum { + struct darray_spectrum_data data; +}; + +struct solparser_spectrum_id { size_t i; }; + +static INLINE void +solparser_spectrum_init + (struct mem_allocator* allocator, struct solparser_spectrum* spectrum) +{ + ASSERT(spectrum); + darray_spectrum_data_init(allocator, &spectrum->data); +} + +static INLINE void +solparser_spectrum_release(struct solparser_spectrum* spectrum) +{ + ASSERT(spectrum); + darray_spectrum_data_release(&spectrum->data); +} + +static INLINE res_T +solparser_spectrum_copy + (struct solparser_spectrum* dst, + const struct solparser_spectrum* src) +{ + ASSERT(dst && src); + return darray_spectrum_data_copy(&dst->data, &src->data); +} + +static INLINE res_T +solparser_spectrum_copy_and_release + (struct solparser_spectrum* dst, + struct solparser_spectrum* src) +{ + ASSERT(dst && src); + return darray_spectrum_data_copy_and_release(&dst->data, &src->data); +} + #endif /* SOLPARSER_SPECTRUM_H */ diff --git a/src/parser/solparser_sun.h b/src/parser/solparser_sun.h @@ -30,7 +30,7 @@ struct solparser_sun_pillbox { double aperture; }; struct solparser_sun { double dni; /* In ]0, INF) */ - struct darray_spectrum_data spectrum; + struct solparser_spectrum_id spectrum; enum solparser_sun_radang_distrib_type radang_distrib_type; union { struct solparser_sun_buie buie; @@ -42,38 +42,25 @@ static INLINE void solparser_sun_init(struct mem_allocator* allocator, struct solparser_sun* sun) { ASSERT(sun); + (void)allocator; sun->dni = 1.0; sun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL; - darray_spectrum_data_init(allocator, &sun->spectrum); + sun->spectrum.i = SIZE_MAX; } static INLINE void solparser_sun_release(struct solparser_sun* sun) { ASSERT(sun); - darray_spectrum_data_release(&sun->spectrum); -} - -static INLINE res_T -solparser_sun_copy(struct solparser_sun* dst, const struct solparser_sun* src) -{ - ASSERT(dst && src); - return darray_spectrum_data_copy(&dst->spectrum, &src->spectrum); -} - -static INLINE res_T -solparser_sun_copy_and_release - (struct solparser_sun* dst, struct solparser_sun* src) -{ - ASSERT(dst && src); - return darray_spectrum_data_copy_and_release(&dst->spectrum, &src->spectrum); + (void)sun; + /* Do nothing */ } static INLINE void solparser_sun_clear(struct solparser_sun* sun) { ASSERT(sun); - darray_spectrum_data_clear(&sun->spectrum); + sun->spectrum.i = SIZE_MAX; } #endif /* SOLPARSER_SUN_H */ diff --git a/src/parser/test_solparser2.c b/src/parser/test_solparser2.c @@ -40,6 +40,7 @@ main(int argc, char** argv) const struct solparser_material_mirror* mirror; const struct solparser_shape_sphere* sphere; const struct solparser_sun* sun; + const struct solparser_spectrum* spectrum; size_t nmtls = 0; size_t ngeoms = 0; double tmp[3]; @@ -114,7 +115,7 @@ main(int argc, char** argv) entity_id = solparser_entity_iterator_get(&it); entity = solparser_get_entity(parser, entity_id); - + CHECK(strcmp("lvl 0", str_cget(&entity->name)), 0); CHECK(solparser_entity_get_children_count(entity), 2); CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY); @@ -203,9 +204,11 @@ main(int argc, char** argv) NCHECK(sun, NULL); CHECK(sun->dni, 1.0); CHECK(sun->radang_distrib_type, SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL); - CHECK(darray_spectrum_data_size_get(&sun->spectrum), 1); - CHECK(darray_spectrum_data_cdata_get(&sun->spectrum)[0].wavelength, 1.0); - CHECK(darray_spectrum_data_cdata_get(&sun->spectrum)[0].data, 1.0); + CHECK(SOLPARSER_ID_IS_VALID(sun->spectrum), 1); + spectrum = solparser_get_spectrum(parser, sun->spectrum); + CHECK(darray_spectrum_data_size_get(&spectrum->data), 1); + CHECK(darray_spectrum_data_cdata_get(&spectrum->data)[0].wavelength, 1.0); + CHECK(darray_spectrum_data_cdata_get(&spectrum->data)[0].data, 1.0); CHECK(solparser_load(parser), RES_BAD_OP); solparser_ref_put(parser); diff --git a/src/parser/test_solparser8.c b/src/parser/test_solparser8.c @@ -37,12 +37,14 @@ main(int argc, char** argv) (void)argc, (void)argv; CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); - solparser_create(&allocator, &parser); + CHECK(solparser_create(&allocator, &parser), RES_OK); stream = tmpfile(); NCHECK(stream, NULL); fprintf(stream, "- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1 }] }\n"); + fprintf(stream, "- medium: &vacuum {refractive_index: 1, absorptivity: 0}\n"); + fprintf(stream, "- medium: &glass {refractive_index: 1.5, absorptivity: 20}\n"); fprintf(stream, "- entity:\n"); fprintf(stream, " name: test\n"); fprintf(stream, " primary: 0\n"); @@ -51,16 +53,12 @@ main(int argc, char** argv) fprintf(stream, " material:\n"); fprintf(stream, " front:\n"); fprintf(stream, " dielectric:\n"); - fprintf(stream, " medium_i: &outside\n"); - fprintf(stream, " refractive_index: 1\n"); - fprintf(stream, " absorptivity: 0\n"); - fprintf(stream, " medium_t: &inside\n"); - fprintf(stream, " refractive_index: 1.5\n"); - fprintf(stream, " absorptivity: 20\n"); + fprintf(stream, " medium_i: *vacuum\n"); + fprintf(stream, " medium_t: *glass\n"); fprintf(stream, " back:\n"); fprintf(stream, " dielectric:\n"); - fprintf(stream, " medium_i: *inside\n"); - fprintf(stream, " medium_t: *outside\n"); + fprintf(stream, " medium_i: *glass\n"); + fprintf(stream, " medium_t: *vacuum\n"); rewind(stream); CHECK(solparser_setup(parser, NULL, stream), RES_OK); diff --git a/src/parser/test_solparser_normal_map.c b/src/parser/test_solparser_normal_map.c @@ -0,0 +1,335 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "solparser.h" +#include "test_solstice_utils.h" + +static void +test_dielectric(struct solparser* parser) +{ + struct solparser_entity_iterator it, end; + struct solparser_entity_id entity_id; + struct solparser_object_id obj_id; + const struct solparser_entity* entity; + const struct solparser_image* img; + const struct solparser_geometry* geom; + const struct solparser_material_double_sided* mtl2; + const struct solparser_material* mtl; + const struct solparser_material_dielectric* dielectric; + const struct solparser_object* obj; + const struct solparser_shape* shape; + FILE* stream; + + stream = tmpfile(); + NCHECK(stream, NULL); + + fprintf(stream, "- sun: {dni: 1, spectrum: [{wavelength: 1, data: 1} ]}\n"); + fprintf(stream, "\n"); + fprintf(stream, "- material: &glass\n"); + fprintf(stream, " front:\n"); + fprintf(stream, " dielectric:\n"); + fprintf(stream, " medium_i: &out {refractive_index: 1, absorptivity: 0}\n"); + fprintf(stream, " medium_t: &in {refractive_index: 1.5, absorptivity: 20}\n"); + fprintf(stream, " normal_map: {path: my_normal_map}\n"); + fprintf(stream, " back: {dielectric: {medium_i: *in, medium_t: *out}}\n"); + fprintf(stream, "\n"); + fprintf(stream, "- entity:\n"); + fprintf(stream, " name: foo\n"); + fprintf(stream, " primary: 1\n"); + fprintf(stream, " geometry:\n"); + fprintf(stream, " - cylinder: { radius: 2, height: 2 }\n"); + fprintf(stream, " material: *glass\n"); + rewind(stream); + + CHECK(solparser_setup(parser, NULL, stream), RES_OK); + CHECK(solparser_load(parser), RES_OK); + + solparser_entity_iterator_begin(parser, &it); + solparser_entity_iterator_end(parser, &end); + CHECK(solparser_entity_iterator_eq(&it, &end), 0); + + entity_id = solparser_entity_iterator_get(&it); + entity = solparser_get_entity(parser, entity_id); + + CHECK(strcmp("foo", str_cget(&entity->name)), 0); + CHECK(solparser_entity_get_children_count(entity), 0); + CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY); + CHECK(entity->primary, 1); + geom = solparser_get_geometry(parser, entity->data.geometry); + CHECK(solparser_geometry_get_objects_count(geom), 1); + obj_id = solparser_geometry_get_object(geom, 0); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_CYLINDER); + mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); + NCHECK(mtl2->front.i, mtl2->back.i); + + mtl = solparser_get_material(parser, mtl2->front); + CHECK(mtl->type, SOLPARSER_MATERIAL_DIELECTRIC); + dielectric = solparser_get_material_dielectric(parser, mtl->data.dielectric); + CHECK(SOLPARSER_ID_IS_VALID(dielectric->normal_map), 1); + img = solparser_get_image(parser, dielectric->normal_map); + CHECK(strcmp(str_cget(&img->filename), "my_normal_map"), 0); + + mtl = solparser_get_material(parser, mtl2->back); + CHECK(mtl->type, SOLPARSER_MATERIAL_DIELECTRIC); + dielectric = solparser_get_material_dielectric(parser, mtl->data.dielectric); + CHECK(SOLPARSER_ID_IS_VALID(dielectric->normal_map), 0); + + solparser_entity_iterator_next(&it); + CHECK(solparser_entity_iterator_eq(&it, &end), 1); + + CHECK(solparser_load(parser), RES_BAD_OP); + fclose(stream); +} + +static void +test_matte(struct solparser* parser) +{ + struct solparser_entity_iterator it, end; + struct solparser_entity_id entity_id; + struct solparser_object_id obj_id; + const struct solparser_entity* entity; + const struct solparser_image* img; + const struct solparser_geometry* geom; + const struct solparser_material_double_sided* mtl2; + const struct solparser_material* mtl; + const struct solparser_material_matte* matte; + const struct solparser_object* obj; + const struct solparser_shape* shape; + FILE* stream; + + stream = tmpfile(); + NCHECK(stream, NULL); + + fprintf(stream, "- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1} ] }\n"); + fprintf(stream, "- entity:\n"); + fprintf(stream, " name: test\n"); + fprintf(stream, " primary: 0\n"); + fprintf(stream, " geometry:\n"); + fprintf(stream, " - sphere: { radius: 1 }\n"); + fprintf(stream, " material:\n"); + fprintf(stream, " matte:\n"); + fprintf(stream, " reflectivity: 0.123\n"); + fprintf(stream, " normal_map: { path: \"path to normal map\" }\n"); + rewind(stream); + + CHECK(solparser_setup(parser, NULL, stream), RES_OK); + CHECK(solparser_load(parser), RES_OK); + + solparser_entity_iterator_begin(parser, &it); + solparser_entity_iterator_end(parser, &end); + CHECK(solparser_entity_iterator_eq(&it, &end), 0); + + entity_id = solparser_entity_iterator_get(&it); + entity = solparser_get_entity(parser, entity_id); + + CHECK(strcmp("test", str_cget(&entity->name)), 0); + CHECK(solparser_entity_get_children_count(entity), 0); + CHECK(entity->primary, 0); + CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY); + geom = solparser_get_geometry(parser, entity->data.geometry); + CHECK(solparser_geometry_get_objects_count(geom), 1); + obj_id = solparser_geometry_get_object(geom, 0); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_SPHERE); + mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); + CHECK(mtl2->front.i, mtl2->back.i); + + mtl = solparser_get_material(parser, mtl2->front); + CHECK(mtl->type, SOLPARSER_MATERIAL_MATTE); + matte = solparser_get_material_matte(parser, mtl->data.matte); + CHECK(matte->reflectivity, 0.123); + CHECK(SOLPARSER_ID_IS_VALID(matte->normal_map), 1); + img = solparser_get_image(parser, matte->normal_map); + CHECK(strcmp(str_cget(&img->filename), "path to normal map"), 0); + + solparser_entity_iterator_next(&it); + CHECK(solparser_entity_iterator_eq(&it, &end), 1); + + CHECK(solparser_load(parser), RES_BAD_OP); + fclose(stream); +} + +static void +test_mirror(struct solparser* parser) +{ + struct solparser_entity_iterator it, end; + struct solparser_entity_id entity_id; + struct solparser_object_id obj_id; + const struct solparser_entity* entity; + const struct solparser_image* img; + const struct solparser_geometry* geom; + const struct solparser_material_double_sided* mtl2; + const struct solparser_material* mtl; + const struct solparser_material_mirror* mirror; + const struct solparser_object* obj; + const struct solparser_shape* shape; + FILE* stream; + + stream = tmpfile(); + NCHECK(stream, NULL); + + fprintf(stream, "- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1} ] }\n"); + fprintf(stream, "- entity: \n"); + fprintf(stream, " name: my entity\n"); + fprintf(stream, " primary: 0\n"); + fprintf(stream, " geometry: \n"); + fprintf(stream, " - cuboid: { size: [1, 1, 1] }\n"); + fprintf(stream, " material: \n"); + fprintf(stream, " mirror:\n"); + fprintf(stream, " reflectivity: 1\n"); + fprintf(stream, " roughness: 0.1\n"); + fprintf(stream, " normal_map: { path: Normal map } \n"); + rewind(stream); + + CHECK(solparser_setup(parser, NULL, stream), RES_OK); + CHECK(solparser_load(parser), RES_OK); + + solparser_entity_iterator_begin(parser, &it); + solparser_entity_iterator_end(parser, &end); + CHECK(solparser_entity_iterator_eq(&it, &end), 0); + + entity_id = solparser_entity_iterator_get(&it); + entity = solparser_get_entity(parser, entity_id); + + CHECK(strcmp("my entity", str_cget(&entity->name)), 0); + CHECK(solparser_entity_get_children_count(entity), 0); + CHECK(entity->primary, 0); + CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY); + geom = solparser_get_geometry(parser, entity->data.geometry); + CHECK(solparser_geometry_get_objects_count(geom), 1); + obj_id = solparser_geometry_get_object(geom, 0); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_CUBOID); + mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); + CHECK(mtl2->front.i, mtl2->back.i); + + mtl = solparser_get_material(parser, mtl2->front); + CHECK(mtl->type, SOLPARSER_MATERIAL_MIRROR); + mirror = solparser_get_material_mirror(parser, mtl->data.mirror); + CHECK(mirror->reflectivity, 1); + CHECK(mirror->roughness, 0.1); + CHECK(SOLPARSER_ID_IS_VALID(mirror->normal_map), 1); + img = solparser_get_image(parser, mirror->normal_map); + CHECK(strcmp(str_cget(&img->filename), "Normal map"), 0); + + solparser_entity_iterator_next(&it); + CHECK(solparser_entity_iterator_eq(&it, &end), 1); + + CHECK(solparser_load(parser), RES_BAD_OP); + fclose(stream); +} + +static void +test_thin_dielectric(struct solparser* parser) +{ + struct solparser_entity_iterator it, end; + struct solparser_entity_id entity_id; + struct solparser_object_id obj_id; + const struct solparser_entity* entity; + const struct solparser_image* img; + const struct solparser_geometry* geom; + const struct solparser_material_double_sided* mtl2; + const struct solparser_material* mtl; + const struct solparser_material_thin_dielectric* thin; + const struct solparser_object* obj; + const struct solparser_shape* shape; + FILE* stream; + + stream = tmpfile(); + NCHECK(stream, NULL); + fprintf(stream, "- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1} ] }\n"); + fprintf(stream, "- entity:\n"); + fprintf(stream, " name: test\n"); + fprintf(stream, " primary: 0\n"); + fprintf(stream, " geometry:\n"); + fprintf(stream, " - sphere: { radius: 1 }\n"); + fprintf(stream, " material:\n"); + fprintf(stream, " thin_dielectric:\n"); + fprintf(stream, " thickness: 0.1\n"); + fprintf(stream, " medium_i:\n"); + fprintf(stream, " refractive_index: 1\n"); + fprintf(stream, " absorptivity: 0\n"); + fprintf(stream, " medium_t:\n"); + fprintf(stream, " refractive_index: 1.5\n"); + fprintf(stream, " absorptivity: 20\n"); + fprintf(stream, " normal_map: { path: Bump }\n"); + rewind(stream); + + CHECK(solparser_setup(parser, NULL, stream), RES_OK); + CHECK(solparser_load(parser), RES_OK); + + solparser_entity_iterator_begin(parser, &it); + solparser_entity_iterator_end(parser, &end); + CHECK(solparser_entity_iterator_eq(&it, &end), 0); + + entity_id = solparser_entity_iterator_get(&it); + entity = solparser_get_entity(parser, entity_id); + + CHECK(strcmp("test", str_cget(&entity->name)), 0); + CHECK(solparser_entity_get_children_count(entity), 0); + CHECK(entity->primary, 0); + CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY); + geom = solparser_get_geometry(parser, entity->data.geometry); + CHECK(solparser_geometry_get_objects_count(geom), 1); + obj_id = solparser_geometry_get_object(geom, 0); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_SPHERE); + mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); + CHECK(mtl2->front.i, mtl2->back.i); + + mtl = solparser_get_material(parser, mtl2->front); + CHECK(mtl->type, SOLPARSER_MATERIAL_THIN_DIELECTRIC); + thin = solparser_get_material_thin_dielectric(parser, mtl->data.thin_dielectric); + CHECK(thin->thickness, 0.1); + NCHECK(thin->medium_i.i, thin->medium_t.i); + CHECK(SOLPARSER_ID_IS_VALID(thin->normal_map), 1); + img = solparser_get_image(parser, thin->normal_map); + CHECK(strcmp(str_cget(&img->filename), "Bump"), 0); + + solparser_entity_iterator_next(&it); + CHECK(solparser_entity_iterator_eq(&it, &end), 1); + + CHECK(solparser_load(parser), RES_BAD_OP); + fclose(stream); +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct solparser* parser; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + CHECK(solparser_create(&allocator, &parser), RES_OK); + + test_dielectric(parser); + test_matte(parser); + test_mirror(parser); + test_thin_dielectric(parser); + + solparser_ref_put(parser); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/parser/test_solparser_spectrum.c b/src/parser/test_solparser_spectrum.c @@ -0,0 +1,101 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "solparser.h" +#include "solparser_sun.h" +#include "test_solstice_utils.h" + +static void +test_sun(struct solparser* parser) +{ + const struct solparser_sun* sun; + const struct solparser_spectrum* spectrum; + FILE* stream; + size_t i; + + NCHECK(stream = tmpfile(), NULL); + + fprintf(stream, "- spectrum: &my_spectrum\n"); + fprintf(stream, " - { wavelength: 2, data: 2 }\n"); + fprintf(stream, " - { wavelength: 1, data: 1 }\n"); + fprintf(stream, " - { wavelength: 8, data: 8 }\n"); + fprintf(stream, " - { wavelength: 3, data: 3 }\n"); + fprintf(stream, " - { wavelength: 5, data: 5 }\n"); + fprintf(stream, " - { wavelength: 9, data: 9 }\n"); + fprintf(stream, " - { wavelength: 6, data: 6 }\n"); + fprintf(stream, " - { wavelength: 7, data: 7 }\n"); + fprintf(stream, " - { wavelength: 4, data: 4 }\n"); + fprintf(stream, "- sun:\n"); + fprintf(stream, " dni: 123.456\n"); + fprintf(stream, " spectrum: *my_spectrum\n"); + fprintf(stream, "- material: &matte { matte: { reflectivity: 1 } }\n"); + fprintf(stream, "- entity:\n"); + fprintf(stream, " name: foo bar\n"); + fprintf(stream, " primary: 0\n"); + fprintf(stream, " geometry: [{sphere: {radius: 1}, material: *matte}]\n"); + rewind(stream); + + CHECK(solparser_setup(parser, NULL, stream), RES_OK); + CHECK(solparser_load(parser), RES_OK); + + sun = solparser_get_sun(parser); + CHECK(sun->dni, 123.456); + CHECK(sun->radang_distrib_type, SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL); + CHECK(SOLPARSER_ID_IS_VALID(sun->spectrum), 1); + spectrum = solparser_get_spectrum(parser, sun->spectrum); + + CHECK(darray_spectrum_data_size_get(&spectrum->data), 9); + + FOR_EACH(i, 0, darray_spectrum_data_size_get(&spectrum->data)) { + CHECK(darray_spectrum_data_cdata_get(&spectrum->data)[i].wavelength, i+1); + CHECK(darray_spectrum_data_cdata_get(&spectrum->data)[i].wavelength, i+1); + } + + CHECK(solparser_load(parser), RES_BAD_OP); + fclose(stream); + + NCHECK(stream = tmpfile(), NULL); + fprintf(stream, "- sun: {dni: 1}\n"); + rewind(stream); + + CHECK(solparser_setup(parser, NULL, stream), RES_OK); + CHECK(solparser_load(parser), RES_OK); + + CHECK(SOLPARSER_ID_IS_VALID(sun->spectrum), 0); + + CHECK(solparser_load(parser), RES_BAD_OP); + fclose(stream); +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct solparser* parser; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + CHECK(solparser_create(&allocator, &parser), RES_OK); + + test_sun(parser); + + solparser_ref_put(parser); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml @@ -204,6 +204,7 @@ # <matte> ::= # matte: # reflectivity: REAL # in [0, 1] +# [ normal_map: { path: PATH } ] # # missing matte parameters @@ -224,7 +225,25 @@ # 2x reflectivity - material: { matte: { reflectivity: 1, reflectivity: 1 } } --- - +# bad normal map +- material: + matte: { reflectivity: 1, normal_map: map } +--- +# bad normal map +- material: + matte: { reflectivity: 1, normal_map: { path: } } +--- +# Missing reflectivity +- material: + matte: { normal_map: { path: test } } +--- +# 2x normal map +- material: + matte: + reflectivity: 1 + normal_map: { path: test } + normal_map: { path: test2} +# # # <thin-dielectric> ::= # thin_dielectric: diff --git a/src/parser/yaml/test_ok_0.yaml b/src/parser/yaml/test_ok_0.yaml @@ -50,8 +50,13 @@ - entity: { name: "hop", primary: 1, geometry: *cuboid } - sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } --- +- spectrum: &sun_spectrum + - { wavelength: 1.1, data: 1.2 } + - { wavelength: 2.2, data: 2.3 } + - { wavelength: 3.3, data: 3.4 } + - { wavelength: 4.4, data: 4.4 } - material: &lambertian { matte: { reflectivity: 1 } } -- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- sun: { dni: 1, spectrum: *sun_spectrum } - entity: name: hop primary: 0 diff --git a/src/parser/yaml/test_ok_2.yaml b/src/parser/yaml/test_ok_2.yaml @@ -39,3 +39,16 @@ geometry: - material: { matte: { reflectivity: 1 } } stl: { path: "path/path/path" } +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- material: &lambertian + matte: + reflectivity: 0.123 + normal_map: { path: "path/to my normal map" } +- entity: + name: hop + primary: 1 + geometry: + - material: *lambertian + stl: { path: "path/path/path" } + diff --git a/src/parser/yaml/test_ok_7.yaml b/src/parser/yaml/test_ok_7.yaml @@ -38,3 +38,16 @@ medium_i: { absorptivity: 0, refractive_index: 1 } medium_t: { absorptivity: 20, refractive_index: 1.5 } +--- +- sun: { dni: 1 } +- medium: &vacuum { refractive_index: 1, absorptivity: 0 } +- medium: &glass { refractive_index: 1.5, absorptivity: 20 } +- entity: + name: "entity" + primary: 0 + geometry: + - cylinder: { height: 1, radius: 1 } + material: + front: {dielectric: { medium_i: *vacuum, medium_t: *glass }} + back: {dielectric: {medium_i: *glass, medium_t: *vacuum}} + diff --git a/src/solstice_draw.c b/src/solstice_draw.c @@ -23,27 +23,32 @@ /******************************************************************************* * Helper function ******************************************************************************/ -/* Assume that the pixel format of the src is DOUBLE3 in gray scale while the - * pixel format of dst is UBYTE */ +/* Assume that the pixel format of the src is DOUBLE3 and dst is UBYTE3 */ static void -tone_map(const double* src, unsigned char* dst, const size_t count) +tone_map(const double* src, uint8_t* dst, const size_t count) { size_t i; ASSERT(src && dst && count); FOR_EACH(i, 0, count) { - double val; - val = pow(src[i*3/*#channels*/], 1/SCREEN_GAMMA);/* Gamma correction */ - val = CLAMP(val, 0, 1); - dst[i] = (unsigned char)((val * 255) + 0.5/*round*/); + double val[3]; + val[0] = pow(src[i*3/*#channels*/+0], 1/SCREEN_GAMMA);/* Gamma correction */ + val[1] = pow(src[i*3/*#channels*/+1], 1/SCREEN_GAMMA);/* Gamma correction */ + val[2] = pow(src[i*3/*#channels*/+2], 1/SCREEN_GAMMA);/* Gamma correction */ + val[0] = CLAMP(val[0], 0, 1); + val[1] = CLAMP(val[1], 0, 1); + val[2] = CLAMP(val[2], 0, 1); + dst[i*3/*#channels*/ + 0] = (uint8_t)((val[0]*255) + 0.5/*round*/); + dst[i*3/*#channels*/ + 1] = (uint8_t)((val[1]*255) + 0.5/*round*/); + dst[i*3/*#channels*/ + 2] = (uint8_t)((val[2]*255) + 0.5/*round*/); } } static void -tone_map_image(const struct ssol_image* img, unsigned char* dst) +tone_map_image(const struct ssol_image* img, uint8_t* dst) { struct ssol_image_layout layout; size_t irow = 0; - void* mem; + char* mem; ASSERT(img && dst); SSOL(image_get_layout(img, &layout)); @@ -52,7 +57,7 @@ tone_map_image(const struct ssol_image* img, unsigned char* dst) SSOL(image_map(img, &mem)); FOR_EACH(irow, 0, layout.height) { const void* src_row = ((char*)mem) + layout.offset + irow * layout.row_pitch; - unsigned char* dst_row = dst + irow * layout.width; + uint8_t* dst_row = dst + irow * layout.width * 3/*#channels*/; tone_map(src_row, dst_row, layout.width); } } @@ -64,13 +69,17 @@ res_T solstice_draw(struct solstice* solstice) { struct ssol_image_layout layout; - unsigned char* ubytes = NULL; + struct image img; + size_t pitch; res_T res = RES_OK; ASSERT(solstice); SSOL(image_get_layout(solstice->framebuffer, &layout)); - ubytes = MEM_ALLOC(solstice->allocator, layout.width*layout.height); - if(!ubytes) { + + pitch = layout.width * sizeof_image_format(IMAGE_RGB8); + image_init(solstice->allocator, &img); + res = image_setup(&img, layout.width, layout.height, pitch, IMAGE_RGB8, NULL); + if(res != RES_OK) { fprintf(stderr, "Could not allocate the 8-bits image buffer.\n"); res = RES_MEM_ERR; goto error; @@ -92,9 +101,9 @@ solstice_draw(struct solstice* solstice) goto error; } - tone_map_image(solstice->framebuffer, ubytes); - res = image_ppm_write_stream(solstice->output, (int)layout.width, - (int)layout.height, 1, ubytes); + tone_map_image(solstice->framebuffer, (uint8_t*)img.pixels); + + res = image_write_ppm_stream(&img, 0, solstice->output); if(res != RES_OK) { fprintf(stderr, "Could not write the rendered image to the output stream.\n"); @@ -102,7 +111,7 @@ solstice_draw(struct solstice* solstice) } exit: - if(ubytes) MEM_RM(solstice->allocator, ubytes); + image_release(&img); return res; error: goto exit; diff --git a/src/solstice_material.c b/src/solstice_material.c @@ -16,36 +16,87 @@ #include "solstice.h" #include "solstice_c.h" +#include <rsys/double33.h> +#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; }; struct mirror_param { double reflectivity; double roughness; + struct ssol_image* normal_map; +}; + +struct thin_dielectric_param { + struct ssol_image* normal_map; }; /******************************************************************************* * Helper functions ******************************************************************************/ static void +perturb_normal + (const struct ssol_surface_fragment* frag, + const struct ssol_image* normal_map, + double normal[3]) +{ + double basis[9]; + double N[3]; + ASSERT(frag && normal_map && normal); + + SSOL(image_sample(normal_map, SSOL_FILTER_LINEAR, SSOL_ADDRESS_CLAMP, + SSOL_ADDRESS_CLAMP, frag->uv, N)); + + d3_set(basis+0, frag->dPdu); + d3_set(basis+3, frag->dPdv); + d3_set(basis+6, frag->Ns); + d3_normalize(basis + 0, basis + 0); + d3_normalize(basis + 3, basis + 3); + + d3_subd(N, d3_muld(N, N, 2), 1); + d33_muld3(N, basis, N); + d3_normalize(normal, N); +} + +static void mtl_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], + const struct ssol_surface_fragment* frag, double* val) { - (void)dev, (void)buf, (void)wavelength, (void)P, (void)Ng, (void)uv, (void)w; - val[0] = Ns[0]; - val[1] = Ns[1]; - val[2] = Ns[2]; + (void)dev, (void)buf, (void)wavelength; + d3_set(val, frag->Ns); +} + +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 @@ -53,32 +104,45 @@ matte_get_reflectivity (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], + const struct ssol_surface_fragment* frag, double* val) { const struct matte_param* param = ssol_param_buffer_get(buf); - (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; + (void)dev, (void)wavelength, (void)frag; *val = param->reflectivity; } static void +matte_get_normal + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const struct ssol_surface_fragment* frag, + double* val) +{ + const struct matte_param* param = ssol_param_buffer_get(buf); + (void)dev, (void)wavelength; + perturb_normal(frag, param->normal_map, val); +} + +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, const double wavelength, - const double P[3], - const double Ng[3], - const double Ns[3], - const double uv[2], - const double w[3], + const struct ssol_surface_fragment* frag, double* val) { const struct mirror_param* param = ssol_param_buffer_get(buf); - (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; + (void)dev, (void)wavelength, (void)frag; *val = param->reflectivity; } @@ -87,18 +151,125 @@ mirror_get_roughness (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], + const struct ssol_surface_fragment* frag, double* val) { const struct mirror_param* param = ssol_param_buffer_get(buf); - (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; + (void)dev, (void)wavelength, (void)frag; *val = param->roughness; } +static void +mirror_get_normal + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const struct ssol_surface_fragment* frag, + double* val) +{ + 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)); +} + +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, @@ -110,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); @@ -123,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; @@ -131,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; } @@ -145,6 +349,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 +369,27 @@ 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)) { + 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 +400,7 @@ exit: return res; error: if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; + if(img) SSOL(image_ref_put(img)); goto exit; } @@ -193,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; @@ -213,17 +431,28 @@ create_material_mirror goto error; } - param = ssol_param_buffer_allocate - (pbuf, sizeof(struct mirror_param), ALIGNOF(struct mirror_param)); + 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)); @@ -235,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; } @@ -244,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); @@ -260,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; @@ -271,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; } diff --git a/src/solstice_object.c b/src/solstice_object.c @@ -525,11 +525,17 @@ create_shaded_shape res_T res = RES_OK; ASSERT(solstice && ssol_front && ssol_back && ssol_shape); + *ssol_front = NULL; + *ssol_back = NULL; + *ssol_shape = NULL; + obj = solparser_get_object(solstice->parser, obj_id); mtl2 = solparser_get_material_double_sided(solstice->parser, obj->mtl2); - solstice_create_ssol_material(solstice, mtl2->front, ssol_front); - solstice_create_ssol_material(solstice, mtl2->back, ssol_back); + res = solstice_create_ssol_material(solstice, mtl2->front, ssol_front); + if(res != RES_OK) goto error; + res = solstice_create_ssol_material(solstice, mtl2->back, ssol_back); + if(res != RES_OK) goto error; /* Define the shape transformation */ rotation[0] = MDEG2RAD(obj->rotation[0]); @@ -576,7 +582,15 @@ create_shaded_shape break; default: FATAL("Unreachable code.\n"); break; } + if(res != RES_OK) goto error; + +exit: return res; +error: + if(*ssol_front) SSOL(material_ref_put(*ssol_front)); + if(*ssol_back) SSOL(material_ref_put(*ssol_back)); + if(*ssol_shape) SSOL(shape_ref_put(*ssol_shape)); + goto exit; } /******************************************************************************* diff --git a/src/solstice_solve.c b/src/solstice_solve.c @@ -44,7 +44,7 @@ write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator) irradiance_factor = 1 / potential; /* Counts */ - fprintf(solstice->output, "%lu %lu %lu %lu %lu\n", + fprintf(solstice->output, "%d %lu %lu %lu %lu\n", 7, /* #global results count */ (unsigned long)htable_receiver_size_get(&solstice->receivers), (unsigned long)nprimary, @@ -52,20 +52,16 @@ write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator) (unsigned long)nfailed); /* Global data */ - fprintf(solstice->output, "%g %g\n", - potential, 0.); - fprintf(solstice->output, "%g %g\n", - mc_global.absorbed.E, mc_global.absorbed.SE); - fprintf(solstice->output, "%g %g\n", - mc_global.cos_factor.E, mc_global.cos_factor.SE); - fprintf(solstice->output, "%g %g\n", - mc_global.shadowed.E, mc_global.shadowed.SE); - fprintf(solstice->output, "%g %g\n", - mc_global.missing.E, mc_global.missing.SE); - fprintf(solstice->output, "%g %g\n", - mc_global.atmosphere.E, mc_global.atmosphere.SE); - fprintf(solstice->output, "%g %g\n", - mc_global.reflectivity.E, mc_global.reflectivity.SE); + #define PRINT_MC_GLOBAL(Name) \ + fprintf(solstice->output, "%g %g\n", mc_global.Name.E, mc_global.Name.SE) + fprintf(solstice->output, "%g %g\n", potential, 0.); + PRINT_MC_GLOBAL(absorbed); + PRINT_MC_GLOBAL(cos_factor); + PRINT_MC_GLOBAL(shadowed); + PRINT_MC_GLOBAL(missing); + PRINT_MC_GLOBAL(atmosphere); + PRINT_MC_GLOBAL(reflectivity); + #undef PRINT_MC_GLOBAL /* Receivers' data */ htable_receiver_begin(&solstice->receivers, &r_it); diff --git a/src/solstice_sun.c b/src/solstice_sun.c @@ -139,6 +139,7 @@ create_sun_spectrum { struct ssol_spectrum* spectrum = NULL; const struct solparser_spectrum_data* data; + const struct solparser_spectrum* spec; size_t nwlens; res_T res = RES_OK; ASSERT(solstice && solparser_sun && out_spectrum); @@ -149,8 +150,9 @@ create_sun_spectrum goto error; } - nwlens = darray_spectrum_data_size_get(&solparser_sun->spectrum); - data = darray_spectrum_data_cdata_get(&solparser_sun->spectrum); + spec = solparser_get_spectrum(solstice->parser, solparser_sun->spectrum); + nwlens = darray_spectrum_data_size_get(&spec->data); + data = darray_spectrum_data_cdata_get(&spec->data); res = ssol_spectrum_setup(spectrum, get_wavelength, nwlens, (void*)data); if(res != RES_OK) { fprintf(stderr, "Could not setup the spectrum of the solver sun.\n"); @@ -195,7 +197,7 @@ solstice_create_sun(struct solstice* solstice) } if(res != RES_OK) goto error; - if(solparser_sun->spectrum.size) { + if(SOLPARSER_ID_IS_VALID(solparser_sun->spectrum)) { res = create_sun_spectrum(solstice, solparser_sun, &spectrum); if (res != RES_OK) goto error; diff --git a/src/test_solstice_simulation.c b/src/test_solstice_simulation.c @@ -261,7 +261,7 @@ read_recv(FILE* file, char name[], double E[], double SE[]) CHECK(read_line(line, sizeof(line), file), 1); CHECK( sscanf(line, - "%s %*lu %*lg " + "%s %*u %*g " "FRONT: %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg " " BACK: %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg", name, /* ID, area */ @@ -295,7 +295,7 @@ read_primary CHECK(read_line(line, sizeof(line), file), 1); CHECK( sscanf(line, - "%s %*lu " + "%s %*u " "%lg %*lu %lg " "%lg %lg\n", name, /* ID */