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 b854926a3731f2bc175b7d00b3e7fe54f22779d9
parent 619a4d04d54cd6e721736e1990d6f11c006b8c32
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu,  2 Mar 2017 10:06:30 +0100

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

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Mcmake/parser/CMakeLists.txt | 3+++
Mdoc/input | 101+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/parser/solparser.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/parser/solparser.h | 5+++++
Msrc/parser/solparser_material.h | 10++++++++++
Msrc/parser/test_solparser2.c | 1-
Asrc/parser/test_solparser7.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/yaml/test_ko_0.yaml | 56++++++++++++++++++++++++++++++++++++++++++--------------
Asrc/parser/yaml/test_ok_5.yaml | 43+++++++++++++++++++++++++++++++++++++++++++
Msrc/solstice_args.c | 4+++-
Asrc/solstice_dump.c | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/solstice_dump_obj.c | 147-------------------------------------------------------------------------------
Msrc/solstice_entity.c | 45++++++++++++++++++++++++++++++++++++---------
14 files changed, 568 insertions(+), 224 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -86,7 +86,7 @@ set(SOLSTICE_FILES_SRC solstice.c solstice_args.c solstice_draw.c - solstice_dump_obj.c + solstice_dump.c solstice_entity.c solstice_material.c solstice_node.c diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt @@ -80,6 +80,8 @@ if(NOT NO_TEST) ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_3.yaml) add_test(test_solparser_ok_4 test_solparser ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_4.yaml) + add_test(test_solparser_ok_5 test_solparser + ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_5.yaml) add_test(test_solparser_ko test_solparser -e ${SOLPARSER_SOURCE_DIR}/yaml/test_ko_0.yaml) @@ -88,6 +90,7 @@ if(NOT NO_TEST) new_test(test_solparser4) new_test(test_solparser5) new_test(test_solparser6) + new_test(test_solparser7) rcmake_copy_runtime_libraries(test_solparser) endif() diff --git a/doc/input b/doc/input @@ -83,46 +83,46 @@ # <solar-factory> ::= # <sun> # <items> -# +# # <items> ::= # - <item> # [ - <item> ... ] -# +# # <item> ::= # <geometry> # | <material> # | <entity> # | <template> -# +# # ---------------------------------------- # <geometry> ::= # geometry: # - <object> # [ - <object> ... ] -# +# # <object> ::= # <shape> # <material> # [ <transform> ] -# +# # <x_pivot> ::= # x_pivot: # [ ref_point: <real3>. Default 0,0,0 ] # <target> -# +# # <zx_pivot> ::= # zx_pivot: # [ spacing: REAL # in [0, INF). Default 0 ] # [ ref_point: <real3>. Default 0,0,0 ] # <target> -# +# # <target> ::= # target: # anchor: <anchor-identifier> # | direction: <real3> # | position: <real3> # | <sun> -# +# # ---------------------------------------- # <shape> ::= # <cuboid> @@ -133,167 +133,173 @@ # | <plane> # | <sphere> # | <stl> -# +# # <cuboid> ::= # cuboid: # size: <real3*+> -# +# # <cylinder> ::= # cylinder: # height: REAL # in ]0, INF) # radius: REAL # in ]0, INF) # [ slices: INTEGER ] # in [4, 4096]. Default 16 -# +# # <obj> ::= # obj: # path: PATH -# +# # <parabol> ::= # parabol: # x^2 + y^2 - 4*focal*z = 0 # focal: REAL # in ]0, INF) # clip: <polyclip-list> -# +# # <parabolic-cylinder> ::= # parabolic-cylinder: # y^2 - 4*focal*z = 0 # focal: REAL # in ]0, INF) # clip: <polyclip-list> -# +# # <plane> ::= # plane: # clip: <polyclip-list> -# +# # <sphere> ::= # sphere: # radius: REAL # in ]0, INF) # [ slices: INTEGER ] # in [4, 4096]. Default 16 -# +# # <stl> ::= # stl: # path: PATH -# +# # ---------------------------------------- # <polyclip-list> ::= # - <polyclip> # [ - <polyclip> ... ] -# +# # <polyclip> ::= # operation: <AND|SUB> # vertices: <vertices-list> -# +# # <vertices-list> ::= # - <real2> # - <real2> # - <real2> # [ - <real2> ... ] -# +# # ---------------------------------------- # <material> ::= # <material-descriptor> | <double-sided-material> -# +# # <double-sided-material> ::= # front: <material-descriptor> # back: <material-descriptor> -# +# # <material-descriptor> ::= -# <mirror> | <matte> | <virtual> -# +# <mirror> | <matte> | <thin-dielectric> | <virtual> +# # <mirror> ::= # mirror: # reflectivity: REAL # in [0, 1] # roughness: REAL # in [0, 1] -# +# # <matte> ::= # matte: # reflectivity: REAL # in [0, 1] -# +# # <virtual> ::= # virtual: EMPTY-STRING -# +# +# <thin-dielectric> ::= +# thin_dielectric: +# absorption: REAL # in [0, 1] +# thickness: REAL # in [0, INF) +# refractive_index: REAL # in ]0, INF) +# # ---------------------------------------- # <entity> ::= # entity: # <entity-data> -# +# # <template> ::= # template: # <entity-data> -# +# # <entity-data> ::= # name: STRING # except "self" # [ <geometry-data> | <x_pivot> | <zx_pivot> ] # [ <anchors> ] # [ <transform> ] # [ <children> ] -# +# # <geometry-data> ::= # primary: INTEGER # in [0, 1] -# <geometry> -# +# <geometry> +# # <children> ::= # children: # - <entity-data> # [ - <entity-data> ... ] -# +# # <anchors> ::= # anchors: # - <anchor-data> # [ - <anchor-data> ... ] -# +# # <anchor-data> ::= # name: STRING # position: <real3> -# +# # # "self" references the first level entity # <entity-identifier> ::= # <self|STRING>[.STRING ... ] -# +# # <anchor-identifier> ::= # <entity-identifier>.STRING -# +# # ---------------------------------------- # <sun> ::= # sun: # dni: REAL # Direct Normal Irradiance in ]0, INF) # <spectrum> # [ <radial-angular-distribution> ] -# +# # <radial-angular-distribution> ::= # <pillbox> | <buie> -# +# # <buie> ::= # buie: # csr: REAL # in [1e-6, 0.849] -# +# # <pillbox> ::= # pillbox: # aperture: REAL # in ]0, 90] -# +# # ---------------------------------------- # <transform> ::= # transform: # translation: <real3> # rotation: <real3> -# +# # <real2> ::= # - REAL # - REAL -# +# # <real3> ::= # - REAL # - REAL # - REAL -# +# # <real3*+> ::= # - REAL # in ]0, inf) # - REAL # in ]0, inf) # - REAL # in ]0, inf) -# +# # <spectrum> ::= # spectrum: # - <spectrum-data> # [ - <spectrum-data> ... ] -# +# # <spectrum-data> ::= # wavelength: REAL # in [0, INF) # data: REAL # in [0, INF) -# -\ No newline at end of file +# diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -54,6 +54,11 @@ struct target_alias { #define DARRAY_DATA struct solparser_material_mirror #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 +#include <rsys/dynamic_array.h> + /* Declare the array of materials */ #define DARRAY_NAME material #define DARRAY_DATA struct solparser_material @@ -185,6 +190,7 @@ struct solparser { struct darray_material2 mtls2; /* Double sided materials */ struct darray_matte mattes; struct darray_mirror mirrors; + struct darray_thin_dielectric thin_dielectrics; /* Use to deferred the setup of the anchor targeted by a pivot */ struct darray_tgtalias tgtaliases; @@ -383,6 +389,7 @@ parser_clear(struct solparser* parser) darray_material2_clear(&parser->mtls2); darray_matte_clear(&parser->mattes); darray_mirror_clear(&parser->mirrors); + darray_thin_dielectric_clear(&parser->thin_dielectrics); /* Deferred targeted anchors */ darray_tgtalias_clear(&parser->tgtaliases); @@ -435,6 +442,7 @@ parser_release(ref_T* ref) darray_material2_release(&parser->mtls2); darray_matte_release(&parser->mattes); darray_mirror_release(&parser->mirrors); + darray_thin_dielectric_release(&parser->thin_dielectrics); /* Deferred targeted anchors */ darray_tgtalias_release(&parser->tgtaliases); @@ -1027,6 +1035,106 @@ error: } static res_T +parse_material_thin_dielectric + (struct solparser* parser, + yaml_document_t* doc, + yaml_node_t* thin, + struct solparser_material_thin_dielectric_id* out_imtl) +{ + enum { ABSORPTION, REFRACTIVE_INDEX, THICKNESS }; + struct solparser_material_thin_dielectric* mtl = NULL; + size_t imtl = SIZE_MAX; + int mask = 0; /* Register the parsed attributes */ + intptr_t i, n; + res_T res = RES_OK; + ASSERT(doc && thin && out_imtl); + + if(thin->type != YAML_MAPPING_NODE) { + log_err(parser, thin, + "expect a mapping of thin material attributes.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Allocate the thin dielectric material */ + imtl = darray_thin_dielectric_size_get(&parser->thin_dielectrics); + res = darray_thin_dielectric_resize(&parser->thin_dielectrics, imtl + 1); + if(res != RES_OK) { + log_err(parser, thin, + "could not allocate the thin dielectric material.\n"); + goto error; + } + mtl = darray_thin_dielectric_data_get(&parser->thin_dielectrics) + imtl; + + n = thin->data.mapping.pairs.top - thin->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, thin->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, thin->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect a thin dielectric material 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 thin dielectric material is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "absorption")) { + SETUP_MASK(ABSORPTION, "absorption"); + res = parse_real(parser, val, 0, 1, &mtl->absorption); + } 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, &mtl->refractive_index); + } else if(!strcmp((char*)key->data.scalar.value, "thickness")) { + SETUP_MASK(THICKNESS, "thickness"); + res = parse_real(parser, val, 0, DBL_MAX, &mtl->thickness); + } else { + log_err(parser, key, "unknown thin dielectric 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, thin, \ + "the "Name" of the thin dielectric material is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(ABSORPTION, "absorption"); + CHECK_PARAM(REFRACTIVE_INDEX, "refractive_index"); + CHECK_PARAM(THICKNESS, "thickness"); + #undef CHECK_PARAM + +exit: + out_imtl->i = imtl; + return res; +error: + if(mtl) { + darray_thin_dielectric_pop_back(&parser->thin_dielectrics); + imtl = SIZE_MAX; + } + goto exit; +} + +static res_T parse_material_virtual(struct solparser* parser, yaml_node_t* virtual) { res_T res = RES_OK; @@ -1114,8 +1222,13 @@ parse_material_descriptor SETUP_MASK(DESCRIPTOR, "descriptor"); mtl->type = SOLPARSER_MATERIAL_MIRROR; res = parse_material_mirror(parser, doc, val, &mtl->data.mirror); + } else if(!strcmp((char*)key->data.scalar.value, "thin_dielectric")) { + SETUP_MASK(DESCRIPTOR, "descriptor"); + mtl->type = SOLPARSER_MATERIAL_THIN_DIELECTRIC; + res = parse_material_thin_dielectric + (parser, doc, val, &mtl->data.thin_dielectric); } else if(!strcmp((char*)key->data.scalar.value, "virtual")) { - SETUP_MASK(DESCRIPTOR, "virtual"); + SETUP_MASK(DESCRIPTOR, "descriptor"); mtl->type = SOLPARSER_MATERIAL_VIRTUAL; res = parse_material_virtual(parser, val); } else { @@ -1620,7 +1733,7 @@ parse_cylinder *(Ptr) = Value; \ } (void)0 DEFAULT_PARAM(SLICES, &shape->nslices, 16); - #undef DEFAULT_PARAM + #undef DEFAULT_PARAM exit: out_ishape->i = ishape; @@ -3064,7 +3177,7 @@ parse_zx_pivot parser, doc, val, -DBL_MAX, DBL_MAX, solxzpivot->ref_point); } else if(!strcmp((char*) key->data.scalar.value, "target")) { struct solparser_pivot_id pivot_id; - pivot_id.i = + pivot_id.i = (size_t) (solxzpivot - darray_zx_pivot_cdata_get(&parser->zx_pivots)); SETUP_MASK(TARGET, "target"); res = parse_target(parser, doc, val, &solxzpivot->target, pivot_id); @@ -3451,6 +3564,7 @@ solparser_create darray_material2_init(mem_allocator, &parser->mtls2); darray_matte_init(mem_allocator, &parser->mattes); darray_mirror_init(mem_allocator, &parser->mirrors); + darray_thin_dielectric_init(mem_allocator, &parser->thin_dielectrics); /* Deferred targeted anchors */ darray_tgtalias_init(mem_allocator, &parser->tgtaliases); @@ -3804,6 +3918,16 @@ solparser_get_material_mirror return darray_mirror_cdata_get(&parser->mirrors) + mirror.i; } +const struct solparser_material_thin_dielectric* +solparser_get_material_thin_dielectric + (const struct solparser* parser, + const struct solparser_material_thin_dielectric_id thin) +{ + ASSERT(parser); + ASSERT(thin.i < darray_thin_dielectric_size_get(&parser->thin_dielectrics)); + return darray_thin_dielectric_cdata_get(&parser->thin_dielectrics) + thin.i; +} + const struct solparser_object* solparser_get_object (const struct solparser* parser, diff --git a/src/parser/solparser.h b/src/parser/solparser.h @@ -112,6 +112,11 @@ solparser_get_material_mirror (const struct solparser* parser, const struct solparser_material_mirror_id mirror); +extern LOCAL_SYM const struct solparser_material_thin_dielectric* +solparser_get_material_thin_dielectric + (const struct solparser* parser, + const struct solparser_material_thin_dielectric_id thin_dielectric); + extern LOCAL_SYM const struct solparser_object* solparser_get_object (const struct solparser* parser, diff --git a/src/parser/solparser_material.h b/src/parser/solparser_material.h @@ -21,6 +21,7 @@ enum solparser_material_type { SOLPARSER_MATERIAL_MATTE, SOLPARSER_MATERIAL_MIRROR, + SOLPARSER_MATERIAL_THIN_DIELECTRIC, SOLPARSER_MATERIAL_VIRTUAL }; @@ -37,11 +38,20 @@ struct solparser_material_mirror { struct solparser_material_mirror_id { size_t i; }; +struct solparser_material_thin_dielectric { + double absorption; + double refractive_index; + double thickness; +}; + +struct solparser_material_thin_dielectric_id { size_t i; }; + struct solparser_material { enum solparser_material_type type; union { struct solparser_material_matte_id matte; struct solparser_material_mirror_id mirror; + struct solparser_material_thin_dielectric_id thin_dielectric; } data; }; diff --git a/src/parser/test_solparser2.c b/src/parser/test_solparser2.c @@ -114,7 +114,6 @@ 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); diff --git a/src/parser/test_solparser7.c b/src/parser/test_solparser7.c @@ -0,0 +1,95 @@ +/* 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" + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + 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_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; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + solparser_create(&allocator, &parser); + + 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, " absorption: 0.5\n"); + fprintf(stream, " thickness: 0.123\n"); + fprintf(stream, " refractive_index: 1.5\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->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->absorption, 0.5); + CHECK(thin->thickness, 0.123); + CHECK(thin->refractive_index, 1.5); + + CHECK(solparser_load(parser), RES_BAD_OP); + solparser_ref_put(parser); + + fclose(stream); + + 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 @@ -16,7 +16,7 @@ - sun: { spectrum: [{data: 1}] } --- # missing data -- sun: { spectrum: [{wavelength: 1}] } +- sun: { spectrum: [{wavelength: 1}] } --- # 2x wavelength - sun: { spectrum: [{wavelength: 1, wavelength: 1}] } @@ -143,7 +143,7 @@ - sun: { dni: 1, dni: 1 } --- # 2x spectrum -- sun: +- sun: spectrum: [{wavelength: 1, data: 1}] spectrum: [{wavelength: 1, data: 1}] --- @@ -223,6 +223,35 @@ --- # +# <thin-dielectric> ::= +# thin_dielectric: +# absorption: REAL # in [0, 1] +# thickness: REAL # in [0, INF) +# refractive_index: REAL # in ]0, INF) +# + +# invalid absorption +- material: + thin_dielectric: { absorption: -1, thickness: 0, refractive_index: 1 } +--- +# invalid absorption +- material: + thin_dielectric: { absorption: 1.001, thickness: 0, refractive_index: 1 } +--- +# invalid thickness +- material: + thin_dielectric: { absorption: 0, thickness: -0.01, refractive_index: 1 } +--- +# invalid refractive index +- material: + thin_dielectric: { absorption: 0, thickness: 0, refractive_index: 0 } +--- +# invalid refractive index +- material: + thin_dielectric: { absorption: 0, thickness: 0, refractive_index: -0.0001 } +--- + +# # front: <material-descriptor> # @@ -254,7 +283,7 @@ # # missing material definition -- material: +- material: --- # unknown dummy parameter - material: { dummy: 123 } @@ -941,14 +970,14 @@ # spacing: REAL # in [0, INF) # ref_point: <real3> # <target> -# +# # <target> ::= # target: # anchor: <anchor-identifier> # | direction: <real3> # | position: <real3> # | <sun> -# +# # missing zx_pivot definition - entity: @@ -1157,7 +1186,7 @@ # # <geometry-data> ::= # primary: INTEGER # in [0, 1] -# <geometry> +# <geometry> # # missing entity definition @@ -1273,9 +1302,9 @@ --- # 2x children - entity: - children: + children: - name: "child1" - children: + children: - name: "child2" --- # 2 entities with the same name @@ -1306,7 +1335,7 @@ # # <geometry-data> ::= # primary: INTEGER # in [0, 1] -# <geometry> +# <geometry> # # missing template definition @@ -1440,9 +1469,9 @@ --- # 2x children - template: &temp - children: + children: - name: "child1" - children: + children: - name: "child2" - entity: *temp --- @@ -1517,7 +1546,7 @@ - geometry: --- # unknown dummy parameter -- geometry: +- geometry: - dummy: 1 --- # missing material definition @@ -1570,4 +1599,4 @@ geometry: - cuboid: { size: [1, 2, 3] } material: { matte: { reflectivity: 1 } } - -\ No newline at end of file + diff --git a/src/parser/yaml/test_ok_5.yaml b/src/parser/yaml/test_ok_5.yaml @@ -0,0 +1,43 @@ +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } + +- material: &thin_dielectric + thin_dielectric: + absorption: 0.1 + thickness: 0.2 + refractive_index: 1.00027 + +- entity: + name: "entity" + primary: 0 + geometry: + - material: *thin_dielectric + cylinder: { height: 1, radius: 1 } +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } + +- material: &thin_dielectric + thin_dielectric: + absorption: 0 + thickness: 0 + refractive_index: 0.0001 + +- entity: + name: "entity" + primary: 0 + geometry: + - material: *thin_dielectric + cylinder: { height: 1, radius: 1 } + +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: "entity" + primary: 0 + geometry: + - cylinder: { height: 1, radius: 1 } + material: + thin_dielectric: + absorption: 0 + thickness: 10 + refractive_index: 0.0001 + diff --git a/src/solstice_args.c b/src/solstice_args.c @@ -254,7 +254,9 @@ parse_rendering_option(const char* str, struct solstice_args* args) } } else { fprintf(stderr, "Invalid rendering option `%s'.\n", val); - fprintf(stderr, "Valid options are: fov=FOV:img=WIDTHxHEIGHT:pos=X,Y,Z:tgt=X,Y,Z:up=X,Y,Z\n"); + /* TODO remove this. The man page will be sufficient */ + fprintf(stderr, +"Valid options are: fov=FOV:img=WIDTHxHEIGHT:pos=X,Y,Z:tgt=X,Y,Z:up=X,Y,Z\n"); res = RES_BAD_ARG; goto error; } diff --git a/src/solstice_dump.c b/src/solstice_dump.c @@ -0,0 +1,150 @@ +/* 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 "solstice_c.h" +#include <solstice/ssol.h> + +struct dump_context { + FILE* output; + size_t ids_offset; + enum solstice_args_dump_split_mode split_mode; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +dump_instantiated_shaded_shape + (struct ssol_instantiated_shaded_shape* sshape, struct dump_context* ctx) +{ + unsigned i, ntris, nverts; + enum ssol_material_type type; + const char* mtl; + ASSERT(sshape && ctx); + + SSOL(material_get_type(sshape->mtl_front, &type)); + switch(type) { + case SSOL_MATERIAL_MATTE: mtl = "matte"; break; + case SSOL_MATERIAL_MIRROR: mtl = "mirror"; break; + case SSOL_MATERIAL_VIRTUAL: mtl = "virtual"; break; + default: FATAL("Unexpected Solstice Solver material type.\n"); break; + } + + fprintf(ctx->output, "usemtl %s\n", mtl); + + SSOL(shape_get_vertices_count(sshape->shape, &nverts)); + FOR_EACH(i, 0, nverts) { + double pos[3]; + SSOL(instantiated_shaded_shape_get_vertex_attrib + (sshape, i, SSOL_POSITION, pos)); + fprintf(ctx->output, "v %g %g %g\n", SPLIT3(pos)); + } + + SSOL(shape_get_triangles_count(sshape->shape, &ntris)); + FOR_EACH(i, 0, ntris) { + unsigned ids[3]; + SSOL(shape_get_triangle_indices(sshape->shape, i, ids)); + /* Note that in the obj fileformat the first index is 1 rather than 0 */ + fprintf(ctx->output, "f %lu %lu %lu\n", + (unsigned long)(ids[0] + 1 + ctx->ids_offset), + (unsigned long)(ids[1] + 1 + ctx->ids_offset), + (unsigned long)(ids[2] + 1 + ctx->ids_offset)); + } + + if(ctx->split_mode == SOLSTICE_ARGS_DUMP_SPLIT_OBJECT) { + fprintf(ctx->output, "---\n"); + ctx->ids_offset = 0; + } else { + ctx->ids_offset += nverts; + } +} + +static res_T +dump_instance(struct ssol_instance* instance, void* context) +{ + struct dump_context* ctx = context; + size_t i, n; + ASSERT(instance && ctx); + + SSOL(instance_get_shaded_shapes_count(instance, &n)); + FOR_EACH(i, 0, n) { + struct ssol_instantiated_shaded_shape sshape; + SSOL(instance_get_shaded_shape(instance, i, &sshape)); + dump_instantiated_shaded_shape(&sshape, ctx); + } + + return RES_OK; +} + +static res_T +dump_geometry + (const struct sanim_node* n, const double transform[12], void* data) +{ + struct solstice_node* node; + struct dump_context* ctx = data; + res_T res = RES_OK; + ASSERT(n && data); + (void)transform; + + node = CONTAINER_OF(n, struct solstice_node, anim); + if(node->type != SOLSTICE_NODE_GEOMETRY) return RES_OK; + fprintf(ctx->output, "g %s\n", solstice_node_get_name(node)); + res = dump_instance(node->instance, data); + if(res != RES_OK) return res; + + if(ctx->split_mode == SOLSTICE_ARGS_DUMP_SPLIT_GEOMETRY) { + fprintf(ctx->output, "---\n"); + ctx->ids_offset = 0; + } + return RES_OK; +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +solstice_dump(struct solstice* solstice) +{ + struct dump_context ctx; + double dummy_dir[3] = {0, 0, 1}; + size_t i, n; + res_T res = RES_OK; + ASSERT(solstice && solstice->dump_format == SOLSTICE_ARGS_DUMP_OBJ); + + ctx.output = solstice->output; + ctx.ids_offset = 0; + ctx.split_mode = solstice->dump_split_mode; + + n = darray_nodes_size_get(&solstice->roots); + FOR_EACH(i, 0, n) { + struct solstice_node* node = darray_nodes_data_get(&solstice->roots)[i]; + + fprintf(solstice->output, "# %s\n", solstice_node_get_name(node)); + + /* TODO use a anim tree visitor that neither resolve the pivot + * transformations nor compute the node transforms */ + res = sanim_node_visit_tree(&node->anim, dummy_dir, &ctx, dump_geometry); + if(res != RES_OK) { + fprintf(stderr, "Could not dump the solstice geometry.\n"); + goto error; + } + } + +exit: + return res; +error: + goto exit; +} + diff --git a/src/solstice_dump_obj.c b/src/solstice_dump_obj.c @@ -1,147 +0,0 @@ -/* 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 "solstice_c.h" -#include <solstice/ssol.h> - -struct dump_context { - FILE* output; - size_t ids_offset; - enum solstice_args_dump_split_mode split_mode; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static void -dump_instantiated_shaded_shape - (struct ssol_instantiated_shaded_shape* sshape, struct dump_context* ctx) -{ - unsigned i, ntris, nverts; - enum ssol_material_type type; - const char* mtl; - ASSERT(sshape && ctx); - - SSOL(material_get_type(sshape->mtl_front, &type)); - switch(type) { - case SSOL_MATERIAL_MATTE: mtl = "matte"; break; - case SSOL_MATERIAL_MIRROR: mtl = "mirror"; break; - case SSOL_MATERIAL_VIRTUAL: mtl = "virtual"; break; - default: FATAL("Unexpected Solstice Solver material type.\n"); break; - } - - fprintf(ctx->output, "usemtl %s\n", mtl); - - SSOL(shape_get_vertices_count(sshape->shape, &nverts)); - FOR_EACH(i, 0, nverts) { - double pos[3]; - SSOL(instantiated_shaded_shape_get_vertex_attrib - (sshape, i, SSOL_POSITION, pos)); - fprintf(ctx->output, "v %g %g %g\n", SPLIT3(pos)); - } - - SSOL(shape_get_triangles_count(sshape->shape, &ntris)); - FOR_EACH(i, 0, ntris) { - unsigned ids[3]; - SSOL(shape_get_triangle_indices(sshape->shape, i, ids)); - /* Note that in the obj fileformat the first index is 1 rather than 0 */ - fprintf(ctx->output, "f %lu %lu %lu\n", - (unsigned long)(ids[0] + 1 + ctx->ids_offset), - (unsigned long)(ids[1] + 1 + ctx->ids_offset), - (unsigned long)(ids[2] + 1 + ctx->ids_offset)); - } - - if(ctx->split_mode == SOLSTICE_ARGS_DUMP_SPLIT_OBJECT) { - fprintf(ctx->output, "---\n"); - ctx->ids_offset = 0; - } else { - ctx->ids_offset += nverts; - } -} - -static res_T -dump_instance(struct ssol_instance* instance, void* context) -{ - struct dump_context* ctx = context; - size_t i, n; - ASSERT(instance && ctx); - - SSOL(instance_get_shaded_shapes_count(instance, &n)); - FOR_EACH(i, 0, n) { - struct ssol_instantiated_shaded_shape sshape; - SSOL(instance_get_shaded_shape(instance, i, &sshape)); - dump_instantiated_shaded_shape(&sshape, ctx); - } - - return RES_OK; -} - -static res_T -dump_geometry - (const struct sanim_node* n, const double transform[12], void* data) -{ - struct solstice_node* node; - struct dump_context* ctx = data; - res_T res = RES_OK; - ASSERT(n && data); - (void)transform; - - node = CONTAINER_OF(n, struct solstice_node, anim); - if(node->type != SOLSTICE_NODE_GEOMETRY) return RES_OK; - fprintf(ctx->output, "g %s\n", solstice_node_get_name(node)); - res = dump_instance(node->instance, data); - if(res != RES_OK) return res; - - if(ctx->split_mode == SOLSTICE_ARGS_DUMP_SPLIT_GEOMETRY) { - fprintf(ctx->output, "---\n"); - ctx->ids_offset = 0; - } - return RES_OK; -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -res_T -solstice_dump(struct solstice* solstice) -{ - struct dump_context ctx; - double dummy_dir[3] = {0, 0, 1}; - size_t i, n; - res_T res = RES_OK; - ASSERT(solstice && solstice->dump_format == SOLSTICE_ARGS_DUMP_OBJ); - - ctx.output = solstice->output; - ctx.ids_offset = 0; - ctx.split_mode = solstice->dump_split_mode; - - n = darray_nodes_size_get(&solstice->roots); - FOR_EACH(i, 0, n) { - struct solstice_node* node = darray_nodes_data_get(&solstice->roots)[i]; - - fprintf(solstice->output, "# %s\n", solstice_node_get_name(node)); - res = sanim_node_visit_tree(&node->anim, dummy_dir, &ctx, dump_geometry); - if(res != RES_OK) { - fprintf(stderr, "Could not dump the solstice geometry.\n"); - goto error; - } - } - -exit: - return res; -error: - goto exit; -} - diff --git a/src/solstice_entity.c b/src/solstice_entity.c @@ -97,6 +97,37 @@ error: goto exit; } +static res_T +get_anchor_node + (struct solstice* solstice, + struct solparser_anchor_id anchor_id, + struct solstice_node** out_node) +{ + struct solstice_node* node = NULL; + struct solstice_node** pnode = NULL; + res_T res = RES_OK; + ASSERT(solstice && out_node); + + pnode = htable_anchor_find(&solstice->anchors, &anchor_id.i); + if(pnode) { + node = *pnode; + } else { + res = solstice_node_target_create(solstice->allocator, &node); + if(res != RES_OK) goto error; + + res = htable_anchor_set(&solstice->anchors, &anchor_id.i, &node); + if(res != RES_OK) goto error; + } + +exit: + *out_node = node; + return res; +error: + if(node) solstice_node_ref_put(node); + goto exit; +} + + static struct solstice_node* create_x_pivot_node (struct solstice* solstice, @@ -180,8 +211,8 @@ create_zx_pivot_node switch (parser_zx_pivot->target.type) { case SOLPARSER_TARGET_ANCHOR: anim_tracking.policy = TRACKING_NODE_TARGET; - target = *htable_anchor_find - (&solstice->anchors, &parser_zx_pivot->target.data.anchor.i); + CHECK(RES_OK, + get_anchor_node(solstice, parser_zx_pivot->target.data.anchor, &target)); solstice_node_target_get_tracking(target, &anim_tracking); break; case SOLPARSER_TARGET_DIRECTION: @@ -223,7 +254,6 @@ create_node const struct str* name) { struct solstice_node* node = NULL; - struct solstice_node* tgt = NULL; struct solstice_node* child = NULL; struct solstice_receiver* rcv = NULL; struct str child_name; @@ -296,16 +326,14 @@ create_node /* Register entity anchors */ FOR_EACH(i, 0, solparser_entity_get_anchors_count(entity)) { + struct solstice_node* tgt = NULL; struct solparser_anchor_id id; - const struct solparser_anchor* anchor = NULL; - - res = solstice_node_target_create(solstice->allocator, &tgt); - if(res != RES_OK) goto error; + const struct solparser_anchor* anchor; id = solparser_entity_get_anchor(entity, i); anchor = solparser_get_anchor(solstice->parser, id); - res = htable_anchor_set(&solstice->anchors, &id.i, &tgt); + res = get_anchor_node(solstice, id, &tgt); if(res != RES_OK) goto error; solstice_node_set_translation(tgt, anchor->position); @@ -349,7 +377,6 @@ exit: str_release(&child_name); return node; error: - if(tgt) solstice_node_ref_put(tgt); if(child) solstice_node_ref_put(child); if(node) solstice_node_ref_put(node); node = NULL;