star-schiff

Library for estimating radiative properties
git clone git://git.meso-star.com/star-schiff.git
Log | Files | Refs | README | LICENSE

commit 1b508a1927856bc55a8aa51411881b58c30ee52f
parent d52298d1d16f4214dbaafcddae6a9ab0389630d0
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu,  8 Oct 2015 09:52:48 +0200

Rename the project from Star-Algae to Star-Schiff

Update the API prefix, the file and library names with respect to the
new project name.

Diffstat:
MREADME.md | 11+++++------
Mcmake/CMakeLists.txt | 48++++++++++++++++++++++++------------------------
Dsrc/salgae.h | 156-------------------------------------------------------------------------------
Dsrc/salgae_device.c | 143-------------------------------------------------------------------------------
Dsrc/salgae_device.h | 57---------------------------------------------------------
Dsrc/salgae_estimator.c | 395-------------------------------------------------------------------------------
Asrc/sschiff.h | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sschiff_device.c | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sschiff_device.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sschiff_estimator.c | 395+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/test_salgae_device.c | 98-------------------------------------------------------------------------------
Dsrc/test_salgae_estimator.c | 203-------------------------------------------------------------------------------
Asrc/test_sschiff_device.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_sschiff_estimator.c | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/test_salgae_utils.h -> src/test_sschiff_utils.h | 0
15 files changed, 1080 insertions(+), 1082 deletions(-)

