stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

commit 2e5d7bbff2ddd30b25d7e46a096c625dd68c49bf
parent 8602f12a2b64d4631b8b7b281440666c3da322d4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 21 Feb 2018 12:07:35 +0100

Implement and test the sdis_camera API

Diffstat:
Mcmake/CMakeLists.txt | 8+++++++-
Msrc/sdis.h | 41++++++++++++++++++++++++++++++++++++++---
Asrc/sdis_camera.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sdis_camera.h | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_sdis_camera.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 337 insertions(+), 4 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -45,6 +45,7 @@ set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SDIS_FILES_SRC + sdis_camera.c sdis_data.c sdis_device.c sdis_estimator.c @@ -57,6 +58,7 @@ set(SDIS_FILES_INC_API sdis.h) set(SDIS_FILES_INC + sdis_camera.h sdis_device_c.h sdis_estimator_c.h sdis_interface_c.h @@ -75,7 +77,10 @@ add_library(sdis SHARED ${SDIS_FILES_SRC} ${SDIS_FILES_INC} ${SDIS_FILES_INC_API}) -target_link_libraries(sdis RSys Star2D Star3D StarSP) +target_link_libraries(sdis RSys Star2D Star3D StarSP m) +if(CMAKE_COMPILER_IS_GNUCC) + target_link_libraries(sdis m) +endif() set_target_properties(sdis PROPERTIES DEFINE_SYMBOL SDIS_SHARED_BUILD @@ -111,6 +116,7 @@ if(NOT NO_TEST) register_test(${_name} ${_name}) endfunction() + new_test(test_sdis_camera) new_test(test_sdis_data) new_test(test_sdis_device) new_test(test_sdis_interface) diff --git a/src/sdis.h b/src/sdis.h @@ -51,6 +51,7 @@ struct mem_allocator; * a reference on the data, i.e. they increment or decrement the reference * counter, respectively. When this counter reaches 0, the object is silently * destroyed and cannot be used anymore. */ +struct sdis_camera; struct sdis_data; struct sdis_device; struct sdis_estimator; @@ -124,7 +125,7 @@ struct sdis_solid_shader { * unknown for the submitted random walk vertex. */ sdis_medium_getter_T temperature; }; -#define SDIS_SOLID_SHADER_NULL__ {NULL} +#define SDIS_SOLID_SHADER_NULL__ {NULL, NULL, NULL, NULL, NULL, NULL} static const struct sdis_solid_shader SDIS_SOLID_SHADER_NULL = SDIS_SOLID_SHADER_NULL__; @@ -137,7 +138,7 @@ struct sdis_fluid_shader { * unknown for the submitted position and time. */ sdis_medium_getter_T temperature; }; -#define SDIS_FLUID_SHADER_NULL__ {NULL} +#define SDIS_FLUID_SHADER_NULL__ {NULL, NULL, NULL} static const struct sdis_fluid_shader SDIS_FLUID_SHADER_NULL = SDIS_FLUID_SHADER_NULL__; @@ -149,7 +150,7 @@ struct sdis_interface_shader { sdis_interface_getter_T emissivity; /* Overall emissivity */ sdis_interface_getter_T specular_fraction; /* Specular fraction in [0, 1] */ }; -#define SDIS_INTERFACE_SHADER_NULL__ {NULL} +#define SDIS_INTERFACE_SHADER_NULL__ {NULL, NULL, NULL, NULL} static const struct sdis_interface_shader SDIS_INTERFACE_SHADER_NULL = SDIS_INTERFACE_SHADER_NULL__; @@ -204,6 +205,40 @@ sdis_data_cget (const struct sdis_data* data); /******************************************************************************* + * A camera describes a point of view + ******************************************************************************/ +SDIS_API res_T +sdis_camera_create + (struct sdis_device* dev, + struct sdis_camera** cam); + +SDIS_API res_T +sdis_camera_ref_get + (struct sdis_camera* cam); + +SDIS_API res_T +sdis_camera_ref_put + (struct sdis_camera* cam); + +/* Width/height projection ratio */ +SDIS_API res_T +sdis_camera_set_proj_ratio + (struct sdis_camera* cam, + const double proj_ratio); + +SDIS_API res_T +sdis_camera_set_fov /* Horizontal field of view */ + (struct sdis_camera* cam, + const double fov); /* In radian */ + +SDIS_API res_T +sdis_camera_look_at + (struct sdis_camera* cam, + const double position[3], + const double target[3], + const double up[3]); + +/******************************************************************************* * A medium encapsulates the properties of either a fluid or a solid. ******************************************************************************/ SDIS_API res_T diff --git a/src/sdis_camera.c b/src/sdis_camera.c @@ -0,0 +1,138 @@ +/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com) + * + * 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 "sdis.h" +#include "sdis_camera.h" +#include "sdis_device_c.h" + +#include <rsys/mem_allocator.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +camera_release(ref_T* ref) +{ + struct sdis_camera* cam = CONTAINER_OF(ref, struct sdis_camera, ref); + struct sdis_device* dev; + ASSERT(ref); + dev = cam->dev; + MEM_RM(dev->allocator, cam); + SDIS(device_ref_put(dev)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sdis_camera_create(struct sdis_device* dev, struct sdis_camera** out_cam) +{ + const double pos[3] = {0, 0, 0}; + const double tgt[3] = {0, 0,-1}; + const double up[3] = {0, 1, 0}; + struct sdis_camera* cam = NULL; + res_T res = RES_OK; + + if(!dev || !out_cam) { + res = RES_BAD_ARG; + goto error; + } + + cam = MEM_CALLOC(dev->allocator, 1, sizeof(struct sdis_camera)); + if(!cam) { + res = RES_MEM_ERR; + goto error; + } + SDIS(device_ref_get(dev)); + cam->dev = dev; + ref_init(&cam->ref); + cam->rcp_proj_ratio = 1.0; + cam->fov_x = PI/2.0; + SDIS(camera_look_at(cam, pos, tgt, up)); + +exit: + if(out_cam) *out_cam = cam; + return res; +error: + if(cam) { + SDIS(camera_ref_put(cam)); + cam = NULL; + } + goto exit; +} + +res_T +sdis_camera_ref_get(struct sdis_camera* cam) +{ + if(!cam) return RES_BAD_ARG; + ref_get(&cam->ref); + return RES_OK; +} + +res_T +sdis_camera_ref_put(struct sdis_camera* cam) +{ + if(!cam) return RES_BAD_ARG; + ref_put(&cam->ref, camera_release); + return RES_OK; +} + +res_T +sdis_camera_set_proj_ratio(struct sdis_camera* cam, const double ratio) +{ + double y[3] = {0}; + if(!cam || ratio <= 0) return RES_BAD_ARG; + if(d3_normalize(y, cam->axis_y) <= 0) return RES_BAD_ARG; + cam->rcp_proj_ratio = 1.0 / ratio; + d3_muld(cam->axis_y, y, cam->rcp_proj_ratio); + return RES_OK; +} + +res_T +sdis_camera_set_fov(struct sdis_camera* cam, const double fov_x) +{ + double z[3] = {0}; + double img_plane_depth; + if(!cam || (float)fov_x <= 0) return RES_BAD_ARG; + if(d3_normalize(z, cam->axis_z) <= 0) return RES_BAD_ARG; + img_plane_depth = 1.0/tan(fov_x*0.5); + d3_muld(cam->axis_z, z, img_plane_depth); + cam->fov_x = fov_x; + return RES_OK; +} + +res_T +sdis_camera_look_at + (struct sdis_camera* cam, + const double pos[3], + const double tgt[3], + const double up[3]) +{ + double x[3], y[3], z[3]; + double img_plane_depth; + if(!cam || !pos || !tgt || !up) return RES_BAD_ARG; + + if(d3_normalize(z, d3_sub(z, tgt, pos)) <= 0) return RES_BAD_ARG; + if(d3_normalize(x, d3_cross(x, z, up)) <= 0) return RES_BAD_ARG; + if(d3_normalize(y, d3_cross(y, z, x)) <= 0) return RES_BAD_ARG; + img_plane_depth = 1.0/tan(cam->fov_x*0.5); + + d3_set(cam->axis_x, x); + d3_muld(cam->axis_y, y, cam->rcp_proj_ratio); + d3_muld(cam->axis_z, z, img_plane_depth); + d3_set(cam->position, pos); + return RES_OK; +} + diff --git a/src/sdis_camera.h b/src/sdis_camera.h @@ -0,0 +1,60 @@ +/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com) + * + * 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 SDIS_CAMERA_H +#define SDIS_CAMERA_H + +#include <rsys/double3.h> +#include <rsys/ref_count.h> + +struct sdis_device; + +struct sdis_camera { + /* Orthogonal camera frame */ + double axis_x[3]; + double axis_y[3]; + double axis_z[3]; + + double position[3]; + double fov_x; /* Field of view in radians */ + double rcp_proj_ratio; /* height / width */ + + ref_T ref; + struct sdis_device* dev; +}; + +static FINLINE void +camera_ray + (const struct sdis_camera* cam, + const double sample[2], /* In [0, 1[ */ + double org[3], + double dir[3]) +{ + double x[3], y[3], len; + (void)len; /* Avoid warning in debug */ + ASSERT(cam && sample && org && dir); + ASSERT(sample[0] >= 0.0 || sample[0] < 1.0); + ASSERT(sample[1] >= 0.0 || sample[1] < 1.0); + + d3_muld(x, cam->axis_x, sample[0]*2.0 - 1.0); + d3_muld(y, cam->axis_y, sample[1]*2.0 - 1.0); + d3_add(dir, d3_add(dir, x, y), cam->axis_z); + len = d3_normalize(dir, dir); + ASSERT(len >= 1.e-6); + d3_set(org, cam->position); +} + +#endif /* SDIS_CAMERA_H */ + diff --git a/src/test_sdis_camera.c b/src/test_sdis_camera.c @@ -0,0 +1,94 @@ +/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com) + * + * 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 "sdis.h" +#include "test_sdis_utils.h" + +#include <rsys/math.h> + +int +main(int argc, char** argv) +{ + struct sdis_device* dev; + struct sdis_camera* cam; + struct mem_allocator allocator; + double pos[3] = {0}; + double tgt[3] = {0}; + double up[3] = {0}; + (void)argc, (void)argv; + + CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); + + CHK(sdis_device_create + (NULL, &allocator, SDIS_NTHREADS_DEFAULT, 0, &dev) == RES_OK); + + CHK(sdis_camera_create(NULL, NULL) == RES_BAD_ARG); + CHK(sdis_camera_create(dev, NULL) == RES_BAD_ARG); + CHK(sdis_camera_create(NULL, &cam) == RES_BAD_ARG); + CHK(sdis_camera_create(dev, &cam) == RES_OK); + + CHK(sdis_camera_ref_get(NULL) == RES_BAD_ARG); + CHK(sdis_camera_ref_get(cam) == RES_OK); + CHK(sdis_camera_ref_put(NULL) == RES_BAD_ARG); + CHK(sdis_camera_ref_put(cam) == RES_OK); + CHK(sdis_camera_ref_put(cam) == RES_OK); + + CHK(sdis_camera_create(dev, &cam) == RES_OK); + CHK(sdis_camera_set_proj_ratio(NULL, 0) == RES_BAD_ARG); + CHK(sdis_camera_set_proj_ratio(cam, 0) == RES_BAD_ARG); + CHK(sdis_camera_set_proj_ratio(NULL, 4.0/3.0) == RES_BAD_ARG); + CHK(sdis_camera_set_proj_ratio(cam, 4.0/3.0) == RES_OK); + CHK(sdis_camera_set_proj_ratio(cam, -4.0/3.0) == RES_BAD_ARG); + + CHK(sdis_camera_set_fov(NULL, 0) == RES_BAD_ARG); + CHK(sdis_camera_set_fov(cam, 0) == RES_BAD_ARG); + CHK(sdis_camera_set_fov(NULL, PI/4.0) == RES_BAD_ARG); + CHK(sdis_camera_set_fov(cam, PI/4.0) == RES_OK); + CHK(sdis_camera_set_fov(cam, -PI/4.0) == RES_BAD_ARG); + + pos[0] = 0, pos[1] = 0, pos[2] = 0; + tgt[0] = 0, tgt[1] = 0, tgt[2] = -1; + up[0] = 0, up[1] = 1, up[2] = 0; + CHK(sdis_camera_look_at(NULL, NULL, NULL, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, NULL, NULL, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, pos, NULL, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, pos, NULL, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, NULL, tgt, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, NULL, tgt, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, pos, tgt, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, pos, tgt, NULL) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, NULL, NULL, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, NULL, NULL, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, pos, NULL, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, pos, NULL, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, NULL, tgt, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, NULL, tgt, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(NULL, pos, tgt, up) == RES_BAD_ARG); + CHK(sdis_camera_look_at(cam, pos, tgt, up) == RES_OK); + tgt[0] = 0, tgt[1] = 0, tgt[2] = 0; + CHK(sdis_camera_look_at(cam, pos, tgt, up) == RES_BAD_ARG); + tgt[0] = 0, tgt[1] = 0, tgt[2] = -1; + up[0] = 0, up[1] = 0, up[2] = 0; + CHK(sdis_camera_look_at(cam, pos, tgt, up) == RES_BAD_ARG); + + CHK(sdis_device_ref_put(dev) == RES_OK); + CHK(sdis_camera_ref_put(cam) == RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} +