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:
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 */