diff --git a/README.md b/README.md @@ -1,4 +1,4 @@ -# Star Algae +# Star Schiff The purpose of this library is to numericaly solve the radiative properties of micro organism with respect to an "Approximation Method for Short Wavelength or @@ -6,22 +6,21 @@ High-Energy Scattering" (L. Schiff, 1956). ## How to build -The *Star-Algae* library relies on the [CMake](http://www.cmake.org) and the +The *Star-Schiff* library relies on the [CMake](http://www.cmake.org) and the [RCMake](https://gitlab.com/vaplv/rcmake/) package to build. It also depends on the [RSys](https://gitlab.com/vaplv/rsys/), -[Star-3D](https://gitlab.com/meso-star/star-3d/), -[Star-MC](https://gitlab.com/meso-star/star-mc/) and +[Star-3D](https://gitlab.com/meso-star/star-3d/) and [Star-SP](https://gitlab.com/meso-star/star-sp/) libraries. First ensure that CMake is installed on your system. Then install the RCMake -package as well as all the *Star-Algae* prerequisites. Then generate the +package as well as all the *Star-Schiff* prerequisites. Then generate the project from the `cmake/CMakeLists.txt` file by appending to the `CMAKE_PREFIX_PATH` variable the install directories of its dependencies and the RCMake package. ## Licenses -*Star-Algae* is Copyright (C) |Meso|Star> 2015 (<contact@meso-star.com>). It is a +*Star-Schiff* is Copyright (C) |Meso|Star> 2015 (<contact@meso-star.com>). It is a free software released under the [OSI](http://opensource.org)-approved CeCILL license. You are welcome to redistribute it under certain conditions; refer to the COPYING files for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -27,10 +27,10 @@ # knowledge of the CeCILL license and that you accept its terms. cmake_minimum_required(VERSION 2.8) -project(star-algae C) +project(star-schiff C) enable_testing() -set(SALGAE_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) +set(SSCHIFF_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) option(NO_TEST "Disable the test" OFF) ################################################################################ @@ -59,50 +59,50 @@ set(VERSION_MINOR 3) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(SALGAE_FILES_SRC salgae_device.c salgae_estimator.c) -set(SALGAE_FILES_INC_API salgae.h) -set(SALGAE_FILES_INC salgae_device.h) -set(SALGAE_FILES_DOC COPYING.en COPYING.fr README.md) +set(SSCHIFF_FILES_SRC sschiff_device.c sschiff_estimator.c) +set(SSCHIFF_FILES_INC_API sschiff.h) +set(SSCHIFF_FILES_INC sschiff_device.h) +set(SSCHIFF_FILES_DOC COPYING.en COPYING.fr README.md) -# Prepend each file in the `SALGAE_FILES_<SRC|INC>' list by `SALGAE_SOURCE_DIR' -rcmake_prepend_path(SALGAE_FILES_SRC ${SALGAE_SOURCE_DIR}) -rcmake_prepend_path(SALGAE_FILES_INC_API ${SALGAE_SOURCE_DIR}) -rcmake_prepend_path(SALGAE_FILES_INC ${SALGAE_SOURCE_DIR}) -rcmake_prepend_path(SALGAE_FILES_DOC ${PROJECT_SOURCE_DIR}/../) +# Prepend each file in the `SSCHIFF_FILES_<SRC|INC>' list by `SSCHIFF_SOURCE_DIR' +rcmake_prepend_path(SSCHIFF_FILES_SRC ${SSCHIFF_SOURCE_DIR}) +rcmake_prepend_path(SSCHIFF_FILES_INC_API ${SSCHIFF_SOURCE_DIR}) +rcmake_prepend_path(SSCHIFF_FILES_INC ${SSCHIFF_SOURCE_DIR}) +rcmake_prepend_path(SSCHIFF_FILES_DOC ${PROJECT_SOURCE_DIR}/../) -add_library(salgae SHARED ${SALGAE_FILES_SRC} ${SALGAE_FILES_INC_API} ${SALGAE_FILES_INC}) -set_target_properties(salgae PROPERTIES - DEFINE_SYMBOL SALGAE_SHARED_BUILD +add_library(sschiff SHARED ${SSCHIFF_FILES_SRC} ${SSCHIFF_FILES_INC_API} ${SSCHIFF_FILES_INC}) +set_target_properties(sschiff PROPERTIES + DEFINE_SYMBOL SSCHIFF_SHARED_BUILD VERSION ${VERSION} SOVERSION ${VERSION_MAJOR}) -target_link_libraries(salgae RSys Star3D StarSP) +target_link_libraries(sschiff RSys Star3D StarSP) if(CMAKE_COMPILER_IS_GNUCC) - target_link_libraries(salgae m) + target_link_libraries(sschiff m) endif() -rcmake_setup_devel(salgae StarAlgae ${VERSION} star/salgae_version.h) +rcmake_setup_devel(sschiff StarAlgae ${VERSION} star/sschiff_version.h) ################################################################################ # Add tests ################################################################################ if(NOT NO_TEST) function(new_test _name) - add_executable(${_name} ${SALGAE_SOURCE_DIR}/${_name}.c) - target_link_libraries(${_name} salgae RSys) + add_executable(${_name} ${SSCHIFF_SOURCE_DIR}/${_name}.c) + target_link_libraries(${_name} sschiff RSys) add_test(${_name} ${_name}) endfunction(new_test) - new_test(test_salgae_device) - new_test(test_salgae_estimator) + new_test(test_sschiff_device) + new_test(test_sschiff_estimator) endif() ################################################################################ # Define output & install directories ################################################################################ -install(TARGETS salgae +install(TARGETS sschiff ARCHIVE DESTINATION bin LIBRARY DESTINATION lib RUNTIME DESTINATION bin) -install(FILES ${SALGAE_FILES_INC_API} DESTINATION include/star) -install(FILES ${SALGAE_FILES_DOC} DESTINATION doc/star-algae) +install(FILES ${SSCHIFF_FILES_INC_API} DESTINATION include/star) +install(FILES ${SSCHIFF_FILES_DOC} DESTINATION doc/star-schiff) diff --git a/src/salgae.h b/src/salgae.h @@ -1,156 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#ifndef SALGAE_H -#define SALGAE_H - -#include <rsys/rsys.h> - -/* Library symbol management */ -#if defined(SALGAE_SHARED_BUILD) /* Build shared library */ - #define SALGAE_API extern EXPORT_SYM -#elif defined(SALGAE_STATIC) /* Use/build static library */ - #define SALGAE_API extern LOCAL_SYM -#else /* Use shared library */ - #define SALGAE_API extern IMPORT_SYM -#endif - -/* Helper macro that asserts if the invocation of the sgf function `Func' - * returns an error. One should use this macro on salgae function calls for - * which no explicit error checking is performed */ -#ifndef NDEBUG - #define SALGAE(Func) ASSERT(salgae_ ## Func == RES_OK) -#else - #define SALGAE(Func) salgae_ ## Func -#endif - -/* Forward declaration of external types */ -struct mem_allocator; -struct logger; -struct s3d_device; -struct s3d_shape; -struct ssp_rng; - -struct salgae_refractive_index { double real, imag; }; - -/* Material of an Algae */ -struct salgae_material { - /* Retrieve the refractive complex index of the material */ - void (*get_refractive_index) - (void* material, - const double wavelength, - struct salgae_refractive_index* value); - void* material; /* Opaque user defined representation of the material */ -}; - -static const struct salgae_material SALGAE_NULL_MATERIAL = { NULL, NULL }; - -struct salgae_integrator_desc { - res_T (*sample_geometry) /* Sample a geometry i.e. a shape and its material */ - (struct ssp_rng* rng, - struct salgae_material* mtl, /* Sampled material */ - struct s3d_shape* shape, /* Sampled shape */ - void* sampler_context); - void* sampler_context; - size_t scattering_angles_count; /* # of scattering angles to handle */ -}; - -static const struct salgae_integrator_desc SALGAE_NULL_INTEGRATOR_DESC = { - NULL, NULL, 0 -}; - -/* Result of the Monte Carlo estimation */ -struct salgae_estimator_status { - double E; /* Expected value */ - double V; /* Variance */ - double SE; /* Standard error */ - size_t nsteps; -}; - -/* Opaque types */ -struct salgae_device; -struct salgae_estimator; - -/******************************************************************************* - * Star Algae API - ******************************************************************************/ -BEGIN_DECLS - -SALGAE_API res_T -salgae_device_create - (struct logger* logger, /* May be NULL <=> use default logger */ - struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ - const int verbose, - struct s3d_device* s3d, /* May be NULL <=> internally create a S3D device */ - struct salgae_device** dev); - -SALGAE_API res_T -salgae_device_ref_get - (struct salgae_device* dev); - -SALGAE_API res_T -salgae_device_ref_put - (struct salgae_device* dev); - -SALGAE_API res_T -salgae_integrate - (struct salgae_device* dev, - struct ssp_rng* rng, - struct salgae_integrator_desc* desc, - const double wavelength, /* Wavelength to integrate */ - const size_t steps_count, /* #realisations */ - struct salgae_estimator** estimator); - -SALGAE_API res_T -salgae_estimator_ref_get - (struct salgae_estimator* estimator); - -SALGAE_API res_T -salgae_estimator_ref_put - (struct salgae_estimator* estimator); - -SALGAE_API res_T -salgae_estimator_get_extinction_cross_section - (struct salgae_estimator* estimator, - struct salgae_estimator_status* status); - -SALGAE_API res_T -salgae_estimator_get_absorption_cross_section - (struct salgae_estimator* estimator, - struct salgae_estimator_status* status); - -SALGAE_API res_T -salgae_estimator_get_phase_function - (struct salgae_estimator* estimator, - const size_t iscattering_angle, - struct salgae_estimator_status* status); - -END_DECLS - -#endif /* SALGAE_H */ - diff --git a/src/salgae_device.c b/src/salgae_device.c @@ -1,143 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#include "salgae.h" -#include "salgae_device.h" - -#include <rsys/logger.h> -#include <rsys/mem_allocator.h> - -#include <star/s3d.h> - -#include <stdarg.h> - -/******************************************************************************* - * Helper function - ******************************************************************************/ -static void -device_release(ref_T* ref) -{ - struct salgae_device* dev; - ASSERT(ref); - dev = CONTAINER_OF(ref, struct salgae_device, ref); - if(dev) S3D(device_ref_put(dev->s3d)); - MEM_RM(dev->allocator, dev); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -void -log_error(struct salgae_device* dev, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(dev && msg); - if(dev->verbose) { - res_T res; (void)res; - va_start(vargs_list, msg); - res = logger_vprint(dev->logger, LOG_ERROR, msg, vargs_list); - ASSERT(res == RES_OK); - va_end(vargs_list); - } -} - - -/******************************************************************************* - * API functions - ******************************************************************************/ -res_T -salgae_device_create - (struct logger* log, - struct mem_allocator* allocator, - const int verbose, - struct s3d_device* s3d, - struct salgae_device** out_dev) -{ - struct mem_allocator* mem_allocator; - struct salgae_device* dev = NULL; - struct logger* logger = NULL; - res_T res = RES_OK; - - if(!out_dev) { - res = RES_BAD_ARG; - goto error; - } - - mem_allocator = allocator ? allocator : &mem_default_allocator; - logger = log ? log : LOGGER_DEFAULT; - - dev = MEM_CALLOC(mem_allocator, 1, sizeof(struct salgae_device)); - if(!dev) { - log_error(dev, "Couldn't allocate the Star-Algae device.\n"); - res = RES_MEM_ERR; - goto error; - } - ref_init(&dev->ref); - dev->allocator = mem_allocator; - dev->logger = logger; - dev->verbose = verbose; - - if(s3d) { - S3D(device_ref_get(s3d)); - dev->s3d = s3d; - } else { - res = s3d_device_create(dev->logger, dev->allocator, verbose, &dev->s3d); - if(res != RES_OK) { - log_error - (dev, "Couldn't create the internal Star-3D device of Star-Algea.\n"); - goto error; - } - } - -exit: - if(out_dev) *out_dev = dev; - return res; -error: - if(dev) { - SALGAE(device_ref_put(dev)); - dev = NULL; - } - goto exit; -} - -res_T -salgae_device_ref_get(struct salgae_device* dev) -{ - if(!dev) return RES_BAD_ARG; - ref_get(&dev->ref); - return RES_OK; -} - -res_T -salgae_device_ref_put(struct salgae_device* dev) -{ - if(!dev) return RES_BAD_ARG; - ref_put(&dev->ref, device_release); - return RES_OK; -} - diff --git a/src/salgae_device.h b/src/salgae_device.h @@ -1,57 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#ifndef SALGAE_DEVICE_H -#define SALGAE_DEVICE_H - -#include <rsys/ref_count.h> - -struct logger; -struct mem_allocator; -struct s3d_device; - -struct salgae_device { - int verbose; - struct logger* logger; - struct s3d_device* s3d; - - struct mem_allocator* allocator; - ref_T ref; -}; - -extern LOCAL_SYM void -log_error - (struct salgae_device* dev, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; -#endif /* SALGAE_DEVICE_H */ - diff --git a/src/salgae_estimator.c b/src/salgae_estimator.c @@ -1,395 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#include "salgae.h" -#include "salgae_device.h" - -#include <rsys/float2.h> -#include <rsys/float3.h> -#include <rsys/image.h> -#include <rsys/logger.h> -#include <rsys/mem_allocator.h> -#include <rsys/stretchy_array.h> - -#include <star/s3d.h> -#include <star/ssp.h> - -#define NDIRS 1 /* # Sampled directions */ - -struct salgae_estimator { - size_t nsteps; - double wavelength; - - struct salgae_device* dev; - ref_T ref; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static FINLINE uint16_t -morton2D_decode(const uint32_t u32) -{ - uint32_t x = u32 & 0x55555555; - x = (x | (x >> 1)) & 0x33333333; - x = (x | (x >> 2)) & 0x0F0F0F0F; - x = (x | (x >> 4)) & 0x00FF00FF; - x = (x | (x >> 8)) & 0x0000FFFF; - return (uint16_t)x; -} - -/* Compute an orthonormal basis where `dir' is the Z axis */ -static void -build_basis(const float dir[3], float basis[9]) -{ - float dir_abs[3]; - float axis_min[3]; - int i; - ASSERT(dir && basis && f3_is_normalized(dir)); - - /* Define which axis direction is minimal and use its unit vector to compute - * a vector ortogonal to `dir'. This ensures that the unit vector and `dir' - * are not colinear and thus that their cross product is not a zero vector */ - FOR_EACH(i, 0, 3) dir_abs[i] = absf(dir[i]); - if(dir_abs[0] < dir_abs[1]) { - if(dir_abs[0] < dir_abs[2]) f3(axis_min, 1.f, 0.f, 0.f); - else f3(axis_min, 0.f, 0.f, 1.f); - } else { - if(dir_abs[1] < dir_abs[2]) f3(axis_min, 0.f, 1.f, 0.f); - else f3(axis_min, 0.f, 0.f, 1.f); - } - - f3_normalize(basis + 0, f3_cross(basis + 0, dir, axis_min)); - f3_cross(basis + 3, dir, basis + 0); - f3_set(basis + 6, dir); -} - -/* Compute a 3x4 affine transformation from a orthonormal basis and the - * position of the origin */ -static FINLINE void -build_transform - (const float pos[3], /* Position of the origin */ - const float basis[9], /* Column major */ - float transform[12]) /* Column major */ -{ - ASSERT(pos && basis && transform); - - /* The linear part of the transformamatrix is the inverse of the - * orthonormal basis (i.e. its transpose) */ - f3(transform + 0, basis[0], basis[3], basis[6]); - f3(transform + 3, basis[1], basis[4], basis[7]); - f3(transform + 6, basis[2], basis[5], basis[8]); - - /* Affine part of the transform matrix */ - transform[9 ] = -f3_dot(basis+0, pos); - transform[10] = -f3_dot(basis+3, pos); - transform[11] = -f3_dot(basis+6, pos); -} - -/* Cast rays into the RT volume */ -static void -draw_thumbnail - (struct s3d_scene* scn, - const float basis[9], /* World space basis of the RT volume */ - const float pos[3], /* World space centroid of the RT volume */ - const float lower[3], /* Lower boundary of the RT volume */ - const float upper[3], /* Upper boundary of the RT volume */ - const char* name) /* Filename of the thumbnail */ -{ -#define DEFINITION 128 - STATIC_ASSERT(IS_POW2(DEFINITION), Invalid_thumbnail_definition); - const float range[2] = { 0, FLT_MAX }; - const float pixel_size = 1.f/(float)DEFINITION; - float axis_x[3], axis_y[3], axis_z[3]; - float plane_size[2]; - float ray_org[3]; - float org[3]; - uint32_t npixels = (uint32_t)(DEFINITION * DEFINITION); - uint32_t mcode; - unsigned char* img = NULL; - ASSERT(basis && pos && lower && upper); - - /* Allocate the thumbnail buffer */ - img = sa_add(img, DEFINITION*DEFINITION); - ASSERT(img != NULL); - - /* Define the projection axis */ - f2_sub(plane_size, upper, lower); - f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f); - f3_mulf(axis_y, basis + 3, plane_size[1] * 0.5f); - f3_set(axis_z, basis + 6); - - /* Compute the origin of the projection plane */ - f3_add(org, pos, f3_mulf(org, axis_z, lower[2])); - - FOR_EACH(mcode, 0, npixels) { - struct s3d_hit hit; - size_t ipixel; - float sample[2], x[3], y[3]; - uint16_t ipixel_x, ipixel_y; - - /* Compute the sample position in [0, 1)^2 onto the projection plane */ - ipixel_x = morton2D_decode(mcode); - ipixel_y = morton2D_decode(mcode>>1); - sample[0] = ((float)ipixel_x + 0.5f) * pixel_size; - sample[1] = ((float)ipixel_y + 0.5f) * pixel_size; - - /* Compute the ray origin */ - f3_mulf(x, axis_x, sample[0]*2.f - 1.f); - f3_mulf(y, axis_y, sample[1]*2.f - 1.f); - f3_add(ray_org, f3_add(ray_org, x, y), org); - - S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit)); - - /* Simple shading */ - ipixel = (size_t)(ipixel_y * DEFINITION + ipixel_x); - if(S3D_HIT_NONE(&hit)) { - img[ipixel] = 0; - } else { - float N[3] = {0.f,0.f,0.f}; - float cosine; - f3_normalize(N, hit.normal); - if(0 > (cosine = f3_dot(N, axis_z))) { - cosine = f3_dot(f3_minus(N, N), axis_z); - } - img[ipixel] = (unsigned char)(cosine*255.f + 0.5f/*Round*/); - } - } - image_ppm_write(name, DEFINITION, DEFINITION, 1, img); - sa_release(img); -#undef DEFINITION -} - -static res_T -radiative_path_length - (struct salgae_device* dev, - struct ssp_rng* rng, - struct salgae_integrator_desc* desc, - const int istep) -{ - struct s3d_shape* shape = NULL; - struct s3d_scene* scene = NULL; - struct salgae_material material = SALGAE_NULL_MATERIAL; - int idir; - res_T res = RES_OK; - ASSERT(dev && rng && desc); - - res = s3d_shape_create_mesh(dev->s3d, &shape); - if(res != RES_OK) { - log_error(dev, "Couldn't create the Star-3D Algae shape.\n"); - goto error; - } - res = s3d_scene_create(dev->s3d, &scene); - if(res != RES_OK) { - log_error(dev, "Couldn't create the Star-3D Algae scene.\n"); - goto error; - } - res = s3d_scene_attach_shape(scene, shape); - if(res != RES_OK) { - log_error(dev, - "Couldn't attach the Star-3D Algae shape to the Star-3D Algae scene.\n"); - goto error; - } - - res = desc->sample_geometry(rng, &material, shape, desc->sampler_context); - if(res != RES_OK) { - log_error(dev, "Error in sampling an Algea geometry.\n"); - goto error; - } - - S3D(scene_begin_session(scene, S3D_TRACE)); - FOR_EACH(idir, 0, NDIRS) { - char thumb_name[64]; - float dir[4]; - float centroid[3]; - float basis[9]; - float lower[3], upper[3]; - float transform[12]; - float pt[8][3]; - int i; - - ssp_ran_sphere_uniform(rng, dir); - S3D(scene_get_aabb(scene, lower, upper)); - - /* AABB vertex layout - * 6-------7 - * /' /| - * 2-------3 | - * | 4.....|.5 - * |, |/ - * 0-------1 */ - f3(pt[0], lower[0], lower[1], lower[2]); - f3(pt[1], upper[0], lower[1], lower[2]); - f3(pt[2], lower[0], upper[1], lower[2]); - f3(pt[3], upper[0], upper[1], lower[2]); - f3(pt[4], lower[0], lower[1], upper[2]); - f3(pt[5], upper[0], lower[1], upper[2]); - f3(pt[6], lower[0], upper[1], upper[2]); - f3(pt[7], upper[0], upper[1], upper[2]); - - /* Build the transformation matrix from world to footprint space. Use the - * AABB centroid as the origin of the footprint space. */ - f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); - build_basis(dir, basis); - build_transform(centroid, basis, transform); - - /* Transform the AABB from world to footprint space */ - FOR_EACH(i, 0, 8) { - f3_add(pt[i], f33_mulf3(pt[i], transform, pt[i]), transform + 9); - } - - /* Compute the AABB of the footprint */ - f3_splat(lower, FLT_MAX); f3_splat(upper,-FLT_MAX); - FOR_EACH(i, 0, 8) { - f3_min(lower, lower, pt[i]); - f3_max(upper, upper, pt[i]); - } - - /* Compute an image of the shape transformed in the footprint space */ - sprintf(thumb_name, "%d_%d.ppm", istep, idir); - draw_thumbnail(scene, basis, centroid, lower, upper, thumb_name); - } - S3D(scene_end_session(scene)); - -exit: - if(scene) S3D(scene_ref_put(scene)); - if(shape) S3D(shape_ref_put(shape)); - return res; -error: - goto exit; -} - -static char -check_desc(struct salgae_integrator_desc* desc) -{ - ASSERT(desc); - return desc->sample_geometry - && desc->scattering_angles_count; -} - -static void -estimator_release(ref_T* ref) -{ - struct salgae_estimator* estimator; - struct salgae_device* dev; - ASSERT(ref); - estimator = CONTAINER_OF(ref, struct salgae_estimator, ref); - dev = estimator->dev; - MEM_RM(dev->allocator, estimator); - SALGAE(device_ref_put(dev)); -} - -static res_T -estimator_create - (struct salgae_device* dev, struct salgae_estimator** out_estimator) -{ - struct salgae_estimator* estimator = NULL; - res_T res = RES_OK; - ASSERT(dev && out_estimator); - - estimator = MEM_CALLOC(dev->allocator, 1, sizeof(struct salgae_estimator)); - if(!estimator) { - log_error - (dev, "Not enough memory: couldn't allocate the Star-Algea estimator.\n"); - res = RES_MEM_ERR; - goto error; - } - ref_init(&estimator->ref); - SALGAE(device_ref_get(dev)); - estimator->dev = dev; - -exit: - *out_estimator = estimator; - return res; -error: - if(estimator) { - SALGAE(estimator_ref_put(estimator)); - estimator = NULL; - } - goto exit; -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -salgae_integrate - (struct salgae_device* dev, - struct ssp_rng* rng, - struct salgae_integrator_desc* desc, - const double wavelength, /* Wavelength to integrate */ - const size_t steps_count, /* #realisations */ - struct salgae_estimator** out_estimator) -{ - struct salgae_estimator* estimator = NULL; - int i; - res_T res = RES_OK; - - if(!dev || !rng || !desc || !check_desc(desc) || wavelength < 0.0 - || !steps_count || !out_estimator) { - res = RES_BAD_ARG; - goto error; - } - - res = estimator_create(dev, &estimator); - if(res != RES_OK) goto error; - estimator->nsteps = steps_count; - estimator->wavelength = wavelength; - - FOR_EACH(i, 0, (int)steps_count) { - res = radiative_path_length(dev, rng, desc, i); - if(res != RES_OK) goto error; - } - -exit: - if(out_estimator) *out_estimator = estimator; - return res; -error: - if(estimator) { - SALGAE(estimator_ref_put(estimator)); - estimator = NULL; - } - goto exit; -} - -res_T -salgae_estimator_ref_get(struct salgae_estimator* estimator) -{ - if(!estimator) return RES_BAD_ARG; - ref_get(&estimator->ref); - return RES_OK; -} - -res_T -salgae_estimator_ref_put(struct salgae_estimator* estimator) -{ - if(!estimator) return RES_BAD_ARG; - ref_put(&estimator->ref, estimator_release); - return RES_OK; -} - diff --git a/src/sschiff.h b/src/sschiff.h @@ -0,0 +1,155 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#ifndef SSCHIFF_H +#define SSCHIFF_H + +#include <rsys/rsys.h> + +/* Library symbol management */ +#if defined(SSCHIFF_SHARED_BUILD) /* Build shared library */ + #define SSCHIFF_API extern EXPORT_SYM +#elif defined(SSCHIFF_STATIC) /* Use/build static library */ + #define SSCHIFF_API extern LOCAL_SYM +#else /* Use shared library */ + #define SSCHIFF_API extern IMPORT_SYM +#endif + +/* Helper macro that asserts if the invocation of the sgf function `Func' + * returns an error. One should use this macro on sschiff function calls for + * which no explicit error checking is performed */ +#ifndef NDEBUG + #define SSCHIFF(Func) ASSERT(sschiff_ ## Func == RES_OK) +#else + #define SSCHIFF(Func) sschiff_ ## Func +#endif + +/* Forward declaration of external types */ +struct mem_allocator; +struct logger; +struct s3d_device; +struct s3d_shape; +struct ssp_rng; + +struct sschiff_refractive_index { double real, imag; }; + +struct sschiff_material { + /* Retrieve the refractive complex index of the material */ + void (*get_refractive_index) + (void* material, + const double wavelength, + struct sschiff_refractive_index* value); + void* material; /* Opaque user defined representation of the material */ +}; + +static const struct sschiff_material SSCHIFF_NULL_MATERIAL = { NULL, NULL }; + +struct sschiff_integrator_desc { + res_T (*sample_geometry) /* Sample a geometry i.e. a shape and its material */ + (struct ssp_rng* rng, + struct sschiff_material* mtl, /* Sampled material */ + struct s3d_shape* shape, /* Sampled shape */ + void* sampler_context); + void* sampler_context; + size_t scattering_angles_count; /* # of scattering angles to handle */ +}; + +static const struct sschiff_integrator_desc SSCHIFF_NULL_INTEGRATOR_DESC = { + NULL, NULL, 0 +}; + +/* Result of the Monte Carlo estimation */ +struct sschiff_estimator_status { + double E; /* Expected value */ + double V; /* Variance */ + double SE; /* Standard error */ + size_t nsteps; +}; + +/* Opaque types */ +struct sschiff_device; +struct sschiff_estimator; + +/******************************************************************************* + * Star Schiff API + ******************************************************************************/ +BEGIN_DECLS + +SSCHIFF_API res_T +sschiff_device_create + (struct logger* logger, /* May be NULL <=> use default logger */ + struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const int verbose, + struct s3d_device* s3d, /* May be NULL <=> internally create a S3D device */ + struct sschiff_device** dev); + +SSCHIFF_API res_T +sschiff_device_ref_get + (struct sschiff_device* dev); + +SSCHIFF_API res_T +sschiff_device_ref_put + (struct sschiff_device* dev); + +SSCHIFF_API res_T +sschiff_integrate + (struct sschiff_device* dev, + struct ssp_rng* rng, + struct sschiff_integrator_desc* desc, + const double wavelength, /* Wavelength to integrate */ + const size_t steps_count, /* #realisations */ + struct sschiff_estimator** estimator); + +SSCHIFF_API res_T +sschiff_estimator_ref_get + (struct sschiff_estimator* estimator); + +SSCHIFF_API res_T +sschiff_estimator_ref_put + (struct sschiff_estimator* estimator); + +SSCHIFF_API res_T +sschiff_estimator_get_extinction_cross_section + (struct sschiff_estimator* estimator, + struct sschiff_estimator_status* status); + +SSCHIFF_API res_T +sschiff_estimator_get_absorption_cross_section + (struct sschiff_estimator* estimator, + struct sschiff_estimator_status* status); + +SSCHIFF_API res_T +sschiff_estimator_get_phase_function + (struct sschiff_estimator* estimator, + const size_t iscattering_angle, + struct sschiff_estimator_status* status); + +END_DECLS + +#endif /* SSCHIFF_H */ + diff --git a/src/sschiff_device.c b/src/sschiff_device.c @@ -0,0 +1,143 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#include "sschiff.h" +#include "sschiff_device.h" + +#include <rsys/logger.h> +#include <rsys/mem_allocator.h> + +#include <star/s3d.h> + +#include <stdarg.h> + +/******************************************************************************* + * Helper function + ******************************************************************************/ +static void +device_release(ref_T* ref) +{ + struct sschiff_device* dev; + ASSERT(ref); + dev = CONTAINER_OF(ref, struct sschiff_device, ref); + if(dev) S3D(device_ref_put(dev->s3d)); + MEM_RM(dev->allocator, dev); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +void +log_error(struct sschiff_device* dev, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(dev && msg); + if(dev->verbose) { + res_T res; (void)res; + va_start(vargs_list, msg); + res = logger_vprint(dev->logger, LOG_ERROR, msg, vargs_list); + ASSERT(res == RES_OK); + va_end(vargs_list); + } +} + + +/******************************************************************************* + * API functions + ******************************************************************************/ +res_T +sschiff_device_create + (struct logger* log, + struct mem_allocator* allocator, + const int verbose, + struct s3d_device* s3d, + struct sschiff_device** out_dev) +{ + struct mem_allocator* mem_allocator; + struct sschiff_device* dev = NULL; + struct logger* logger = NULL; + res_T res = RES_OK; + + if(!out_dev) { + res = RES_BAD_ARG; + goto error; + } + + mem_allocator = allocator ? allocator : &mem_default_allocator; + logger = log ? log : LOGGER_DEFAULT; + + dev = MEM_CALLOC(mem_allocator, 1, sizeof(struct sschiff_device)); + if(!dev) { + log_error(dev, "Couldn't allocate the Star-Schiff device.\n"); + res = RES_MEM_ERR; + goto error; + } + ref_init(&dev->ref); + dev->allocator = mem_allocator; + dev->logger = logger; + dev->verbose = verbose; + + if(s3d) { + S3D(device_ref_get(s3d)); + dev->s3d = s3d; + } else { + res = s3d_device_create(dev->logger, dev->allocator, verbose, &dev->s3d); + if(res != RES_OK) { + log_error + (dev, "Couldn't create the internal Star-3D device of Star-Schiff.\n"); + goto error; + } + } + +exit: + if(out_dev) *out_dev = dev; + return res; +error: + if(dev) { + SSCHIFF(device_ref_put(dev)); + dev = NULL; + } + goto exit; +} + +res_T +sschiff_device_ref_get(struct sschiff_device* dev) +{ + if(!dev) return RES_BAD_ARG; + ref_get(&dev->ref); + return RES_OK; +} + +res_T +sschiff_device_ref_put(struct sschiff_device* dev) +{ + if(!dev) return RES_BAD_ARG; + ref_put(&dev->ref, device_release); + return RES_OK; +} + diff --git a/src/sschiff_device.h b/src/sschiff_device.h @@ -0,0 +1,57 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#ifndef SSCHIFF_DEVICE_H +#define SSCHIFF_DEVICE_H + +#include <rsys/ref_count.h> + +struct logger; +struct mem_allocator; +struct s3d_device; + +struct sschiff_device { + int verbose; + struct logger* logger; + struct s3d_device* s3d; + + struct mem_allocator* allocator; + ref_T ref; +}; + +extern LOCAL_SYM void +log_error + (struct sschiff_device* dev, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; +#endif /* SSCHIFF_DEVICE_H */ + diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c @@ -0,0 +1,395 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#include "sschiff.h" +#include "sschiff_device.h" + +#include <rsys/float2.h> +#include <rsys/float3.h> +#include <rsys/image.h> +#include <rsys/logger.h> +#include <rsys/mem_allocator.h> +#include <rsys/stretchy_array.h> + +#include <star/s3d.h> +#include <star/ssp.h> + +#define NDIRS 1 /* # Sampled directions */ + +struct sschiff_estimator { + size_t nsteps; + double wavelength; + + struct sschiff_device* dev; + ref_T ref; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static FINLINE uint16_t +morton2D_decode(const uint32_t u32) +{ + uint32_t x = u32 & 0x55555555; + x = (x | (x >> 1)) & 0x33333333; + x = (x | (x >> 2)) & 0x0F0F0F0F; + x = (x | (x >> 4)) & 0x00FF00FF; + x = (x | (x >> 8)) & 0x0000FFFF; + return (uint16_t)x; +} + +/* Compute an orthonormal basis where `dir' is the Z axis */ +static void +build_basis(const float dir[3], float basis[9]) +{ + float dir_abs[3]; + float axis_min[3]; + int i; + ASSERT(dir && basis && f3_is_normalized(dir)); + + /* Define which axis direction is minimal and use its unit vector to compute + * a vector ortogonal to `dir'. This ensures that the unit vector and `dir' + * are not colinear and thus that their cross product is not a zero vector */ + FOR_EACH(i, 0, 3) dir_abs[i] = absf(dir[i]); + if(dir_abs[0] < dir_abs[1]) { + if(dir_abs[0] < dir_abs[2]) f3(axis_min, 1.f, 0.f, 0.f); + else f3(axis_min, 0.f, 0.f, 1.f); + } else { + if(dir_abs[1] < dir_abs[2]) f3(axis_min, 0.f, 1.f, 0.f); + else f3(axis_min, 0.f, 0.f, 1.f); + } + + f3_normalize(basis + 0, f3_cross(basis + 0, dir, axis_min)); + f3_cross(basis + 3, dir, basis + 0); + f3_set(basis + 6, dir); +} + +/* Compute a 3x4 affine transformation from a orthonormal basis and the + * position of the origin */ +static FINLINE void +build_transform + (const float pos[3], /* Position of the origin */ + const float basis[9], /* Column major */ + float transform[12]) /* Column major */ +{ + ASSERT(pos && basis && transform); + + /* The linear part of the transformamatrix is the inverse of the + * orthonormal basis (i.e. its transpose) */ + f3(transform + 0, basis[0], basis[3], basis[6]); + f3(transform + 3, basis[1], basis[4], basis[7]); + f3(transform + 6, basis[2], basis[5], basis[8]); + + /* Affine part of the transform matrix */ + transform[9 ] = -f3_dot(basis+0, pos); + transform[10] = -f3_dot(basis+3, pos); + transform[11] = -f3_dot(basis+6, pos); +} + +/* Cast rays into the RT volume */ +static void +draw_thumbnail + (struct s3d_scene* scn, + const float basis[9], /* World space basis of the RT volume */ + const float pos[3], /* World space centroid of the RT volume */ + const float lower[3], /* Lower boundary of the RT volume */ + const float upper[3], /* Upper boundary of the RT volume */ + const char* name) /* Filename of the thumbnail */ +{ +#define DEFINITION 128 + STATIC_ASSERT(IS_POW2(DEFINITION), Invalid_thumbnail_definition); + const float range[2] = { 0, FLT_MAX }; + const float pixel_size = 1.f/(float)DEFINITION; + float axis_x[3], axis_y[3], axis_z[3]; + float plane_size[2]; + float ray_org[3]; + float org[3]; + uint32_t npixels = (uint32_t)(DEFINITION * DEFINITION); + uint32_t mcode; + unsigned char* img = NULL; + ASSERT(basis && pos && lower && upper); + + /* Allocate the thumbnail buffer */ + img = sa_add(img, DEFINITION*DEFINITION); + ASSERT(img != NULL); + + /* Define the projection axis */ + f2_sub(plane_size, upper, lower); + f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f); + f3_mulf(axis_y, basis + 3, plane_size[1] * 0.5f); + f3_set(axis_z, basis + 6); + + /* Compute the origin of the projection plane */ + f3_add(org, pos, f3_mulf(org, axis_z, lower[2])); + + FOR_EACH(mcode, 0, npixels) { + struct s3d_hit hit; + size_t ipixel; + float sample[2], x[3], y[3]; + uint16_t ipixel_x, ipixel_y; + + /* Compute the sample position in [0, 1)^2 onto the projection plane */ + ipixel_x = morton2D_decode(mcode); + ipixel_y = morton2D_decode(mcode>>1); + sample[0] = ((float)ipixel_x + 0.5f) * pixel_size; + sample[1] = ((float)ipixel_y + 0.5f) * pixel_size; + + /* Compute the ray origin */ + f3_mulf(x, axis_x, sample[0]*2.f - 1.f); + f3_mulf(y, axis_y, sample[1]*2.f - 1.f); + f3_add(ray_org, f3_add(ray_org, x, y), org); + + S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit)); + + /* Simple shading */ + ipixel = (size_t)(ipixel_y * DEFINITION + ipixel_x); + if(S3D_HIT_NONE(&hit)) { + img[ipixel] = 0; + } else { + float N[3] = {0.f,0.f,0.f}; + float cosine; + f3_normalize(N, hit.normal); + if(0 > (cosine = f3_dot(N, axis_z))) { + cosine = f3_dot(f3_minus(N, N), axis_z); + } + img[ipixel] = (unsigned char)(cosine*255.f + 0.5f/*Round*/); + } + } + image_ppm_write(name, DEFINITION, DEFINITION, 1, img); + sa_release(img); +#undef DEFINITION +} + +static res_T +radiative_path_length + (struct sschiff_device* dev, + struct ssp_rng* rng, + struct sschiff_integrator_desc* desc, + const int istep) +{ + struct s3d_shape* shape = NULL; + struct s3d_scene* scene = NULL; + struct sschiff_material material = SSCHIFF_NULL_MATERIAL; + int idir; + res_T res = RES_OK; + ASSERT(dev && rng && desc); + + res = s3d_shape_create_mesh(dev->s3d, &shape); + if(res != RES_OK) { + log_error(dev, "Couldn't create the Star-3D Schiff shape.\n"); + goto error; + } + res = s3d_scene_create(dev->s3d, &scene); + if(res != RES_OK) { + log_error(dev, "Couldn't create the Star-3D Schiff scene.\n"); + goto error; + } + res = s3d_scene_attach_shape(scene, shape); + if(res != RES_OK) { + log_error(dev, + "Couldn't attach the Star-3D Schiff shape to the Star-3D Schiff scene.\n"); + goto error; + } + + res = desc->sample_geometry(rng, &material, shape, desc->sampler_context); + if(res != RES_OK) { + log_error(dev, "Error in sampling a Schiff geometry.\n"); + goto error; + } + + S3D(scene_begin_session(scene, S3D_TRACE)); + FOR_EACH(idir, 0, NDIRS) { + char thumb_name[64]; + float dir[4]; + float centroid[3]; + float basis[9]; + float lower[3], upper[3]; + float transform[12]; + float pt[8][3]; + int i; + + ssp_ran_sphere_uniform(rng, dir); + S3D(scene_get_aabb(scene, lower, upper)); + + /* AABB vertex layout + * 6-------7 + * /' /| + * 2-------3 | + * | 4.....|.5 + * |, |/ + * 0-------1 */ + f3(pt[0], lower[0], lower[1], lower[2]); + f3(pt[1], upper[0], lower[1], lower[2]); + f3(pt[2], lower[0], upper[1], lower[2]); + f3(pt[3], upper[0], upper[1], lower[2]); + f3(pt[4], lower[0], lower[1], upper[2]); + f3(pt[5], upper[0], lower[1], upper[2]); + f3(pt[6], lower[0], upper[1], upper[2]); + f3(pt[7], upper[0], upper[1], upper[2]); + + /* Build the transformation matrix from world to footprint space. Use the + * AABB centroid as the origin of the footprint space. */ + f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); + build_basis(dir, basis); + build_transform(centroid, basis, transform); + + /* Transform the AABB from world to footprint space */ + FOR_EACH(i, 0, 8) { + f3_add(pt[i], f33_mulf3(pt[i], transform, pt[i]), transform + 9); + } + + /* Compute the AABB of the footprint */ + f3_splat(lower, FLT_MAX); f3_splat(upper,-FLT_MAX); + FOR_EACH(i, 0, 8) { + f3_min(lower, lower, pt[i]); + f3_max(upper, upper, pt[i]); + } + + /* Compute an image of the shape transformed in the footprint space */ + sprintf(thumb_name, "%d_%d.ppm", istep, idir); + draw_thumbnail(scene, basis, centroid, lower, upper, thumb_name); + } + S3D(scene_end_session(scene)); + +exit: + if(scene) S3D(scene_ref_put(scene)); + if(shape) S3D(shape_ref_put(shape)); + return res; +error: + goto exit; +} + +static char +check_desc(struct sschiff_integrator_desc* desc) +{ + ASSERT(desc); + return desc->sample_geometry + && desc->scattering_angles_count; +} + +static void +estimator_release(ref_T* ref) +{ + struct sschiff_estimator* estimator; + struct sschiff_device* dev; + ASSERT(ref); + estimator = CONTAINER_OF(ref, struct sschiff_estimator, ref); + dev = estimator->dev; + MEM_RM(dev->allocator, estimator); + SSCHIFF(device_ref_put(dev)); +} + +static res_T +estimator_create + (struct sschiff_device* dev, struct sschiff_estimator** out_estimator) +{ + struct sschiff_estimator* estimator = NULL; + res_T res = RES_OK; + ASSERT(dev && out_estimator); + + estimator = MEM_CALLOC(dev->allocator, 1, sizeof(struct sschiff_estimator)); + if(!estimator) { + log_error + (dev, "Not enough memory: couldn't allocate the Star-Schiff estimator.\n"); + res = RES_MEM_ERR; + goto error; + } + ref_init(&estimator->ref); + SSCHIFF(device_ref_get(dev)); + estimator->dev = dev; + +exit: + *out_estimator = estimator; + return res; +error: + if(estimator) { + SSCHIFF(estimator_ref_put(estimator)); + estimator = NULL; + } + goto exit; +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sschiff_integrate + (struct sschiff_device* dev, + struct ssp_rng* rng, + struct sschiff_integrator_desc* desc, + const double wavelength, /* Wavelength to integrate */ + const size_t steps_count, /* #realisations */ + struct sschiff_estimator** out_estimator) +{ + struct sschiff_estimator* estimator = NULL; + int i; + res_T res = RES_OK; + + if(!dev || !rng || !desc || !check_desc(desc) || wavelength < 0.0 + || !steps_count || !out_estimator) { + res = RES_BAD_ARG; + goto error; + } + + res = estimator_create(dev, &estimator); + if(res != RES_OK) goto error; + estimator->nsteps = steps_count; + estimator->wavelength = wavelength; + + FOR_EACH(i, 0, (int)steps_count) { + res = radiative_path_length(dev, rng, desc, i); + if(res != RES_OK) goto error; + } + +exit: + if(out_estimator) *out_estimator = estimator; + return res; +error: + if(estimator) { + SSCHIFF(estimator_ref_put(estimator)); + estimator = NULL; + } + goto exit; +} + +res_T +sschiff_estimator_ref_get(struct sschiff_estimator* estimator) +{ + if(!estimator) return RES_BAD_ARG; + ref_get(&estimator->ref); + return RES_OK; +} + +res_T +sschiff_estimator_ref_put(struct sschiff_estimator* estimator) +{ + if(!estimator) return RES_BAD_ARG; + ref_put(&estimator->ref, estimator_release); + return RES_OK; +} + diff --git a/src/test_salgae_device.c b/src/test_salgae_device.c @@ -1,98 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#include "salgae.h" -#include "test_salgae_utils.h" - -#include <rsys/logger.h> -#include <rsys/mem_allocator.h> -#include <rsys/rsys.h> - -#include <star/s3d.h> - -static void -log_stream(const char* msg, void* ctx) -{ - ASSERT(msg); - (void)msg, (void)ctx; - printf("%s\n", msg); -} - -int -main(int argc, char** argv) -{ - struct logger logger; - struct mem_allocator allocator; - struct salgae_device* dev; - struct s3d_device* s3d; - (void)argc, (void)argv; - - CHECK(salgae_device_create(NULL, NULL, 0, NULL, NULL), RES_BAD_ARG); - CHECK(salgae_device_create(NULL, NULL, 0, NULL, &dev), RES_OK); - - CHECK(salgae_device_ref_get(NULL), RES_BAD_ARG); - CHECK(salgae_device_ref_get(dev), RES_OK); - CHECK(salgae_device_ref_put(NULL), RES_BAD_ARG); - CHECK(salgae_device_ref_put(dev), RES_OK); - CHECK(salgae_device_ref_put(dev), RES_OK); - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - - CHECK(MEM_ALLOCATED_SIZE(&allocator), 0); - CHECK(salgae_device_create(NULL, &allocator, 1, NULL, NULL), RES_BAD_ARG); - CHECK(salgae_device_create(NULL, &allocator, 1, NULL, &dev), RES_OK); - CHECK(salgae_device_ref_put(dev), RES_OK); - CHECK(MEM_ALLOCATED_SIZE(&allocator), 0); - - CHECK(logger_init(&allocator, &logger), RES_OK); - logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); - logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); - logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); - - CHECK(salgae_device_create(&logger, NULL, 0, NULL, NULL), RES_BAD_ARG); - CHECK(salgae_device_create(&logger, NULL, 0, NULL, &dev), RES_OK); - CHECK(salgae_device_ref_put(dev), RES_OK); - - CHECK(salgae_device_create(&logger, &allocator, 1, NULL, NULL), RES_BAD_ARG); - CHECK(salgae_device_create(&logger, &allocator, 1, NULL, &dev), RES_OK); - CHECK(salgae_device_ref_put(dev), RES_OK); - - CHECK(s3d_device_create(NULL, NULL, 0, &s3d), RES_OK); - CHECK(salgae_device_create(NULL, NULL, 0, s3d, NULL), RES_BAD_ARG); - CHECK(salgae_device_create(NULL, NULL, 0, s3d, &dev), RES_OK); - - CHECK(s3d_device_ref_put(s3d), RES_OK); - CHECK(salgae_device_ref_put(dev), RES_OK); - - logger_release(&logger); - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); - return 0; -} - diff --git a/src/test_salgae_estimator.c b/src/test_salgae_estimator.c @@ -1,203 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#include "salgae.h" -#include "test_salgae_utils.h" - -#include <rsys/float3.h> - -#include <star/s3d.h> -#include <star/ssp.h> - -#define STEP 0.05f - -enum { A, B, M, N0, N1, N2 }; - -struct super_shape { - float super_formulas[2][6]; - size_t ntheta, nphi; -}; - -static void -super_shape_get_indices(const unsigned itri, unsigned ids[3], void* ctx) -{ - struct super_shape* sshape = ctx; - const size_t iquad = itri / 2; - const size_t iquad_tri = itri % 2; - const size_t i = iquad / (sshape->nphi - 1); - const size_t j = iquad % (sshape->nphi - 1); - size_t A, B; - - B = i * sshape->nphi + j + 1; - A = ((i + 1) % sshape->ntheta) * sshape->nphi + j; - if(iquad_tri == 0) { - ids[0] = (unsigned)B - 1; - ids[1] = (unsigned)A; - ids[2] = (unsigned)B; - } else { ASSERT(iquad_tri == 1); - ids[0] = (unsigned)B; - ids[1] = (unsigned)A; - ids[2] = (unsigned)A + 1; - } -} - -static void -super_shape_get_vertex_position(const unsigned ivert, float vertex[3], void* ctx) -{ - struct super_shape* sshape = ctx; - const size_t itheta = ivert / sshape->nphi; - const size_t iphi = ivert % sshape->nphi; - double angle[2]; - double sin_angle[2]; - double cos_angle[2]; - double uv[2]; - int iform; - ASSERT(itheta < sshape->ntheta); - - if(iphi == sshape->nphi - 1) { /* Polar vertices: Force polar coordinates */ - angle[0] = PI; - angle[1] = PI/2; - } else { - angle[0] = -PI + (double)itheta * STEP; - angle[1] = -PI/2 + (double)iphi * STEP; - } - - FOR_EACH(iform, 0, 2) { - double m, k, g; - float* form = sshape->super_formulas[iform]; - m = cos(form[M] * angle[iform] / 4.0); - m = fabs(m) / form[A]; - k = sin(form[M] * angle[iform] / 4.0); - k = fabs(k) / form[B]; - g = pow(m, form[N1]) + pow(k, form[N2]); - uv[iform] = pow(g, (-1.0/form[N0])); - - cos_angle[iform] = cos(angle[iform]); - sin_angle[iform] = sin(angle[iform]); - } - - vertex[0] = (float)(uv[0] * cos_angle[0] * uv[1] * cos_angle[1]); - vertex[1] = (float)(uv[0] * sin_angle[0] * uv[1] * cos_angle[1]); - vertex[2] = (float)(uv[1] * sin_angle[1]); -} - -static res_T -sample_geometry - (struct ssp_rng* rng, - struct salgae_material* mtl, - struct s3d_shape* shape, - void* sampler_context) -{ - struct s3d_vertex_data attrib; - struct super_shape sshape; - const size_t ntheta = (int)((2*PI)/STEP) + 1; - const size_t nphi = (int)((PI)/STEP) + 1; - const size_t nverts = ntheta * nphi; - const size_t nprims = ntheta * (nphi - 1)/*#quads*/ * 2/*#triangles*/; - - (void)sampler_context; - - NCHECK(rng, NULL); - NCHECK(mtl, NULL); - NCHECK(shape, NULL); - - attrib.usage = S3D_POSITION; - attrib.type = S3D_FLOAT3; - attrib.get = super_shape_get_vertex_position; - - sshape.super_formulas[0][A] = 1; - sshape.super_formulas[0][B] = 1; - sshape.super_formulas[0][M] = (float)ssp_rng_uniform_double(rng, 0.1, 6); - sshape.super_formulas[0][N0] = 1; - sshape.super_formulas[0][N1] = 1; - sshape.super_formulas[0][N2] = (float)ssp_rng_uniform_double(rng, 0.1, 6); - - sshape.super_formulas[1][A] = 1; - sshape.super_formulas[1][B] = 1; - sshape.super_formulas[1][M] = (float)ssp_rng_uniform_double(rng, 0.1, 6); - sshape.super_formulas[1][N0] = 1; - sshape.super_formulas[1][N1] = 1; - sshape.super_formulas[1][N2] = (float)ssp_rng_uniform_double(rng, 0.1, 6); - - sshape.ntheta = ntheta; - sshape.nphi = nphi; - - *mtl = SALGAE_NULL_MATERIAL; - return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, - super_shape_get_indices, (unsigned)nverts, &attrib, 1, &sshape); -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct salgae_device* dev; - struct salgae_estimator* estimator; - struct salgae_integrator_desc desc = SALGAE_NULL_INTEGRATOR_DESC; - struct ssp_rng* rng; - (void)argc, (void)argv; - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - - CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(salgae_device_create(NULL, &allocator, 0, NULL, &dev), RES_OK); - - desc.sample_geometry = sample_geometry; - desc.scattering_angles_count = 1; - CHECK(salgae_integrate(NULL, NULL, NULL, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(dev, NULL, NULL, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, rng, NULL, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(dev, rng, NULL, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, NULL, &desc, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(dev, NULL, &desc, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, rng, &desc, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(dev, rng, &desc, 0, 0, NULL), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, NULL, NULL, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(dev, NULL, NULL, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, rng, NULL, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(dev, rng, NULL, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, NULL, &desc, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(dev, NULL, &desc, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(NULL, rng, &desc, 0, 1, &estimator), RES_BAD_ARG); - CHECK(salgae_integrate(dev, rng, &desc, 0, 100, &estimator), RES_OK); - - CHECK(salgae_estimator_ref_get(NULL), RES_BAD_ARG); - CHECK(salgae_estimator_ref_get(estimator), RES_OK); - CHECK(salgae_estimator_ref_put(NULL), RES_BAD_ARG); - CHECK(salgae_estimator_ref_put(estimator), RES_OK); - CHECK(salgae_estimator_ref_put(estimator), RES_OK); - - CHECK(salgae_device_ref_put(dev), RES_OK); - CHECK(ssp_rng_ref_put(rng), RES_OK); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); - return 0; -} - diff --git a/src/test_sschiff_device.c b/src/test_sschiff_device.c @@ -0,0 +1,98 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#include "sschiff.h" +#include "test_sschiff_utils.h" + +#include <rsys/logger.h> +#include <rsys/mem_allocator.h> +#include <rsys/rsys.h> + +#include <star/s3d.h> + +static void +log_stream(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)msg, (void)ctx; + printf("%s\n", msg); +} + +int +main(int argc, char** argv) +{ + struct logger logger; + struct mem_allocator allocator; + struct sschiff_device* dev; + struct s3d_device* s3d; + (void)argc, (void)argv; + + CHECK(sschiff_device_create(NULL, NULL, 0, NULL, NULL), RES_BAD_ARG); + CHECK(sschiff_device_create(NULL, NULL, 0, NULL, &dev), RES_OK); + + CHECK(sschiff_device_ref_get(NULL), RES_BAD_ARG); + CHECK(sschiff_device_ref_get(dev), RES_OK); + CHECK(sschiff_device_ref_put(NULL), RES_BAD_ARG); + CHECK(sschiff_device_ref_put(dev), RES_OK); + CHECK(sschiff_device_ref_put(dev), RES_OK); + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + CHECK(MEM_ALLOCATED_SIZE(&allocator), 0); + CHECK(sschiff_device_create(NULL, &allocator, 1, NULL, NULL), RES_BAD_ARG); + CHECK(sschiff_device_create(NULL, &allocator, 1, NULL, &dev), RES_OK); + CHECK(sschiff_device_ref_put(dev), RES_OK); + CHECK(MEM_ALLOCATED_SIZE(&allocator), 0); + + CHECK(logger_init(&allocator, &logger), RES_OK); + logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); + logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); + logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); + + CHECK(sschiff_device_create(&logger, NULL, 0, NULL, NULL), RES_BAD_ARG); + CHECK(sschiff_device_create(&logger, NULL, 0, NULL, &dev), RES_OK); + CHECK(sschiff_device_ref_put(dev), RES_OK); + + CHECK(sschiff_device_create(&logger, &allocator, 1, NULL, NULL), RES_BAD_ARG); + CHECK(sschiff_device_create(&logger, &allocator, 1, NULL, &dev), RES_OK); + CHECK(sschiff_device_ref_put(dev), RES_OK); + + CHECK(s3d_device_create(NULL, NULL, 0, &s3d), RES_OK); + CHECK(sschiff_device_create(NULL, NULL, 0, s3d, NULL), RES_BAD_ARG); + CHECK(sschiff_device_create(NULL, NULL, 0, s3d, &dev), RES_OK); + + CHECK(s3d_device_ref_put(s3d), RES_OK); + CHECK(sschiff_device_ref_put(dev), RES_OK); + + logger_release(&logger); + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/test_sschiff_estimator.c b/src/test_sschiff_estimator.c @@ -0,0 +1,203 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#include "sschiff.h" +#include "test_sschiff_utils.h" + +#include <rsys/float3.h> + +#include <star/s3d.h> +#include <star/ssp.h> + +#define STEP 0.05f + +enum { A, B, M, N0, N1, N2 }; + +struct super_shape { + float super_formulas[2][6]; + size_t ntheta, nphi; +}; + +static void +super_shape_get_indices(const unsigned itri, unsigned ids[3], void* ctx) +{ + struct super_shape* sshape = ctx; + const size_t iquad = itri / 2; + const size_t iquad_tri = itri % 2; + const size_t i = iquad / (sshape->nphi - 1); + const size_t j = iquad % (sshape->nphi - 1); + size_t A, B; + + B = i * sshape->nphi + j + 1; + A = ((i + 1) % sshape->ntheta) * sshape->nphi + j; + if(iquad_tri == 0) { + ids[0] = (unsigned)B - 1; + ids[1] = (unsigned)A; + ids[2] = (unsigned)B; + } else { ASSERT(iquad_tri == 1); + ids[0] = (unsigned)B; + ids[1] = (unsigned)A; + ids[2] = (unsigned)A + 1; + } +} + +static void +super_shape_get_vertex_position(const unsigned ivert, float vertex[3], void* ctx) +{ + struct super_shape* sshape = ctx; + const size_t itheta = ivert / sshape->nphi; + const size_t iphi = ivert % sshape->nphi; + double angle[2]; + double sin_angle[2]; + double cos_angle[2]; + double uv[2]; + int iform; + ASSERT(itheta < sshape->ntheta); + + if(iphi == sshape->nphi - 1) { /* Polar vertices: Force polar coordinates */ + angle[0] = PI; + angle[1] = PI/2; + } else { + angle[0] = -PI + (double)itheta * STEP; + angle[1] = -PI/2 + (double)iphi * STEP; + } + + FOR_EACH(iform, 0, 2) { + double m, k, g; + float* form = sshape->super_formulas[iform]; + m = cos(form[M] * angle[iform] / 4.0); + m = fabs(m) / form[A]; + k = sin(form[M] * angle[iform] / 4.0); + k = fabs(k) / form[B]; + g = pow(m, form[N1]) + pow(k, form[N2]); + uv[iform] = pow(g, (-1.0/form[N0])); + + cos_angle[iform] = cos(angle[iform]); + sin_angle[iform] = sin(angle[iform]); + } + + vertex[0] = (float)(uv[0] * cos_angle[0] * uv[1] * cos_angle[1]); + vertex[1] = (float)(uv[0] * sin_angle[0] * uv[1] * cos_angle[1]); + vertex[2] = (float)(uv[1] * sin_angle[1]); +} + +static res_T +sample_geometry + (struct ssp_rng* rng, + struct sschiff_material* mtl, + struct s3d_shape* shape, + void* sampler_context) +{ + struct s3d_vertex_data attrib; + struct super_shape sshape; + const size_t ntheta = (int)((2*PI)/STEP) + 1; + const size_t nphi = (int)((PI)/STEP) + 1; + const size_t nverts = ntheta * nphi; + const size_t nprims = ntheta * (nphi - 1)/*#quads*/ * 2/*#triangles*/; + + (void)sampler_context; + + NCHECK(rng, NULL); + NCHECK(mtl, NULL); + NCHECK(shape, NULL); + + attrib.usage = S3D_POSITION; + attrib.type = S3D_FLOAT3; + attrib.get = super_shape_get_vertex_position; + + sshape.super_formulas[0][A] = 1; + sshape.super_formulas[0][B] = 1; + sshape.super_formulas[0][M] = (float)ssp_rng_uniform_double(rng, 0.1, 6); + sshape.super_formulas[0][N0] = 1; + sshape.super_formulas[0][N1] = 1; + sshape.super_formulas[0][N2] = (float)ssp_rng_uniform_double(rng, 0.1, 6); + + sshape.super_formulas[1][A] = 1; + sshape.super_formulas[1][B] = 1; + sshape.super_formulas[1][M] = (float)ssp_rng_uniform_double(rng, 0.1, 6); + sshape.super_formulas[1][N0] = 1; + sshape.super_formulas[1][N1] = 1; + sshape.super_formulas[1][N2] = (float)ssp_rng_uniform_double(rng, 0.1, 6); + + sshape.ntheta = ntheta; + sshape.nphi = nphi; + + *mtl = SSCHIFF_NULL_MATERIAL; + return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, + super_shape_get_indices, (unsigned)nverts, &attrib, 1, &sshape); +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct sschiff_device* dev; + struct sschiff_estimator* estimator; + struct sschiff_integrator_desc desc = SSCHIFF_NULL_INTEGRATOR_DESC; + struct ssp_rng* rng; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); + CHECK(sschiff_device_create(NULL, &allocator, 0, NULL, &dev), RES_OK); + + desc.sample_geometry = sample_geometry; + desc.scattering_angles_count = 1; + CHECK(sschiff_integrate(NULL, NULL, NULL, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &desc, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &desc, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &desc, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &desc, 0, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &desc, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &desc, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &desc, 0, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &desc, 0, 100, &estimator), RES_OK); + + CHECK(sschiff_estimator_ref_get(NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_ref_get(estimator), RES_OK); + CHECK(sschiff_estimator_ref_put(NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_ref_put(estimator), RES_OK); + CHECK(sschiff_estimator_ref_put(estimator), RES_OK); + + CHECK(sschiff_device_ref_put(dev), RES_OK); + CHECK(ssp_rng_ref_put(rng), RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/test_salgae_utils.h b/src/test_sschiff_utils.h