solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

commit bbe9455fd031e8c8f9ff07c9d467a4d9a3c5a396
parent ce4c3e327c556d3ba30ce2e04d2df5dc936243fb
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 30 Jun 2016 18:03:05 +0200

Preliminary work on solver.

Diffstat:
Mcmake/CMakeLists.txt | 3+++
Asrc/ssol_solver.c | 264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ssol_solver_c.h | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_ssol_solver.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 400 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -55,6 +55,7 @@ set(SSOL_FILES_SRC ssol_scene.c ssol_shape.c ssol_spectrum.c + ssol_solver.c ssol_sun.c) set(SSOL_FILES_INC_API @@ -69,6 +70,7 @@ set(SSOL_FILES_INC ssol_scene_c.h ssol_shape_c.h ssol_spectrum_c.h + ssol_solver_c.h ssol_sun_c.h) set(SSOL_FILES_DOC COPYING README.md) @@ -126,6 +128,7 @@ if(NOT NO_TEST) new_test(test_ssol_scene) new_test(test_ssol_shape) new_test(test_ssol_spectrum) + new_test(test_ssol_solver) new_test(test_ssol_sun) endif(NOT NO_TEST) diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -0,0 +1,263 @@ +/* Copyright (C) CNRS 2016 +* +* 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 "ssol.h" +#include "ssol_solver_c.h" +#include "ssol_device_c.h" +#include "ssol_scene_c.h" +#include "ssol_shape_c.h" +#include "ssol_object_c.h" +#include "ssol_object_instance_c.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/ref_count.h> + +/******************************************************************************* +* Helper functions +******************************************************************************/ + +static void quadric_to_mat4x4 + (const struct ssol_general_quadric* from, double* to) +{ + to[0] = from->a; + to[1] = to[4] = from->b; + to[2] = to[8] = from->c; + to[3] = to[12] = from->d; + to[5] = from->e; + to[6] = to[9] = from->f; + to[7] = to[13] = from->g; + to[10] = from->h; + to[11] = to[14] = from->i; + to[15] = from->j; +} + +static void mat4x4_to_quadric + (const double* from, struct ssol_general_quadric* to) +{ + to->a = from[0]; + to->b = from[1]; + to->c = from[2]; + to->d = from[3]; + to->e = from[5]; + to->f = from[6]; + to->g = from[7]; + to->h = from[10]; + to->i = from[11]; + to->j = from[15]; +} + +static void mat_3x4_to_4x4 + (const double* from, double* to) +{ + int r, c, idx_f = 0, idx_t = 0; + for (c = 0; c < 4; c++) { + for (r = 0; r < 3; r++) { + to[idx_t++] = from[idx_f++]; + } + to[idx_t++] = (c == 3) ? 1 : 0; + } +} + +static void +mat_4x4_mul + (const double* a, const double* b, double* to) +{ + int r, c, k; + for (c = 0; c < 4; c++) { + for (r = 0; r < 4; r++) { + to[r * 4 + c] = 0; + for (k = 0; k < 4; k++) { + to[r * 4 + c] += a[r * 4 + k] * b[k * 4 + c]; + } + } + } +} + +static void +mat_4x4_transp + (const double* from, double* to) +{ + int r, c, idx_f = 0, idx_t = 0; + for (c = 0; c < 4; c++) { + for (r = 0; r < 4; r++) { + to[15 - idx_t++] = from[idx_f++]; + } + } +} + +static int +is_instance_punched + (const struct ssol_object_instance* instance) +{ + return instance->object->shape->type == SHAPE_PUNCHED; +} + +static const struct ssol_quadric* +get_quadric + (const struct ssol_object_instance* instance) +{ + ASSERT(is_instance_punched(instance)); + return instance->object->shape->quadric; +} + +static struct s3d_scene* +get_3dscene +(const struct ssol_object_instance* instance) +{ + return instance->object->shape->scene; +} + +static const double* +get_transform +(const struct ssol_object_instance* instance) +{ + return instance->transform; +} + +/******************************************************************************* +* Local functions +******************************************************************************/ + +/******************************************************************************* +* Exported ssol_solver functions +******************************************************************************/ + +/* Implementation notes: + * + * The transform of a plane is still a plane (first degree equation) + * so we could construct a ssol_quadric that would be a plane if + * the input quadric is a plane. + * + * The quadric matrices are diagonal, so that operators could be specialized. + * + * Ultimately we could process quadric directly without intermediate + * matricial representation. + * + * These are possible performance improvement. + */ +res_T +quadric_transform + (const struct ssol_quadric* quadric, + const double transform [], + struct ssol_quadric* transformed) +{ + double transform44[16], quadric44[16], transp[16], tmp[16]; + struct ssol_general_quadric* tr = &transformed->data.general_quadric; + if (!quadric || !transformed || !transform) + return RES_BAD_ARG; + + /* feed transformed with quadric data */ + transformed->type = SSOL_GENERAL_QUADRIC; + switch (quadric->type) { + case SSOL_QUADRIC_PLANE: + /* Define z = 0 */ + tr->a = 0; + tr->b = 0; + tr->c = 0; + tr->d = 0; + tr->e = 0; + tr->f = 0; + tr->g = 0; + tr->h = 0; + tr->i = 0.5; + tr->j = 0; + break; + case SSOL_QUADRIC_PARABOL: + /* Define x^2 + y^2 - 4 focal z = 0 */ + tr->a = 1; + tr->b = 0; + tr->c = 0; + tr->d = 0; + tr->e = 1; + tr->f = 0; + tr->g = 0; + tr->h = 0; + tr->i = -2 * quadric->data.parabol.focal; + tr->j = 0; + break; + case SSOL_QUADRIC_PARABOLIC_CYLINDER: + /* Define y^2 - 4 focal z = 0 */ + tr->a = 0; + tr->b = 0; + tr->c = 0; + tr->d = 0; + tr->e = 1; + tr->f = 0; + tr->g = 0; + tr->h = 0; + tr->i = -2 * quadric->data.parabolic_cylinder.focal;; + tr->j = 0; + break; + case SSOL_GENERAL_QUADRIC: + /* Define ax² + 2bxy + 2cxz + 2dx + ey² + 2fyz + 2gy + hz² + 2iz + j = 0 */ + *tr = quadric->data.general_quadric; + break; + default: + FATAL("Unreachable code \n"); + } + /* transform */ + quadric_to_mat4x4(tr, quadric44); + mat_3x4_to_4x4(transform, transform44); + mat_4x4_transp(transform44, transp); + mat_4x4_mul(transp, quadric44, tmp); + mat_4x4_mul(tmp, transform44, quadric44); + mat4x4_to_quadric(quadric44, tr); + + return RES_OK; +} + +res_T +process_instances + (const struct ssol_scene* scene, + struct solver_data* data) +{ + struct list_node* node; + + if (!scene || !data) + return RES_BAD_ARG; + data->quadrics_count = 0; + data->shapes_count = scene->instances_count; + darray_3dshape_reserve(&data->shapes, data->shapes_count); + + /* create the main scene */ + s3d_scene_create(0, &data->scene); + LIST_FOR_EACH(node, &scene->instances) { + struct ssol_object_instance* instance = CONTAINER_OF + (node, struct ssol_object_instance, scene_attachment); + struct s3d_scene* scene3D; + struct s3d_shape* shape3D; + + if (is_instance_punched(instance)) { + const struct ssol_quadric* quadric = get_quadric(instance); + const double* transform = get_transform(instance); + struct ssol_quadric transformed; + quadric_transform(quadric, transform, &transformed); + darray_quadric_push_back(&data->quadrics, &transformed); + ++data->quadrics_count; + } + /* instantiate each s3d_scene as a s3d_shape */ + scene3D = get_3dscene(instance); + s3d_scene_instantiate(scene3D, &shape3D); + /* apply transform: TODO */ + + + darray_3dshape_push_back(&data->shapes, &shape3D); + /* and attach it to the main scene */ + s3d_scene_attach_shape(data->scene, shape3D); + } + + return RES_OK; +} +\ No newline at end of file diff --git a/src/ssol_solver_c.h b/src/ssol_solver_c.h @@ -0,0 +1,58 @@ +/* Copyright (C) CNRS 2016 +* +* 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 SSOL_SOLVER_C_H +#define SSOL_SOLVER_C_H + +#include <rsys/ref_count.h> +#include <rsys/list.h> +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME quadric +#define DARRAY_DATA struct ssol_quadric +#include <rsys/dynamic_array.h> +#undef DARRAY_NAME +#undef DARRAY_DATA + +#define DARRAY_NAME 3dshape +#define DARRAY_DATA struct s3d_shape* +#include <rsys/dynamic_array.h> +#undef DARRAY_NAME +#undef DARRAY_DATA + +struct solver_data { + /* data comming from instances of the scene */ + size_t shapes_count; + size_t quadrics_count; + struct darray_quadric quadrics; + struct darray_3dshape shapes; + /* the 3D scene used for raytracing */ + struct s3d_scene *scene; + /* the random distribution for sun sampling */ +}; + +SSOL_API res_T +process_instances + (const struct ssol_scene* scene, + struct solver_data* data); + +/* transform a single quadric in world space */ +SSOL_API res_T +quadric_transform + (const struct ssol_quadric* quadric, + const double transform[], + struct ssol_quadric* transformed); + +#endif /* SSOL_SOLVER_C_H */ diff --git a/src/test_ssol_solver.c b/src/test_ssol_solver.c @@ -0,0 +1,75 @@ +/* Copyright (C) CNRS 2016 +* +* 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 "ssol.h" +#include "test_ssol_utils.h" + +#include "ssol_solver_c.h" + +#include <rsys/logger.h> + +/******************************************************************************* +* test main program +******************************************************************************/ +int +main(int argc, char** argv) +{ + struct logger logger; + struct mem_allocator allocator; + struct ssol_device* dev; + struct ssol_quadric plane; + struct ssol_quadric parabol; + struct ssol_quadric general; + struct ssol_quadric quadric; + double identity[12] = {1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}; + int i; + double* p; + (void) argc, (void) argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + 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(ssol_device_create(&logger, &allocator, SSOL_NTHREADS_DEFAULT, 0, &dev), RES_OK); + + plane.type = SSOL_QUADRIC_PLANE; + quadric_transform(&plane, identity, &quadric); + CHECK(quadric.data.general_quadric.i, 0.5); + + parabol.type = SSOL_QUADRIC_PARABOL; + parabol.data.parabol.focal = 1; + quadric_transform(&parabol, identity, &quadric); + CHECK(quadric.data.general_quadric.a, 1); + CHECK(quadric.data.general_quadric.e, 1); + CHECK(quadric.data.general_quadric.i, -2); + + general.type = SSOL_GENERAL_QUADRIC; + p = &general.data.general_quadric.a; + for (i = 0; i < 10; i++) p[i] = rand() / (double)RAND_MAX; + quadric_transform(&general, identity, &quadric); + CHECK(memcmp(&general, &quadric, sizeof(struct ssol_quadric)), 0); + CHECK(ssol_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; +}