commit 99b250ce4ed539d9c3e446374cc61feb69b721a8
parent b616ce8d0d5a84bb1470927497271fef284a1c38
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 19 Dec 2016 21:54:13 +0100
Merge remote-tracking branch 'origin/master'
Diffstat:
19 files changed, 889 insertions(+), 869 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -34,6 +34,11 @@ find_package(SolSolver 0.1 REQUIRED)
find_package(Star3DUT REQUIRED)
find_package(StarSP 0.4 REQUIRED)
+if(MSVC)
+ find_package(MuslGetopt REQUIRED)
+ include_directories(${MuslGetopt_INCLUDE_DIR})
+endif()
+
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR})
include(rcmake)
include(rcmake_runtime)
@@ -43,7 +48,8 @@ include_directories(
${SolAnim_INCLUDE_DIR}
${SolSolver_INCLUDE_DIR}
${StarSP_INCLUDE_DIR}
- ${Star3DUT_INCLUDE_DIR})
+ ${Star3DUT_INCLUDE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR})
################################################################################
# Build subprojects
@@ -52,6 +58,20 @@ add_subdirectory(parser)
add_subdirectory(core)
################################################################################
+# Generate files
+################################################################################
+set(SOLSTICE_ARGS_DEFAULT_NREALISATIONS "10000")
+set(SOLSTICE_ARGS_DEFAULT_CAMERA_POS "0,0,0")
+set(SOLSTICE_ARGS_DEFAULT_CAMERA_TGT "0,0,-1")
+set(SOLSTICE_ARGS_DEFAULT_CAMERA_UP "0,1,0")
+set(SOLSTICE_ARGS_DEFAULT_CAMERA_FOV "70")
+set(SOLSTICE_ARGS_DEFAULT_IMG_WIDTH "800")
+set(SOLSTICE_ARGS_DEFAULT_IMG_HEIGHT "600")
+
+configure_file(${SOLSTICE_SOURCE_DIR}/solstice_args.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/solstice_args.h @ONLY)
+
+################################################################################
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
@@ -61,11 +81,13 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SOLSTICE_FILES_SRC
solstice.c
+ solstice_args.c
solstice_entity.c
solstice_material.c
solstice_object.c)
set(SOLSTICE_FILES_INC
solstice.h
+ solstice_args.h.in
solstice_c.h)
set(SOLSTICE_FILES_DOC COPYING README.md)
@@ -88,6 +110,26 @@ set_target_properties(solstice PROPERTIES
rcmake_copy_runtime_libraries(solstice)
################################################################################
+# Tests
+################################################################################
+if(NOT NO_TEST)
+ function(build_test _name)
+ add_executable(${_name}
+ ${SOLSTICE_SOURCE_DIR}/${_name}.c
+ ${SOLSTICE_SOURCE_DIR}/test_solstice_utils.h)
+ target_link_libraries(${_name} ${MATH_LIB} RSys sollib)
+ endfunction()
+
+ function(new_test _name)
+ build_test(${_name})
+ add_test(${_name} ${_name})
+ endfunction()
+
+ new_test(test_solstice_args)
+
+endif()
+
+################################################################################
# Define output & install directories
################################################################################
install(TARGETS solstice
diff --git a/cmake/core/CMakeLists.txt b/cmake/core/CMakeLists.txt
@@ -34,14 +34,12 @@ include_directories(
set(CORE_FILES_SRC
solstice_core_device.c
solstice_core_node.c
- solstice_core_scene.c
solstice_core_solver.c)
set(CORE_FILES_INC
solstice_core.h
solstice_core_device.h
- solstice_core_node.h
- solstice_core_scene.h)
+ solstice_core_node.h)
# Prepend each file in the `SOLSTICE_FILES_<SRC|INC>' list by `SOLSTICE_SOURCE_DIR'
rcmake_prepend_path(CORE_FILES_SRC ${CORE_SOURCE_DIR})
@@ -70,11 +68,11 @@ if(NOT NO_TEST)
${CORE_SOURCE_DIR}/test_core_utils.h
${CORE_SOURCE_DIR}/test_core_utils.c)
-
- new_test(test_core_device)
- new_test(test_core_node)
- new_test(test_core_scene)
- new_test(test_core_solve1)
+# TODO: tests need to be fixed
+# new_test(test_core_device)
+# new_test(test_core_node)
+# new_test(test_core_scene)
+# new_test(test_core_solve1)
- rcmake_copy_runtime_libraries(test_core_solve1)
+# rcmake_copy_runtime_libraries(test_core_solve1)
endif()
diff --git a/doc/cli b/doc/cli
@@ -0,0 +1,51 @@
+solstice
+ -d <date-list>:<pos-on-earth>
+ -D <sun-dir-list>
+ -h # Short help and exit
+ -o OUTPUT # defaulting to stdout if not defined
+ -q # don't print a message if no INPUT is submitted
+ -n INTEGER # Realisations count
+ -r [rendering] # Switch in rendering mode
+ INPUT # Input scene in YAML
+
+solstice -r img=1280x720:pos=0,100,0:tgt=0,0,0:up=0,1,0:fov=70
+
+<date-list> ::=
+ <date> [ ... ]
+
+<date> ::=
+ year:month:day:minutes:seconds:timezone # <=> UNIX format
+
+<sun-dir-list> ::=
+ <sun-dir> [ ... ]
+
+<sun-dir> ::=
+ REAL:REAL # azimuth:elevation
+
+<pos-on-earth> ::=
+ REAL:REAL:REAL # longititude:latitude:altitude
+
+<rendering> ::=
+ <rendering-option>[:<rendering-option> ... ]
+
+<rendering-option> ::=
+ <fov> | <img> | <position> | <target> | <up>
+
+<fov> ::=
+ fov=<real3>
+
+<img> ::=
+ img=INTEGERxINTEGER
+
+<position> ::=
+ pos=<real3>
+
+<target> ::=
+ tgt=<real3>
+
+<up> ::=
+ up=<real3>
+
+<real3> ::=
+ REAL,REAL,REAL
+
diff --git a/src/core/solstice_core.h b/src/core/solstice_core.h
@@ -35,7 +35,6 @@ struct ssp_rng;
struct score_device;
struct score_node;
-struct score_scene;
/*******************************************************************************
* Device API - Main entry point of Solstice core. Applications
@@ -65,22 +64,17 @@ score_device_get_solver_device
* Node API
******************************************************************************/
extern LOCAL_SYM res_T
-score_node_template_create
+score_node_geometry_create
(struct score_device* dev,
- struct score_node** node);
-
-extern LOCAL_SYM res_T
-score_node_instantiate
- (struct score_node* template,
- struct score_node** instance);
+ struct score_node** geom);
extern LOCAL_SYM res_T
-score_node_create_object
+score_node_pivot_create
(struct score_device* dev,
struct score_node** node);
extern LOCAL_SYM res_T
-score_node_pivot_create
+score_node_empty_create
(struct score_device* dev,
struct score_node** node);
@@ -98,9 +92,9 @@ score_node_ref_put
(struct score_node* node);
extern LOCAL_SYM res_T
-score_node_object_setup
+score_node_geometry_setup
(struct score_node* node,
- struct ssol_object* object);
+ struct ssol_instance* geom);
extern LOCAL_SYM res_T
score_node_pivot_setup
@@ -150,80 +144,26 @@ score_node_sample
(struct score_node* node,
const int sample);
-/* Temporary API for testing purpose
- * Instance introspection.
- * If the template tree from which instance was created contains node,
- * find the corresponding node in instance */
-extern LOCAL_SYM void
-score_node_get_instance_of
- (const struct score_node* instance,
- const struct score_node* node,
- struct ssol_instance** solver);
-
/*******************************************************************************
- * Scene API
- ******************************************************************************/
-extern LOCAL_SYM res_T
-score_scene_create
- (struct score_device* dev,
- struct score_scene** scene);
-
-extern LOCAL_SYM void
-score_scene_ref_get
- (struct score_scene* scene);
-
-extern LOCAL_SYM void
-score_scene_ref_put
- (struct score_scene* scene);
-
-extern LOCAL_SYM res_T
-score_scene_attach_instance
- (struct score_scene* scene,
- struct score_node* instance);
-
-extern LOCAL_SYM void
-score_scene_detach_instance
- (struct score_scene* scene,
- struct score_node* instance);
-
-extern LOCAL_SYM void
-score_scene_attach_sun
- (struct score_scene* scene,
- struct ssol_sun* sun);
-
-extern LOCAL_SYM void
-score_scene_detach_sun
- (struct score_scene* scene,
- struct ssol_sun* sun);
-
-extern LOCAL_SYM void
-score_scene_attach_atmosphere
- (struct score_scene* scene,
- struct ssol_atmosphere* atm);
-
-extern LOCAL_SYM void
-score_scene_detach_atmosphere
- (struct score_scene* scene,
- struct ssol_atmosphere* atm);
-
+* Miscellaneous functions
+******************************************************************************/
extern LOCAL_SYM void
score_scene_clear
- (struct score_scene* scene);
+ (struct score_device* dev);
extern LOCAL_SYM res_T
-score_scene_reset_simulation
- (struct score_scene* scene);
+score_reset_simulation
+ (struct score_device* dev,
+ const double sun_dir[3]);
extern LOCAL_SYM res_T
-score_scene_update_simulation
- (struct score_scene* scene);
+score_update_simulation
+ (struct score_device* dev,
+ const double sun_dir[3]);
-/*******************************************************************************
- * Miscellaneous functions
- ******************************************************************************/
extern LOCAL_SYM res_T
score_solve
- (struct score_scene* scene,
+ (struct score_device* dev,
struct ssp_rng* rng,
const size_t realisations_count,
FILE* output,
diff --git a/src/core/solstice_core_device.c b/src/core/solstice_core_device.c
@@ -48,6 +48,9 @@ device_release(ref_T* ref)
ASSERT(ref);
dev = CONTAINER_OF(ref, struct score_device, ref);
ASSERT(dev && dev->allocator);
+ if (dev->solver) SSOL(scene_ref_put(dev->solver));
+ darray_nodes_release(&dev->instances);
+ darray_nodes_release(&dev->pivots);
if (dev->ssol) ssol_device_ref_put(dev->ssol);
MEM_RM(dev->allocator, dev);
}
@@ -83,6 +86,12 @@ score_device_create
res = ssol_device_create(logger, allocator, nthreads_hint, verbose, &dev->ssol);
if (res != RES_OK) goto error;
+ res = ssol_scene_create(dev->ssol, &dev->solver);
+ if (res != RES_OK) goto error;
+
+ darray_nodes_init(dev->allocator, &dev->instances);
+ darray_nodes_init(dev->allocator, &dev->pivots);
+
exit:
if (out_dev) *out_dev = dev;
return res;
diff --git a/src/core/solstice_core_device.h b/src/core/solstice_core_device.h
@@ -16,6 +16,8 @@
#ifndef SOLSTICE_CORE_DEVICE_H
#define SOLSTICE_CORE_DEVICE_H
+#include "solstice_core_node.h"
+
#include <rsys/ref_count.h>
#include <rsys/mem_allocator.h>
@@ -28,6 +30,10 @@ struct score_device {
int verbose;
struct ssol_device* ssol;
+ struct darray_nodes instances;
+ struct darray_nodes pivots;
+ struct ssol_scene* solver;
+
ref_T ref;
};
diff --git a/src/core/solstice_core_node.c b/src/core/solstice_core_node.c
@@ -36,22 +36,11 @@ node_release(ref_T* ref)
dev = node->device;
ASSERT(dev && dev->allocator);
switch (node->type) {
- case NODE_TEMPLATE_ROOT:
- break;
- case NODE_INSTANCE_ROOT:
- darray_nodes_release(&node->data.instance_root.pivots);
- if (node->data.instance_root.template)
- score_node_ref_put(node->data.instance_root.template);
- break;
case NODE_TRACKING_TARGET:
break;
- case NODE_TEMPLATE:
- if (node->data.template_node.solver_object)
- SSOL(object_ref_put(node->data.template_node.solver_object));
- break;
- case NODE_INSTANCE:
- if (node->data.instance_node.solver_instance)
- SSOL(instance_ref_put(node->data.instance_node.solver_instance));
+ case NODE_GEOMETRY:
+ if (node->data.geometry_node.solver_instance)
+ SSOL(instance_ref_put(node->data.geometry_node.solver_instance));
break;
case NODE_PIVOT:
break;
@@ -68,27 +57,6 @@ struct data {
struct ssol_instance* result;
};
-static res_T
-search(const struct sanim_node* n, void* data_, int* found)
-{
- const struct score_node* node;
- struct data* data;
- ASSERT(n && data_ && found);
-
- data = data_;
- node = CONTAINER_OF(n, struct score_node, anim);
- if (node->type == NODE_INSTANCE) {
- const struct ssol_object* solver_model;
- ASSERT(node->data.instance_node.model->type == NODE_TEMPLATE);
- solver_model = node->data.instance_node.model->data.template_node.solver_object;
- if (solver_model == data->searched) {
- data->result = node->data.instance_node.solver_instance;
- *found = 1;
- return RES_OK;
- }
- }
- return RES_OK;
-}
/*******************************************************************************
* Local functions
@@ -144,139 +112,39 @@ node_ref_put_children(struct sanim_node* node)
}
}
-static res_T
-instance_internal_node_create
- (struct score_device* dev, struct score_node** node)
-{
- struct sanim_node* anim;
- res_T res = RES_OK;
- res = node_create(dev, node, NODE_INSTANCE);
- if (res != RES_OK) goto error;
- anim = &(*node)->anim;
- res = sanim_node_initialize((*node)->device->allocator, anim);
- if (res != RES_OK) goto error;
-exit:
- return res;
-error:
- if (node && *node) {
- score_node_ref_put(*node);
- *node = NULL;
- }
- goto exit;
-}
-
-res_T
-node_instanciate_any
- (struct score_node* tp_node,
- struct score_node** out_node)
-{
- struct score_node* node = NULL;
- struct score_device* dev;
- double v[3];
- res_T res = RES_OK;
-
- ASSERT(tp_node && out_node);
-
- dev = tp_node->device;
- ASSERT(dev && dev->allocator);
-
- switch (tp_node->type) {
- case NODE_TEMPLATE_ROOT:
- res = score_node_instantiate(tp_node, &node);
- if (res != RES_OK) goto error;
- break;
- case NODE_INSTANCE_ROOT:
- ASSERT(0);
- goto error;
- case NODE_TRACKING_TARGET:
- res = score_node_tracking_target_create(dev, &node);
- if (res != RES_OK) goto error;
- SANIM(node_get_translation(&tp_node->anim, v));
- SANIM(node_set_translation(&node->anim, v));
- /* rotations have no meaning for a target */
- break;
- case NODE_TEMPLATE:
- res = instance_internal_node_create(dev, &node);
- if (res != RES_OK) goto error;
- res = ssol_object_instantiate(
- tp_node->data.template_node.solver_object,
- &node->data.instance_node.solver_instance);
- if (res != RES_OK) goto error;
- node->data.instance_node.model = tp_node;
- node->data.instance_node.receiver_mask
- = tp_node->data.template_node.receiver_mask;
- node->data.instance_node.sample
- = tp_node->data.template_node.sample;
- SANIM(node_get_translation(&tp_node->anim, v));
- SANIM(node_set_translation(&node->anim, v));
- SANIM(node_get_rotations(&tp_node->anim, v));
- SANIM(node_set_rotations(&node->anim, v));
- break;
- case NODE_INSTANCE:
- ASSERT(0);
- goto error;
- case NODE_PIVOT:
-#ifndef NDEBUG
- {
- int p;
- ASSERT(sanim_node_is_pivot(&tp_node->anim, &p) == RES_OK && p);
- }
-#endif
- res = score_node_pivot_create(dev, &node);
- if (res != RES_OK) goto error;
- res = sanim_node_copy_initialize(
- dev->allocator, &tp_node->anim, &node->anim);
- /* copy includes translation and rotations */
- if (res != RES_OK) goto error;
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
-
-exit:
- if (out_node) *out_node = node;
- return res;
-error:
- if (node) {
- score_node_ref_put(node);
- node = NULL;
- }
- goto exit;
-}
-
/*******************************************************************************
* Exported score_node functions
******************************************************************************/
res_T
-score_node_template_create
+score_node_geometry_create
(struct score_device* dev,
- struct score_node** node)
+ struct score_node** geom)
{
struct sanim_node* anim;
res_T res = RES_OK;
- res = node_create(dev, node, NODE_TEMPLATE_ROOT);
+ res = node_create(dev, geom, NODE_GEOMETRY);
if (res != RES_OK) goto error;
- anim = &(*node)->anim;
- res = sanim_node_initialize((*node)->device->allocator, anim);
+ anim = &(*geom)->anim;
+ res = sanim_node_initialize((*geom)->device->allocator, anim);
if (res != RES_OK) goto error;
exit:
return res;
error:
- if (node && *node) {
- score_node_ref_put(*node);
- *node = NULL;
+ if (geom && *geom) {
+ score_node_ref_put(*geom);
+ *geom = NULL;
}
goto exit;
}
res_T
-score_node_create_object
+score_node_pivot_create
(struct score_device* dev,
struct score_node** node)
{
res_T res = RES_OK;
- res = node_create(dev, node, NODE_TEMPLATE);
+ res = node_create(dev, node, NODE_PIVOT);
if (res != RES_OK) goto error;
- (*node)->data.template_node.sample = 1;
exit:
return res;
error:
@@ -288,12 +156,12 @@ error:
}
res_T
-score_node_pivot_create
+score_node_empty_create
(struct score_device* dev,
struct score_node** node)
{
res_T res = RES_OK;
- res = node_create(dev, node, NODE_PIVOT);
+ res = node_create(dev, node, NODE_EMPTY);
if (res != RES_OK) goto error;
exit:
return res;
@@ -326,52 +194,22 @@ error:
}
res_T
-score_node_instantiate
- (struct score_node* template,
- struct score_node** out_instance)
-{
- res_T res = RES_OK;
- struct score_device* dev;
- struct score_node* instance;
- ASSERT(template && out_instance && template->type == NODE_TEMPLATE_ROOT);
- dev = template->device;
- ASSERT(dev);
- res = node_create(dev, &instance, NODE_INSTANCE_ROOT);
- if (res != RES_OK) goto error;
- res = sanim_node_initialize(instance->device->allocator, &instance->anim);
- if (res != RES_OK) goto error;
- /* actual instantiation is deferred */
- instance->data.instance_root.template = template;
- darray_nodes_init(dev->allocator, &instance->data.instance_root.pivots);
- score_node_ref_get(template);
-exit:
- *out_instance = instance;
- return res;
-error:
- if (instance) {
- score_node_ref_put(instance);
- instance = NULL;
- }
- goto exit;
-}
-
-res_T
-score_node_object_setup
+score_node_geometry_setup
(struct score_node* node,
- struct ssol_object* object)
+ struct ssol_instance* instance)
{
res_T res = RES_OK;
- ASSERT(node && object && node->type == NODE_TEMPLATE);
+ ASSERT(node && instance && node->type == NODE_GEOMETRY);
/* TODO: deal with multiple setups */
res = sanim_node_initialize(node->device->allocator, &node->anim);
if (res != RES_OK) goto error;
- node->data.template_node.solver_object = object;
- SSOL(object_ref_get(object));
+ node->data.geometry_node.solver_instance = instance;
+ SSOL(instance_ref_put(instance));
exit:
return res;
error:
- if (node->data.template_node.solver_object) {
- SSOL(object_ref_put(node->data.template_node.solver_object));
+ if (node->data.geometry_node.solver_instance) {
+ SSOL(instance_ref_put(node->data.geometry_node.solver_instance));
}
if (node->anim.data) {
SANIM(node_release(&node->anim));
@@ -416,11 +254,7 @@ score_node_add_child
{
res_T res = RES_OK;
ASSERT(father && child
- && father->type != NODE_INSTANCE_ROOT
- && father->type != NODE_TRACKING_TARGET
- && child->type != NODE_TEMPLATE_ROOT
- && child->type != NODE_INSTANCE_ROOT
- );
+ && father->type != NODE_TRACKING_TARGET);
res = sanim_node_add_child(&father->anim, &child->anim);
if (res != RES_OK) return res;
score_node_ref_get(child);
@@ -446,7 +280,7 @@ score_node_set_translation
(struct score_node* node,
const double translation[3])
{
- ASSERT(node && translation && node->type != NODE_TEMPLATE_ROOT);
+ ASSERT(node && translation);
SANIM(node_set_translation(&node->anim, translation));
}
@@ -455,7 +289,7 @@ score_node_get_translation
(const struct score_node* node,
double translation[3])
{
- ASSERT(node && translation && node->type != NODE_TEMPLATE_ROOT);
+ ASSERT(node && translation);
SANIM(node_get_translation(&node->anim, translation));
}
@@ -465,7 +299,6 @@ score_node_set_rotations
const double rotations[3])
{
ASSERT(node && rotations
- && node->type != NODE_TEMPLATE_ROOT
&& node->type != NODE_TRACKING_TARGET);
SANIM(node_set_rotations(&node->anim, rotations));
}
@@ -476,7 +309,6 @@ score_node_get_rotations
double rotations[3])
{
ASSERT(node && rotations
- && node->type != NODE_TEMPLATE_ROOT
&& node->type != NODE_TRACKING_TARGET);
SANIM(node_get_rotations(&node->anim, rotations));
}
@@ -486,8 +318,8 @@ score_node_set_receiver
(struct score_node* node,
const int mask)
{
- ASSERT(node && node->type == NODE_TEMPLATE);
- node->data.template_node.receiver_mask = mask;
+ ASSERT(node && node->type == NODE_GEOMETRY);
+ node->data.geometry_node.receiver_mask = mask;
}
void
@@ -495,25 +327,7 @@ score_node_sample
(struct score_node* node,
const int sample)
{
- ASSERT(node && node->type == NODE_TEMPLATE);
- node->data.template_node.sample = sample;
+ ASSERT(node && node->type == NODE_GEOMETRY);
+ node->data.geometry_node.sample = sample;
}
-void
-score_node_get_instance_of
- (const struct score_node* instance,
- const struct score_node* node,
- struct ssol_instance** solver)
-{
- struct data data;
- int found = 0;
- ASSERT(instance && node && solver
- && instance->type == NODE_INSTANCE_ROOT
- && node->type == NODE_TEMPLATE);
-
- data.searched = node->data.template_node.solver_object;
- data.result = NULL;
- SANIM(node_search_tree(&instance->anim, &data, search, &found));
- ASSERT(data.result);
- *solver = data.result;
-}
diff --git a/src/core/solstice_core_node.h b/src/core/solstice_core_node.h
@@ -21,11 +21,11 @@
#include <rsys/dynamic_array.h>
#include <rsys/ref_count.h>
-struct sanim_node;
+struct score_node;
/* Define the darray_nodes data structure */
#define DARRAY_NAME nodes
-#define DARRAY_DATA struct sanim_node*
+#define DARRAY_DATA struct score_node*
#include <rsys/dynamic_array.h>
struct score_device;
@@ -35,32 +35,16 @@ struct ssol_object;
struct ssol_instance;
enum node_type {
- NODE_TEMPLATE_ROOT,
- NODE_INSTANCE_ROOT,
- NODE_TEMPLATE,
- NODE_INSTANCE,
+ NODE_GEOMETRY,
NODE_TRACKING_TARGET,
NODE_PIVOT,
+ NODE_EMPTY,
NODE_TYPES_COUNT__
};
-struct instance_root_data {
- struct score_scene* scene_attachment;
- struct score_node* template;
- /* keep own pivots */
- struct darray_nodes pivots;
-};
-
-struct template_node_data {
- struct ssol_object* solver_object;
- int receiver_mask;
- int sample;
-};
-
-struct instance_node_data {
+struct geometry_node_data {
struct ssol_instance* solver_instance;
- struct score_node* model;
int receiver_mask;
int sample;
};
@@ -70,9 +54,8 @@ struct score_node {
struct score_device* device;
struct sanim_node anim;
union {
- struct instance_root_data instance_root;
- struct template_node_data template_node;
- struct instance_node_data instance_node;
+ /* only types of nodes with specific data */
+ struct geometry_node_data geometry_node;
} data;
ref_T ref;
};
@@ -86,9 +69,4 @@ node_create
void
node_ref_put_children(struct sanim_node* node);
-res_T
-node_instanciate_any
- (struct score_node* tp_node,
- struct score_node** out_node);
-
#endif /* SOLSTICE_CORE_NODE_H */
diff --git a/src/core/solstice_core_scene.c b/src/core/solstice_core_scene.c
@@ -1,450 +0,0 @@
-/* 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 "solstice_core.h"
-#include "solstice_core_scene.h"
-#include "solstice_core_node.h"
-#include "solstice_core_device.h"
-
-#include <rsys/double3.h>
-
-#include <solstice/ssol.h>
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static INLINE struct sanim_node**
-contains(struct darray_nodes* array, struct sanim_node* elt)
-{
- size_t count, i;
- struct sanim_node** data;
- ASSERT(array && elt);
- count = darray_nodes_size_get(array);
- data = darray_nodes_data_get(array);
- for (i = 0; i < count; i++) {
- if (elt == data[i]) return &data[i];
- }
- return NULL;
-}
-
-static int
-remove_if(struct darray_nodes* array, struct sanim_node* elt)
-{
- size_t count;
- struct sanim_node** data;
- struct sanim_node** ptr;
- ASSERT(array && elt);
- ptr = contains(array, elt);
- if (ptr == NULL) return 0;
- count = darray_nodes_size_get(array);
- data = darray_nodes_data_get(array);
- *ptr = data[count - 1];
- darray_nodes_pop_back(array);
- return 1;
-}
-
-static res_T
-create_instance_tree_
- (struct darray_nodes* pivots,
- const struct score_node* t_node,
- struct score_node* i_node)
-{
- res_T res = RES_OK;
- size_t count, i;
- struct score_node* node = NULL;
- int p;
- ASSERT(pivots && t_node && i_node);
-
- SANIM(node_get_children_count(&t_node->anim, &count));
- for (i = 0; i < count; i++) {
- struct sanim_node* t_child_;
- struct score_node *t_child, *i_child;
- SANIM(node_get_child(&t_node->anim, i, &t_child_));
- t_child = CONTAINER_OF(t_child_, struct score_node, anim);
- res = node_instanciate_any(t_child, &i_child);
- if (res != RES_OK) goto error;
- res = sanim_node_add_child(&i_node->anim, &i_child->anim);
- if (res != RES_OK) goto error;
- create_instance_tree_(pivots, t_child, i_child);
- }
-
- SANIM(node_is_pivot(&i_node->anim, &p));
- if (p) {
- struct sanim_node* n = &i_node->anim;
- res = darray_nodes_push_back(pivots, &n);
- if (res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- if (node) {
- node = NULL;
- }
- goto exit;
-}
-
-static res_T
-create_instance_tree(struct score_node* instance)
-{
- res_T res = RES_OK;
- struct score_node* temp;
- ASSERT(instance && instance->type == NODE_INSTANCE_ROOT);
- node_ref_put_children(&instance->anim);
- darray_nodes_clear(&instance->data.instance_root.pivots);
- temp = instance->data.instance_root.template;
- ASSERT(temp->type == NODE_TEMPLATE_ROOT);
- res = create_instance_tree_(&instance->data.instance_root.pivots, temp, instance);
- if (res != RES_OK) goto error;
-exit:
- return res;
-error:
- node_ref_put_children(&instance->anim);
- darray_nodes_clear(&instance->data.instance_root.pivots);
- goto exit;
-}
-
-static res_T
-node_to_solver(const struct sanim_node* node_, const double transform[12], void* data)
-{
- struct score_node* node;
- struct ssol_scene* scene = data;
- res_T res = RES_OK;
- ASSERT(node_ && transform && data);
- node = CONTAINER_OF(node_, struct score_node, anim);
- switch (node->type) {
- case NODE_TEMPLATE_ROOT:
- ASSERT(0);
- break;
- case NODE_INSTANCE_ROOT:
- /* the root doesn't include any solver-related item */
- break;
- case NODE_TRACKING_TARGET:
- /* not a solver-related item */
- break;
- case NODE_TEMPLATE:
- ASSERT(0);
- break;
- case NODE_INSTANCE:
- SSOL(instance_set_transform(
- node->data.instance_node.solver_instance, transform));
- SSOL(instance_set_receiver(
- node->data.instance_node.solver_instance,
- node->data.instance_node.receiver_mask));
- SSOL(instance_sample(
- node->data.instance_node.solver_instance,
- node->data.instance_node.sample));
- res = ssol_scene_attach_instance(
- scene, node->data.instance_node.solver_instance);
- break;
- case NODE_PIVOT:
- /* not a solver-related item */
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
- return res;
-}
-
-static res_T
-node_to_solver_update(const struct sanim_node* node_, const double transform[12], void* data)
-{
- struct score_node* node;
- res_T res = RES_OK;
- (void) data;
- ASSERT(node_ && transform);
- node = CONTAINER_OF(node_, struct score_node, anim);
- switch (node->type) {
- case NODE_TEMPLATE_ROOT:
- ASSERT(0);
- break;
- case NODE_INSTANCE_ROOT:
- ASSERT(0); /* should only visit post-pivot nodes */
- break;
- case NODE_TRACKING_TARGET:
- /* not a solver-related item */
- break;
- case NODE_TEMPLATE:
- ASSERT(0);
- break;
- case NODE_INSTANCE:
- SSOL(instance_set_transform(
- node->data.instance_node.solver_instance, transform));
- break;
- case NODE_PIVOT:
- /* not a solver-related item */
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
- return res;
-}
-
-static INLINE res_T
-update_pivots(struct score_scene* scene, const double sun_dir[3])
-{
- size_t i_count, i;
- struct sanim_node** instances;
- res_T res = RES_OK;
- ASSERT(scene && sun_dir);
- i_count = darray_nodes_size_get(&scene->instances);
- instances = darray_nodes_data_get(&scene->instances);
- for (i = 0; i < i_count; i++) {
- size_t p_count, p;
- struct sanim_node** pivots;
- struct score_node* instance = CONTAINER_OF(instances[i], struct score_node, anim);
- ASSERT(instance->type == NODE_INSTANCE_ROOT);
- p_count = darray_nodes_size_get(&instance->data.instance_root.pivots);
- pivots = darray_nodes_data_get(&instance->data.instance_root.pivots);
- for (p = 0; p < p_count; p++) {
- struct score_node* pivot = CONTAINER_OF(pivots[p], struct score_node, anim);
- res = sanim_node_solve_pivot(&pivot->anim, sun_dir);
- if (res != RES_OK) return res;
- }
- }
- return RES_OK;
-}
-
-static void
-scene_release(ref_T* ref)
-{
- struct score_device* dev;
- struct score_scene* scene = CONTAINER_OF(ref, struct score_scene, ref);
- ASSERT(ref);
- dev = scene->device;
- ASSERT(dev && dev->allocator);
- score_scene_clear(scene);
- darray_nodes_release(&scene->instances);
- if (scene->solver) SSOL(scene_ref_put(scene->solver));
- if (scene->sun) SSOL(sun_ref_put(scene->sun));
- if (scene->atmosphere) SSOL(atmosphere_ref_put(scene->atmosphere));
- MEM_RM(dev->allocator, scene);
- score_device_ref_put(dev);
-}
-
-/*******************************************************************************
- * Exported score_scene functions
- ******************************************************************************/
-res_T
-score_scene_create
- (struct score_device* dev,
- struct score_scene** out_scene)
-{
- struct score_scene* scene;
- res_T res = RES_OK;
- ASSERT(dev && out_scene);
-
- scene = MEM_CALLOC(dev->allocator, 1, sizeof(struct score_scene));
- if (!scene) {
- res = RES_MEM_ERR;
- goto error;
- }
-
- score_device_ref_get(dev);
- scene->device = dev;
- ref_init(&scene->ref);
- darray_nodes_init(dev->allocator, &scene->instances);
-
- res = ssol_scene_create(dev->ssol, &scene->solver);
- if (res != RES_OK) goto error;
-
-exit:
- if (out_scene) *out_scene = scene;
- return res;
-error:
- if (scene) {
- score_scene_ref_put(scene);
- scene = NULL;
- }
- goto exit;
-}
-
-void
-score_scene_ref_get(struct score_scene* scene)
-{
- ASSERT(scene);
- ref_get(&scene->ref);
-}
-
-void
-score_scene_ref_put(struct score_scene* scene)
-{
- ASSERT(scene);
- ref_put(&scene->ref, scene_release);
-}
-
-res_T
-score_scene_attach_instance
- (struct score_scene* scene,
- struct score_node* instance)
-{
- struct sanim_node* anim;
- res_T res = RES_OK;
- int ok;
- ASSERT(scene && instance
- && instance->type == NODE_INSTANCE_ROOT
- && !instance->data.instance_root.scene_attachment);
- anim = &instance->anim;
- SANIM(node_is_initialized(anim, &ok));
- ASSERT(ok);
- res = darray_nodes_push_back(&scene->instances, &anim);
- if (res != RES_OK) goto error;
- instance->data.instance_root.scene_attachment = scene;
- score_node_ref_get(instance);
-exit:
- return res;
-error:
- remove_if(&scene->instances, anim);
- goto exit;
-}
-
-void
-score_scene_detach_instance
- (struct score_scene* scene,
- struct score_node* instance)
-{
- struct sanim_node* anim;
- int ok;
- ASSERT(scene && instance
- && instance->type == NODE_INSTANCE_ROOT
- && instance->data.instance_root.scene_attachment == scene);
- anim = &instance->anim;
- SANIM(node_is_initialized(anim, &ok));
- ASSERT(ok);
- ok = remove_if(&scene->instances, anim);
- ASSERT(ok);
- instance->data.instance_root.scene_attachment = NULL;
- score_node_ref_put(instance);
-}
-
-void
-score_scene_attach_sun
- (struct score_scene* scene,
- struct ssol_sun* sun)
-{
- ASSERT(scene && sun);
- SSOL(scene_attach_sun(scene->solver, sun));
- SSOL(sun_ref_get(sun));
- scene->sun = sun;
-}
-
-void
-score_scene_detach_sun
- (struct score_scene* scene,
- struct ssol_sun* sun)
-{
- ASSERT(scene && sun);
- SSOL(scene_detach_sun(scene->solver, sun));
- SSOL(sun_ref_put(sun));
- scene->sun = NULL;
-}
-
-void
-score_scene_attach_atmosphere
- (struct score_scene* scene,
- struct ssol_atmosphere* atm)
-{
- ASSERT(scene && atm);
- SSOL(scene_attach_atmosphere(scene->solver, atm));
- SSOL(atmosphere_ref_get(atm));
- scene->atmosphere = atm;
-}
-
-void
-score_scene_detach_atmosphere
- (struct score_scene* scene,
- struct ssol_atmosphere* atm)
-{
- ASSERT(scene && atm);
- SSOL(scene_detach_atmosphere(scene->solver, atm));
- SSOL(atmosphere_ref_put(atm));
- scene->atmosphere = NULL;
-}
-
-void
-score_scene_clear
- (struct score_scene* scene)
-{
- size_t count, i;
- struct sanim_node** data;
- ASSERT(scene);
- count = darray_nodes_size_get(&scene->instances);
- data = darray_nodes_data_get(&scene->instances);
- for (i = 0; i < count; i++) {
- struct score_node* node = CONTAINER_OF(data[i], struct score_node, anim);
- score_node_ref_put(node);
- }
- darray_nodes_clear(&scene->instances);
-}
-
-res_T
-score_scene_reset_simulation(struct score_scene* scene)
-{
- res_T res = RES_OK;
- size_t count = 0, i;
- struct sanim_node** instances;
- double sun_dir[3];
- ASSERT(scene && scene->sun);
- SSOL(sun_get_direction(scene->sun, sun_dir));
- count = darray_nodes_size_get(&scene->instances);
- instances = darray_nodes_data_get(&scene->instances);
- SSOL(scene_clear(scene->solver));
- SSOL(scene_attach_sun(scene->solver, scene->sun));
- if (scene->atmosphere)
- SSOL(scene_attach_atmosphere(scene->solver, scene->atmosphere));
- for (i = 0; i < count; i++) {
- struct score_node* inst = CONTAINER_OF(instances[i], struct score_node, anim);
- ASSERT(inst->type == NODE_INSTANCE_ROOT);
- res = create_instance_tree(inst);
- if (res != RES_OK) goto error;
- res = sanim_node_visit_tree(
- instances[i], sun_dir, scene->solver, &node_to_solver);
- if (res != RES_OK) goto error;
- }
-exit:
- return res;
-error:
- for (i = 0; i < count; i++) node_ref_put_children(instances[i]);
- goto exit;
-}
-
-res_T
-score_scene_update_simulation(struct score_scene* scene)
-{
- res_T res = RES_OK;
- size_t count = 0, i;
- size_t p_count = 0, p;
- struct sanim_node** instances;
- double sun_dir[3];
- ASSERT(scene && scene->sun);
- SSOL(sun_get_direction(scene->sun, sun_dir));
- count = darray_nodes_size_get(&scene->instances);
- instances = darray_nodes_data_get(&scene->instances);
- for (i = 0; i < count; i++) {
- struct sanim_node** pivots;
- struct score_node* inst = CONTAINER_OF(instances[i], struct score_node, anim);
- ASSERT(inst->type == NODE_INSTANCE_ROOT);
- p_count = darray_nodes_size_get(&inst->data.instance_root.pivots);
- pivots = darray_nodes_data_get(&inst->data.instance_root.pivots);
- for (p = 0; p < p_count; p++) {
- res = sanim_node_visit_tree(
- pivots[p], sun_dir, NULL, &node_to_solver_update);
- if (res != RES_OK) goto error;
- }
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
diff --git a/src/core/solstice_core_scene.h b/src/core/solstice_core_scene.h
@@ -1,40 +0,0 @@
-/* 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 SCORE_SCENE_H
-#define SCORE_SCENE_H
-
-#include "solstice_core.h"
-#include "solstice_core_node.h"
-
-#include <rsys/dynamic_array.h>
-#include <rsys/ref_count.h>
-
-struct ssol_scene;
-struct ssol_sun;
-struct ssol_atmosphere;
-
-struct score_device;
-
-struct score_scene {
- struct score_device* device;
- struct darray_nodes instances;
- struct ssol_scene* solver;
- struct ssol_sun* sun;
- struct ssol_atmosphere* atmosphere;
- ref_T ref;
-};
-
-#endif /* SCORE_SCENE_H */
diff --git a/src/core/solstice_core_solver.c b/src/core/solstice_core_solver.c
@@ -14,18 +14,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "solstice_core.h"
-#include "solstice_core_scene.h"
+#include "solstice_core_device.h"
#include <solstice/ssol.h>
res_T
score_solve
- (struct score_scene* scene,
+ (struct score_device* dev,
struct ssp_rng* rng,
const size_t realisations_count,
FILE* output,
struct ssol_estimator* estimator)
{
- ASSERT(scene && rng && realisations_count && output && estimator);
- return ssol_solve(scene->solver, rng, realisations_count, output, estimator);
+ ASSERT(dev && rng && realisations_count && output && estimator);
+ return ssol_solve(dev->solver, rng, realisations_count, output, estimator);
}
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
@@ -13,48 +13,21 @@
* 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 "parser/solparser.h"
+#include "solstice_args.h"
#include <rsys/rsys.h>
int
main(int argc, char** argv)
{
- FILE* file = NULL;
- struct solparser* parser = NULL;
+ struct solstice_args args;
res_T res;
int err = 0;
- int i;
- if(argc < 2) {
- fprintf(stderr, "Usage: %s FILE [FILE ...]\n", argv[0]);
- err = 1;
- goto error;
- }
-
- res = solparser_create(NULL, &parser);
+ res = solstice_args_init(&args, argc, argv);
if(res != RES_OK) goto error;
- FOR_EACH(i, 1, argc) {
- file = fopen(argv[i], "rb");
- if(!file) {
- fprintf(stderr, "Could not open the file `%s'.\n", argv[i]);
- goto error;
- }
-
- res = solparser_setup(parser, argv[i], file);
- if(res != RES_OK) break;
-
- do {
- res = solparser_load(parser);
- } while(res != RES_BAD_OP);
-
- fclose(file);
- file = NULL;
- }
-
exit:
- if(parser) solparser_ref_put(parser);
- if(file) fclose(file);
+ solstice_args_release(&args);
return err;
error:
err = -1;
diff --git a/src/solstice.h b/src/solstice.h
@@ -25,23 +25,38 @@ struct solparser;
struct ssol_device;
struct ssol_material;
struct ssol_object;
+struct sanim_node;
+struct score_device;
+struct score_node;
#define HTABLE_NAME material
#define HTABLE_KEY size_t
#define HTABLE_DATA struct ssol_material*
#include <rsys/hash_table.h>
+#include <rsys/dynamic_array.h>
#define HTABLE_NAME object
#define HTABLE_KEY size_t
#define HTABLE_DATA struct ssol_object*
#include <rsys/hash_table.h>
+#define HTABLE_NAME anchor
+#define HTABLE_KEY size_t
+#define HTABLE_DATA struct score_node*
+#include <rsys/hash_table.h>
+
+#include "core/solstice_core_node.h"
+
struct solstice {
struct ssol_device* ssol;
struct solparser* parser;
+ struct score_device* score;
struct htable_material materials;
struct htable_object objects;
+ struct htable_anchor anchors;
+ struct darray_nodes roots;
+ struct darray_nodes pivots;
struct mem_allocator* allocator;
};
diff --git a/src/solstice_args.c b/src/solstice_args.c
@@ -0,0 +1,283 @@
+/* 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/>. */
+
+#define _POSIX_C_SOURCE 2
+
+#include "solstice_args.h"
+
+#include <rsys/cstr.h>
+#include <rsys/double3.h>
+
+#ifdef COMPILER_CL
+ #include <getopt.h>
+ #define strtok_r strtok_s
+#else
+ #include <unistd.h>
+#endif
+
+#include <string.h>
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+print_help(const char* program)
+{
+ printf(
+"Usage: %s [OPTIONS] [FILE]\n"
+"Integrate the solar flux in complex solar facilities.\n",
+ program);
+ /* TODO print short help for the options */
+}
+
+static res_T
+parse_fov(const char* str, double* out_fov)
+{
+ double fov;
+ res_T res = RES_OK;
+ ASSERT(str && out_fov);
+
+ res = cstr_to_double(str, &fov);
+ if(res != RES_OK) {
+ fprintf(stderr, "Invalid field of view `%s'.\n", str);
+ return RES_BAD_ARG;
+ }
+
+ if(fov < 30 || fov > 120) {
+ fprintf(stderr, "The field of view %g is not in [30, 120].\n", fov);
+ return RES_BAD_ARG;
+ }
+ *out_fov = MDEG2RAD(fov);
+ return RES_OK;
+}
+
+
+static res_T
+parse_double3(const char* str, double dbl3[3])
+{
+ char buf[64];
+ char* tk;
+ char* ctx;
+ res_T res = RES_OK;
+ ASSERT(str && dbl3);
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the string `%s'.\n", str);
+ return RES_MEM_ERR;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ tk = strtok_r(buf, ",", &ctx);
+ res = cstr_to_double(tk, dbl3+0);
+ if(res != RES_OK) return res;
+
+ tk = strtok_r(NULL, ",", &ctx);
+ res = cstr_to_double(tk, dbl3+1);
+ if(res != RES_OK) return res;
+
+ tk = strtok_r(NULL, "", &ctx);
+ res = cstr_to_double(tk, dbl3+2);
+ if(res != RES_OK) return res;
+
+ return RES_OK;
+}
+
+static res_T
+parse_image_definition
+ (const char* str,
+ unsigned long* width,
+ unsigned long* height)
+{
+ char buf[64];
+ char* tk;
+ char* ctx;
+ res_T res = RES_OK;
+ ASSERT(str && width && height);
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the image definition string `%s'.\n", str);
+ return RES_MEM_ERR;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ tk = strtok_r(buf, "x", &ctx);
+ res = cstr_to_ulong(tk, width);
+ if(res != RES_OK) {
+ fprintf(stderr, "Invalid image width `%s'\n", tk);
+ return res;
+ }
+
+ tk = strtok_r(NULL, "", &ctx);
+ res = cstr_to_ulong(tk, height);
+ if(res != RES_OK) {
+ fprintf(stderr, "Invalid image height `%s'\n", tk);
+ return res;
+ }
+
+ return res;
+}
+
+static res_T
+parse_rendering_option(const char* str, struct solstice_args* args)
+{
+ char buf[128];
+ char* key;
+ char* val;
+ char* ctx;
+ res_T res;
+ ASSERT(str && args);
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the rendering option string `%s'\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ key = strtok_r(buf, "=", &ctx);
+ val = strtok_r(NULL, "", &ctx);
+
+ if(!strcmp(key, "fov")) {
+ res = parse_fov(val, &args->camera.fov_x);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(key, "img")) {
+ res = parse_image_definition(val, &args->img.width, &args->img.height);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(key, "pos")) {
+ res = parse_double3(val, args->camera.pos);
+ if(res != RES_OK) {
+ fprintf(stderr, "Invalid camera position `%s'.\n", val);
+ goto error;
+ }
+ } else if(!strcmp(key, "tgt")) {
+ res = parse_double3(val, args->camera.tgt);
+ if(res != RES_OK) {
+ fprintf(stderr, "Invalid camera target `%s'.\n", val);
+ goto error;
+ }
+ } else if(!strcmp(key, "up")) {
+ res = parse_double3(val, args->camera.up);
+ if(res != RES_OK) {
+ fprintf(stderr, "Invalid camera up vector `%s'.\n", val);
+ goto error;
+ }
+ } else {
+ fprintf(stderr, "Invalid rendering option `%s'.\n", val);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ args->rendering = 1;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_rendering_options(const char* str, struct solstice_args* args)
+{
+ char buf[512];
+ char* tk;
+ char* ctx;
+ res_T res = RES_OK;
+ ASSERT(args);
+ (void)str, (void)args;
+
+ /* Setup default values of the rendering parameters */
+ d3(args->camera.pos, 0, 0, 0);
+ d3(args->camera.tgt, 0, 0, -1);
+ d3(args->camera.up, 0, 1, 0);
+ args->camera.fov_x = MDEG2RAD(70);
+ args->img.width = 800;
+ args->img.height = 600;
+
+ if(!str) goto exit;
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the rendering options string `%s'.\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ tk = strtok_r(buf, ":", &ctx);
+ do {
+ res = parse_rendering_option(tk, args);
+ tk = strtok_r(NULL, ":", &ctx);
+ } while(tk);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * Local function
+ ******************************************************************************/
+res_T
+solstice_args_init(struct solstice_args* args, const int argc, char** argv)
+{
+ int opt;
+ res_T res = RES_OK;
+ ASSERT(args && argc && argv);
+
+ *args = SOLSTICE_ARGS_DEFAULT;
+
+ optind = 1;
+ while((opt = getopt(argc, argv, "hn:o:qr:")) != -1) {
+ switch(opt) {
+ case 'h':
+ print_help(argv[0]);
+ solstice_args_release(args);
+ goto exit;
+ case 'n':
+ res = cstr_to_ulong(optarg, &args->nrealisations);
+ if(res != RES_OK && !args->nrealisations) res = RES_BAD_ARG;
+ break;
+ case 'o': args->output_filename = optarg; break;
+ case 'q': args->quiet = 1; break;
+ case 'r': res = parse_rendering_options(optarg, args); break;
+ default: res = RES_BAD_ARG; break;
+ }
+ if(res != RES_OK) {
+ if(optarg) {
+ fprintf(stderr, "%s: invalid option argument '%s' -- '%c'\n",
+ argv[0], optarg, opt);
+ }
+ goto error;
+ }
+ }
+
+exit:
+ optind = 1;
+ return res;
+error:
+ solstice_args_release(args);
+ goto exit;
+}
+
+void
+solstice_args_release(struct solstice_args* args)
+{
+ ASSERT(args);
+ *args = SOLSTICE_ARGS_NULL;
+}
+
diff --git a/src/solstice_args.h.in b/src/solstice_args.h.in
@@ -0,0 +1,77 @@
+/* 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 SOLSTICE_ARGS_H
+#define SOLSTICE_ARGS_H
+
+#include <rsys/math.h>
+
+struct solstice_args {
+ const char* output_filename;
+ unsigned long nrealisations; /* #realisations */
+
+ struct {
+ double pos[3];
+ double tgt[3];
+ double up[3];
+ double fov_x;
+ } camera;
+
+ struct {
+ unsigned long width;
+ unsigned long height;
+ } img;
+
+ int rendering;
+ int quiet;
+};
+
+#define SOLSTICE_ARGS_NULL__ {0}
+static const struct solstice_args SOLSTICE_ARGS_NULL = SOLSTICE_ARGS_NULL__;
+
+#define SOLSTICE_ARGS_DEFAULT__ { \
+ NULL, /* Output_filename */ \
+ @SOLSTICE_ARGS_DEFAULT_NREALISATIONS@, \
+ \
+ { /* Camera */ \
+ { @SOLSTICE_ARGS_DEFAULT_CAMERA_POS@ }, \
+ { @SOLSTICE_ARGS_DEFAULT_CAMERA_TGT@ }, \
+ { @SOLSTICE_ARGS_DEFAULT_CAMERA_UP@ }, \
+ MDEG2RAD(@SOLSTICE_ARGS_DEFAULT_CAMERA_FOV@) \
+ }, \
+ \
+ { /* Image */ \
+ @SOLSTICE_ARGS_DEFAULT_IMG_WIDTH@, \
+ @SOLSTICE_ARGS_DEFAULT_IMG_HEIGHT@ \
+ }, \
+ \
+ 0, /* Rendering */ \
+ 0 /* Quiet */ \
+}
+static const struct solstice_args SOLSTICE_ARGS_DEFAULT =
+ SOLSTICE_ARGS_DEFAULT__;
+
+extern LOCAL_SYM res_T
+solstice_args_init
+ (struct solstice_args* args,
+ const int argc,
+ char** argv);
+
+extern LOCAL_SYM void
+solstice_args_release
+ (struct solstice_args* args);
+
+#endif /* SOLSTICE_ARGS_H */
+
diff --git a/src/solstice_c.h b/src/solstice_c.h
@@ -22,6 +22,10 @@
struct ssol_instance;
extern LOCAL_SYM res_T
+solstice_setup_entities
+ (struct solstice* solstice);
+
+extern LOCAL_SYM res_T
solstice_get_ssol_material
(struct solstice* solstice,
const struct solparser_material_id mtl_id,
diff --git a/src/solstice_entity.c b/src/solstice_entity.c
@@ -1,17 +1,208 @@
/* 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/>. */
+ *
+ * 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 "solstice.h"
#include "solstice_c.h"
+
+#include <solstice/ssol.h>
+#include <solstice/sanim.h>
+#include "core/solstice_core.h"
+
+/*******************************************************************************
+ * Helper function
+ ******************************************************************************/
+static res_T
+solstice_setup_entity
+ (struct solstice* solstice,
+ const struct solparser_entity* entity,
+ const char is_root,
+ struct score_node** out_node)
+{
+ struct score_node* root_node = NULL;
+ struct score_node* atchmnt_node = NULL;
+ struct ssol_instance* instance = NULL;
+ const struct solparser_anchor_id* anchors = NULL;
+ const struct solparser_entity_id* children = NULL;
+ size_t count, i;
+ res_T res = RES_OK;
+ ASSERT(solstice && solstice->parser && solstice->score && entity);
+
+ /* TODO Split the cases un sub-functions! */
+ switch (entity->type) {
+ case SOLPARSER_ENTITY_EMPTY:
+ {
+ struct score_node* empty_node = NULL;
+ res = score_node_empty_create(solstice->score, &empty_node);
+ if (res != RES_OK) goto error;
+ score_node_set_translation(empty_node, entity->translation);
+ score_node_set_rotations(empty_node, entity->rotation);
+ atchmnt_node = root_node = empty_node;
+ break;
+ }
+ case SOLPARSER_ENTITY_GEOMETRY:
+ {
+ struct score_node* geometry_node = NULL;
+ res = score_node_geometry_create(solstice->score, &geometry_node);
+ if (res != RES_OK) goto error;
+ score_node_set_translation(geometry_node, entity->translation);
+ score_node_set_rotations(geometry_node, entity->rotation);
+ res = solstice_instantiate_geometry(
+ /* TODO: attach instance to solver */
+ solstice, entity->data.geometry, &instance);
+ if (res != RES_OK) goto error;
+ res = score_node_geometry_setup(geometry_node, instance);
+ if (res != RES_OK) goto error;
+ atchmnt_node = root_node = geometry_node;
+ break;
+ }
+ case SOLPARSER_ENTITY_PIVOT:
+ {
+ /* Each entity introduces a new coordinate system
+ * and each object or pivot has some positionning in this system.
+ * This behaviour is implemented through 2 levels of sanim_node. */
+ /* TODO: remove pivot positionning? */
+ struct score_node* entity_node = NULL;
+ struct score_node* pivot_node = NULL;
+ const struct solparser_pivot* parser_pivot = NULL;
+ struct sanim_pivot anim_pivot = SANIM_PIVOT_NULL;
+ struct sanim_tracking anim_tracking = SANIM_TRACKING_NULL;
+ res = score_node_empty_create(solstice->score, &entity_node);
+ if (res != RES_OK) goto error;
+ score_node_set_translation(entity_node, entity->translation);
+ score_node_set_rotations(entity_node, entity->rotation);
+ res = score_node_pivot_create(solstice->score, &pivot_node);
+ if (res != RES_OK) goto error;
+ parser_pivot = solparser_get_pivot(solstice->parser, entity->data.pivot);
+ ASSERT(parser_pivot);
+ score_node_set_translation(pivot_node, parser_pivot->translation);
+ score_node_set_rotations(pivot_node, parser_pivot->rotation);
+ /* TODO: 2-axis pivots */
+ anim_pivot.type = PIVOT_SINGLE_AXIS;
+ d3_set(anim_pivot.data.pivot1.ref_normal, parser_pivot->normal);
+ d3_set(anim_pivot.data.pivot1.ref_point, parser_pivot->point);
+ switch (parser_pivot->target_type) {
+ case SOLPARSER_TARGET_ANCHOR:
+ {
+ struct score_node** ptgt = NULL;
+ const struct solparser_anchor_id id = parser_pivot->target.anchor;
+ anim_tracking.policy = TRACKING_NODE_TARGET;
+ ptgt = htable_anchor_find(&solstice->anchors, &id.i);
+ score_node_track_me(*ptgt, &anim_tracking);
+ break;
+ }
+ case SOLPARSER_TARGET_DIRECTION:
+ anim_tracking.policy = TRACKING_OUT_DIR;
+ d3_set(anim_tracking.data.out_dir.u, parser_pivot->target.direction);
+ break;
+ case SOLPARSER_TARGET_POSITION:
+ anim_tracking.policy = TRACKING_POINT;
+ d3_set(anim_tracking.data.point.target, parser_pivot->target.position);
+ anim_tracking.data.point.target_is_local = 0; /* TODO */
+ break;
+ case SOLPARSER_TARGET_SUN:
+ anim_tracking.policy = TRACKING_SUN;
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ res = score_node_pivot_setup(pivot_node, &anim_pivot, &anim_tracking);
+ if (res != RES_OK) goto error;
+ res = darray_nodes_push_back(&solstice->pivots, &pivot_node);
+ if (res != RES_OK) goto error;
+ root_node = entity_node;
+ atchmnt_node = pivot_node;
+ break;
+ }
+ default: FATAL("Unreachable code.\n"); break;
+ }
+
+ ASSERT(root_node && atchmnt_node);
+ if (is_root) darray_nodes_push_back(&solstice->roots, &root_node);
+
+ /* register anchors */
+ count = darray_anchor_id_size_get(&entity->anchors);
+ anchors = darray_anchor_id_cdata_get(&entity->anchors);
+ for (i = 0; i < count; i++) {
+ struct score_node* tgt;
+ const struct solparser_anchor* anchor = NULL;
+ res = score_node_tracking_target_create(solstice->score, &tgt);
+ if (res != RES_OK) goto error;
+ anchor = solparser_get_anchor(solstice->parser, anchors[i]);
+ ASSERT(anchor);
+ res = htable_anchor_set(&solstice->anchors, &anchors[i].i, &tgt);
+ if (res != RES_OK) goto error;
+ score_node_set_translation(tgt, anchor->position);
+ res = score_node_add_child(atchmnt_node, tgt);
+ if (res != RES_OK) goto error;
+ }
+
+ /* TODO: setup children */
+ count = solparser_entity_get_children_count(entity);
+ children = darray_child_id_cdata_get(&entity->children);
+ for (i = 0; i < count; i++) {
+ const struct solparser_entity* child;
+ struct score_node* child_root = NULL;
+ child = solparser_get_entity(solstice->parser, children[i]);
+ ASSERT(child);
+ res = solstice_setup_entity(solstice, child, 0, &child_root);
+ if (res != RES_OK) goto error;
+ ASSERT(child_root);
+ res = score_node_add_child(atchmnt_node, child_root);
+ if (res != RES_OK) goto error;
+ }
+
+end:
+ if (out_node) *out_node = root_node;
+ return res;
+
+error:
+ goto end;
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+solstice_setup_entities
+ (struct solstice* solstice)
+{
+ struct solparser_entity_iterator it, it_end;
+ res_T res = RES_OK;
+ ASSERT(solstice && solstice->parser && solstice->score);
+
+ /* Release possible previous roots (incomplete, TODO) */
+ score_scene_clear(solstice->score);
+
+ /* (re) create the list of roots from entities */
+ solparser_entity_iterator_begin(solstice->parser, &it);
+ solparser_entity_iterator_end(solstice->parser, &it);
+ while (!solparser_entity_iterator_eq(&it, &it_end)) {
+ struct solparser_entity_id entity_id;
+ const struct solparser_entity* entity;
+
+ entity_id = solparser_entity_iterator_get(&it);
+ entity = solparser_get_entity(solstice->parser, entity_id);
+
+ res = solstice_setup_entity(solstice, entity, 1, NULL);
+ if (res != RES_OK) goto error;
+
+ solparser_entity_iterator_next(&it);
+ }
+
+end:
+ return res;
+error:
+ goto end;
+}
+
diff --git a/src/solstice_material.c b/src/solstice_material.c
@@ -122,7 +122,6 @@ create_material_mirror
res = RES_MEM_ERR;
goto error;
}
-
param->reflectivity = mirror->reflectivity;
param->roughness = mirror->roughness;
diff --git a/src/test_solstice_args.c b/src/test_solstice_args.c
@@ -0,0 +1,130 @@
+/* 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 "solstice_args.h"
+#include "test_solstice_utils.h"
+
+#include <rsys/double3.h>
+#include <rsys/stretchy_array.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+static char**
+cmd_create(int dummy, ...)
+{
+ va_list ap;
+ va_list ap_cp;
+ const char* str;
+ size_t i, n = 0;
+ char** cmd = NULL;
+
+ va_start(ap, dummy);
+ VA_COPY(ap_cp, ap);
+ while((str = va_arg(ap, const char*))) ++n;
+ va_end(ap);
+
+ NCHECK(cmd = sa_add(cmd, n), NULL);
+ i = 0;
+ while((str = va_arg(ap_cp, const char*))) {
+ cmd[i] = NULL;
+ NCHECK(cmd[i] = sa_add(cmd[i], strlen(str)+1), NULL);
+ strcpy(cmd[i], str);
+ ++i;
+ }
+ va_end(ap_cp);
+ return cmd;
+}
+
+static void
+cmd_delete(char** cmd)
+{
+ size_t i = 0;
+ const size_t n = sa_size(cmd);
+ FOR_EACH(i, 0, n) sa_release(cmd[i]);
+ sa_release(cmd);
+}
+
+static FINLINE int
+cmd_size(char** cmd)
+{
+ return (int)sa_size(cmd);
+}
+
+int
+main(int argc, char** argv)
+{
+ struct solstice_args args = SOLSTICE_ARGS_NULL;
+ char** cmd = NULL;
+ double tmp[3];
+ (void)argc, (void)argv;
+
+ cmd = cmd_create(0, "test", "-r", "img=1280x720", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.rendering, 1);
+ CHECK(args.nrealisations, SOLSTICE_ARGS_DEFAULT.nrealisations);
+ CHECK(d3_eq(args.camera.pos, SOLSTICE_ARGS_DEFAULT.camera.pos), 1);
+ CHECK(d3_eq(args.camera.tgt, SOLSTICE_ARGS_DEFAULT.camera.tgt), 1);
+ CHECK(d3_eq(args.camera.up, SOLSTICE_ARGS_DEFAULT.camera.up), 1);
+ CHECK(args.camera.fov_x, SOLSTICE_ARGS_DEFAULT.camera.fov_x);
+ CHECK(args.img.width, 1280);
+ CHECK(args.img.height, 720);
+ CHECK(args.quiet, 0);
+ CHECK(args.output_filename, NULL);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-q", "-r", "img=640x480:fov=70:pos=1,2,3", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.rendering, 1);
+ CHECK(args.nrealisations, SOLSTICE_ARGS_DEFAULT.nrealisations);
+ CHECK(d3_eq(args.camera.pos, d3(tmp, 1, 2, 3)), 1);
+ CHECK(d3_eq(args.camera.tgt, SOLSTICE_ARGS_DEFAULT.camera.tgt), 1);
+ CHECK(d3_eq(args.camera.up, SOLSTICE_ARGS_DEFAULT.camera.up), 1);
+ CHECK(args.img.width, 640);
+ CHECK(args.img.height, 480);
+ CHECK(args.quiet, 1);
+ CHECK(eq_eps(args.camera.fov_x, MDEG2RAD(70), 1.e-6), 1);
+ CHECK(args.output_filename, NULL);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-r", "up=0,0,1:tgt=0,-10,0", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.nrealisations, SOLSTICE_ARGS_DEFAULT.nrealisations);
+ CHECK(d3_eq(args.camera.pos, SOLSTICE_ARGS_DEFAULT.camera.pos), 1);
+ CHECK(d3_eq(args.camera.tgt, d3(tmp, 0,-10, 0)), 1);
+ CHECK(d3_eq(args.camera.up, d3(tmp, 0, 0, 1)), 1);
+ CHECK(args.img.width, SOLSTICE_ARGS_DEFAULT.img.width);
+ CHECK(args.img.height, SOLSTICE_ARGS_DEFAULT.img.height);
+ CHECK(args.rendering, 1);
+ CHECK(args.quiet, 0);
+ CHECK(args.output_filename, NULL);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-r", "up=0,10,0", "-o", "my_output", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(d3_eq(args.camera.up, d3(tmp, 0, 10, 0)), 1);
+ CHECK(args.rendering, 1);
+ CHECK(args.quiet, 0);
+ CHECK(strcmp(args.output_filename, "my_output"), 0);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
+