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:
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(¶bol, 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;
+}