star-enclosures-3d

Extract enclosures from 3D geometry
git clone git://git.meso-star.fr/star-enclosures-3d.git
Log | Files | Refs | README | LICENSE

commit acae3736a9595dab4b4606ffef961a7365781743
parent e70b1309a821c6ef260ecdbd724755006a4ef216
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed,  5 Feb 2020 15:10:08 +0100

Rename everything senc3d (from senc) for coherency reasons

Diffstat:
MREADME.md | 10+++++-----
Mcmake/CMakeLists.txt | 140+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Dsrc/senc.h | 364-------------------------------------------------------------------------------
Asrc/senc3d.h | 364+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_descriptor.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_device.c | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_device_c.h | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_enclosure.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_enclosure_c.h | 37+++++++++++++++++++++++++++++++++++++
Asrc/senc3d_enclosure_data.h | 235+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_internal_types.h | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_s3d_helper.h | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_scene.c | 327+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_scene_analyze.c | 1347+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_scene_analyze_c.h | 201+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_scene_c.h | 302++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/senc3d_side_range.h | 44++++++++++++++++++++++++++++++++++++++++++++
Dsrc/sencX3.h | 423-------------------------------------------------------------------------------
Asrc/sencX3d.h | 488+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/senc_descriptor.c | 160-------------------------------------------------------------------------------
Dsrc/senc_device.c | 148-------------------------------------------------------------------------------
Dsrc/senc_device_c.h | 71-----------------------------------------------------------------------
Dsrc/senc_enclosure.c | 167-------------------------------------------------------------------------------
Dsrc/senc_enclosure_c.h | 37-------------------------------------
Dsrc/senc_enclosure_data.h | 235-------------------------------------------------------------------------------
Dsrc/senc_internal_types.h | 142-------------------------------------------------------------------------------
Dsrc/senc_s3d_helper.h | 92-------------------------------------------------------------------------------
Dsrc/senc_scene.c | 327-------------------------------------------------------------------------------
Dsrc/senc_scene_analyze.c | 1347-------------------------------------------------------------------------------
Dsrc/senc_scene_analyze_c.h | 201-------------------------------------------------------------------------------
Dsrc/senc_scene_c.h | 302------------------------------------------------------------------------------
Dsrc/senc_side_range.h | 44--------------------------------------------
Asrc/test_senc3d_cube_behind_cube.c | 311+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_cube_in_cube.c | 314+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_cube_on_cube.c | 205+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_device.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_enclosure.c | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_inconsistant_cube.c | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_many_enclosures.c | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_many_triangles.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_sample_enclosure.c | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_scene.c | 296+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_some_enclosures.c | 3427+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_some_triangles.c | 2737+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_unspecified_medium.c | 327+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_utils.h | 271+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_senc3d_utils2.h | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/test_senc_cube_behind_cube.c | 311-------------------------------------------------------------------------------
Dsrc/test_senc_cube_in_cube.c | 314-------------------------------------------------------------------------------
Dsrc/test_senc_cube_on_cube.c | 205-------------------------------------------------------------------------------
Dsrc/test_senc_device.c | 77-----------------------------------------------------------------------------
Dsrc/test_senc_enclosure.c | 248-------------------------------------------------------------------------------
Dsrc/test_senc_inconsistant_cube.c | 145-------------------------------------------------------------------------------
Dsrc/test_senc_many_enclosures.c | 108-------------------------------------------------------------------------------
Dsrc/test_senc_many_triangles.c | 101-------------------------------------------------------------------------------
Dsrc/test_senc_sample_enclosure.c | 124-------------------------------------------------------------------------------
Dsrc/test_senc_scene.c | 296-------------------------------------------------------------------------------
Dsrc/test_senc_some_enclosures.c | 3427-------------------------------------------------------------------------------
Dsrc/test_senc_some_triangles.c | 2737-------------------------------------------------------------------------------
Dsrc/test_senc_unspecified_medium.c | 327-------------------------------------------------------------------------------
Dsrc/test_senc_utils.h | 271-------------------------------------------------------------------------------
Dsrc/test_senc_utils2.h | 107-------------------------------------------------------------------------------
62 files changed, 13000 insertions(+), 12931 deletions(-)

diff --git a/README.md b/README.md @@ -1,10 +1,10 @@ -StarEnclosures -============== +Star-enclosures-3d +================== Overview -------- -The purpose of Star-enclosures is to extract enclosures from raw +The purpose of Star-enclosures-3d is to extract enclosures from raw geometry. An enclosure is a set of triangles enclosing a given volume. The enclosure notion extends to open enclosures for which there is no inside or outside. For every detected enclosure, the library provides @@ -22,7 +22,7 @@ triangles can be set. How to build ------------ -StarEnclosures relies on the [CMake](http://www.cmake.org) and the +Star-enclosures-3d relies on the [CMake](http://www.cmake.org) and the [RCMake](https://gitlab.com/vaplv/rcmake/) package to build. It also depends on the [RSys](https://gitlab.com/vaplv/rsys/) and [Star-3D](https://gitlab.com/meso-star/star-3d/) libraries. Additionaly, @@ -91,7 +91,7 @@ Release notes License ------- -StarEnclosures is Copyright (C) |Méso|Star> 2019-2020 +Star-enclosures-3d is Copyright (C) |Méso|Star> 2019-2020 (<a href="mailto:contact@meso-star.com" class="email">contact@meso-star.com</a>). It is free software released under the GPLv3+ license. You are welcome to redistribute it under certain conditions; refer to the COPYING files diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -14,12 +14,12 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required(VERSION 3.1) -project(Star-Enclosures C) +project(star-enclosures-3d C) enable_testing() include(CMakeDependentOption) -set(SENC_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) +set(SENC3D_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) option(NO_TEST "Do not build tests" OFF) cmake_dependent_option(HUGE_ADDITIONAL_TESTS @@ -72,58 +72,58 @@ set(VERSION_MINOR 4) set(VERSION_PATCH 2) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(SENC_FILES_SRC - senc_descriptor.c - senc_device.c - senc_enclosure.c - senc_scene.c - senc_scene_analyze.c) - -set(SENC_FILES_INC_API - senc.h - senc_s3d_helper.h - sencX3.h) - -set(SENC_FILES_INC - senc_device_c.h - senc_enclosure_c.h - senc_enclosure_data.h - senc_internal_types.h - senc_scene_c.h - senc_scene_analyze_c.h - senc_side_range.h) - -set(SENC_FILES_DOC COPYING README.md) - -# Prepend each file by `SENC_SOURCE_DIR' -rcmake_prepend_path(SENC_FILES_SRC ${SENC_SOURCE_DIR}) -rcmake_prepend_path(SENC_FILES_INC ${SENC_SOURCE_DIR}) -rcmake_prepend_path(SENC_FILES_INC_API ${SENC_SOURCE_DIR}) -rcmake_prepend_path(SENC_FILES_DOC ${PROJECT_SOURCE_DIR}/../) +set(SENC3D_FILES_SRC + senc3d_descriptor.c + senc3d_device.c + senc3d_enclosure.c + senc3d_scene.c + senc3d_scene_analyze.c) + +set(SENC3D_FILES_INC_API + senc3d.h + senc3d_s3d_helper.h + sencX3d.h) + +set(SENC3D_FILES_INC + senc3d_device_c.h + senc3d_enclosure_c.h + senc3d_enclosure_data.h + senc3d_internal_types.h + senc3d_scene_c.h + senc3d_scene_analyze_c.h + senc3d_side_range.h) + +set(SENC3D_FILES_DOC COPYING README.md) + +# Prepend each file by `SENC3D_SOURCE_DIR' +rcmake_prepend_path(SENC3D_FILES_SRC ${SENC3D_SOURCE_DIR}) +rcmake_prepend_path(SENC3D_FILES_INC ${SENC3D_SOURCE_DIR}) +rcmake_prepend_path(SENC3D_FILES_INC_API ${SENC3D_SOURCE_DIR}) +rcmake_prepend_path(SENC3D_FILES_DOC ${PROJECT_SOURCE_DIR}/../) if(CMAKE_COMPILER_IS_GNUCC) set(MATH_LIB m) endif() -add_library(senc SHARED - ${SENC_FILES_SRC} - ${SENC_FILES_INC} - ${SENC_FILES_INC_API}) -target_link_libraries(senc RSys Star3D ${MATH_LIB}) +add_library(senc3d SHARED + ${SENC3D_FILES_SRC} + ${SENC3D_FILES_INC} + ${SENC3D_FILES_INC_API}) +target_link_libraries(senc3d RSys Star3D ${MATH_LIB}) -set_target_properties(senc PROPERTIES - DEFINE_SYMBOL SENC_SHARED_BUILD +set_target_properties(senc3d PROPERTIES + DEFINE_SYMBOL SENC3D_SHARED_BUILD VERSION ${VERSION} COMPILE_FLAGS ${OpenMP_C_FLAGS} SOVERSION ${VERSION_MAJOR}) -rcmake_copy_runtime_libraries(senc) +rcmake_copy_runtime_libraries(senc3d) if(CMAKE_COMPILER_IS_GNUCC) - set_target_properties(senc PROPERTIES LINK_FLAGS "${OpenMP_C_FLAGS}") - target_link_libraries(senc m) + set_target_properties(senc3d PROPERTIES LINK_FLAGS "${OpenMP_C_FLAGS}") + target_link_libraries(senc3d m) endif() -rcmake_setup_devel(senc StarEnc ${VERSION} star/senc_version.h) +rcmake_setup_devel(senc3d StarEnc3D ${VERSION} star/senc3d_version.h) ############################################################################### # Add tests @@ -131,9 +131,13 @@ rcmake_setup_devel(senc StarEnc ${VERSION} star/senc_version.h) if(NOT NO_TEST) function(build_test _name) add_executable(${_name} - ${SENC_SOURCE_DIR}/test_senc_utils.h - ${SENC_SOURCE_DIR}/${_name}.c) - target_link_libraries(${_name} RSys senc) + ${SENC3D_SOURCE_DIR}/test_senc3d_utils.h + ${SENC3D_SOURCE_DIR}/${_name}.c) + foreach(other ${ARGN}) + target_sources(${_name} + PUBLIC ${SENC3D_SOURCE_DIR}/${other}) + endforeach() + target_link_libraries(${_name} RSys senc3d) endfunction() function(register_test _name) @@ -142,45 +146,45 @@ if(NOT NO_TEST) endfunction() function(new_test _name) - build_test(${_name}) + build_test(${_name} ${ARGN}) register_test(${_name} ${_name}) endfunction() - new_test(test_senc_cube_behind_cube) - new_test(test_senc_cube_in_cube) - new_test(test_senc_cube_on_cube) - new_test(test_senc_device) - new_test(test_senc_enclosure) - new_test(test_senc_inconsistant_cube) - new_test(test_senc_sample_enclosure) - new_test(test_senc_scene) - new_test(test_senc_some_enclosures) - new_test(test_senc_some_triangles) - new_test(test_senc_unspecified_medium) + new_test(test_senc3d_cube_behind_cube) + new_test(test_senc3d_cube_in_cube) + new_test(test_senc3d_cube_on_cube) + new_test(test_senc3d_device) + new_test(test_senc3d_enclosure) + new_test(test_senc3d_inconsistant_cube) + new_test(test_senc3d_sample_enclosure) + new_test(test_senc3d_scene) + new_test(test_senc3d_some_enclosures) + new_test(test_senc3d_some_triangles) + new_test(test_senc3d_unspecified_medium) - target_link_libraries(test_senc_enclosure Star3D) - target_link_libraries(test_senc_sample_enclosure StarSP Star3D) + target_link_libraries(test_senc3d_enclosure Star3D) + target_link_libraries(test_senc3d_sample_enclosure StarSP Star3D) - rcmake_copy_runtime_libraries(test_senc_sample_enclosure) + rcmake_copy_runtime_libraries(test_senc3d_sample_enclosure) if(HUGE_ADDITIONAL_TESTS) - new_test(test_senc_many_enclosures) - new_test(test_senc_many_triangles) + new_test(test_senc3d_many_enclosures test_senc3d_utils2.h) + new_test(test_senc3d_many_triangles test_senc3d_utils2.h) - target_link_libraries(test_senc_many_enclosures Star3DUT) - target_link_libraries(test_senc_many_triangles Star3DUT) + target_link_libraries(test_senc3d_many_enclosures Star3DUT) + target_link_libraries(test_senc3d_many_triangles Star3DUT) - rcmake_copy_runtime_libraries(test_senc_many_enclosures) - rcmake_copy_runtime_libraries(test_senc_many_triangles) + rcmake_copy_runtime_libraries(test_senc3d_many_enclosures) + rcmake_copy_runtime_libraries(test_senc3d_many_triangles) endif() endif() ############################################################################### # Define output & install directories ############################################################################### -install(TARGETS senc +install(TARGETS senc3d ARCHIVE DESTINATION bin LIBRARY DESTINATION lib RUNTIME DESTINATION bin) -install(FILES ${SENC_FILES_INC_API} DESTINATION include/star) -install(FILES ${SENC_FILES_DOC} DESTINATION share/doc/star-enc) +install(FILES ${SENC3D_FILES_INC_API} DESTINATION include/star) +install(FILES ${SENC3D_FILES_DOC} DESTINATION share/doc/star-enclosures-3d) diff --git a/src/senc.h b/src/senc.h @@ -1,364 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_H -#define SENC_H - -#include <rsys/rsys.h> - -#include <limits.h> - -/* Library symbol management */ -#if defined(SENC_SHARED_BUILD) - #define SENC_API extern EXPORT_SYM -#elif defined(SENC_STATIC_BUILD) - #define SENC_API extern LOCAL_SYM -#else /* Use shared library */ - #define SENC_API extern IMPORT_SYM -#endif - -/* Helper macro that asserts if the invocation of the StarEnc function `Func' - * returns an error. One should use this macro on StarEnc function calls for - * which no explicit error checking is performed. */ -#ifndef NDEBUG - #define SENC(Func) ASSERT(senc_ ## Func == RES_OK) -#else - #define SENC(Func) senc_ ## Func -#endif - -/* Syntactic sugar used to inform the library that it can use as many threads - * as CPU cores */ -#define SENC_NTHREADS_DEFAULT (~0u) - -/* A constant to specify an unspecified medium */ -#define SENC_UNSPECIFIED_MEDIUM UINT_MAX - -/* Forward declaration of external opaque data types */ -struct logger; -struct mem_allocator; - -/* Forward declaration of StarEnclosures opaque data types. These data types - * are ref counted. Once created with the appropriated `senc_<TYPE>_create' - * function, the caller implicitly owns the created data, i.e. its reference - * counter is set to 1. The senc_<TYPE>_ref_<get|put> functions get or release - * 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 senc_device; -struct senc_scene; -struct senc_enclosure; - -/******************************************************************************* - * The dimension of the geometry used in the library. - ******************************************************************************/ -#define SENC_GEOMETRY_DIMENSION 3 - -/* A type to discriminate triangle sides */ -enum senc_side { - SENC_FRONT, - SENC_BACK -}; - -/* Enclosure header type */ -struct senc_enclosure_header { - /* The ID of the enclosure; 0, 1, ... */ - unsigned enclosure_id; - /* Number of triangles; a triangle can be accounted for twice, once by side*/ - unsigned primitives_count; - /* Number of unique triangles; a triangle cannot be accounted for twice */ - unsigned unique_primitives_count; - /* Number of vertices */ - unsigned vertices_count; - /* The number of media inside the enclosure, - * SENC_UNSPECIFIED_MEDIUM included */ - unsigned enclosed_media_count; - /* Is the enclosure open/infinite? - * Only the outermost enclosure is infinite. */ - char is_infinite; -}; - -/* We consider the geometrical normal Ng to a triangle V0 V1 V2 - * that verifies "(V0, V0V1, V0V2, Ng) is a direct system" - * (right-handed system). - * - * The user can set the convention used to determine which side of - * a triangle is to be considered front/back by using the flags : - * SENC_CONVENTION_NORMAL_FRONT => Ng points toward the front side, - * SENC_CONVENTION_NORMAL_BACK => Ng points toward the back side. - * - * Additionaly the user can set the convention used to output enclosures - * so that Ng points toward the enclosure or on the opposite direction - * (for a closed enclosure Ng points toward the inside or toward the outside) - * by using the flags : - * SENC_CONVENTION_NORMAL_INSIDE => Ng points toward the enclosure, - * SENC_CONVENTION_NORMAL_OUTSIDE => Ng points toward the opposite of the - * enclosure. - * - * Note that normals in output data can be opposite to normals in input data - * (vertices are then given in reverse order). - * - * Also note that both sides of a triangle can be part of the same enclosure; - * in this case the 2 sides will be given with opposite Ng (meaning they - * will be given with opposite vertices order). - */ -enum senc_convention { - /* - * Convention regarding FRONT/BACK sides in input data - */ - - /* Geometrical normals point toward the front side */ - SENC_CONVENTION_NORMAL_FRONT = BIT(0), - /* Geometrical normals point toward the back side */ - SENC_CONVENTION_NORMAL_BACK = BIT(1), - - /* - * Convention regarding geometrical normals in output data - */ - - /* Geometrical normals point toward the enclosure */ - SENC_CONVENTION_NORMAL_INSIDE = BIT(2), - /* Geometrical normals point to the opposite of the enclosure */ - SENC_CONVENTION_NORMAL_OUTSIDE = BIT(3) -}; - -BEGIN_DECLS - -/****************************************************************************** - * StarEnclosures device. It is an handle toward the StarEnc library. - * It manages the lib resources. - * If provided, the allocator has to be suitable for parallel high frequency - * allocations. As a consequence, a rsys proxy allocator should be avoided. - *****************************************************************************/ -SENC_API res_T -senc_device_create - (struct logger* logger, /* May be NULL <=> use default logger */ - struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ - const unsigned nthreads_hint, - const int verbose, - struct senc_device** device); - -SENC_API res_T -senc_device_ref_get - (struct senc_device* device); - -SENC_API res_T -senc_device_ref_put - (struct senc_device* device); - -/****************************************************************************** - * StarEnclosures scene. A scene is a collection of triangles. Each triangle is - * defined with a medium on each side. - *****************************************************************************/ -/* Creates a scene from some vertices and triangles. - * Neither vertices nor triangles can include duplicates. - * Triangles cannot be degenerated. */ -SENC_API res_T -senc_scene_create - (struct senc_device* device, - const int convention, - /* Number of triangles */ - const unsigned triangles_count, - /* User function that provides vertices ids for triangles */ - void(*get_indices)( - const unsigned itri, - unsigned ids[SENC_GEOMETRY_DIMENSION], - void* context), - /* User function that provides media ids for triangles */ - void(*get_media) /* Can be NULL <=> SENC_UNSPECIFIED_MEDIUM medium used */ - (const unsigned itri, unsigned med[2], void* context), - /* Number of vertices */ - const unsigned vertices_count, - /* User function that provides coordinates for vertices */ - void(*get_position)( - const unsigned ivert, - double pos[SENC_GEOMETRY_DIMENSION], - void* context), - /* Context provided to user callbacks; can be NULL */ - void* context, - /* The created scene */ - struct senc_scene** scene); - -/* Returns the convention flags in use with the scene. */ -SENC_API res_T -senc_scene_get_convention - (const struct senc_scene* scene, - int* convention); - -/* Returns the number of triangles in the scene. */ -SENC_API res_T -senc_scene_get_triangles_count - (const struct senc_scene* scene, - unsigned* count); - -/* Returns the itri_th triangle vertices' indices. */ -SENC_API res_T -senc_scene_get_triangle - (const struct senc_scene* scene, - const unsigned itri, - unsigned indices[SENC_GEOMETRY_DIMENSION]); - -/* Returns the media for the itri_th triangle. */ -SENC_API res_T -senc_scene_get_triangle_media - (const struct senc_scene* scene, - const unsigned itri, - unsigned media[2]); - -/* Returns the number of vertices in the scene. */ -SENC_API res_T -senc_scene_get_vertices_count - (const struct senc_scene* scene, - unsigned* count); - -/* Returns the coordinates of the ivert_th vertex. */ -SENC_API res_T -senc_scene_get_vertex - (const struct senc_scene* scene, - const unsigned ivert, - double coord[SENC_GEOMETRY_DIMENSION]); - -/* Returns the greater medium id found in added geometry. In API calls using a - * medium, any value in the [0 max_medium_id[ range is valid. However there can - * be unused ids (no geometry refered to this medium id). */ -SENC_API res_T -senc_scene_get_max_medium - (const struct senc_scene* scene, - unsigned* max_medium_id); - -/* Returns the number of enclosures. */ -SENC_API res_T -senc_scene_get_enclosure_count - (const struct senc_scene* scene, - unsigned* count); - -/* Returns the number of enclosures that have some geometry refering to the - * imed_th medium or SENC_UNSPECIFIED_MEDIUM. */ -SENC_API res_T -senc_scene_get_enclosure_count_by_medium - (const struct senc_scene* scene, - const unsigned imed, - unsigned* count); - -/* Returns the idx_th enclosure. */ -SENC_API res_T -senc_scene_get_enclosure - (struct senc_scene* scene, - const unsigned idx, - struct senc_enclosure** enclosure); - -/* Returns the idx_th enclosure using the imed_th medium or - * SENC_UNSPECIFIED_MEDIUM. */ -SENC_API res_T -senc_scene_get_enclosure_by_medium - (struct senc_scene* scene, - const unsigned imed, - const unsigned idx, - struct senc_enclosure** enclosure); - -/* Returns the enclosures the itri_th triangle front and back sides are member - * of. */ -SENC_API res_T -senc_scene_get_triangle_enclosures - (const struct senc_scene* scene, - const unsigned itri, - unsigned enclosures[2]); - -/* Returns the number of segments that are frontier segments: - * - that have arity 1 (single triangle using the segment) - * - that connect 2 different media */ -SENC_API res_T -senc_scene_get_frontier_segments_count - (const struct senc_scene* scene, - unsigned* count); - -/* Returns the iseg_th frontier segment; the returned indices are global vertex - * indices whose coordinates can be retrieved using senc_scene_get_vertex. */ -SENC_API res_T -senc_scene_get_frontier_segment - (const struct senc_scene* scene, - const unsigned iseg, - unsigned vrtx_id[SENC_GEOMETRY_DIMENSION-1]); - -SENC_API res_T -senc_scene_ref_get - (struct senc_scene* scene); - -SENC_API res_T -senc_scene_ref_put - (struct senc_scene* scene); - -/****************************************************************************** - * StarEnclosures enclosure. It is an handle toward an enclosure. - * Counts and other information on enclosures are not individually accessible, - * but as a whole through header access. - * An enclosure can list the "same" triangle twice if both sides are in. In - * this case the 2 occurences of the triangle have reversed vertices order and - * unique_triangle_count and triangle_count differ. - * Vertices and triangles numbering schemes are specific to each enclosure: - * the "same" item appearing in 2 different enclosures has no reason to get the - * same index twice or to have the same index in the global numbering scheme. - * By-index API accesses of triangles (or properties) visit unique triangles - * for indices in the [0 unique_triangle_count[ range and back-faces of the - * doubly-included triangles in the [unique_triangle_count triangle_count[ - * range. - *****************************************************************************/ -/* Returns the header of an enclosure. */ -SENC_API res_T -senc_enclosure_get_header - (const struct senc_enclosure* enclosure, - struct senc_enclosure_header* header); - -/* Returns the itri_th triangle of an enclosure. - * Indices are local to the enclosure. */ -SENC_API res_T -senc_enclosure_get_triangle - (const struct senc_enclosure* enclosure, - const unsigned itri, - unsigned indices[SENC_GEOMETRY_DIMENSION]); - -/* Returns the coordinates of the ivert_th vertex of an enclosure. */ -SENC_API res_T -senc_enclosure_get_vertex - (const struct senc_enclosure* enclosure, - const unsigned ivert, - double coord[SENC_GEOMETRY_DIMENSION]); - -/* Returns the global id of the itri_th triangle of an enclosure - * and the involved side. */ -SENC_API res_T -senc_enclosure_get_triangle_id - (const struct senc_enclosure* enclosure, - const unsigned itri, - unsigned* gid, - enum senc_side* side); - -/* Returns the id of the imed_th medium of an enclosure. */ -SENC_API res_T -senc_enclosure_get_medium - (const struct senc_enclosure* enclosure, - const unsigned imed, - unsigned* medium); - -SENC_API res_T -senc_enclosure_ref_get - (struct senc_enclosure* enclosure); - -SENC_API res_T -senc_enclosure_ref_put - (struct senc_enclosure* enclosure); - -END_DECLS - -#endif /* SENC_H */ diff --git a/src/senc3d.h b/src/senc3d.h @@ -0,0 +1,364 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_H +#define SENC3D_H + +#include <rsys/rsys.h> + +#include <limits.h> + +/* Library symbol management */ +#if defined(SENC3D_SHARED_BUILD) + #define SENC3D_API extern EXPORT_SYM +#elif defined(SENC3D_STATIC_BUILD) + #define SENC3D_API extern LOCAL_SYM +#else /* Use shared library */ + #define SENC3D_API extern IMPORT_SYM +#endif + +/* Helper macro that asserts if the invocation of the StarEnc function `Func' + * returns an error. One should use this macro on StarEnc function calls for + * which no explicit error checking is performed. */ +#ifndef NDEBUG + #define SENC3D(Func) ASSERT(senc3d_ ## Func == RES_OK) +#else + #define SENC3D(Func) senc3d_ ## Func +#endif + +/* Syntactic sugar used to inform the library that it can use as many threads + * as CPU cores */ +#define SENC3D_NTHREADS_DEFAULT (~0u) + +/* A constant to denote an unspecified medium */ +#define SENC3D_UNSPECIFIED_MEDIUM UINT_MAX + +/* Forward declaration of external opaque data types */ +struct logger; +struct mem_allocator; + +/* Forward declaration of StarEnclosures opaque data types. These data types + * are ref counted. Once created with the appropriated `SENC3D_<TYPE>_create' + * function, the caller implicitly owns the created data, i.e. its reference + * counter is set to 1. The SENC3D_<TYPE>_ref_<get|put> functions get or release + * 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 senc3d_device; +struct senc3d_scene; +struct senc3d_enclosure; + +/******************************************************************************* + * The dimension of the geometry used in the library. + ******************************************************************************/ +#define SENC3D_GEOMETRY_DIMENSION 3 + +/* A type to discriminate triangle sides */ +enum senc3d_side { + SENC3D_FRONT, + SENC3D_BACK +}; + +/* Enclosure header type */ +struct senc3d_enclosure_header { + /* The ID of the enclosure; 0, 1, ... */ + unsigned enclosure_id; + /* Number of triangles; a triangle can be accounted for twice, once by side*/ + unsigned primitives_count; + /* Number of unique triangles; a triangle cannot be accounted for twice */ + unsigned unique_primitives_count; + /* Number of vertices */ + unsigned vertices_count; + /* The number of media inside the enclosure, + * SENC3D_UNSPECIFIED_MEDIUM included */ + unsigned enclosed_media_count; + /* Is the enclosure open/infinite? + * Only the outermost enclosure is infinite. */ + char is_infinite; +}; + +/* We consider the geometrical normal Ng to a triangle V0 V1 V2 + * that verifies "(V0, V0V1, V0V2, Ng) is a direct system" + * (right-handed system). + * + * The user can set the convention used to determine which side of + * a triangle is to be considered front/back by using the flags : + * SENC3D_CONVENTION_NORMAL_FRONT => Ng points toward the front side, + * SENC3D_CONVENTION_NORMAL_BACK => Ng points toward the back side. + * + * Additionaly the user can set the convention used to output enclosures + * so that Ng points toward the enclosure or on the opposite direction + * (for a closed enclosure Ng points toward the inside or toward the outside) + * by using the flags : + * SENC3D_CONVENTION_NORMAL_INSIDE => Ng points toward the enclosure, + * SENC3D_CONVENTION_NORMAL_OUTSIDE => Ng points toward the opposite of the + * enclosure. + * + * Note that normals in output data can be opposite to normals in input data + * (vertices are then given in reverse order). + * + * Also note that both sides of a triangle can be part of the same enclosure; + * in this case the 2 sides will be given with opposite Ng (meaning they + * will be given with opposite vertices order). + */ +enum senc3d_convention { + /* + * Convention regarding FRONT/BACK sides in input data + */ + + /* Geometrical normals point toward the front side */ + SENC3D_CONVENTION_NORMAL_FRONT = BIT(0), + /* Geometrical normals point toward the back side */ + SENC3D_CONVENTION_NORMAL_BACK = BIT(1), + + /* + * Convention regarding geometrical normals in output data + */ + + /* Geometrical normals point toward the enclosure */ + SENC3D_CONVENTION_NORMAL_INSIDE = BIT(2), + /* Geometrical normals point to the opposite of the enclosure */ + SENC3D_CONVENTION_NORMAL_OUTSIDE = BIT(3) +}; + +BEGIN_DECLS + +/****************************************************************************** + * StarEnclosures device. It is an handle toward the StarEnc library. + * It manages the lib resources. + * If provided, the allocator has to be suitable for parallel high frequency + * allocations. As a consequence, a rsys proxy allocator should be avoided. + *****************************************************************************/ +SENC3D_API res_T +senc3d_device_create + (struct logger* logger, /* May be NULL <=> use default logger */ + struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const unsigned nthreads_hint, + const int verbose, + struct senc3d_device** device); + +SENC3D_API res_T +senc3d_device_ref_get + (struct senc3d_device* device); + +SENC3D_API res_T +senc3d_device_ref_put + (struct senc3d_device* device); + +/****************************************************************************** + * StarEnclosures scene. A scene is a collection of triangles. Each triangle is + * defined with a medium on each side. + *****************************************************************************/ +/* Creates a scene from some vertices and triangles. + * Neither vertices nor triangles can include duplicates. + * Triangles cannot be degenerated. */ +SENC3D_API res_T +senc3d_scene_create + (struct senc3d_device* device, + const int convention, + /* Number of triangles */ + const unsigned triangles_count, + /* User function that provides vertices ids for triangles */ + void(*get_indices)( + const unsigned itri, + unsigned ids[SENC3D_GEOMETRY_DIMENSION], + void* context), + /* User function that provides media ids for triangles */ + void(*get_media) /* Can be NULL <=> SENC3D_UNSPECIFIED_MEDIUM medium used */ + (const unsigned itri, unsigned med[2], void* context), + /* Number of vertices */ + const unsigned vertices_count, + /* User function that provides coordinates for vertices */ + void(*get_position)( + const unsigned ivert, + double pos[SENC3D_GEOMETRY_DIMENSION], + void* context), + /* Context provided to user callbacks; can be NULL */ + void* context, + /* The created scene */ + struct senc3d_scene** scene); + +/* Returns the convention flags in use with the scene. */ +SENC3D_API res_T +senc3d_scene_get_convention + (const struct senc3d_scene* scene, + int* convention); + +/* Returns the number of triangles in the scene. */ +SENC3D_API res_T +senc3d_scene_get_triangles_count + (const struct senc3d_scene* scene, + unsigned* count); + +/* Returns the itri_th triangle vertices' indices. */ +SENC3D_API res_T +senc3d_scene_get_triangle + (const struct senc3d_scene* scene, + const unsigned itri, + unsigned indices[SENC3D_GEOMETRY_DIMENSION]); + +/* Returns the media for the itri_th triangle. */ +SENC3D_API res_T +senc3d_scene_get_triangle_media + (const struct senc3d_scene* scene, + const unsigned itri, + unsigned media[2]); + +/* Returns the number of vertices in the scene. */ +SENC3D_API res_T +senc3d_scene_get_vertices_count + (const struct senc3d_scene* scene, + unsigned* count); + +/* Returns the coordinates of the ivert_th vertex. */ +SENC3D_API res_T +senc3d_scene_get_vertex + (const struct senc3d_scene* scene, + const unsigned ivert, + double coord[SENC3D_GEOMETRY_DIMENSION]); + +/* Returns the greater medium id found in added geometry. In API calls using a + * medium, any value in the [0 max_medium_id[ range is valid. However there can + * be unused ids (no geometry refered to this medium id). */ +SENC3D_API res_T +senc3d_scene_get_max_medium + (const struct senc3d_scene* scene, + unsigned* max_medium_id); + +/* Returns the number of enclosures. */ +SENC3D_API res_T +senc3d_scene_get_enclosure_count + (const struct senc3d_scene* scene, + unsigned* count); + +/* Returns the number of enclosures that have some geometry refering to the + * imed_th medium or SENC3D_UNSPECIFIED_MEDIUM. */ +SENC3D_API res_T +senc3d_scene_get_enclosure_count_by_medium + (const struct senc3d_scene* scene, + const unsigned imed, + unsigned* count); + +/* Returns the idx_th enclosure. */ +SENC3D_API res_T +senc3d_scene_get_enclosure + (struct senc3d_scene* scene, + const unsigned idx, + struct senc3d_enclosure** enclosure); + +/* Returns the idx_th enclosure using the imed_th medium or + * SENC3D_UNSPECIFIED_MEDIUM. */ +SENC3D_API res_T +senc3d_scene_get_enclosure_by_medium + (struct senc3d_scene* scene, + const unsigned imed, + const unsigned idx, + struct senc3d_enclosure** enclosure); + +/* Returns the enclosures the itri_th triangle front and back sides are member + * of. */ +SENC3D_API res_T +senc3d_scene_get_triangle_enclosures + (const struct senc3d_scene* scene, + const unsigned itri, + unsigned enclosures[2]); + +/* Returns the number of segments that are frontier segments: + * - that have arity 1 (single triangle using the segment) + * - that connect 2 different media */ +SENC3D_API res_T +senc3d_scene_get_frontier_segments_count + (const struct senc3d_scene* scene, + unsigned* count); + +/* Returns the iseg_th frontier segment; the returned indices are global vertex + * indices whose coordinates can be retrieved using senc3d_scene_get_vertex. */ +SENC3D_API res_T +senc3d_scene_get_frontier_segment + (const struct senc3d_scene* scene, + const unsigned iseg, + unsigned vrtx_id[SENC3D_GEOMETRY_DIMENSION-1]); + +SENC3D_API res_T +senc3d_scene_ref_get + (struct senc3d_scene* scene); + +SENC3D_API res_T +senc3d_scene_ref_put + (struct senc3d_scene* scene); + +/****************************************************************************** + * StarEnclosures enclosure. It is an handle toward an enclosure. + * Counts and other information on enclosures are not individually accessible, + * but as a whole through header access. + * An enclosure can list the "same" triangle twice if both sides are in. In + * this case the 2 occurences of the triangle have reversed vertices order and + * unique_triangle_count and triangle_count differ. + * Vertices and triangles numbering schemes are specific to each enclosure: + * the "same" item appearing in 2 different enclosures has no reason to get the + * same index twice or to have the same index in the global numbering scheme. + * By-index API accesses of triangles (or properties) visit unique triangles + * for indices in the [0 unique_triangle_count[ range and back-faces of the + * doubly-included triangles in the [unique_triangle_count triangle_count[ + * range. + *****************************************************************************/ +/* Returns the header of an enclosure. */ +SENC3D_API res_T +senc3d_enclosure_get_header + (const struct senc3d_enclosure* enclosure, + struct senc3d_enclosure_header* header); + +/* Returns the itri_th triangle of an enclosure. + * Indices are local to the enclosure. */ +SENC3D_API res_T +senc3d_enclosure_get_triangle + (const struct senc3d_enclosure* enclosure, + const unsigned itri, + unsigned indices[SENC3D_GEOMETRY_DIMENSION]); + +/* Returns the coordinates of the ivert_th vertex of an enclosure. */ +SENC3D_API res_T +senc3d_enclosure_get_vertex + (const struct senc3d_enclosure* enclosure, + const unsigned ivert, + double coord[SENC3D_GEOMETRY_DIMENSION]); + +/* Returns the global id of the itri_th triangle of an enclosure + * and the involved side. */ +SENC3D_API res_T +senc3d_enclosure_get_triangle_id + (const struct senc3d_enclosure* enclosure, + const unsigned itri, + unsigned* gid, + enum senc3d_side* side); + +/* Returns the id of the imed_th medium of an enclosure. */ +SENC3D_API res_T +senc3d_enclosure_get_medium + (const struct senc3d_enclosure* enclosure, + const unsigned imed, + unsigned* medium); + +SENC3D_API res_T +senc3d_enclosure_ref_get + (struct senc3d_enclosure* enclosure); + +SENC3D_API res_T +senc3d_enclosure_ref_put + (struct senc3d_enclosure* enclosure); + +END_DECLS + +#endif /* SENC3D_H */ diff --git a/src/senc3d_descriptor.c b/src/senc3d_descriptor.c @@ -0,0 +1,160 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d_enclosure_c.h" +#include "senc3d_scene_c.h" +#include "senc3d.h" + +#include <rsys/rsys.h> +#include <rsys/double3.h> +#include <rsys/mem_allocator.h> + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +senc3d_scene_get_max_medium + (const struct senc3d_scene* scn, unsigned* max_medium_id) +{ + if(!scn || !max_medium_id) return RES_BAD_ARG; + ASSERT(scn->next_medium_idx < UINT_MAX); /* API type */ + *max_medium_id = (unsigned)scn->next_medium_idx - 1; + return RES_OK; +} + +res_T +senc3d_scene_get_enclosure_count + (const struct senc3d_scene* scn, unsigned* count) +{ + size_t tmp; + if(!scn || !count) return RES_BAD_ARG; + tmp = darray_enclosure_size_get(&scn->analyze.enclosures); + ASSERT(tmp < UINT_MAX); /* API type */ + ASSERT(scn->analyze.enclosures_count == tmp); + *count = (unsigned)tmp; + return RES_OK; +} + +res_T +senc3d_scene_get_enclosure_count_by_medium + (const struct senc3d_scene* scn, + const unsigned imed, + unsigned* count) +{ + size_t tmp, m_idx; + const struct darray_enc_id* enc_ids; + if(!scn || !count + || (imed != SENC3D_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) + return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + m_idx = (imed == SENC3D_UNSPECIFIED_MEDIUM) ? 0 : imed + 1; + enc_ids = darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + + m_idx; + tmp = darray_enc_id_size_get(enc_ids); + ASSERT(tmp < UINT_MAX); /* API type */ + *count = (unsigned)tmp; + return RES_OK; +} + +FINLINE res_T +senc3d_scene_get_enclosure + (struct senc3d_scene* scn, + const unsigned idx, + struct senc3d_enclosure** out_enc) +{ + struct senc3d_enclosure* enc; + if(!scn || idx >= darray_enclosure_size_get(&scn->analyze.enclosures) + || !out_enc) + return RES_BAD_ARG; + enc = enclosure_create(scn, idx); + if(!enc) return RES_MEM_ERR; + *out_enc = enc; + return RES_OK; +} + +res_T +senc3d_scene_get_enclosure_by_medium + (struct senc3d_scene* scn, + const unsigned imed, + const unsigned idx, + struct senc3d_enclosure** out_enc) +{ + size_t m_idx; + const struct darray_enc_id* enc_ids; + unsigned index; + if(!scn || !out_enc + || (imed != SENC3D_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) + return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + m_idx = (imed == SENC3D_UNSPECIFIED_MEDIUM) ? 0 : imed + 1; + enc_ids = + darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; + if(idx >= darray_enc_id_size_get(enc_ids)) return RES_BAD_ARG; + index = darray_enc_id_cdata_get(enc_ids)[idx]; + return senc3d_scene_get_enclosure(scn, index, out_enc); +} + +res_T +senc3d_scene_get_triangle_enclosures + (const struct senc3d_scene* scn, + const unsigned itri, + unsigned enclosures[2]) +{ + const struct triangle_enc* trg; + int i; + if(!enclosures || !scn + || itri >= darray_triangle_enc_size_get(&scn->analyze.triangles_enc)) + return RES_BAD_ARG; + trg = darray_triangle_enc_cdata_get(&scn->analyze.triangles_enc) + itri; + FOR_EACH(i, 0, 2) { +#if (UINT_MAX < ENCLOSURE_MAX__) + ASSERT(trg->enclosure[i] < UINT_MAX); +#endif + enclosures[i] = (unsigned)trg->enclosure[i]; /* Back to API type */ + } + return RES_OK; +} + +res_T +senc3d_scene_get_frontier_segments_count + (const struct senc3d_scene* scn, + unsigned* count) +{ + size_t tmp; + if(!scn || !count) + return RES_BAD_ARG; + tmp = darray_frontier_edge_size_get(&scn->analyze.frontiers); + ASSERT(tmp < UINT_MAX); + *count = (unsigned)tmp; + return RES_OK; +} + +res_T +senc3d_scene_get_frontier_segment + (const struct senc3d_scene* scn, + const unsigned iseg, + unsigned vrtx_id[2]) +{ + const struct trg_edge* edge; + if(!vrtx_id || !scn + || iseg >= darray_frontier_edge_size_get(&scn->analyze.frontiers)) + return RES_BAD_ARG; + edge = darray_frontier_edge_cdata_get(&scn->analyze.frontiers) + iseg; + vrtx_id[0] = (unsigned)edge->vrtx0; /* Back to API type */ + vrtx_id[1] = (unsigned)edge->vrtx1; /* Back to API type */ + return RES_OK; +} diff --git a/src/senc3d_device.c b/src/senc3d_device.c @@ -0,0 +1,148 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "senc3d_device_c.h" + +#include <rsys/logger.h> +#include <rsys/mem_allocator.h> + +#include <omp.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +log_msg + (struct senc3d_device* dev, + const enum log_type stream, + const char* msg, + va_list vargs) +{ + ASSERT(dev && msg); + if(dev->verbose) { + res_T res; (void)res; + res = logger_vprint(dev->logger, stream, msg, vargs); + ASSERT(res == RES_OK); + } +} + +static void +device_release(ref_T* ref) +{ + struct senc3d_device* dev; + ASSERT(ref); + dev = CONTAINER_OF(ref, struct senc3d_device, ref); + MEM_RM(dev->allocator, dev); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +void +log_err(struct senc3d_device* dev, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(dev && msg); + + va_start(vargs_list, msg); + log_msg(dev, LOG_ERROR, msg, vargs_list); + va_end(vargs_list); +} + +void +log_warn(struct senc3d_device* dev, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(dev && msg); + + va_start(vargs_list, msg); + log_msg(dev, LOG_WARNING, msg, vargs_list); + va_end(vargs_list); +} + +void +log_info(struct senc3d_device* dev, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(dev && msg); + + va_start(vargs_list, msg); + log_msg(dev, LOG_OUTPUT, msg, vargs_list); + va_end(vargs_list); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +senc3d_device_create + (struct logger* logger, + struct mem_allocator* mem_allocator, + const unsigned nthreads_hint, + const int verbose, + struct senc3d_device** out_dev) +{ + struct logger* log = NULL; + struct senc3d_device* dev = NULL; + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + if(nthreads_hint == 0 || !out_dev) return RES_BAD_ARG; + + log = logger ? logger : LOGGER_DEFAULT; + allocator = mem_allocator ? mem_allocator : &mem_default_allocator; + dev = MEM_CALLOC(allocator, 1, sizeof(struct senc3d_device)); + if(!dev) { + if(verbose) { + /* Do not use helper log functions since dev is not initialised */ + CHK(logger_print(log, LOG_ERROR, + "%s: could not allocate the StarEnclosures device.\n", FUNC_NAME) == RES_OK); + } + res = RES_MEM_ERR; + goto error; + } + dev->logger = log; + dev->allocator = allocator; + dev->verbose = verbose; + /* Cannot use int args for MMIN here as default is -1 */ + dev->nthreads = (int)MMIN(nthreads_hint, (unsigned)omp_get_num_procs()); + ref_init(&dev->ref); + +exit: + if(dev) *out_dev = dev; + return res; +error: + if(dev) { + SENC3D(device_ref_put(dev)); + dev = NULL; + } + goto exit; +} + +res_T +senc3d_device_ref_get(struct senc3d_device* dev) +{ + if(!dev) return RES_BAD_ARG; + ref_get(&dev->ref); + return RES_OK; +} + +res_T +senc3d_device_ref_put(struct senc3d_device* dev) +{ + if(!dev) return RES_BAD_ARG; + ref_put(&dev->ref, device_release); + return RES_OK; +} diff --git a/src/senc3d_device_c.h b/src/senc3d_device_c.h @@ -0,0 +1,71 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_DEVICE_C_H +#define SENC3D_DEVICE_C_H + +#include <rsys/free_list.h> +#include <rsys/ref_count.h> + +struct name { FITEM; }; +#define FITEM_TYPE name +#include <rsys/free_list.h> + +struct senc3d_device { + struct logger* logger; + struct mem_allocator* allocator; + int verbose; + int nthreads; + + ref_T ref; +}; + +/* Conditionally log a message on the LOG_ERROR stream of the device logger, + * with respect to the device verbose flag */ +extern LOCAL_SYM void +log_err + (struct senc3d_device* dev, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +/* Conditionally log a message on the LOG_WARNING stream of the device logger, + * with respect to the device verbose flag */ +extern LOCAL_SYM void +log_warn + (struct senc3d_device* dev, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +/* Conditionally log a message on the LOG_OUTPUT stream of the device logger, + * with respect to the device verbose flag */ +extern LOCAL_SYM void +log_info + (struct senc3d_device* dev, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif + ; + +#endif /* SENC3D_DEVICE_C_H */ diff --git a/src/senc3d_enclosure.c b/src/senc3d_enclosure.c @@ -0,0 +1,167 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d_enclosure_c.h" +#include "senc3d_enclosure_data.h" +#include "senc3d_scene_c.h" +#include "senc3d_device_c.h" +#include "senc3d.h" + +#include <rsys/rsys.h> +#include <rsys/double3.h> +#include <rsys/mem_allocator.h> + + +/******************************************************************************* + * Helper function + ******************************************************************************/ +static void +enclosure_release(ref_T * ref) +{ + struct senc3d_enclosure* enclosure = NULL; + struct senc3d_scene* scn = NULL; + ASSERT(ref); + enclosure = CONTAINER_OF(ref, struct senc3d_enclosure, ref); + scn = enclosure->scene; + MEM_RM(scn->dev->allocator, enclosure); + SENC3D(scene_ref_put(scn)); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +struct senc3d_enclosure* +enclosure_create + (struct senc3d_scene* scn, + const unsigned idx) +{ + struct senc3d_enclosure* enc; + ASSERT(scn && idx < darray_enclosure_size_get(&scn->analyze.enclosures)); + enc = MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct senc3d_enclosure)); + if(enc) { + const struct enclosure_data* data + = darray_enclosure_data_get(&scn->analyze.enclosures) + idx; + enc->scene = scn; + enc->data = data; + ref_init(&enc->ref); + SENC3D(scene_ref_get(scn)); + } + return enc; +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +senc3d_enclosure_get_header + (const struct senc3d_enclosure* enclosure, + struct senc3d_enclosure_header* header) +{ + if(!enclosure || !header) return RES_BAD_ARG; + *header = enclosure->data->header; + return RES_OK; +} + +res_T +senc3d_enclosure_get_triangle + (const struct senc3d_enclosure* enclosure, + const unsigned itri, + unsigned indices[3]) +{ + const struct side_enc* side; + int i; + if(!enclosure || !indices + || itri >= enclosure->data->header.primitives_count) + return RES_BAD_ARG; + ASSERT(darray_sides_enc_size_get(&enclosure->data->sides) + == enclosure->data->header.primitives_count); + side = darray_sides_enc_cdata_get(&enclosure->data->sides) + itri; + FOR_EACH(i, 0, 3) { + ASSERT(side->vertice_id[i] < UINT_MAX); + indices[i] = (unsigned)side->vertice_id[i]; /* Back to API type */ + } + return RES_OK; +} + +res_T +senc3d_enclosure_get_vertex + (const struct senc3d_enclosure* enclosure, + const unsigned ivert, + double coord[3]) +{ + if(!enclosure || !coord + || ivert >= enclosure->data->header.vertices_count) { + return RES_BAD_ARG; + } else { + const vrtx_id_t idx + = darray_vrtx_id_cdata_get(&enclosure->data->vertices)[ivert]; + const union double3* positions + = darray_position_cdata_get(&enclosure->scene->vertices); + ASSERT(darray_vrtx_id_size_get(&enclosure->data->vertices) + == enclosure->data->header.vertices_count); + d3_set(coord, positions[idx].vec); + return RES_OK; + } +} + +res_T +senc3d_enclosure_get_triangle_id + (const struct senc3d_enclosure* enclosure, + const unsigned itri, + unsigned* gid, + enum senc3d_side* sde) +{ + const struct side_enc* side; + if(!enclosure || !gid || !sde + || itri >= enclosure->data->header.primitives_count) + return RES_BAD_ARG; + ASSERT(darray_sides_enc_size_get(&enclosure->data->sides) + == enclosure->data->header.primitives_count); + side = darray_sides_enc_cdata_get(&enclosure->data->sides) + itri; + *gid = (unsigned)TRGSIDE_2_TRG(side->side_id); + *sde = TRGSIDE_2_SIDE(side->side_id); + return RES_OK; +} + +res_T +senc3d_enclosure_get_medium + (const struct senc3d_enclosure* enclosure, + const unsigned imed, + unsigned* medium) +{ + if(!enclosure || !medium + || imed >= enclosure->data->header.enclosed_media_count) + return RES_BAD_ARG; + ASSERT(enclosure->data->header.enclosed_media_count + == darray_media_size_get(&enclosure->data->enclosed_media)); + *medium = darray_media_cdata_get(&enclosure->data->enclosed_media)[imed]; + return RES_OK; +} + +res_T +senc3d_enclosure_ref_get(struct senc3d_enclosure* enc) +{ + if(!enc) return RES_BAD_ARG; + ref_get(&enc->ref); + return RES_OK; +} + +res_T +senc3d_enclosure_ref_put(struct senc3d_enclosure* enc) +{ + if(!enc) return RES_BAD_ARG; + ref_put(&enc->ref, enclosure_release); + return RES_OK; +} diff --git a/src/senc3d_enclosure_c.h b/src/senc3d_enclosure_c.h @@ -0,0 +1,37 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_ENCLOSURE_C_H +#define SENC3D_ENCLOSURE_C_H + +#include <rsys/ref_count.h> + +#include "senc3d.h" + +struct enclosure_data; +struct senc3d_scene; + +struct senc3d_enclosure { + const struct enclosure_data* data; + struct senc3d_scene* scene; + ref_T ref; +}; + +struct senc3d_enclosure* +enclosure_create + (struct senc3d_scene* scene, + const unsigned idx); + +#endif /* SENC3D_ENCLOSURE_C_H */ diff --git a/src/senc3d_enclosure_data.h b/src/senc3d_enclosure_data.h @@ -0,0 +1,235 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_ENCLOSURE_DATA_H +#define SENC3D_ENCLOSURE_DATA_H + +#include "senc3d.h" +#include "SENC3D_internal_types.h" +#include "SENC3D_side_range.h" + +#include <rsys/rsys.h> +#include <rsys/ref_count.h> +#include <rsys/hash_table.h> +#include <rsys/dynamic_array.h> +#include <rsys/hash_table.h> + +#include <limits.h> + +#define DARRAY_NAME vrtx_id +#define DARRAY_DATA vrtx_id_t +#include <rsys/dynamic_array.h> + +#define HTABLE_NAME vrtx_id +#define HTABLE_KEY vrtx_id_t +#define HTABLE_DATA vrtx_id_t +#include <rsys/hash_table.h> + +struct side_enc { + vrtx_id_t vertice_id[3]; + side_id_t side_id; +}; + +#define DARRAY_NAME sides_enc +#define DARRAY_DATA struct side_enc +#include <rsys/dynamic_array.h> + +/* unsigned char array with init to zero */ +static FINLINE void +zero_init_uchar + (struct mem_allocator* alloc, unsigned char* data) +{ + ASSERT(data); (void) alloc; + *data = 0; +} +#define DARRAY_FUNCTOR_INIT zero_init_uchar +#include <rsys/dynamic_array_uchar.h> + +static void +init_header(struct senc3d_enclosure_header* header) +{ + ASSERT(header); + header->enclosure_id = ENCLOSURE_NULL__; + header->primitives_count = 0; + header->unique_primitives_count = 0; + header->vertices_count = 0; + header->enclosed_media_count = 0; + header->is_infinite = CHAR_MAX; +} + +#define DARRAY_NAME media +#define DARRAY_DATA medium_id_t +#include <rsys/dynamic_array.h> + +static FINLINE res_T +bool_array_of_media_merge + (struct darray_uchar* dst, + const unsigned char* src, + const medium_id_t sz) +{ + res_T res = RES_OK; + medium_id_t i; + unsigned char* data_dst; + + ASSERT(src && dst); + + OK(darray_uchar_resize(dst, sz)); + data_dst = darray_uchar_data_get(dst); + ASSERT(sz <= MEDIUM_MAX__); + if(res != RES_OK) goto error; + FOR_EACH(i, 0, sz) { + if(!src[i]) continue; + data_dst[i] = 1; + } +end: + return res; +error: + goto end; +} + +static FINLINE res_T +bool_array_of_media_to_darray_media + (struct darray_media* dst, + const struct darray_uchar* src, + const medium_id_t next_medium_idx) +{ + res_T res = RES_OK; + unsigned m_idx; + const unsigned char* data; + + ASSERT(src && dst); + + data = darray_uchar_cdata_get(src); + ASSERT(next_medium_idx + 1 == darray_uchar_size_get(src)); + ASSERT(next_medium_idx < MEDIUM_MAX__); + darray_media_clear(dst); + if(res != RES_OK) goto error; + FOR_EACH(m_idx, 0, next_medium_idx + 1) { + medium_id_t medium = m_idx ? (medium_id_t)(m_idx - 1) : SENC3D_UNSPECIFIED_MEDIUM; + if(!data[m_idx]) continue; + res = darray_media_push_back(dst, &medium); + if(res != RES_OK) goto error; + } +end: + return res; +error: + goto end; +} + +struct enclosure_data { + struct senc3d_enclosure_header header; + /* Same triangle can appear twice if both sides */ + struct darray_sides_enc sides; + /* Index of vertices in scene's unique vertices */ + struct darray_vrtx_id vertices; + /* List of the enclosed media */ + struct darray_uchar tmp_enclosed_media; + struct darray_media enclosed_media; + /* Number of components involved in this enclosure */ + component_id_t cc_count; + /* Linked list of the components */ + component_id_t first_component; + /* Range of triangles member of the enclosure */ + struct side_range side_range; + /* Counts */ + side_id_t side_count; +}; + +static FINLINE void +enclosure_data_init(struct mem_allocator* alloc, struct enclosure_data* enc) { + ASSERT(enc); + init_header(&enc->header); + enc->cc_count = 0; + enc->first_component = COMPONENT_NULL__; + enc->side_range.first = SIDE_NULL__; + enc->side_range.last = 0; + enc->side_count = 0; + darray_sides_enc_init(alloc, &enc->sides); + darray_vrtx_id_init(alloc, &enc->vertices); + darray_uchar_init(alloc, &enc->tmp_enclosed_media); + darray_media_init(alloc, &enc->enclosed_media); +} + +static FINLINE res_T +enclosure_data_copy + (struct enclosure_data* dst, + const struct enclosure_data* src) +{ + res_T res = RES_OK; + ASSERT(src && dst); + dst->header = src->header; + dst->cc_count = src->cc_count; + dst->first_component = src->first_component; + dst->side_range = src->side_range; + dst->side_count = src->side_count; + OK(darray_sides_enc_copy(&dst->sides, &src->sides)); + OK(darray_vrtx_id_copy(&dst->vertices, &src->vertices)); + OK(darray_uchar_copy(&dst->tmp_enclosed_media, &src->tmp_enclosed_media)); + OK(darray_media_copy(&dst->enclosed_media, &src->enclosed_media)); +error: + return res; +} + +static FINLINE void +enclosure_data_release(struct enclosure_data* n) { + ASSERT(n); + darray_sides_enc_release(&n->sides); + darray_vrtx_id_release(&n->vertices); + darray_uchar_release(&n->tmp_enclosed_media); + darray_media_release(&n->enclosed_media); +} + +static FINLINE res_T +enclosure_data_copy_and_release + (struct enclosure_data* dst, + struct enclosure_data* src) +{ + res_T res = RES_OK; + ASSERT(src && dst); + dst->header = src->header; + dst->cc_count = src->cc_count; + dst->first_component = src->first_component; + dst->side_range = src->side_range; + dst->side_count = src->side_count; + OK(darray_sides_enc_copy_and_release(&dst->sides, &src->sides)); + OK(darray_vrtx_id_copy_and_release(&dst->vertices, &src->vertices)); + OK(darray_uchar_copy_and_release(&dst->tmp_enclosed_media, + &src->tmp_enclosed_media)); + OK(darray_media_copy_and_release(&dst->enclosed_media, &src->enclosed_media)); +error: + return res; +} + +#define DARRAY_NAME enclosure +#define DARRAY_DATA struct enclosure_data +#define DARRAY_FUNCTOR_INIT enclosure_data_init +#define DARRAY_FUNCTOR_COPY enclosure_data_copy +#define DARRAY_FUNCTOR_RELEASE enclosure_data_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE enclosure_data_copy_and_release +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME enc_id +#define DARRAY_DATA enclosure_id_t +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME enc_ids_array +#define DARRAY_DATA struct darray_enc_id +#define DARRAY_FUNCTOR_INIT darray_enc_id_init +#define DARRAY_FUNCTOR_COPY darray_enc_id_copy +#define DARRAY_FUNCTOR_RELEASE darray_enc_id_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release +#include <rsys/dynamic_array.h> + +#endif /* SENC3D_ENCLOSURE_DATA_H */ diff --git a/src/senc3d_internal_types.h b/src/senc3d_internal_types.h @@ -0,0 +1,142 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_INTERNAL_TYPES_H +#define SENC3D_INTERNAL_TYPES_H + +#include "senc3d.h" + +#include <rsys/math.h> + +#include <stdio.h> +#include <stdint.h> + +/* Utility macros */ +#ifdef NDEBUG +#define OK2(Expr)\ + if((tmp_res = (Expr)) != RES_OK) goto tmp_error; + +#define OK(Expr)\ + if((res = (Expr)) != RES_OK) goto error; +#else +#define OK2(Expr)\ + if((tmp_res = (Expr)) != RES_OK) {\ + fprintf(stderr, "%s: error code set to %d at line %d\n", FUNC_NAME,\ + tmp_res, __LINE__);\ + goto tmp_error;\ + } + +#define OK(Expr)\ + if((res = (Expr)) != RES_OK) {\ + fprintf(stderr, "%s: error code set to %d at line %d\n", FUNC_NAME,\ + res, __LINE__);\ + goto error;\ + } +#endif + +/* Side IDs are uint32_t */ +typedef uint32_t side_id_t; +#define SIDE_MAX__ (UINT32_MAX-1) +#define SIDE_NULL__ UINT32_MAX + +/* Trg IDs use internally side_id_t */ +/* Cannot be larger than unsigned, as the API uses it. */ +typedef side_id_t trg_id_t; +/* TRG_MAX__ is limited to allow to count sides */ +#define TRG_MAX__ (SIDE_MAX__ / 2) +#define TRG_NULL__ UINT32_MAX + +/* Vertex IDs are internally uint32_t */ +/* Cannot be larger than unsigned, as the API uses it. */ +typedef uint32_t vrtx_id_t; +#define VRTX_MAX__ (UINT32_MAX-1) +#define VRTX_NULL__ UINT32_MAX + +/* Edge IDs use the same type than vertex IDs */ +/* Cannot be larger than unsigned, as the API uses it. */ +typedef vrtx_id_t edge_id_t; +#define EDGE_MAX__ VRTX_MAX__ +#define EDGE_NULL__ VRTX_NULL__ + +/* Medium IDs are internally uint32_t */ +/* Should nnot be larger than unsigned, as the API uses it. */ +typedef uint32_t medium_id_t; +#define MEDIUM_MAX__ INT32_MAX +#define MEDIUM_NULL__ UINT32_MAX + +/* Enclosure IDs are internally uint32_t */ +/* Cannot be larger than unsigned, as the API uses it. */ +typedef uint32_t enclosure_id_t; +#define ENCLOSURE_MAX__ UINT32_MAX +#define ENCLOSURE_NULL__ UINT32_MAX + +/* Component IDs use the same type than enclosure IDs */ +typedef enclosure_id_t component_id_t; +#define COMPONENT_MAX__ (UINT32_MAX - 2) /* To allow special values */ +#define COMPONENT_NULL__ UINT32_MAX +/* Special values */ +#define CC_GROUP_ROOT_NONE UINT32_MAX +#define CC_GROUP_ROOT_INFINITE (UINT32_MAX - 1) +#define CC_GROUP_ID_NONE UINT32_MAX +#define CC_ID_NONE UINT32_MAX + +/* This one is used as flag */ +enum side_flag { + FLAG_FRONT = BIT(0), + FLAG_BACK = BIT(1) +}; + +/* Utility macros */ +static FINLINE trg_id_t +TRGSIDE_2_TRG(side_id_t s) { + ASSERT(((size_t)s >> 1) <= TRG_MAX__); + return s >> 1; +} + +static FINLINE int +TRGSIDE_IS_FRONT(side_id_t s) { + return (s & 1) == 0; +} + +static FINLINE enum senc3d_side +TRGSIDE_2_SIDE(side_id_t s) { + return (s & 1) ? SENC3D_BACK : SENC3D_FRONT; +} + +static FINLINE enum side_flag +TRGSIDE_2_SIDEFLAG(side_id_t s) { + return (s & 1) ? FLAG_BACK : FLAG_FRONT; +} + +static FINLINE unsigned char +SIDE_CANCELED_FLAG(enum side_flag f) { + ASSERT((f << 4) <= UCHAR_MAX); + return (unsigned char)(f << 4); +} + +static FINLINE side_id_t +TRGIDxSIDE_2_TRGSIDE(trg_id_t t, enum senc3d_side i) { + ASSERT((((size_t)t << 1) | (i == SENC3D_BACK)) < SIDE_MAX__); + ASSERT(i == SENC3D_FRONT || i == SENC3D_BACK); + return (side_id_t)((t << 1) | (i == SENC3D_BACK)); +} + +static FINLINE side_id_t +TRGSIDE_OPPOSITE(side_id_t s) { + return TRGIDxSIDE_2_TRGSIDE(TRGSIDE_2_TRG(s), + TRGSIDE_IS_FRONT(s) ? SENC3D_BACK : SENC3D_FRONT); +} + +#endif /* SENC3D_INTERNAL_TYPES_H */ diff --git a/src/senc3d_s3d_helper.h b/src/senc3d_s3d_helper.h @@ -0,0 +1,92 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_S3D_WRAPPER_H +#define SENC3D_S3D_WRAPPER_H + +#include "senc3d.h" + +#include <rsys/rsys.h> +#include <rsys/float3.h> + +/* Get vertex indices for the itri_th triangle. + * Suitable for use as get_indice callback in s3d_mesh_setup_indexed_vertices + * calls. */ +static FINLINE void +SENC3D_s3d_scene_get_indices + (const unsigned itri, + unsigned indices[3], + void* ctx) +{ + const struct senc3d_scene* scene = ctx; + res_T r; + ASSERT(indices && scene); + r = senc3d_scene_get_triangle(scene, itri, indices); + ASSERT(r == RES_OK); (void)r; +} + +/* Get coordinates for the ivert_th vertex. + * Suitable for use as s3d_vertex_data getter for S3D_POSITION s3d_attrib_usage + * in s3d_mesh_setup_indexed_vertices calls. */ +static FINLINE void +SENC3D_s3d_scene_get_position + (const unsigned ivert, + float coord[3], + void* ctx) +{ + const struct senc3d_scene* scene = ctx; + double tmp[3]; + res_T r; + ASSERT(coord && scene); + r = senc3d_scene_get_vertex(scene, ivert, tmp); + ASSERT(r == RES_OK); (void)r; + f3_set_d3(coord, tmp); +} + +/* Get vertex indices for the itri_th triangle of the enclosure. + * Suitable for use as get_indice callback in s3d_mesh_setup_indexed_vertices + * calls. */ +static FINLINE void +SENC3D_s3d_enclosure_get_indices + (const unsigned itri, + unsigned indices[3], + void* ctx) +{ + const struct senc3d_enclosure* enclosure = ctx; + res_T r; + ASSERT(indices && ctx); + r = senc3d_enclosure_get_triangle(enclosure, itri, indices); + ASSERT(r == RES_OK); (void)r; +} + +/* Get coordinates for the ivert_th vertex of the enclosure. + * Suitable for use as s3d_vertex_data getter for S3D_POSITION s3d_attrib_usage + * in s3d_mesh_setup_indexed_vertices calls. */ +static FINLINE void +SENC3D_s3d_enclosure_get_position + (const unsigned ivert, + float coord[3], + void* ctx) +{ + const struct senc3d_enclosure* enclosure = ctx; + double tmp[3]; + res_T r; + ASSERT(coord && ctx); + r = senc3d_enclosure_get_vertex(enclosure, ivert, tmp); + ASSERT(r == RES_OK); (void)r; + f3_set_d3(coord, tmp); +} + +#endif /* SENC3D_S3D_WRAPPER_H */ diff --git a/src/senc3d_scene.c b/src/senc3d_scene.c @@ -0,0 +1,327 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "senc3d_device_c.h" +#include "senc3d_scene_c.h" +#include "senc3d_scene_analyze_c.h" + +#include <rsys/rsys.h> +#include <rsys/double3.h> +#include <rsys/mem_allocator.h> + +#include <limits.h> + +/******************************************************************************* + * Helper function + ******************************************************************************/ +static void +scene_release(ref_T * ref) +{ + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + ASSERT(ref); + scn = CONTAINER_OF(ref, struct senc3d_scene, ref); + dev = scn->dev; + darray_triangle_in_release(&scn->triangles_in); + darray_position_release(&scn->vertices); + darray_side_range_release(&scn->media_use); + + darray_triangle_enc_release(&scn->analyze.triangles_enc); + darray_enclosure_release(&scn->analyze.enclosures); + darray_enc_ids_array_release(&scn->analyze.enc_ids_array_by_medium); + darray_frontier_edge_release(&scn->analyze.frontiers); + + MEM_RM(dev->allocator, scn); + SENC3D(device_ref_put(dev)); +} + +static INLINE int +compatible_medium + (const medium_id_t m1, + const medium_id_t m2) +{ + if(m1 == SENC3D_UNSPECIFIED_MEDIUM || m2 == SENC3D_UNSPECIFIED_MEDIUM) return 1; + return (m1 == m2); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +senc3d_scene_create + (struct senc3d_device* dev, + const int conv, + const unsigned ntris, + void(*indices)(const unsigned, unsigned*, void*), + void(*media)(const unsigned, unsigned*, void*), + const unsigned nverts, + void(*position)(const unsigned, double*, void* ctx), + void* ctx, + struct senc3d_scene** out_scn) +{ + struct senc3d_scene* scn = NULL; + /* Tables to detect duplicates */ + struct htable_vrtx unique_vertices; + struct htable_trg unique_triangles; + unsigned i; + res_T res = RES_OK; + + if(!dev || !out_scn || !indices || !position + /* Convention must be set both regarding FRONT/BACK and INSIDE/OUTSIDE */ + || !(conv & (SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_BACK)) + || !(conv & (SENC3D_CONVENTION_NORMAL_INSIDE | SENC3D_CONVENTION_NORMAL_OUTSIDE))) + return RES_BAD_ARG; + + scn = MEM_CALLOC(dev->allocator, 1, sizeof(struct senc3d_scene)); + if(!scn) { + log_err(dev, "%s: could not allocate the StarEnclosures scene.\n", FUNC_NAME); + res = RES_MEM_ERR; + goto error; + } + ref_init(&scn->ref); + SENC3D(device_ref_get(dev)); + scn->dev = dev; + scn->convention = conv; + scn->ntris = ntris; + scn->next_medium_idx = 0; + scn->nverts = nverts; + darray_triangle_in_init(dev->allocator, &scn->triangles_in); + darray_position_init(dev->allocator, &scn->vertices); + htable_vrtx_init(dev->allocator, &unique_vertices); + htable_trg_init(dev->allocator, &unique_triangles); + darray_side_range_init(dev->allocator, &scn->media_use); + + darray_triangle_enc_init(scn->dev->allocator, &scn->analyze.triangles_enc); + darray_enclosure_init(scn->dev->allocator, &scn->analyze.enclosures); + darray_enc_ids_array_init(scn->dev->allocator, + &scn->analyze.enc_ids_array_by_medium); + darray_frontier_edge_init(scn->dev->allocator, &scn->analyze.frontiers); + /* Enclosure 0 is always defined for infinite */ + OK(darray_enclosure_resize(&scn->analyze.enclosures, 1)); + scn->analyze.enclosures_count = 1; + + if(!scn || !indices || !position || !nverts || !ntris) { + res = RES_BAD_ARG; + goto error; + } + + OK(darray_position_reserve(&scn->vertices, scn->nverts)); + OK(darray_triangle_in_reserve(&scn->triangles_in, scn->ntris)); + OK(htable_vrtx_reserve(&unique_vertices, scn->nverts)); + OK(htable_trg_reserve(&unique_triangles, scn->ntris)); + + /* Get vertices */ + FOR_EACH(i, 0, nverts) { + vrtx_id_t* p_vrtx; + union double3 tmp; + /* API: position needs an unsigned */ + position(i, tmp.vec, ctx); + p_vrtx = htable_vrtx_find(&unique_vertices, &tmp); + if(p_vrtx) { + /* Duplicate vertex */ + log_err(scn->dev, "%s: vertex %u is a duplicate.\n", + FUNC_NAME, i); + res = RES_BAD_ARG; + goto error; + } + /* New vertex */ + ASSERT(i == htable_vrtx_size_get(&unique_vertices)); + OK(darray_position_push_back(&scn->vertices, &tmp)); + OK(htable_vrtx_set(&unique_vertices, &tmp, &i)); + } + /* Get triangles */ + FOR_EACH(i, 0, ntris) { + int j; + unsigned med[2] = { SENC3D_UNSPECIFIED_MEDIUM, SENC3D_UNSPECIFIED_MEDIUM }; + unsigned ind[3]; + union vrtx_id3 trg_key; + struct triangle_in tmp; + trg_id_t* p_trg; + indices(i, ind, ctx); /* API: indices need unsigneds */ + FOR_EACH(j, 0, 3) { + if(ind[j] >= nverts) { + log_err(scn->dev, "%s: triangle %u uses invalid vertex id %u.\n", + FUNC_NAME, i, ind[j]); + res = RES_BAD_ARG; + goto error; + } + ASSERT(ind[j] <= VRTX_MAX__); + tmp.vertice_id[j] = (vrtx_id_t)ind[j]; + } + if(tmp.vertice_id[0] == tmp.vertice_id[1] + || tmp.vertice_id[0] == tmp.vertice_id[2] + || tmp.vertice_id[1] == tmp.vertice_id[2]) + { + log_err(scn->dev, "%s: triangle %u is degenerated.\n", + FUNC_NAME, i); + res = RES_BAD_ARG; + goto error; + } + /* Get media */ + if(media) media(i, med, ctx); /* API: media needs an unsigned */ + trg_make_key(&trg_key, tmp.vertice_id); + p_trg = htable_trg_find(&unique_triangles, &trg_key); + if(p_trg) { + /* Duplicate triangle */ + log_err(scn->dev, "%s: triangle %u is a duplicate.\n", + FUNC_NAME, i); + res = RES_BAD_ARG; + goto error; + } + /* New triangle */ + ASSERT(i == htable_trg_size_get(&unique_triangles)); + OK(htable_trg_set(&unique_triangles, &trg_key, &i)); + FOR_EACH(j, 0, 2) { + struct side_range* media_use; + unsigned m_idx = (med[j] == SENC3D_UNSPECIFIED_MEDIUM) ? 0 : med[j] + 1; + tmp.medium[j] = (medium_id_t)med[j]; + if(m_idx >= scn->next_medium_idx) { + scn->next_medium_idx = m_idx; + darray_side_range_resize(&scn->media_use, 1 + m_idx); + } + /* media_use 0 is for SENC3D_UNSPECIFIED_MEDIUM */ + media_use = darray_side_range_data_get(&scn->media_use) + m_idx; + media_use->first = + MMIN(media_use->first, TRGIDxSIDE_2_TRGSIDE((trg_id_t)i, j)); + ASSERT(media_use->first < 2 * (scn->ntris + 1)); + media_use->last = + MMAX(media_use->last, TRGIDxSIDE_2_TRGSIDE((trg_id_t)i, j)); + ASSERT(media_use->last < 2 * (scn->ntris + 1)); + ASSERT(media_use->first <= media_use->last); + } + OK(darray_triangle_in_push_back(&scn->triangles_in, &tmp)); + } + + OK(darray_enc_ids_array_resize(&scn->analyze.enc_ids_array_by_medium, + 1 + scn->next_medium_idx)); /* +1 is for unspecified */ + /* Proceed to the analyze */ + OK(scene_analyze(scn)); + +exit: + htable_vrtx_release(&unique_vertices); + htable_trg_release(&unique_triangles); + if(scn) *out_scn = scn; + return res; + +error: + if(scn) { + SENC3D(scene_ref_put(scn)); + scn = NULL; + } + goto exit; +} + +res_T +senc3d_scene_get_convention + (const struct senc3d_scene* scn, + int* convention) +{ + if(!scn || !convention) return RES_BAD_ARG; + *convention = scn->convention; + return RES_OK; +} + +res_T +senc3d_scene_get_triangles_count + (const struct senc3d_scene* scn, + unsigned* count) +{ + if(!scn || !count) return RES_BAD_ARG; + *count = scn->ntris; + return RES_OK; +} + +res_T +senc3d_scene_get_triangle + (const struct senc3d_scene* scn, + const unsigned itri, + unsigned indices[3]) +{ + const struct triangle_in* trg; + int i; + if(!scn || !indices + || itri >= darray_triangle_in_size_get(&scn->triangles_in)) + return RES_BAD_ARG; + trg = darray_triangle_in_cdata_get(&scn->triangles_in) + itri; + + FOR_EACH(i, 0, 3) { + ASSERT(trg->vertice_id[i] < UINT_MAX); + indices[i] = (unsigned)trg->vertice_id[i]; /* Back to API type */ + } + return RES_OK; +} + +res_T +senc3d_scene_get_triangle_media + (const struct senc3d_scene* scn, + const unsigned itri, + unsigned media[2]) +{ + const struct triangle_in* trg; + int i; + if(!scn || !media + || itri >= darray_triangle_in_size_get(&scn->triangles_in)) + return RES_BAD_ARG; + trg = darray_triangle_in_cdata_get(&scn->triangles_in) + itri; + + FOR_EACH(i, 0, 2) { + ASSERT(trg->vertice_id[i] < UINT_MAX); + media[i] = (unsigned)trg->medium[i]; /* Back to API type */ + } + return RES_OK; +} + +res_T +senc3d_scene_get_vertices_count + (const struct senc3d_scene* scn, + unsigned* count) +{ + if(!scn || !count) return RES_BAD_ARG; + *count = scn->nverts; + return RES_OK; +} + +res_T +senc3d_scene_get_vertex + (const struct senc3d_scene* scn, + const unsigned ivert, + double coord[3]) +{ + const union double3* v; + if(!scn || !coord + || ivert >= darray_position_size_get(&scn->vertices)) + return RES_BAD_ARG; + + v = darray_position_cdata_get(&scn->vertices) + ivert; + d3_set(coord, v->vec); + return RES_OK; +} + +res_T +senc3d_scene_ref_get(struct senc3d_scene* scn) +{ + if(!scn) return RES_BAD_ARG; + ref_get(&scn->ref); + return RES_OK; +} + +res_T +senc3d_scene_ref_put(struct senc3d_scene* scn) +{ + if(!scn) return RES_BAD_ARG; + ref_put(&scn->ref, scene_release); + return RES_OK; +} diff --git a/src/senc3d_scene_analyze.c b/src/senc3d_scene_analyze.c @@ -0,0 +1,1347 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "senc3d_device_c.h" +#include "senc3d_scene_c.h" +#include "senc3d_scene_analyze_c.h" +#include "SENC3D_internal_types.h" + +#include <rsys/rsys.h> +#include <rsys/float3.h> +#include <rsys/double33.h> +#include <rsys/mem_allocator.h> +#include <rsys/hash_table.h> +#include <rsys/dynamic_array.h> +#include <rsys/dynamic_array_uchar.h> +#include <rsys/clock_time.h> + +#include <star/s3d.h> + +#include <omp.h> +#include <limits.h> +#include <stdlib.h> + +#define CC_DESCRIPTOR_NULL__ {\ + CHAR_MAX, VRTX_NULL__, 0,\ + CC_ID_NONE, CC_GROUP_ROOT_NONE, ENCLOSURE_NULL__,\ + { TRG_NULL__, 0},\ + NULL\ +} +#ifdef COMPILER_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif +const struct cc_descriptor CC_DESCRIPTOR_NULL = CC_DESCRIPTOR_NULL__; +#ifdef COMPILER_GCC + #pragma GCC diagnostic pop +#endif + +#define DARRAY_NAME component_id +#define DARRAY_DATA component_id_t +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Helper function + ******************************************************************************/ +static INLINE int +neighbour_cmp(const void* w1, const void* w2) +{ + const double a1 = ((struct neighbour_info*)w1)->angle; + const double a2 = ((struct neighbour_info*)w2)->angle; + return (a1 > a2) - (a1 < a2); +} + +static side_id_t +get_side_not_in_connex_component + (const side_id_t last_side, + const struct trgside* trgsides, + const unsigned char* processed, + side_id_t* first_side_not_in_component, + const medium_id_t medium) +{ + ASSERT(trgsides && processed && first_side_not_in_component); + { + side_id_t i = *first_side_not_in_component; + while (i <= last_side + && (trgsides[i].medium != medium + || (processed[TRGSIDE_2_TRG(i)] & TRGSIDE_2_SIDEFLAG(i)))) + ++i; + + *first_side_not_in_component = i + 1; + if(i > last_side) return SIDE_NULL__; + return i; + } +} + +static void +get_scn_indices(const unsigned itri, unsigned ids[3], void* ctx) { + int i; + const struct senc3d_scene* scene = ctx; + const struct triangle_in* trg = + darray_triangle_in_cdata_get(&scene->triangles_in) + itri; + FOR_EACH(i, 0, 3) { + ASSERT(trg->vertice_id[i] < scene->nverts); + ids[i] = (unsigned)trg->vertice_id[i]; /* Back to API type */ + } +} + +static void +get_scn_position(const unsigned ivert, float pos[3], void* ctx) { + const struct senc3d_scene* scene = ctx; + const union double3* pt = + darray_position_cdata_get(&scene->vertices) + ivert; + f3_set_d3(pos, pt->vec); +} + +static int +self_hit_filter + (const struct s3d_hit* hit, + const float ray_org[3], + const float ray_dir[3], + void* ray_data, + void* filter_data) +{ + const struct darray_triangle_comp* triangles_comp = filter_data; + const component_id_t* origin_component = ray_data; + const struct triangle_comp* hit_trg_comp; + + (void)ray_org; (void)ray_dir; + ASSERT(hit && triangles_comp && origin_component); + ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(triangles_comp)); + hit_trg_comp = darray_triangle_comp_cdata_get(triangles_comp) + + hit->prim.prim_id; + return (hit_trg_comp->component[SENC3D_FRONT] == *origin_component + || hit_trg_comp->component[SENC3D_BACK] == *origin_component); + +} + +static void +extract_connex_components + (struct senc3d_scene* scn, + struct trgside* trgsides, + struct darray_ptr_component_descriptor* connex_components, + const struct darray_triangle_tmp* triangles_tmp_array, + struct darray_triangle_comp* triangles_comp_array, + struct s3d_scene_view** s3d_view, + ATOMIC* component_count, + /* Shared error status. + * We accept to overwrite an error with a different error */ + res_T* p_res) +{ + /* This function is called from an omp parallel block and executed + * concurrently. */ + struct mem_allocator* alloc; + int64_t m_idx; + struct darray_side_id stack; + struct darray_side_id ids_of_sides_around_max_z_vertex; + const union double3* positions; + const struct triangle_tmp* triangles_tmp; + struct triangle_comp* triangles_comp; + /* An array to flag sides when processed */ + unsigned char* processed; + /* An array to store the component being processed */ + struct darray_side_id current_component; + /* A bool array to store media of the component being processed */ + unsigned char* current_media = NULL; + size_t sz, ii; + + ASSERT(scn && trgsides && connex_components && triangles_tmp_array + && triangles_comp_array && s3d_view && component_count && p_res); + alloc = scn->dev->allocator; + positions = darray_position_cdata_get(&scn->vertices); + triangles_tmp = darray_triangle_tmp_cdata_get(triangles_tmp_array); + triangles_comp = darray_triangle_comp_data_get(triangles_comp_array); + darray_side_id_init(alloc, &stack); + darray_side_id_init(alloc, &ids_of_sides_around_max_z_vertex); + darray_side_id_init(alloc, &current_component); + processed = MEM_CALLOC(alloc, scn->ntris, sizeof(unsigned char)); + if(!processed) { + *p_res = RES_MEM_ERR; + return; + } + +#ifndef NDEBUG + #pragma omp single + { + trg_id_t t_; + int s; + ASSERT(darray_ptr_component_descriptor_size_get(connex_components) == 0); + FOR_EACH(t_, 0, scn->ntris) { + const struct triangle_in* trg_in = + darray_triangle_in_cdata_get(&scn->triangles_in) + t_; + const struct side_range* media_use + = darray_side_range_cdata_get(&scn->media_use); + FOR_EACH(s, 0, 2) { + const side_id_t side = TRGIDxSIDE_2_TRGSIDE(t_, s); + medium_id_t medium = trg_in->medium[s]; + m_idx = (medium == SENC3D_UNSPECIFIED_MEDIUM) ? 0 : medium + 1; + ASSERT(media_use[m_idx].first <= side && side + <= media_use[m_idx].last); + } + } + } /* Implicit barrier here */ +#endif + + /* We loop on sides to build connex components. */ + #pragma omp for schedule(dynamic) nowait + /* Process all media, including unspecified */ + for(m_idx = 0; m_idx < 1 + (int64_t)scn->next_medium_idx; m_idx++) { + const medium_id_t medium + = m_idx ? (medium_id_t)(m_idx - 1) : SENC3D_UNSPECIFIED_MEDIUM; + /* media_use 0 is for SENC3D_UNSPECIFIED_MEDIUM, n+1 is for n */ + const struct side_range* media_use = + darray_side_range_cdata_get(&scn->media_use) + m_idx; + /* Any not-already-used side is used as a starting point */ + side_id_t first_side_not_in_component = media_use->first; + double max_nz; + side_id_t max_nz_side_id = SIDE_NULL__; + const side_id_t last_side = media_use->last; + int component_canceled = 0; + res_T tmp_res = RES_OK; + ATOMIC id; + + if(*p_res != RES_OK) continue; + if(first_side_not_in_component == SIDE_NULL__) + continue; /* Unused medium */ + ASSERT(first_side_not_in_component < 2 * scn->ntris); + ASSERT(darray_side_id_size_get(&stack) == 0); + ASSERT(darray_side_id_size_get(&current_component) == 0); + for(;;) { /* Process all components for this medium */ + const side_id_t start_side_id = get_side_not_in_connex_component + (last_side, trgsides, processed, &first_side_not_in_component, medium); + side_id_t crt_side_id = start_side_id; + side_id_t last_side_id = start_side_id; + vrtx_id_t max_z_vrtx_id = VRTX_NULL__; + struct cc_descriptor *cc; + double max_z = -DBL_MAX; + component_canceled = 0; + ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->ntris); + darray_side_id_clear(&current_component); + + if(*p_res != RES_OK) break; + if(start_side_id == SIDE_NULL__) + break; /* start_side_id=SIDE_NULL__ => component done! */ + +#ifndef NDEBUG + { + trg_id_t tid = TRGSIDE_2_TRG(start_side_id); + enum senc3d_side s = TRGSIDE_2_SIDE(start_side_id); + medium_id_t side_med + = darray_triangle_in_data_get(&scn->triangles_in)[tid].medium[s]; + ASSERT(side_med == medium); + } +#endif + + /* Reuse array if possible, or create a new one */ + if(current_media) { + /* current_media 0 is for SENC3D_UNSPECIFIED_MEDIUM, n+1 is for n */ + memset(current_media, 0, 1 + scn->next_medium_idx); + } else { + current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, + sizeof(*current_media)); + if(!current_media) { + *p_res = RES_MEM_ERR; + continue; + } + } + current_media[m_idx] = 1; + for(;;) { /* Process all sides of this component */ + int i; + enum side_flag crt_side_flag = TRGSIDE_2_SIDEFLAG(crt_side_id); + struct trgside* crt_side = trgsides + crt_side_id; + const trg_id_t crt_trg_id = TRGSIDE_2_TRG(crt_side_id); + const struct triangle_in* trg_in = + darray_triangle_in_cdata_get(&scn->triangles_in) + crt_trg_id; + unsigned char* trg_used = processed + crt_trg_id; + const struct triangle_tmp* const trg_tmp = triangles_tmp + crt_trg_id; + ASSERT(crt_trg_id < scn->ntris); + + if(*p_res != RES_OK) break; + + /* Record Zmax information + * Keep track of the appropriate vertex of the component in order + * to cast a ray at the component grouping step of the algorithm. + * The most appropriate vertex is (the) one with the greater Z + * coordinate. */ + if(max_z < trg_tmp->max_z) { + /* New best vertex */ + max_z = trg_tmp->max_z; + /* New vertex: reset list of sides */ + darray_side_id_clear(&ids_of_sides_around_max_z_vertex); + + /* Select a vertex with z == max_z */ + FOR_EACH(i, 0, 3) { + if(max_z == positions[trg_in->vertice_id[i]].pos.z) { + max_z_vrtx_id = trg_in->vertice_id[i]; + break; + } + } + ASSERT(i < 3); /* Found one */ + /* List of sides using the vertex */ + OK2(darray_side_id_push_back(&ids_of_sides_around_max_z_vertex, + &crt_side_id)); + } else if(max_z == trg_tmp->max_z) { + /* Does this triangle use the currently selected max_z vertex? */ + FOR_EACH(i, 0, 3) { + if(max_z_vrtx_id == trg_in->vertice_id[i]) { + /* List of sides using the vertex */ + OK2(darray_side_id_push_back(&ids_of_sides_around_max_z_vertex, + &crt_side_id)); + break; + } + } + } + + /* Record crt_side both as component and triangle level */ + if((*trg_used & crt_side_flag) == 0) { + OK2(darray_side_id_push_back(&current_component, &crt_side_id)); + *trg_used = *trg_used | (unsigned char)crt_side_flag; + } + + /* Store neighbour's sides in a waiting stack */ + FOR_EACH(i, 0, 3) { + side_id_t neighbour_id = crt_side->facing_side_id[i]; + trg_id_t nbour_trg_id = TRGSIDE_2_TRG(neighbour_id); + enum side_flag nbour_side_id = TRGSIDE_2_SIDEFLAG(neighbour_id); + unsigned char* nbour_used = processed + nbour_trg_id; + const struct trgside* neighbour = trgsides + neighbour_id; + medium_id_t nbour_med_idx = (neighbour->medium == SENC3D_UNSPECIFIED_MEDIUM) + ? 0 : neighbour->medium + 1; + if(neighbour->medium < medium + || (*nbour_used & SIDE_CANCELED_FLAG(nbour_side_id))) + { + /* 1) Not the same medium. + * Neighbour's medium id is less than current medium: the whole + * component is to be processed by another thread (possibly the one + * associated with neighbour's medium). + * 2) Neighbour was canceled: no need to replay the component + * again as it will eventually rediscover the side with low medium + * id and recancel all the work in progress */ + component_canceled = 1; + darray_side_id_clear(&stack); + /* Don't cancel used flags as all these sides will get us back to + * (at least) the neighbour side we have just discovered, that will + * cancel them again and again */ + sz = darray_side_id_size_get(&current_component); + FOR_EACH(ii, 0, sz) { + side_id_t used_side + = darray_side_id_cdata_get(&current_component)[ii]; + trg_id_t used_trg_id = TRGSIDE_2_TRG(used_side); + enum side_flag used_side_flag + = TRGSIDE_2_SIDEFLAG(used_side); + unsigned char* used = processed + used_trg_id; + ASSERT(*used & (unsigned char)used_side_flag); + /* Set the used flag for sides in cancelled component as leading + * to further cancellations */ + *used |= SIDE_CANCELED_FLAG(used_side_flag); + } + + goto canceled; + } + if(*nbour_used & nbour_side_id) continue; /* Already processed */ + /* Mark neighbour as processed and stack it */ + *nbour_used |= (unsigned char)nbour_side_id; + OK2(darray_side_id_push_back(&stack, &neighbour_id)); + OK2(darray_side_id_push_back(&current_component, &neighbour_id)); + current_media[nbour_med_idx] = 1; + } + sz = darray_side_id_size_get(&stack); + if(sz == 0) break; /* Empty stack => component is done! */ + crt_side_id = darray_side_id_cdata_get(&stack)[sz - 1]; + darray_side_id_pop_back(&stack); + last_side_id = MMAX(last_side_id, crt_side_id); + } + canceled: + if(component_canceled) continue; + + /* Register the new component and get it initialized */ + cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor)); + if(!cc) *p_res = RES_MEM_ERR; + if(*p_res != RES_OK) break; + + ASSERT(medium == trgsides[start_side_id].medium); + ASSERT(max_z_vrtx_id != VRTX_NULL__); + cc_descriptor_init(alloc, cc); + id = ATOMIC_INCR(component_count) - 1; + ASSERT(id <= COMPONENT_MAX__); + cc->cc_id = (component_id_t)id; + sz = darray_side_id_size_get(&current_component); + ASSERT(sz <= SIDE_MAX__); + cc->side_count = (side_id_t)sz; + cc->side_range.first = start_side_id; + cc->side_range.last = last_side_id; + cc->max_z_vrtx_id = max_z_vrtx_id; + /* Tranfer ownership of the array to component */ + ASSERT(!cc->media && current_media); + cc->media = current_media; + current_media = NULL; + + /* Write component membership in the global structure + * No need for sync here as an unique thread writes a given side */ + {STATIC_ASSERT(sizeof(cc->cc_id) >= 4, Cannot_write_IDs_sync_free);} + ASSERT(IS_ALIGNED(triangles_comp->component, sizeof(cc->cc_id))); + FOR_EACH(ii, 0, sz) { + const side_id_t s = darray_side_id_cdata_get(&current_component)[ii]; + trg_id_t tid = TRGSIDE_2_TRG(s); + enum senc3d_side sid = TRGSIDE_2_SIDE(s); + component_id_t* cmp = triangles_comp[tid].component; + ASSERT(cmp[sid] == COMPONENT_NULL__); + ASSERT(trgsides[s].medium >= medium); + cmp[sid] = cc->cc_id; + } + + /* Compute the normal at the max_z vertex. */ + max_nz = 0; + sz = darray_side_id_size_get(&ids_of_sides_around_max_z_vertex); + ASSERT(sz > 0); + FOR_EACH(ii, 0, sz) { + const side_id_t side_id = + darray_side_id_cdata_get(&ids_of_sides_around_max_z_vertex)[ii]; + const trg_id_t trg_id = TRGSIDE_2_TRG(side_id); + enum senc3d_side s = TRGSIDE_2_SIDE(side_id); + const struct triangle_in* trg_in = + darray_triangle_in_cdata_get(&scn->triangles_in) + trg_id; + const struct triangle_comp* trg_comp = triangles_comp + trg_id; + const union double3* vertices = + darray_position_cdata_get(&scn->vertices); + double edge0[3], edge1[3], normal[3], norm; + + /* To ensure that triangles with 2 sides in the component total to 0 + * regardless of numeric accuracy, we need to prevent them to + * contribute (remember than x + y - y == x can be false). */ + ASSERT(trg_comp->component[s] == cc->cc_id); (void)s; + if(trg_comp->component[SENC3D_FRONT] == trg_comp->component[SENC3D_BACK]) + continue; + + d3_sub(edge0, vertices[trg_in->vertice_id[1]].vec, + vertices[trg_in->vertice_id[0]].vec); + d3_sub(edge1, vertices[trg_in->vertice_id[2]].vec, + vertices[trg_in->vertice_id[0]].vec); + d3_cross(normal, edge0, edge1); + norm = d3_normalize(normal, normal); + ASSERT(norm); (void)norm; + + if(fabs(max_nz) < fabs(normal[2])) { + max_nz_side_id = side_id; + max_nz = normal[2]; + } + } + if(max_nz == 0) cc->is_outer_border = 0; + else { + if(TRGSIDE_IS_FRONT(max_nz_side_id) + == ((scn->convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0)) { + /* Geom normal points towards the component */ + cc->is_outer_border = (max_nz < 0); + } else { + /* Geom normal points away from the component */ + cc->is_outer_border = (max_nz > 0); + } + } + + /* Need to synchronize connex_components growth as this global structure + * is accessed by multipe threads */ + #pragma omp critical + { + struct cc_descriptor** components; + sz = darray_ptr_component_descriptor_size_get(connex_components); + if(sz <= cc->cc_id) { + tmp_res = darray_ptr_component_descriptor_resize(connex_components, + 1 + cc->cc_id); + if(tmp_res != RES_OK) *p_res = tmp_res; + } + if(*p_res == RES_OK) { + /* Don't set the pointer before resize as this can lead to move data */ + components = + darray_ptr_component_descriptor_data_get(connex_components); + ASSERT(components[cc->cc_id] == NULL); + components[cc->cc_id] = cc; + } + } + } + tmp_error: + if(tmp_res != RES_OK) *p_res = tmp_res; + } /* No barrier here */ + + MEM_RM(alloc, processed); + MEM_RM(alloc, current_media); + darray_side_id_release(&current_component); + darray_side_id_release(&stack); + darray_side_id_release(&ids_of_sides_around_max_z_vertex); + + /* The first thread here creates the s3d view */ + #pragma omp single nowait + if(*p_res == RES_OK) { + res_T res = RES_OK; + struct s3d_device* s3d = NULL; + struct s3d_scene* s3d_scn = NULL; + struct s3d_shape* s3d_shp = NULL; + struct s3d_vertex_data attribs; + + attribs.type = S3D_FLOAT3; + attribs.usage = S3D_POSITION; + attribs.get = get_scn_position; + + /* Put geometry in a 3D view */ + OK(s3d_device_create(scn->dev->logger, alloc, 0, &s3d)); + OK(s3d_scene_create(s3d, &s3d_scn)); + OK(s3d_shape_create_mesh(s3d, &s3d_shp)); + + /* Back to API type for ntris and nverts */ + ASSERT(scn->ntris < UINT_MAX); + ASSERT(scn->nverts < UINT_MAX); + OK(s3d_mesh_setup_indexed_vertices(s3d_shp, + (unsigned)scn->ntris, get_scn_indices, + (unsigned)scn->nverts, &attribs, 1, scn)); + s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter, + triangles_comp_array); + OK(s3d_scene_attach_shape(s3d_scn, s3d_shp)); + OK(s3d_scene_view_create(s3d_scn, S3D_TRACE, s3d_view)); + error: + if(res != RES_OK) *p_res = res; + if(s3d) S3D(device_ref_put(s3d)); + if(s3d_scn) S3D(scene_ref_put(s3d_scn)); + if(s3d_shp) S3D(shape_ref_put(s3d_shp)); + } + +#ifndef NDEBUG + /* Need to wait for all threads done to be able to check stuff */ + #pragma omp barrier + if(*p_res != RES_OK) return; + #pragma omp single + { + trg_id_t t_; + component_id_t c; + ASSERT(ATOMIC_GET(component_count) == + (int)darray_ptr_component_descriptor_size_get(connex_components)); + FOR_EACH(t_, 0, scn->ntris) { + struct triangle_comp* trg_comp = + darray_triangle_comp_data_get(triangles_comp_array) + t_; + ASSERT(trg_comp->component[SENC3D_FRONT] != COMPONENT_NULL__); + ASSERT(trg_comp->component[SENC3D_BACK] != COMPONENT_NULL__); + } + FOR_EACH(c, 0, ATOMIC_GET(component_count)) { + struct cc_descriptor** components = + darray_ptr_component_descriptor_data_get(connex_components); + ASSERT(components[c] != NULL && components[c]->cc_id == c); + } + } /* Implicit barrier here */ +#endif +} + +static void +group_connex_components + (struct senc3d_scene* scn, + struct trgside* trgsides, + struct darray_triangle_comp* triangles_comp, + struct darray_ptr_component_descriptor* connex_components, + struct s3d_scene_view* s3d_view, + ATOMIC* next_enclosure_id, + /* Shared error status. + * We accept to overwrite an error with a different error */ + res_T* res) +{ + /* This function is called from an omp parallel block and executed + * concurrently. */ + struct cc_descriptor** descriptors; + const union double3* positions; + size_t tmp; + component_id_t cc_count; + int64_t ccc; + + (void)trgsides; + ASSERT(scn && trgsides && triangles_comp && connex_components + && s3d_view && next_enclosure_id && res); + ASSERT(scn->analyze.enclosures_count == 1); + + descriptors = darray_ptr_component_descriptor_data_get(connex_components); + tmp = darray_ptr_component_descriptor_size_get(connex_components); + ASSERT(tmp <= COMPONENT_MAX__); + cc_count = (component_id_t)tmp; + positions = darray_position_cdata_get(&scn->vertices); + + /* Cast rays to find links between connex components */ + #pragma omp for + for(ccc = 0; ccc < (int64_t)cc_count; ccc++) { + res_T tmp_res = RES_OK; + component_id_t c = (component_id_t)ccc; + struct s3d_hit hit = S3D_HIT_NULL; + float origin[3]; + const float dir[3] = { 0, 0, 1 }; + const float range[2] = { 0, FLT_MAX }; + struct cc_descriptor* const cc = descriptors[c]; + component_id_t self_hit_component = cc->cc_id; + const double* max_vrtx; + + if(*res != RES_OK) continue; + ASSERT(cc->cc_id == c); + ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE); + ASSERT(cc->max_z_vrtx_id < scn->nverts); + + max_vrtx = positions[cc->max_z_vrtx_id].vec; + if(cc->is_outer_border) { + ATOMIC id; + /* Don't need to cast a ray */ + cc->cc_group_root = cc->cc_id; /* New group with self as root */ + id = ATOMIC_INCR(next_enclosure_id) - 1; + ASSERT(id <= ENCLOSURE_MAX__); + cc->enclosure_id = (enclosure_id_t)id; + continue; + } + + f3_set_d3(origin, max_vrtx); + /* Self-hit data: self hit if hit this component "on the other side" */ + tmp_res = s3d_scene_view_trace_ray(s3d_view, origin, dir, range, + &self_hit_component, &hit); + if(tmp_res != RES_OK) { + *res = tmp_res; + continue; + } + /* If no hit, the component is facing an infinite medium */ + if(S3D_HIT_NONE(&hit)) { + cc->cc_group_root = CC_GROUP_ROOT_INFINITE; + cc->enclosure_id = 0; + } else { + /* If hit, group this component */ + const trg_id_t hit_trg_id = (trg_id_t)hit.prim.prim_id; + const struct triangle_comp* hit_trg_comp = + darray_triangle_comp_cdata_get(triangles_comp) + hit_trg_id; + enum senc3d_side hit_side = + ((hit.normal[2] < 0) /* Facing geometrical normal of hit */ + == ((scn->convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0)) + /* Warning: following Embree 2 convention for geometrical normals, + * the Star3D hit normal is left-handed while star-enclosure uses + * right-handed convention */ + ? SENC3D_BACK : SENC3D_FRONT; + ASSERT(hit.normal[2] != 0); + ASSERT(hit_trg_id < scn->ntris); + + /* Not really the root until following links */ + cc->cc_group_root = hit_trg_comp->component[hit_side]; + ASSERT(cc->cc_group_root < cc_count); + } + } + /* Implicit barrier here */ + ASSERT(ATOMIC_GET(next_enclosure_id) < ENCLOSURE_MAX__); + if(*res != RES_OK) return; + + /* One thread post-processes links to group connex components */ + #pragma omp single + { + res_T tmp_res = RES_OK; + scn->analyze.enclosures_count = (enclosure_id_t)ATOMIC_GET(next_enclosure_id); + tmp_res = darray_enclosure_resize(&scn->analyze.enclosures, + scn->analyze.enclosures_count); + if(tmp_res != RES_OK) { + *res = tmp_res; + } else { + struct enclosure_data* enclosures + = darray_enclosure_data_get(&scn->analyze.enclosures); + FOR_EACH(ccc, 0, cc_count) { + component_id_t c = (component_id_t)ccc; + struct cc_descriptor* const cc = descriptors[c]; + const struct cc_descriptor* other_desc = cc; + struct enclosure_data* enc; +#ifndef NDEBUG + component_id_t cc_cpt = 0; +#endif + + while(other_desc->enclosure_id == CC_GROUP_ID_NONE) { + ASSERT(other_desc->cc_group_root < cc_count); + other_desc = descriptors[other_desc->cc_group_root]; + /* Cannot have more components in cc than cc_count! */ + ASSERT(++cc_cpt <= cc_count); + } + ASSERT(other_desc->cc_group_root != CC_GROUP_ROOT_NONE); + ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE); + cc->cc_group_root = other_desc->cc_group_root; + cc->enclosure_id = other_desc->enclosure_id; + enc = enclosures + cc->enclosure_id; + ++enc->cc_count; + /* Linked list of componnents */ + enc->first_component = cc->cc_id; + enc->side_range.first = MMIN(enc->side_range.first, cc->side_range.first); + enc->side_range.last = MMAX(enc->side_range.last, cc->side_range.last); + enc->side_count += cc->side_count; + tmp_res = bool_array_of_media_merge(&enc->tmp_enclosed_media, cc->media, + scn->next_medium_idx + 1); + if(tmp_res != RES_OK) { + *res = tmp_res; + break; + } + } + } + } + /* Implicit barrier here */ +} + +static void +collect_and_link_neighbours + (struct senc3d_scene* scn, + struct trgside* trgsides, + struct darray_triangle_tmp* triangles_tmp_array, + struct darray_frontier_edge* frontiers, + /* Shared error status. + * We accept to overwrite an error with a different error */ + res_T* res) +{ + /* This function is called from an omp parallel block and executed + * concurrently. */ + const struct triangle_in* triangles_in; + struct triangle_tmp* triangles_tmp; + const union double3* vertices; + const int thread_count = omp_get_num_threads(); + const int rank = omp_get_thread_num(); + /* Htable used to give an id to edges */ + struct htable_edge_id edge_ids; + /* Array to keep neighbourhood of edges + * Resize/Push operations on neighbourhood_by_edge are valid in the + * openmp block because a given neighbourhood is only processed + * by a single thread */ + struct darray_neighbourhood neighbourhood_by_edge; + edge_id_t edge_count; + edge_id_t nbedges_guess; + edge_id_t e; + trg_id_t t; + size_t sz; + res_T tmp_res; + + ASSERT(scn && trgsides && triangles_tmp_array && frontiers && res); + ASSERT((size_t)scn->nverts + (size_t)scn->ntris + 2 <= EDGE_MAX__); + + htable_edge_id_init(scn->dev->allocator, &edge_ids); + darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); + + triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); + triangles_tmp = darray_triangle_tmp_data_get(triangles_tmp_array); + vertices = darray_position_cdata_get(&scn->vertices); + + ASSERT(scn->ntris == darray_triangle_tmp_size_get(triangles_tmp_array)); + + /* Make some room for edges. */ + nbedges_guess = 4 + (thread_count == 1 + ? (edge_id_t)(scn->nverts + scn->ntris) + : (edge_id_t)((scn->nverts + scn->ntris) / (0.75 * thread_count))); + OK2(darray_neighbourhood_reserve(&neighbourhood_by_edge, nbedges_guess)); + OK2(htable_edge_id_reserve(&edge_ids, nbedges_guess)); + + /* Loop on triangles to register edges. + * All threads considering all the edges and processing some */ + FOR_EACH(t, 0, scn->ntris) { + struct trg_edge edge; + unsigned char ee; + FOR_EACH(ee, 0, 3) { + edge_id_t* p_id; + size_t n_sz; + struct edge_neighbourhood* neighbourhood; + struct neighbour_info* info; + const vrtx_id_t v0 = triangles_in[t].vertice_id[ee]; + const vrtx_id_t v1 = triangles_in[t].vertice_id[(ee + 1) % 3]; + /* Process only "my" edges! */ + const int64_t h = + /* v0,v1 and v1,v0 must give the same hash!!! */ + v0 + v1 + (int64_t)MMIN(v0, v1); + if(h % thread_count != rank) continue; + /* Create edge. */ + set_edge(v0, v1, &edge, &triangles_tmp[t].reversed_edge[ee]); + /* Find edge id; create it if not already done. */ + p_id = htable_edge_id_find(&edge_ids, &edge); + if(p_id) { + neighbourhood = + darray_neighbourhood_data_get(&neighbourhood_by_edge) + *p_id; + ASSERT(neighbourhood->edge.vrtx0 == edge.vrtx0 + && neighbourhood->edge.vrtx1 == edge.vrtx1); + } else { + /* Create id */ + edge_id_t id; + sz = htable_edge_id_size_get(&edge_ids); + ASSERT(sz <= EDGE_MAX__); + id = (edge_id_t)sz; + ASSERT(htable_edge_id_size_get(&edge_ids) + == darray_neighbourhood_size_get(&neighbourhood_by_edge)); + OK2(htable_edge_id_set(&edge_ids, &edge, &id)); + OK2(darray_neighbourhood_resize(&neighbourhood_by_edge, 1 + sz)); + neighbourhood = darray_neighbourhood_data_get(&neighbourhood_by_edge) + sz; + /* Add neighbour info to a newly created edge's neighbour list */ + neighbourhood->edge = edge; + ASSERT(darray_neighbour_size_get(&neighbourhood->neighbours) == 0); + /* Just a guess: few edges will have less than 2 neighbours */ + OK2(darray_neighbour_reserve(&neighbourhood->neighbours, 2)); + } + /* Add neighbour info to neighbourhood */ + n_sz = darray_neighbour_size_get(&neighbourhood->neighbours); + OK2(darray_neighbour_resize(&neighbourhood->neighbours, 1 + n_sz)); + info = darray_neighbour_data_get(&neighbourhood->neighbours) + n_sz; + info->trg_id = t; + info->common_edge_rank = ee; + } + } /* No barrier here. */ + + /* Loop on collected edges. + * For each edge sort triangle sides by rotation angle + * and connect neighbours. */ + sz = darray_neighbourhood_size_get(&neighbourhood_by_edge); + ASSERT(sz <= EDGE_MAX__); + edge_count = (edge_id_t)sz; + FOR_EACH(e, 0, edge_count) { + double edge[3], common_edge[3], basis[9], norm, max_z, maxz_edge, a; + vrtx_id_t v0, v1, v2; + struct edge_neighbourhood* neighbourhood + = darray_neighbourhood_data_get(&neighbourhood_by_edge) + e; + struct darray_neighbour* neighbour_list = &neighbourhood->neighbours; + side_id_t i, neighbour_count; + sz = darray_neighbour_size_get(neighbour_list); + ASSERT(sz > 0 && sz <= SIDE_MAX__); + neighbour_count = (side_id_t)sz; + ASSERT(neighbour_count); + v0 = neighbourhood->edge.vrtx0; + v1 = neighbourhood->edge.vrtx1; + d3_sub(common_edge, vertices[v1].vec, vertices[v0].vec); + maxz_edge = MMAX(vertices[v0].pos.z, vertices[v1].pos.z); + norm = d3_normalize(common_edge, common_edge); + ASSERT(norm); (void)norm; + d33_basis(basis, common_edge); + d33_inverse(basis, basis); + FOR_EACH(i, 0, neighbour_count) { + struct neighbour_info* neighbour_info + = darray_neighbour_data_get(neighbour_list) + i; + const trg_id_t crt_id = neighbour_info->trg_id; + const unsigned char crt_edge = neighbour_info->common_edge_rank; + const struct triangle_in* trg_in = triangles_in + crt_id; + struct triangle_tmp* neighbour = triangles_tmp + crt_id; + union double3 n; /* Geometrical normal to neighbour triangle */ + const int is_reversed = neighbour->reversed_edge[crt_edge]; + v2 = trg_in->vertice_id[(crt_edge + 2) % 3]; + max_z = MMAX(vertices[v2].pos.z, maxz_edge); + ASSERT(neighbour->max_z <= max_z); + neighbour->max_z = max_z; + /* Compute rotation angle around common edge */ + d3_sub(edge, vertices[v2].vec, vertices[v0].vec); + d33_muld3(edge, basis, edge); + ASSERT(d3_len(edge) && (edge[0] || edge[1])); + neighbour_info->angle = atan2(edge[1], edge[0]); + if(is_reversed) + d3(n.vec, +edge[1], -edge[0], 0); + else + d3(n.vec, -edge[1], +edge[0], 0); + if(neighbour_info->angle < 0) neighbour_info->angle += 2 * PI; + + /* Normal orientation calculation. */ + if(neighbour_info->angle <= PI / 4) { + ASSERT(n.pos.y); + neighbour_info->normal_toward_next_neighbour = (n.pos.y > 0); + } else if(neighbour_info->angle <= 3 * PI / 4) { + ASSERT(n.pos.x); + neighbour_info->normal_toward_next_neighbour = (n.pos.x < 0); + } else if(neighbour_info->angle <= 5 * PI / 4) { + ASSERT(n.pos.y); + neighbour_info->normal_toward_next_neighbour = (n.pos.y < 0); + } else if(neighbour_info->angle <= 7 * PI / 4) { + ASSERT(n.pos.x); + neighbour_info->normal_toward_next_neighbour = (n.pos.x > 0); + } else { + ASSERT(n.pos.y); + neighbour_info->normal_toward_next_neighbour = (n.pos.y > 0); + } + } + /* Sort triangles by rotation angle */ + qsort(darray_neighbour_data_get(neighbour_list), neighbour_count, + sizeof(struct neighbour_info), neighbour_cmp); + /* Link sides. + * Create cycles of sides by neighbourhood around common edge. */ + a = -DBL_MAX; + FOR_EACH(i, 0, neighbour_count) { + /* Neighbourhood info for current pair of triangles */ + const struct neighbour_info* current + = darray_neighbour_cdata_get(neighbour_list) + i; + const struct neighbour_info* ccw_neighbour + = darray_neighbour_cdata_get(neighbour_list) + (i + 1) % neighbour_count; + /* Rank of the edge of interest in triangles */ + const unsigned char crt_edge = current->common_edge_rank; + /* Here ccw refers to the rotation around the common edge + * and has nothing to do with vertices order in triangle definition + * nor Front/Back side convention */ + const unsigned char ccw_edge = ccw_neighbour->common_edge_rank; + /* User id of current triangles */ + const trg_id_t crt_id = current->trg_id; + const trg_id_t ccw_id = ccw_neighbour->trg_id; + /* Facing sides of triangles */ + const int front = ((scn->convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0); + const enum senc3d_side crt_side + = current->normal_toward_next_neighbour == front ? SENC3D_FRONT : SENC3D_BACK; + const enum senc3d_side ccw_side + = ccw_neighbour->normal_toward_next_neighbour == front ? + SENC3D_BACK : SENC3D_FRONT; + /* Index of sides in trgsides */ + const side_id_t crt_side_idx = TRGIDxSIDE_2_TRGSIDE(crt_id, crt_side); + const side_id_t ccw_side_idx = TRGIDxSIDE_2_TRGSIDE(ccw_id, ccw_side); + /* Side ptrs */ + struct trgside* const p_crt_side = trgsides + crt_side_idx; + struct trgside* const p_ccw_side = trgsides + ccw_side_idx; + /* Check that angle is a discriminant property */ + ASSERT(a <= current->angle); /* Is sorted */ + if(a == current->angle) { + /* Two consecutive triangles with same angle! */ + const struct neighbour_info* previous; + trg_id_t prev_id; + ASSERT(i > 0); + previous = darray_neighbour_cdata_get(neighbour_list) + i - 1; + prev_id = previous->trg_id; + log_err(scn->dev, + "%s: found 2 overlying triangles (%u & %u).\n", FUNC_NAME, + (unsigned)crt_id, (unsigned)prev_id); + tmp_res = RES_BAD_OP; + goto tmp_error; + } + a = current->angle; + /* Link sides */ + ASSERT(p_crt_side->facing_side_id[crt_edge] == SIDE_NULL__); + ASSERT(p_ccw_side->facing_side_id[ccw_edge] == SIDE_NULL__); + p_crt_side->facing_side_id[crt_edge] = ccw_side_idx; + p_ccw_side->facing_side_id[ccw_edge] = crt_side_idx; + /* Record media */ + ASSERT(p_crt_side->medium == MEDIUM_NULL__ + || p_crt_side->medium == triangles_in[crt_id].medium[crt_side]); + ASSERT(p_ccw_side->medium == MEDIUM_NULL__ + || p_ccw_side->medium == triangles_in[ccw_id].medium[ccw_side]); + p_crt_side->medium = triangles_in[crt_id].medium[crt_side]; + p_ccw_side->medium = triangles_in[ccw_id].medium[ccw_side]; + ASSERT(p_crt_side->medium == SENC3D_UNSPECIFIED_MEDIUM + || p_crt_side->medium < scn->next_medium_idx); + ASSERT(p_ccw_side->medium == SENC3D_UNSPECIFIED_MEDIUM + || p_ccw_side->medium < scn->next_medium_idx); + /* Detect triangles that could surround a hole: + * - single triangle on (one of) its edge + * - different media on its sides */ + if(neighbour_count == 1 + && p_crt_side->medium != p_ccw_side->medium) +#pragma omp critical + { + struct trg_edge disc; + log_warn(scn->dev, + "%s: found frontier involving triangle %lu.\n", + FUNC_NAME, (unsigned long)crt_id); + disc.vrtx0 = v0; + disc.vrtx1 = v1; + darray_frontier_edge_push_back(frontiers, &disc); + } + } + } +tmp_error: + if(tmp_res != RES_OK) *res = tmp_res; + /* Threads are allowed to return whitout sync. */ + htable_edge_id_release(&edge_ids); + darray_neighbourhood_release(&neighbourhood_by_edge); +} + +static void +build_result + (struct senc3d_scene* scn, + const struct darray_ptr_component_descriptor* connex_components, + const struct darray_triangle_comp* triangles_comp_array, + struct darray_frontier_edge* frontiers, + /* Shared error status. + * We accept to overwrite an error with a different error */ + res_T* res) +{ + /* This function is called from an omp parallel block and executed + * concurrently. */ + struct mem_allocator* alloc; + struct cc_descriptor* const* cc_descriptors; + struct enclosure_data* enclosures; + const struct triangle_in* triangles_in; + struct triangle_enc* triangles_enc; + const struct triangle_comp* triangles_comp; + struct htable_vrtx_id vtable; + int output_normal_in, normals_front, normals_back; + int64_t tt; + int64_t ee; + + ASSERT(scn && connex_components && triangles_comp_array && frontiers && res); + + alloc = scn->dev->allocator; + output_normal_in = (scn->convention & SENC3D_CONVENTION_NORMAL_INSIDE) != 0; + normals_front = (scn->convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0; + normals_back = (scn->convention & SENC3D_CONVENTION_NORMAL_BACK) != 0; + ASSERT(normals_back != normals_front); + ASSERT(output_normal_in + != ((scn->convention & SENC3D_CONVENTION_NORMAL_OUTSIDE) != 0)); + ASSERT(darray_ptr_component_descriptor_size_get(connex_components) + <= COMPONENT_MAX__); + cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components); + enclosures = darray_enclosure_data_get(&scn->analyze.enclosures); + triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); + triangles_comp = darray_triangle_comp_cdata_get(triangles_comp_array); + + #pragma omp single + { + res_T tmp_res = + darray_triangle_enc_resize(&scn->analyze.triangles_enc, scn->ntris); + if(tmp_res != RES_OK) *res = tmp_res; + }/* Implicit barrier here. */ + if(*res != RES_OK) return; + triangles_enc = darray_triangle_enc_data_get(&scn->analyze.triangles_enc); + + /* Build global enclosure information */ + #pragma omp for + for(tt = 0; tt < (int64_t)scn->ntris; tt++) { + trg_id_t t = (trg_id_t)tt; + const component_id_t cf_id = triangles_comp[t].component[SENC3D_FRONT]; + const component_id_t cb_id = triangles_comp[t].component[SENC3D_BACK]; + const struct cc_descriptor* cf = cc_descriptors[cf_id]; + const struct cc_descriptor* cb = cc_descriptors[cb_id]; + const enclosure_id_t ef_id = cf->enclosure_id; + const enclosure_id_t eb_id = cb->enclosure_id; + ASSERT(triangles_enc[t].enclosure[SENC3D_FRONT] == ENCLOSURE_NULL__); + triangles_enc[t].enclosure[SENC3D_FRONT] = ef_id; + ASSERT(triangles_enc[t].enclosure[SENC3D_BACK] == ENCLOSURE_NULL__); + triangles_enc[t].enclosure[SENC3D_BACK] = eb_id; + } + /* Implicit barrier here */ + + /* Resize/push operations on enclosure's fields are valid in the + * openmp block as a given enclosure is processed by a single thread */ + htable_vrtx_id_init(alloc, &vtable); + + ASSERT(scn->analyze.enclosures_count <= ENCLOSURE_MAX__); + #pragma omp for schedule(dynamic) nowait + for(ee = 0; ee < (int64_t)scn->analyze.enclosures_count; ee++) { + const enclosure_id_t e = (enclosure_id_t)ee; + struct enclosure_data* enc = enclosures + e; + trg_id_t fst_idx = 0; + trg_id_t sgd_idx = enc->side_count; + trg_id_t t; + medium_id_t m; + res_T tmp_res = RES_OK; + ASSERT(enc->first_component + < darray_ptr_component_descriptor_size_get(connex_components)); + ASSERT(cc_descriptors[enc->first_component]->cc_id + == enc->first_component); + + if(*res != RES_OK) continue; + ASSERT(e <= UINT_MAX); + enc->header.enclosure_id = (unsigned)e; /* Back to API type */ + ASSERT(cc_descriptors[enc->first_component]->enclosure_id + == enc->header.enclosure_id); + enc->header.is_infinite = (e == 0); + + ASSERT(darray_uchar_size_get(&enc->tmp_enclosed_media) <= UINT_MAX); + ASSERT(enc->header.enclosed_media_count < 1 + scn->next_medium_idx); + OK2(bool_array_of_media_to_darray_media + (&enc->enclosed_media, &enc->tmp_enclosed_media, scn->next_medium_idx)); + enc->header.enclosed_media_count + = (unsigned)darray_media_size_get(&enc->enclosed_media); + darray_uchar_purge(&enc->tmp_enclosed_media); + + /* Add this enclosure in relevant by-medium lists */ + FOR_EACH(m, 0, enc->header.enclosed_media_count) { + medium_id_t medium = darray_media_cdata_get(&enc->enclosed_media)[m]; + unsigned m_idx = (medium == SENC3D_UNSPECIFIED_MEDIUM) ? 0 : medium + 1; + struct darray_enc_id* enc_ids_array_by_medium; + ASSERT(medium == SENC3D_UNSPECIFIED_MEDIUM || medium < scn->next_medium_idx); + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + enc_ids_array_by_medium = + darray_enc_ids_array_data_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; + #pragma omp critical + { + tmp_res = darray_enc_id_push_back(enc_ids_array_by_medium, &e); + } + if(tmp_res != RES_OK) { + *res = tmp_res; + break; + } + } + if(*res != RES_OK) continue; + + /* Build side and vertex lists. */ + OK2(darray_sides_enc_resize(&enc->sides, enc->side_count)); + /* Size is just a int */ + OK2(darray_vrtx_id_reserve(&enc->vertices, + (size_t)(enc->side_count * 0.6))); + /* New vertex numbering scheme local to the enclosure */ + htable_vrtx_id_clear(&vtable); + ASSERT(scn->ntris == darray_triangle_in_size_get(&scn->triangles_in)); + /* Put at the end the back-faces of triangles that also have their + * front-face in the list. */ + for(t = TRGSIDE_2_TRG(enc->side_range.first); + t <= TRGSIDE_2_TRG(enc->side_range.last); + t++) + { + const struct triangle_in* trg_in = triangles_in + t; + struct side_enc* side_enc; + unsigned vertice_id[3]; + int i; + if(triangles_enc[t].enclosure[SENC3D_FRONT] != e + && triangles_enc[t].enclosure[SENC3D_BACK] != e) + continue; + ++enc->header.unique_primitives_count; + + FOR_EACH(i, 0, 3) { + vrtx_id_t* p_id = htable_vrtx_id_find(&vtable, trg_in->vertice_id + i); + if(p_id) { + vertice_id[i] = *p_id; /* Known vertex */ + } else { + /* Create new association */ + size_t tmp = htable_vrtx_id_size_get(&vtable); + ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices)); + ASSERT(tmp < VRTX_MAX__); + vertice_id[i] = (vrtx_id_t)tmp; + OK2(htable_vrtx_id_set(&vtable, trg_in->vertice_id + i, + vertice_id + i)); + OK2(darray_vrtx_id_push_back(&enc->vertices, trg_in->vertice_id + i)); + ++enc->header.vertices_count; + } + } + ASSERT(triangles_enc[t].enclosure[SENC3D_FRONT] == e + || triangles_enc[t].enclosure[SENC3D_BACK] == e); + if(triangles_enc[t].enclosure[SENC3D_FRONT] == e) { + /* Front side of the original triangle is member of the enclosure */ + int input_normal_in = normals_front; + int revert_triangle = (input_normal_in != output_normal_in); + ++enc->header.primitives_count; + side_enc = darray_sides_enc_data_get(&enc->sides) + fst_idx++; + FOR_EACH(i, 0, 3) { + int ii = revert_triangle ? 2 - i : i; + side_enc->vertice_id[i] = vertice_id[ii]; + } + side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC3D_FRONT); + } + if(triangles_enc[t].enclosure[SENC3D_BACK] == e) { + /* Back side of the original triangle is member of the enclosure */ + int input_normal_in = normals_back; + int revert_triangle = (input_normal_in != output_normal_in); + ++enc->header.primitives_count; + /* If both sides are in the enclosure, put the second side at the end */ + side_enc = darray_sides_enc_data_get(&enc->sides) + + ((triangles_enc[t].enclosure[SENC3D_FRONT] == e) ? --sgd_idx : fst_idx++); + FOR_EACH(i, 0, 3) { + int ii = revert_triangle ? 2 - i : i; + side_enc->vertice_id[i] = vertice_id[ii]; + } + side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC3D_BACK); + } + if(fst_idx == sgd_idx) break; + } + continue; + tmp_error: + ASSERT(tmp_res != RES_OK); + *res = tmp_res; + } /* No barrier here */ + htable_vrtx_id_release(&vtable); + /* The first thread here copies frontiers into descriptor */ +#pragma omp single nowait + darray_frontier_edge_copy_and_clear(&scn->analyze.frontiers, frontiers); + /* No barrier here */ +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +scene_analyze + (struct senc3d_scene* scn) +{ + /* By triangle tmp data */ + struct darray_triangle_tmp triangles_tmp; + char triangles_tmp_initialized = 0; + /* Array of connex components. + * They are refered to by arrays of ids. */ + struct darray_ptr_component_descriptor connex_components; + char connex_components_initialized = 0; + /* Array of frontiers edges */ + struct darray_frontier_edge frontiers; + char frontiers_initialized = 0; + /* Store by-triangle components */ + struct darray_triangle_comp triangles_comp; + char triangles_comp_initialized = 0; + /* Array of triangle sides. */ + struct trgside* trgsides = NULL; + struct s3d_scene_view* s3d_view = NULL; + /* Atomic counters to share beetwen threads */ + ATOMIC component_count = 0; + ATOMIC next_enclosure_id = 1; + res_T res = RES_OK; + res_T res2 = RES_OK; + + if(!scn) return RES_BAD_ARG; + + if(!scn->ntris) goto exit; + + darray_triangle_tmp_init(scn->dev->allocator, &triangles_tmp); + triangles_tmp_initialized = 1; + darray_frontier_edge_init(scn->dev->allocator, &frontiers); + frontiers_initialized = 1; + + OK(darray_triangle_tmp_resize(&triangles_tmp, scn->ntris)); + trgsides + = MEM_CALLOC(scn->dev->allocator, 2 * scn->ntris, sizeof(struct trgside)); + if(!trgsides) { + res = RES_MEM_ERR; + goto error; + } +#ifndef NDEBUG + else { + /* Initialise trgsides to allow assert code */ + size_t i; + FOR_EACH(i, 0, 2 * scn->ntris) + init_trgside(scn->dev->allocator, trgsides + i); + } +#endif + + /* The end of the analyze is multithreaded */ + ASSERT(scn->dev->nthreads > 0); + #pragma omp parallel num_threads(scn->dev->nthreads) + { + /* Step 1: build neighbourhoods */ + collect_and_link_neighbours(scn, trgsides, &triangles_tmp, &frontiers, + &res); + /* No barrier at the end of step 1: data used in step 1 cannot be + * released / data produced by step 1 cannot be used + * until next sync point */ + + /* The first thread here allocates some data. + * Barrier needed at the end to ensure data created before any use. */ + #pragma omp single + { + res_T tmp_res = RES_OK; + darray_ptr_component_descriptor_init(scn->dev->allocator, + &connex_components); + connex_components_initialized = 1; + /* Just a hint; to limit contention */ + OK2(darray_ptr_component_descriptor_reserve(&connex_components, + 2 + 2 * scn->next_medium_idx)); + darray_triangle_comp_init(scn->dev->allocator, &triangles_comp); + triangles_comp_initialized = 1; + OK2(darray_triangle_comp_resize(&triangles_comp, scn->ntris)); + tmp_error: + if(tmp_res != RES_OK) res2 = tmp_res; + } + /* Implicit barrier here: constraints on step 1 data are now met */ + + if(res != RES_OK || res2 != RES_OK) { + #pragma omp single nowait + { + if(res != RES_OK) { + log_err(scn->dev, + "%s: could not build neighbourhoods from scene.\n", FUNC_NAME); + } else { + res = res2; + } + } + goto error_; + } + + /* Step 2: extract triangle connex components */ + extract_connex_components(scn, trgsides, &connex_components, + &triangles_tmp, &triangles_comp, &s3d_view, &component_count, &res); + /* No barrier at the end of step 2: data used in step 2 cannot be + * released / data produced by step 2 cannot be used + * until next sync point */ + + #pragma omp barrier + /* Constraints on step 2 data are now met */ + + if(res != RES_OK) { + #pragma omp single nowait + { + log_err(scn->dev, + "%s: could not extract connex components from scene.\n", FUNC_NAME); + } /* No barrier here */ + goto error_; + } + + /* One thread releases some data before going to step 3, + * the others go to step 3 without sync */ + #pragma omp single nowait + { + darray_triangle_tmp_release(&triangles_tmp); + triangles_tmp_initialized = 0; + } /* No barrier here */ + + /* Step 3: group components */ + group_connex_components(scn, trgsides, &triangles_comp, + &connex_components, s3d_view, &next_enclosure_id, &res); + /* Barrier at the end of step 3: data used in step 3 can be released / + * data produced by step 3 can be used */ + + if(res != RES_OK) { + #pragma omp single nowait + { + log_err(scn->dev, + "%s: could not group connex components from scene.\n", FUNC_NAME); + } + goto error_; + } + + /* One thread releases some data before going to step 4, + * the others go to step 4 without sync */ + #pragma omp single nowait + { + if(s3d_view) S3D(scene_view_ref_put(s3d_view)); + s3d_view = NULL; + } /* No barrier here */ + + /* Step 4: Build result */ + build_result(scn, &connex_components, &triangles_comp, &frontiers, &res); + /* No barrier at the end of step 4: data used in step 4 cannot be + * released / data produced by step 4 cannot be used + * until next sync point */ + + #pragma omp barrier + /* Constraints on step 4 data are now met */ + + if(res != RES_OK) { + #pragma omp single nowait + { + log_err(scn->dev, "%s: could not build result.\n", FUNC_NAME); + } + goto error_; + } + + /* Some threads release data */ + #pragma omp sections nowait + { + #pragma omp section + { + custom_darray_ptr_component_descriptor_release(&connex_components); + connex_components_initialized = 0; + } + #pragma omp section + { + darray_triangle_comp_release(&triangles_comp); + triangles_comp_initialized = 0; + } + } /* No barrier here */ + +error_: + ; + } /* Implicit barrier here */ + + if(res != RES_OK) goto error; +exit: + if(connex_components_initialized) + custom_darray_ptr_component_descriptor_release(&connex_components); + if(s3d_view) S3D(scene_view_ref_put(s3d_view)); + if(triangles_tmp_initialized) darray_triangle_tmp_release(&triangles_tmp); + if(triangles_comp_initialized) darray_triangle_comp_release(&triangles_comp); + if(frontiers_initialized) + darray_frontier_edge_release(&frontiers); + if(trgsides) MEM_RM(scn->dev->allocator, trgsides); + + return res; +error: + goto exit; +} diff --git a/src/senc3d_scene_analyze_c.h b/src/senc3d_scene_analyze_c.h @@ -0,0 +1,201 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_SCNENE_ANALYZE_C_H +#define SENC3D_SCNENE_ANALYZE_C_H + +#include "SENC3D_internal_types.h" +#include "senc3d.h" + +#include <rsys/mem_allocator.h> +#include <rsys/hash_table.h> +#include <rsys/double3.h> + +struct senc3d_scene; + +static FINLINE void +init_trgside(struct mem_allocator* alloc, struct trgside* data) +{ + int i; + ASSERT(data); (void)alloc; + FOR_EACH(i, 0, 3) data->facing_side_id[i] = SIDE_NULL__; + data->medium = MEDIUM_NULL__; +} + +#define DARRAY_NAME side_id +#define DARRAY_DATA side_id_t +#include <rsys/dynamic_array.h> + +/* Descriptors for connex component. + * Define lists of trg sides starting from a given head. + * Also keeps the maximum z info of the component + * and the list of media found */ +struct cc_descriptor { + /* Does this component is an outer border of an enclosure or an inner one? */ + char is_outer_border; + vrtx_id_t max_z_vrtx_id; /* id of the vrtx with max z value */ + side_id_t side_count; + /* Used when grouping components to form enclosures */ + component_id_t cc_id; + component_id_t cc_group_root; + enclosure_id_t enclosure_id; + /* Range of sides member of this component */ + struct side_range side_range; + /* Media used by this component */ + unsigned char* media; +}; +extern const struct cc_descriptor CC_DESCRIPTOR_NULL; + +static FINLINE void +cc_descriptor_init + (struct mem_allocator* alloc, + struct cc_descriptor* data) +{ + ASSERT(data); + (void)alloc; + *data = CC_DESCRIPTOR_NULL; +} + +static FINLINE void +ptr_component_descriptor_init + (struct mem_allocator* alloc, + struct cc_descriptor** data) +{ + (void)alloc; + ASSERT(data); + *data = NULL; +} + +#define DARRAY_NAME ptr_component_descriptor +#define DARRAY_DATA struct cc_descriptor* +#define DARRAY_FUNCTOR_INIT ptr_component_descriptor_init +#include <rsys/dynamic_array.h> + +/* Need allocator to free array elts: cannot rely on standard + * darray release stuff */ +static FINLINE void +custom_darray_ptr_component_descriptor_release + (struct darray_ptr_component_descriptor* array) +{ + size_t c, cc_count; + struct cc_descriptor** components; + if(!array) return; + cc_count = darray_ptr_component_descriptor_size_get(array); + components = darray_ptr_component_descriptor_data_get(array); + FOR_EACH(c, 0, cc_count) { + if(!components[c]) continue; + MEM_RM(array->allocator, components[c]->media); + MEM_RM(array->allocator, components[c]); + } + darray_ptr_component_descriptor_release(array); +} + +/* Triangle information. + * Depending on lifespan, information is kept in different places: + * - triangle_in for user provided information (kept in scene) + * - triangle_tmp for tmp information (kept until triangle_comp is ready) + * - triangle_comp for information describing components (kept until + * triangle_enc is ready) + * - triangle_enc for information describing enclosures (kept in + * struct descriptor). */ +struct triangle_tmp { + /* Are the edges of the triangle defined in the same order than + * the edges they are linked to? */ + unsigned char reversed_edge[3]; + double max_z; +}; + +#ifndef NDEBUG +static FINLINE void +triangle_tmp_init(struct mem_allocator* alloc, struct triangle_tmp* trg) { + int i; + (void)alloc; + ASSERT(trg); + FOR_EACH(i, 0, 3) trg->reversed_edge[i] = UCHAR_MAX; + trg->max_z = -DBL_MAX; +} +#define DARRAY_FUNCTOR_INIT triangle_tmp_init +#endif + +#define DARRAY_NAME triangle_tmp +#define DARRAY_DATA struct triangle_tmp +#include <rsys/dynamic_array.h> + +#define HTABLE_NAME edge_id +#define HTABLE_KEY struct trg_edge +#define HTABLE_DATA edge_id_t +#define HTABLE_KEY_FUNCTOR_EQ edge_eq +#include <rsys/hash_table.h> + +struct neighbour_info { + double angle; + trg_id_t trg_id; + /* Rank of the edge in the triangle (in [0 2]) */ + unsigned char common_edge_rank; + /* Does the geometrical normal point towards the next neighbour + * (if not, it points towards the previous one)? */ + unsigned char normal_toward_next_neighbour; +}; +#define DARRAY_NAME neighbour +#define DARRAY_DATA struct neighbour_info +#include <rsys/dynamic_array.h> + +struct edge_neighbourhood { + struct trg_edge edge; + struct darray_neighbour neighbours; +}; +static void +neighbourhood_init + (struct mem_allocator* alloc, + struct edge_neighbourhood* n) +{ + ASSERT(n); + darray_neighbour_init(alloc, &n->neighbours); +} +static res_T +neighbourhood_copy + (struct edge_neighbourhood* dst, + const struct edge_neighbourhood* src) +{ + ASSERT(src && dst); + dst->edge = src->edge; + return darray_neighbour_copy(&dst->neighbours, &src->neighbours); +} +static void +neighbourhood_release(struct edge_neighbourhood* n) { + ASSERT(n); + darray_neighbour_release(&n->neighbours); +} +static res_T +neighbourhood_copy_and_release + (struct edge_neighbourhood* dst, + struct edge_neighbourhood* src) +{ + ASSERT(src && dst); + dst->edge = src->edge; + return darray_neighbour_copy_and_release(&dst->neighbours, &src->neighbours); +} +#define DARRAY_NAME neighbourhood +#define DARRAY_DATA struct edge_neighbourhood +#define DARRAY_FUNCTOR_INIT neighbourhood_init +#define DARRAY_FUNCTOR_COPY neighbourhood_copy +#define DARRAY_FUNCTOR_RELEASE neighbourhood_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE neighbourhood_copy_and_release +#include <rsys/dynamic_array.h> + +extern LOCAL_SYM res_T +scene_analyze(struct senc3d_scene* scene); + +#endif /* SENC3D_SCNENE_ANALYZE_C_H */ diff --git a/src/senc3d_scene_c.h b/src/senc3d_scene_c.h @@ -0,0 +1,302 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_SCENE_C_H +#define SENC3D_SCENE_C_H + +#include "SENC3D_internal_types.h" +#include "senc3d_enclosure_data.h" +#include "SENC3D_side_range.h" +#include "senc3d.h" + +#include <rsys/ref_count.h> +#include <rsys/dynamic_array.h> +#include <rsys/hash_table.h> + +struct mem_allocator; +struct senc3d_scene; + +struct triangle_comp { + /* The connex component in which each side is. */ + component_id_t component[2]; +}; + +static void +triangle_comp_init(struct mem_allocator* alloc, struct triangle_comp* trg) { + int i; + (void)alloc; + ASSERT(trg); + FOR_EACH(i, 0, 2) trg->component[i] = COMPONENT_NULL__; +} + +#define DARRAY_NAME triangle_comp +#define DARRAY_DATA struct triangle_comp +#define DARRAY_FUNCTOR_INIT triangle_comp_init +#include <rsys/dynamic_array.h> + +struct triangle_enc { + /* The enclosure in which each side is. */ + enclosure_id_t enclosure[2]; +}; + +#ifndef NDEBUG +static void +triangle_enc_init(struct mem_allocator* alloc, struct triangle_enc* trg) { + int i; + (void)alloc; + ASSERT(trg); + FOR_EACH(i, 0, 2) trg->enclosure[i] = ENCLOSURE_NULL__; +} +#define DARRAY_FUNCTOR_INIT triangle_enc_init +#endif + +#define DARRAY_NAME triangle_enc +#define DARRAY_DATA struct triangle_enc +#include <rsys/dynamic_array.h> + +/* Triangle edge struct and basic functions */ +struct trg_edge { + vrtx_id_t vrtx0, vrtx1; +}; + +static FINLINE int +edge_ok(const struct trg_edge* edge) { + return(edge + && edge->vrtx0 <= VRTX_MAX__ + && edge->vrtx1 <= VRTX_MAX__ + && edge->vrtx0 < edge->vrtx1); +} + +static FINLINE void +set_edge + (const vrtx_id_t vrtx0, + const vrtx_id_t vrtx1, + struct trg_edge* edge, + unsigned char* reversed) +{ + ASSERT(edge && reversed && vrtx0 != vrtx1); + ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */ + if(vrtx0 < vrtx1) { + edge->vrtx0 = vrtx0; + edge->vrtx1 = vrtx1; + *reversed = 0; /* Non reversed edge */ + } else { + edge->vrtx0 = vrtx1; + edge->vrtx1 = vrtx0; + *reversed = 1; /* Reversed edge */ + } + ASSERT(edge_ok(edge)); +} + +static FINLINE int +edge_eq(const struct trg_edge* e1, const struct trg_edge* e2) +{ + ASSERT(edge_ok(e1) && edge_ok(e2)); + return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1; +} + +/* Information kept during the building of side groups. */ +struct trgside { + /* Rank of the trgside facing this trgside through its edges */ + side_id_t facing_side_id[3]; + /* Id of this trgside's medium */ + medium_id_t medium; + + /* Implicit information that we don't need to store: + * - triangle_id + * - side + * This is due to the memory layout of the elt darray: + * front(trg_0), back(trg_0), front(trg_1), back(trg_1), ... */ +}; + +#define DARRAY_NAME frontier_edge +#define DARRAY_DATA struct trg_edge +#include <rsys/dynamic_array.h> + +union double3 { + struct { + double x, y, z; + } pos; + double vec[3]; +}; +#define DARRAY_NAME position +#define DARRAY_DATA union double3 +#include <rsys/dynamic_array.h> +/* Triangle information. + * Depending on lifespan, information is kept in different places: + * - triangle_in for user provided information (kept in scene) + * - triangle_comp for information describing components (kept in struct descriptor) + * - triangle_tmp for tmp information (kept until triangle_comp is ready) */ +struct triangle_in { + /* Ids of the triangle's vertices */ + vrtx_id_t vertice_id[3]; + /* Ids of this triangle's media */ + medium_id_t medium[2]; +}; + +static FINLINE void +triangle_in_init(struct mem_allocator* alloc, struct triangle_in* trg) { + int i; + (void)alloc; + ASSERT(trg); + FOR_EACH(i, 0, 3) trg->vertice_id[i] = VRTX_NULL__; + FOR_EACH(i, 0, 2) trg->medium[i] = SENC3D_UNSPECIFIED_MEDIUM; +} + +#define DARRAY_NAME triangle_in +#define DARRAY_DATA struct triangle_in +#define DARRAY_FUNCTOR_INIT triangle_in_init +#include <rsys/dynamic_array.h> + +static FINLINE void +triangle_in_flip(struct triangle_in* trg) { + vrtx_id_t v; + medium_id_t m; + ASSERT(trg); + v = trg->vertice_id[1]; + trg->vertice_id[1] = trg->vertice_id[2]; + trg->vertice_id[2] = v; + m = trg->medium[0]; + trg->medium[0] = trg->medium[1]; + trg->medium[1] = m; +} + +static FINLINE int +vrtx_eq(const union double3* v1, const union double3* v2) +{ + ASSERT(v1 && v2); + return (v1->pos.x == v2->pos.x + && v1->pos.y == v2->pos.y + && v1->pos.z == v2->pos.z); +} + +#define HTABLE_NAME vrtx +#define HTABLE_KEY union double3 +#define HTABLE_DATA vrtx_id_t +#define HTABLE_KEY_FUNCTOR_EQ vrtx_eq +#include <rsys/hash_table.h> + +union vrtx_id3 { + struct { + vrtx_id_t v0, v1, v2; + } pos; + vrtx_id_t vec[3]; +}; + +static FINLINE char /* Return 1 if reversed */ +trg_make_key(union vrtx_id3* k, const vrtx_id_t t[3]) +{ + ASSERT(t); + ASSERT(t[0] != t[1] && t[0] != t[2] && t[1] != t[2]); + if(t[0] < t[2]) { + if(t[0] < t[1]) { + k->vec[0] = t[0]; + if(t[1] < t[2]) { + k->vec[1] = t[1]; + k->vec[2] = t[2]; + return 0; + } else { + k->vec[1] = t[2]; + k->vec[2] = t[1]; + return 1; + } + } else { + k->vec[0] = t[1]; + if(t[0] < t[2]) { + k->vec[1] = t[0]; + k->vec[2] = t[2]; + return 1; + } else { + k->vec[1] = t[2]; + k->vec[2] = t[0]; + return 0; + } + } + } else if(t[2] < t[1]) { + k->vec[0] = t[2]; + if(t[0] < t[1]) { + k->vec[1] = t[0]; + k->vec[2] = t[1]; + return 0; + } else { + k->vec[1] = t[1]; + k->vec[2] = t[0]; + return 1; + } + } else { + k->vec[0] = t[1]; + if(t[0] < t[2]) { + k->vec[1] = t[0]; + k->vec[2] = t[2]; + return 1; + } else { + k->vec[1] = t[2]; + k->vec[2] = t[0]; + return 0; + } + } +} + +static FINLINE int +trg_key_eq(const union vrtx_id3* k1, const union vrtx_id3* k2) +{ + ASSERT(k1 && k2); + ASSERT(k1->vec[0] < k1->vec[1] && k1->vec[1] < k1->vec[2]); + ASSERT(k2->vec[0] < k2->vec[1] && k2->vec[1] < k2->vec[2]); + return (k1->vec[0] == k2->vec[0]) + && (k1->vec[1] == k2->vec[1]) + && (k1->vec[2] == k2->vec[2]); +} + +#define HTABLE_NAME trg +#define HTABLE_KEY union vrtx_id3 +#define HTABLE_DATA trg_id_t +#define HTABLE_KEY_FUNCTOR_EQ trg_key_eq +#include <rsys/hash_table.h> + +struct descriptor { + enclosure_id_t enclosures_count; + /* Store by-triangle enclosures */ + struct darray_triangle_enc triangles_enc; + /* Store enclosures */ + struct darray_enclosure enclosures; + struct darray_enc_ids_array enc_ids_array_by_medium; + /* Store frontiers */ + struct darray_frontier_edge frontiers; +}; + +struct senc3d_scene { + /* Front / Back sides convention */ + int convention; + /* Triangle information as given by user */ + struct darray_triangle_in triangles_in; + /* Vertex information as given by user */ + struct darray_position vertices; + + /* Keep sizes */ + trg_id_t ntris; /* Trg count */ + vrtx_id_t nverts; /* Vrtx count */ + medium_id_t next_medium_idx; + /* media_use 0 is for SENC3D_UNSPECIFIED_MEDIUM, n+1 is for n */ + struct darray_side_range media_use; + + /* The descriptor of the analyze */ + struct descriptor analyze; + + ref_T ref; + struct senc3d_device* dev; +}; + +#endif /* SENC3D_SCENE_C_H */ diff --git a/src/senc3d_side_range.h b/src/senc3d_side_range.h @@ -0,0 +1,44 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_SIDE_RANGE_H +#define SENC3D_SIDE_RANGE_H + +#include "SENC3D_internal_types.h" + +#include <rsys/dynamic_array.h> + +struct mem_allocator; + +struct side_range { + side_id_t first, last; +}; + +static FINLINE void +side_range_init(struct mem_allocator* alloc, struct side_range* data) +{ + ASSERT(data); + (void)alloc; + data->first = SIDE_NULL__; + data->last = 0; +} + +#define DARRAY_NAME side_range +#define DARRAY_DATA struct side_range +#define DARRAY_FUNCTOR_INIT side_range_init +#include <rsys/dynamic_array.h> + + +#endif /* SENC3D_SCENE_C_H */ diff --git a/src/sencX3.h b/src/sencX3.h @@ -1,423 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_X_3D_H -#define SENC_X_3D_H - -#include <star/senc.h> -#include <rsys/rsys.h> - -/* This file can be used in conjunction with sencX2.h from the the - * star-enclosures-2D library to write code for both 2D and 3D geometries using - * the following pattern: - * - * #if (DIM==2) - * #include <star/sencX2.h> - * #elif (DIM==3) - * #include <star/sencX3.h> - * #else - * #error DIM should be defined; possible values are 2 and 3 - * #endif - * - * Then use the sencX_... types and functions in your code. - */ - -/* Forward declaration of external opaque data types */ -struct logger; -struct mem_allocator; - -/* Forward declaration of StarEnclosures opaque data types. These data types - * are ref counted. Once created with the appropriated `senc_<TYPE>_create' - * function, the caller implicitly owns the created data, i.e. its reference - * counter is set to 1. The senc_<TYPE>_ref_<get|put> functions get or release - * 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. */ -typedef struct senc_device sencX_device; -typedef struct senc_scene sencX_scene; -typedef struct senc_enclosure sencX_enclosure; - -/******************************************************************************* - * The dimension of the geometry used in the library. - ******************************************************************************/ -#define SENCX_GEOMETRY_DIMENSION SENC_GEOMETRY_DIMENSION - -/* A type to discriminate triangle sides */ -enum sencXd_side { - SENCXD_FRONT = SENC_FRONT, - SENCXD_BACK = SENC_BACK -}; - -/* Enclosure header type */ -typedef struct senc_enclosure_header sencXd_enclosure_header; - -/* We consider the geometrical normal Ng to a triangle V0 V1 V2 - * that verifies "(V0, V0V1, V0V2, Ng) is a direct system" - * (right-handed system). - * - * The user can set the convention used to determine which side of - * a triangle is to be considered front/back by using the flags : - * SENC_CONVENTION_NORMAL_FRONT => Ng points toward the front side, - * SENC_CONVENTION_NORMAL_BACK => Ng points toward the back side. - * - * Additionaly the user can set the convention used to output enclosures - * so that Ng points toward the enclosure or on the opposite direction - * (for a closed enclosure Ng points toward the inside or toward the outside) - * by using the flags : - * SENC_CONVENTION_NORMAL_INSIDE => Ng points toward the enclosure, - * SENC_CONVENTION_NORMAL_OUTSIDE => Ng points to the opposite of the enclosure. - * - * Note that normals in output data can be opposite to normals in input data - * (vertices are then given in reverse order). - * - * Also note that both sides of a triangle can be part of the same enclosure; - * in this case the 2 sides will be given with opposite Ng (meaning they - * will be given with opposite vertices order). - */ -enum sencXd_convention { - /* - * Convention regarding FRONT/BACK sides in input data - */ - - /* Geometrical normals point toward the front side */ - SENCXD_CONVENTION_NORMAL_FRONT = SENC_CONVENTION_NORMAL_FRONT, - /* Geometrical normals point toward the back side */ - SENCXD_CONVENTION_NORMAL_BACK = SENC_CONVENTION_NORMAL_BACK, - - /* - * Convention regarding geometrical normals in output data - */ - - /* Geometrical normals point toward the enclosure */ - SENCXD_CONVENTION_NORMAL_INSIDE = SENC_CONVENTION_NORMAL_INSIDE, - /* Geometrical normals point to the opposite of the enclosure */ - SENCXD_CONVENTION_NORMAL_OUTSIDE = SENC_CONVENTION_NORMAL_OUTSIDE -}; - -/****************************************************************************** - * The value that should be used to let media unspecified. - *****************************************************************************/ -#define SENCXD_UNSPECIFIED_MEDIUM SENC_UNSPECIFIED_MEDIUM - -BEGIN_DECLS - -/****************************************************************************** - * StarEnclosures device. It is an handle toward the StarEnc library. - * It manages the lib resources. - * If provided, the allocator has to be suitable for parallel high frequency - * allocations. As a consequence, a rsys proxy allocator should be avoided. - *****************************************************************************/ -static FINLINE res_T -sencXd_device_create - (struct logger* logger, /* May be NULL <=> use default logger */ - struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ - const unsigned nthreads_hint, - const int verbose, - struct senc_device** device) -{ - return senc_device_create(logger, allocator, nthreads_hint, verbose, device); -} - -static FINLINE res_T -sencXd_device_ref_get - (struct senc_device* device) -{ - return senc_device_ref_get(device); -} - -static FINLINE res_T -sencXd_device_ref_put - (struct senc_device* device) -{ - return senc_device_ref_put(device); -} - -/****************************************************************************** - * StarEnclosures scene. A scene is a collection of triangles. Each triangle is - * defined with a medium on each side. - *****************************************************************************/ -/* Creates a scene from some vertices and triangles. - * Neither vertices nor triangles can include duplicates. - * Triangles cannot be degenerated. */ -static FINLINE res_T -sencXd_scene_create - (struct senc_device* device, - const int convention, - /* Number of triangles */ - const unsigned triangles_count, - /* User function that provides vertices ids for triangles */ - void(*get_indices)( - const unsigned itri, - unsigned ids[SENCX_GEOMETRY_DIMENSION], - void* context), - /* User function that provides media ids for triangles */ - void(*get_media) /* Can be NULL <=> SENC_UNSPECIFIED_MEDIUM medium used */ - (const unsigned itri, unsigned med[2], void* context), - /* Number of vertices */ - const unsigned vertices_count, - /* User function that provides coordinates for vertices */ - void(*get_position)( - const unsigned ivert, - double pos[SENCX_GEOMETRY_DIMENSION], - void* context), - /* Context provided to user callbacks; can be NULL */ - void* context, - /* The created scene */ - struct senc_scene** scene) -{ - return senc_scene_create(device, convention, triangles_count, get_indices, - get_media, vertices_count, get_position, context, scene); -} - -/* Returns the convention flags in use with the scene. */ -static FINLINE res_T -sencXd_scene_get_convention - (const struct senc_scene* scene, - int* convention) -{ - return senc_scene_get_convention(scene, convention); -} - -/* Returns the number of triangles in the scene. */ -static FINLINE res_T -sencXd_scene_get_primitives_count - (const struct senc_scene* scene, - unsigned* count) -{ - return senc_enclosure_get_triangles_count(scene, count); -} - -/* Returns the itri_th triangle vertices' indices. */ -static FINLINE res_T -sencXd_scene_get_primitive - (const struct senc_scene* scene, - const unsigned itri, - unsigned indices[SENCX_GEOMETRY_DIMENSION]) -{ - return senc_enclosure_get_triangle(scene, itri, indices); -} - -/* Returns the media for the itri_th triangle. */ -static FINLINE res_T -sencXd_scene_get_primitive_media - (const struct senc_scene* scene, - const unsigned itri, - unsigned media[2]) -{ - return senc_enclosure_get_triangle_media(scene, itri, media); -} - -/* Returns the number of vertices in the scene. */ -static FINLINE res_T -sencXd_scene_get_vertices_count - (const struct senc_scene* scene, - unsigned* count) -{ - return senc_scene_get_vertices_count(scene, count); -} - -/* Returns the coordinates of the ivert_th vertex. */ -static FINLINE res_T -sencXd_scene_get_vertex - (const struct senc_scene* scene, - const unsigned ivert, - double coord[SENCX_GEOMETRY_DIMENSION]) -{ - return senc_scene_get_vertex(scene, ivert, coord); -} - -/* Returns the greater medium id found in added geometry. In API calls using a - * medium, any value in the [0 max_medium_id[ range is valid. However there can - * be unused ids (no geometry refered to this medium id). */ -static FINLINE res_T -sencXd_scene_get_max_medium - (const struct senc_scene* scene, - unsigned* max_medium_id) -{ - return senc_scene_get_max_medium(scene, max_medium_id); -} - -/* Returns the number of enclosures. */ -static FINLINE res_T -sencXd_scene_get_enclosure_count - (const struct senc_scene* scene, - unsigned* count) -{ - return senc_scene_get_enclosure_count(scene, count); -} - -/* Returns the number of enclosures that have some geometry refering to the - * imed_th medium or SENC_UNSPECIFIED_MEDIUM. */ -static FINLINE res_T -sencXd_scene_get_enclosure_count_by_medium - (const struct senc_scene* scene, - const unsigned imed, - unsigned* count) -{ - return senc_scene_get_enclosure_count_by_medium(scene, imed, count); -} - -/* Returns the idx_th enclosure. */ -static FINLINE res_T -sencXd_scene_get_enclosure - (struct senc_scene* scene, - const unsigned idx, - struct senc_enclosure** enclosure) -{ - return senc_scene_get_enclosure(scene, idx, enclosure); -} - -/* Returns the idx_th enclosure using the imed_th medium or - * SENC_UNSPECIFIED_MEDIUM. */ -static FINLINE res_T -sencXd_scene_get_enclosure_by_medium - (struct senc_scene* scene, - const unsigned imed, - const unsigned idx, - struct senc_enclosure** enclosure) -{ - return senc_scene_get_enclosure_by_medium(scene, imed, idx, enclosure); -} - -/* Returns the enclosures the itri_th triangle front and back sides are member - * of. */ -static FINLINE res_T -sencXd_scene_get_primitive_enclosures - (const struct senc_scene* scene, - const unsigned itri, - unsigned enclosures[2]) -{ - return senc_scene_get_triangle_enclosures(scene, itri, enclosures); -} - -/* Returns the number of segments that are frontier segments: - * - that have arity 1 (single triangle using the segment) - * - that connect 2 different media */ -static FINLINE res_T -sencXd_scene_get_frontier_elements_count - (const struct senc_scene* scene, - unsigned* count) -{ - return senc_scene_get_frontier_segments_count(scene, count); -} - -/* Returns the iseg_th frontier segment; the returned indices are global vertex - * indices whose coordinates can be retrieved using sencXd_scene_get_vertex. */ -static FINLINE res_T -sencXd_scene_get_frontier_element - (const struct senc_scene* scene, - const unsigned iseg, - unsigned vrtx_id[SENCX_GEOMETRY_DIMENSION-1]) -{ - return senc_scene_get_frontier_segment(scene, iseg, vrtx_id); -} - -static FINLINE res_T -sencXd_scene_ref_get - (struct senc_scene* scene) -{ - return senc_scene_ref_get(scene); -} - -static FINLINE res_T -sencXd_scene_ref_put - (struct senc_scene* scene) -{ - return senc_scene_ref_put(scene); -} - -/******************************************************************************* - * StarEnclosures enclosure. It is an handle toward an enclosure. - * Counts and other information on enclosures are not individually accessible, - * but as a whole through header access. - * An enclosure can list the "same" triangle twice if both sides are in. In this - * case the 2 occurences of the triangle have reversed vertices order and - * unique_triangle_count and triangle_count differ. - * Vertices and triangles numbering schemes are specific to each enclosure: - * the "same" item appearing in 2 different enclosures has no reason to get the - * same index twice or to have the same index in the global numbering scheme. - * By-index API accesses of triangles (or properties) visit unique triangles - * for indices in the [0 unique_triangle_count[ range and back-faces of the - * doubly-included triangles in the [unique_triangle_count triangle_count[ range. - ******************************************************************************/ -/* Returns the header of an enclosure. */ -static FINLINE res_T -sencXd_enclosure_get_header - (const struct senc_enclosure* enclosure, - struct senc_enclosure_header* header) -{ - return senc_enclosure_get_header(enclosure, header); -} - -/* Returns the itri_th triangle of an enclosure. - * Indices are local to the enclosure. */ -static FINLINE res_T -sencXd_enclosure_get_primitive - (const struct senc_enclosure* enclosure, - const unsigned itri, - unsigned indices[SENCX_GEOMETRY_DIMENSION]) -{ - return senc_enclosure_get_triangle(enclosure, itri, indices); -} - -/* Returns the coordinates of the ivert_th vertex of an enclosure. */ -static FINLINE res_T -sencXd_enclosure_get_vertex - (const struct senc_enclosure* enclosure, - const unsigned ivert, - double coord[SENCX_GEOMETRY_DIMENSION]) -{ - return senc_enclosure_get_vertex(enclosure, ivert, coord); -} - -/* Returns the global id of the itri_th triangle of an enclosure - * and the involved side. */ -static FINLINE res_T -sencXd_enclosure_get_primitive_id - (const struct senc_enclosure* enclosure, - const unsigned itri, - unsigned* gid, - enum senc_side* side) -{ - return senc_enclosure_get_triangle_id(enclosure, itri, gid, side); -} - -/* Returns the id of the imed_th medium of an enclosure. */ -static FINLINE res_T -sencXd_enclosure_get_medium - (const struct senc_enclosure* enclosure, - const unsigned imed, - unsigned* medium) -{ - return senc_enclosure_get_medium(enclosure, imed, medium); -} - -static FINLINE res_T -sencXd_enclosure_ref_get - (struct senc_enclosure* enclosure) -{ - return senc_enclosure_ref_get(enclosure); -} - -static FINLINE res_T -sencXd_enclosure_ref_put - (struct senc_enclosure* enclosure) -{ - return senc_enclosure_ref_put(enclosure); -} - -END_DECLS - -#endif /* SENC_X_3D_H */ diff --git a/src/sencX3d.h b/src/sencX3d.h @@ -0,0 +1,488 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC3D_X_3D_H +#define SENC3D_X_3D_H + +#include <star/senc3d.h> +#include <star/SENC3D_s3d_helper.h> +#include <rsys/rsys.h> + +/* This file can be used in conjunction with sencX2.h from the the + * star-enclosures-2D library to write code for both 2D and 3D geometries using + * the following pattern: + * + * #if (DIM==2) + * #include <star/sencX2.h> + * #elif (DIM==3) + * #include <star/sencX3d.h> + * #else + * #error DIM should be defined; possible values are 2 and 3 + * #endif + * + * Then use the sencX_... types and functions in your code. + * + * Definitions from sencX2.h and sencX3d.h cannot be visible at the same time + * as some of them conflict. + */ + +/* Helper macro that asserts if the invocation of the StarEnclosures function + * `Func' returns an error. One should use this macro on StarEnc function calls + * for which no explicit error checking is performed. */ +#ifndef NDEBUG +#define SENCX(Func) ASSERT(sencX_ ## Func == RES_OK) +#else +#define SENCX(Func) sencX_ ## Func +#endif + +/* Forward declaration of external opaque data types */ +struct logger; +struct mem_allocator; + +/* Forward declaration of StarEnclosures opaque data types. These data types + * are ref counted. Once created with the appropriated `SENC3D_<TYPE>_create' + * function, the caller implicitly owns the created data, i.e. its reference + * counter is set to 1. The SENC3D_<TYPE>_ref_<get|put> functions get or release + * 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. */ +typedef struct senc3d_device sencX_device; +typedef struct senc3d_scene sencX_scene; +typedef struct senc3d_enclosure sencX_enclosure; + +/******************************************************************************* + * The dimension of the geometry used in the library. + ******************************************************************************/ +#define SENCX_GEOMETRY_DIMENSION SENC3D_GEOMETRY_DIMENSION + +/* A type to discriminate triangle sides */ +enum sencX_side { + SENCX_FRONT = SENC3D_FRONT, + SENCX_BACK = SENC3D_BACK +}; + +/* Enclosure header type */ +typedef struct senc3d_enclosure_header sencX_enclosure_header; + +/* We consider the geometrical normal Ng to a triangle V0 V1 V2 + * that verifies "(V0, V0V1, V0V2, Ng) is a direct system" + * (right-handed system). + * + * The user can set the convention used to determine which side of + * a triangle is to be considered front/back by using the flags : + * SENC3D_CONVENTION_NORMAL_FRONT => Ng points toward the front side, + * SENC3D_CONVENTION_NORMAL_BACK => Ng points toward the back side. + * + * Additionaly the user can set the convention used to output enclosures + * so that Ng points toward the enclosure or on the opposite direction + * (for a closed enclosure Ng points toward the inside or toward the outside) + * by using the flags : + * SENC3D_CONVENTION_NORMAL_INSIDE => Ng points toward the enclosure, + * SENC3D_CONVENTION_NORMAL_OUTSIDE => Ng points to the opposite of the enclosure. + * + * Note that normals in output data can be opposite to normals in input data + * (vertices are then given in reverse order). + * + * Also note that both sides of a triangle can be part of the same enclosure; + * in this case the 2 sides will be given with opposite Ng (meaning they + * will be given with opposite vertices order). + */ +enum sencX_convention { + /* + * Convention regarding FRONT/BACK sides in input data + */ + + /* Geometrical normals point toward the front side */ + SENCX_CONVENTION_NORMAL_FRONT = SENC3D_CONVENTION_NORMAL_FRONT, + /* Geometrical normals point toward the back side */ + SENCX_CONVENTION_NORMAL_BACK = SENC3D_CONVENTION_NORMAL_BACK, + + /* + * Convention regarding geometrical normals in output data + */ + + /* Geometrical normals point toward the enclosure */ + SENCX_CONVENTION_NORMAL_INSIDE = SENC3D_CONVENTION_NORMAL_INSIDE, + /* Geometrical normals point to the opposite of the enclosure */ + SENCX_CONVENTION_NORMAL_OUTSIDE = SENC3D_CONVENTION_NORMAL_OUTSIDE +}; + +/****************************************************************************** + * The value that should be used to let media unspecified. + *****************************************************************************/ +#define SENCX_UNSPECIFIED_MEDIUM SENC3D_UNSPECIFIED_MEDIUM + +BEGIN_DECLS + +/****************************************************************************** + * StarEnclosures device. It is an handle toward the StarEnc library. + * It manages the lib resources. + * If provided, the allocator has to be suitable for parallel high frequency + * allocations. As a consequence, a rsys proxy allocator should be avoided. + *****************************************************************************/ +static FINLINE res_T +sencX_device_create + (struct logger* logger, /* May be NULL <=> use default logger */ + struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const unsigned nthreads_hint, + const int verbose, + sencX_device** device) +{ + return senc3d_device_create(logger, allocator, nthreads_hint, verbose, device); +} + +static FINLINE res_T +sencX_device_ref_get + (sencX_device* device) +{ + return senc3d_device_ref_get(device); +} + +static FINLINE res_T +sencX_device_ref_put + (sencX_device* device) +{ + return senc3d_device_ref_put(device); +} + +/****************************************************************************** + * StarEnclosures scene. A scene is a collection of triangles. Each triangle is + * defined with a medium on each side. + *****************************************************************************/ +/* Creates a scene from some vertices and triangles. + * Neither vertices nor triangles can include duplicates. + * Triangles cannot be degenerated. */ +static FINLINE res_T +sencX_scene_create + (sencX_device* device, + const int convention, + /* Number of triangles */ + const unsigned triangles_count, + /* User function that provides vertices ids for triangles */ + void(*get_indices)( + const unsigned itri, + unsigned ids[SENCX_GEOMETRY_DIMENSION], + void* context), + /* User function that provides media ids for triangles */ + void(*get_media) /* Can be NULL <=> SENC3D_UNSPECIFIED_MEDIUM medium used */ + (const unsigned itri, unsigned med[2], void* context), + /* Number of vertices */ + const unsigned vertices_count, + /* User function that provides coordinates for vertices */ + void(*get_position)( + const unsigned ivert, + double pos[SENCX_GEOMETRY_DIMENSION], + void* context), + /* Context provided to user callbacks; can be NULL */ + void* context, + /* The created scene */ + sencX_scene** scene) +{ + return senc3d_scene_create(device, convention, triangles_count, get_indices, + get_media, vertices_count, get_position, context, scene); +} + +/* Returns the convention flags in use with the scene. */ +static FINLINE res_T +sencX_scene_get_convention + (const sencX_scene* scene, + int* convention) +{ + return senc3d_scene_get_convention(scene, convention); +} + +/* Returns the number of triangles in the scene. */ +static FINLINE res_T +sencX_scene_get_primitives_count + (const sencX_scene* scene, + unsigned* count) +{ + return senc3d_scene_get_triangles_count(scene, count); +} + +/* Returns the itri_th triangle vertices' indices. */ +static FINLINE res_T +sencX_scene_get_primitive + (const sencX_scene* scene, + const unsigned itri, + unsigned indices[SENCX_GEOMETRY_DIMENSION]) +{ + return senc3d_scene_get_triangle(scene, itri, indices); +} + +/* Returns the media for the itri_th triangle. */ +static FINLINE res_T +sencX_scene_get_primitive_media + (const sencX_scene* scene, + const unsigned itri, + unsigned media[2]) +{ + return senc3d_scene_get_triangle_media(scene, itri, media); +} + +/* Returns the number of vertices in the scene. */ +static FINLINE res_T +sencX_scene_get_vertices_count + (const sencX_scene* scene, + unsigned* count) +{ + return senc3d_scene_get_vertices_count(scene, count); +} + +/* Returns the coordinates of the ivert_th vertex. */ +static FINLINE res_T +sencX_scene_get_vertex + (const sencX_scene* scene, + const unsigned ivert, + double coord[SENCX_GEOMETRY_DIMENSION]) +{ + return senc3d_scene_get_vertex(scene, ivert, coord); +} + +/* Returns the greater medium id found in added geometry. In API calls using a + * medium, any value in the [0 max_medium_id[ range is valid. However there can + * be unused ids (no geometry refered to this medium id). */ +static FINLINE res_T +sencX_scene_get_max_medium + (const sencX_scene* scene, + unsigned* max_medium_id) +{ + return senc3d_scene_get_max_medium(scene, max_medium_id); +} + +/* Returns the number of enclosures. */ +static FINLINE res_T +sencX_scene_get_enclosure_count + (const sencX_scene* scene, + unsigned* count) +{ + return senc3d_scene_get_enclosure_count(scene, count); +} + +/* Returns the number of enclosures that have some geometry refering to the + * imed_th medium or SENC3D_UNSPECIFIED_MEDIUM. */ +static FINLINE res_T +sencX_scene_get_enclosure_count_by_medium + (const sencX_scene* scene, + const unsigned imed, + unsigned* count) +{ + return senc3d_scene_get_enclosure_count_by_medium(scene, imed, count); +} + +/* Returns the idx_th enclosure. */ +static FINLINE res_T +sencX_scene_get_enclosure + (sencX_scene* scene, + const unsigned idx, + sencX_enclosure** enclosure) +{ + return senc3d_scene_get_enclosure(scene, idx, enclosure); +} + +/* Returns the idx_th enclosure using the imed_th medium or + * SENC3D_UNSPECIFIED_MEDIUM. */ +static FINLINE res_T +sencX_scene_get_enclosure_by_medium + (sencX_scene* scene, + const unsigned imed, + const unsigned idx, + sencX_enclosure** enclosure) +{ + return senc3d_scene_get_enclosure_by_medium(scene, imed, idx, enclosure); +} + +/* Returns the enclosures the itri_th triangle front and back sides are member + * of. */ +static FINLINE res_T +sencX_scene_get_primitive_enclosures + (const sencX_scene* scene, + const unsigned itri, + unsigned enclosures[2]) +{ + return senc3d_scene_get_triangle_enclosures(scene, itri, enclosures); +} + +/* Returns the number of segments that are frontier segments: + * - that have arity 1 (single triangle using the segment) + * - that connect 2 different media */ +static FINLINE res_T +sencX_scene_get_frontier_elements_count + (const sencX_scene* scene, + unsigned* count) +{ + return senc3d_scene_get_frontier_segments_count(scene, count); +} + +/* Returns the iseg_th frontier segment; the returned indices are global vertex + * indices whose coordinates can be retrieved using sencX_scene_get_vertex. */ +static FINLINE res_T +sencX_scene_get_frontier_element + (const sencX_scene* scene, + const unsigned iseg, + unsigned vrtx_id[SENCX_GEOMETRY_DIMENSION-1]) +{ + return senc3d_scene_get_frontier_segment(scene, iseg, vrtx_id); +} + +static FINLINE res_T +sencX_scene_ref_get + (sencX_scene* scene) +{ + return senc3d_scene_ref_get(scene); +} + +static FINLINE res_T +sencX_scene_ref_put + (sencX_scene* scene) +{ + return senc3d_scene_ref_put(scene); +} + +/******************************************************************************* + * StarEnclosures enclosure. It is an handle toward an enclosure. + * Counts and other information on enclosures are not individually accessible, + * but as a whole through header access. + * An enclosure can list the "same" triangle twice if both sides are in. In this + * case the 2 occurences of the triangle have reversed vertices order and + * unique_triangle_count and triangle_count differ. + * Vertices and triangles numbering schemes are specific to each enclosure: + * the "same" item appearing in 2 different enclosures has no reason to get the + * same index twice or to have the same index in the global numbering scheme. + * By-index API accesses of triangles (or properties) visit unique triangles + * for indices in the [0 unique_triangle_count[ range and back-faces of the + * doubly-included triangles in the [unique_triangle_count triangle_count[ range. + ******************************************************************************/ +/* Returns the header of an enclosure. */ +static FINLINE res_T +sencX_enclosure_get_header + (const sencX_enclosure* enclosure, + sencX_enclosure_header* header) +{ + return senc3d_enclosure_get_header(enclosure, header); +} + +/* Returns the itri_th triangle of an enclosure. + * Indices are local to the enclosure. */ +static FINLINE res_T +sencX_enclosure_get_primitive + (const sencX_enclosure* enclosure, + const unsigned itri, + unsigned indices[SENCX_GEOMETRY_DIMENSION]) +{ + return senc3d_enclosure_get_triangle(enclosure, itri, indices); +} + +/* Returns the coordinates of the ivert_th vertex of an enclosure. */ +static FINLINE res_T +sencX_enclosure_get_vertex + (const sencX_enclosure* enclosure, + const unsigned ivert, + double coord[SENCX_GEOMETRY_DIMENSION]) +{ + return senc3d_enclosure_get_vertex(enclosure, ivert, coord); +} + +/* Returns the global id of the itri_th triangle of an enclosure + * and the involved side. */ +static FINLINE res_T +sencX_enclosure_get_primitive_id + (const sencX_enclosure* enclosure, + const unsigned itri, + unsigned* gid, + enum senc3d_side* side) +{ + return senc3d_enclosure_get_triangle_id(enclosure, itri, gid, side); +} + +/* Returns the id of the imed_th medium of an enclosure. */ +static FINLINE res_T +sencX_enclosure_get_medium + (const sencX_enclosure* enclosure, + const unsigned imed, + unsigned* medium) +{ + return senc3d_enclosure_get_medium(enclosure, imed, medium); +} + +static FINLINE res_T +sencX_enclosure_ref_get + (sencX_enclosure* enclosure) +{ + return senc3d_enclosure_ref_get(enclosure); +} + +static FINLINE res_T +sencX_enclosure_ref_put + (sencX_enclosure* enclosure) +{ + return senc3d_enclosure_ref_put(enclosure); +} + +/****************************************************************************** + * StarEnclosuresXD to StarXD helper. + *****************************************************************************/ + + /* Get vertex indices for the iseg_th segment. + * Suitable for use as get_indice callback in s3d_mesh_setup_indexed_vertices + * calls. */ +static FINLINE void +sencX_sXd_scene_get_indices + (const unsigned iseg, + unsigned indices[SENCX_GEOMETRY_DIMENSION], + void* ctx) +{ + SENC3D_s3d_scene_get_indices(iseg, indices, ctx); +} + +/* Get coordinates for the ivert_th vertex. + * Suitable for use as s3d_vertex_data getter for S3D_POSITION s3d_attrib_usage + * in s3d_mesh_setup_indexed_vertices calls. */ +static FINLINE void +sencX_sXd_scene_get_position + (const unsigned ivert, + float coord[SENCX_GEOMETRY_DIMENSION], + void* ctx) +{ + SENC3D_s3d_scene_get_position(ivert, coord, ctx); +} + +/* Get vertex indices for the iseg_th segment of the enclosure. + * Suitable for use as get_indice callback in s3d_mesh_setup_indexed_vertices + * calls. */ +static FINLINE void +sencX_sXd_enclosure_get_indices + (const unsigned iseg, + unsigned indices[SENCX_GEOMETRY_DIMENSION], + void* ctx) +{ + SENC3D_s3d_enclosure_get_indices(iseg, indices, ctx); +} + +/* Get coordinates for the ivert_th vertex of the enclosure. + * Suitable for use as s3d_vertex_data getter for S3D_POSITION s3d_attrib_usage + * in s3d_mesh_setup_indexed_vertices calls. */ +static FINLINE void +sencX_sXd_enclosure_get_position + (const unsigned ivert, + float coord[SENCX_GEOMETRY_DIMENSION], + void* ctx) +{ + SENC3D_s3d_enclosure_get_position(ivert, coord, ctx); +} + +END_DECLS + +#endif /* SENC3D_X_3D_H */ diff --git a/src/senc_descriptor.c b/src/senc_descriptor.c @@ -1,160 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc_enclosure_c.h" -#include "senc_scene_c.h" -#include "senc.h" - -#include <rsys/rsys.h> -#include <rsys/double3.h> -#include <rsys/mem_allocator.h> - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -senc_scene_get_max_medium - (const struct senc_scene* scn, unsigned* max_medium_id) -{ - if(!scn || !max_medium_id) return RES_BAD_ARG; - ASSERT(scn->next_medium_idx < UINT_MAX); /* API type */ - *max_medium_id = (unsigned)scn->next_medium_idx - 1; - return RES_OK; -} - -res_T -senc_scene_get_enclosure_count - (const struct senc_scene* scn, unsigned* count) -{ - size_t tmp; - if(!scn || !count) return RES_BAD_ARG; - tmp = darray_enclosure_size_get(&scn->analyze.enclosures); - ASSERT(tmp < UINT_MAX); /* API type */ - ASSERT(scn->analyze.enclosures_count == tmp); - *count = (unsigned)tmp; - return RES_OK; -} - -res_T -senc_scene_get_enclosure_count_by_medium - (const struct senc_scene* scn, - const unsigned imed, - unsigned* count) -{ - size_t tmp, m_idx; - const struct darray_enc_id* enc_ids; - if(!scn || !count - || (imed != SENC_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) - return RES_BAD_ARG; - ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) - == 1 + scn->next_medium_idx); - m_idx = (imed == SENC_UNSPECIFIED_MEDIUM) ? 0 : imed + 1; - enc_ids = darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) - + m_idx; - tmp = darray_enc_id_size_get(enc_ids); - ASSERT(tmp < UINT_MAX); /* API type */ - *count = (unsigned)tmp; - return RES_OK; -} - -FINLINE res_T -senc_scene_get_enclosure - (struct senc_scene* scn, - const unsigned idx, - struct senc_enclosure** out_enc) -{ - struct senc_enclosure* enc; - if(!scn || idx >= darray_enclosure_size_get(&scn->analyze.enclosures) - || !out_enc) - return RES_BAD_ARG; - enc = enclosure_create(scn, idx); - if(!enc) return RES_MEM_ERR; - *out_enc = enc; - return RES_OK; -} - -res_T -senc_scene_get_enclosure_by_medium - (struct senc_scene* scn, - const unsigned imed, - const unsigned idx, - struct senc_enclosure** out_enc) -{ - size_t m_idx; - const struct darray_enc_id* enc_ids; - unsigned index; - if(!scn || !out_enc - || (imed != SENC_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) - return RES_BAD_ARG; - ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) - == 1 + scn->next_medium_idx); - m_idx = (imed == SENC_UNSPECIFIED_MEDIUM) ? 0 : imed + 1; - enc_ids = - darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; - if(idx >= darray_enc_id_size_get(enc_ids)) return RES_BAD_ARG; - index = darray_enc_id_cdata_get(enc_ids)[idx]; - return senc_scene_get_enclosure(scn, index, out_enc); -} - -res_T -senc_scene_get_triangle_enclosures - (const struct senc_scene* scn, - const unsigned itri, - unsigned enclosures[2]) -{ - const struct triangle_enc* trg; - int i; - if(!enclosures || !scn - || itri >= darray_triangle_enc_size_get(&scn->analyze.triangles_enc)) - return RES_BAD_ARG; - trg = darray_triangle_enc_cdata_get(&scn->analyze.triangles_enc) + itri; - FOR_EACH(i, 0, 2) { -#if (UINT_MAX < ENCLOSURE_MAX__) - ASSERT(trg->enclosure[i] < UINT_MAX); -#endif - enclosures[i] = (unsigned)trg->enclosure[i]; /* Back to API type */ - } - return RES_OK; -} - -res_T -senc_scene_get_frontier_segments_count - (const struct senc_scene* scn, - unsigned* count) -{ - size_t tmp; - if(!scn || !count) - return RES_BAD_ARG; - tmp = darray_frontier_edge_size_get(&scn->analyze.frontiers); - ASSERT(tmp < UINT_MAX); - *count = (unsigned)tmp; - return RES_OK; -} - -res_T -senc_scene_get_frontier_segment - (const struct senc_scene* scn, - const unsigned iseg, - unsigned vrtx_id[2]) -{ - const struct trg_edge* edge; - if(!vrtx_id || !scn - || iseg >= darray_frontier_edge_size_get(&scn->analyze.frontiers)) - return RES_BAD_ARG; - edge = darray_frontier_edge_cdata_get(&scn->analyze.frontiers) + iseg; - vrtx_id[0] = (unsigned)edge->vrtx0; /* Back to API type */ - vrtx_id[1] = (unsigned)edge->vrtx1; /* Back to API type */ - return RES_OK; -} diff --git a/src/senc_device.c b/src/senc_device.c @@ -1,148 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "senc_device_c.h" - -#include <rsys/logger.h> -#include <rsys/mem_allocator.h> - -#include <omp.h> - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static void -log_msg - (struct senc_device* dev, - const enum log_type stream, - const char* msg, - va_list vargs) -{ - ASSERT(dev && msg); - if(dev->verbose) { - res_T res; (void)res; - res = logger_vprint(dev->logger, stream, msg, vargs); - ASSERT(res == RES_OK); - } -} - -static void -device_release(ref_T* ref) -{ - struct senc_device* dev; - ASSERT(ref); - dev = CONTAINER_OF(ref, struct senc_device, ref); - MEM_RM(dev->allocator, dev); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -void -log_err(struct senc_device* dev, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(dev && msg); - - va_start(vargs_list, msg); - log_msg(dev, LOG_ERROR, msg, vargs_list); - va_end(vargs_list); -} - -void -log_warn(struct senc_device* dev, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(dev && msg); - - va_start(vargs_list, msg); - log_msg(dev, LOG_WARNING, msg, vargs_list); - va_end(vargs_list); -} - -void -log_info(struct senc_device* dev, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(dev && msg); - - va_start(vargs_list, msg); - log_msg(dev, LOG_OUTPUT, msg, vargs_list); - va_end(vargs_list); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -senc_device_create - (struct logger* logger, - struct mem_allocator* mem_allocator, - const unsigned nthreads_hint, - const int verbose, - struct senc_device** out_dev) -{ - struct logger* log = NULL; - struct senc_device* dev = NULL; - struct mem_allocator* allocator = NULL; - res_T res = RES_OK; - if(nthreads_hint == 0 || !out_dev) return RES_BAD_ARG; - - log = logger ? logger : LOGGER_DEFAULT; - allocator = mem_allocator ? mem_allocator : &mem_default_allocator; - dev = MEM_CALLOC(allocator, 1, sizeof(struct senc_device)); - if(!dev) { - if(verbose) { - /* Do not use helper log functions since dev is not initialised */ - CHK(logger_print(log, LOG_ERROR, - "%s: could not allocate the StarEnclosures device.\n", FUNC_NAME) == RES_OK); - } - res = RES_MEM_ERR; - goto error; - } - dev->logger = log; - dev->allocator = allocator; - dev->verbose = verbose; - /* Cannot use int args for MMIN here as default is -1 */ - dev->nthreads = (int)MMIN(nthreads_hint, (unsigned)omp_get_num_procs()); - ref_init(&dev->ref); - -exit: - if(dev) *out_dev = dev; - return res; -error: - if(dev) { - SENC(device_ref_put(dev)); - dev = NULL; - } - goto exit; -} - -res_T -senc_device_ref_get(struct senc_device* dev) -{ - if(!dev) return RES_BAD_ARG; - ref_get(&dev->ref); - return RES_OK; -} - -res_T -senc_device_ref_put(struct senc_device* dev) -{ - if(!dev) return RES_BAD_ARG; - ref_put(&dev->ref, device_release); - return RES_OK; -} diff --git a/src/senc_device_c.h b/src/senc_device_c.h @@ -1,71 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_DEVICE_C_H -#define SENC_DEVICE_C_H - -#include <rsys/free_list.h> -#include <rsys/ref_count.h> - -struct name { FITEM; }; -#define FITEM_TYPE name -#include <rsys/free_list.h> - -struct senc_device { - struct logger* logger; - struct mem_allocator* allocator; - int verbose; - int nthreads; - - ref_T ref; -}; - -/* Conditionally log a message on the LOG_ERROR stream of the device logger, - * with respect to the device verbose flag */ -extern LOCAL_SYM void -log_err - (struct senc_device* dev, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -/* Conditionally log a message on the LOG_WARNING stream of the device logger, - * with respect to the device verbose flag */ -extern LOCAL_SYM void -log_warn - (struct senc_device* dev, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -/* Conditionally log a message on the LOG_OUTPUT stream of the device logger, - * with respect to the device verbose flag */ -extern LOCAL_SYM void -log_info - (struct senc_device* dev, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif - ; - -#endif /* SENC_DEVICE_C_H */ diff --git a/src/senc_enclosure.c b/src/senc_enclosure.c @@ -1,167 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc_enclosure_c.h" -#include "senc_enclosure_data.h" -#include "senc_scene_c.h" -#include "senc_device_c.h" -#include "senc.h" - -#include <rsys/rsys.h> -#include <rsys/double3.h> -#include <rsys/mem_allocator.h> - - -/******************************************************************************* - * Helper function - ******************************************************************************/ -static void -enclosure_release(ref_T * ref) -{ - struct senc_enclosure* enclosure = NULL; - struct senc_scene* scn = NULL; - ASSERT(ref); - enclosure = CONTAINER_OF(ref, struct senc_enclosure, ref); - scn = enclosure->scene; - MEM_RM(scn->dev->allocator, enclosure); - SENC(scene_ref_put(scn)); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -struct senc_enclosure* -enclosure_create - (struct senc_scene* scn, - const unsigned idx) -{ - struct senc_enclosure* enc; - ASSERT(scn && idx < darray_enclosure_size_get(&scn->analyze.enclosures)); - enc = MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct senc_enclosure)); - if(enc) { - const struct enclosure_data* data - = darray_enclosure_data_get(&scn->analyze.enclosures) + idx; - enc->scene = scn; - enc->data = data; - ref_init(&enc->ref); - SENC(scene_ref_get(scn)); - } - return enc; -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -senc_enclosure_get_header - (const struct senc_enclosure* enclosure, - struct senc_enclosure_header* header) -{ - if(!enclosure || !header) return RES_BAD_ARG; - *header = enclosure->data->header; - return RES_OK; -} - -res_T -senc_enclosure_get_triangle - (const struct senc_enclosure* enclosure, - const unsigned itri, - unsigned indices[3]) -{ - const struct side_enc* side; - int i; - if(!enclosure || !indices - || itri >= enclosure->data->header.primitives_count) - return RES_BAD_ARG; - ASSERT(darray_sides_enc_size_get(&enclosure->data->sides) - == enclosure->data->header.primitives_count); - side = darray_sides_enc_cdata_get(&enclosure->data->sides) + itri; - FOR_EACH(i, 0, 3) { - ASSERT(side->vertice_id[i] < UINT_MAX); - indices[i] = (unsigned)side->vertice_id[i]; /* Back to API type */ - } - return RES_OK; -} - -res_T -senc_enclosure_get_vertex - (const struct senc_enclosure* enclosure, - const unsigned ivert, - double coord[3]) -{ - if(!enclosure || !coord - || ivert >= enclosure->data->header.vertices_count) { - return RES_BAD_ARG; - } else { - const vrtx_id_t idx - = darray_vrtx_id_cdata_get(&enclosure->data->vertices)[ivert]; - const union double3* positions - = darray_position_cdata_get(&enclosure->scene->vertices); - ASSERT(darray_vrtx_id_size_get(&enclosure->data->vertices) - == enclosure->data->header.vertices_count); - d3_set(coord, positions[idx].vec); - return RES_OK; - } -} - -res_T -senc_enclosure_get_triangle_id - (const struct senc_enclosure* enclosure, - const unsigned itri, - unsigned* gid, - enum senc_side* sde) -{ - const struct side_enc* side; - if(!enclosure || !gid || !sde - || itri >= enclosure->data->header.primitives_count) - return RES_BAD_ARG; - ASSERT(darray_sides_enc_size_get(&enclosure->data->sides) - == enclosure->data->header.primitives_count); - side = darray_sides_enc_cdata_get(&enclosure->data->sides) + itri; - *gid = (unsigned)TRGSIDE_2_TRG(side->side_id); - *sde = TRGSIDE_2_SIDE(side->side_id); - return RES_OK; -} - -res_T -senc_enclosure_get_medium - (const struct senc_enclosure* enclosure, - const unsigned imed, - unsigned* medium) -{ - if(!enclosure || !medium - || imed >= enclosure->data->header.enclosed_media_count) - return RES_BAD_ARG; - ASSERT(enclosure->data->header.enclosed_media_count - == darray_media_size_get(&enclosure->data->enclosed_media)); - *medium = darray_media_cdata_get(&enclosure->data->enclosed_media)[imed]; - return RES_OK; -} - -res_T -senc_enclosure_ref_get(struct senc_enclosure* enc) -{ - if(!enc) return RES_BAD_ARG; - ref_get(&enc->ref); - return RES_OK; -} - -res_T -senc_enclosure_ref_put(struct senc_enclosure* enc) -{ - if(!enc) return RES_BAD_ARG; - ref_put(&enc->ref, enclosure_release); - return RES_OK; -} diff --git a/src/senc_enclosure_c.h b/src/senc_enclosure_c.h @@ -1,37 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_ENCLOSURE_C_H -#define SENC_ENCLOSURE_C_H - -#include <rsys/ref_count.h> - -#include "senc.h" - -struct enclosure_data; -struct senc_scene; - -struct senc_enclosure { - const struct enclosure_data* data; - struct senc_scene* scene; - ref_T ref; -}; - -struct senc_enclosure* -enclosure_create - (struct senc_scene* scene, - const unsigned idx); - -#endif /* SENC_ENCLOSURE_C_H */ diff --git a/src/senc_enclosure_data.h b/src/senc_enclosure_data.h @@ -1,235 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_ENCLOSURE_DATA_H -#define SENC_ENCLOSURE_DATA_H - -#include "senc.h" -#include "senc_internal_types.h" -#include "senc_side_range.h" - -#include <rsys/rsys.h> -#include <rsys/ref_count.h> -#include <rsys/hash_table.h> -#include <rsys/dynamic_array.h> -#include <rsys/hash_table.h> - -#include <limits.h> - -#define DARRAY_NAME vrtx_id -#define DARRAY_DATA vrtx_id_t -#include <rsys/dynamic_array.h> - -#define HTABLE_NAME vrtx_id -#define HTABLE_KEY vrtx_id_t -#define HTABLE_DATA vrtx_id_t -#include <rsys/hash_table.h> - -struct side_enc { - vrtx_id_t vertice_id[3]; - side_id_t side_id; -}; - -#define DARRAY_NAME sides_enc -#define DARRAY_DATA struct side_enc -#include <rsys/dynamic_array.h> - -/* unsigned char array with init to zero */ -static FINLINE void -zero_init_uchar - (struct mem_allocator* alloc, unsigned char* data) -{ - ASSERT(data); (void) alloc; - *data = 0; -} -#define DARRAY_FUNCTOR_INIT zero_init_uchar -#include <rsys/dynamic_array_uchar.h> - -static void -init_header(struct senc_enclosure_header* header) -{ - ASSERT(header); - header->enclosure_id = ENCLOSURE_NULL__; - header->primitives_count = 0; - header->unique_primitives_count = 0; - header->vertices_count = 0; - header->enclosed_media_count = 0; - header->is_infinite = CHAR_MAX; -} - -#define DARRAY_NAME media -#define DARRAY_DATA medium_id_t -#include <rsys/dynamic_array.h> - -static FINLINE res_T -bool_array_of_media_merge - (struct darray_uchar* dst, - const unsigned char* src, - const medium_id_t sz) -{ - res_T res = RES_OK; - medium_id_t i; - unsigned char* data_dst; - - ASSERT(src && dst); - - OK(darray_uchar_resize(dst, sz)); - data_dst = darray_uchar_data_get(dst); - ASSERT(sz <= MEDIUM_MAX__); - if(res != RES_OK) goto error; - FOR_EACH(i, 0, sz) { - if(!src[i]) continue; - data_dst[i] = 1; - } -end: - return res; -error: - goto end; -} - -static FINLINE res_T -bool_array_of_media_to_darray_media - (struct darray_media* dst, - const struct darray_uchar* src, - const medium_id_t next_medium_idx) -{ - res_T res = RES_OK; - unsigned m_idx; - const unsigned char* data; - - ASSERT(src && dst); - - data = darray_uchar_cdata_get(src); - ASSERT(next_medium_idx + 1 == darray_uchar_size_get(src)); - ASSERT(next_medium_idx < MEDIUM_MAX__); - darray_media_clear(dst); - if(res != RES_OK) goto error; - FOR_EACH(m_idx, 0, next_medium_idx + 1) { - medium_id_t medium = m_idx ? (medium_id_t)(m_idx - 1) : SENC_UNSPECIFIED_MEDIUM; - if(!data[m_idx]) continue; - res = darray_media_push_back(dst, &medium); - if(res != RES_OK) goto error; - } -end: - return res; -error: - goto end; -} - -struct enclosure_data { - struct senc_enclosure_header header; - /* Same triangle can appear twice if both sides */ - struct darray_sides_enc sides; - /* Index of vertices in scene's unique vertices */ - struct darray_vrtx_id vertices; - /* List of the enclosed media */ - struct darray_uchar tmp_enclosed_media; - struct darray_media enclosed_media; - /* Number of components involved in this enclosure */ - component_id_t cc_count; - /* Linked list of the components */ - component_id_t first_component; - /* Range of triangles member of the enclosure */ - struct side_range side_range; - /* Counts */ - side_id_t side_count; -}; - -static FINLINE void -enclosure_data_init(struct mem_allocator* alloc, struct enclosure_data* enc) { - ASSERT(enc); - init_header(&enc->header); - enc->cc_count = 0; - enc->first_component = COMPONENT_NULL__; - enc->side_range.first = SIDE_NULL__; - enc->side_range.last = 0; - enc->side_count = 0; - darray_sides_enc_init(alloc, &enc->sides); - darray_vrtx_id_init(alloc, &enc->vertices); - darray_uchar_init(alloc, &enc->tmp_enclosed_media); - darray_media_init(alloc, &enc->enclosed_media); -} - -static FINLINE res_T -enclosure_data_copy - (struct enclosure_data* dst, - const struct enclosure_data* src) -{ - res_T res = RES_OK; - ASSERT(src && dst); - dst->header = src->header; - dst->cc_count = src->cc_count; - dst->first_component = src->first_component; - dst->side_range = src->side_range; - dst->side_count = src->side_count; - OK(darray_sides_enc_copy(&dst->sides, &src->sides)); - OK(darray_vrtx_id_copy(&dst->vertices, &src->vertices)); - OK(darray_uchar_copy(&dst->tmp_enclosed_media, &src->tmp_enclosed_media)); - OK(darray_media_copy(&dst->enclosed_media, &src->enclosed_media)); -error: - return res; -} - -static FINLINE void -enclosure_data_release(struct enclosure_data* n) { - ASSERT(n); - darray_sides_enc_release(&n->sides); - darray_vrtx_id_release(&n->vertices); - darray_uchar_release(&n->tmp_enclosed_media); - darray_media_release(&n->enclosed_media); -} - -static FINLINE res_T -enclosure_data_copy_and_release - (struct enclosure_data* dst, - struct enclosure_data* src) -{ - res_T res = RES_OK; - ASSERT(src && dst); - dst->header = src->header; - dst->cc_count = src->cc_count; - dst->first_component = src->first_component; - dst->side_range = src->side_range; - dst->side_count = src->side_count; - OK(darray_sides_enc_copy_and_release(&dst->sides, &src->sides)); - OK(darray_vrtx_id_copy_and_release(&dst->vertices, &src->vertices)); - OK(darray_uchar_copy_and_release(&dst->tmp_enclosed_media, - &src->tmp_enclosed_media)); - OK(darray_media_copy_and_release(&dst->enclosed_media, &src->enclosed_media)); -error: - return res; -} - -#define DARRAY_NAME enclosure -#define DARRAY_DATA struct enclosure_data -#define DARRAY_FUNCTOR_INIT enclosure_data_init -#define DARRAY_FUNCTOR_COPY enclosure_data_copy -#define DARRAY_FUNCTOR_RELEASE enclosure_data_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE enclosure_data_copy_and_release -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enc_id -#define DARRAY_DATA enclosure_id_t -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enc_ids_array -#define DARRAY_DATA struct darray_enc_id -#define DARRAY_FUNCTOR_INIT darray_enc_id_init -#define DARRAY_FUNCTOR_COPY darray_enc_id_copy -#define DARRAY_FUNCTOR_RELEASE darray_enc_id_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release -#include <rsys/dynamic_array.h> - -#endif /* SENC_ENCLOSURE_DATA_H */ diff --git a/src/senc_internal_types.h b/src/senc_internal_types.h @@ -1,142 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_INTERNAL_TYPES_H -#define SENC_INTERNAL_TYPES_H - -#include "senc.h" - -#include <rsys/math.h> - -#include <stdio.h> -#include <stdint.h> - -/* Utility macros */ -#ifdef NDEBUG -#define OK2(Expr)\ - if((tmp_res = (Expr)) != RES_OK) goto tmp_error; - -#define OK(Expr)\ - if((res = (Expr)) != RES_OK) goto error; -#else -#define OK2(Expr)\ - if((tmp_res = (Expr)) != RES_OK) {\ - fprintf(stderr, "%s: error code set to %d at line %d\n", FUNC_NAME,\ - tmp_res, __LINE__);\ - goto tmp_error;\ - } - -#define OK(Expr)\ - if((res = (Expr)) != RES_OK) {\ - fprintf(stderr, "%s: error code set to %d at line %d\n", FUNC_NAME,\ - res, __LINE__);\ - goto error;\ - } -#endif - -/* Side IDs are uint32_t */ -typedef uint32_t side_id_t; -#define SIDE_MAX__ (UINT32_MAX-1) -#define SIDE_NULL__ UINT32_MAX - -/* Trg IDs use internally side_id_t */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef side_id_t trg_id_t; -/* TRG_MAX__ is limited to allow to count sides */ -#define TRG_MAX__ (SIDE_MAX__ / 2) -#define TRG_NULL__ UINT32_MAX - -/* Vertex IDs are internally uint32_t */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef uint32_t vrtx_id_t; -#define VRTX_MAX__ (UINT32_MAX-1) -#define VRTX_NULL__ UINT32_MAX - -/* Edge IDs use the same type than vertex IDs */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef vrtx_id_t edge_id_t; -#define EDGE_MAX__ VRTX_MAX__ -#define EDGE_NULL__ VRTX_NULL__ - -/* Medium IDs are internally uint32_t */ -/* Should nnot be larger than unsigned, as the API uses it. */ -typedef uint32_t medium_id_t; -#define MEDIUM_MAX__ INT32_MAX -#define MEDIUM_NULL__ UINT32_MAX - -/* Enclosure IDs are internally uint32_t */ -/* Cannot be larger than unsigned, as the API uses it. */ -typedef uint32_t enclosure_id_t; -#define ENCLOSURE_MAX__ UINT32_MAX -#define ENCLOSURE_NULL__ UINT32_MAX - -/* Component IDs use the same type than enclosure IDs */ -typedef enclosure_id_t component_id_t; -#define COMPONENT_MAX__ (UINT32_MAX - 2) /* To allow special values */ -#define COMPONENT_NULL__ UINT32_MAX -/* Special values */ -#define CC_GROUP_ROOT_NONE UINT32_MAX -#define CC_GROUP_ROOT_INFINITE (UINT32_MAX - 1) -#define CC_GROUP_ID_NONE UINT32_MAX -#define CC_ID_NONE UINT32_MAX - -/* This one is used as flag */ -enum side_flag { - FLAG_FRONT = BIT(0), - FLAG_BACK = BIT(1) -}; - -/* Utility macros */ -static FINLINE trg_id_t -TRGSIDE_2_TRG(side_id_t s) { - ASSERT(((size_t)s >> 1) <= TRG_MAX__); - return s >> 1; -} - -static FINLINE int -TRGSIDE_IS_FRONT(side_id_t s) { - return (s & 1) == 0; -} - -static FINLINE enum senc_side -TRGSIDE_2_SIDE(side_id_t s) { - return (s & 1) ? SENC_BACK : SENC_FRONT; -} - -static FINLINE enum side_flag -TRGSIDE_2_SIDEFLAG(side_id_t s) { - return (s & 1) ? FLAG_BACK : FLAG_FRONT; -} - -static FINLINE unsigned char -SIDE_CANCELED_FLAG(enum side_flag f) { - ASSERT((f << 4) <= UCHAR_MAX); - return (unsigned char)(f << 4); -} - -static FINLINE side_id_t -TRGIDxSIDE_2_TRGSIDE(trg_id_t t, enum senc_side i) { - ASSERT((((size_t)t << 1) | (i == SENC_BACK)) < SIDE_MAX__); - ASSERT(i == SENC_FRONT || i == SENC_BACK); - return (side_id_t)((t << 1) | (i == SENC_BACK)); -} - -static FINLINE side_id_t -TRGSIDE_OPPOSITE(side_id_t s) { - return TRGIDxSIDE_2_TRGSIDE(TRGSIDE_2_TRG(s), - TRGSIDE_IS_FRONT(s) ? SENC_BACK : SENC_FRONT); -} - -#endif /* SENC_INTERNAL_TYPES_H */ diff --git a/src/senc_s3d_helper.h b/src/senc_s3d_helper.h @@ -1,92 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_S3D_WRAPPER_H -#define SENC_S3D_WRAPPER_H - -#include "senc.h" - -#include <rsys/rsys.h> -#include <rsys/float3.h> - -/* Get vertex indices for the itri_th triangle. - * Suitable for use as get_indice callback in s3d_mesh_setup_indexed_vertices - * calls. */ -static FINLINE void -senc_s3d_scene_get_indices__ - (const unsigned itri, - unsigned indices[3], - void* ctx) -{ - const struct senc_scene* scene = ctx; - res_T r; - ASSERT(indices && scene); - r = senc_scene_get_triangle(scene, itri, indices); - ASSERT(r == RES_OK); (void)r; -} - -/* Get coordinates for the ivert_th vertex. - * Suitable for use as s3d_vertex_data getter for S3D_POSITION s3d_attrib_usage - * in s3d_mesh_setup_indexed_vertices calls. */ -static FINLINE void -senc_s3d_scene_get_position__ - (const unsigned ivert, - float coord[3], - void* ctx) -{ - const struct senc_scene* scene = ctx; - double tmp[3]; - res_T r; - ASSERT(coord && scene); - r = senc_scene_get_vertex(scene, ivert, tmp); - ASSERT(r == RES_OK); (void)r; - f3_set_d3(coord, tmp); -} - -/* Get vertex indices for the itri_th triangle of the enclosure. - * Suitable for use as get_indice callback in s3d_mesh_setup_indexed_vertices - * calls. */ -static FINLINE void -senc_s3d_enclosure_get_indices__ - (const unsigned itri, - unsigned indices[3], - void* ctx) -{ - const struct senc_enclosure* enclosure = ctx; - res_T r; - ASSERT(indices && ctx); - r = senc_enclosure_get_triangle(enclosure, itri, indices); - ASSERT(r == RES_OK); (void)r; -} - -/* Get coordinates for the ivert_th vertex of the enclosure. - * Suitable for use as s3d_vertex_data getter for S3D_POSITION s3d_attrib_usage - * in s3d_mesh_setup_indexed_vertices calls. */ -static FINLINE void -senc_s3d_enclosure_get_position__ - (const unsigned ivert, - float coord[3], - void* ctx) -{ - const struct senc_enclosure* enclosure = ctx; - double tmp[3]; - res_T r; - ASSERT(coord && ctx); - r = senc_enclosure_get_vertex(enclosure, ivert, tmp); - ASSERT(r == RES_OK); (void)r; - f3_set_d3(coord, tmp); -} - -#endif /* SENC_S3D_WRAPPER_H */ diff --git a/src/senc_scene.c b/src/senc_scene.c @@ -1,327 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "senc_device_c.h" -#include "senc_scene_c.h" -#include "senc_scene_analyze_c.h" - -#include <rsys/rsys.h> -#include <rsys/double3.h> -#include <rsys/mem_allocator.h> - -#include <limits.h> - -/******************************************************************************* - * Helper function - ******************************************************************************/ -static void -scene_release(ref_T * ref) -{ - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - ASSERT(ref); - scn = CONTAINER_OF(ref, struct senc_scene, ref); - dev = scn->dev; - darray_triangle_in_release(&scn->triangles_in); - darray_position_release(&scn->vertices); - darray_side_range_release(&scn->media_use); - - darray_triangle_enc_release(&scn->analyze.triangles_enc); - darray_enclosure_release(&scn->analyze.enclosures); - darray_enc_ids_array_release(&scn->analyze.enc_ids_array_by_medium); - darray_frontier_edge_release(&scn->analyze.frontiers); - - MEM_RM(dev->allocator, scn); - SENC(device_ref_put(dev)); -} - -static INLINE int -compatible_medium - (const medium_id_t m1, - const medium_id_t m2) -{ - if(m1 == SENC_UNSPECIFIED_MEDIUM || m2 == SENC_UNSPECIFIED_MEDIUM) return 1; - return (m1 == m2); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -senc_scene_create - (struct senc_device* dev, - const int conv, - const unsigned ntris, - void(*indices)(const unsigned, unsigned*, void*), - void(*media)(const unsigned, unsigned*, void*), - const unsigned nverts, - void(*position)(const unsigned, double*, void* ctx), - void* ctx, - struct senc_scene** out_scn) -{ - struct senc_scene* scn = NULL; - /* Tables to detect duplicates */ - struct htable_vrtx unique_vertices; - struct htable_trg unique_triangles; - unsigned i; - res_T res = RES_OK; - - if(!dev || !out_scn || !indices || !position - /* Convention must be set both regarding FRONT/BACK and INSIDE/OUTSIDE */ - || !(conv & (SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_BACK)) - || !(conv & (SENC_CONVENTION_NORMAL_INSIDE | SENC_CONVENTION_NORMAL_OUTSIDE))) - return RES_BAD_ARG; - - scn = MEM_CALLOC(dev->allocator, 1, sizeof(struct senc_scene)); - if(!scn) { - log_err(dev, "%s: could not allocate the StarEnclosures scene.\n", FUNC_NAME); - res = RES_MEM_ERR; - goto error; - } - ref_init(&scn->ref); - SENC(device_ref_get(dev)); - scn->dev = dev; - scn->convention = conv; - scn->ntris = ntris; - scn->next_medium_idx = 0; - scn->nverts = nverts; - darray_triangle_in_init(dev->allocator, &scn->triangles_in); - darray_position_init(dev->allocator, &scn->vertices); - htable_vrtx_init(dev->allocator, &unique_vertices); - htable_trg_init(dev->allocator, &unique_triangles); - darray_side_range_init(dev->allocator, &scn->media_use); - - darray_triangle_enc_init(scn->dev->allocator, &scn->analyze.triangles_enc); - darray_enclosure_init(scn->dev->allocator, &scn->analyze.enclosures); - darray_enc_ids_array_init(scn->dev->allocator, - &scn->analyze.enc_ids_array_by_medium); - darray_frontier_edge_init(scn->dev->allocator, &scn->analyze.frontiers); - /* Enclosure 0 is always defined for infinite */ - OK(darray_enclosure_resize(&scn->analyze.enclosures, 1)); - scn->analyze.enclosures_count = 1; - - if(!scn || !indices || !position || !nverts || !ntris) { - res = RES_BAD_ARG; - goto error; - } - - OK(darray_position_reserve(&scn->vertices, scn->nverts)); - OK(darray_triangle_in_reserve(&scn->triangles_in, scn->ntris)); - OK(htable_vrtx_reserve(&unique_vertices, scn->nverts)); - OK(htable_trg_reserve(&unique_triangles, scn->ntris)); - - /* Get vertices */ - FOR_EACH(i, 0, nverts) { - vrtx_id_t* p_vrtx; - union double3 tmp; - /* API: position needs an unsigned */ - position(i, tmp.vec, ctx); - p_vrtx = htable_vrtx_find(&unique_vertices, &tmp); - if(p_vrtx) { - /* Duplicate vertex */ - log_err(scn->dev, "%s: vertex %u is a duplicate.\n", - FUNC_NAME, i); - res = RES_BAD_ARG; - goto error; - } - /* New vertex */ - ASSERT(i == htable_vrtx_size_get(&unique_vertices)); - OK(darray_position_push_back(&scn->vertices, &tmp)); - OK(htable_vrtx_set(&unique_vertices, &tmp, &i)); - } - /* Get triangles */ - FOR_EACH(i, 0, ntris) { - int j; - unsigned med[2] = { SENC_UNSPECIFIED_MEDIUM, SENC_UNSPECIFIED_MEDIUM }; - unsigned ind[3]; - union vrtx_id3 trg_key; - struct triangle_in tmp; - trg_id_t* p_trg; - indices(i, ind, ctx); /* API: indices need unsigneds */ - FOR_EACH(j, 0, 3) { - if(ind[j] >= nverts) { - log_err(scn->dev, "%s: triangle %u uses invalid vertex id %u.\n", - FUNC_NAME, i, ind[j]); - res = RES_BAD_ARG; - goto error; - } - ASSERT(ind[j] <= VRTX_MAX__); - tmp.vertice_id[j] = (vrtx_id_t)ind[j]; - } - if(tmp.vertice_id[0] == tmp.vertice_id[1] - || tmp.vertice_id[0] == tmp.vertice_id[2] - || tmp.vertice_id[1] == tmp.vertice_id[2]) - { - log_err(scn->dev, "%s: triangle %u is degenerated.\n", - FUNC_NAME, i); - res = RES_BAD_ARG; - goto error; - } - /* Get media */ - if(media) media(i, med, ctx); /* API: media needs an unsigned */ - trg_make_key(&trg_key, tmp.vertice_id); - p_trg = htable_trg_find(&unique_triangles, &trg_key); - if(p_trg) { - /* Duplicate triangle */ - log_err(scn->dev, "%s: triangle %u is a duplicate.\n", - FUNC_NAME, i); - res = RES_BAD_ARG; - goto error; - } - /* New triangle */ - ASSERT(i == htable_trg_size_get(&unique_triangles)); - OK(htable_trg_set(&unique_triangles, &trg_key, &i)); - FOR_EACH(j, 0, 2) { - struct side_range* media_use; - unsigned m_idx = (med[j] == SENC_UNSPECIFIED_MEDIUM) ? 0 : med[j] + 1; - tmp.medium[j] = (medium_id_t)med[j]; - if(m_idx >= scn->next_medium_idx) { - scn->next_medium_idx = m_idx; - darray_side_range_resize(&scn->media_use, 1 + m_idx); - } - /* media_use 0 is for SENC_UNSPECIFIED_MEDIUM */ - media_use = darray_side_range_data_get(&scn->media_use) + m_idx; - media_use->first = - MMIN(media_use->first, TRGIDxSIDE_2_TRGSIDE((trg_id_t)i, j)); - ASSERT(media_use->first < 2 * (scn->ntris + 1)); - media_use->last = - MMAX(media_use->last, TRGIDxSIDE_2_TRGSIDE((trg_id_t)i, j)); - ASSERT(media_use->last < 2 * (scn->ntris + 1)); - ASSERT(media_use->first <= media_use->last); - } - OK(darray_triangle_in_push_back(&scn->triangles_in, &tmp)); - } - - OK(darray_enc_ids_array_resize(&scn->analyze.enc_ids_array_by_medium, - 1 + scn->next_medium_idx)); /* +1 is for unspecified */ - /* Proceed to the analyze */ - OK(scene_analyze(scn)); - -exit: - htable_vrtx_release(&unique_vertices); - htable_trg_release(&unique_triangles); - if(scn) *out_scn = scn; - return res; - -error: - if(scn) { - SENC(scene_ref_put(scn)); - scn = NULL; - } - goto exit; -} - -res_T -senc_scene_get_convention - (const struct senc_scene* scn, - int* convention) -{ - if(!scn || !convention) return RES_BAD_ARG; - *convention = scn->convention; - return RES_OK; -} - -res_T -senc_scene_get_triangles_count - (const struct senc_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - *count = scn->ntris; - return RES_OK; -} - -res_T -senc_scene_get_triangle - (const struct senc_scene* scn, - const unsigned itri, - unsigned indices[3]) -{ - const struct triangle_in* trg; - int i; - if(!scn || !indices - || itri >= darray_triangle_in_size_get(&scn->triangles_in)) - return RES_BAD_ARG; - trg = darray_triangle_in_cdata_get(&scn->triangles_in) + itri; - - FOR_EACH(i, 0, 3) { - ASSERT(trg->vertice_id[i] < UINT_MAX); - indices[i] = (unsigned)trg->vertice_id[i]; /* Back to API type */ - } - return RES_OK; -} - -res_T -senc_scene_get_triangle_media - (const struct senc_scene* scn, - const unsigned itri, - unsigned media[2]) -{ - const struct triangle_in* trg; - int i; - if(!scn || !media - || itri >= darray_triangle_in_size_get(&scn->triangles_in)) - return RES_BAD_ARG; - trg = darray_triangle_in_cdata_get(&scn->triangles_in) + itri; - - FOR_EACH(i, 0, 2) { - ASSERT(trg->vertice_id[i] < UINT_MAX); - media[i] = (unsigned)trg->medium[i]; /* Back to API type */ - } - return RES_OK; -} - -res_T -senc_scene_get_vertices_count - (const struct senc_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - *count = scn->nverts; - return RES_OK; -} - -res_T -senc_scene_get_vertex - (const struct senc_scene* scn, - const unsigned ivert, - double coord[3]) -{ - const union double3* v; - if(!scn || !coord - || ivert >= darray_position_size_get(&scn->vertices)) - return RES_BAD_ARG; - - v = darray_position_cdata_get(&scn->vertices) + ivert; - d3_set(coord, v->vec); - return RES_OK; -} - -res_T -senc_scene_ref_get(struct senc_scene* scn) -{ - if(!scn) return RES_BAD_ARG; - ref_get(&scn->ref); - return RES_OK; -} - -res_T -senc_scene_ref_put(struct senc_scene* scn) -{ - if(!scn) return RES_BAD_ARG; - ref_put(&scn->ref, scene_release); - return RES_OK; -} diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c @@ -1,1347 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "senc_device_c.h" -#include "senc_scene_c.h" -#include "senc_scene_analyze_c.h" -#include "senc_internal_types.h" - -#include <rsys/rsys.h> -#include <rsys/float3.h> -#include <rsys/double33.h> -#include <rsys/mem_allocator.h> -#include <rsys/hash_table.h> -#include <rsys/dynamic_array.h> -#include <rsys/dynamic_array_uchar.h> -#include <rsys/clock_time.h> - -#include <star/s3d.h> - -#include <omp.h> -#include <limits.h> -#include <stdlib.h> - -#define CC_DESCRIPTOR_NULL__ {\ - CHAR_MAX, VRTX_NULL__, 0,\ - CC_ID_NONE, CC_GROUP_ROOT_NONE, ENCLOSURE_NULL__,\ - { TRG_NULL__, 0},\ - NULL\ -} -#ifdef COMPILER_GCC - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif -const struct cc_descriptor CC_DESCRIPTOR_NULL = CC_DESCRIPTOR_NULL__; -#ifdef COMPILER_GCC - #pragma GCC diagnostic pop -#endif - -#define DARRAY_NAME component_id -#define DARRAY_DATA component_id_t -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * Helper function - ******************************************************************************/ -static INLINE int -neighbour_cmp(const void* w1, const void* w2) -{ - const double a1 = ((struct neighbour_info*)w1)->angle; - const double a2 = ((struct neighbour_info*)w2)->angle; - return (a1 > a2) - (a1 < a2); -} - -static side_id_t -get_side_not_in_connex_component - (const side_id_t last_side, - const struct trgside* trgsides, - const unsigned char* processed, - side_id_t* first_side_not_in_component, - const medium_id_t medium) -{ - ASSERT(trgsides && processed && first_side_not_in_component); - { - side_id_t i = *first_side_not_in_component; - while (i <= last_side - && (trgsides[i].medium != medium - || (processed[TRGSIDE_2_TRG(i)] & TRGSIDE_2_SIDEFLAG(i)))) - ++i; - - *first_side_not_in_component = i + 1; - if(i > last_side) return SIDE_NULL__; - return i; - } -} - -static void -get_scn_indices(const unsigned itri, unsigned ids[3], void* ctx) { - int i; - const struct senc_scene* scene = ctx; - const struct triangle_in* trg = - darray_triangle_in_cdata_get(&scene->triangles_in) + itri; - FOR_EACH(i, 0, 3) { - ASSERT(trg->vertice_id[i] < scene->nverts); - ids[i] = (unsigned)trg->vertice_id[i]; /* Back to API type */ - } -} - -static void -get_scn_position(const unsigned ivert, float pos[3], void* ctx) { - const struct senc_scene* scene = ctx; - const union double3* pt = - darray_position_cdata_get(&scene->vertices) + ivert; - f3_set_d3(pos, pt->vec); -} - -static int -self_hit_filter - (const struct s3d_hit* hit, - const float ray_org[3], - const float ray_dir[3], - void* ray_data, - void* filter_data) -{ - const struct darray_triangle_comp* triangles_comp = filter_data; - const component_id_t* origin_component = ray_data; - const struct triangle_comp* hit_trg_comp; - - (void)ray_org; (void)ray_dir; - ASSERT(hit && triangles_comp && origin_component); - ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(triangles_comp)); - hit_trg_comp = darray_triangle_comp_cdata_get(triangles_comp) - + hit->prim.prim_id; - return (hit_trg_comp->component[SENC_FRONT] == *origin_component - || hit_trg_comp->component[SENC_BACK] == *origin_component); - -} - -static void -extract_connex_components - (struct senc_scene* scn, - struct trgside* trgsides, - struct darray_ptr_component_descriptor* connex_components, - const struct darray_triangle_tmp* triangles_tmp_array, - struct darray_triangle_comp* triangles_comp_array, - struct s3d_scene_view** s3d_view, - ATOMIC* component_count, - /* Shared error status. - * We accept to overwrite an error with a different error */ - res_T* p_res) -{ - /* This function is called from an omp parallel block and executed - * concurrently. */ - struct mem_allocator* alloc; - int64_t m_idx; - struct darray_side_id stack; - struct darray_side_id ids_of_sides_around_max_z_vertex; - const union double3* positions; - const struct triangle_tmp* triangles_tmp; - struct triangle_comp* triangles_comp; - /* An array to flag sides when processed */ - unsigned char* processed; - /* An array to store the component being processed */ - struct darray_side_id current_component; - /* A bool array to store media of the component being processed */ - unsigned char* current_media = NULL; - size_t sz, ii; - - ASSERT(scn && trgsides && connex_components && triangles_tmp_array - && triangles_comp_array && s3d_view && component_count && p_res); - alloc = scn->dev->allocator; - positions = darray_position_cdata_get(&scn->vertices); - triangles_tmp = darray_triangle_tmp_cdata_get(triangles_tmp_array); - triangles_comp = darray_triangle_comp_data_get(triangles_comp_array); - darray_side_id_init(alloc, &stack); - darray_side_id_init(alloc, &ids_of_sides_around_max_z_vertex); - darray_side_id_init(alloc, &current_component); - processed = MEM_CALLOC(alloc, scn->ntris, sizeof(unsigned char)); - if(!processed) { - *p_res = RES_MEM_ERR; - return; - } - -#ifndef NDEBUG - #pragma omp single - { - trg_id_t t_; - int s; - ASSERT(darray_ptr_component_descriptor_size_get(connex_components) == 0); - FOR_EACH(t_, 0, scn->ntris) { - const struct triangle_in* trg_in = - darray_triangle_in_cdata_get(&scn->triangles_in) + t_; - const struct side_range* media_use - = darray_side_range_cdata_get(&scn->media_use); - FOR_EACH(s, 0, 2) { - const side_id_t side = TRGIDxSIDE_2_TRGSIDE(t_, s); - medium_id_t medium = trg_in->medium[s]; - m_idx = (medium == SENC_UNSPECIFIED_MEDIUM) ? 0 : medium + 1; - ASSERT(media_use[m_idx].first <= side && side - <= media_use[m_idx].last); - } - } - } /* Implicit barrier here */ -#endif - - /* We loop on sides to build connex components. */ - #pragma omp for schedule(dynamic) nowait - /* Process all media, including unspecified */ - for(m_idx = 0; m_idx < 1 + (int64_t)scn->next_medium_idx; m_idx++) { - const medium_id_t medium - = m_idx ? (medium_id_t)(m_idx - 1) : SENC_UNSPECIFIED_MEDIUM; - /* media_use 0 is for SENC_UNSPECIFIED_MEDIUM, n+1 is for n */ - const struct side_range* media_use = - darray_side_range_cdata_get(&scn->media_use) + m_idx; - /* Any not-already-used side is used as a starting point */ - side_id_t first_side_not_in_component = media_use->first; - double max_nz; - side_id_t max_nz_side_id = SIDE_NULL__; - const side_id_t last_side = media_use->last; - int component_canceled = 0; - res_T tmp_res = RES_OK; - ATOMIC id; - - if(*p_res != RES_OK) continue; - if(first_side_not_in_component == SIDE_NULL__) - continue; /* Unused medium */ - ASSERT(first_side_not_in_component < 2 * scn->ntris); - ASSERT(darray_side_id_size_get(&stack) == 0); - ASSERT(darray_side_id_size_get(&current_component) == 0); - for(;;) { /* Process all components for this medium */ - const side_id_t start_side_id = get_side_not_in_connex_component - (last_side, trgsides, processed, &first_side_not_in_component, medium); - side_id_t crt_side_id = start_side_id; - side_id_t last_side_id = start_side_id; - vrtx_id_t max_z_vrtx_id = VRTX_NULL__; - struct cc_descriptor *cc; - double max_z = -DBL_MAX; - component_canceled = 0; - ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->ntris); - darray_side_id_clear(&current_component); - - if(*p_res != RES_OK) break; - if(start_side_id == SIDE_NULL__) - break; /* start_side_id=SIDE_NULL__ => component done! */ - -#ifndef NDEBUG - { - trg_id_t tid = TRGSIDE_2_TRG(start_side_id); - enum senc_side s = TRGSIDE_2_SIDE(start_side_id); - medium_id_t side_med - = darray_triangle_in_data_get(&scn->triangles_in)[tid].medium[s]; - ASSERT(side_med == medium); - } -#endif - - /* Reuse array if possible, or create a new one */ - if(current_media) { - /* current_media 0 is for SENC_UNSPECIFIED_MEDIUM, n+1 is for n */ - memset(current_media, 0, 1 + scn->next_medium_idx); - } else { - current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, - sizeof(*current_media)); - if(!current_media) { - *p_res = RES_MEM_ERR; - continue; - } - } - current_media[m_idx] = 1; - for(;;) { /* Process all sides of this component */ - int i; - enum side_flag crt_side_flag = TRGSIDE_2_SIDEFLAG(crt_side_id); - struct trgside* crt_side = trgsides + crt_side_id; - const trg_id_t crt_trg_id = TRGSIDE_2_TRG(crt_side_id); - const struct triangle_in* trg_in = - darray_triangle_in_cdata_get(&scn->triangles_in) + crt_trg_id; - unsigned char* trg_used = processed + crt_trg_id; - const struct triangle_tmp* const trg_tmp = triangles_tmp + crt_trg_id; - ASSERT(crt_trg_id < scn->ntris); - - if(*p_res != RES_OK) break; - - /* Record Zmax information - * Keep track of the appropriate vertex of the component in order - * to cast a ray at the component grouping step of the algorithm. - * The most appropriate vertex is (the) one with the greater Z - * coordinate. */ - if(max_z < trg_tmp->max_z) { - /* New best vertex */ - max_z = trg_tmp->max_z; - /* New vertex: reset list of sides */ - darray_side_id_clear(&ids_of_sides_around_max_z_vertex); - - /* Select a vertex with z == max_z */ - FOR_EACH(i, 0, 3) { - if(max_z == positions[trg_in->vertice_id[i]].pos.z) { - max_z_vrtx_id = trg_in->vertice_id[i]; - break; - } - } - ASSERT(i < 3); /* Found one */ - /* List of sides using the vertex */ - OK2(darray_side_id_push_back(&ids_of_sides_around_max_z_vertex, - &crt_side_id)); - } else if(max_z == trg_tmp->max_z) { - /* Does this triangle use the currently selected max_z vertex? */ - FOR_EACH(i, 0, 3) { - if(max_z_vrtx_id == trg_in->vertice_id[i]) { - /* List of sides using the vertex */ - OK2(darray_side_id_push_back(&ids_of_sides_around_max_z_vertex, - &crt_side_id)); - break; - } - } - } - - /* Record crt_side both as component and triangle level */ - if((*trg_used & crt_side_flag) == 0) { - OK2(darray_side_id_push_back(&current_component, &crt_side_id)); - *trg_used = *trg_used | (unsigned char)crt_side_flag; - } - - /* Store neighbour's sides in a waiting stack */ - FOR_EACH(i, 0, 3) { - side_id_t neighbour_id = crt_side->facing_side_id[i]; - trg_id_t nbour_trg_id = TRGSIDE_2_TRG(neighbour_id); - enum side_flag nbour_side_id = TRGSIDE_2_SIDEFLAG(neighbour_id); - unsigned char* nbour_used = processed + nbour_trg_id; - const struct trgside* neighbour = trgsides + neighbour_id; - medium_id_t nbour_med_idx = (neighbour->medium == SENC_UNSPECIFIED_MEDIUM) - ? 0 : neighbour->medium + 1; - if(neighbour->medium < medium - || (*nbour_used & SIDE_CANCELED_FLAG(nbour_side_id))) - { - /* 1) Not the same medium. - * Neighbour's medium id is less than current medium: the whole - * component is to be processed by another thread (possibly the one - * associated with neighbour's medium). - * 2) Neighbour was canceled: no need to replay the component - * again as it will eventually rediscover the side with low medium - * id and recancel all the work in progress */ - component_canceled = 1; - darray_side_id_clear(&stack); - /* Don't cancel used flags as all these sides will get us back to - * (at least) the neighbour side we have just discovered, that will - * cancel them again and again */ - sz = darray_side_id_size_get(&current_component); - FOR_EACH(ii, 0, sz) { - side_id_t used_side - = darray_side_id_cdata_get(&current_component)[ii]; - trg_id_t used_trg_id = TRGSIDE_2_TRG(used_side); - enum side_flag used_side_flag - = TRGSIDE_2_SIDEFLAG(used_side); - unsigned char* used = processed + used_trg_id; - ASSERT(*used & (unsigned char)used_side_flag); - /* Set the used flag for sides in cancelled component as leading - * to further cancellations */ - *used |= SIDE_CANCELED_FLAG(used_side_flag); - } - - goto canceled; - } - if(*nbour_used & nbour_side_id) continue; /* Already processed */ - /* Mark neighbour as processed and stack it */ - *nbour_used |= (unsigned char)nbour_side_id; - OK2(darray_side_id_push_back(&stack, &neighbour_id)); - OK2(darray_side_id_push_back(&current_component, &neighbour_id)); - current_media[nbour_med_idx] = 1; - } - sz = darray_side_id_size_get(&stack); - if(sz == 0) break; /* Empty stack => component is done! */ - crt_side_id = darray_side_id_cdata_get(&stack)[sz - 1]; - darray_side_id_pop_back(&stack); - last_side_id = MMAX(last_side_id, crt_side_id); - } - canceled: - if(component_canceled) continue; - - /* Register the new component and get it initialized */ - cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor)); - if(!cc) *p_res = RES_MEM_ERR; - if(*p_res != RES_OK) break; - - ASSERT(medium == trgsides[start_side_id].medium); - ASSERT(max_z_vrtx_id != VRTX_NULL__); - cc_descriptor_init(alloc, cc); - id = ATOMIC_INCR(component_count) - 1; - ASSERT(id <= COMPONENT_MAX__); - cc->cc_id = (component_id_t)id; - sz = darray_side_id_size_get(&current_component); - ASSERT(sz <= SIDE_MAX__); - cc->side_count = (side_id_t)sz; - cc->side_range.first = start_side_id; - cc->side_range.last = last_side_id; - cc->max_z_vrtx_id = max_z_vrtx_id; - /* Tranfer ownership of the array to component */ - ASSERT(!cc->media && current_media); - cc->media = current_media; - current_media = NULL; - - /* Write component membership in the global structure - * No need for sync here as an unique thread writes a given side */ - {STATIC_ASSERT(sizeof(cc->cc_id) >= 4, Cannot_write_IDs_sync_free);} - ASSERT(IS_ALIGNED(triangles_comp->component, sizeof(cc->cc_id))); - FOR_EACH(ii, 0, sz) { - const side_id_t s = darray_side_id_cdata_get(&current_component)[ii]; - trg_id_t tid = TRGSIDE_2_TRG(s); - enum senc_side sid = TRGSIDE_2_SIDE(s); - component_id_t* cmp = triangles_comp[tid].component; - ASSERT(cmp[sid] == COMPONENT_NULL__); - ASSERT(trgsides[s].medium >= medium); - cmp[sid] = cc->cc_id; - } - - /* Compute the normal at the max_z vertex. */ - max_nz = 0; - sz = darray_side_id_size_get(&ids_of_sides_around_max_z_vertex); - ASSERT(sz > 0); - FOR_EACH(ii, 0, sz) { - const side_id_t side_id = - darray_side_id_cdata_get(&ids_of_sides_around_max_z_vertex)[ii]; - const trg_id_t trg_id = TRGSIDE_2_TRG(side_id); - enum senc_side s = TRGSIDE_2_SIDE(side_id); - const struct triangle_in* trg_in = - darray_triangle_in_cdata_get(&scn->triangles_in) + trg_id; - const struct triangle_comp* trg_comp = triangles_comp + trg_id; - const union double3* vertices = - darray_position_cdata_get(&scn->vertices); - double edge0[3], edge1[3], normal[3], norm; - - /* To ensure that triangles with 2 sides in the component total to 0 - * regardless of numeric accuracy, we need to prevent them to - * contribute (remember than x + y - y == x can be false). */ - ASSERT(trg_comp->component[s] == cc->cc_id); (void)s; - if(trg_comp->component[SENC_FRONT] == trg_comp->component[SENC_BACK]) - continue; - - d3_sub(edge0, vertices[trg_in->vertice_id[1]].vec, - vertices[trg_in->vertice_id[0]].vec); - d3_sub(edge1, vertices[trg_in->vertice_id[2]].vec, - vertices[trg_in->vertice_id[0]].vec); - d3_cross(normal, edge0, edge1); - norm = d3_normalize(normal, normal); - ASSERT(norm); (void)norm; - - if(fabs(max_nz) < fabs(normal[2])) { - max_nz_side_id = side_id; - max_nz = normal[2]; - } - } - if(max_nz == 0) cc->is_outer_border = 0; - else { - if(TRGSIDE_IS_FRONT(max_nz_side_id) - == ((scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0)) { - /* Geom normal points towards the component */ - cc->is_outer_border = (max_nz < 0); - } else { - /* Geom normal points away from the component */ - cc->is_outer_border = (max_nz > 0); - } - } - - /* Need to synchronize connex_components growth as this global structure - * is accessed by multipe threads */ - #pragma omp critical - { - struct cc_descriptor** components; - sz = darray_ptr_component_descriptor_size_get(connex_components); - if(sz <= cc->cc_id) { - tmp_res = darray_ptr_component_descriptor_resize(connex_components, - 1 + cc->cc_id); - if(tmp_res != RES_OK) *p_res = tmp_res; - } - if(*p_res == RES_OK) { - /* Don't set the pointer before resize as this can lead to move data */ - components = - darray_ptr_component_descriptor_data_get(connex_components); - ASSERT(components[cc->cc_id] == NULL); - components[cc->cc_id] = cc; - } - } - } - tmp_error: - if(tmp_res != RES_OK) *p_res = tmp_res; - } /* No barrier here */ - - MEM_RM(alloc, processed); - MEM_RM(alloc, current_media); - darray_side_id_release(&current_component); - darray_side_id_release(&stack); - darray_side_id_release(&ids_of_sides_around_max_z_vertex); - - /* The first thread here creates the s3d view */ - #pragma omp single nowait - if(*p_res == RES_OK) { - res_T res = RES_OK; - struct s3d_device* s3d = NULL; - struct s3d_scene* s3d_scn = NULL; - struct s3d_shape* s3d_shp = NULL; - struct s3d_vertex_data attribs; - - attribs.type = S3D_FLOAT3; - attribs.usage = S3D_POSITION; - attribs.get = get_scn_position; - - /* Put geometry in a 3D view */ - OK(s3d_device_create(scn->dev->logger, alloc, 0, &s3d)); - OK(s3d_scene_create(s3d, &s3d_scn)); - OK(s3d_shape_create_mesh(s3d, &s3d_shp)); - - /* Back to API type for ntris and nverts */ - ASSERT(scn->ntris < UINT_MAX); - ASSERT(scn->nverts < UINT_MAX); - OK(s3d_mesh_setup_indexed_vertices(s3d_shp, - (unsigned)scn->ntris, get_scn_indices, - (unsigned)scn->nverts, &attribs, 1, scn)); - s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter, - triangles_comp_array); - OK(s3d_scene_attach_shape(s3d_scn, s3d_shp)); - OK(s3d_scene_view_create(s3d_scn, S3D_TRACE, s3d_view)); - error: - if(res != RES_OK) *p_res = res; - if(s3d) S3D(device_ref_put(s3d)); - if(s3d_scn) S3D(scene_ref_put(s3d_scn)); - if(s3d_shp) S3D(shape_ref_put(s3d_shp)); - } - -#ifndef NDEBUG - /* Need to wait for all threads done to be able to check stuff */ - #pragma omp barrier - if(*p_res != RES_OK) return; - #pragma omp single - { - trg_id_t t_; - component_id_t c; - ASSERT(ATOMIC_GET(component_count) == - (int)darray_ptr_component_descriptor_size_get(connex_components)); - FOR_EACH(t_, 0, scn->ntris) { - struct triangle_comp* trg_comp = - darray_triangle_comp_data_get(triangles_comp_array) + t_; - ASSERT(trg_comp->component[SENC_FRONT] != COMPONENT_NULL__); - ASSERT(trg_comp->component[SENC_BACK] != COMPONENT_NULL__); - } - FOR_EACH(c, 0, ATOMIC_GET(component_count)) { - struct cc_descriptor** components = - darray_ptr_component_descriptor_data_get(connex_components); - ASSERT(components[c] != NULL && components[c]->cc_id == c); - } - } /* Implicit barrier here */ -#endif -} - -static void -group_connex_components - (struct senc_scene* scn, - struct trgside* trgsides, - struct darray_triangle_comp* triangles_comp, - struct darray_ptr_component_descriptor* connex_components, - struct s3d_scene_view* s3d_view, - ATOMIC* next_enclosure_id, - /* Shared error status. - * We accept to overwrite an error with a different error */ - res_T* res) -{ - /* This function is called from an omp parallel block and executed - * concurrently. */ - struct cc_descriptor** descriptors; - const union double3* positions; - size_t tmp; - component_id_t cc_count; - int64_t ccc; - - (void)trgsides; - ASSERT(scn && trgsides && triangles_comp && connex_components - && s3d_view && next_enclosure_id && res); - ASSERT(scn->analyze.enclosures_count == 1); - - descriptors = darray_ptr_component_descriptor_data_get(connex_components); - tmp = darray_ptr_component_descriptor_size_get(connex_components); - ASSERT(tmp <= COMPONENT_MAX__); - cc_count = (component_id_t)tmp; - positions = darray_position_cdata_get(&scn->vertices); - - /* Cast rays to find links between connex components */ - #pragma omp for - for(ccc = 0; ccc < (int64_t)cc_count; ccc++) { - res_T tmp_res = RES_OK; - component_id_t c = (component_id_t)ccc; - struct s3d_hit hit = S3D_HIT_NULL; - float origin[3]; - const float dir[3] = { 0, 0, 1 }; - const float range[2] = { 0, FLT_MAX }; - struct cc_descriptor* const cc = descriptors[c]; - component_id_t self_hit_component = cc->cc_id; - const double* max_vrtx; - - if(*res != RES_OK) continue; - ASSERT(cc->cc_id == c); - ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE); - ASSERT(cc->max_z_vrtx_id < scn->nverts); - - max_vrtx = positions[cc->max_z_vrtx_id].vec; - if(cc->is_outer_border) { - ATOMIC id; - /* Don't need to cast a ray */ - cc->cc_group_root = cc->cc_id; /* New group with self as root */ - id = ATOMIC_INCR(next_enclosure_id) - 1; - ASSERT(id <= ENCLOSURE_MAX__); - cc->enclosure_id = (enclosure_id_t)id; - continue; - } - - f3_set_d3(origin, max_vrtx); - /* Self-hit data: self hit if hit this component "on the other side" */ - tmp_res = s3d_scene_view_trace_ray(s3d_view, origin, dir, range, - &self_hit_component, &hit); - if(tmp_res != RES_OK) { - *res = tmp_res; - continue; - } - /* If no hit, the component is facing an infinite medium */ - if(S3D_HIT_NONE(&hit)) { - cc->cc_group_root = CC_GROUP_ROOT_INFINITE; - cc->enclosure_id = 0; - } else { - /* If hit, group this component */ - const trg_id_t hit_trg_id = (trg_id_t)hit.prim.prim_id; - const struct triangle_comp* hit_trg_comp = - darray_triangle_comp_cdata_get(triangles_comp) + hit_trg_id; - enum senc_side hit_side = - ((hit.normal[2] < 0) /* Facing geometrical normal of hit */ - == ((scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0)) - /* Warning: following Embree 2 convention for geometrical normals, - * the Star3D hit normal is left-handed while star-enclosure uses - * right-handed convention */ - ? SENC_BACK : SENC_FRONT; - ASSERT(hit.normal[2] != 0); - ASSERT(hit_trg_id < scn->ntris); - - /* Not really the root until following links */ - cc->cc_group_root = hit_trg_comp->component[hit_side]; - ASSERT(cc->cc_group_root < cc_count); - } - } - /* Implicit barrier here */ - ASSERT(ATOMIC_GET(next_enclosure_id) < ENCLOSURE_MAX__); - if(*res != RES_OK) return; - - /* One thread post-processes links to group connex components */ - #pragma omp single - { - res_T tmp_res = RES_OK; - scn->analyze.enclosures_count = (enclosure_id_t)ATOMIC_GET(next_enclosure_id); - tmp_res = darray_enclosure_resize(&scn->analyze.enclosures, - scn->analyze.enclosures_count); - if(tmp_res != RES_OK) { - *res = tmp_res; - } else { - struct enclosure_data* enclosures - = darray_enclosure_data_get(&scn->analyze.enclosures); - FOR_EACH(ccc, 0, cc_count) { - component_id_t c = (component_id_t)ccc; - struct cc_descriptor* const cc = descriptors[c]; - const struct cc_descriptor* other_desc = cc; - struct enclosure_data* enc; -#ifndef NDEBUG - component_id_t cc_cpt = 0; -#endif - - while(other_desc->enclosure_id == CC_GROUP_ID_NONE) { - ASSERT(other_desc->cc_group_root < cc_count); - other_desc = descriptors[other_desc->cc_group_root]; - /* Cannot have more components in cc than cc_count! */ - ASSERT(++cc_cpt <= cc_count); - } - ASSERT(other_desc->cc_group_root != CC_GROUP_ROOT_NONE); - ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE); - cc->cc_group_root = other_desc->cc_group_root; - cc->enclosure_id = other_desc->enclosure_id; - enc = enclosures + cc->enclosure_id; - ++enc->cc_count; - /* Linked list of componnents */ - enc->first_component = cc->cc_id; - enc->side_range.first = MMIN(enc->side_range.first, cc->side_range.first); - enc->side_range.last = MMAX(enc->side_range.last, cc->side_range.last); - enc->side_count += cc->side_count; - tmp_res = bool_array_of_media_merge(&enc->tmp_enclosed_media, cc->media, - scn->next_medium_idx + 1); - if(tmp_res != RES_OK) { - *res = tmp_res; - break; - } - } - } - } - /* Implicit barrier here */ -} - -static void -collect_and_link_neighbours - (struct senc_scene* scn, - struct trgside* trgsides, - struct darray_triangle_tmp* triangles_tmp_array, - struct darray_frontier_edge* frontiers, - /* Shared error status. - * We accept to overwrite an error with a different error */ - res_T* res) -{ - /* This function is called from an omp parallel block and executed - * concurrently. */ - const struct triangle_in* triangles_in; - struct triangle_tmp* triangles_tmp; - const union double3* vertices; - const int thread_count = omp_get_num_threads(); - const int rank = omp_get_thread_num(); - /* Htable used to give an id to edges */ - struct htable_edge_id edge_ids; - /* Array to keep neighbourhood of edges - * Resize/Push operations on neighbourhood_by_edge are valid in the - * openmp block because a given neighbourhood is only processed - * by a single thread */ - struct darray_neighbourhood neighbourhood_by_edge; - edge_id_t edge_count; - edge_id_t nbedges_guess; - edge_id_t e; - trg_id_t t; - size_t sz; - res_T tmp_res; - - ASSERT(scn && trgsides && triangles_tmp_array && frontiers && res); - ASSERT((size_t)scn->nverts + (size_t)scn->ntris + 2 <= EDGE_MAX__); - - htable_edge_id_init(scn->dev->allocator, &edge_ids); - darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); - - triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); - triangles_tmp = darray_triangle_tmp_data_get(triangles_tmp_array); - vertices = darray_position_cdata_get(&scn->vertices); - - ASSERT(scn->ntris == darray_triangle_tmp_size_get(triangles_tmp_array)); - - /* Make some room for edges. */ - nbedges_guess = 4 + (thread_count == 1 - ? (edge_id_t)(scn->nverts + scn->ntris) - : (edge_id_t)((scn->nverts + scn->ntris) / (0.75 * thread_count))); - OK2(darray_neighbourhood_reserve(&neighbourhood_by_edge, nbedges_guess)); - OK2(htable_edge_id_reserve(&edge_ids, nbedges_guess)); - - /* Loop on triangles to register edges. - * All threads considering all the edges and processing some */ - FOR_EACH(t, 0, scn->ntris) { - struct trg_edge edge; - unsigned char ee; - FOR_EACH(ee, 0, 3) { - edge_id_t* p_id; - size_t n_sz; - struct edge_neighbourhood* neighbourhood; - struct neighbour_info* info; - const vrtx_id_t v0 = triangles_in[t].vertice_id[ee]; - const vrtx_id_t v1 = triangles_in[t].vertice_id[(ee + 1) % 3]; - /* Process only "my" edges! */ - const int64_t h = - /* v0,v1 and v1,v0 must give the same hash!!! */ - v0 + v1 + (int64_t)MMIN(v0, v1); - if(h % thread_count != rank) continue; - /* Create edge. */ - set_edge(v0, v1, &edge, &triangles_tmp[t].reversed_edge[ee]); - /* Find edge id; create it if not already done. */ - p_id = htable_edge_id_find(&edge_ids, &edge); - if(p_id) { - neighbourhood = - darray_neighbourhood_data_get(&neighbourhood_by_edge) + *p_id; - ASSERT(neighbourhood->edge.vrtx0 == edge.vrtx0 - && neighbourhood->edge.vrtx1 == edge.vrtx1); - } else { - /* Create id */ - edge_id_t id; - sz = htable_edge_id_size_get(&edge_ids); - ASSERT(sz <= EDGE_MAX__); - id = (edge_id_t)sz; - ASSERT(htable_edge_id_size_get(&edge_ids) - == darray_neighbourhood_size_get(&neighbourhood_by_edge)); - OK2(htable_edge_id_set(&edge_ids, &edge, &id)); - OK2(darray_neighbourhood_resize(&neighbourhood_by_edge, 1 + sz)); - neighbourhood = darray_neighbourhood_data_get(&neighbourhood_by_edge) + sz; - /* Add neighbour info to a newly created edge's neighbour list */ - neighbourhood->edge = edge; - ASSERT(darray_neighbour_size_get(&neighbourhood->neighbours) == 0); - /* Just a guess: few edges will have less than 2 neighbours */ - OK2(darray_neighbour_reserve(&neighbourhood->neighbours, 2)); - } - /* Add neighbour info to neighbourhood */ - n_sz = darray_neighbour_size_get(&neighbourhood->neighbours); - OK2(darray_neighbour_resize(&neighbourhood->neighbours, 1 + n_sz)); - info = darray_neighbour_data_get(&neighbourhood->neighbours) + n_sz; - info->trg_id = t; - info->common_edge_rank = ee; - } - } /* No barrier here. */ - - /* Loop on collected edges. - * For each edge sort triangle sides by rotation angle - * and connect neighbours. */ - sz = darray_neighbourhood_size_get(&neighbourhood_by_edge); - ASSERT(sz <= EDGE_MAX__); - edge_count = (edge_id_t)sz; - FOR_EACH(e, 0, edge_count) { - double edge[3], common_edge[3], basis[9], norm, max_z, maxz_edge, a; - vrtx_id_t v0, v1, v2; - struct edge_neighbourhood* neighbourhood - = darray_neighbourhood_data_get(&neighbourhood_by_edge) + e; - struct darray_neighbour* neighbour_list = &neighbourhood->neighbours; - side_id_t i, neighbour_count; - sz = darray_neighbour_size_get(neighbour_list); - ASSERT(sz > 0 && sz <= SIDE_MAX__); - neighbour_count = (side_id_t)sz; - ASSERT(neighbour_count); - v0 = neighbourhood->edge.vrtx0; - v1 = neighbourhood->edge.vrtx1; - d3_sub(common_edge, vertices[v1].vec, vertices[v0].vec); - maxz_edge = MMAX(vertices[v0].pos.z, vertices[v1].pos.z); - norm = d3_normalize(common_edge, common_edge); - ASSERT(norm); (void)norm; - d33_basis(basis, common_edge); - d33_inverse(basis, basis); - FOR_EACH(i, 0, neighbour_count) { - struct neighbour_info* neighbour_info - = darray_neighbour_data_get(neighbour_list) + i; - const trg_id_t crt_id = neighbour_info->trg_id; - const unsigned char crt_edge = neighbour_info->common_edge_rank; - const struct triangle_in* trg_in = triangles_in + crt_id; - struct triangle_tmp* neighbour = triangles_tmp + crt_id; - union double3 n; /* Geometrical normal to neighbour triangle */ - const int is_reversed = neighbour->reversed_edge[crt_edge]; - v2 = trg_in->vertice_id[(crt_edge + 2) % 3]; - max_z = MMAX(vertices[v2].pos.z, maxz_edge); - ASSERT(neighbour->max_z <= max_z); - neighbour->max_z = max_z; - /* Compute rotation angle around common edge */ - d3_sub(edge, vertices[v2].vec, vertices[v0].vec); - d33_muld3(edge, basis, edge); - ASSERT(d3_len(edge) && (edge[0] || edge[1])); - neighbour_info->angle = atan2(edge[1], edge[0]); - if(is_reversed) - d3(n.vec, +edge[1], -edge[0], 0); - else - d3(n.vec, -edge[1], +edge[0], 0); - if(neighbour_info->angle < 0) neighbour_info->angle += 2 * PI; - - /* Normal orientation calculation. */ - if(neighbour_info->angle <= PI / 4) { - ASSERT(n.pos.y); - neighbour_info->normal_toward_next_neighbour = (n.pos.y > 0); - } else if(neighbour_info->angle <= 3 * PI / 4) { - ASSERT(n.pos.x); - neighbour_info->normal_toward_next_neighbour = (n.pos.x < 0); - } else if(neighbour_info->angle <= 5 * PI / 4) { - ASSERT(n.pos.y); - neighbour_info->normal_toward_next_neighbour = (n.pos.y < 0); - } else if(neighbour_info->angle <= 7 * PI / 4) { - ASSERT(n.pos.x); - neighbour_info->normal_toward_next_neighbour = (n.pos.x > 0); - } else { - ASSERT(n.pos.y); - neighbour_info->normal_toward_next_neighbour = (n.pos.y > 0); - } - } - /* Sort triangles by rotation angle */ - qsort(darray_neighbour_data_get(neighbour_list), neighbour_count, - sizeof(struct neighbour_info), neighbour_cmp); - /* Link sides. - * Create cycles of sides by neighbourhood around common edge. */ - a = -DBL_MAX; - FOR_EACH(i, 0, neighbour_count) { - /* Neighbourhood info for current pair of triangles */ - const struct neighbour_info* current - = darray_neighbour_cdata_get(neighbour_list) + i; - const struct neighbour_info* ccw_neighbour - = darray_neighbour_cdata_get(neighbour_list) + (i + 1) % neighbour_count; - /* Rank of the edge of interest in triangles */ - const unsigned char crt_edge = current->common_edge_rank; - /* Here ccw refers to the rotation around the common edge - * and has nothing to do with vertices order in triangle definition - * nor Front/Back side convention */ - const unsigned char ccw_edge = ccw_neighbour->common_edge_rank; - /* User id of current triangles */ - const trg_id_t crt_id = current->trg_id; - const trg_id_t ccw_id = ccw_neighbour->trg_id; - /* Facing sides of triangles */ - const int front = ((scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0); - const enum senc_side crt_side - = current->normal_toward_next_neighbour == front ? SENC_FRONT : SENC_BACK; - const enum senc_side ccw_side - = ccw_neighbour->normal_toward_next_neighbour == front ? - SENC_BACK : SENC_FRONT; - /* Index of sides in trgsides */ - const side_id_t crt_side_idx = TRGIDxSIDE_2_TRGSIDE(crt_id, crt_side); - const side_id_t ccw_side_idx = TRGIDxSIDE_2_TRGSIDE(ccw_id, ccw_side); - /* Side ptrs */ - struct trgside* const p_crt_side = trgsides + crt_side_idx; - struct trgside* const p_ccw_side = trgsides + ccw_side_idx; - /* Check that angle is a discriminant property */ - ASSERT(a <= current->angle); /* Is sorted */ - if(a == current->angle) { - /* Two consecutive triangles with same angle! */ - const struct neighbour_info* previous; - trg_id_t prev_id; - ASSERT(i > 0); - previous = darray_neighbour_cdata_get(neighbour_list) + i - 1; - prev_id = previous->trg_id; - log_err(scn->dev, - "%s: found 2 overlying triangles (%u & %u).\n", FUNC_NAME, - (unsigned)crt_id, (unsigned)prev_id); - tmp_res = RES_BAD_OP; - goto tmp_error; - } - a = current->angle; - /* Link sides */ - ASSERT(p_crt_side->facing_side_id[crt_edge] == SIDE_NULL__); - ASSERT(p_ccw_side->facing_side_id[ccw_edge] == SIDE_NULL__); - p_crt_side->facing_side_id[crt_edge] = ccw_side_idx; - p_ccw_side->facing_side_id[ccw_edge] = crt_side_idx; - /* Record media */ - ASSERT(p_crt_side->medium == MEDIUM_NULL__ - || p_crt_side->medium == triangles_in[crt_id].medium[crt_side]); - ASSERT(p_ccw_side->medium == MEDIUM_NULL__ - || p_ccw_side->medium == triangles_in[ccw_id].medium[ccw_side]); - p_crt_side->medium = triangles_in[crt_id].medium[crt_side]; - p_ccw_side->medium = triangles_in[ccw_id].medium[ccw_side]; - ASSERT(p_crt_side->medium == SENC_UNSPECIFIED_MEDIUM - || p_crt_side->medium < scn->next_medium_idx); - ASSERT(p_ccw_side->medium == SENC_UNSPECIFIED_MEDIUM - || p_ccw_side->medium < scn->next_medium_idx); - /* Detect triangles that could surround a hole: - * - single triangle on (one of) its edge - * - different media on its sides */ - if(neighbour_count == 1 - && p_crt_side->medium != p_ccw_side->medium) -#pragma omp critical - { - struct trg_edge disc; - log_warn(scn->dev, - "%s: found frontier involving triangle %lu.\n", - FUNC_NAME, (unsigned long)crt_id); - disc.vrtx0 = v0; - disc.vrtx1 = v1; - darray_frontier_edge_push_back(frontiers, &disc); - } - } - } -tmp_error: - if(tmp_res != RES_OK) *res = tmp_res; - /* Threads are allowed to return whitout sync. */ - htable_edge_id_release(&edge_ids); - darray_neighbourhood_release(&neighbourhood_by_edge); -} - -static void -build_result - (struct senc_scene* scn, - const struct darray_ptr_component_descriptor* connex_components, - const struct darray_triangle_comp* triangles_comp_array, - struct darray_frontier_edge* frontiers, - /* Shared error status. - * We accept to overwrite an error with a different error */ - res_T* res) -{ - /* This function is called from an omp parallel block and executed - * concurrently. */ - struct mem_allocator* alloc; - struct cc_descriptor* const* cc_descriptors; - struct enclosure_data* enclosures; - const struct triangle_in* triangles_in; - struct triangle_enc* triangles_enc; - const struct triangle_comp* triangles_comp; - struct htable_vrtx_id vtable; - int output_normal_in, normals_front, normals_back; - int64_t tt; - int64_t ee; - - ASSERT(scn && connex_components && triangles_comp_array && frontiers && res); - - alloc = scn->dev->allocator; - output_normal_in = (scn->convention & SENC_CONVENTION_NORMAL_INSIDE) != 0; - normals_front = (scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0; - normals_back = (scn->convention & SENC_CONVENTION_NORMAL_BACK) != 0; - ASSERT(normals_back != normals_front); - ASSERT(output_normal_in - != ((scn->convention & SENC_CONVENTION_NORMAL_OUTSIDE) != 0)); - ASSERT(darray_ptr_component_descriptor_size_get(connex_components) - <= COMPONENT_MAX__); - cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components); - enclosures = darray_enclosure_data_get(&scn->analyze.enclosures); - triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); - triangles_comp = darray_triangle_comp_cdata_get(triangles_comp_array); - - #pragma omp single - { - res_T tmp_res = - darray_triangle_enc_resize(&scn->analyze.triangles_enc, scn->ntris); - if(tmp_res != RES_OK) *res = tmp_res; - }/* Implicit barrier here. */ - if(*res != RES_OK) return; - triangles_enc = darray_triangle_enc_data_get(&scn->analyze.triangles_enc); - - /* Build global enclosure information */ - #pragma omp for - for(tt = 0; tt < (int64_t)scn->ntris; tt++) { - trg_id_t t = (trg_id_t)tt; - const component_id_t cf_id = triangles_comp[t].component[SENC_FRONT]; - const component_id_t cb_id = triangles_comp[t].component[SENC_BACK]; - const struct cc_descriptor* cf = cc_descriptors[cf_id]; - const struct cc_descriptor* cb = cc_descriptors[cb_id]; - const enclosure_id_t ef_id = cf->enclosure_id; - const enclosure_id_t eb_id = cb->enclosure_id; - ASSERT(triangles_enc[t].enclosure[SENC_FRONT] == ENCLOSURE_NULL__); - triangles_enc[t].enclosure[SENC_FRONT] = ef_id; - ASSERT(triangles_enc[t].enclosure[SENC_BACK] == ENCLOSURE_NULL__); - triangles_enc[t].enclosure[SENC_BACK] = eb_id; - } - /* Implicit barrier here */ - - /* Resize/push operations on enclosure's fields are valid in the - * openmp block as a given enclosure is processed by a single thread */ - htable_vrtx_id_init(alloc, &vtable); - - ASSERT(scn->analyze.enclosures_count <= ENCLOSURE_MAX__); - #pragma omp for schedule(dynamic) nowait - for(ee = 0; ee < (int64_t)scn->analyze.enclosures_count; ee++) { - const enclosure_id_t e = (enclosure_id_t)ee; - struct enclosure_data* enc = enclosures + e; - trg_id_t fst_idx = 0; - trg_id_t sgd_idx = enc->side_count; - trg_id_t t; - medium_id_t m; - res_T tmp_res = RES_OK; - ASSERT(enc->first_component - < darray_ptr_component_descriptor_size_get(connex_components)); - ASSERT(cc_descriptors[enc->first_component]->cc_id - == enc->first_component); - - if(*res != RES_OK) continue; - ASSERT(e <= UINT_MAX); - enc->header.enclosure_id = (unsigned)e; /* Back to API type */ - ASSERT(cc_descriptors[enc->first_component]->enclosure_id - == enc->header.enclosure_id); - enc->header.is_infinite = (e == 0); - - ASSERT(darray_uchar_size_get(&enc->tmp_enclosed_media) <= UINT_MAX); - ASSERT(enc->header.enclosed_media_count < 1 + scn->next_medium_idx); - OK2(bool_array_of_media_to_darray_media - (&enc->enclosed_media, &enc->tmp_enclosed_media, scn->next_medium_idx)); - enc->header.enclosed_media_count - = (unsigned)darray_media_size_get(&enc->enclosed_media); - darray_uchar_purge(&enc->tmp_enclosed_media); - - /* Add this enclosure in relevant by-medium lists */ - FOR_EACH(m, 0, enc->header.enclosed_media_count) { - medium_id_t medium = darray_media_cdata_get(&enc->enclosed_media)[m]; - unsigned m_idx = (medium == SENC_UNSPECIFIED_MEDIUM) ? 0 : medium + 1; - struct darray_enc_id* enc_ids_array_by_medium; - ASSERT(medium == SENC_UNSPECIFIED_MEDIUM || medium < scn->next_medium_idx); - ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) - == 1 + scn->next_medium_idx); - enc_ids_array_by_medium = - darray_enc_ids_array_data_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; - #pragma omp critical - { - tmp_res = darray_enc_id_push_back(enc_ids_array_by_medium, &e); - } - if(tmp_res != RES_OK) { - *res = tmp_res; - break; - } - } - if(*res != RES_OK) continue; - - /* Build side and vertex lists. */ - OK2(darray_sides_enc_resize(&enc->sides, enc->side_count)); - /* Size is just a int */ - OK2(darray_vrtx_id_reserve(&enc->vertices, - (size_t)(enc->side_count * 0.6))); - /* New vertex numbering scheme local to the enclosure */ - htable_vrtx_id_clear(&vtable); - ASSERT(scn->ntris == darray_triangle_in_size_get(&scn->triangles_in)); - /* Put at the end the back-faces of triangles that also have their - * front-face in the list. */ - for(t = TRGSIDE_2_TRG(enc->side_range.first); - t <= TRGSIDE_2_TRG(enc->side_range.last); - t++) - { - const struct triangle_in* trg_in = triangles_in + t; - struct side_enc* side_enc; - unsigned vertice_id[3]; - int i; - if(triangles_enc[t].enclosure[SENC_FRONT] != e - && triangles_enc[t].enclosure[SENC_BACK] != e) - continue; - ++enc->header.unique_primitives_count; - - FOR_EACH(i, 0, 3) { - vrtx_id_t* p_id = htable_vrtx_id_find(&vtable, trg_in->vertice_id + i); - if(p_id) { - vertice_id[i] = *p_id; /* Known vertex */ - } else { - /* Create new association */ - size_t tmp = htable_vrtx_id_size_get(&vtable); - ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices)); - ASSERT(tmp < VRTX_MAX__); - vertice_id[i] = (vrtx_id_t)tmp; - OK2(htable_vrtx_id_set(&vtable, trg_in->vertice_id + i, - vertice_id + i)); - OK2(darray_vrtx_id_push_back(&enc->vertices, trg_in->vertice_id + i)); - ++enc->header.vertices_count; - } - } - ASSERT(triangles_enc[t].enclosure[SENC_FRONT] == e - || triangles_enc[t].enclosure[SENC_BACK] == e); - if(triangles_enc[t].enclosure[SENC_FRONT] == e) { - /* Front side of the original triangle is member of the enclosure */ - int input_normal_in = normals_front; - int revert_triangle = (input_normal_in != output_normal_in); - ++enc->header.primitives_count; - side_enc = darray_sides_enc_data_get(&enc->sides) + fst_idx++; - FOR_EACH(i, 0, 3) { - int ii = revert_triangle ? 2 - i : i; - side_enc->vertice_id[i] = vertice_id[ii]; - } - side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC_FRONT); - } - if(triangles_enc[t].enclosure[SENC_BACK] == e) { - /* Back side of the original triangle is member of the enclosure */ - int input_normal_in = normals_back; - int revert_triangle = (input_normal_in != output_normal_in); - ++enc->header.primitives_count; - /* If both sides are in the enclosure, put the second side at the end */ - side_enc = darray_sides_enc_data_get(&enc->sides) + - ((triangles_enc[t].enclosure[SENC_FRONT] == e) ? --sgd_idx : fst_idx++); - FOR_EACH(i, 0, 3) { - int ii = revert_triangle ? 2 - i : i; - side_enc->vertice_id[i] = vertice_id[ii]; - } - side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC_BACK); - } - if(fst_idx == sgd_idx) break; - } - continue; - tmp_error: - ASSERT(tmp_res != RES_OK); - *res = tmp_res; - } /* No barrier here */ - htable_vrtx_id_release(&vtable); - /* The first thread here copies frontiers into descriptor */ -#pragma omp single nowait - darray_frontier_edge_copy_and_clear(&scn->analyze.frontiers, frontiers); - /* No barrier here */ -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -scene_analyze - (struct senc_scene* scn) -{ - /* By triangle tmp data */ - struct darray_triangle_tmp triangles_tmp; - char triangles_tmp_initialized = 0; - /* Array of connex components. - * They are refered to by arrays of ids. */ - struct darray_ptr_component_descriptor connex_components; - char connex_components_initialized = 0; - /* Array of frontiers edges */ - struct darray_frontier_edge frontiers; - char frontiers_initialized = 0; - /* Store by-triangle components */ - struct darray_triangle_comp triangles_comp; - char triangles_comp_initialized = 0; - /* Array of triangle sides. */ - struct trgside* trgsides = NULL; - struct s3d_scene_view* s3d_view = NULL; - /* Atomic counters to share beetwen threads */ - ATOMIC component_count = 0; - ATOMIC next_enclosure_id = 1; - res_T res = RES_OK; - res_T res2 = RES_OK; - - if(!scn) return RES_BAD_ARG; - - if(!scn->ntris) goto exit; - - darray_triangle_tmp_init(scn->dev->allocator, &triangles_tmp); - triangles_tmp_initialized = 1; - darray_frontier_edge_init(scn->dev->allocator, &frontiers); - frontiers_initialized = 1; - - OK(darray_triangle_tmp_resize(&triangles_tmp, scn->ntris)); - trgsides - = MEM_CALLOC(scn->dev->allocator, 2 * scn->ntris, sizeof(struct trgside)); - if(!trgsides) { - res = RES_MEM_ERR; - goto error; - } -#ifndef NDEBUG - else { - /* Initialise trgsides to allow assert code */ - size_t i; - FOR_EACH(i, 0, 2 * scn->ntris) - init_trgside(scn->dev->allocator, trgsides + i); - } -#endif - - /* The end of the analyze is multithreaded */ - ASSERT(scn->dev->nthreads > 0); - #pragma omp parallel num_threads(scn->dev->nthreads) - { - /* Step 1: build neighbourhoods */ - collect_and_link_neighbours(scn, trgsides, &triangles_tmp, &frontiers, - &res); - /* No barrier at the end of step 1: data used in step 1 cannot be - * released / data produced by step 1 cannot be used - * until next sync point */ - - /* The first thread here allocates some data. - * Barrier needed at the end to ensure data created before any use. */ - #pragma omp single - { - res_T tmp_res = RES_OK; - darray_ptr_component_descriptor_init(scn->dev->allocator, - &connex_components); - connex_components_initialized = 1; - /* Just a hint; to limit contention */ - OK2(darray_ptr_component_descriptor_reserve(&connex_components, - 2 + 2 * scn->next_medium_idx)); - darray_triangle_comp_init(scn->dev->allocator, &triangles_comp); - triangles_comp_initialized = 1; - OK2(darray_triangle_comp_resize(&triangles_comp, scn->ntris)); - tmp_error: - if(tmp_res != RES_OK) res2 = tmp_res; - } - /* Implicit barrier here: constraints on step 1 data are now met */ - - if(res != RES_OK || res2 != RES_OK) { - #pragma omp single nowait - { - if(res != RES_OK) { - log_err(scn->dev, - "%s: could not build neighbourhoods from scene.\n", FUNC_NAME); - } else { - res = res2; - } - } - goto error_; - } - - /* Step 2: extract triangle connex components */ - extract_connex_components(scn, trgsides, &connex_components, - &triangles_tmp, &triangles_comp, &s3d_view, &component_count, &res); - /* No barrier at the end of step 2: data used in step 2 cannot be - * released / data produced by step 2 cannot be used - * until next sync point */ - - #pragma omp barrier - /* Constraints on step 2 data are now met */ - - if(res != RES_OK) { - #pragma omp single nowait - { - log_err(scn->dev, - "%s: could not extract connex components from scene.\n", FUNC_NAME); - } /* No barrier here */ - goto error_; - } - - /* One thread releases some data before going to step 3, - * the others go to step 3 without sync */ - #pragma omp single nowait - { - darray_triangle_tmp_release(&triangles_tmp); - triangles_tmp_initialized = 0; - } /* No barrier here */ - - /* Step 3: group components */ - group_connex_components(scn, trgsides, &triangles_comp, - &connex_components, s3d_view, &next_enclosure_id, &res); - /* Barrier at the end of step 3: data used in step 3 can be released / - * data produced by step 3 can be used */ - - if(res != RES_OK) { - #pragma omp single nowait - { - log_err(scn->dev, - "%s: could not group connex components from scene.\n", FUNC_NAME); - } - goto error_; - } - - /* One thread releases some data before going to step 4, - * the others go to step 4 without sync */ - #pragma omp single nowait - { - if(s3d_view) S3D(scene_view_ref_put(s3d_view)); - s3d_view = NULL; - } /* No barrier here */ - - /* Step 4: Build result */ - build_result(scn, &connex_components, &triangles_comp, &frontiers, &res); - /* No barrier at the end of step 4: data used in step 4 cannot be - * released / data produced by step 4 cannot be used - * until next sync point */ - - #pragma omp barrier - /* Constraints on step 4 data are now met */ - - if(res != RES_OK) { - #pragma omp single nowait - { - log_err(scn->dev, "%s: could not build result.\n", FUNC_NAME); - } - goto error_; - } - - /* Some threads release data */ - #pragma omp sections nowait - { - #pragma omp section - { - custom_darray_ptr_component_descriptor_release(&connex_components); - connex_components_initialized = 0; - } - #pragma omp section - { - darray_triangle_comp_release(&triangles_comp); - triangles_comp_initialized = 0; - } - } /* No barrier here */ - -error_: - ; - } /* Implicit barrier here */ - - if(res != RES_OK) goto error; -exit: - if(connex_components_initialized) - custom_darray_ptr_component_descriptor_release(&connex_components); - if(s3d_view) S3D(scene_view_ref_put(s3d_view)); - if(triangles_tmp_initialized) darray_triangle_tmp_release(&triangles_tmp); - if(triangles_comp_initialized) darray_triangle_comp_release(&triangles_comp); - if(frontiers_initialized) - darray_frontier_edge_release(&frontiers); - if(trgsides) MEM_RM(scn->dev->allocator, trgsides); - - return res; -error: - goto exit; -} diff --git a/src/senc_scene_analyze_c.h b/src/senc_scene_analyze_c.h @@ -1,201 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_SCNENE_ANALYZE_C_H -#define SENC_SCNENE_ANALYZE_C_H - -#include "senc_internal_types.h" -#include "senc.h" - -#include <rsys/mem_allocator.h> -#include <rsys/hash_table.h> -#include <rsys/double3.h> - -struct senc_scene; - -static FINLINE void -init_trgside(struct mem_allocator* alloc, struct trgside* data) -{ - int i; - ASSERT(data); (void)alloc; - FOR_EACH(i, 0, 3) data->facing_side_id[i] = SIDE_NULL__; - data->medium = MEDIUM_NULL__; -} - -#define DARRAY_NAME side_id -#define DARRAY_DATA side_id_t -#include <rsys/dynamic_array.h> - -/* Descriptors for connex component. - * Define lists of trg sides starting from a given head. - * Also keeps the maximum z info of the component - * and the list of media found */ -struct cc_descriptor { - /* Does this component is an outer border of an enclosure or an inner one? */ - char is_outer_border; - vrtx_id_t max_z_vrtx_id; /* id of the vrtx with max z value */ - side_id_t side_count; - /* Used when grouping components to form enclosures */ - component_id_t cc_id; - component_id_t cc_group_root; - enclosure_id_t enclosure_id; - /* Range of sides member of this component */ - struct side_range side_range; - /* Media used by this component */ - unsigned char* media; -}; -extern const struct cc_descriptor CC_DESCRIPTOR_NULL; - -static FINLINE void -cc_descriptor_init - (struct mem_allocator* alloc, - struct cc_descriptor* data) -{ - ASSERT(data); - (void)alloc; - *data = CC_DESCRIPTOR_NULL; -} - -static FINLINE void -ptr_component_descriptor_init - (struct mem_allocator* alloc, - struct cc_descriptor** data) -{ - (void)alloc; - ASSERT(data); - *data = NULL; -} - -#define DARRAY_NAME ptr_component_descriptor -#define DARRAY_DATA struct cc_descriptor* -#define DARRAY_FUNCTOR_INIT ptr_component_descriptor_init -#include <rsys/dynamic_array.h> - -/* Need allocator to free array elts: cannot rely on standard - * darray release stuff */ -static FINLINE void -custom_darray_ptr_component_descriptor_release - (struct darray_ptr_component_descriptor* array) -{ - size_t c, cc_count; - struct cc_descriptor** components; - if(!array) return; - cc_count = darray_ptr_component_descriptor_size_get(array); - components = darray_ptr_component_descriptor_data_get(array); - FOR_EACH(c, 0, cc_count) { - if(!components[c]) continue; - MEM_RM(array->allocator, components[c]->media); - MEM_RM(array->allocator, components[c]); - } - darray_ptr_component_descriptor_release(array); -} - -/* Triangle information. - * Depending on lifespan, information is kept in different places: - * - triangle_in for user provided information (kept in scene) - * - triangle_tmp for tmp information (kept until triangle_comp is ready) - * - triangle_comp for information describing components (kept until - * triangle_enc is ready) - * - triangle_enc for information describing enclosures (kept in - * struct descriptor). */ -struct triangle_tmp { - /* Are the edges of the triangle defined in the same order than - * the edges they are linked to? */ - unsigned char reversed_edge[3]; - double max_z; -}; - -#ifndef NDEBUG -static FINLINE void -triangle_tmp_init(struct mem_allocator* alloc, struct triangle_tmp* trg) { - int i; - (void)alloc; - ASSERT(trg); - FOR_EACH(i, 0, 3) trg->reversed_edge[i] = UCHAR_MAX; - trg->max_z = -DBL_MAX; -} -#define DARRAY_FUNCTOR_INIT triangle_tmp_init -#endif - -#define DARRAY_NAME triangle_tmp -#define DARRAY_DATA struct triangle_tmp -#include <rsys/dynamic_array.h> - -#define HTABLE_NAME edge_id -#define HTABLE_KEY struct trg_edge -#define HTABLE_DATA edge_id_t -#define HTABLE_KEY_FUNCTOR_EQ edge_eq -#include <rsys/hash_table.h> - -struct neighbour_info { - double angle; - trg_id_t trg_id; - /* Rank of the edge in the triangle (in [0 2]) */ - unsigned char common_edge_rank; - /* Does the geometrical normal point towards the next neighbour - * (if not, it points towards the previous one)? */ - unsigned char normal_toward_next_neighbour; -}; -#define DARRAY_NAME neighbour -#define DARRAY_DATA struct neighbour_info -#include <rsys/dynamic_array.h> - -struct edge_neighbourhood { - struct trg_edge edge; - struct darray_neighbour neighbours; -}; -static void -neighbourhood_init - (struct mem_allocator* alloc, - struct edge_neighbourhood* n) -{ - ASSERT(n); - darray_neighbour_init(alloc, &n->neighbours); -} -static res_T -neighbourhood_copy - (struct edge_neighbourhood* dst, - const struct edge_neighbourhood* src) -{ - ASSERT(src && dst); - dst->edge = src->edge; - return darray_neighbour_copy(&dst->neighbours, &src->neighbours); -} -static void -neighbourhood_release(struct edge_neighbourhood* n) { - ASSERT(n); - darray_neighbour_release(&n->neighbours); -} -static res_T -neighbourhood_copy_and_release - (struct edge_neighbourhood* dst, - struct edge_neighbourhood* src) -{ - ASSERT(src && dst); - dst->edge = src->edge; - return darray_neighbour_copy_and_release(&dst->neighbours, &src->neighbours); -} -#define DARRAY_NAME neighbourhood -#define DARRAY_DATA struct edge_neighbourhood -#define DARRAY_FUNCTOR_INIT neighbourhood_init -#define DARRAY_FUNCTOR_COPY neighbourhood_copy -#define DARRAY_FUNCTOR_RELEASE neighbourhood_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE neighbourhood_copy_and_release -#include <rsys/dynamic_array.h> - -extern LOCAL_SYM res_T -scene_analyze(struct senc_scene* scene); - -#endif /* SENC_SCNENE_ANALYZE_C_H */ diff --git a/src/senc_scene_c.h b/src/senc_scene_c.h @@ -1,302 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_SCENE_C_H -#define SENC_SCENE_C_H - -#include "senc_internal_types.h" -#include "senc_enclosure_data.h" -#include "senc_side_range.h" -#include "senc.h" - -#include <rsys/ref_count.h> -#include <rsys/dynamic_array.h> -#include <rsys/hash_table.h> - -struct mem_allocator; -struct senc_scene; - -struct triangle_comp { - /* The connex component in which each side is. */ - component_id_t component[2]; -}; - -static void -triangle_comp_init(struct mem_allocator* alloc, struct triangle_comp* trg) { - int i; - (void)alloc; - ASSERT(trg); - FOR_EACH(i, 0, 2) trg->component[i] = COMPONENT_NULL__; -} - -#define DARRAY_NAME triangle_comp -#define DARRAY_DATA struct triangle_comp -#define DARRAY_FUNCTOR_INIT triangle_comp_init -#include <rsys/dynamic_array.h> - -struct triangle_enc { - /* The enclosure in which each side is. */ - enclosure_id_t enclosure[2]; -}; - -#ifndef NDEBUG -static void -triangle_enc_init(struct mem_allocator* alloc, struct triangle_enc* trg) { - int i; - (void)alloc; - ASSERT(trg); - FOR_EACH(i, 0, 2) trg->enclosure[i] = ENCLOSURE_NULL__; -} -#define DARRAY_FUNCTOR_INIT triangle_enc_init -#endif - -#define DARRAY_NAME triangle_enc -#define DARRAY_DATA struct triangle_enc -#include <rsys/dynamic_array.h> - -/* Triangle edge struct and basic functions */ -struct trg_edge { - vrtx_id_t vrtx0, vrtx1; -}; - -static FINLINE int -edge_ok(const struct trg_edge* edge) { - return(edge - && edge->vrtx0 <= VRTX_MAX__ - && edge->vrtx1 <= VRTX_MAX__ - && edge->vrtx0 < edge->vrtx1); -} - -static FINLINE void -set_edge - (const vrtx_id_t vrtx0, - const vrtx_id_t vrtx1, - struct trg_edge* edge, - unsigned char* reversed) -{ - ASSERT(edge && reversed && vrtx0 != vrtx1); - ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */ - if(vrtx0 < vrtx1) { - edge->vrtx0 = vrtx0; - edge->vrtx1 = vrtx1; - *reversed = 0; /* Non reversed edge */ - } else { - edge->vrtx0 = vrtx1; - edge->vrtx1 = vrtx0; - *reversed = 1; /* Reversed edge */ - } - ASSERT(edge_ok(edge)); -} - -static FINLINE int -edge_eq(const struct trg_edge* e1, const struct trg_edge* e2) -{ - ASSERT(edge_ok(e1) && edge_ok(e2)); - return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1; -} - -/* Information kept during the building of side groups. */ -struct trgside { - /* Rank of the trgside facing this trgside through its edges */ - side_id_t facing_side_id[3]; - /* Id of this trgside's medium */ - medium_id_t medium; - - /* Implicit information that we don't need to store: - * - triangle_id - * - side - * This is due to the memory layout of the elt darray: - * front(trg_0), back(trg_0), front(trg_1), back(trg_1), ... */ -}; - -#define DARRAY_NAME frontier_edge -#define DARRAY_DATA struct trg_edge -#include <rsys/dynamic_array.h> - -union double3 { - struct { - double x, y, z; - } pos; - double vec[3]; -}; -#define DARRAY_NAME position -#define DARRAY_DATA union double3 -#include <rsys/dynamic_array.h> -/* Triangle information. - * Depending on lifespan, information is kept in different places: - * - triangle_in for user provided information (kept in scene) - * - triangle_comp for information describing components (kept in struct descriptor) - * - triangle_tmp for tmp information (kept until triangle_comp is ready) */ -struct triangle_in { - /* Ids of the triangle's vertices */ - vrtx_id_t vertice_id[3]; - /* Ids of this triangle's media */ - medium_id_t medium[2]; -}; - -static FINLINE void -triangle_in_init(struct mem_allocator* alloc, struct triangle_in* trg) { - int i; - (void)alloc; - ASSERT(trg); - FOR_EACH(i, 0, 3) trg->vertice_id[i] = VRTX_NULL__; - FOR_EACH(i, 0, 2) trg->medium[i] = SENC_UNSPECIFIED_MEDIUM; -} - -#define DARRAY_NAME triangle_in -#define DARRAY_DATA struct triangle_in -#define DARRAY_FUNCTOR_INIT triangle_in_init -#include <rsys/dynamic_array.h> - -static FINLINE void -triangle_in_flip(struct triangle_in* trg) { - vrtx_id_t v; - medium_id_t m; - ASSERT(trg); - v = trg->vertice_id[1]; - trg->vertice_id[1] = trg->vertice_id[2]; - trg->vertice_id[2] = v; - m = trg->medium[0]; - trg->medium[0] = trg->medium[1]; - trg->medium[1] = m; -} - -static FINLINE int -vrtx_eq(const union double3* v1, const union double3* v2) -{ - ASSERT(v1 && v2); - return (v1->pos.x == v2->pos.x - && v1->pos.y == v2->pos.y - && v1->pos.z == v2->pos.z); -} - -#define HTABLE_NAME vrtx -#define HTABLE_KEY union double3 -#define HTABLE_DATA vrtx_id_t -#define HTABLE_KEY_FUNCTOR_EQ vrtx_eq -#include <rsys/hash_table.h> - -union vrtx_id3 { - struct { - vrtx_id_t v0, v1, v2; - } pos; - vrtx_id_t vec[3]; -}; - -static FINLINE char /* Return 1 if reversed */ -trg_make_key(union vrtx_id3* k, const vrtx_id_t t[3]) -{ - ASSERT(t); - ASSERT(t[0] != t[1] && t[0] != t[2] && t[1] != t[2]); - if(t[0] < t[2]) { - if(t[0] < t[1]) { - k->vec[0] = t[0]; - if(t[1] < t[2]) { - k->vec[1] = t[1]; - k->vec[2] = t[2]; - return 0; - } else { - k->vec[1] = t[2]; - k->vec[2] = t[1]; - return 1; - } - } else { - k->vec[0] = t[1]; - if(t[0] < t[2]) { - k->vec[1] = t[0]; - k->vec[2] = t[2]; - return 1; - } else { - k->vec[1] = t[2]; - k->vec[2] = t[0]; - return 0; - } - } - } else if(t[2] < t[1]) { - k->vec[0] = t[2]; - if(t[0] < t[1]) { - k->vec[1] = t[0]; - k->vec[2] = t[1]; - return 0; - } else { - k->vec[1] = t[1]; - k->vec[2] = t[0]; - return 1; - } - } else { - k->vec[0] = t[1]; - if(t[0] < t[2]) { - k->vec[1] = t[0]; - k->vec[2] = t[2]; - return 1; - } else { - k->vec[1] = t[2]; - k->vec[2] = t[0]; - return 0; - } - } -} - -static FINLINE int -trg_key_eq(const union vrtx_id3* k1, const union vrtx_id3* k2) -{ - ASSERT(k1 && k2); - ASSERT(k1->vec[0] < k1->vec[1] && k1->vec[1] < k1->vec[2]); - ASSERT(k2->vec[0] < k2->vec[1] && k2->vec[1] < k2->vec[2]); - return (k1->vec[0] == k2->vec[0]) - && (k1->vec[1] == k2->vec[1]) - && (k1->vec[2] == k2->vec[2]); -} - -#define HTABLE_NAME trg -#define HTABLE_KEY union vrtx_id3 -#define HTABLE_DATA trg_id_t -#define HTABLE_KEY_FUNCTOR_EQ trg_key_eq -#include <rsys/hash_table.h> - -struct descriptor { - enclosure_id_t enclosures_count; - /* Store by-triangle enclosures */ - struct darray_triangle_enc triangles_enc; - /* Store enclosures */ - struct darray_enclosure enclosures; - struct darray_enc_ids_array enc_ids_array_by_medium; - /* Store frontiers */ - struct darray_frontier_edge frontiers; -}; - -struct senc_scene { - /* Front / Back sides convention */ - int convention; - /* Triangle information as given by user */ - struct darray_triangle_in triangles_in; - /* Vertex information as given by user */ - struct darray_position vertices; - - /* Keep sizes */ - trg_id_t ntris; /* Trg count */ - vrtx_id_t nverts; /* Vrtx count */ - medium_id_t next_medium_idx; - /* media_use 0 is for SENC_UNSPECIFIED_MEDIUM, n+1 is for n */ - struct darray_side_range media_use; - - /* The descriptor of the analyze */ - struct descriptor analyze; - - ref_T ref; - struct senc_device* dev; -}; - -#endif /* SENC_SCENE_C_H */ diff --git a/src/senc_side_range.h b/src/senc_side_range.h @@ -1,44 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 SENC_SIDE_RANGE_H -#define SENC_SIDE_RANGE_H - -#include "senc_internal_types.h" - -#include <rsys/dynamic_array.h> - -struct mem_allocator; - -struct side_range { - side_id_t first, last; -}; - -static FINLINE void -side_range_init(struct mem_allocator* alloc, struct side_range* data) -{ - ASSERT(data); - (void)alloc; - data->first = SIDE_NULL__; - data->last = 0; -} - -#define DARRAY_NAME side_range -#define DARRAY_DATA struct side_range -#define DARRAY_FUNCTOR_INIT side_range_init -#include <rsys/dynamic_array.h> - - -#endif /* SENC_SCENE_C_H */ diff --git a/src/test_senc3d_cube_behind_cube.c b/src/test_senc3d_cube_behind_cube.c @@ -0,0 +1,311 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_cube_behind_cube. */ + +#include "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +/* Dump of star-geometry 'cube_behind_cube_2'. */ +static const unsigned cube_behind_cube_2_vertices_count = 16; +static const double cube_behind_cube_2_vertices[48] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1, + -1.5, -2, 20, + 3, -2, 20, + -2, 3, 20, + 3, 3, 20, + -2, -2, 25.5, + 3, -2, 25, + -2, 3, 25, + 3, 3.5, 25 +}; +static const unsigned cube_behind_cube_2_triangles_count = 24; +static const unsigned cube_behind_cube_2_triangles[72] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 10, 9, + 9, 10, 11, + 8, 12, 10, + 10, 12, 14, + 12, 13, 14, + 14, 13, 15, + 11, 15, 9, + 9, 15, 13, + 10, 14, 11, + 11, 14, 15, + 8, 9, 12, + 12, 9, 13 +}; +static const unsigned cube_behind_cube_2_properties[72] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; +/* Dump of star-geometry 'cube_behind_cube_3'. */ +static const unsigned cube_behind_cube_3_vertices_count = 24; +static const double cube_behind_cube_3_vertices[72] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1, + -1.5, -2, 20, + 3, -2, 20, + -2, 3, 20, + 3, 3, 20, + -2, -2, 25.5, + 3, -2, 25, + -2, 3, 25, + 3, 3.5, 25, + -2.3, -3, 30, + 4, -3, 30, + -3, 4, 30, + 4, 4, 30, + -3, -3, 37.7, + 4, -3, 37, + -3, 4, 37, + 4, 4.7, 37 +}; +static const unsigned cube_behind_cube_3_triangles_count = 36; +static const unsigned cube_behind_cube_3_triangles[108] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 10, 9, + 9, 10, 11, + 8, 12, 10, + 10, 12, 14, + 12, 13, 14, + 14, 13, 15, + 11, 15, 9, + 9, 15, 13, + 10, 14, 11, + 11, 14, 15, + 8, 9, 12, + 12, 9, 13, + 16, 18, 17, + 17, 18, 19, + 16, 20, 18, + 18, 20, 22, + 20, 21, 22, + 22, 21, 23, + 19, 23, 17, + 17, 23, 21, + 18, 22, 19, + 19, 22, 23, + 16, 17, 20, + 20, 17, 21 +}; +static const unsigned cube_behind_cube_3_properties[108] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0 +}; + +/* + cube_2 cube_3 + + +-----------------------+ + | 3 + | | + m1 | m0 | + | | + | | + | | + | |--> N + | | + | | + +-----------------------+ + +------------+ +------------+ + | 2 | 2 + m0 | m1 | m0 | m1 | + | | | | + | |--> N | |--> N + | | | | + +------------+ +------------+ + +-----+ +-----+ + m0 | m1 1 m0 | m1 1 + | |--> N | |--> N + +-----+ +-----+ + */ + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned i, ecount, maxm; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene with the first and second cubes. + * Both cubes have medium 1 inside and medium 0 outside, + * the second cube is +Z from the first cube and is big enough + * to prevent rays from the first cube to miss it. */ + ctx.positions = cube_behind_cube_2_vertices; + ctx.indices = cube_behind_cube_2_triangles; + ctx.properties = cube_behind_cube_2_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + cube_behind_cube_2_triangles_count, get_indices, get_media_from_properties, + cube_behind_cube_2_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 3); + + FOR_EACH(i, 0, ecount) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + OK(senc3d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + ASSERT(header.enclosed_media_count == 1); + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 1); + OK(senc3d_scene_ref_put(scn)); + + /* Create a scene with the 3 cubes, same 2 first cubes as above + * The third cube has medium 0 inside and medium 1 outside and is further + * in +Z and bigger */ + ctx.positions = cube_behind_cube_3_vertices; + ctx.indices = cube_behind_cube_3_triangles; + ctx.properties = cube_behind_cube_3_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + cube_behind_cube_3_triangles_count, get_indices, get_media_from_properties, + cube_behind_cube_3_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 4); + + FOR_EACH(i, 0, ecount) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + OK(senc3d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + /* Inside enclosures contain 1 single media */ + ASSERT(header.enclosed_media_count == (header.is_infinite ? 2u : 1u)); + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 1); + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_cube_in_cube.c b/src/test_senc3d_cube_in_cube.c @@ -0,0 +1,314 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_cube_in_cube. */ + +#include "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +/* + cube_2 cube_3 + + +-------------------------+ + | B + +-------------+ | +-------------+ | + m1 | m0 M m1 | m1 | m0 M | + | +------+ | | m0 | +------+ | | + | | m1 S | | | | m1 S | | + | | N <--| | | | | N <--| | | + | +------+ | | | +------+ | | + | N <--| | | N <--| | + +-------------+ | +-------------+ | + | N <--| + +-------------------------+ + */ + + +/* Dump of star-geometry 'cube_in_cube_2'. */ +static const unsigned cube_in_cube_2_vertices_count = 16; +static const double cube_in_cube_2_vertices[48] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1, + -0.7, -1, -1, + 2, -1, -1, + -1, 2, -1, + 2, 2, -1, + -1, -1, 2.3, + 2, -1, 2, + -1, 2, 2, + 2, 2.3, 2 +}; +static const unsigned cube_in_cube_2_triangles_count = 24; +static const unsigned cube_in_cube_2_triangles[72] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 9, 10, + 9, 11, 10, + 8, 10, 12, + 10, 14, 12, + 12, 14, 13, + 14, 15, 13, + 11, 9, 15, + 9, 13, 15, + 10, 11, 14, + 11, 15, 14, + 8, 12, 9, + 12, 13, 9 +}; +static const unsigned cube_in_cube_2_properties[72] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; +/* Dump of star-geometry 'cube_in_cube_3'. */ +static const unsigned cube_in_cube_3_vertices_count = 24; +static const double cube_in_cube_3_vertices[72] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1, + -0.7, -1, -1, + 2, -1, -1, + -1, 2, -1, + 2, 2, -1, + -1, -1, 2.3, + 2, -1, 2, + -1, 2, 2, + 2, 2.3, 2, + -3, -4, -4, + 6, -4, -4, + -4, 6, -4, + 6, 6, -4, + -4, -4, 7, + 6, -4, 6, + -4, 6, 6, + 6, 7, 6 +}; +static const unsigned cube_in_cube_3_triangles_count = 36; +static const unsigned cube_in_cube_3_triangles[108] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 9, 10, + 9, 11, 10, + 8, 10, 12, + 10, 14, 12, + 12, 14, 13, + 14, 15, 13, + 11, 9, 15, + 9, 13, 15, + 10, 11, 14, + 11, 15, 14, + 8, 12, 9, + 12, 13, 9, + 16, 17, 18, + 17, 19, 18, + 16, 18, 20, + 18, 22, 20, + 20, 22, 21, + 22, 23, 21, + 19, 17, 23, + 17, 21, 23, + 18, 19, 22, + 19, 23, 22, + 16, 20, 17, + 20, 21, 17 +}; +static const unsigned cube_in_cube_3_properties[108] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned e, ecount, maxm, e2; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene with the first and second cubes. + * The enclosure in the small contains medium 1, the external enclosure + * contains medium 1, the enclosure between the small and medium cubes + * contains medium 0. */ + ctx.positions = cube_in_cube_2_vertices; + ctx.indices = cube_in_cube_2_triangles; + ctx.properties = cube_in_cube_2_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + cube_in_cube_2_triangles_count, get_indices, get_media_from_properties, + cube_in_cube_2_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 3); + + FOR_EACH(e, 0, ecount) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + unsigned m; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + ASSERT(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &m)); + ASSERT(m <= 1); + ASSERT((m == 0) == (header.primitives_count == cube_in_cube_2_triangles_count)); + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 1); + OK(senc3d_scene_ref_put(scn)); + + /* Create a scene with the 3 cubes, same 2 first cubes as above. + * The enclosure in the small cube contains medium 1, the external enclosure + * contains medium 1, the enclosure between the small and medium cubes + * contains medium 0 and the enclosure between the medium and big cubes + * contains both media 0 and 1. */ + ctx.positions = cube_in_cube_3_vertices; + ctx.indices = cube_in_cube_3_triangles; + ctx.properties = cube_in_cube_3_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + cube_in_cube_3_triangles_count, get_indices, get_media_from_properties, + cube_in_cube_3_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 4); + + e2 = ecount; + FOR_EACH(e, 0, ecount) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + ASSERT(header.enclosed_media_count <= 2); + if(header.enclosed_media_count == 2) { + /* A single internal enclosure has 2 media */ + ASSERT(!header.is_infinite); + ASSERT(e2 == ecount); + e2 = e; + } + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 1); + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_cube_on_cube.c b/src/test_senc3d_cube_on_cube.c @@ -0,0 +1,205 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_cube_on_cube. */ + +#define _POSIX_C_SOURCE 200112L /* snprintf */ + +#include "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +#include <stdio.h> + +/* + +-----------------------+ + | 3 + | +------+ | + m2 | m1 | m0 2 | + | | |--> N | + | +------+ | + | | m0 1 | + | | |--> N | + | +------+ | + |--> N | + +-----------------------+ + */ + +/* Dump of star-geometry 'cube_on_cube'. */ +static const unsigned cube_on_cube_vertices_count = 20; +static const double cube_on_cube_vertices[60] = +{ + 1, 1, 2, + 2, 1, 2, + 1, 2, 2, + 2, 2, 2, + 1, 1, 3, + 2, 1, 3, + 1, 2, 3, + 2, 2, 3, + 1, 1, 1, + 2, 1, 1, + 1, 2, 1, + 2, 2, 1, + 0.4, 0, 0, + 4, 0, 0, + 0, 4, 0, + 4, 4, 0, + 0, 0, 4.4, + 4, 0, 4, + 0, 4, 4, + 4, 4.4, 4 +}; +static const unsigned cube_on_cube_triangles_count = 34; +static const unsigned cube_on_cube_triangles[102] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 10, 9, + 9, 10, 11, + 8, 0, 10, + 10, 0, 2, + 11, 3, 9, + 9, 3, 1, + 10, 2, 11, + 11, 2, 3, + 8, 9, 0, + 0, 9, 1, + 12, 13, 14, + 13, 15, 14, + 12, 14, 16, + 14, 18, 16, + 16, 18, 17, + 18, 19, 17, + 15, 13, 19, + 13, 17, 19, + 14, 15, 18, + 15, 19, 18, + 12, 16, 13, + 16, 17, 13 +}; +static const unsigned cube_on_cube_properties[102] = +{ + 0, 0, 0, + 0, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0 +}; + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned count, e; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene with the cubes. + * The enclosures in the small cubes contain medium 0, the external enclosure + * contains medium 2, the enclosure between the small and big cubes + * contains medium 1. */ + ctx.positions = cube_on_cube_vertices; + ctx.indices = cube_on_cube_triangles; + ctx.properties = cube_on_cube_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + cube_on_cube_triangles_count, get_indices, get_media_from_properties, + cube_on_cube_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 4); + + OK(senc3d_scene_get_vertices_count(scn, &count)); + CHK(count == cube_on_cube_vertices_count); + + OK(senc3d_scene_get_triangles_count(scn, &count)); + CHK(count == cube_on_cube_triangles_count); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 4); + FOR_EACH(e, 0, count) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + unsigned m; + char name[128]; (void)name; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + CHK(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &m)); + if(header.is_infinite) ASSERT(m == 2); /* External */ + else if(header.primitives_count == 12) ASSERT(m == 0); /* Internal */ + else ASSERT(m == 1); /* In between */ + OK(senc3d_enclosure_ref_put(enclosure)); +#ifdef DUMP_ENCLOSURES + snprintf(name, sizeof(name), "test_cube_on_cube_%u.obj", e); + dump_enclosure(scn, e, name); +#endif + } + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_device.c b/src/test_senc3d_device.c @@ -0,0 +1,77 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/logger.h> + +#include <stdio.h> + +static INLINE void +log_stream(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)msg, (void)ctx; + printf("%s\n", msg); +} + +int +main(int argc, char** argv) +{ + struct logger logger; + struct mem_allocator allocator; + struct senc3d_device* dev; + (void)argc, (void)argv; + + BA(senc3d_device_create(NULL, NULL, 0, 0, NULL)); + BA(senc3d_device_create(NULL, NULL, 0, 0, &dev)); + OK(senc3d_device_create(NULL, NULL, 1, 0, &dev)); + BA(senc3d_device_ref_get(NULL)); + OK(senc3d_device_ref_get(dev)); + BA(senc3d_device_ref_put(NULL)); + OK(senc3d_device_ref_put(dev)); + OK(senc3d_device_ref_put(dev)); + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + + CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); + BA(senc3d_device_create(NULL, &allocator, 1, 0, NULL)); + OK(senc3d_device_create(NULL, &allocator, 1, 0, &dev)); + OK(senc3d_device_ref_put(dev)); + CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); + + OK(logger_init(&allocator, &logger)); + 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); + + BA(senc3d_device_create(&logger, NULL, 1, 0, NULL)); + OK(senc3d_device_create(&logger, NULL, 1, 0, &dev)); + OK(senc3d_device_ref_put(dev)); + + BA(senc3d_device_create(&logger, &allocator, 1, 0, NULL)); + OK(senc3d_device_create(&logger, &allocator, 1, 0, &dev)); + OK(senc3d_device_ref_put(dev)); + + OK(senc3d_device_create(&logger, &allocator, SENC3D_NTHREADS_DEFAULT, 0, &dev)); + OK(senc3d_device_ref_put(dev)); + + logger_release(&logger); + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_enclosure.c b/src/test_senc3d_enclosure.c @@ -0,0 +1,248 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "SENC3D_s3d_helper.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +#include <star/s3d.h> + +static void +test(const int convention) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct senc3d_enclosure* enclosures[2] = { NULL, NULL }; + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + struct s3d_device* s3d = NULL; + struct s3d_scene* s3d_scn = NULL; + struct s3d_shape* s3d_shp = NULL; + struct s3d_vertex_data s3d_attribs; + unsigned indices[2][3]; + unsigned medium; + unsigned gid; + enum senc3d_side side; + double vrtx[3]; + struct context ctx = CONTEXT_NULL__; + unsigned i, n, t, count; + int conv; + const int conv_front = (convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0; + const int conv_in = (convention & SENC3D_CONVENTION_NORMAL_INSIDE) != 0; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* A 3D cube. + * 2 enclosures (inside, outside) sharing the same triangles, + * but opposite sides */ + ctx.positions = box_vertices; + ctx.indices = box_indices; + ctx.front_media = medium0; + ctx.back_media = medium1; + + OK(senc3d_scene_create(dev, convention, ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_convention(scn, &conv)); + CHK(conv == convention); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 2); + + OK(senc3d_scene_get_enclosure(scn, 0, &enclosure)); + BA(senc3d_enclosure_ref_get(NULL)); + OK(senc3d_enclosure_ref_get(enclosure)); + BA(senc3d_enclosure_ref_put(NULL)); + OK(senc3d_enclosure_ref_put(enclosure)); + + BA(senc3d_enclosure_get_triangle(NULL, 0, indices[0])); + BA(senc3d_enclosure_get_triangle(enclosure, ntriangles, indices[0])); + BA(senc3d_enclosure_get_triangle(enclosure, 0, NULL)); + BA(senc3d_enclosure_get_triangle(NULL, ntriangles, indices[0])); + BA(senc3d_enclosure_get_triangle(NULL, 0, NULL)); + BA(senc3d_enclosure_get_triangle(enclosure, ntriangles, NULL)); + BA(senc3d_enclosure_get_triangle(NULL, ntriangles, NULL)); + OK(senc3d_enclosure_get_triangle(enclosure, 0, indices[0])); + + BA(senc3d_enclosure_get_vertex(NULL, 0, vrtx)); + BA(senc3d_enclosure_get_vertex(enclosure, nvertices, vrtx)); + BA(senc3d_enclosure_get_vertex(enclosure, 0, NULL)); + BA(senc3d_enclosure_get_vertex(NULL, nvertices, vrtx)); + BA(senc3d_enclosure_get_vertex(NULL, 0, NULL)); + BA(senc3d_enclosure_get_vertex(enclosure, nvertices, NULL)); + BA(senc3d_enclosure_get_vertex(NULL, nvertices, NULL)); + OK(senc3d_enclosure_get_vertex(enclosure, 0, vrtx)); + + BA(senc3d_enclosure_get_triangle_id(NULL, 0, &gid, NULL)); + BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, &gid, NULL)); + BA(senc3d_enclosure_get_triangle_id(enclosure, 0, NULL, NULL)); + BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, &gid, NULL)); + BA(senc3d_enclosure_get_triangle_id(NULL, 0, NULL, NULL)); + BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, NULL, NULL)); + BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, NULL, NULL)); + BA(senc3d_enclosure_get_triangle_id(enclosure, 0, &gid, NULL)); + BA(senc3d_enclosure_get_triangle_id(NULL, 0, &gid, &side)); + BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, &gid, &side)); + BA(senc3d_enclosure_get_triangle_id(enclosure, 0, NULL, &side)); + BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, &gid, &side)); + BA(senc3d_enclosure_get_triangle_id(NULL, 0, NULL, &side)); + BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, NULL, &side)); + BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, NULL, &side)); + OK(senc3d_enclosure_get_triangle_id(enclosure, 0, &gid, &side)); + + BA(senc3d_enclosure_get_medium(NULL, 0, &medium)); + BA(senc3d_enclosure_get_medium(enclosure, 2, &medium)); + BA(senc3d_enclosure_get_medium(enclosure, 0, NULL)); + BA(senc3d_enclosure_get_medium(NULL, 2, &medium)); + BA(senc3d_enclosure_get_medium(NULL, 0, NULL)); + BA(senc3d_enclosure_get_medium(enclosure, 2, NULL)); + BA(senc3d_enclosure_get_medium(NULL, 2, NULL)); + OK(senc3d_enclosure_get_medium(enclosure, 0, &medium)); + + OK(senc3d_enclosure_ref_put(enclosure)); + + FOR_EACH(i, 0, count) { + OK(senc3d_scene_get_enclosure(scn, i, &enclosure)); + + BA(senc3d_enclosure_get_header(NULL, &header)); + BA(senc3d_enclosure_get_header(enclosure, NULL)); + BA(senc3d_enclosure_get_header(NULL, NULL)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + CHK(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the cube in input triangles: + * if convention is front, front medium (0) is outside, + * that is medium 0's enclosure is infinite */ + CHK(conv_front == ((medium == 0) == header.is_infinite)); + CHK(header.primitives_count == ntriangles); + CHK(header.unique_primitives_count == ntriangles); + CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == (i == 0)); + + FOR_EACH(t, 0, header.primitives_count) { + OK(senc3d_enclosure_get_triangle_id(enclosure, t, &gid, &side)); + CHK(gid == t); + CHK(side == (medium == 0) ? SENC3D_FRONT : SENC3D_BACK); + } + + OK(senc3d_enclosure_ref_put(enclosure)); + } + + FOR_EACH(i, 0, 2) + OK(senc3d_scene_get_enclosure(scn, i, enclosures + i)); + FOR_EACH(n, 0, ntriangles) { + int same, reversed; + /* Read same triangles in both enclosures */ + FOR_EACH(i, 0, 2) + OK(senc3d_enclosure_get_triangle(enclosures[i], n, indices[i])); + /* Same triangles and opposite sides for the 2 enclosures */ + FOR_EACH(i, 0, 3) CHK(indices[0][i] == indices[1][2 - i]); + /* Enclosure 0 is outside (and contains medium 0 if convention is front). + * Geometrical normals in output data point in the same direction that those + * of input triangles for enclosure 0 iff convention is inside. + * The opposite holds for enclosure 1. */ + cmp_trg(n, enclosures[0], box_indices + 3 * n, box_vertices, &same, &reversed); + CHK((same && !reversed) == conv_in); + cmp_trg(n, enclosures[1], box_indices + 3 * n, box_vertices, &same, &reversed); + CHK(same && reversed == conv_in); + } + FOR_EACH(i, 0, 2) + OK(senc3d_enclosure_ref_put(enclosures[i])); + + OK(senc3d_scene_ref_put(scn)); + + /* Same 3D cube, but with a hole (incomplete). + * 1 single enclosure including both sides of triangles */ + + ctx.positions = box_vertices; + ctx.indices = box_indices; + ctx.front_media = medium0; + ctx.back_media = medium1; + + OK(senc3d_scene_create(dev, convention, ntriangles - 1, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_frontier_segments_count(scn, &count)); + CHK(count == 3); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1); + +#ifdef DUMP_ENCLOSURES + dump_enclosure(scn, 0, "test_enclosure_hole.obj"); +#endif + + OK(senc3d_scene_get_enclosure(scn, 0, &enclosure)); + + BA(senc3d_enclosure_get_header(NULL, &header)); + BA(senc3d_enclosure_get_header(enclosure, NULL)); + BA(senc3d_enclosure_get_header(NULL, NULL)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == 0); + CHK(header.enclosed_media_count == 2); + CHK(header.primitives_count == 2 * header.unique_primitives_count); + CHK(header.unique_primitives_count == ntriangles - 1); + CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == 1); + + FOR_EACH(t, 0, header.primitives_count) { + OK(senc3d_enclosure_get_triangle_id(enclosure, t, &gid, &side)); + /* The first unique_triangle_count triangles of an enclosure + * are unique triangles */ + if(t < header.unique_primitives_count) CHK(gid == t); + CHK(side == (t < header.unique_primitives_count) ? SENC3D_FRONT : SENC3D_BACK); + } + + /* Put geometry in a 3D view using helper functions */ + s3d_attribs.type = S3D_FLOAT3; + s3d_attribs.usage = S3D_POSITION; + s3d_attribs.get = SENC3D_s3d_enclosure_get_position; + OK(s3d_device_create(NULL, &allocator, 0, &s3d)); + OK(s3d_scene_create(s3d, &s3d_scn)); + OK(s3d_shape_create_mesh(s3d, &s3d_shp)); + OK(s3d_mesh_setup_indexed_vertices(s3d_shp, header.primitives_count, + SENC3D_s3d_enclosure_get_indices, header.vertices_count, &s3d_attribs, + 1, enclosure)); + OK(s3d_scene_attach_shape(s3d_scn, s3d_shp)); + S3D(shape_ref_put(s3d_shp)); + S3D(device_ref_put(s3d)); + S3D(scene_ref_put(s3d_scn)); + + SENC3D(scene_ref_put(scn)); + SENC3D(device_ref_put(dev)); + SENC3D(enclosure_ref_put(enclosure)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); +} + +int +main(int argc, char** argv) +{ + (void) argc, (void) argv; + test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE); + test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_INSIDE); + test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_OUTSIDE); + test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_OUTSIDE); + return 0; +} diff --git a/src/test_senc3d_inconsistant_cube.c b/src/test_senc3d_inconsistant_cube.c @@ -0,0 +1,145 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +/* The following array lists the indices toward the 3D vertices of each +* triangle. +* ,6---,7 ,6----7 +* ,' | ,'/| ,' | \ | Y Z +* 2----3' / | 2', | \ | | ,' +* |', | / ,5 | ',4---,5 0----X +* | ',|/,' | ,' | ,' +* 0----1' 0----1' +* Front, right Back, left and +* and Top faces bottom faces */ +/* Triangle #1 rotation order is not consistant with other triangles */ +static unsigned +inconsistant_box_indices[12/*#triangles*/ * 3/*#indices per triangle*/] = { + 0, 1, 2, 1, 2, 3, /* Front face */ + 0, 4, 2, 2, 4, 6, /* Left face*/ + 4, 5, 6, 6, 5, 7, /* Back face */ + 3, 7, 1, 1, 7, 5, /* Right face */ + 2, 6, 3, 3, 6, 7, /* Top face */ + 0, 1, 4, 4, 1, 5 /* Bottom face */ +}; +static const unsigned inconsistant_box_ntriangles += sizeof(inconsistant_box_indices) / (3 * sizeof(*inconsistant_box_indices)); + +/* Media definitions reflect triangle #1 inconsistancy */ +static const unsigned +inconsistant_medium_front[12] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static const unsigned +inconsistant_medium_back[12] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + +static void +test(const int convention) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + int conv; + int conv_front, conv_in; + struct context ctx = CONTEXT_NULL__; + unsigned i, e, ecount; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* A 3D cube. + * 2 enclosures (inside, outside) sharing the same triangles, + * but opposite sides. + * What differs in this test is that triangle #0 vertices are given + * in the opposite rotation order. */ + ctx.positions = box_vertices; + ctx.indices = inconsistant_box_indices; + ctx.front_media = inconsistant_medium_front; + ctx.back_media = inconsistant_medium_back; + + OK(senc3d_scene_create(dev, convention, inconsistant_box_ntriangles, + get_indices, get_media, nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + OK(senc3d_scene_get_convention(scn, &conv)); + CHK(conv == convention); + conv_front = (conv & SENC3D_CONVENTION_NORMAL_FRONT) != 0; + conv_in = (conv & SENC3D_CONVENTION_NORMAL_INSIDE) != 0; + + FOR_EACH(e, 0, ecount) { + unsigned medium, expected_external_medium, expected_medium; + char name[128]; + enum senc3d_side side, expected_side; + unsigned gid; + (void)name; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + CHK(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &medium)); + /* If NORMAL_FRONT the external enclosure's medium should be 0, + * 1 if NORMAL_BACK */ + expected_external_medium = conv_front ? 0 : 1; + expected_medium = (header.is_infinite ? + expected_external_medium : !expected_external_medium); + CHK(medium == expected_medium); + +#ifdef DUMP_ENCLOSURES + sprintf(name, "test_inconsistant_cube_%s_%s_%u.obj", + conv_front ? "front" : "back", conv_in ? "in" : "out", e); + dump_enclosure(scn, e, name); +#endif + + FOR_EACH(i, 0, header.primitives_count) { + int same, reversed, fst_reversed; + fst_reversed = ((e == 0) == conv_in); + expected_side = (inconsistant_medium_front[i] == expected_medium) + ? SENC3D_FRONT : SENC3D_BACK; + cmp_trg(i, enclosure, + inconsistant_box_indices + (3 * i), box_vertices, + &same, &reversed); + /* Should be made of the same triangles */ + CHK(same); + CHK(i ? reversed != fst_reversed : reversed == fst_reversed); + OK(senc3d_enclosure_get_triangle_id(enclosure, i, &gid, &side)); + CHK(side == expected_side); + } + SENC3D(enclosure_ref_put(enclosure)); + } + + SENC3D(scene_ref_put(scn)); + SENC3D(device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); +} + +int main(int argc, char** argv) +{ + (void) argc, (void) argv; + + test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE); + test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_INSIDE); + test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_OUTSIDE); + test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_OUTSIDE); + + return 0; +} diff --git a/src/test_senc3d_many_enclosures.c b/src/test_senc3d_many_enclosures.c @@ -0,0 +1,108 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test is similar to test_senc3d_some_enclosures, but involves 64*64*64 + * cylinders instead of 4*4*4, thus making it impossible to define the geometry + * through static arrays. */ + +#define NB_CYL_X 32 +#define NB_CYL_Y 32 +#define NB_CYL_Z 64 + /* 64^3 = 262144 cylinders */ +#define NB_CYL (NB_CYL_X * NB_CYL_Y * NB_CYL_Z) + +#include "senc3d.h" +#include "test_senc3d_utils.h" +#include "test_senc3d_utils2.h" + +#include <star/s3dut.h> +#include <rsys/clock_time.h> +#include <rsys/double3.h> + +#include <stdio.h> +#include <limits.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct s3dut_mesh* cyl = NULL; + struct s3dut_context ctx = { {NULL,NULL,0,0}, CONTEXT_NULL__ }; + unsigned count; + unsigned cyl_trg_count, cyl_vrtx_count, e; + char dump[64]; + struct time t0, t1; + (void)argc, (void)argv; + + OK(mem_init_regular_allocator(&allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* A 20 triangles 12 vertices cylinder template */ + S3DUT(create_cylinder(&allocator, 1, 1, 3, 1, &cyl)); + S3DUT(mesh_get_data(cyl, &ctx.data)); + ASSERT(ctx.data.nprimitives < UINT_MAX); + ASSERT(ctx.data.nvertices < UINT_MAX); + cyl_trg_count = (unsigned)ctx.data.nprimitives; + cyl_vrtx_count = (unsigned)ctx.data.nvertices; + + /* Create the scene with N_CYL cylinders. + * There are NB_CYL_X * NB_CYL_Y imbrications of NB_CYL_Z cylinders each. + * Each imbrication is located on a grid. + * The get_s3du_xxx getters have to retrieve the cylinder from the + * primitive and vertice indexes. */ + time_current(&t0); + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + NB_CYL * cyl_trg_count, get_s3dut_indices, get_s3dut_media, + NB_CYL * cyl_vrtx_count, get_s3dut_position, &ctx, &scn)); + time_sub(&t0, time_current(&t1), &t0); + time_dump(&t0, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump)); + printf("Scene created in: %s\n", dump); + S3DUT(mesh_ref_put(cyl)); + + OK(senc3d_scene_get_vertices_count(scn, &count)); + CHK(count == NB_CYL * cyl_vrtx_count); + OK(senc3d_scene_get_triangles_count(scn, &count)); + CHK(count == NB_CYL * cyl_trg_count); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1 + NB_CYL); + FOR_EACH(e, 0, count) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + unsigned m; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + CHK(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &m)); + CHK(header.primitives_count == + (header.is_infinite /* Outermost enclosure: NB_CYL_X*NB_CYL_Y cylinders */ + ? NB_CYL_X * NB_CYL_Y * cyl_trg_count + : (m == 0 + ? cyl_trg_count /* Innermost enclosures: 1 cylinder */ + : 2 * cyl_trg_count))); /* Other enclosures: 2 cylinders */ + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_regular_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_many_triangles.c b/src/test_senc3d_many_triangles.c @@ -0,0 +1,101 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test is similar to test_senc3d_some_triangles, but involves 4*2562560 + * triangles instead of 4*1054, thus making it impossible to define the geometry + * through static arrays. */ + +#define NB_CYL_X 2 +#define NB_CYL_Y 1 +#define NB_CYL_Z 1 + /* 4 cylinders */ +#define NB_CYL (NB_CYL_X * NB_CYL_Y * NB_CYL_Z) + +#include "senc3d.h" +#include "test_senc3d_utils.h" +#include "test_senc3d_utils2.h" + +#include <star/s3dut.h> +#include <rsys/clock_time.h> +#include <rsys/double3.h> + +#include <stdio.h> +#include <limits.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct s3dut_mesh* cyl = NULL; + struct s3dut_context ctx = { {NULL,NULL,0,0}, CONTEXT_NULL__ }; + unsigned m0 = 0; + unsigned count; + unsigned cyl_trg_count, cyl_vrtx_count, e; + char dump[64]; + struct time t0, t1; + (void)argc, (void)argv; + + OK(mem_init_regular_allocator(&allocator)); + OK(senc3d_device_create (NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* A 2,562,560 triangles 1,281,282 vertices cylinder template */ + S3DUT(create_cylinder(&allocator, 1, 2, 1280, 1000, &cyl)); + S3DUT(mesh_get_data(cyl, &ctx.data)); + ASSERT(ctx.data.nprimitives < UINT_MAX); + ASSERT(ctx.data.nvertices < UINT_MAX); + cyl_trg_count = (unsigned)ctx.data.nprimitives; + cyl_vrtx_count = (unsigned)ctx.data.nvertices; + + /* Create the scene with 4 cylinders. + * The get_s3du_xxx getters have to retrieve the cylinder from the + * primitive and vertice indexes. */ + ctx.ctx.back_media = &m0; + time_current(&t0); + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + NB_CYL* cyl_trg_count, get_s3dut_indices, get_s3dut_media, + NB_CYL* cyl_vrtx_count, get_s3dut_position, &ctx, &scn)); + time_sub(&t0, time_current(&t1), &t0); + time_dump(&t0, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump)); + printf("Scene created in: %s\n", dump); + S3DUT(mesh_ref_put(cyl)); + + OK(senc3d_scene_get_vertices_count(scn, &count)); + CHK(count == NB_CYL * cyl_vrtx_count); + OK(senc3d_scene_get_triangles_count(scn, &count)); + CHK(count == NB_CYL * cyl_trg_count); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1 + NB_CYL); + FOR_EACH(e, 0, count) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + CHK(header.primitives_count == + e ? cyl_trg_count : NB_CYL * cyl_trg_count); + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_regular_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_sample_enclosure.c b/src/test_senc3d_sample_enclosure.c @@ -0,0 +1,124 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "SENC3D_s3d_helper.h" +#include "test_SENC3D_utils.h" + +#include <rsys/float3.h> +#include <rsys/double3.h> + +#include <star/s3d.h> +#include <star/ssp.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct senc3d_enclosure* enclosure = NULL; + struct senc3d_enclosure_header header; + struct s3d_device* s3d = NULL; + struct s3d_scene* s3d_scn = NULL; + struct s3d_scene_view* s3d_view = NULL; + struct s3d_shape* s3d_shp = NULL; + struct s3d_primitive prim; + struct s3d_vertex_data vrtx_get; + struct ssp_rng* rng; + struct context ctx = CONTEXT_NULL__; + int i; + float st[2]; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* A 3D cube, but with a hole (incomplete). + * 1 single enclosure including both sides of triangles */ + ctx.positions = cube_vertices; + ctx.indices = box_indices; + ctx.front_media = medium0; + ctx.back_media = medium0; + + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles - 1, get_indices, get_media, nvertices, get_position, &ctx, + &scn)); + + OK(senc3d_scene_get_enclosure(scn, 0, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + /* Put enclosure in a 3D view... */ + vrtx_get.type = S3D_FLOAT3; + vrtx_get.usage = S3D_POSITION; + vrtx_get.get = SENC3D_s3d_enclosure_get_position; + S3D(device_create(NULL, &allocator, 0, &s3d)); + S3D(scene_create(s3d, &s3d_scn)); + S3D(shape_create_mesh(s3d, &s3d_shp)); + S3D(mesh_setup_indexed_vertices(s3d_shp, header.primitives_count, + SENC3D_s3d_enclosure_get_indices, header.vertices_count, &vrtx_get, 1, + enclosure)); + S3D(scene_attach_shape(s3d_scn, s3d_shp)); + S3D(scene_view_create(s3d_scn, S3D_SAMPLE, &s3d_view)); + + /* ... and sample it. */ + OK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng)); + FOR_EACH(i, 0, 10000) { + struct s3d_attrib attrib; + int n, c; + S3D(scene_view_sample(s3d_view, + ssp_rng_canonical_float(rng), + ssp_rng_canonical_float(rng), + ssp_rng_canonical_float(rng), + &prim, st)); + S3D(primitive_get_attrib(&prim, S3D_POSITION, st, &attrib)); + c = 0; + FOR_EACH(n, 0, 3) + if(eq_eps(attrib.value[n], 0, FLT_EPSILON) + || eq_eps(attrib.value[n], 1, FLT_EPSILON)) + c++; + CHK(c == 1); + S3D(primitive_get_attrib(&prim, S3D_GEOMETRY_NORMAL, st, &attrib)); + c = 0; + FOR_EACH(n, 0, 3) + if(eq_eps(attrib.value[n], -1, FLT_EPSILON) + || eq_eps(attrib.value[n], 1, FLT_EPSILON)) + c++; + CHK(c == 1); + c = 0; + FOR_EACH(n, 0, 3) + if(eq_eps(attrib.value[n], 0, FLT_EPSILON)) + c++; + CHK(c == 2); + } + + SENC3D(enclosure_ref_put(enclosure)); + SENC3D(scene_ref_put(scn)); + SENC3D(device_ref_put(dev)); + + SSP(rng_ref_put(rng)); + + S3D(shape_ref_put(s3d_shp)); + S3D(scene_view_ref_put(s3d_view)); + S3D(device_ref_put(s3d)); + S3D(scene_ref_put(s3d_scn)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + + return 0; +} diff --git a/src/test_senc3d_scene.c b/src/test_senc3d_scene.c @@ -0,0 +1,296 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/float3.h> +#include <rsys/double3.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct senc3d_enclosure* enc = NULL; + struct senc3d_enclosure_header header; + struct context ctx = CONTEXT_NULL__; + unsigned medfront[2], medback[2], ind[3], ids[2]; + double vrtx[3]; + unsigned count, i, maxm; + int convention; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* A 3D cube. + * With this geometry front is inside with NORMAL_BACK convention, + * outside with NORMAL_FRONT convention */ + ctx.positions = box_vertices; + ctx.indices = box_indices; + ctx.front_media = medium0; + ctx.back_media = medium1; + + BA(senc3d_scene_create(NULL, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc3d_scene_create(dev, + 0, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + 0, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, NULL, get_media, + nvertices, get_position, &ctx, &scn)); + BA(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + 0, get_position, &ctx, &scn)); + BA(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, NULL, &ctx, &scn)); + BA(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, NULL)); + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + BA(senc3d_scene_get_convention(NULL, &convention)); + BA(senc3d_scene_get_convention(scn, NULL)); + BA(senc3d_scene_get_convention(NULL, NULL)); + OK(senc3d_scene_get_convention(scn, &convention)); + CHK(convention + == (SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE)); + + BA(senc3d_scene_get_triangles_count(NULL, &count)); + BA(senc3d_scene_get_triangles_count(scn, NULL)); + BA(senc3d_scene_get_triangles_count(NULL, NULL)); + OK(senc3d_scene_get_triangles_count(scn, &count)); + CHK(count == ntriangles); + + BA(senc3d_scene_get_vertices_count(NULL, &count)); + BA(senc3d_scene_get_vertices_count(scn, NULL)); + BA(senc3d_scene_get_vertices_count(NULL, NULL)); + OK(senc3d_scene_get_vertices_count(scn, &count)); + CHK(count == nvertices); + + BA(senc3d_scene_get_triangle(NULL, 0, ind)); + BA(senc3d_scene_get_triangle(scn, UINT_MAX, ind)); + BA(senc3d_scene_get_triangle(scn, 0, NULL)); + BA(senc3d_scene_get_triangle(NULL, UINT_MAX, ind)); + BA(senc3d_scene_get_triangle(NULL, 0, NULL)); + BA(senc3d_scene_get_triangle(scn, UINT_MAX, NULL)); + BA(senc3d_scene_get_triangle(NULL, UINT_MAX, NULL)); + OK(senc3d_scene_get_triangle(scn, 0, ind)); + + BA(senc3d_scene_get_triangle_media(NULL, 0, ind)); + BA(senc3d_scene_get_triangle_media(scn, UINT_MAX, ind)); + BA(senc3d_scene_get_triangle_media(scn, 0, NULL)); + BA(senc3d_scene_get_triangle_media(NULL, UINT_MAX, ind)); + BA(senc3d_scene_get_triangle_media(NULL, 0, NULL)); + BA(senc3d_scene_get_triangle_media(scn, UINT_MAX, NULL)); + BA(senc3d_scene_get_triangle_media(NULL, UINT_MAX, NULL)); + OK(senc3d_scene_get_triangle_media(scn, 0, ind)); + + BA(senc3d_scene_get_vertex(NULL, 0, vrtx)); + BA(senc3d_scene_get_vertex(scn, UINT_MAX, vrtx)); + BA(senc3d_scene_get_vertex(scn, 0, NULL)); + BA(senc3d_scene_get_vertex(NULL, UINT_MAX, vrtx)); + BA(senc3d_scene_get_vertex(NULL, 0, NULL)); + BA(senc3d_scene_get_vertex(scn, UINT_MAX, NULL)); + BA(senc3d_scene_get_vertex(NULL, UINT_MAX, NULL)); + OK(senc3d_scene_get_vertex(scn, 0, vrtx)); + + BA(senc3d_scene_get_max_medium(NULL, &maxm)); + BA(senc3d_scene_get_max_medium(scn, NULL)); + BA(senc3d_scene_get_max_medium(NULL, NULL)); + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 1); + + BA(senc3d_scene_get_enclosure_count(NULL, &count)); + BA(senc3d_scene_get_enclosure_count(scn, NULL)); + BA(senc3d_scene_get_enclosure_count(NULL, NULL)); + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 2); + + BA(senc3d_scene_get_enclosure_count_by_medium(NULL, 0, &count)); + BA(senc3d_scene_get_enclosure_count_by_medium(scn, 100, &count)); + BA(senc3d_scene_get_enclosure_count_by_medium(scn, 0, NULL)); + BA(senc3d_scene_get_enclosure_count_by_medium(NULL, 100, &count)); + BA(senc3d_scene_get_enclosure_count_by_medium(NULL, 0, NULL)); + BA(senc3d_scene_get_enclosure_count_by_medium(scn, 100, NULL)); + BA(senc3d_scene_get_enclosure_count_by_medium(NULL, 100, NULL)); + OK(senc3d_scene_get_enclosure_count_by_medium(scn, 0, &count)); + CHK(count == 1); + OK(senc3d_scene_get_enclosure_count_by_medium(scn, SENC3D_UNSPECIFIED_MEDIUM, + &count)); + CHK(count == 0); + + BA(senc3d_scene_get_enclosure(NULL, 0, &enc)); + BA(senc3d_scene_get_enclosure(scn, UINT_MAX, &enc)); + BA(senc3d_scene_get_enclosure(scn, 0, NULL)); + BA(senc3d_scene_get_enclosure(NULL, UINT_MAX, &enc)); + BA(senc3d_scene_get_enclosure(NULL, 0, NULL)); + BA(senc3d_scene_get_enclosure(scn, UINT_MAX, NULL)); + BA(senc3d_scene_get_enclosure(NULL, UINT_MAX, NULL)); + OK(senc3d_scene_get_enclosure(scn, 0, &enc)); + OK(senc3d_enclosure_ref_put(enc)); + + BA(senc3d_scene_get_enclosure_by_medium(NULL, 0, 0, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 100, 0, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 0, UINT_MAX, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 0, 0, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 100, 0, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 0, UINT_MAX, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 0, 0, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 100, UINT_MAX, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 100, 0, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 0, UINT_MAX, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(scn, 100, UINT_MAX, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 0, UINT_MAX, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 100, 0, NULL)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 100, UINT_MAX, &enc)); + BA(senc3d_scene_get_enclosure_by_medium(NULL, 100, UINT_MAX, NULL)); + OK(senc3d_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); + OK(senc3d_enclosure_ref_put(enc)); + /* Index 0 is out of range for SENC3D_UNSPECIFIED_MEDIUM. */ + BA(senc3d_scene_get_enclosure_by_medium(scn, SENC3D_UNSPECIFIED_MEDIUM, 0, &enc)); + + BA(senc3d_scene_get_triangle_enclosures(NULL, 0, ids)); + BA(senc3d_scene_get_triangle_enclosures(scn, UINT_MAX, ids)); + BA(senc3d_scene_get_triangle_enclosures(scn, 0, NULL)); + BA(senc3d_scene_get_triangle_enclosures(NULL, UINT_MAX, ids)); + BA(senc3d_scene_get_triangle_enclosures(NULL, 0, NULL)); + BA(senc3d_scene_get_triangle_enclosures(scn, UINT_MAX, NULL)); + BA(senc3d_scene_get_triangle_enclosures(NULL, UINT_MAX, NULL)); + OK(senc3d_scene_get_triangle_enclosures(scn, 0, ids)); + + BA(senc3d_scene_get_frontier_segments_count(NULL, &count)); + BA(senc3d_scene_get_frontier_segments_count(scn, NULL)); + BA(senc3d_scene_get_frontier_segments_count(NULL, NULL)); + OK(senc3d_scene_get_frontier_segments_count(scn, &count)); + CHK(count == 0); + + BA(senc3d_scene_get_frontier_segment(NULL, 0, ids)); + BA(senc3d_scene_get_frontier_segment(scn, UINT_MAX, ids)); + BA(senc3d_scene_get_frontier_segment(scn, 0, NULL)); + BA(senc3d_scene_get_frontier_segment(NULL, UINT_MAX, ids)); + BA(senc3d_scene_get_frontier_segment(NULL, 0, NULL)); + BA(senc3d_scene_get_frontier_segment(scn, UINT_MAX, NULL)); + BA(senc3d_scene_get_frontier_segment(NULL, UINT_MAX, NULL)); + + BA(senc3d_scene_ref_get(NULL)); + OK(senc3d_scene_ref_get(scn)); + BA(senc3d_scene_ref_put(NULL)); + OK(senc3d_scene_ref_put(scn)); + + OK(senc3d_scene_ref_put(scn)); + + /* Same geometry with SENC3D_UNSPECIFIED_MEDIUM */ + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, NULL, + nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_by_medium(scn, SENC3D_UNSPECIFIED_MEDIUM, 0, &enc)); + OK(senc3d_enclosure_ref_put(enc)); + BA(senc3d_scene_get_enclosure_by_medium(scn, SENC3D_UNSPECIFIED_MEDIUM, 100, &enc)); + + OK(senc3d_scene_ref_put(scn)); + + /* Same geometry with a hole (1 missing triangle) */ + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles - 1, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_frontier_segments_count(scn, &count)); + CHK(count == 3); + OK(senc3d_scene_get_frontier_segment(scn, 0, ids)); + BA(senc3d_scene_get_frontier_segment(scn, 3, ids)); + + OK(senc3d_scene_ref_put(scn)); + + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_convention(scn, &convention)); + CHK(convention + == (SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_INSIDE)); + /* Check that medium 0 is inside */ + OK(senc3d_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); + OK(senc3d_enclosure_get_header(enc, &header)); + CHK(!header.is_infinite); + OK(senc3d_enclosure_ref_put(enc)); + + OK(senc3d_scene_get_triangle_media(scn, 0, medback)); + OK(senc3d_scene_ref_put(scn)); + + /* Medium mismatch between neighbour segments, but OK */ + ctx.front_media = medium1_3; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == 3); + OK(senc3d_scene_get_enclosure_count_by_medium(scn, 0, &count)); + CHK(count == 0); /* Medium 0 unused */ + OK(senc3d_scene_get_enclosure_count_by_medium(scn, 1, &count)); + CHK(count == 2); /* Medium 1 used twice */ + OK(senc3d_scene_get_enclosure_count_by_medium(scn, 2, &count)); + CHK(count == 0); /* Medium 2 unused */ + OK(senc3d_scene_get_enclosure_count_by_medium(scn, 3, &count)); + CHK(count == 1); /* Medium 3 used */ + + OK(senc3d_scene_ref_put(scn)); + + ctx.front_media = medium0; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, get_media, + nvertices, get_position, &ctx, &scn)); + /* Check that medium 0 is outside */ + OK(senc3d_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); + OK(senc3d_enclosure_get_header(enc, &header)); + CHK(header.is_infinite); + OK(senc3d_enclosure_ref_put(enc)); + + OK(senc3d_scene_get_triangle_media(scn, 0, medfront)); + FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]); + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + + return 0; +} diff --git a/src/test_senc3d_some_enclosures.c b/src/test_senc3d_some_enclosures.c @@ -0,0 +1,3427 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_some_enclosures. + * This test is similar to test_SENC3D_many_enclosures that creates a huge + * geometry by program. */ + +#include "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +/* Dump of star-geometry 'some_enclosures'. */ +static const unsigned some_enclosures_vertices_count = 768; +static const double some_enclosures_vertices[2304] = +{ + -19, -20, -0.5, + -19, -20, 0.5, + -19.691, -19.0489, -0.5, + -19.691, -19.0489, 0.5, + -20.809, -19.4122, -0.5, + -20.809, -19.4122, 0.5, + -20.809, -20.5878, -0.5, + -20.809, -20.5878, 0.5, + -19.691, -20.9511, -0.5, + -19.691, -20.9511, 0.5, + -20, -20, -0.5, + -20, -20, 0.5, + -18, -20, -1, + -18, -20, 1, + -19.382, -18.0979, -1, + -19.382, -18.0979, 1, + -21.618, -18.8244, -1, + -21.618, -18.8244, 1, + -21.618, -21.1756, -1, + -21.618, -21.1756, 1, + -19.382, -21.9021, -1, + -19.382, -21.9021, 1, + -20, -20, -1, + -20, -20, 1, + -17, -20, -1.5, + -17, -20, 1.5, + -19.0729, -17.1468, -1.5, + -19.0729, -17.1468, 1.5, + -22.4271, -18.2366, -1.5, + -22.4271, -18.2366, 1.5, + -22.4271, -21.7634, -1.5, + -22.4271, -21.7634, 1.5, + -19.0729, -22.8532, -1.5, + -19.0729, -22.8532, 1.5, + -20, -20, -1.5, + -20, -20, 1.5, + -16, -20, -2, + -16, -20, 2, + -18.7639, -16.1958, -2, + -18.7639, -16.1958, 2, + -23.2361, -17.6489, -2, + -23.2361, -17.6489, 2, + -23.2361, -22.3511, -2, + -23.2361, -22.3511, 2, + -18.7639, -23.8042, -2, + -18.7639, -23.8042, 2, + -20, -20, -2, + -20, -20, 2, + -19, -10, -0.5, + -19, -10, 0.5, + -19.691, -9.04894, -0.5, + -19.691, -9.04894, 0.5, + -20.809, -9.41221, -0.5, + -20.809, -9.41221, 0.5, + -20.809, -10.5878, -0.5, + -20.809, -10.5878, 0.5, + -19.691, -10.9511, -0.5, + -19.691, -10.9511, 0.5, + -20, -10, -0.5, + -20, -10, 0.5, + -18, -10, -1, + -18, -10, 1, + -19.382, -8.09789, -1, + -19.382, -8.09789, 1, + -21.618, -8.82443, -1, + -21.618, -8.82443, 1, + -21.618, -11.1756, -1, + -21.618, -11.1756, 1, + -19.382, -11.9021, -1, + -19.382, -11.9021, 1, + -20, -10, -1, + -20, -10, 1, + -17, -10, -1.5, + -17, -10, 1.5, + -19.0729, -7.14683, -1.5, + -19.0729, -7.14683, 1.5, + -22.4271, -8.23664, -1.5, + -22.4271, -8.23664, 1.5, + -22.4271, -11.7634, -1.5, + -22.4271, -11.7634, 1.5, + -19.0729, -12.8532, -1.5, + -19.0729, -12.8532, 1.5, + -20, -10, -1.5, + -20, -10, 1.5, + -16, -10, -2, + -16, -10, 2, + -18.7639, -6.19577, -2, + -18.7639, -6.19577, 2, + -23.2361, -7.64886, -2, + -23.2361, -7.64886, 2, + -23.2361, -12.3511, -2, + -23.2361, -12.3511, 2, + -18.7639, -13.8042, -2, + -18.7639, -13.8042, 2, + -20, -10, -2, + -20, -10, 2, + -19, 0, -0.5, + -19, 0, 0.5, + -19.691, 0.951057, -0.5, + -19.691, 0.951057, 0.5, + -20.809, 0.587785, -0.5, + -20.809, 0.587785, 0.5, + -20.809, -0.587785, -0.5, + -20.809, -0.587785, 0.5, + -19.691, -0.951057, -0.5, + -19.691, -0.951057, 0.5, + -20, 0, -0.5, + -20, 0, 0.5, + -18, 0, -1, + -18, 0, 1, + -19.382, 1.90211, -1, + -19.382, 1.90211, 1, + -21.618, 1.17557, -1, + -21.618, 1.17557, 1, + -21.618, -1.17557, -1, + -21.618, -1.17557, 1, + -19.382, -1.90211, -1, + -19.382, -1.90211, 1, + -20, 0, -1, + -20, 0, 1, + -17, 0, -1.5, + -17, 0, 1.5, + -19.0729, 2.85317, -1.5, + -19.0729, 2.85317, 1.5, + -22.4271, 1.76336, -1.5, + -22.4271, 1.76336, 1.5, + -22.4271, -1.76336, -1.5, + -22.4271, -1.76336, 1.5, + -19.0729, -2.85317, -1.5, + -19.0729, -2.85317, 1.5, + -20, 0, -1.5, + -20, 0, 1.5, + -16, 0, -2, + -16, 0, 2, + -18.7639, 3.80423, -2, + -18.7639, 3.80423, 2, + -23.2361, 2.35114, -2, + -23.2361, 2.35114, 2, + -23.2361, -2.35114, -2, + -23.2361, -2.35114, 2, + -18.7639, -3.80423, -2, + -18.7639, -3.80423, 2, + -20, 0, -2, + -20, 0, 2, + -19, 10, -0.5, + -19, 10, 0.5, + -19.691, 10.9511, -0.5, + -19.691, 10.9511, 0.5, + -20.809, 10.5878, -0.5, + -20.809, 10.5878, 0.5, + -20.809, 9.41221, -0.5, + -20.809, 9.41221, 0.5, + -19.691, 9.04894, -0.5, + -19.691, 9.04894, 0.5, + -20, 10, -0.5, + -20, 10, 0.5, + -18, 10, -1, + -18, 10, 1, + -19.382, 11.9021, -1, + -19.382, 11.9021, 1, + -21.618, 11.1756, -1, + -21.618, 11.1756, 1, + -21.618, 8.82443, -1, + -21.618, 8.82443, 1, + -19.382, 8.09789, -1, + -19.382, 8.09789, 1, + -20, 10, -1, + -20, 10, 1, + -17, 10, -1.5, + -17, 10, 1.5, + -19.0729, 12.8532, -1.5, + -19.0729, 12.8532, 1.5, + -22.4271, 11.7634, -1.5, + -22.4271, 11.7634, 1.5, + -22.4271, 8.23664, -1.5, + -22.4271, 8.23664, 1.5, + -19.0729, 7.14683, -1.5, + -19.0729, 7.14683, 1.5, + -20, 10, -1.5, + -20, 10, 1.5, + -16, 10, -2, + -16, 10, 2, + -18.7639, 13.8042, -2, + -18.7639, 13.8042, 2, + -23.2361, 12.3511, -2, + -23.2361, 12.3511, 2, + -23.2361, 7.64886, -2, + -23.2361, 7.64886, 2, + -18.7639, 6.19577, -2, + -18.7639, 6.19577, 2, + -20, 10, -2, + -20, 10, 2, + -9, -20, -0.5, + -9, -20, 0.5, + -9.69098, -19.0489, -0.5, + -9.69098, -19.0489, 0.5, + -10.809, -19.4122, -0.5, + -10.809, -19.4122, 0.5, + -10.809, -20.5878, -0.5, + -10.809, -20.5878, 0.5, + -9.69098, -20.9511, -0.5, + -9.69098, -20.9511, 0.5, + -10, -20, -0.5, + -10, -20, 0.5, + -8, -20, -1, + -8, -20, 1, + -9.38197, -18.0979, -1, + -9.38197, -18.0979, 1, + -11.618, -18.8244, -1, + -11.618, -18.8244, 1, + -11.618, -21.1756, -1, + -11.618, -21.1756, 1, + -9.38197, -21.9021, -1, + -9.38197, -21.9021, 1, + -10, -20, -1, + -10, -20, 1, + -7, -20, -1.5, + -7, -20, 1.5, + -9.07295, -17.1468, -1.5, + -9.07295, -17.1468, 1.5, + -12.4271, -18.2366, -1.5, + -12.4271, -18.2366, 1.5, + -12.4271, -21.7634, -1.5, + -12.4271, -21.7634, 1.5, + -9.07295, -22.8532, -1.5, + -9.07295, -22.8532, 1.5, + -10, -20, -1.5, + -10, -20, 1.5, + -6, -20, -2, + -6, -20, 2, + -8.76393, -16.1958, -2, + -8.76393, -16.1958, 2, + -13.2361, -17.6489, -2, + -13.2361, -17.6489, 2, + -13.2361, -22.3511, -2, + -13.2361, -22.3511, 2, + -8.76393, -23.8042, -2, + -8.76393, -23.8042, 2, + -10, -20, -2, + -10, -20, 2, + -9, -10, -0.5, + -9, -10, 0.5, + -9.69098, -9.04894, -0.5, + -9.69098, -9.04894, 0.5, + -10.809, -9.41221, -0.5, + -10.809, -9.41221, 0.5, + -10.809, -10.5878, -0.5, + -10.809, -10.5878, 0.5, + -9.69098, -10.9511, -0.5, + -9.69098, -10.9511, 0.5, + -10, -10, -0.5, + -10, -10, 0.5, + -8, -10, -1, + -8, -10, 1, + -9.38197, -8.09789, -1, + -9.38197, -8.09789, 1, + -11.618, -8.82443, -1, + -11.618, -8.82443, 1, + -11.618, -11.1756, -1, + -11.618, -11.1756, 1, + -9.38197, -11.9021, -1, + -9.38197, -11.9021, 1, + -10, -10, -1, + -10, -10, 1, + -7, -10, -1.5, + -7, -10, 1.5, + -9.07295, -7.14683, -1.5, + -9.07295, -7.14683, 1.5, + -12.4271, -8.23664, -1.5, + -12.4271, -8.23664, 1.5, + -12.4271, -11.7634, -1.5, + -12.4271, -11.7634, 1.5, + -9.07295, -12.8532, -1.5, + -9.07295, -12.8532, 1.5, + -10, -10, -1.5, + -10, -10, 1.5, + -6, -10, -2, + -6, -10, 2, + -8.76393, -6.19577, -2, + -8.76393, -6.19577, 2, + -13.2361, -7.64886, -2, + -13.2361, -7.64886, 2, + -13.2361, -12.3511, -2, + -13.2361, -12.3511, 2, + -8.76393, -13.8042, -2, + -8.76393, -13.8042, 2, + -10, -10, -2, + -10, -10, 2, + -9, 0, -0.5, + -9, 0, 0.5, + -9.69098, 0.951057, -0.5, + -9.69098, 0.951057, 0.5, + -10.809, 0.587785, -0.5, + -10.809, 0.587785, 0.5, + -10.809, -0.587785, -0.5, + -10.809, -0.587785, 0.5, + -9.69098, -0.951057, -0.5, + -9.69098, -0.951057, 0.5, + -10, 0, -0.5, + -10, 0, 0.5, + -8, 0, -1, + -8, 0, 1, + -9.38197, 1.90211, -1, + -9.38197, 1.90211, 1, + -11.618, 1.17557, -1, + -11.618, 1.17557, 1, + -11.618, -1.17557, -1, + -11.618, -1.17557, 1, + -9.38197, -1.90211, -1, + -9.38197, -1.90211, 1, + -10, 0, -1, + -10, 0, 1, + -7, 0, -1.5, + -7, 0, 1.5, + -9.07295, 2.85317, -1.5, + -9.07295, 2.85317, 1.5, + -12.4271, 1.76336, -1.5, + -12.4271, 1.76336, 1.5, + -12.4271, -1.76336, -1.5, + -12.4271, -1.76336, 1.5, + -9.07295, -2.85317, -1.5, + -9.07295, -2.85317, 1.5, + -10, 0, -1.5, + -10, 0, 1.5, + -6, 0, -2, + -6, 0, 2, + -8.76393, 3.80423, -2, + -8.76393, 3.80423, 2, + -13.2361, 2.35114, -2, + -13.2361, 2.35114, 2, + -13.2361, -2.35114, -2, + -13.2361, -2.35114, 2, + -8.76393, -3.80423, -2, + -8.76393, -3.80423, 2, + -10, 0, -2, + -10, 0, 2, + -9, 10, -0.5, + -9, 10, 0.5, + -9.69098, 10.9511, -0.5, + -9.69098, 10.9511, 0.5, + -10.809, 10.5878, -0.5, + -10.809, 10.5878, 0.5, + -10.809, 9.41221, -0.5, + -10.809, 9.41221, 0.5, + -9.69098, 9.04894, -0.5, + -9.69098, 9.04894, 0.5, + -10, 10, -0.5, + -10, 10, 0.5, + -8, 10, -1, + -8, 10, 1, + -9.38197, 11.9021, -1, + -9.38197, 11.9021, 1, + -11.618, 11.1756, -1, + -11.618, 11.1756, 1, + -11.618, 8.82443, -1, + -11.618, 8.82443, 1, + -9.38197, 8.09789, -1, + -9.38197, 8.09789, 1, + -10, 10, -1, + -10, 10, 1, + -7, 10, -1.5, + -7, 10, 1.5, + -9.07295, 12.8532, -1.5, + -9.07295, 12.8532, 1.5, + -12.4271, 11.7634, -1.5, + -12.4271, 11.7634, 1.5, + -12.4271, 8.23664, -1.5, + -12.4271, 8.23664, 1.5, + -9.07295, 7.14683, -1.5, + -9.07295, 7.14683, 1.5, + -10, 10, -1.5, + -10, 10, 1.5, + -6, 10, -2, + -6, 10, 2, + -8.76393, 13.8042, -2, + -8.76393, 13.8042, 2, + -13.2361, 12.3511, -2, + -13.2361, 12.3511, 2, + -13.2361, 7.64886, -2, + -13.2361, 7.64886, 2, + -8.76393, 6.19577, -2, + -8.76393, 6.19577, 2, + -10, 10, -2, + -10, 10, 2, + 1, -20, -0.5, + 1, -20, 0.5, + 0.309017, -19.0489, -0.5, + 0.309017, -19.0489, 0.5, + -0.809017, -19.4122, -0.5, + -0.809017, -19.4122, 0.5, + -0.809017, -20.5878, -0.5, + -0.809017, -20.5878, 0.5, + 0.309017, -20.9511, -0.5, + 0.309017, -20.9511, 0.5, + 0, -20, -0.5, + 0, -20, 0.5, + 2, -20, -1, + 2, -20, 1, + 0.618034, -18.0979, -1, + 0.618034, -18.0979, 1, + -1.61803, -18.8244, -1, + -1.61803, -18.8244, 1, + -1.61803, -21.1756, -1, + -1.61803, -21.1756, 1, + 0.618034, -21.9021, -1, + 0.618034, -21.9021, 1, + 0, -20, -1, + 0, -20, 1, + 3, -20, -1.5, + 3, -20, 1.5, + 0.927051, -17.1468, -1.5, + 0.927051, -17.1468, 1.5, + -2.42705, -18.2366, -1.5, + -2.42705, -18.2366, 1.5, + -2.42705, -21.7634, -1.5, + -2.42705, -21.7634, 1.5, + 0.927051, -22.8532, -1.5, + 0.927051, -22.8532, 1.5, + 0, -20, -1.5, + 0, -20, 1.5, + 4, -20, -2, + 4, -20, 2, + 1.23607, -16.1958, -2, + 1.23607, -16.1958, 2, + -3.23607, -17.6489, -2, + -3.23607, -17.6489, 2, + -3.23607, -22.3511, -2, + -3.23607, -22.3511, 2, + 1.23607, -23.8042, -2, + 1.23607, -23.8042, 2, + 0, -20, -2, + 0, -20, 2, + 1, -10, -0.5, + 1, -10, 0.5, + 0.309017, -9.04894, -0.5, + 0.309017, -9.04894, 0.5, + -0.809017, -9.41221, -0.5, + -0.809017, -9.41221, 0.5, + -0.809017, -10.5878, -0.5, + -0.809017, -10.5878, 0.5, + 0.309017, -10.9511, -0.5, + 0.309017, -10.9511, 0.5, + 0, -10, -0.5, + 0, -10, 0.5, + 2, -10, -1, + 2, -10, 1, + 0.618034, -8.09789, -1, + 0.618034, -8.09789, 1, + -1.61803, -8.82443, -1, + -1.61803, -8.82443, 1, + -1.61803, -11.1756, -1, + -1.61803, -11.1756, 1, + 0.618034, -11.9021, -1, + 0.618034, -11.9021, 1, + 0, -10, -1, + 0, -10, 1, + 3, -10, -1.5, + 3, -10, 1.5, + 0.927051, -7.14683, -1.5, + 0.927051, -7.14683, 1.5, + -2.42705, -8.23664, -1.5, + -2.42705, -8.23664, 1.5, + -2.42705, -11.7634, -1.5, + -2.42705, -11.7634, 1.5, + 0.927051, -12.8532, -1.5, + 0.927051, -12.8532, 1.5, + 0, -10, -1.5, + 0, -10, 1.5, + 4, -10, -2, + 4, -10, 2, + 1.23607, -6.19577, -2, + 1.23607, -6.19577, 2, + -3.23607, -7.64886, -2, + -3.23607, -7.64886, 2, + -3.23607, -12.3511, -2, + -3.23607, -12.3511, 2, + 1.23607, -13.8042, -2, + 1.23607, -13.8042, 2, + 0, -10, -2, + 0, -10, 2, + 1, 0, -0.5, + 1, 0, 0.5, + 0.309017, 0.951057, -0.5, + 0.309017, 0.951057, 0.5, + -0.809017, 0.587785, -0.5, + -0.809017, 0.587785, 0.5, + -0.809017, -0.587785, -0.5, + -0.809017, -0.587785, 0.5, + 0.309017, -0.951057, -0.5, + 0.309017, -0.951057, 0.5, + 0, 0, -0.5, + 0, 0, 0.5, + 2, 0, -1, + 2, 0, 1, + 0.618034, 1.90211, -1, + 0.618034, 1.90211, 1, + -1.61803, 1.17557, -1, + -1.61803, 1.17557, 1, + -1.61803, -1.17557, -1, + -1.61803, -1.17557, 1, + 0.618034, -1.90211, -1, + 0.618034, -1.90211, 1, + 0, 0, -1, + 0, 0, 1, + 3, 0, -1.5, + 3, 0, 1.5, + 0.927051, 2.85317, -1.5, + 0.927051, 2.85317, 1.5, + -2.42705, 1.76336, -1.5, + -2.42705, 1.76336, 1.5, + -2.42705, -1.76336, -1.5, + -2.42705, -1.76336, 1.5, + 0.927051, -2.85317, -1.5, + 0.927051, -2.85317, 1.5, + 0, 0, -1.5, + 0, 0, 1.5, + 4, 0, -2, + 4, 0, 2, + 1.23607, 3.80423, -2, + 1.23607, 3.80423, 2, + -3.23607, 2.35114, -2, + -3.23607, 2.35114, 2, + -3.23607, -2.35114, -2, + -3.23607, -2.35114, 2, + 1.23607, -3.80423, -2, + 1.23607, -3.80423, 2, + 0, 0, -2, + 0, 0, 2, + 1, 10, -0.5, + 1, 10, 0.5, + 0.309017, 10.9511, -0.5, + 0.309017, 10.9511, 0.5, + -0.809017, 10.5878, -0.5, + -0.809017, 10.5878, 0.5, + -0.809017, 9.41221, -0.5, + -0.809017, 9.41221, 0.5, + 0.309017, 9.04894, -0.5, + 0.309017, 9.04894, 0.5, + 0, 10, -0.5, + 0, 10, 0.5, + 2, 10, -1, + 2, 10, 1, + 0.618034, 11.9021, -1, + 0.618034, 11.9021, 1, + -1.61803, 11.1756, -1, + -1.61803, 11.1756, 1, + -1.61803, 8.82443, -1, + -1.61803, 8.82443, 1, + 0.618034, 8.09789, -1, + 0.618034, 8.09789, 1, + 0, 10, -1, + 0, 10, 1, + 3, 10, -1.5, + 3, 10, 1.5, + 0.927051, 12.8532, -1.5, + 0.927051, 12.8532, 1.5, + -2.42705, 11.7634, -1.5, + -2.42705, 11.7634, 1.5, + -2.42705, 8.23664, -1.5, + -2.42705, 8.23664, 1.5, + 0.927051, 7.14683, -1.5, + 0.927051, 7.14683, 1.5, + 0, 10, -1.5, + 0, 10, 1.5, + 4, 10, -2, + 4, 10, 2, + 1.23607, 13.8042, -2, + 1.23607, 13.8042, 2, + -3.23607, 12.3511, -2, + -3.23607, 12.3511, 2, + -3.23607, 7.64886, -2, + -3.23607, 7.64886, 2, + 1.23607, 6.19577, -2, + 1.23607, 6.19577, 2, + 0, 10, -2, + 0, 10, 2, + 11, -20, -0.5, + 11, -20, 0.5, + 10.309, -19.0489, -0.5, + 10.309, -19.0489, 0.5, + 9.19098, -19.4122, -0.5, + 9.19098, -19.4122, 0.5, + 9.19098, -20.5878, -0.5, + 9.19098, -20.5878, 0.5, + 10.309, -20.9511, -0.5, + 10.309, -20.9511, 0.5, + 10, -20, -0.5, + 10, -20, 0.5, + 12, -20, -1, + 12, -20, 1, + 10.618, -18.0979, -1, + 10.618, -18.0979, 1, + 8.38197, -18.8244, -1, + 8.38197, -18.8244, 1, + 8.38197, -21.1756, -1, + 8.38197, -21.1756, 1, + 10.618, -21.9021, -1, + 10.618, -21.9021, 1, + 10, -20, -1, + 10, -20, 1, + 13, -20, -1.5, + 13, -20, 1.5, + 10.9271, -17.1468, -1.5, + 10.9271, -17.1468, 1.5, + 7.57295, -18.2366, -1.5, + 7.57295, -18.2366, 1.5, + 7.57295, -21.7634, -1.5, + 7.57295, -21.7634, 1.5, + 10.9271, -22.8532, -1.5, + 10.9271, -22.8532, 1.5, + 10, -20, -1.5, + 10, -20, 1.5, + 14, -20, -2, + 14, -20, 2, + 11.2361, -16.1958, -2, + 11.2361, -16.1958, 2, + 6.76393, -17.6489, -2, + 6.76393, -17.6489, 2, + 6.76393, -22.3511, -2, + 6.76393, -22.3511, 2, + 11.2361, -23.8042, -2, + 11.2361, -23.8042, 2, + 10, -20, -2, + 10, -20, 2, + 11, -10, -0.5, + 11, -10, 0.5, + 10.309, -9.04894, -0.5, + 10.309, -9.04894, 0.5, + 9.19098, -9.41221, -0.5, + 9.19098, -9.41221, 0.5, + 9.19098, -10.5878, -0.5, + 9.19098, -10.5878, 0.5, + 10.309, -10.9511, -0.5, + 10.309, -10.9511, 0.5, + 10, -10, -0.5, + 10, -10, 0.5, + 12, -10, -1, + 12, -10, 1, + 10.618, -8.09789, -1, + 10.618, -8.09789, 1, + 8.38197, -8.82443, -1, + 8.38197, -8.82443, 1, + 8.38197, -11.1756, -1, + 8.38197, -11.1756, 1, + 10.618, -11.9021, -1, + 10.618, -11.9021, 1, + 10, -10, -1, + 10, -10, 1, + 13, -10, -1.5, + 13, -10, 1.5, + 10.9271, -7.14683, -1.5, + 10.9271, -7.14683, 1.5, + 7.57295, -8.23664, -1.5, + 7.57295, -8.23664, 1.5, + 7.57295, -11.7634, -1.5, + 7.57295, -11.7634, 1.5, + 10.9271, -12.8532, -1.5, + 10.9271, -12.8532, 1.5, + 10, -10, -1.5, + 10, -10, 1.5, + 14, -10, -2, + 14, -10, 2, + 11.2361, -6.19577, -2, + 11.2361, -6.19577, 2, + 6.76393, -7.64886, -2, + 6.76393, -7.64886, 2, + 6.76393, -12.3511, -2, + 6.76393, -12.3511, 2, + 11.2361, -13.8042, -2, + 11.2361, -13.8042, 2, + 10, -10, -2, + 10, -10, 2, + 11, 0, -0.5, + 11, 0, 0.5, + 10.309, 0.951057, -0.5, + 10.309, 0.951057, 0.5, + 9.19098, 0.587785, -0.5, + 9.19098, 0.587785, 0.5, + 9.19098, -0.587785, -0.5, + 9.19098, -0.587785, 0.5, + 10.309, -0.951057, -0.5, + 10.309, -0.951057, 0.5, + 10, 0, -0.5, + 10, 0, 0.5, + 12, 0, -1, + 12, 0, 1, + 10.618, 1.90211, -1, + 10.618, 1.90211, 1, + 8.38197, 1.17557, -1, + 8.38197, 1.17557, 1, + 8.38197, -1.17557, -1, + 8.38197, -1.17557, 1, + 10.618, -1.90211, -1, + 10.618, -1.90211, 1, + 10, 0, -1, + 10, 0, 1, + 13, 0, -1.5, + 13, 0, 1.5, + 10.9271, 2.85317, -1.5, + 10.9271, 2.85317, 1.5, + 7.57295, 1.76336, -1.5, + 7.57295, 1.76336, 1.5, + 7.57295, -1.76336, -1.5, + 7.57295, -1.76336, 1.5, + 10.9271, -2.85317, -1.5, + 10.9271, -2.85317, 1.5, + 10, 0, -1.5, + 10, 0, 1.5, + 14, 0, -2, + 14, 0, 2, + 11.2361, 3.80423, -2, + 11.2361, 3.80423, 2, + 6.76393, 2.35114, -2, + 6.76393, 2.35114, 2, + 6.76393, -2.35114, -2, + 6.76393, -2.35114, 2, + 11.2361, -3.80423, -2, + 11.2361, -3.80423, 2, + 10, 0, -2, + 10, 0, 2, + 11, 10, -0.5, + 11, 10, 0.5, + 10.309, 10.9511, -0.5, + 10.309, 10.9511, 0.5, + 9.19098, 10.5878, -0.5, + 9.19098, 10.5878, 0.5, + 9.19098, 9.41221, -0.5, + 9.19098, 9.41221, 0.5, + 10.309, 9.04894, -0.5, + 10.309, 9.04894, 0.5, + 10, 10, -0.5, + 10, 10, 0.5, + 12, 10, -1, + 12, 10, 1, + 10.618, 11.9021, -1, + 10.618, 11.9021, 1, + 8.38197, 11.1756, -1, + 8.38197, 11.1756, 1, + 8.38197, 8.82443, -1, + 8.38197, 8.82443, 1, + 10.618, 8.09789, -1, + 10.618, 8.09789, 1, + 10, 10, -1, + 10, 10, 1, + 13, 10, -1.5, + 13, 10, 1.5, + 10.9271, 12.8532, -1.5, + 10.9271, 12.8532, 1.5, + 7.57295, 11.7634, -1.5, + 7.57295, 11.7634, 1.5, + 7.57295, 8.23664, -1.5, + 7.57295, 8.23664, 1.5, + 10.9271, 7.14683, -1.5, + 10.9271, 7.14683, 1.5, + 10, 10, -1.5, + 10, 10, 1.5, + 14, 10, -2, + 14, 10, 2, + 11.2361, 13.8042, -2, + 11.2361, 13.8042, 2, + 6.76393, 12.3511, -2, + 6.76393, 12.3511, 2, + 6.76393, 7.64886, -2, + 6.76393, 7.64886, 2, + 11.2361, 6.19577, -2, + 11.2361, 6.19577, 2, + 10, 10, -2, + 10, 10, 2 +}; +static const unsigned some_enclosures_triangles_count = 1280; +static const unsigned some_enclosures_triangles[3840] = +{ + 0, 1, 2, + 2, 1, 3, + 2, 3, 4, + 4, 3, 5, + 4, 5, 6, + 6, 5, 7, + 6, 7, 8, + 8, 7, 9, + 8, 9, 0, + 0, 9, 1, + 10, 0, 2, + 10, 2, 4, + 10, 4, 6, + 10, 6, 8, + 10, 8, 0, + 11, 3, 1, + 11, 5, 3, + 11, 7, 5, + 11, 9, 7, + 11, 1, 9, + 12, 13, 14, + 14, 13, 15, + 14, 15, 16, + 16, 15, 17, + 16, 17, 18, + 18, 17, 19, + 18, 19, 20, + 20, 19, 21, + 20, 21, 12, + 12, 21, 13, + 22, 12, 14, + 22, 14, 16, + 22, 16, 18, + 22, 18, 20, + 22, 20, 12, + 23, 15, 13, + 23, 17, 15, + 23, 19, 17, + 23, 21, 19, + 23, 13, 21, + 24, 25, 26, + 26, 25, 27, + 26, 27, 28, + 28, 27, 29, + 28, 29, 30, + 30, 29, 31, + 30, 31, 32, + 32, 31, 33, + 32, 33, 24, + 24, 33, 25, + 34, 24, 26, + 34, 26, 28, + 34, 28, 30, + 34, 30, 32, + 34, 32, 24, + 35, 27, 25, + 35, 29, 27, + 35, 31, 29, + 35, 33, 31, + 35, 25, 33, + 36, 37, 38, + 38, 37, 39, + 38, 39, 40, + 40, 39, 41, + 40, 41, 42, + 42, 41, 43, + 42, 43, 44, + 44, 43, 45, + 44, 45, 36, + 36, 45, 37, + 46, 36, 38, + 46, 38, 40, + 46, 40, 42, + 46, 42, 44, + 46, 44, 36, + 47, 39, 37, + 47, 41, 39, + 47, 43, 41, + 47, 45, 43, + 47, 37, 45, + 48, 49, 50, + 50, 49, 51, + 50, 51, 52, + 52, 51, 53, + 52, 53, 54, + 54, 53, 55, + 54, 55, 56, + 56, 55, 57, + 56, 57, 48, + 48, 57, 49, + 58, 48, 50, + 58, 50, 52, + 58, 52, 54, + 58, 54, 56, + 58, 56, 48, + 59, 51, 49, + 59, 53, 51, + 59, 55, 53, + 59, 57, 55, + 59, 49, 57, + 60, 61, 62, + 62, 61, 63, + 62, 63, 64, + 64, 63, 65, + 64, 65, 66, + 66, 65, 67, + 66, 67, 68, + 68, 67, 69, + 68, 69, 60, + 60, 69, 61, + 70, 60, 62, + 70, 62, 64, + 70, 64, 66, + 70, 66, 68, + 70, 68, 60, + 71, 63, 61, + 71, 65, 63, + 71, 67, 65, + 71, 69, 67, + 71, 61, 69, + 72, 73, 74, + 74, 73, 75, + 74, 75, 76, + 76, 75, 77, + 76, 77, 78, + 78, 77, 79, + 78, 79, 80, + 80, 79, 81, + 80, 81, 72, + 72, 81, 73, + 82, 72, 74, + 82, 74, 76, + 82, 76, 78, + 82, 78, 80, + 82, 80, 72, + 83, 75, 73, + 83, 77, 75, + 83, 79, 77, + 83, 81, 79, + 83, 73, 81, + 84, 85, 86, + 86, 85, 87, + 86, 87, 88, + 88, 87, 89, + 88, 89, 90, + 90, 89, 91, + 90, 91, 92, + 92, 91, 93, + 92, 93, 84, + 84, 93, 85, + 94, 84, 86, + 94, 86, 88, + 94, 88, 90, + 94, 90, 92, + 94, 92, 84, + 95, 87, 85, + 95, 89, 87, + 95, 91, 89, + 95, 93, 91, + 95, 85, 93, + 96, 97, 98, + 98, 97, 99, + 98, 99, 100, + 100, 99, 101, + 100, 101, 102, + 102, 101, 103, + 102, 103, 104, + 104, 103, 105, + 104, 105, 96, + 96, 105, 97, + 106, 96, 98, + 106, 98, 100, + 106, 100, 102, + 106, 102, 104, + 106, 104, 96, + 107, 99, 97, + 107, 101, 99, + 107, 103, 101, + 107, 105, 103, + 107, 97, 105, + 108, 109, 110, + 110, 109, 111, + 110, 111, 112, + 112, 111, 113, + 112, 113, 114, + 114, 113, 115, + 114, 115, 116, + 116, 115, 117, + 116, 117, 108, + 108, 117, 109, + 118, 108, 110, + 118, 110, 112, + 118, 112, 114, + 118, 114, 116, + 118, 116, 108, + 119, 111, 109, + 119, 113, 111, + 119, 115, 113, + 119, 117, 115, + 119, 109, 117, + 120, 121, 122, + 122, 121, 123, + 122, 123, 124, + 124, 123, 125, + 124, 125, 126, + 126, 125, 127, + 126, 127, 128, + 128, 127, 129, + 128, 129, 120, + 120, 129, 121, + 130, 120, 122, + 130, 122, 124, + 130, 124, 126, + 130, 126, 128, + 130, 128, 120, + 131, 123, 121, + 131, 125, 123, + 131, 127, 125, + 131, 129, 127, + 131, 121, 129, + 132, 133, 134, + 134, 133, 135, + 134, 135, 136, + 136, 135, 137, + 136, 137, 138, + 138, 137, 139, + 138, 139, 140, + 140, 139, 141, + 140, 141, 132, + 132, 141, 133, + 142, 132, 134, + 142, 134, 136, + 142, 136, 138, + 142, 138, 140, + 142, 140, 132, + 143, 135, 133, + 143, 137, 135, + 143, 139, 137, + 143, 141, 139, + 143, 133, 141, + 144, 145, 146, + 146, 145, 147, + 146, 147, 148, + 148, 147, 149, + 148, 149, 150, + 150, 149, 151, + 150, 151, 152, + 152, 151, 153, + 152, 153, 144, + 144, 153, 145, + 154, 144, 146, + 154, 146, 148, + 154, 148, 150, + 154, 150, 152, + 154, 152, 144, + 155, 147, 145, + 155, 149, 147, + 155, 151, 149, + 155, 153, 151, + 155, 145, 153, + 156, 157, 158, + 158, 157, 159, + 158, 159, 160, + 160, 159, 161, + 160, 161, 162, + 162, 161, 163, + 162, 163, 164, + 164, 163, 165, + 164, 165, 156, + 156, 165, 157, + 166, 156, 158, + 166, 158, 160, + 166, 160, 162, + 166, 162, 164, + 166, 164, 156, + 167, 159, 157, + 167, 161, 159, + 167, 163, 161, + 167, 165, 163, + 167, 157, 165, + 168, 169, 170, + 170, 169, 171, + 170, 171, 172, + 172, 171, 173, + 172, 173, 174, + 174, 173, 175, + 174, 175, 176, + 176, 175, 177, + 176, 177, 168, + 168, 177, 169, + 178, 168, 170, + 178, 170, 172, + 178, 172, 174, + 178, 174, 176, + 178, 176, 168, + 179, 171, 169, + 179, 173, 171, + 179, 175, 173, + 179, 177, 175, + 179, 169, 177, + 180, 181, 182, + 182, 181, 183, + 182, 183, 184, + 184, 183, 185, + 184, 185, 186, + 186, 185, 187, + 186, 187, 188, + 188, 187, 189, + 188, 189, 180, + 180, 189, 181, + 190, 180, 182, + 190, 182, 184, + 190, 184, 186, + 190, 186, 188, + 190, 188, 180, + 191, 183, 181, + 191, 185, 183, + 191, 187, 185, + 191, 189, 187, + 191, 181, 189, + 192, 193, 194, + 194, 193, 195, + 194, 195, 196, + 196, 195, 197, + 196, 197, 198, + 198, 197, 199, + 198, 199, 200, + 200, 199, 201, + 200, 201, 192, + 192, 201, 193, + 202, 192, 194, + 202, 194, 196, + 202, 196, 198, + 202, 198, 200, + 202, 200, 192, + 203, 195, 193, + 203, 197, 195, + 203, 199, 197, + 203, 201, 199, + 203, 193, 201, + 204, 205, 206, + 206, 205, 207, + 206, 207, 208, + 208, 207, 209, + 208, 209, 210, + 210, 209, 211, + 210, 211, 212, + 212, 211, 213, + 212, 213, 204, + 204, 213, 205, + 214, 204, 206, + 214, 206, 208, + 214, 208, 210, + 214, 210, 212, + 214, 212, 204, + 215, 207, 205, + 215, 209, 207, + 215, 211, 209, + 215, 213, 211, + 215, 205, 213, + 216, 217, 218, + 218, 217, 219, + 218, 219, 220, + 220, 219, 221, + 220, 221, 222, + 222, 221, 223, + 222, 223, 224, + 224, 223, 225, + 224, 225, 216, + 216, 225, 217, + 226, 216, 218, + 226, 218, 220, + 226, 220, 222, + 226, 222, 224, + 226, 224, 216, + 227, 219, 217, + 227, 221, 219, + 227, 223, 221, + 227, 225, 223, + 227, 217, 225, + 228, 229, 230, + 230, 229, 231, + 230, 231, 232, + 232, 231, 233, + 232, 233, 234, + 234, 233, 235, + 234, 235, 236, + 236, 235, 237, + 236, 237, 228, + 228, 237, 229, + 238, 228, 230, + 238, 230, 232, + 238, 232, 234, + 238, 234, 236, + 238, 236, 228, + 239, 231, 229, + 239, 233, 231, + 239, 235, 233, + 239, 237, 235, + 239, 229, 237, + 240, 241, 242, + 242, 241, 243, + 242, 243, 244, + 244, 243, 245, + 244, 245, 246, + 246, 245, 247, + 246, 247, 248, + 248, 247, 249, + 248, 249, 240, + 240, 249, 241, + 250, 240, 242, + 250, 242, 244, + 250, 244, 246, + 250, 246, 248, + 250, 248, 240, + 251, 243, 241, + 251, 245, 243, + 251, 247, 245, + 251, 249, 247, + 251, 241, 249, + 252, 253, 254, + 254, 253, 255, + 254, 255, 256, + 256, 255, 257, + 256, 257, 258, + 258, 257, 259, + 258, 259, 260, + 260, 259, 261, + 260, 261, 252, + 252, 261, 253, + 262, 252, 254, + 262, 254, 256, + 262, 256, 258, + 262, 258, 260, + 262, 260, 252, + 263, 255, 253, + 263, 257, 255, + 263, 259, 257, + 263, 261, 259, + 263, 253, 261, + 264, 265, 266, + 266, 265, 267, + 266, 267, 268, + 268, 267, 269, + 268, 269, 270, + 270, 269, 271, + 270, 271, 272, + 272, 271, 273, + 272, 273, 264, + 264, 273, 265, + 274, 264, 266, + 274, 266, 268, + 274, 268, 270, + 274, 270, 272, + 274, 272, 264, + 275, 267, 265, + 275, 269, 267, + 275, 271, 269, + 275, 273, 271, + 275, 265, 273, + 276, 277, 278, + 278, 277, 279, + 278, 279, 280, + 280, 279, 281, + 280, 281, 282, + 282, 281, 283, + 282, 283, 284, + 284, 283, 285, + 284, 285, 276, + 276, 285, 277, + 286, 276, 278, + 286, 278, 280, + 286, 280, 282, + 286, 282, 284, + 286, 284, 276, + 287, 279, 277, + 287, 281, 279, + 287, 283, 281, + 287, 285, 283, + 287, 277, 285, + 288, 289, 290, + 290, 289, 291, + 290, 291, 292, + 292, 291, 293, + 292, 293, 294, + 294, 293, 295, + 294, 295, 296, + 296, 295, 297, + 296, 297, 288, + 288, 297, 289, + 298, 288, 290, + 298, 290, 292, + 298, 292, 294, + 298, 294, 296, + 298, 296, 288, + 299, 291, 289, + 299, 293, 291, + 299, 295, 293, + 299, 297, 295, + 299, 289, 297, + 300, 301, 302, + 302, 301, 303, + 302, 303, 304, + 304, 303, 305, + 304, 305, 306, + 306, 305, 307, + 306, 307, 308, + 308, 307, 309, + 308, 309, 300, + 300, 309, 301, + 310, 300, 302, + 310, 302, 304, + 310, 304, 306, + 310, 306, 308, + 310, 308, 300, + 311, 303, 301, + 311, 305, 303, + 311, 307, 305, + 311, 309, 307, + 311, 301, 309, + 312, 313, 314, + 314, 313, 315, + 314, 315, 316, + 316, 315, 317, + 316, 317, 318, + 318, 317, 319, + 318, 319, 320, + 320, 319, 321, + 320, 321, 312, + 312, 321, 313, + 322, 312, 314, + 322, 314, 316, + 322, 316, 318, + 322, 318, 320, + 322, 320, 312, + 323, 315, 313, + 323, 317, 315, + 323, 319, 317, + 323, 321, 319, + 323, 313, 321, + 324, 325, 326, + 326, 325, 327, + 326, 327, 328, + 328, 327, 329, + 328, 329, 330, + 330, 329, 331, + 330, 331, 332, + 332, 331, 333, + 332, 333, 324, + 324, 333, 325, + 334, 324, 326, + 334, 326, 328, + 334, 328, 330, + 334, 330, 332, + 334, 332, 324, + 335, 327, 325, + 335, 329, 327, + 335, 331, 329, + 335, 333, 331, + 335, 325, 333, + 336, 337, 338, + 338, 337, 339, + 338, 339, 340, + 340, 339, 341, + 340, 341, 342, + 342, 341, 343, + 342, 343, 344, + 344, 343, 345, + 344, 345, 336, + 336, 345, 337, + 346, 336, 338, + 346, 338, 340, + 346, 340, 342, + 346, 342, 344, + 346, 344, 336, + 347, 339, 337, + 347, 341, 339, + 347, 343, 341, + 347, 345, 343, + 347, 337, 345, + 348, 349, 350, + 350, 349, 351, + 350, 351, 352, + 352, 351, 353, + 352, 353, 354, + 354, 353, 355, + 354, 355, 356, + 356, 355, 357, + 356, 357, 348, + 348, 357, 349, + 358, 348, 350, + 358, 350, 352, + 358, 352, 354, + 358, 354, 356, + 358, 356, 348, + 359, 351, 349, + 359, 353, 351, + 359, 355, 353, + 359, 357, 355, + 359, 349, 357, + 360, 361, 362, + 362, 361, 363, + 362, 363, 364, + 364, 363, 365, + 364, 365, 366, + 366, 365, 367, + 366, 367, 368, + 368, 367, 369, + 368, 369, 360, + 360, 369, 361, + 370, 360, 362, + 370, 362, 364, + 370, 364, 366, + 370, 366, 368, + 370, 368, 360, + 371, 363, 361, + 371, 365, 363, + 371, 367, 365, + 371, 369, 367, + 371, 361, 369, + 372, 373, 374, + 374, 373, 375, + 374, 375, 376, + 376, 375, 377, + 376, 377, 378, + 378, 377, 379, + 378, 379, 380, + 380, 379, 381, + 380, 381, 372, + 372, 381, 373, + 382, 372, 374, + 382, 374, 376, + 382, 376, 378, + 382, 378, 380, + 382, 380, 372, + 383, 375, 373, + 383, 377, 375, + 383, 379, 377, + 383, 381, 379, + 383, 373, 381, + 384, 385, 386, + 386, 385, 387, + 386, 387, 388, + 388, 387, 389, + 388, 389, 390, + 390, 389, 391, + 390, 391, 392, + 392, 391, 393, + 392, 393, 384, + 384, 393, 385, + 394, 384, 386, + 394, 386, 388, + 394, 388, 390, + 394, 390, 392, + 394, 392, 384, + 395, 387, 385, + 395, 389, 387, + 395, 391, 389, + 395, 393, 391, + 395, 385, 393, + 396, 397, 398, + 398, 397, 399, + 398, 399, 400, + 400, 399, 401, + 400, 401, 402, + 402, 401, 403, + 402, 403, 404, + 404, 403, 405, + 404, 405, 396, + 396, 405, 397, + 406, 396, 398, + 406, 398, 400, + 406, 400, 402, + 406, 402, 404, + 406, 404, 396, + 407, 399, 397, + 407, 401, 399, + 407, 403, 401, + 407, 405, 403, + 407, 397, 405, + 408, 409, 410, + 410, 409, 411, + 410, 411, 412, + 412, 411, 413, + 412, 413, 414, + 414, 413, 415, + 414, 415, 416, + 416, 415, 417, + 416, 417, 408, + 408, 417, 409, + 418, 408, 410, + 418, 410, 412, + 418, 412, 414, + 418, 414, 416, + 418, 416, 408, + 419, 411, 409, + 419, 413, 411, + 419, 415, 413, + 419, 417, 415, + 419, 409, 417, + 420, 421, 422, + 422, 421, 423, + 422, 423, 424, + 424, 423, 425, + 424, 425, 426, + 426, 425, 427, + 426, 427, 428, + 428, 427, 429, + 428, 429, 420, + 420, 429, 421, + 430, 420, 422, + 430, 422, 424, + 430, 424, 426, + 430, 426, 428, + 430, 428, 420, + 431, 423, 421, + 431, 425, 423, + 431, 427, 425, + 431, 429, 427, + 431, 421, 429, + 432, 433, 434, + 434, 433, 435, + 434, 435, 436, + 436, 435, 437, + 436, 437, 438, + 438, 437, 439, + 438, 439, 440, + 440, 439, 441, + 440, 441, 432, + 432, 441, 433, + 442, 432, 434, + 442, 434, 436, + 442, 436, 438, + 442, 438, 440, + 442, 440, 432, + 443, 435, 433, + 443, 437, 435, + 443, 439, 437, + 443, 441, 439, + 443, 433, 441, + 444, 445, 446, + 446, 445, 447, + 446, 447, 448, + 448, 447, 449, + 448, 449, 450, + 450, 449, 451, + 450, 451, 452, + 452, 451, 453, + 452, 453, 444, + 444, 453, 445, + 454, 444, 446, + 454, 446, 448, + 454, 448, 450, + 454, 450, 452, + 454, 452, 444, + 455, 447, 445, + 455, 449, 447, + 455, 451, 449, + 455, 453, 451, + 455, 445, 453, + 456, 457, 458, + 458, 457, 459, + 458, 459, 460, + 460, 459, 461, + 460, 461, 462, + 462, 461, 463, + 462, 463, 464, + 464, 463, 465, + 464, 465, 456, + 456, 465, 457, + 466, 456, 458, + 466, 458, 460, + 466, 460, 462, + 466, 462, 464, + 466, 464, 456, + 467, 459, 457, + 467, 461, 459, + 467, 463, 461, + 467, 465, 463, + 467, 457, 465, + 468, 469, 470, + 470, 469, 471, + 470, 471, 472, + 472, 471, 473, + 472, 473, 474, + 474, 473, 475, + 474, 475, 476, + 476, 475, 477, + 476, 477, 468, + 468, 477, 469, + 478, 468, 470, + 478, 470, 472, + 478, 472, 474, + 478, 474, 476, + 478, 476, 468, + 479, 471, 469, + 479, 473, 471, + 479, 475, 473, + 479, 477, 475, + 479, 469, 477, + 480, 481, 482, + 482, 481, 483, + 482, 483, 484, + 484, 483, 485, + 484, 485, 486, + 486, 485, 487, + 486, 487, 488, + 488, 487, 489, + 488, 489, 480, + 480, 489, 481, + 490, 480, 482, + 490, 482, 484, + 490, 484, 486, + 490, 486, 488, + 490, 488, 480, + 491, 483, 481, + 491, 485, 483, + 491, 487, 485, + 491, 489, 487, + 491, 481, 489, + 492, 493, 494, + 494, 493, 495, + 494, 495, 496, + 496, 495, 497, + 496, 497, 498, + 498, 497, 499, + 498, 499, 500, + 500, 499, 501, + 500, 501, 492, + 492, 501, 493, + 502, 492, 494, + 502, 494, 496, + 502, 496, 498, + 502, 498, 500, + 502, 500, 492, + 503, 495, 493, + 503, 497, 495, + 503, 499, 497, + 503, 501, 499, + 503, 493, 501, + 504, 505, 506, + 506, 505, 507, + 506, 507, 508, + 508, 507, 509, + 508, 509, 510, + 510, 509, 511, + 510, 511, 512, + 512, 511, 513, + 512, 513, 504, + 504, 513, 505, + 514, 504, 506, + 514, 506, 508, + 514, 508, 510, + 514, 510, 512, + 514, 512, 504, + 515, 507, 505, + 515, 509, 507, + 515, 511, 509, + 515, 513, 511, + 515, 505, 513, + 516, 517, 518, + 518, 517, 519, + 518, 519, 520, + 520, 519, 521, + 520, 521, 522, + 522, 521, 523, + 522, 523, 524, + 524, 523, 525, + 524, 525, 516, + 516, 525, 517, + 526, 516, 518, + 526, 518, 520, + 526, 520, 522, + 526, 522, 524, + 526, 524, 516, + 527, 519, 517, + 527, 521, 519, + 527, 523, 521, + 527, 525, 523, + 527, 517, 525, + 528, 529, 530, + 530, 529, 531, + 530, 531, 532, + 532, 531, 533, + 532, 533, 534, + 534, 533, 535, + 534, 535, 536, + 536, 535, 537, + 536, 537, 528, + 528, 537, 529, + 538, 528, 530, + 538, 530, 532, + 538, 532, 534, + 538, 534, 536, + 538, 536, 528, + 539, 531, 529, + 539, 533, 531, + 539, 535, 533, + 539, 537, 535, + 539, 529, 537, + 540, 541, 542, + 542, 541, 543, + 542, 543, 544, + 544, 543, 545, + 544, 545, 546, + 546, 545, 547, + 546, 547, 548, + 548, 547, 549, + 548, 549, 540, + 540, 549, 541, + 550, 540, 542, + 550, 542, 544, + 550, 544, 546, + 550, 546, 548, + 550, 548, 540, + 551, 543, 541, + 551, 545, 543, + 551, 547, 545, + 551, 549, 547, + 551, 541, 549, + 552, 553, 554, + 554, 553, 555, + 554, 555, 556, + 556, 555, 557, + 556, 557, 558, + 558, 557, 559, + 558, 559, 560, + 560, 559, 561, + 560, 561, 552, + 552, 561, 553, + 562, 552, 554, + 562, 554, 556, + 562, 556, 558, + 562, 558, 560, + 562, 560, 552, + 563, 555, 553, + 563, 557, 555, + 563, 559, 557, + 563, 561, 559, + 563, 553, 561, + 564, 565, 566, + 566, 565, 567, + 566, 567, 568, + 568, 567, 569, + 568, 569, 570, + 570, 569, 571, + 570, 571, 572, + 572, 571, 573, + 572, 573, 564, + 564, 573, 565, + 574, 564, 566, + 574, 566, 568, + 574, 568, 570, + 574, 570, 572, + 574, 572, 564, + 575, 567, 565, + 575, 569, 567, + 575, 571, 569, + 575, 573, 571, + 575, 565, 573, + 576, 577, 578, + 578, 577, 579, + 578, 579, 580, + 580, 579, 581, + 580, 581, 582, + 582, 581, 583, + 582, 583, 584, + 584, 583, 585, + 584, 585, 576, + 576, 585, 577, + 586, 576, 578, + 586, 578, 580, + 586, 580, 582, + 586, 582, 584, + 586, 584, 576, + 587, 579, 577, + 587, 581, 579, + 587, 583, 581, + 587, 585, 583, + 587, 577, 585, + 588, 589, 590, + 590, 589, 591, + 590, 591, 592, + 592, 591, 593, + 592, 593, 594, + 594, 593, 595, + 594, 595, 596, + 596, 595, 597, + 596, 597, 588, + 588, 597, 589, + 598, 588, 590, + 598, 590, 592, + 598, 592, 594, + 598, 594, 596, + 598, 596, 588, + 599, 591, 589, + 599, 593, 591, + 599, 595, 593, + 599, 597, 595, + 599, 589, 597, + 600, 601, 602, + 602, 601, 603, + 602, 603, 604, + 604, 603, 605, + 604, 605, 606, + 606, 605, 607, + 606, 607, 608, + 608, 607, 609, + 608, 609, 600, + 600, 609, 601, + 610, 600, 602, + 610, 602, 604, + 610, 604, 606, + 610, 606, 608, + 610, 608, 600, + 611, 603, 601, + 611, 605, 603, + 611, 607, 605, + 611, 609, 607, + 611, 601, 609, + 612, 613, 614, + 614, 613, 615, + 614, 615, 616, + 616, 615, 617, + 616, 617, 618, + 618, 617, 619, + 618, 619, 620, + 620, 619, 621, + 620, 621, 612, + 612, 621, 613, + 622, 612, 614, + 622, 614, 616, + 622, 616, 618, + 622, 618, 620, + 622, 620, 612, + 623, 615, 613, + 623, 617, 615, + 623, 619, 617, + 623, 621, 619, + 623, 613, 621, + 624, 625, 626, + 626, 625, 627, + 626, 627, 628, + 628, 627, 629, + 628, 629, 630, + 630, 629, 631, + 630, 631, 632, + 632, 631, 633, + 632, 633, 624, + 624, 633, 625, + 634, 624, 626, + 634, 626, 628, + 634, 628, 630, + 634, 630, 632, + 634, 632, 624, + 635, 627, 625, + 635, 629, 627, + 635, 631, 629, + 635, 633, 631, + 635, 625, 633, + 636, 637, 638, + 638, 637, 639, + 638, 639, 640, + 640, 639, 641, + 640, 641, 642, + 642, 641, 643, + 642, 643, 644, + 644, 643, 645, + 644, 645, 636, + 636, 645, 637, + 646, 636, 638, + 646, 638, 640, + 646, 640, 642, + 646, 642, 644, + 646, 644, 636, + 647, 639, 637, + 647, 641, 639, + 647, 643, 641, + 647, 645, 643, + 647, 637, 645, + 648, 649, 650, + 650, 649, 651, + 650, 651, 652, + 652, 651, 653, + 652, 653, 654, + 654, 653, 655, + 654, 655, 656, + 656, 655, 657, + 656, 657, 648, + 648, 657, 649, + 658, 648, 650, + 658, 650, 652, + 658, 652, 654, + 658, 654, 656, + 658, 656, 648, + 659, 651, 649, + 659, 653, 651, + 659, 655, 653, + 659, 657, 655, + 659, 649, 657, + 660, 661, 662, + 662, 661, 663, + 662, 663, 664, + 664, 663, 665, + 664, 665, 666, + 666, 665, 667, + 666, 667, 668, + 668, 667, 669, + 668, 669, 660, + 660, 669, 661, + 670, 660, 662, + 670, 662, 664, + 670, 664, 666, + 670, 666, 668, + 670, 668, 660, + 671, 663, 661, + 671, 665, 663, + 671, 667, 665, + 671, 669, 667, + 671, 661, 669, + 672, 673, 674, + 674, 673, 675, + 674, 675, 676, + 676, 675, 677, + 676, 677, 678, + 678, 677, 679, + 678, 679, 680, + 680, 679, 681, + 680, 681, 672, + 672, 681, 673, + 682, 672, 674, + 682, 674, 676, + 682, 676, 678, + 682, 678, 680, + 682, 680, 672, + 683, 675, 673, + 683, 677, 675, + 683, 679, 677, + 683, 681, 679, + 683, 673, 681, + 684, 685, 686, + 686, 685, 687, + 686, 687, 688, + 688, 687, 689, + 688, 689, 690, + 690, 689, 691, + 690, 691, 692, + 692, 691, 693, + 692, 693, 684, + 684, 693, 685, + 694, 684, 686, + 694, 686, 688, + 694, 688, 690, + 694, 690, 692, + 694, 692, 684, + 695, 687, 685, + 695, 689, 687, + 695, 691, 689, + 695, 693, 691, + 695, 685, 693, + 696, 697, 698, + 698, 697, 699, + 698, 699, 700, + 700, 699, 701, + 700, 701, 702, + 702, 701, 703, + 702, 703, 704, + 704, 703, 705, + 704, 705, 696, + 696, 705, 697, + 706, 696, 698, + 706, 698, 700, + 706, 700, 702, + 706, 702, 704, + 706, 704, 696, + 707, 699, 697, + 707, 701, 699, + 707, 703, 701, + 707, 705, 703, + 707, 697, 705, + 708, 709, 710, + 710, 709, 711, + 710, 711, 712, + 712, 711, 713, + 712, 713, 714, + 714, 713, 715, + 714, 715, 716, + 716, 715, 717, + 716, 717, 708, + 708, 717, 709, + 718, 708, 710, + 718, 710, 712, + 718, 712, 714, + 718, 714, 716, + 718, 716, 708, + 719, 711, 709, + 719, 713, 711, + 719, 715, 713, + 719, 717, 715, + 719, 709, 717, + 720, 721, 722, + 722, 721, 723, + 722, 723, 724, + 724, 723, 725, + 724, 725, 726, + 726, 725, 727, + 726, 727, 728, + 728, 727, 729, + 728, 729, 720, + 720, 729, 721, + 730, 720, 722, + 730, 722, 724, + 730, 724, 726, + 730, 726, 728, + 730, 728, 720, + 731, 723, 721, + 731, 725, 723, + 731, 727, 725, + 731, 729, 727, + 731, 721, 729, + 732, 733, 734, + 734, 733, 735, + 734, 735, 736, + 736, 735, 737, + 736, 737, 738, + 738, 737, 739, + 738, 739, 740, + 740, 739, 741, + 740, 741, 732, + 732, 741, 733, + 742, 732, 734, + 742, 734, 736, + 742, 736, 738, + 742, 738, 740, + 742, 740, 732, + 743, 735, 733, + 743, 737, 735, + 743, 739, 737, + 743, 741, 739, + 743, 733, 741, + 744, 745, 746, + 746, 745, 747, + 746, 747, 748, + 748, 747, 749, + 748, 749, 750, + 750, 749, 751, + 750, 751, 752, + 752, 751, 753, + 752, 753, 744, + 744, 753, 745, + 754, 744, 746, + 754, 746, 748, + 754, 748, 750, + 754, 750, 752, + 754, 752, 744, + 755, 747, 745, + 755, 749, 747, + 755, 751, 749, + 755, 753, 751, + 755, 745, 753, + 756, 757, 758, + 758, 757, 759, + 758, 759, 760, + 760, 759, 761, + 760, 761, 762, + 762, 761, 763, + 762, 763, 764, + 764, 763, 765, + 764, 765, 756, + 756, 765, 757, + 766, 756, 758, + 766, 758, 760, + 766, 760, 762, + 766, 762, 764, + 766, 764, 756, + 767, 759, 757, + 767, 761, 759, + 767, 763, 761, + 767, 765, 763, + 767, 757, 765 +}; +static const unsigned some_enclosures_properties[3840] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 1, 2, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 2, 3, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0, + 3, 4, 0 +}; + +#define NB_CYL_X 4 +#define NB_CYL_Y 4 +#define NB_CYL_Z 4 +#define NB_CYL (NB_CYL_X * NB_CYL_Y * NB_CYL_Z) +#define CYL_VRTX_COUNT 12u +#define CYL_TRG_COUNT 20u + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned e, count; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene */ + ctx.positions = some_enclosures_vertices; + ctx.indices = some_enclosures_triangles; + ctx.properties = some_enclosures_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + some_enclosures_triangles_count, get_indices, get_media_from_properties, + some_enclosures_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_vertices_count(scn, &count)); + CHK(count == NB_CYL * CYL_VRTX_COUNT); + OK(senc3d_scene_get_triangles_count(scn, &count)); + CHK(count == NB_CYL * CYL_TRG_COUNT); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1 + NB_CYL); + FOR_EACH(e, 0, count) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + unsigned m; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + CHK(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &m)); + CHK(header.primitives_count == + (header.is_infinite /* Outermost enclosure: NB_CYL_X*NB_CYL_Y cylinders */ + ? NB_CYL_X * NB_CYL_Y * CYL_TRG_COUNT + : (m == 0 + ? CYL_TRG_COUNT /* Innermost enclosures: 1 cylinder */ + : 2 * CYL_TRG_COUNT))); /* Other enclosures: 2 cylinders */ + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_some_triangles.c b/src/test_senc3d_some_triangles.c @@ -0,0 +1,2737 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_some_triangles. + * This test is similar to test_SENC3D_many_triangles that creates a huge + * geometry by program. */ + +#include "senc3d.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +/* Dump of star-geometry 'some_triangles'. */ +static const unsigned some_triangles_vertices_count = 536; +static const double some_triangles_vertices[1608] = +{ + 1, 0, -1, + 1, 0, -0.8, + 1, 0, -0.6, + 1, 0, -0.4, + 1, 0, -0.2, + 1, 0, -5.55112e-17, + 1, 0, 0.2, + 1, 0, 0.4, + 1, 0, 0.6, + 1, 0, 0.8, + 1, 0, 1, + 0.866025, 0.5, -1, + 0.866025, 0.5, -0.8, + 0.866025, 0.5, -0.6, + 0.866025, 0.5, -0.4, + 0.866025, 0.5, -0.2, + 0.866025, 0.5, -5.55112e-17, + 0.866025, 0.5, 0.2, + 0.866025, 0.5, 0.4, + 0.866025, 0.5, 0.6, + 0.866025, 0.5, 0.8, + 0.866025, 0.5, 1, + 0.5, 0.866025, -1, + 0.5, 0.866025, -0.8, + 0.5, 0.866025, -0.6, + 0.5, 0.866025, -0.4, + 0.5, 0.866025, -0.2, + 0.5, 0.866025, -5.55112e-17, + 0.5, 0.866025, 0.2, + 0.5, 0.866025, 0.4, + 0.5, 0.866025, 0.6, + 0.5, 0.866025, 0.8, + 0.5, 0.866025, 1, + 6.12323e-17, 1, -1, + 6.12323e-17, 1, -0.8, + 6.12323e-17, 1, -0.6, + 6.12323e-17, 1, -0.4, + 6.12323e-17, 1, -0.2, + 6.12323e-17, 1, -5.55112e-17, + 6.12323e-17, 1, 0.2, + 6.12323e-17, 1, 0.4, + 6.12323e-17, 1, 0.6, + 6.12323e-17, 1, 0.8, + 6.12323e-17, 1, 1, + -0.5, 0.866025, -1, + -0.5, 0.866025, -0.8, + -0.5, 0.866025, -0.6, + -0.5, 0.866025, -0.4, + -0.5, 0.866025, -0.2, + -0.5, 0.866025, -5.55112e-17, + -0.5, 0.866025, 0.2, + -0.5, 0.866025, 0.4, + -0.5, 0.866025, 0.6, + -0.5, 0.866025, 0.8, + -0.5, 0.866025, 1, + -0.866025, 0.5, -1, + -0.866025, 0.5, -0.8, + -0.866025, 0.5, -0.6, + -0.866025, 0.5, -0.4, + -0.866025, 0.5, -0.2, + -0.866025, 0.5, -5.55112e-17, + -0.866025, 0.5, 0.2, + -0.866025, 0.5, 0.4, + -0.866025, 0.5, 0.6, + -0.866025, 0.5, 0.8, + -0.866025, 0.5, 1, + -1, 1.22465e-16, -1, + -1, 1.22465e-16, -0.8, + -1, 1.22465e-16, -0.6, + -1, 1.22465e-16, -0.4, + -1, 1.22465e-16, -0.2, + -1, 1.22465e-16, -5.55112e-17, + -1, 1.22465e-16, 0.2, + -1, 1.22465e-16, 0.4, + -1, 1.22465e-16, 0.6, + -1, 1.22465e-16, 0.8, + -1, 1.22465e-16, 1, + -0.866025, -0.5, -1, + -0.866025, -0.5, -0.8, + -0.866025, -0.5, -0.6, + -0.866025, -0.5, -0.4, + -0.866025, -0.5, -0.2, + -0.866025, -0.5, -5.55112e-17, + -0.866025, -0.5, 0.2, + -0.866025, -0.5, 0.4, + -0.866025, -0.5, 0.6, + -0.866025, -0.5, 0.8, + -0.866025, -0.5, 1, + -0.5, -0.866025, -1, + -0.5, -0.866025, -0.8, + -0.5, -0.866025, -0.6, + -0.5, -0.866025, -0.4, + -0.5, -0.866025, -0.2, + -0.5, -0.866025, -5.55112e-17, + -0.5, -0.866025, 0.2, + -0.5, -0.866025, 0.4, + -0.5, -0.866025, 0.6, + -0.5, -0.866025, 0.8, + -0.5, -0.866025, 1, + -1.83697e-16, -1, -1, + -1.83697e-16, -1, -0.8, + -1.83697e-16, -1, -0.6, + -1.83697e-16, -1, -0.4, + -1.83697e-16, -1, -0.2, + -1.83697e-16, -1, -5.55112e-17, + -1.83697e-16, -1, 0.2, + -1.83697e-16, -1, 0.4, + -1.83697e-16, -1, 0.6, + -1.83697e-16, -1, 0.8, + -1.83697e-16, -1, 1, + 0.5, -0.866025, -1, + 0.5, -0.866025, -0.8, + 0.5, -0.866025, -0.6, + 0.5, -0.866025, -0.4, + 0.5, -0.866025, -0.2, + 0.5, -0.866025, -5.55112e-17, + 0.5, -0.866025, 0.2, + 0.5, -0.866025, 0.4, + 0.5, -0.866025, 0.6, + 0.5, -0.866025, 0.8, + 0.5, -0.866025, 1, + 0.866025, -0.5, -1, + 0.866025, -0.5, -0.8, + 0.866025, -0.5, -0.6, + 0.866025, -0.5, -0.4, + 0.866025, -0.5, -0.2, + 0.866025, -0.5, -5.55112e-17, + 0.866025, -0.5, 0.2, + 0.866025, -0.5, 0.4, + 0.866025, -0.5, 0.6, + 0.866025, -0.5, 0.8, + 0.866025, -0.5, 1, + 0, 0, -1, + 0, 0, 1, + 1, 0, 9, + 1, 0, 9.2, + 1, 0, 9.4, + 1, 0, 9.6, + 1, 0, 9.8, + 1, 0, 10, + 1, 0, 10.2, + 1, 0, 10.4, + 1, 0, 10.6, + 1, 0, 10.8, + 1, 0, 11, + 0.866025, 0.5, 9, + 0.866025, 0.5, 9.2, + 0.866025, 0.5, 9.4, + 0.866025, 0.5, 9.6, + 0.866025, 0.5, 9.8, + 0.866025, 0.5, 10, + 0.866025, 0.5, 10.2, + 0.866025, 0.5, 10.4, + 0.866025, 0.5, 10.6, + 0.866025, 0.5, 10.8, + 0.866025, 0.5, 11, + 0.5, 0.866025, 9, + 0.5, 0.866025, 9.2, + 0.5, 0.866025, 9.4, + 0.5, 0.866025, 9.6, + 0.5, 0.866025, 9.8, + 0.5, 0.866025, 10, + 0.5, 0.866025, 10.2, + 0.5, 0.866025, 10.4, + 0.5, 0.866025, 10.6, + 0.5, 0.866025, 10.8, + 0.5, 0.866025, 11, + 6.12323e-17, 1, 9, + 6.12323e-17, 1, 9.2, + 6.12323e-17, 1, 9.4, + 6.12323e-17, 1, 9.6, + 6.12323e-17, 1, 9.8, + 6.12323e-17, 1, 10, + 6.12323e-17, 1, 10.2, + 6.12323e-17, 1, 10.4, + 6.12323e-17, 1, 10.6, + 6.12323e-17, 1, 10.8, + 6.12323e-17, 1, 11, + -0.5, 0.866025, 9, + -0.5, 0.866025, 9.2, + -0.5, 0.866025, 9.4, + -0.5, 0.866025, 9.6, + -0.5, 0.866025, 9.8, + -0.5, 0.866025, 10, + -0.5, 0.866025, 10.2, + -0.5, 0.866025, 10.4, + -0.5, 0.866025, 10.6, + -0.5, 0.866025, 10.8, + -0.5, 0.866025, 11, + -0.866025, 0.5, 9, + -0.866025, 0.5, 9.2, + -0.866025, 0.5, 9.4, + -0.866025, 0.5, 9.6, + -0.866025, 0.5, 9.8, + -0.866025, 0.5, 10, + -0.866025, 0.5, 10.2, + -0.866025, 0.5, 10.4, + -0.866025, 0.5, 10.6, + -0.866025, 0.5, 10.8, + -0.866025, 0.5, 11, + -1, 1.22465e-16, 9, + -1, 1.22465e-16, 9.2, + -1, 1.22465e-16, 9.4, + -1, 1.22465e-16, 9.6, + -1, 1.22465e-16, 9.8, + -1, 1.22465e-16, 10, + -1, 1.22465e-16, 10.2, + -1, 1.22465e-16, 10.4, + -1, 1.22465e-16, 10.6, + -1, 1.22465e-16, 10.8, + -1, 1.22465e-16, 11, + -0.866025, -0.5, 9, + -0.866025, -0.5, 9.2, + -0.866025, -0.5, 9.4, + -0.866025, -0.5, 9.6, + -0.866025, -0.5, 9.8, + -0.866025, -0.5, 10, + -0.866025, -0.5, 10.2, + -0.866025, -0.5, 10.4, + -0.866025, -0.5, 10.6, + -0.866025, -0.5, 10.8, + -0.866025, -0.5, 11, + -0.5, -0.866025, 9, + -0.5, -0.866025, 9.2, + -0.5, -0.866025, 9.4, + -0.5, -0.866025, 9.6, + -0.5, -0.866025, 9.8, + -0.5, -0.866025, 10, + -0.5, -0.866025, 10.2, + -0.5, -0.866025, 10.4, + -0.5, -0.866025, 10.6, + -0.5, -0.866025, 10.8, + -0.5, -0.866025, 11, + -1.83697e-16, -1, 9, + -1.83697e-16, -1, 9.2, + -1.83697e-16, -1, 9.4, + -1.83697e-16, -1, 9.6, + -1.83697e-16, -1, 9.8, + -1.83697e-16, -1, 10, + -1.83697e-16, -1, 10.2, + -1.83697e-16, -1, 10.4, + -1.83697e-16, -1, 10.6, + -1.83697e-16, -1, 10.8, + -1.83697e-16, -1, 11, + 0.5, -0.866025, 9, + 0.5, -0.866025, 9.2, + 0.5, -0.866025, 9.4, + 0.5, -0.866025, 9.6, + 0.5, -0.866025, 9.8, + 0.5, -0.866025, 10, + 0.5, -0.866025, 10.2, + 0.5, -0.866025, 10.4, + 0.5, -0.866025, 10.6, + 0.5, -0.866025, 10.8, + 0.5, -0.866025, 11, + 0.866025, -0.5, 9, + 0.866025, -0.5, 9.2, + 0.866025, -0.5, 9.4, + 0.866025, -0.5, 9.6, + 0.866025, -0.5, 9.8, + 0.866025, -0.5, 10, + 0.866025, -0.5, 10.2, + 0.866025, -0.5, 10.4, + 0.866025, -0.5, 10.6, + 0.866025, -0.5, 10.8, + 0.866025, -0.5, 11, + 0, 0, 9, + 0, 0, 11, + 1, 0, 19, + 1, 0, 19.2, + 1, 0, 19.4, + 1, 0, 19.6, + 1, 0, 19.8, + 1, 0, 20, + 1, 0, 20.2, + 1, 0, 20.4, + 1, 0, 20.6, + 1, 0, 20.8, + 1, 0, 21, + 0.866025, 0.5, 19, + 0.866025, 0.5, 19.2, + 0.866025, 0.5, 19.4, + 0.866025, 0.5, 19.6, + 0.866025, 0.5, 19.8, + 0.866025, 0.5, 20, + 0.866025, 0.5, 20.2, + 0.866025, 0.5, 20.4, + 0.866025, 0.5, 20.6, + 0.866025, 0.5, 20.8, + 0.866025, 0.5, 21, + 0.5, 0.866025, 19, + 0.5, 0.866025, 19.2, + 0.5, 0.866025, 19.4, + 0.5, 0.866025, 19.6, + 0.5, 0.866025, 19.8, + 0.5, 0.866025, 20, + 0.5, 0.866025, 20.2, + 0.5, 0.866025, 20.4, + 0.5, 0.866025, 20.6, + 0.5, 0.866025, 20.8, + 0.5, 0.866025, 21, + 6.12323e-17, 1, 19, + 6.12323e-17, 1, 19.2, + 6.12323e-17, 1, 19.4, + 6.12323e-17, 1, 19.6, + 6.12323e-17, 1, 19.8, + 6.12323e-17, 1, 20, + 6.12323e-17, 1, 20.2, + 6.12323e-17, 1, 20.4, + 6.12323e-17, 1, 20.6, + 6.12323e-17, 1, 20.8, + 6.12323e-17, 1, 21, + -0.5, 0.866025, 19, + -0.5, 0.866025, 19.2, + -0.5, 0.866025, 19.4, + -0.5, 0.866025, 19.6, + -0.5, 0.866025, 19.8, + -0.5, 0.866025, 20, + -0.5, 0.866025, 20.2, + -0.5, 0.866025, 20.4, + -0.5, 0.866025, 20.6, + -0.5, 0.866025, 20.8, + -0.5, 0.866025, 21, + -0.866025, 0.5, 19, + -0.866025, 0.5, 19.2, + -0.866025, 0.5, 19.4, + -0.866025, 0.5, 19.6, + -0.866025, 0.5, 19.8, + -0.866025, 0.5, 20, + -0.866025, 0.5, 20.2, + -0.866025, 0.5, 20.4, + -0.866025, 0.5, 20.6, + -0.866025, 0.5, 20.8, + -0.866025, 0.5, 21, + -1, 1.22465e-16, 19, + -1, 1.22465e-16, 19.2, + -1, 1.22465e-16, 19.4, + -1, 1.22465e-16, 19.6, + -1, 1.22465e-16, 19.8, + -1, 1.22465e-16, 20, + -1, 1.22465e-16, 20.2, + -1, 1.22465e-16, 20.4, + -1, 1.22465e-16, 20.6, + -1, 1.22465e-16, 20.8, + -1, 1.22465e-16, 21, + -0.866025, -0.5, 19, + -0.866025, -0.5, 19.2, + -0.866025, -0.5, 19.4, + -0.866025, -0.5, 19.6, + -0.866025, -0.5, 19.8, + -0.866025, -0.5, 20, + -0.866025, -0.5, 20.2, + -0.866025, -0.5, 20.4, + -0.866025, -0.5, 20.6, + -0.866025, -0.5, 20.8, + -0.866025, -0.5, 21, + -0.5, -0.866025, 19, + -0.5, -0.866025, 19.2, + -0.5, -0.866025, 19.4, + -0.5, -0.866025, 19.6, + -0.5, -0.866025, 19.8, + -0.5, -0.866025, 20, + -0.5, -0.866025, 20.2, + -0.5, -0.866025, 20.4, + -0.5, -0.866025, 20.6, + -0.5, -0.866025, 20.8, + -0.5, -0.866025, 21, + -1.83697e-16, -1, 19, + -1.83697e-16, -1, 19.2, + -1.83697e-16, -1, 19.4, + -1.83697e-16, -1, 19.6, + -1.83697e-16, -1, 19.8, + -1.83697e-16, -1, 20, + -1.83697e-16, -1, 20.2, + -1.83697e-16, -1, 20.4, + -1.83697e-16, -1, 20.6, + -1.83697e-16, -1, 20.8, + -1.83697e-16, -1, 21, + 0.5, -0.866025, 19, + 0.5, -0.866025, 19.2, + 0.5, -0.866025, 19.4, + 0.5, -0.866025, 19.6, + 0.5, -0.866025, 19.8, + 0.5, -0.866025, 20, + 0.5, -0.866025, 20.2, + 0.5, -0.866025, 20.4, + 0.5, -0.866025, 20.6, + 0.5, -0.866025, 20.8, + 0.5, -0.866025, 21, + 0.866025, -0.5, 19, + 0.866025, -0.5, 19.2, + 0.866025, -0.5, 19.4, + 0.866025, -0.5, 19.6, + 0.866025, -0.5, 19.8, + 0.866025, -0.5, 20, + 0.866025, -0.5, 20.2, + 0.866025, -0.5, 20.4, + 0.866025, -0.5, 20.6, + 0.866025, -0.5, 20.8, + 0.866025, -0.5, 21, + 0, 0, 19, + 0, 0, 21, + 1, 0, 29, + 1, 0, 29.2, + 1, 0, 29.4, + 1, 0, 29.6, + 1, 0, 29.8, + 1, 0, 30, + 1, 0, 30.2, + 1, 0, 30.4, + 1, 0, 30.6, + 1, 0, 30.8, + 1, 0, 31, + 0.866025, 0.5, 29, + 0.866025, 0.5, 29.2, + 0.866025, 0.5, 29.4, + 0.866025, 0.5, 29.6, + 0.866025, 0.5, 29.8, + 0.866025, 0.5, 30, + 0.866025, 0.5, 30.2, + 0.866025, 0.5, 30.4, + 0.866025, 0.5, 30.6, + 0.866025, 0.5, 30.8, + 0.866025, 0.5, 31, + 0.5, 0.866025, 29, + 0.5, 0.866025, 29.2, + 0.5, 0.866025, 29.4, + 0.5, 0.866025, 29.6, + 0.5, 0.866025, 29.8, + 0.5, 0.866025, 30, + 0.5, 0.866025, 30.2, + 0.5, 0.866025, 30.4, + 0.5, 0.866025, 30.6, + 0.5, 0.866025, 30.8, + 0.5, 0.866025, 31, + 6.12323e-17, 1, 29, + 6.12323e-17, 1, 29.2, + 6.12323e-17, 1, 29.4, + 6.12323e-17, 1, 29.6, + 6.12323e-17, 1, 29.8, + 6.12323e-17, 1, 30, + 6.12323e-17, 1, 30.2, + 6.12323e-17, 1, 30.4, + 6.12323e-17, 1, 30.6, + 6.12323e-17, 1, 30.8, + 6.12323e-17, 1, 31, + -0.5, 0.866025, 29, + -0.5, 0.866025, 29.2, + -0.5, 0.866025, 29.4, + -0.5, 0.866025, 29.6, + -0.5, 0.866025, 29.8, + -0.5, 0.866025, 30, + -0.5, 0.866025, 30.2, + -0.5, 0.866025, 30.4, + -0.5, 0.866025, 30.6, + -0.5, 0.866025, 30.8, + -0.5, 0.866025, 31, + -0.866025, 0.5, 29, + -0.866025, 0.5, 29.2, + -0.866025, 0.5, 29.4, + -0.866025, 0.5, 29.6, + -0.866025, 0.5, 29.8, + -0.866025, 0.5, 30, + -0.866025, 0.5, 30.2, + -0.866025, 0.5, 30.4, + -0.866025, 0.5, 30.6, + -0.866025, 0.5, 30.8, + -0.866025, 0.5, 31, + -1, 1.22465e-16, 29, + -1, 1.22465e-16, 29.2, + -1, 1.22465e-16, 29.4, + -1, 1.22465e-16, 29.6, + -1, 1.22465e-16, 29.8, + -1, 1.22465e-16, 30, + -1, 1.22465e-16, 30.2, + -1, 1.22465e-16, 30.4, + -1, 1.22465e-16, 30.6, + -1, 1.22465e-16, 30.8, + -1, 1.22465e-16, 31, + -0.866025, -0.5, 29, + -0.866025, -0.5, 29.2, + -0.866025, -0.5, 29.4, + -0.866025, -0.5, 29.6, + -0.866025, -0.5, 29.8, + -0.866025, -0.5, 30, + -0.866025, -0.5, 30.2, + -0.866025, -0.5, 30.4, + -0.866025, -0.5, 30.6, + -0.866025, -0.5, 30.8, + -0.866025, -0.5, 31, + -0.5, -0.866025, 29, + -0.5, -0.866025, 29.2, + -0.5, -0.866025, 29.4, + -0.5, -0.866025, 29.6, + -0.5, -0.866025, 29.8, + -0.5, -0.866025, 30, + -0.5, -0.866025, 30.2, + -0.5, -0.866025, 30.4, + -0.5, -0.866025, 30.6, + -0.5, -0.866025, 30.8, + -0.5, -0.866025, 31, + -1.83697e-16, -1, 29, + -1.83697e-16, -1, 29.2, + -1.83697e-16, -1, 29.4, + -1.83697e-16, -1, 29.6, + -1.83697e-16, -1, 29.8, + -1.83697e-16, -1, 30, + -1.83697e-16, -1, 30.2, + -1.83697e-16, -1, 30.4, + -1.83697e-16, -1, 30.6, + -1.83697e-16, -1, 30.8, + -1.83697e-16, -1, 31, + 0.5, -0.866025, 29, + 0.5, -0.866025, 29.2, + 0.5, -0.866025, 29.4, + 0.5, -0.866025, 29.6, + 0.5, -0.866025, 29.8, + 0.5, -0.866025, 30, + 0.5, -0.866025, 30.2, + 0.5, -0.866025, 30.4, + 0.5, -0.866025, 30.6, + 0.5, -0.866025, 30.8, + 0.5, -0.866025, 31, + 0.866025, -0.5, 29, + 0.866025, -0.5, 29.2, + 0.866025, -0.5, 29.4, + 0.866025, -0.5, 29.6, + 0.866025, -0.5, 29.8, + 0.866025, -0.5, 30, + 0.866025, -0.5, 30.2, + 0.866025, -0.5, 30.4, + 0.866025, -0.5, 30.6, + 0.866025, -0.5, 30.8, + 0.866025, -0.5, 31, + 0, 0, 29, + 0, 0, 31 +}; +static const unsigned some_triangles_triangles_count = 1056; +static const unsigned some_triangles_triangles[3168] = +{ + 0, 1, 11, + 11, 1, 12, + 1, 2, 12, + 12, 2, 13, + 2, 3, 13, + 13, 3, 14, + 3, 4, 14, + 14, 4, 15, + 4, 5, 15, + 15, 5, 16, + 5, 6, 16, + 16, 6, 17, + 6, 7, 17, + 17, 7, 18, + 7, 8, 18, + 18, 8, 19, + 8, 9, 19, + 19, 9, 20, + 9, 10, 20, + 20, 10, 21, + 11, 12, 22, + 22, 12, 23, + 12, 13, 23, + 23, 13, 24, + 13, 14, 24, + 24, 14, 25, + 14, 15, 25, + 25, 15, 26, + 15, 16, 26, + 26, 16, 27, + 16, 17, 27, + 27, 17, 28, + 17, 18, 28, + 28, 18, 29, + 18, 19, 29, + 29, 19, 30, + 19, 20, 30, + 30, 20, 31, + 20, 21, 31, + 31, 21, 32, + 22, 23, 33, + 33, 23, 34, + 23, 24, 34, + 34, 24, 35, + 24, 25, 35, + 35, 25, 36, + 25, 26, 36, + 36, 26, 37, + 26, 27, 37, + 37, 27, 38, + 27, 28, 38, + 38, 28, 39, + 28, 29, 39, + 39, 29, 40, + 29, 30, 40, + 40, 30, 41, + 30, 31, 41, + 41, 31, 42, + 31, 32, 42, + 42, 32, 43, + 33, 34, 44, + 44, 34, 45, + 34, 35, 45, + 45, 35, 46, + 35, 36, 46, + 46, 36, 47, + 36, 37, 47, + 47, 37, 48, + 37, 38, 48, + 48, 38, 49, + 38, 39, 49, + 49, 39, 50, + 39, 40, 50, + 50, 40, 51, + 40, 41, 51, + 51, 41, 52, + 41, 42, 52, + 52, 42, 53, + 42, 43, 53, + 53, 43, 54, + 44, 45, 55, + 55, 45, 56, + 45, 46, 56, + 56, 46, 57, + 46, 47, 57, + 57, 47, 58, + 47, 48, 58, + 58, 48, 59, + 48, 49, 59, + 59, 49, 60, + 49, 50, 60, + 60, 50, 61, + 50, 51, 61, + 61, 51, 62, + 51, 52, 62, + 62, 52, 63, + 52, 53, 63, + 63, 53, 64, + 53, 54, 64, + 64, 54, 65, + 55, 56, 66, + 66, 56, 67, + 56, 57, 67, + 67, 57, 68, + 57, 58, 68, + 68, 58, 69, + 58, 59, 69, + 69, 59, 70, + 59, 60, 70, + 70, 60, 71, + 60, 61, 71, + 71, 61, 72, + 61, 62, 72, + 72, 62, 73, + 62, 63, 73, + 73, 63, 74, + 63, 64, 74, + 74, 64, 75, + 64, 65, 75, + 75, 65, 76, + 66, 67, 77, + 77, 67, 78, + 67, 68, 78, + 78, 68, 79, + 68, 69, 79, + 79, 69, 80, + 69, 70, 80, + 80, 70, 81, + 70, 71, 81, + 81, 71, 82, + 71, 72, 82, + 82, 72, 83, + 72, 73, 83, + 83, 73, 84, + 73, 74, 84, + 84, 74, 85, + 74, 75, 85, + 85, 75, 86, + 75, 76, 86, + 86, 76, 87, + 77, 78, 88, + 88, 78, 89, + 78, 79, 89, + 89, 79, 90, + 79, 80, 90, + 90, 80, 91, + 80, 81, 91, + 91, 81, 92, + 81, 82, 92, + 92, 82, 93, + 82, 83, 93, + 93, 83, 94, + 83, 84, 94, + 94, 84, 95, + 84, 85, 95, + 95, 85, 96, + 85, 86, 96, + 96, 86, 97, + 86, 87, 97, + 97, 87, 98, + 88, 89, 99, + 99, 89, 100, + 89, 90, 100, + 100, 90, 101, + 90, 91, 101, + 101, 91, 102, + 91, 92, 102, + 102, 92, 103, + 92, 93, 103, + 103, 93, 104, + 93, 94, 104, + 104, 94, 105, + 94, 95, 105, + 105, 95, 106, + 95, 96, 106, + 106, 96, 107, + 96, 97, 107, + 107, 97, 108, + 97, 98, 108, + 108, 98, 109, + 99, 100, 110, + 110, 100, 111, + 100, 101, 111, + 111, 101, 112, + 101, 102, 112, + 112, 102, 113, + 102, 103, 113, + 113, 103, 114, + 103, 104, 114, + 114, 104, 115, + 104, 105, 115, + 115, 105, 116, + 105, 106, 116, + 116, 106, 117, + 106, 107, 117, + 117, 107, 118, + 107, 108, 118, + 118, 108, 119, + 108, 109, 119, + 119, 109, 120, + 110, 111, 121, + 121, 111, 122, + 111, 112, 122, + 122, 112, 123, + 112, 113, 123, + 123, 113, 124, + 113, 114, 124, + 124, 114, 125, + 114, 115, 125, + 125, 115, 126, + 115, 116, 126, + 126, 116, 127, + 116, 117, 127, + 127, 117, 128, + 117, 118, 128, + 128, 118, 129, + 118, 119, 129, + 129, 119, 130, + 119, 120, 130, + 130, 120, 131, + 121, 122, 0, + 0, 122, 1, + 122, 123, 1, + 1, 123, 2, + 123, 124, 2, + 2, 124, 3, + 124, 125, 3, + 3, 125, 4, + 125, 126, 4, + 4, 126, 5, + 126, 127, 5, + 5, 127, 6, + 127, 128, 6, + 6, 128, 7, + 128, 129, 7, + 7, 129, 8, + 129, 130, 8, + 8, 130, 9, + 130, 131, 9, + 9, 131, 10, + 132, 0, 11, + 132, 11, 22, + 132, 22, 33, + 132, 33, 44, + 132, 44, 55, + 132, 55, 66, + 132, 66, 77, + 132, 77, 88, + 132, 88, 99, + 132, 99, 110, + 132, 110, 121, + 132, 121, 0, + 133, 21, 10, + 133, 32, 21, + 133, 43, 32, + 133, 54, 43, + 133, 65, 54, + 133, 76, 65, + 133, 87, 76, + 133, 98, 87, + 133, 109, 98, + 133, 120, 109, + 133, 131, 120, + 133, 10, 131, + 134, 135, 145, + 145, 135, 146, + 135, 136, 146, + 146, 136, 147, + 136, 137, 147, + 147, 137, 148, + 137, 138, 148, + 148, 138, 149, + 138, 139, 149, + 149, 139, 150, + 139, 140, 150, + 150, 140, 151, + 140, 141, 151, + 151, 141, 152, + 141, 142, 152, + 152, 142, 153, + 142, 143, 153, + 153, 143, 154, + 143, 144, 154, + 154, 144, 155, + 145, 146, 156, + 156, 146, 157, + 146, 147, 157, + 157, 147, 158, + 147, 148, 158, + 158, 148, 159, + 148, 149, 159, + 159, 149, 160, + 149, 150, 160, + 160, 150, 161, + 150, 151, 161, + 161, 151, 162, + 151, 152, 162, + 162, 152, 163, + 152, 153, 163, + 163, 153, 164, + 153, 154, 164, + 164, 154, 165, + 154, 155, 165, + 165, 155, 166, + 156, 157, 167, + 167, 157, 168, + 157, 158, 168, + 168, 158, 169, + 158, 159, 169, + 169, 159, 170, + 159, 160, 170, + 170, 160, 171, + 160, 161, 171, + 171, 161, 172, + 161, 162, 172, + 172, 162, 173, + 162, 163, 173, + 173, 163, 174, + 163, 164, 174, + 174, 164, 175, + 164, 165, 175, + 175, 165, 176, + 165, 166, 176, + 176, 166, 177, + 167, 168, 178, + 178, 168, 179, + 168, 169, 179, + 179, 169, 180, + 169, 170, 180, + 180, 170, 181, + 170, 171, 181, + 181, 171, 182, + 171, 172, 182, + 182, 172, 183, + 172, 173, 183, + 183, 173, 184, + 173, 174, 184, + 184, 174, 185, + 174, 175, 185, + 185, 175, 186, + 175, 176, 186, + 186, 176, 187, + 176, 177, 187, + 187, 177, 188, + 178, 179, 189, + 189, 179, 190, + 179, 180, 190, + 190, 180, 191, + 180, 181, 191, + 191, 181, 192, + 181, 182, 192, + 192, 182, 193, + 182, 183, 193, + 193, 183, 194, + 183, 184, 194, + 194, 184, 195, + 184, 185, 195, + 195, 185, 196, + 185, 186, 196, + 196, 186, 197, + 186, 187, 197, + 197, 187, 198, + 187, 188, 198, + 198, 188, 199, + 189, 190, 200, + 200, 190, 201, + 190, 191, 201, + 201, 191, 202, + 191, 192, 202, + 202, 192, 203, + 192, 193, 203, + 203, 193, 204, + 193, 194, 204, + 204, 194, 205, + 194, 195, 205, + 205, 195, 206, + 195, 196, 206, + 206, 196, 207, + 196, 197, 207, + 207, 197, 208, + 197, 198, 208, + 208, 198, 209, + 198, 199, 209, + 209, 199, 210, + 200, 201, 211, + 211, 201, 212, + 201, 202, 212, + 212, 202, 213, + 202, 203, 213, + 213, 203, 214, + 203, 204, 214, + 214, 204, 215, + 204, 205, 215, + 215, 205, 216, + 205, 206, 216, + 216, 206, 217, + 206, 207, 217, + 217, 207, 218, + 207, 208, 218, + 218, 208, 219, + 208, 209, 219, + 219, 209, 220, + 209, 210, 220, + 220, 210, 221, + 211, 212, 222, + 222, 212, 223, + 212, 213, 223, + 223, 213, 224, + 213, 214, 224, + 224, 214, 225, + 214, 215, 225, + 225, 215, 226, + 215, 216, 226, + 226, 216, 227, + 216, 217, 227, + 227, 217, 228, + 217, 218, 228, + 228, 218, 229, + 218, 219, 229, + 229, 219, 230, + 219, 220, 230, + 230, 220, 231, + 220, 221, 231, + 231, 221, 232, + 222, 223, 233, + 233, 223, 234, + 223, 224, 234, + 234, 224, 235, + 224, 225, 235, + 235, 225, 236, + 225, 226, 236, + 236, 226, 237, + 226, 227, 237, + 237, 227, 238, + 227, 228, 238, + 238, 228, 239, + 228, 229, 239, + 239, 229, 240, + 229, 230, 240, + 240, 230, 241, + 230, 231, 241, + 241, 231, 242, + 231, 232, 242, + 242, 232, 243, + 233, 234, 244, + 244, 234, 245, + 234, 235, 245, + 245, 235, 246, + 235, 236, 246, + 246, 236, 247, + 236, 237, 247, + 247, 237, 248, + 237, 238, 248, + 248, 238, 249, + 238, 239, 249, + 249, 239, 250, + 239, 240, 250, + 250, 240, 251, + 240, 241, 251, + 251, 241, 252, + 241, 242, 252, + 252, 242, 253, + 242, 243, 253, + 253, 243, 254, + 244, 245, 255, + 255, 245, 256, + 245, 246, 256, + 256, 246, 257, + 246, 247, 257, + 257, 247, 258, + 247, 248, 258, + 258, 248, 259, + 248, 249, 259, + 259, 249, 260, + 249, 250, 260, + 260, 250, 261, + 250, 251, 261, + 261, 251, 262, + 251, 252, 262, + 262, 252, 263, + 252, 253, 263, + 263, 253, 264, + 253, 254, 264, + 264, 254, 265, + 255, 256, 134, + 134, 256, 135, + 256, 257, 135, + 135, 257, 136, + 257, 258, 136, + 136, 258, 137, + 258, 259, 137, + 137, 259, 138, + 259, 260, 138, + 138, 260, 139, + 260, 261, 139, + 139, 261, 140, + 261, 262, 140, + 140, 262, 141, + 262, 263, 141, + 141, 263, 142, + 263, 264, 142, + 142, 264, 143, + 264, 265, 143, + 143, 265, 144, + 266, 134, 145, + 266, 145, 156, + 266, 156, 167, + 266, 167, 178, + 266, 178, 189, + 266, 189, 200, + 266, 200, 211, + 266, 211, 222, + 266, 222, 233, + 266, 233, 244, + 266, 244, 255, + 266, 255, 134, + 267, 155, 144, + 267, 166, 155, + 267, 177, 166, + 267, 188, 177, + 267, 199, 188, + 267, 210, 199, + 267, 221, 210, + 267, 232, 221, + 267, 243, 232, + 267, 254, 243, + 267, 265, 254, + 267, 144, 265, + 268, 269, 279, + 279, 269, 280, + 269, 270, 280, + 280, 270, 281, + 270, 271, 281, + 281, 271, 282, + 271, 272, 282, + 282, 272, 283, + 272, 273, 283, + 283, 273, 284, + 273, 274, 284, + 284, 274, 285, + 274, 275, 285, + 285, 275, 286, + 275, 276, 286, + 286, 276, 287, + 276, 277, 287, + 287, 277, 288, + 277, 278, 288, + 288, 278, 289, + 279, 280, 290, + 290, 280, 291, + 280, 281, 291, + 291, 281, 292, + 281, 282, 292, + 292, 282, 293, + 282, 283, 293, + 293, 283, 294, + 283, 284, 294, + 294, 284, 295, + 284, 285, 295, + 295, 285, 296, + 285, 286, 296, + 296, 286, 297, + 286, 287, 297, + 297, 287, 298, + 287, 288, 298, + 298, 288, 299, + 288, 289, 299, + 299, 289, 300, + 290, 291, 301, + 301, 291, 302, + 291, 292, 302, + 302, 292, 303, + 292, 293, 303, + 303, 293, 304, + 293, 294, 304, + 304, 294, 305, + 294, 295, 305, + 305, 295, 306, + 295, 296, 306, + 306, 296, 307, + 296, 297, 307, + 307, 297, 308, + 297, 298, 308, + 308, 298, 309, + 298, 299, 309, + 309, 299, 310, + 299, 300, 310, + 310, 300, 311, + 301, 302, 312, + 312, 302, 313, + 302, 303, 313, + 313, 303, 314, + 303, 304, 314, + 314, 304, 315, + 304, 305, 315, + 315, 305, 316, + 305, 306, 316, + 316, 306, 317, + 306, 307, 317, + 317, 307, 318, + 307, 308, 318, + 318, 308, 319, + 308, 309, 319, + 319, 309, 320, + 309, 310, 320, + 320, 310, 321, + 310, 311, 321, + 321, 311, 322, + 312, 313, 323, + 323, 313, 324, + 313, 314, 324, + 324, 314, 325, + 314, 315, 325, + 325, 315, 326, + 315, 316, 326, + 326, 316, 327, + 316, 317, 327, + 327, 317, 328, + 317, 318, 328, + 328, 318, 329, + 318, 319, 329, + 329, 319, 330, + 319, 320, 330, + 330, 320, 331, + 320, 321, 331, + 331, 321, 332, + 321, 322, 332, + 332, 322, 333, + 323, 324, 334, + 334, 324, 335, + 324, 325, 335, + 335, 325, 336, + 325, 326, 336, + 336, 326, 337, + 326, 327, 337, + 337, 327, 338, + 327, 328, 338, + 338, 328, 339, + 328, 329, 339, + 339, 329, 340, + 329, 330, 340, + 340, 330, 341, + 330, 331, 341, + 341, 331, 342, + 331, 332, 342, + 342, 332, 343, + 332, 333, 343, + 343, 333, 344, + 334, 335, 345, + 345, 335, 346, + 335, 336, 346, + 346, 336, 347, + 336, 337, 347, + 347, 337, 348, + 337, 338, 348, + 348, 338, 349, + 338, 339, 349, + 349, 339, 350, + 339, 340, 350, + 350, 340, 351, + 340, 341, 351, + 351, 341, 352, + 341, 342, 352, + 352, 342, 353, + 342, 343, 353, + 353, 343, 354, + 343, 344, 354, + 354, 344, 355, + 345, 346, 356, + 356, 346, 357, + 346, 347, 357, + 357, 347, 358, + 347, 348, 358, + 358, 348, 359, + 348, 349, 359, + 359, 349, 360, + 349, 350, 360, + 360, 350, 361, + 350, 351, 361, + 361, 351, 362, + 351, 352, 362, + 362, 352, 363, + 352, 353, 363, + 363, 353, 364, + 353, 354, 364, + 364, 354, 365, + 354, 355, 365, + 365, 355, 366, + 356, 357, 367, + 367, 357, 368, + 357, 358, 368, + 368, 358, 369, + 358, 359, 369, + 369, 359, 370, + 359, 360, 370, + 370, 360, 371, + 360, 361, 371, + 371, 361, 372, + 361, 362, 372, + 372, 362, 373, + 362, 363, 373, + 373, 363, 374, + 363, 364, 374, + 374, 364, 375, + 364, 365, 375, + 375, 365, 376, + 365, 366, 376, + 376, 366, 377, + 367, 368, 378, + 378, 368, 379, + 368, 369, 379, + 379, 369, 380, + 369, 370, 380, + 380, 370, 381, + 370, 371, 381, + 381, 371, 382, + 371, 372, 382, + 382, 372, 383, + 372, 373, 383, + 383, 373, 384, + 373, 374, 384, + 384, 374, 385, + 374, 375, 385, + 385, 375, 386, + 375, 376, 386, + 386, 376, 387, + 376, 377, 387, + 387, 377, 388, + 378, 379, 389, + 389, 379, 390, + 379, 380, 390, + 390, 380, 391, + 380, 381, 391, + 391, 381, 392, + 381, 382, 392, + 392, 382, 393, + 382, 383, 393, + 393, 383, 394, + 383, 384, 394, + 394, 384, 395, + 384, 385, 395, + 395, 385, 396, + 385, 386, 396, + 396, 386, 397, + 386, 387, 397, + 397, 387, 398, + 387, 388, 398, + 398, 388, 399, + 389, 390, 268, + 268, 390, 269, + 390, 391, 269, + 269, 391, 270, + 391, 392, 270, + 270, 392, 271, + 392, 393, 271, + 271, 393, 272, + 393, 394, 272, + 272, 394, 273, + 394, 395, 273, + 273, 395, 274, + 395, 396, 274, + 274, 396, 275, + 396, 397, 275, + 275, 397, 276, + 397, 398, 276, + 276, 398, 277, + 398, 399, 277, + 277, 399, 278, + 400, 268, 279, + 400, 279, 290, + 400, 290, 301, + 400, 301, 312, + 400, 312, 323, + 400, 323, 334, + 400, 334, 345, + 400, 345, 356, + 400, 356, 367, + 400, 367, 378, + 400, 378, 389, + 400, 389, 268, + 401, 289, 278, + 401, 300, 289, + 401, 311, 300, + 401, 322, 311, + 401, 333, 322, + 401, 344, 333, + 401, 355, 344, + 401, 366, 355, + 401, 377, 366, + 401, 388, 377, + 401, 399, 388, + 401, 278, 399, + 402, 403, 413, + 413, 403, 414, + 403, 404, 414, + 414, 404, 415, + 404, 405, 415, + 415, 405, 416, + 405, 406, 416, + 416, 406, 417, + 406, 407, 417, + 417, 407, 418, + 407, 408, 418, + 418, 408, 419, + 408, 409, 419, + 419, 409, 420, + 409, 410, 420, + 420, 410, 421, + 410, 411, 421, + 421, 411, 422, + 411, 412, 422, + 422, 412, 423, + 413, 414, 424, + 424, 414, 425, + 414, 415, 425, + 425, 415, 426, + 415, 416, 426, + 426, 416, 427, + 416, 417, 427, + 427, 417, 428, + 417, 418, 428, + 428, 418, 429, + 418, 419, 429, + 429, 419, 430, + 419, 420, 430, + 430, 420, 431, + 420, 421, 431, + 431, 421, 432, + 421, 422, 432, + 432, 422, 433, + 422, 423, 433, + 433, 423, 434, + 424, 425, 435, + 435, 425, 436, + 425, 426, 436, + 436, 426, 437, + 426, 427, 437, + 437, 427, 438, + 427, 428, 438, + 438, 428, 439, + 428, 429, 439, + 439, 429, 440, + 429, 430, 440, + 440, 430, 441, + 430, 431, 441, + 441, 431, 442, + 431, 432, 442, + 442, 432, 443, + 432, 433, 443, + 443, 433, 444, + 433, 434, 444, + 444, 434, 445, + 435, 436, 446, + 446, 436, 447, + 436, 437, 447, + 447, 437, 448, + 437, 438, 448, + 448, 438, 449, + 438, 439, 449, + 449, 439, 450, + 439, 440, 450, + 450, 440, 451, + 440, 441, 451, + 451, 441, 452, + 441, 442, 452, + 452, 442, 453, + 442, 443, 453, + 453, 443, 454, + 443, 444, 454, + 454, 444, 455, + 444, 445, 455, + 455, 445, 456, + 446, 447, 457, + 457, 447, 458, + 447, 448, 458, + 458, 448, 459, + 448, 449, 459, + 459, 449, 460, + 449, 450, 460, + 460, 450, 461, + 450, 451, 461, + 461, 451, 462, + 451, 452, 462, + 462, 452, 463, + 452, 453, 463, + 463, 453, 464, + 453, 454, 464, + 464, 454, 465, + 454, 455, 465, + 465, 455, 466, + 455, 456, 466, + 466, 456, 467, + 457, 458, 468, + 468, 458, 469, + 458, 459, 469, + 469, 459, 470, + 459, 460, 470, + 470, 460, 471, + 460, 461, 471, + 471, 461, 472, + 461, 462, 472, + 472, 462, 473, + 462, 463, 473, + 473, 463, 474, + 463, 464, 474, + 474, 464, 475, + 464, 465, 475, + 475, 465, 476, + 465, 466, 476, + 476, 466, 477, + 466, 467, 477, + 477, 467, 478, + 468, 469, 479, + 479, 469, 480, + 469, 470, 480, + 480, 470, 481, + 470, 471, 481, + 481, 471, 482, + 471, 472, 482, + 482, 472, 483, + 472, 473, 483, + 483, 473, 484, + 473, 474, 484, + 484, 474, 485, + 474, 475, 485, + 485, 475, 486, + 475, 476, 486, + 486, 476, 487, + 476, 477, 487, + 487, 477, 488, + 477, 478, 488, + 488, 478, 489, + 479, 480, 490, + 490, 480, 491, + 480, 481, 491, + 491, 481, 492, + 481, 482, 492, + 492, 482, 493, + 482, 483, 493, + 493, 483, 494, + 483, 484, 494, + 494, 484, 495, + 484, 485, 495, + 495, 485, 496, + 485, 486, 496, + 496, 486, 497, + 486, 487, 497, + 497, 487, 498, + 487, 488, 498, + 498, 488, 499, + 488, 489, 499, + 499, 489, 500, + 490, 491, 501, + 501, 491, 502, + 491, 492, 502, + 502, 492, 503, + 492, 493, 503, + 503, 493, 504, + 493, 494, 504, + 504, 494, 505, + 494, 495, 505, + 505, 495, 506, + 495, 496, 506, + 506, 496, 507, + 496, 497, 507, + 507, 497, 508, + 497, 498, 508, + 508, 498, 509, + 498, 499, 509, + 509, 499, 510, + 499, 500, 510, + 510, 500, 511, + 501, 502, 512, + 512, 502, 513, + 502, 503, 513, + 513, 503, 514, + 503, 504, 514, + 514, 504, 515, + 504, 505, 515, + 515, 505, 516, + 505, 506, 516, + 516, 506, 517, + 506, 507, 517, + 517, 507, 518, + 507, 508, 518, + 518, 508, 519, + 508, 509, 519, + 519, 509, 520, + 509, 510, 520, + 520, 510, 521, + 510, 511, 521, + 521, 511, 522, + 512, 513, 523, + 523, 513, 524, + 513, 514, 524, + 524, 514, 525, + 514, 515, 525, + 525, 515, 526, + 515, 516, 526, + 526, 516, 527, + 516, 517, 527, + 527, 517, 528, + 517, 518, 528, + 528, 518, 529, + 518, 519, 529, + 529, 519, 530, + 519, 520, 530, + 530, 520, 531, + 520, 521, 531, + 531, 521, 532, + 521, 522, 532, + 532, 522, 533, + 523, 524, 402, + 402, 524, 403, + 524, 525, 403, + 403, 525, 404, + 525, 526, 404, + 404, 526, 405, + 526, 527, 405, + 405, 527, 406, + 527, 528, 406, + 406, 528, 407, + 528, 529, 407, + 407, 529, 408, + 529, 530, 408, + 408, 530, 409, + 530, 531, 409, + 409, 531, 410, + 531, 532, 410, + 410, 532, 411, + 532, 533, 411, + 411, 533, 412, + 534, 402, 413, + 534, 413, 424, + 534, 424, 435, + 534, 435, 446, + 534, 446, 457, + 534, 457, 468, + 534, 468, 479, + 534, 479, 490, + 534, 490, 501, + 534, 501, 512, + 534, 512, 523, + 534, 523, 402, + 535, 423, 412, + 535, 434, 423, + 535, 445, 434, + 535, 456, 445, + 535, 467, 456, + 535, 478, 467, + 535, 489, 478, + 535, 500, 489, + 535, 511, 500, + 535, 522, 511, + 535, 533, 522, + 535, 412, 533 +}; +static const unsigned some_triangles_properties[3168] = +{ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 2, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0, + 3, 0, 0 +}; + +#define NB_CYL 4 +#define CYL_VRTX_COUNT 134u +#define CYL_TRG_COUNT 264u + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned e, count; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* Create a scene */ + ctx.positions = some_triangles_vertices; + ctx.indices = some_triangles_triangles; + ctx.properties = some_triangles_properties; + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + some_triangles_triangles_count, get_indices, get_media_from_properties, + some_triangles_vertices_count, get_position, &ctx, &scn)); + + OK(senc3d_scene_get_vertices_count(scn, &count)); + CHK(count == NB_CYL * CYL_VRTX_COUNT); + OK(senc3d_scene_get_triangles_count(scn, &count)); + CHK(count == NB_CYL * CYL_TRG_COUNT); + + OK(senc3d_scene_get_enclosure_count(scn, &count)); + CHK(count == 1 + NB_CYL); + FOR_EACH(e, 0, count) { + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + OK(senc3d_scene_get_enclosure(scn, e, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + CHK(header.primitives_count == + (e ? CYL_TRG_COUNT : NB_CYL * CYL_TRG_COUNT)); + OK(senc3d_enclosure_ref_put(enclosure)); + } + + OK(senc3d_scene_ref_put(scn)); + OK(senc3d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_senc3d_unspecified_medium.c b/src/test_senc3d_unspecified_medium.c @@ -0,0 +1,327 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ + +/* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_unspecified_properties. + * This test is similar to test_SENC3D_many_enclosures that creates a huge + * geometry by program. */ + +#include "senc3d.h" +#include "SENC3D_s3d_helper.h" +#include "test_SENC3D_utils.h" + +#include <rsys/double3.h> + +#define SG3_UNSPECIFED_PROPERTY UINT_MAX + +/* Dump of star-geometry 'front_unspecified'. */ +static const unsigned front_unspecified_vertices_count = 8; +static const double front_unspecified_vertices[24] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1 +}; +static const unsigned front_unspecified_triangles_count = 12; +static const unsigned front_unspecified_triangles[36] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5 +}; +static const unsigned front_unspecified_properties[36] = +{ + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY +}; +/* Dump of star-geometry 'front_half_unspecified'. */ +static const unsigned front_half_unspecified_vertices_count = 8; +static const double front_half_unspecified_vertices[24] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1 +}; +static const unsigned front_half_unspecified_triangles_count = 12; +static const unsigned front_half_unspecified_triangles[36] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5 +}; +static const unsigned front_half_unspecified_properties[36] = +{ + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + 0, 1, 0, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + 0, 1, 0, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + 0, 1, 0, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + 0, 1, 0, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + 0, 1, 0, + SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, + 0, 1, 0 +}; +/* Dump of star-geometry 'all_defined'. */ +static const unsigned all_defined_vertices_count = 8; +static const double all_defined_vertices[24] = +{ + 0.1, 0, 0, + 1, 0, 0, + 0, 1, 0, + 1, 1, 0, + 0, 0, 1.1, + 1, 0, 1, + 0, 1, 1, + 1, 1.1, 1 +}; +static const unsigned all_defined_triangles_count = 12; +static const unsigned all_defined_triangles[36] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5 +}; +static const unsigned all_defined_properties[36] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; + +static void +test(const int convention) +{ + struct mem_allocator allocator; + struct senc3d_device* dev = NULL; + struct senc3d_scene* scn = NULL; + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + unsigned medium, expected_external_medium, expected_internal_medium; + unsigned gid; + enum senc3d_side side; + struct context ctx = CONTEXT_NULL__; + unsigned i, t, ecount; + const int conv_front = (convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev)); + + /* Geometry with no media information on both sides */ + ctx.positions = front_unspecified_vertices; + ctx.indices = front_unspecified_triangles; + ctx.properties = front_unspecified_properties; + OK(senc3d_scene_create(dev, convention, front_unspecified_triangles_count, + get_indices, get_media_from_properties, front_unspecified_vertices_count, + get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + FOR_EACH(i, 0, ecount) { + struct senc3d_enclosure* ee; + struct senc3d_enclosure_header hh; + unsigned cc; + OK(senc3d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + CHK(header.enclosed_media_count == 1); + + OK(senc3d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the cube in input triangles: + * if convention is front, front medium (unspecified) is outside, + * that is medium 0's enclosure is infinite */ + expected_external_medium = conv_front ? SENC3D_UNSPECIFIED_MEDIUM : 1; + expected_internal_medium = conv_front ? 1 : SENC3D_UNSPECIFIED_MEDIUM; + + CHK(medium == (header.is_infinite + ? expected_external_medium : expected_internal_medium)); + CHK(header.primitives_count == ntriangles); + CHK(header.unique_primitives_count == ntriangles); + CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == (i == 0)); + + OK(senc3d_scene_get_enclosure_count_by_medium(scn, medium, &cc)); + CHK(cc == 1); + OK(senc3d_scene_get_enclosure_by_medium(scn, medium, 0, &ee)); + OK(senc3d_enclosure_get_header(ee, &hh)); + CHK(header.enclosure_id == hh.enclosure_id); + OK(senc3d_enclosure_ref_put(ee)); + + FOR_EACH(t, 0, header.primitives_count) { + unsigned ind[3]; + OK(senc3d_enclosure_get_triangle_id(enclosure, t, &gid, &side)); + CHK(gid == t); + CHK(side == (medium == 1) ? SENC3D_BACK : SENC3D_FRONT); + OK(senc3d_enclosure_get_triangle(enclosure, t, ind)); + } + OK(senc3d_enclosure_ref_put(enclosure)); + } + OK(senc3d_scene_ref_put(scn)); + + /* Same geometry, front media are defined for odd triangles */ + ctx.positions = front_half_unspecified_vertices; + ctx.indices = front_half_unspecified_triangles; + ctx.properties = front_half_unspecified_properties; + OK(senc3d_scene_create(dev, convention, front_half_unspecified_triangles_count, + get_indices, get_media_from_properties, front_half_unspecified_vertices_count, + get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + FOR_EACH(i, 0, ecount) { + unsigned expected_external_media_count, expected_internal_media_count, + expected_media_count; + OK(senc3d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + + OK(senc3d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the cube in input triangles: + * if convention is front, front medium is outside and the enclosure + * contains 2 media */ + expected_external_media_count = conv_front ? 2 : 1; + expected_internal_media_count = conv_front ? 1 : 2; + expected_media_count = header.is_infinite + ? expected_external_media_count : expected_internal_media_count; + CHK(header.enclosed_media_count == expected_media_count); + OK(senc3d_enclosure_ref_put(enclosure)); + } + OK(senc3d_scene_ref_put(scn)); + + /* Same geometry, all media are defined */ + ctx.positions = all_defined_vertices; + ctx.indices = all_defined_triangles; + ctx.properties = all_defined_properties; + OK(senc3d_scene_create(dev, convention, all_defined_triangles_count, + get_indices, get_media_from_properties, all_defined_vertices_count, + get_position, &ctx, &scn)); + + OK(senc3d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + + FOR_EACH(i, 0, ecount) { + struct senc3d_enclosure* ee; + struct senc3d_enclosure_header hh; + unsigned cc; + OK(senc3d_scene_get_enclosure(scn, i, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + CHK(header.enclosure_id == i); + CHK(header.enclosed_media_count == 1); + OK(senc3d_enclosure_get_medium(enclosure, 0, &medium)); + /* Geometrical normals point outside the cube in input triangles: + * if convention is front, front medium (0) is outside, + * that is medium 0's enclosure is infinite */ + CHK(conv_front == ((medium == 0) == header.is_infinite)); + CHK(header.primitives_count == ntriangles); + CHK(header.unique_primitives_count == ntriangles); + CHK(header.vertices_count == nvertices); + CHK(header.is_infinite == (i == 0)); + + OK(senc3d_scene_get_enclosure_count_by_medium(scn, medium, &cc)); + CHK(cc == 1); + OK(senc3d_scene_get_enclosure_by_medium(scn, medium, 0, &ee)); + OK(senc3d_enclosure_get_header(ee, &hh)); + CHK(header.enclosure_id == hh.enclosure_id); + OK(senc3d_enclosure_ref_put(ee)); + + FOR_EACH(t, 0, header.primitives_count) { + OK(senc3d_enclosure_get_triangle_id(enclosure, t, &gid, &side)); + CHK(gid == t); + CHK(side == (medium == 1) ? SENC3D_BACK : SENC3D_FRONT); + } + OK(senc3d_enclosure_ref_put(enclosure)); + } + + SENC3D(scene_ref_put(scn)); + SENC3D(device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); +} + +int +main(int argc, char** argv) +{ + (void) argc, (void) argv; + test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE); + test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_INSIDE); + test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_OUTSIDE); + test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_OUTSIDE); + return 0; +} diff --git a/src/test_senc3d_utils.h b/src/test_senc3d_utils.h @@ -0,0 +1,271 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 TEST_UTILS_H +#define TEST_UTILS_H + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/double3.h> + +#include <stdio.h> + +#define OK(Expr) CHK((Expr) == RES_OK) +#define BA(Expr) CHK((Expr) == RES_BAD_ARG) + +/******************************************************************************* + * Geometry + ******************************************************************************/ +/* Distorded cube */ +static const double box_vertices[8/*#vertices*/*3/*#coords per vertex*/] = { + 0.1, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 0.0, 0.0, 1.1, + 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 1.1, 1.0 +}; +/* Need a true cube for some tests */ +static const double cube_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = { + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 1.0, 1.0 +}; +static const unsigned nvertices = sizeof(box_vertices) / sizeof(double[3]); +STATIC_ASSERT(sizeof(box_vertices) == sizeof(cube_vertices), + The_2_geometries_must_have_the_same_number_of_vertices); + +/* The following array lists the indices toward the 3D vertices of each + * triangle. + * ,2---,3 ,2----3 + * ,' | ,'/| ,'/| \ | + * 6----7' / | 6' / | \ | Y + * |', | / ,1 | / ,0---,1 | + * | ',|/,' |/,' | ,' o--X + * 4----5' 4----5' / + * Front, right Back, left and Z + * and Top faces bottom faces */ +static const unsigned +box_indices[12/*#triangles*/*3/*#indices per triangle*/] = { + 0, 2, 1, 1, 2, 3, /* Front face */ + 0, 4, 2, 2, 4, 6, /* Left face*/ + 4, 5, 6, 6, 5, 7, /* Back face */ + 3, 7, 1, 1, 7, 5, /* Right face */ + 2, 6, 3, 3, 6, 7, /* Top face */ + 0, 1, 4, 4, 1, 5 /* Bottom face */ +}; +static const unsigned +ntriangles = sizeof(box_indices) / (3 * sizeof(*box_indices)); + +struct context { + const double* positions; + const unsigned* indices; + const unsigned* front_media; + const unsigned* back_media; + const unsigned* properties; + void* custom; + double offset[3]; + double scale; + char reverse_vrtx, reverse_med; +}; +#define CONTEXT_NULL__ {\ + NULL, NULL, NULL, NULL, NULL, NULL, {0,0,0}, 1, 0, 0\ +} + +static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; +static const unsigned medium2[12] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; +static const unsigned medium1_3[12] = { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 }; +static const unsigned medium1_back0[12] = { 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }; +static const unsigned medium1_front0[12] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + +static INLINE void +get_indices(const unsigned itri, unsigned ids[3], void* context) +{ + const struct context* ctx = context; + ASSERT(ids && ctx); + ids[0] = ctx->indices[itri * 3 + 0]; + ids[ctx->reverse_vrtx ? 2 : 1] = ctx->indices[itri * 3 + 1]; + ids[ctx->reverse_vrtx ? 1 : 2] = ctx->indices[itri * 3 + 2]; +} + +static INLINE void +get_position(const unsigned ivert, double pos[3], void* context) +{ + const struct context* ctx = context; + ASSERT(pos && ctx); + pos[0] = ctx->positions[ivert * 3 + 0] * ctx->scale + ctx->offset[0]; + pos[1] = ctx->positions[ivert * 3 + 1] * ctx->scale + ctx->offset[1]; + pos[2] = ctx->positions[ivert * 3 + 2] * ctx->scale + ctx->offset[2]; +} + +static INLINE void +get_media(const unsigned itri, unsigned medium[2], void* context) +{ + const struct context* ctx = context; + ASSERT(medium && ctx); + medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[itri]; + medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri]; +} + +static INLINE void +get_media_from_properties(const unsigned itri, unsigned medium[2], void* context) +{ + const struct context* ctx = context; + ASSERT(medium && ctx); + medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * itri + 0]; + medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * itri + 1]; +} + +/******************************************************************************* + * Miscellaneous + ******************************************************************************/ +static INLINE void +dump_global + (struct senc3d_scene* scn, + const char* name) +{ + FILE* stream; + unsigned triangles_count, vertices_count, i; + + ASSERT(scn && name); + + OK(senc3d_scene_get_vertices_count(scn, &vertices_count)); + OK(senc3d_scene_get_triangles_count(scn, &triangles_count)); + + stream = fopen(name, "w"); + CHK(stream); + FOR_EACH(i, 0, vertices_count) { + double tmp[3]; + OK(senc3d_scene_get_vertex(scn, i, tmp)); + fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); + } + FOR_EACH(i, 0, triangles_count) { + unsigned indices[3]; + OK(senc3d_scene_get_triangle(scn, i, indices)); + fprintf(stream, "f %lu %lu %lu\n", (unsigned long)(1 + indices[0]), + (unsigned long)(1 + indices[1]), (unsigned long)(1 + indices[2])); + } + fclose(stream); +} + +static INLINE void +dump_enclosure + (struct senc3d_scene* scn, + const unsigned enc, + const char* name) +{ + struct senc3d_enclosure* enclosure; + struct senc3d_enclosure_header header; + FILE* stream; + unsigned count, i; + + ASSERT(scn && name); + + SENC3D(scene_get_enclosure_count(scn, &count)); + ASSERT(enc < count); + OK(senc3d_scene_get_enclosure(scn, enc, &enclosure)); + OK(senc3d_enclosure_get_header(enclosure, &header)); + + stream = fopen(name, "w"); + CHK(stream); + FOR_EACH(i, 0, header.vertices_count) { + double tmp[3]; + OK(senc3d_enclosure_get_vertex(enclosure, i, tmp)); + fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); + } + FOR_EACH(i, 0, header.primitives_count) { + unsigned indices[3]; + OK(senc3d_enclosure_get_triangle(enclosure, i, indices)); + fprintf(stream, "f %lu %lu %lu\n", (unsigned long)(1+indices[0]), + (unsigned long)(1+indices[1]), (unsigned long)(1+indices[2])); + } + OK(senc3d_enclosure_ref_put(enclosure)); + fclose(stream); +} + +static INLINE void +check_memory_allocator(struct mem_allocator* allocator) +{ + if(MEM_ALLOCATED_SIZE(allocator)) { + char dump[1024]; + MEM_DUMP(allocator, dump, sizeof(dump)); + fprintf(stderr, "%s\n", dump); + FATAL("Memory leaks.\n"); + } +} + +/******************************************************************************* + * Check functions + ******************************************************************************/ +/* Compare the itri-th triangle of enclosure with a triangle described by trg2 & vertices2 */ +static INLINE void +cmp_trg + (const unsigned itri, + const struct senc3d_enclosure* enclosure, + const unsigned trg2[3], + const double* vertices2, + int* trg_eq, + int* trg_reversed) +{ + unsigned trg1[3]; + double t1[3][3]; + double t2[3][3]; + unsigned trg1_eq[3] = { 3, 3, 3 }; + unsigned i, j, fst_vrtx = 3; + + ASSERT(enclosure && trg2 && vertices2 && trg_eq && trg_reversed); + + OK(senc3d_enclosure_get_triangle(enclosure, itri, trg1)); + FOR_EACH(i, 0, 3) { + OK(senc3d_enclosure_get_vertex(enclosure, trg1[i], t1[i])); + d3_set(t2[i], vertices2 + (3 * trg2[i])); + } + FOR_EACH(i, 0, 3) { + FOR_EACH(j, 0, 3) { + if(d3_eq(t1[i], t2[j])) { + trg1_eq[i] = j; + if(i == 0) fst_vrtx = j; + break; + } + } + } + FOR_EACH(i, 0, 3) { + if(trg1_eq[i] == 3) { + *trg_eq = 0; + return; + } + if(trg1_eq[i] == trg1_eq[(i + 1) % 3] + || trg1_eq[i] == trg1_eq[(i + 2) % 3]) { + *trg_eq = 0; + return; + } + } + /* Same 3 vertices */ + ASSERT(fst_vrtx != 3); + *trg_eq = 1; + + *trg_reversed = (trg1_eq[1] != (fst_vrtx + 1) % 3); + ASSERT(*trg_reversed != (trg1_eq[1] != (fst_vrtx + 2) % 3)); +} + +#endif /* TEST_UTILS_H */ diff --git a/src/test_senc3d_utils2.h b/src/test_senc3d_utils2.h @@ -0,0 +1,107 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (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 TEST_UTILS2_H +#define TEST_UTILS2_H + +#if !defined(NB_CYL_X) || !defined(NB_CYL_Y) || !defined(NB_CYL_Z) | !defined(NB_CYL) +#error "Macro definitions are missing" +#endif + +#include "test_senc3d_utils.h" + +#include <star/s3dut.h> +#include <rsys/double3.h> + +struct s3dut_context { + struct s3dut_mesh_data data; + struct context ctx; +}; + +static void +get_s3dut_indices(const unsigned itri, unsigned ids[3], void* context) +{ + struct s3dut_context* ctx = context; + unsigned s3dut_itri, cyl_idx, v_offset; + ASSERT(ids && ctx); + ASSERT(itri < NB_CYL * ctx->data.nprimitives); + /* Get cyl_idx along with the s3dut vertice index */ + s3dut_itri = itri % (unsigned)ctx->data.nprimitives; + cyl_idx = itri / (unsigned)ctx->data.nprimitives; + ASSERT(ctx->data.indices[s3dut_itri * 3 + 0] <= UINT_MAX + && ctx->data.indices[s3dut_itri * 3 + 1] <= UINT_MAX + && ctx->data.indices[s3dut_itri * 3 + 2] <= UINT_MAX); + /* Compute the vertex index in the user numbering + * from cyl_idx and s3dut data; vertex related getters + * will have to get the s3dut index back */ + v_offset = cyl_idx * (unsigned)ctx->data.nvertices; + ids[0] = v_offset + (unsigned)ctx->data.indices[s3dut_itri * 3 + 0]; + ids[ctx->ctx.reverse_vrtx ? 2 : 1] + = v_offset + (unsigned)ctx->data.indices[s3dut_itri * 3 + 1]; + ids[ctx->ctx.reverse_vrtx ? 1 : 2] + = v_offset + (unsigned)ctx->data.indices[s3dut_itri * 3 + 2]; +} + +static void +get_s3dut_position(const unsigned ivert, double pos[3], void* context) +{ + struct s3dut_context* ctx = context; + unsigned s3dut_ivert, cyl_idx; + int i, j, k; + double offset[3], tmp[3]; + double center_x, center_y, scale, misalignment = 0; + ASSERT(pos && ctx); + ASSERT(ivert < NB_CYL * ctx->data.nvertices); + /* Get cyl_idx and cylinder imbrication along with the s3dut vertice index */ + s3dut_ivert = ivert % (unsigned)ctx->data.nvertices; + cyl_idx = ivert / (unsigned)ctx->data.nvertices; + /* k th cylinder of the imbrication at grid position i,j */ + i = (int)cyl_idx / (NB_CYL_Y * NB_CYL_Z); + j = (cyl_idx / NB_CYL_Z) % NB_CYL_Y; + k = cyl_idx % NB_CYL_Z; + ASSERT(i < NB_CYL_X && j < NB_CYL_Y && k < NB_CYL_Z); + ASSERT((unsigned)(i * NB_CYL_Y * NB_CYL_Z + j * NB_CYL_Z + k) + * ctx->data.nvertices + s3dut_ivert == ivert); + center_x = 2 * (1 + NB_CYL_Z) * (i - NB_CYL_X / 2); + center_y = 2 * (1 + NB_CYL_Z) * (j - NB_CYL_Y / 2); + /* Compute scale and offset from imbrication */ + scale = k + 1; +#ifdef MITIGATE_EMBREE_181 + /* Mitigate Embree issue #181 + * We cannot keep perfect alignment of cylinders + * or some hits are missed */ + misalignment = (k % 2) ? -0.01 : +0.01; +#endif + d3(offset, center_x + misalignment, center_y + misalignment, 0); + d3_add(pos, d3_muld(tmp, ctx->data.positions + s3dut_ivert * 3, scale), + offset); +} + +static void +get_s3dut_media(const unsigned itri, unsigned medium[2], void* context) +{ + struct s3dut_context* ctx = context; + unsigned cyl_idx; + int k; + ASSERT(medium && ctx); + ASSERT(itri < NB_CYL * ctx->data.nprimitives); + /* Get cyl_idx */ + cyl_idx = itri / (unsigned)ctx->data.nprimitives; + /* k th cylinder of the imbrication at some grid position */ + k = cyl_idx % NB_CYL_Z; + medium[ctx->ctx.reverse_med ? SENC3D_BACK : SENC3D_FRONT] = (unsigned)k; + medium[ctx->ctx.reverse_med ? SENC3D_FRONT : SENC3D_BACK] = (unsigned)(k + 1); +} +#endif /* TEST_UTILS2_H */ diff --git a/src/test_senc_cube_behind_cube.c b/src/test_senc_cube_behind_cube.c @@ -1,311 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test has been created using the sg3_geometry_dump_as_C_code feature - * of star-geometry. It uses output from test_sg3_cube_behind_cube. */ - -#include "senc.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -/* Dump of star-geometry 'cube_behind_cube_2'. */ -static const unsigned cube_behind_cube_2_vertices_count = 16; -static const double cube_behind_cube_2_vertices[48] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1, - -1.5, -2, 20, - 3, -2, 20, - -2, 3, 20, - 3, 3, 20, - -2, -2, 25.5, - 3, -2, 25, - -2, 3, 25, - 3, 3.5, 25 -}; -static const unsigned cube_behind_cube_2_triangles_count = 24; -static const unsigned cube_behind_cube_2_triangles[72] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5, - 8, 10, 9, - 9, 10, 11, - 8, 12, 10, - 10, 12, 14, - 12, 13, 14, - 14, 13, 15, - 11, 15, 9, - 9, 15, 13, - 10, 14, 11, - 11, 14, 15, - 8, 9, 12, - 12, 9, 13 -}; -static const unsigned cube_behind_cube_2_properties[72] = -{ - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0 -}; -/* Dump of star-geometry 'cube_behind_cube_3'. */ -static const unsigned cube_behind_cube_3_vertices_count = 24; -static const double cube_behind_cube_3_vertices[72] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1, - -1.5, -2, 20, - 3, -2, 20, - -2, 3, 20, - 3, 3, 20, - -2, -2, 25.5, - 3, -2, 25, - -2, 3, 25, - 3, 3.5, 25, - -2.3, -3, 30, - 4, -3, 30, - -3, 4, 30, - 4, 4, 30, - -3, -3, 37.7, - 4, -3, 37, - -3, 4, 37, - 4, 4.7, 37 -}; -static const unsigned cube_behind_cube_3_triangles_count = 36; -static const unsigned cube_behind_cube_3_triangles[108] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5, - 8, 10, 9, - 9, 10, 11, - 8, 12, 10, - 10, 12, 14, - 12, 13, 14, - 14, 13, 15, - 11, 15, 9, - 9, 15, 13, - 10, 14, 11, - 11, 14, 15, - 8, 9, 12, - 12, 9, 13, - 16, 18, 17, - 17, 18, 19, - 16, 20, 18, - 18, 20, 22, - 20, 21, 22, - 22, 21, 23, - 19, 23, 17, - 17, 23, 21, - 18, 22, 19, - 19, 22, 23, - 16, 17, 20, - 20, 17, 21 -}; -static const unsigned cube_behind_cube_3_properties[108] = -{ - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0 -}; - -/* - cube_2 cube_3 - - +-----------------------+ - | 3 - | | - m1 | m0 | - | | - | | - | | - | |--> N - | | - | | - +-----------------------+ - +------------+ +------------+ - | 2 | 2 - m0 | m1 | m0 | m1 | - | | | | - | |--> N | |--> N - | | | | - +------------+ +------------+ - +-----+ +-----+ - m0 | m1 1 m0 | m1 1 - | |--> N | |--> N - +-----+ +-----+ - */ - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct context ctx = CONTEXT_NULL__; - unsigned i, ecount, maxm; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* Create a scene with the first and second cubes. - * Both cubes have medium 1 inside and medium 0 outside, - * the second cube is +Z from the first cube and is big enough - * to prevent rays from the first cube to miss it. */ - ctx.positions = cube_behind_cube_2_vertices; - ctx.indices = cube_behind_cube_2_triangles; - ctx.properties = cube_behind_cube_2_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - cube_behind_cube_2_triangles_count, get_indices, get_media_from_properties, - cube_behind_cube_2_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 3); - - FOR_EACH(i, 0, ecount) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - OK(senc_scene_get_enclosure(scn, i, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - ASSERT(header.enclosed_media_count == 1); - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_get_max_medium(scn, &maxm)); - CHK(maxm == 1); - OK(senc_scene_ref_put(scn)); - - /* Create a scene with the 3 cubes, same 2 first cubes as above - * The third cube has medium 0 inside and medium 1 outside and is further - * in +Z and bigger */ - ctx.positions = cube_behind_cube_3_vertices; - ctx.indices = cube_behind_cube_3_triangles; - ctx.properties = cube_behind_cube_3_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - cube_behind_cube_3_triangles_count, get_indices, get_media_from_properties, - cube_behind_cube_3_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 4); - - FOR_EACH(i, 0, ecount) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - OK(senc_scene_get_enclosure(scn, i, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - /* Inside enclosures contain 1 single media */ - ASSERT(header.enclosed_media_count == (header.is_infinite ? 2u : 1u)); - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_get_max_medium(scn, &maxm)); - CHK(maxm == 1); - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_cube_in_cube.c b/src/test_senc_cube_in_cube.c @@ -1,314 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test has been created using the sg3_geometry_dump_as_C_code feature - * of star-geometry. It uses output from test_sg3_cube_in_cube. */ - -#include "senc.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -/* - cube_2 cube_3 - - +-------------------------+ - | B - +-------------+ | +-------------+ | - m1 | m0 M m1 | m1 | m0 M | - | +------+ | | m0 | +------+ | | - | | m1 S | | | | m1 S | | - | | N <--| | | | | N <--| | | - | +------+ | | | +------+ | | - | N <--| | | N <--| | - +-------------+ | +-------------+ | - | N <--| - +-------------------------+ - */ - - -/* Dump of star-geometry 'cube_in_cube_2'. */ -static const unsigned cube_in_cube_2_vertices_count = 16; -static const double cube_in_cube_2_vertices[48] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1, - -0.7, -1, -1, - 2, -1, -1, - -1, 2, -1, - 2, 2, -1, - -1, -1, 2.3, - 2, -1, 2, - -1, 2, 2, - 2, 2.3, 2 -}; -static const unsigned cube_in_cube_2_triangles_count = 24; -static const unsigned cube_in_cube_2_triangles[72] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5, - 8, 9, 10, - 9, 11, 10, - 8, 10, 12, - 10, 14, 12, - 12, 14, 13, - 14, 15, 13, - 11, 9, 15, - 9, 13, 15, - 10, 11, 14, - 11, 15, 14, - 8, 12, 9, - 12, 13, 9 -}; -static const unsigned cube_in_cube_2_properties[72] = -{ - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0 -}; -/* Dump of star-geometry 'cube_in_cube_3'. */ -static const unsigned cube_in_cube_3_vertices_count = 24; -static const double cube_in_cube_3_vertices[72] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1, - -0.7, -1, -1, - 2, -1, -1, - -1, 2, -1, - 2, 2, -1, - -1, -1, 2.3, - 2, -1, 2, - -1, 2, 2, - 2, 2.3, 2, - -3, -4, -4, - 6, -4, -4, - -4, 6, -4, - 6, 6, -4, - -4, -4, 7, - 6, -4, 6, - -4, 6, 6, - 6, 7, 6 -}; -static const unsigned cube_in_cube_3_triangles_count = 36; -static const unsigned cube_in_cube_3_triangles[108] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5, - 8, 9, 10, - 9, 11, 10, - 8, 10, 12, - 10, 14, 12, - 12, 14, 13, - 14, 15, 13, - 11, 9, 15, - 9, 13, 15, - 10, 11, 14, - 11, 15, 14, - 8, 12, 9, - 12, 13, 9, - 16, 17, 18, - 17, 19, 18, - 16, 18, 20, - 18, 22, 20, - 20, 22, 21, - 22, 23, 21, - 19, 17, 23, - 17, 21, 23, - 18, 19, 22, - 19, 23, 22, - 16, 20, 17, - 20, 21, 17 -}; -static const unsigned cube_in_cube_3_properties[108] = -{ - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0 -}; - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct context ctx = CONTEXT_NULL__; - unsigned e, ecount, maxm, e2; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* Create a scene with the first and second cubes. - * The enclosure in the small contains medium 1, the external enclosure - * contains medium 1, the enclosure between the small and medium cubes - * contains medium 0. */ - ctx.positions = cube_in_cube_2_vertices; - ctx.indices = cube_in_cube_2_triangles; - ctx.properties = cube_in_cube_2_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - cube_in_cube_2_triangles_count, get_indices, get_media_from_properties, - cube_in_cube_2_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 3); - - FOR_EACH(e, 0, ecount) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - unsigned m; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - ASSERT(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &m)); - ASSERT(m <= 1); - ASSERT((m == 0) == (header.primitives_count == cube_in_cube_2_triangles_count)); - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_get_max_medium(scn, &maxm)); - CHK(maxm == 1); - OK(senc_scene_ref_put(scn)); - - /* Create a scene with the 3 cubes, same 2 first cubes as above. - * The enclosure in the small cube contains medium 1, the external enclosure - * contains medium 1, the enclosure between the small and medium cubes - * contains medium 0 and the enclosure between the medium and big cubes - * contains both media 0 and 1. */ - ctx.positions = cube_in_cube_3_vertices; - ctx.indices = cube_in_cube_3_triangles; - ctx.properties = cube_in_cube_3_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - cube_in_cube_3_triangles_count, get_indices, get_media_from_properties, - cube_in_cube_3_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 4); - - e2 = ecount; - FOR_EACH(e, 0, ecount) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - ASSERT(header.enclosed_media_count <= 2); - if(header.enclosed_media_count == 2) { - /* A single internal enclosure has 2 media */ - ASSERT(!header.is_infinite); - ASSERT(e2 == ecount); - e2 = e; - } - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_get_max_medium(scn, &maxm)); - CHK(maxm == 1); - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_cube_on_cube.c b/src/test_senc_cube_on_cube.c @@ -1,205 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test has been created using the sg3_geometry_dump_as_C_code feature - * of star-geometry. It uses output from test_sg3_cube_on_cube. */ - -#define _POSIX_C_SOURCE 200112L /* snprintf */ - -#include "senc.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -#include <stdio.h> - -/* - +-----------------------+ - | 3 - | +------+ | - m2 | m1 | m0 2 | - | | |--> N | - | +------+ | - | | m0 1 | - | | |--> N | - | +------+ | - |--> N | - +-----------------------+ - */ - -/* Dump of star-geometry 'cube_on_cube'. */ -static const unsigned cube_on_cube_vertices_count = 20; -static const double cube_on_cube_vertices[60] = -{ - 1, 1, 2, - 2, 1, 2, - 1, 2, 2, - 2, 2, 2, - 1, 1, 3, - 2, 1, 3, - 1, 2, 3, - 2, 2, 3, - 1, 1, 1, - 2, 1, 1, - 1, 2, 1, - 2, 2, 1, - 0.4, 0, 0, - 4, 0, 0, - 0, 4, 0, - 4, 4, 0, - 0, 0, 4.4, - 4, 0, 4, - 0, 4, 4, - 4, 4.4, 4 -}; -static const unsigned cube_on_cube_triangles_count = 34; -static const unsigned cube_on_cube_triangles[102] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5, - 8, 10, 9, - 9, 10, 11, - 8, 0, 10, - 10, 0, 2, - 11, 3, 9, - 9, 3, 1, - 10, 2, 11, - 11, 2, 3, - 8, 9, 0, - 0, 9, 1, - 12, 13, 14, - 13, 15, 14, - 12, 14, 16, - 14, 18, 16, - 16, 18, 17, - 18, 19, 17, - 15, 13, 19, - 13, 17, 19, - 14, 15, 18, - 15, 19, 18, - 12, 16, 13, - 16, 17, 13 -}; -static const unsigned cube_on_cube_properties[102] = -{ - 0, 0, 0, - 0, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0 -}; - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct context ctx = CONTEXT_NULL__; - unsigned count, e; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* Create a scene with the cubes. - * The enclosures in the small cubes contain medium 0, the external enclosure - * contains medium 2, the enclosure between the small and big cubes - * contains medium 1. */ - ctx.positions = cube_on_cube_vertices; - ctx.indices = cube_on_cube_triangles; - ctx.properties = cube_on_cube_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - cube_on_cube_triangles_count, get_indices, get_media_from_properties, - cube_on_cube_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 4); - - OK(senc_scene_get_vertices_count(scn, &count)); - CHK(count == cube_on_cube_vertices_count); - - OK(senc_scene_get_triangles_count(scn, &count)); - CHK(count == cube_on_cube_triangles_count); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 4); - FOR_EACH(e, 0, count) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - unsigned m; - char name[128]; (void)name; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - CHK(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &m)); - if(header.is_infinite) ASSERT(m == 2); /* External */ - else if(header.primitives_count == 12) ASSERT(m == 0); /* Internal */ - else ASSERT(m == 1); /* In between */ - OK(senc_enclosure_ref_put(enclosure)); -#ifdef DUMP_ENCLOSURES - snprintf(name, sizeof(name), "test_cube_on_cube_%u.obj", e); - dump_enclosure(scn, e, name); -#endif - } - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_device.c b/src/test_senc_device.c @@ -1,77 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "test_senc_utils.h" - -#include <rsys/logger.h> - -#include <stdio.h> - -static INLINE void -log_stream(const char* msg, void* ctx) -{ - ASSERT(msg); - (void)msg, (void)ctx; - printf("%s\n", msg); -} - -int -main(int argc, char** argv) -{ - struct logger logger; - struct mem_allocator allocator; - struct senc_device* dev; - (void)argc, (void)argv; - - BA(senc_device_create(NULL, NULL, 0, 0, NULL)); - BA(senc_device_create(NULL, NULL, 0, 0, &dev)); - OK(senc_device_create(NULL, NULL, 1, 0, &dev)); - BA(senc_device_ref_get(NULL)); - OK(senc_device_ref_get(dev)); - BA(senc_device_ref_put(NULL)); - OK(senc_device_ref_put(dev)); - OK(senc_device_ref_put(dev)); - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - - CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); - BA(senc_device_create(NULL, &allocator, 1, 0, NULL)); - OK(senc_device_create(NULL, &allocator, 1, 0, &dev)); - OK(senc_device_ref_put(dev)); - CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); - - OK(logger_init(&allocator, &logger)); - 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); - - BA(senc_device_create(&logger, NULL, 1, 0, NULL)); - OK(senc_device_create(&logger, NULL, 1, 0, &dev)); - OK(senc_device_ref_put(dev)); - - BA(senc_device_create(&logger, &allocator, 1, 0, NULL)); - OK(senc_device_create(&logger, &allocator, 1, 0, &dev)); - OK(senc_device_ref_put(dev)); - - OK(senc_device_create(&logger, &allocator, SENC_NTHREADS_DEFAULT, 0, &dev)); - OK(senc_device_ref_put(dev)); - - logger_release(&logger); - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_enclosure.c b/src/test_senc_enclosure.c @@ -1,248 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "senc_s3d_helper.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -#include <star/s3d.h> - -static void -test(const int convention) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct senc_enclosure* enclosures[2] = { NULL, NULL }; - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - struct s3d_device* s3d = NULL; - struct s3d_scene* s3d_scn = NULL; - struct s3d_shape* s3d_shp = NULL; - struct s3d_vertex_data s3d_attribs; - unsigned indices[2][3]; - unsigned medium; - unsigned gid; - enum senc_side side; - double vrtx[3]; - struct context ctx = CONTEXT_NULL__; - unsigned i, n, t, count; - int conv; - const int conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0; - const int conv_in = (convention & SENC_CONVENTION_NORMAL_INSIDE) != 0; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* A 3D cube. - * 2 enclosures (inside, outside) sharing the same triangles, - * but opposite sides */ - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.front_media = medium0; - ctx.back_media = medium1; - - OK(senc_scene_create(dev, convention, ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_convention(scn, &conv)); - CHK(conv == convention); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 2); - - OK(senc_scene_get_enclosure(scn, 0, &enclosure)); - BA(senc_enclosure_ref_get(NULL)); - OK(senc_enclosure_ref_get(enclosure)); - BA(senc_enclosure_ref_put(NULL)); - OK(senc_enclosure_ref_put(enclosure)); - - BA(senc_enclosure_get_triangle(NULL, 0, indices[0])); - BA(senc_enclosure_get_triangle(enclosure, ntriangles, indices[0])); - BA(senc_enclosure_get_triangle(enclosure, 0, NULL)); - BA(senc_enclosure_get_triangle(NULL, ntriangles, indices[0])); - BA(senc_enclosure_get_triangle(NULL, 0, NULL)); - BA(senc_enclosure_get_triangle(enclosure, ntriangles, NULL)); - BA(senc_enclosure_get_triangle(NULL, ntriangles, NULL)); - OK(senc_enclosure_get_triangle(enclosure, 0, indices[0])); - - BA(senc_enclosure_get_vertex(NULL, 0, vrtx)); - BA(senc_enclosure_get_vertex(enclosure, nvertices, vrtx)); - BA(senc_enclosure_get_vertex(enclosure, 0, NULL)); - BA(senc_enclosure_get_vertex(NULL, nvertices, vrtx)); - BA(senc_enclosure_get_vertex(NULL, 0, NULL)); - BA(senc_enclosure_get_vertex(enclosure, nvertices, NULL)); - BA(senc_enclosure_get_vertex(NULL, nvertices, NULL)); - OK(senc_enclosure_get_vertex(enclosure, 0, vrtx)); - - BA(senc_enclosure_get_triangle_id(NULL, 0, &gid, NULL)); - BA(senc_enclosure_get_triangle_id(enclosure, ntriangles, &gid, NULL)); - BA(senc_enclosure_get_triangle_id(enclosure, 0, NULL, NULL)); - BA(senc_enclosure_get_triangle_id(NULL, ntriangles, &gid, NULL)); - BA(senc_enclosure_get_triangle_id(NULL, 0, NULL, NULL)); - BA(senc_enclosure_get_triangle_id(enclosure, ntriangles, NULL, NULL)); - BA(senc_enclosure_get_triangle_id(NULL, ntriangles, NULL, NULL)); - BA(senc_enclosure_get_triangle_id(enclosure, 0, &gid, NULL)); - BA(senc_enclosure_get_triangle_id(NULL, 0, &gid, &side)); - BA(senc_enclosure_get_triangle_id(enclosure, ntriangles, &gid, &side)); - BA(senc_enclosure_get_triangle_id(enclosure, 0, NULL, &side)); - BA(senc_enclosure_get_triangle_id(NULL, ntriangles, &gid, &side)); - BA(senc_enclosure_get_triangle_id(NULL, 0, NULL, &side)); - BA(senc_enclosure_get_triangle_id(enclosure, ntriangles, NULL, &side)); - BA(senc_enclosure_get_triangle_id(NULL, ntriangles, NULL, &side)); - OK(senc_enclosure_get_triangle_id(enclosure, 0, &gid, &side)); - - BA(senc_enclosure_get_medium(NULL, 0, &medium)); - BA(senc_enclosure_get_medium(enclosure, 2, &medium)); - BA(senc_enclosure_get_medium(enclosure, 0, NULL)); - BA(senc_enclosure_get_medium(NULL, 2, &medium)); - BA(senc_enclosure_get_medium(NULL, 0, NULL)); - BA(senc_enclosure_get_medium(enclosure, 2, NULL)); - BA(senc_enclosure_get_medium(NULL, 2, NULL)); - OK(senc_enclosure_get_medium(enclosure, 0, &medium)); - - OK(senc_enclosure_ref_put(enclosure)); - - FOR_EACH(i, 0, count) { - OK(senc_scene_get_enclosure(scn, i, &enclosure)); - - BA(senc_enclosure_get_header(NULL, &header)); - BA(senc_enclosure_get_header(enclosure, NULL)); - BA(senc_enclosure_get_header(NULL, NULL)); - OK(senc_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input triangles: - * if convention is front, front medium (0) is outside, - * that is medium 0's enclosure is infinite */ - CHK(conv_front == ((medium == 0) == header.is_infinite)); - CHK(header.primitives_count == ntriangles); - CHK(header.unique_primitives_count == ntriangles); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - FOR_EACH(t, 0, header.primitives_count) { - OK(senc_enclosure_get_triangle_id(enclosure, t, &gid, &side)); - CHK(gid == t); - CHK(side == (medium == 0) ? SENC_FRONT : SENC_BACK); - } - - OK(senc_enclosure_ref_put(enclosure)); - } - - FOR_EACH(i, 0, 2) - OK(senc_scene_get_enclosure(scn, i, enclosures + i)); - FOR_EACH(n, 0, ntriangles) { - int same, reversed; - /* Read same triangles in both enclosures */ - FOR_EACH(i, 0, 2) - OK(senc_enclosure_get_triangle(enclosures[i], n, indices[i])); - /* Same triangles and opposite sides for the 2 enclosures */ - FOR_EACH(i, 0, 3) CHK(indices[0][i] == indices[1][2 - i]); - /* Enclosure 0 is outside (and contains medium 0 if convention is front). - * Geometrical normals in output data point in the same direction that those - * of input triangles for enclosure 0 iff convention is inside. - * The opposite holds for enclosure 1. */ - cmp_trg(n, enclosures[0], box_indices + 3 * n, box_vertices, &same, &reversed); - CHK((same && !reversed) == conv_in); - cmp_trg(n, enclosures[1], box_indices + 3 * n, box_vertices, &same, &reversed); - CHK(same && reversed == conv_in); - } - FOR_EACH(i, 0, 2) - OK(senc_enclosure_ref_put(enclosures[i])); - - OK(senc_scene_ref_put(scn)); - - /* Same 3D cube, but with a hole (incomplete). - * 1 single enclosure including both sides of triangles */ - - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.front_media = medium0; - ctx.back_media = medium1; - - OK(senc_scene_create(dev, convention, ntriangles - 1, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_frontier_segments_count(scn, &count)); - CHK(count == 3); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 1); - -#ifdef DUMP_ENCLOSURES - dump_enclosure(scn, 0, "test_enclosure_hole.obj"); -#endif - - OK(senc_scene_get_enclosure(scn, 0, &enclosure)); - - BA(senc_enclosure_get_header(NULL, &header)); - BA(senc_enclosure_get_header(enclosure, NULL)); - BA(senc_enclosure_get_header(NULL, NULL)); - OK(senc_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == 0); - CHK(header.enclosed_media_count == 2); - CHK(header.primitives_count == 2 * header.unique_primitives_count); - CHK(header.unique_primitives_count == ntriangles - 1); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == 1); - - FOR_EACH(t, 0, header.primitives_count) { - OK(senc_enclosure_get_triangle_id(enclosure, t, &gid, &side)); - /* The first unique_triangle_count triangles of an enclosure - * are unique triangles */ - if(t < header.unique_primitives_count) CHK(gid == t); - CHK(side == (t < header.unique_primitives_count) ? SENC_FRONT : SENC_BACK); - } - - /* Put geometry in a 3D view using helper functions */ - s3d_attribs.type = S3D_FLOAT3; - s3d_attribs.usage = S3D_POSITION; - s3d_attribs.get = senc_s3d_enclosure_get_position__; - OK(s3d_device_create(NULL, &allocator, 0, &s3d)); - OK(s3d_scene_create(s3d, &s3d_scn)); - OK(s3d_shape_create_mesh(s3d, &s3d_shp)); - OK(s3d_mesh_setup_indexed_vertices(s3d_shp, header.primitives_count, - senc_s3d_enclosure_get_indices__, header.vertices_count, &s3d_attribs, - 1, enclosure)); - OK(s3d_scene_attach_shape(s3d_scn, s3d_shp)); - S3D(shape_ref_put(s3d_shp)); - S3D(device_ref_put(s3d)); - S3D(scene_ref_put(s3d_scn)); - - SENC(scene_ref_put(scn)); - SENC(device_ref_put(dev)); - SENC(enclosure_ref_put(enclosure)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); -} - -int -main(int argc, char** argv) -{ - (void) argc, (void) argv; - test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE); - test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE); - test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_OUTSIDE); - test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_OUTSIDE); - return 0; -} diff --git a/src/test_senc_inconsistant_cube.c b/src/test_senc_inconsistant_cube.c @@ -1,145 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -/* The following array lists the indices toward the 3D vertices of each -* triangle. -* ,6---,7 ,6----7 -* ,' | ,'/| ,' | \ | Y Z -* 2----3' / | 2', | \ | | ,' -* |', | / ,5 | ',4---,5 0----X -* | ',|/,' | ,' | ,' -* 0----1' 0----1' -* Front, right Back, left and -* and Top faces bottom faces */ -/* Triangle #1 rotation order is not consistant with other triangles */ -static unsigned -inconsistant_box_indices[12/*#triangles*/ * 3/*#indices per triangle*/] = { - 0, 1, 2, 1, 2, 3, /* Front face */ - 0, 4, 2, 2, 4, 6, /* Left face*/ - 4, 5, 6, 6, 5, 7, /* Back face */ - 3, 7, 1, 1, 7, 5, /* Right face */ - 2, 6, 3, 3, 6, 7, /* Top face */ - 0, 1, 4, 4, 1, 5 /* Bottom face */ -}; -static const unsigned inconsistant_box_ntriangles -= sizeof(inconsistant_box_indices) / (3 * sizeof(*inconsistant_box_indices)); - -/* Media definitions reflect triangle #1 inconsistancy */ -static const unsigned -inconsistant_medium_front[12] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const unsigned -inconsistant_medium_back[12] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -static void -test(const int convention) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - int conv; - int conv_front, conv_in; - struct context ctx = CONTEXT_NULL__; - unsigned i, e, ecount; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* A 3D cube. - * 2 enclosures (inside, outside) sharing the same triangles, - * but opposite sides. - * What differs in this test is that triangle #0 vertices are given - * in the opposite rotation order. */ - ctx.positions = box_vertices; - ctx.indices = inconsistant_box_indices; - ctx.front_media = inconsistant_medium_front; - ctx.back_media = inconsistant_medium_back; - - OK(senc_scene_create(dev, convention, inconsistant_box_ntriangles, - get_indices, get_media, nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 2); - - OK(senc_scene_get_convention(scn, &conv)); - CHK(conv == convention); - conv_front = (conv & SENC_CONVENTION_NORMAL_FRONT) != 0; - conv_in = (conv & SENC_CONVENTION_NORMAL_INSIDE) != 0; - - FOR_EACH(e, 0, ecount) { - unsigned medium, expected_external_medium, expected_medium; - char name[128]; - enum senc_side side, expected_side; - unsigned gid; - (void)name; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - CHK(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &medium)); - /* If NORMAL_FRONT the external enclosure's medium should be 0, - * 1 if NORMAL_BACK */ - expected_external_medium = conv_front ? 0 : 1; - expected_medium = (header.is_infinite ? - expected_external_medium : !expected_external_medium); - CHK(medium == expected_medium); - -#ifdef DUMP_ENCLOSURES - sprintf(name, "test_inconsistant_cube_%s_%s_%u.obj", - conv_front ? "front" : "back", conv_in ? "in" : "out", e); - dump_enclosure(scn, e, name); -#endif - - FOR_EACH(i, 0, header.primitives_count) { - int same, reversed, fst_reversed; - fst_reversed = ((e == 0) == conv_in); - expected_side = (inconsistant_medium_front[i] == expected_medium) - ? SENC_FRONT : SENC_BACK; - cmp_trg(i, enclosure, - inconsistant_box_indices + (3 * i), box_vertices, - &same, &reversed); - /* Should be made of the same triangles */ - CHK(same); - CHK(i ? reversed != fst_reversed : reversed == fst_reversed); - OK(senc_enclosure_get_triangle_id(enclosure, i, &gid, &side)); - CHK(side == expected_side); - } - SENC(enclosure_ref_put(enclosure)); - } - - SENC(scene_ref_put(scn)); - SENC(device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); -} - -int main(int argc, char** argv) -{ - (void) argc, (void) argv; - - test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE); - test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE); - test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_OUTSIDE); - test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_OUTSIDE); - - return 0; -} diff --git a/src/test_senc_many_enclosures.c b/src/test_senc_many_enclosures.c @@ -1,108 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test is similar to test_senc_some_enclosures, but involves 64*64*64 - * cylinders instead of 4*4*4, thus making it impossible to define the geometry - * through static arrays. */ - -#define NB_CYL_X 32 -#define NB_CYL_Y 32 -#define NB_CYL_Z 64 - /* 64^3 = 262144 cylinders */ -#define NB_CYL (NB_CYL_X * NB_CYL_Y * NB_CYL_Z) - -#include "senc.h" -#include "test_senc_utils.h" -#include "test_senc_utils2.h" - -#include <star/s3dut.h> -#include <rsys/clock_time.h> -#include <rsys/double3.h> - -#include <stdio.h> -#include <limits.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct s3dut_mesh* cyl = NULL; - struct s3dut_context ctx = { {NULL,NULL,0,0}, CONTEXT_NULL__ }; - unsigned count; - unsigned cyl_trg_count, cyl_vrtx_count, e; - char dump[64]; - struct time t0, t1; - (void)argc, (void)argv; - - OK(mem_init_regular_allocator(&allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* A 20 triangles 12 vertices cylinder template */ - S3DUT(create_cylinder(&allocator, 1, 1, 3, 1, &cyl)); - S3DUT(mesh_get_data(cyl, &ctx.data)); - ASSERT(ctx.data.nprimitives < UINT_MAX); - ASSERT(ctx.data.nvertices < UINT_MAX); - cyl_trg_count = (unsigned)ctx.data.nprimitives; - cyl_vrtx_count = (unsigned)ctx.data.nvertices; - - /* Create the scene with N_CYL cylinders. - * There are NB_CYL_X * NB_CYL_Y imbrications of NB_CYL_Z cylinders each. - * Each imbrication is located on a grid. - * The get_s3du_xxx getters have to retrieve the cylinder from the - * primitive and vertice indexes. */ - time_current(&t0); - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - NB_CYL * cyl_trg_count, get_s3dut_indices, get_s3dut_media, - NB_CYL * cyl_vrtx_count, get_s3dut_position, &ctx, &scn)); - time_sub(&t0, time_current(&t1), &t0); - time_dump(&t0, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump)); - printf("Scene created in: %s\n", dump); - S3DUT(mesh_ref_put(cyl)); - - OK(senc_scene_get_vertices_count(scn, &count)); - CHK(count == NB_CYL * cyl_vrtx_count); - OK(senc_scene_get_triangles_count(scn, &count)); - CHK(count == NB_CYL * cyl_trg_count); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 1 + NB_CYL); - FOR_EACH(e, 0, count) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - unsigned m; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - CHK(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &m)); - CHK(header.primitives_count == - (header.is_infinite /* Outermost enclosure: NB_CYL_X*NB_CYL_Y cylinders */ - ? NB_CYL_X * NB_CYL_Y * cyl_trg_count - : (m == 0 - ? cyl_trg_count /* Innermost enclosures: 1 cylinder */ - : 2 * cyl_trg_count))); /* Other enclosures: 2 cylinders */ - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_regular_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_many_triangles.c b/src/test_senc_many_triangles.c @@ -1,101 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test is similar to test_senc_some_triangles, but involves 4*2562560 - * triangles instead of 4*1054, thus making it impossible to define the geometry - * through static arrays. */ - -#define NB_CYL_X 2 -#define NB_CYL_Y 1 -#define NB_CYL_Z 1 - /* 4 cylinders */ -#define NB_CYL (NB_CYL_X * NB_CYL_Y * NB_CYL_Z) - -#include "senc.h" -#include "test_senc_utils.h" -#include "test_senc_utils2.h" - -#include <star/s3dut.h> -#include <rsys/clock_time.h> -#include <rsys/double3.h> - -#include <stdio.h> -#include <limits.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct s3dut_mesh* cyl = NULL; - struct s3dut_context ctx = { {NULL,NULL,0,0}, CONTEXT_NULL__ }; - unsigned m0 = 0; - unsigned count; - unsigned cyl_trg_count, cyl_vrtx_count, e; - char dump[64]; - struct time t0, t1; - (void)argc, (void)argv; - - OK(mem_init_regular_allocator(&allocator)); - OK(senc_device_create (NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* A 2,562,560 triangles 1,281,282 vertices cylinder template */ - S3DUT(create_cylinder(&allocator, 1, 2, 1280, 1000, &cyl)); - S3DUT(mesh_get_data(cyl, &ctx.data)); - ASSERT(ctx.data.nprimitives < UINT_MAX); - ASSERT(ctx.data.nvertices < UINT_MAX); - cyl_trg_count = (unsigned)ctx.data.nprimitives; - cyl_vrtx_count = (unsigned)ctx.data.nvertices; - - /* Create the scene with 4 cylinders. - * The get_s3du_xxx getters have to retrieve the cylinder from the - * primitive and vertice indexes. */ - ctx.ctx.back_media = &m0; - time_current(&t0); - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - NB_CYL* cyl_trg_count, get_s3dut_indices, get_s3dut_media, - NB_CYL* cyl_vrtx_count, get_s3dut_position, &ctx, &scn)); - time_sub(&t0, time_current(&t1), &t0); - time_dump(&t0, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump)); - printf("Scene created in: %s\n", dump); - S3DUT(mesh_ref_put(cyl)); - - OK(senc_scene_get_vertices_count(scn, &count)); - CHK(count == NB_CYL * cyl_vrtx_count); - OK(senc_scene_get_triangles_count(scn, &count)); - CHK(count == NB_CYL * cyl_trg_count); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 1 + NB_CYL); - FOR_EACH(e, 0, count) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - CHK(header.primitives_count == - e ? cyl_trg_count : NB_CYL * cyl_trg_count); - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_regular_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_sample_enclosure.c b/src/test_senc_sample_enclosure.c @@ -1,124 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "senc_s3d_helper.h" -#include "test_senc_utils.h" - -#include <rsys/float3.h> -#include <rsys/double3.h> - -#include <star/s3d.h> -#include <star/ssp.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct senc_enclosure* enclosure = NULL; - struct senc_enclosure_header header; - struct s3d_device* s3d = NULL; - struct s3d_scene* s3d_scn = NULL; - struct s3d_scene_view* s3d_view = NULL; - struct s3d_shape* s3d_shp = NULL; - struct s3d_primitive prim; - struct s3d_vertex_data vrtx_get; - struct ssp_rng* rng; - struct context ctx = CONTEXT_NULL__; - int i; - float st[2]; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* A 3D cube, but with a hole (incomplete). - * 1 single enclosure including both sides of triangles */ - ctx.positions = cube_vertices; - ctx.indices = box_indices; - ctx.front_media = medium0; - ctx.back_media = medium0; - - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles - 1, get_indices, get_media, nvertices, get_position, &ctx, - &scn)); - - OK(senc_scene_get_enclosure(scn, 0, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - - /* Put enclosure in a 3D view... */ - vrtx_get.type = S3D_FLOAT3; - vrtx_get.usage = S3D_POSITION; - vrtx_get.get = senc_s3d_enclosure_get_position__; - S3D(device_create(NULL, &allocator, 0, &s3d)); - S3D(scene_create(s3d, &s3d_scn)); - S3D(shape_create_mesh(s3d, &s3d_shp)); - S3D(mesh_setup_indexed_vertices(s3d_shp, header.primitives_count, - senc_s3d_enclosure_get_indices__, header.vertices_count, &vrtx_get, 1, - enclosure)); - S3D(scene_attach_shape(s3d_scn, s3d_shp)); - S3D(scene_view_create(s3d_scn, S3D_SAMPLE, &s3d_view)); - - /* ... and sample it. */ - OK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng)); - FOR_EACH(i, 0, 10000) { - struct s3d_attrib attrib; - int n, c; - S3D(scene_view_sample(s3d_view, - ssp_rng_canonical_float(rng), - ssp_rng_canonical_float(rng), - ssp_rng_canonical_float(rng), - &prim, st)); - S3D(primitive_get_attrib(&prim, S3D_POSITION, st, &attrib)); - c = 0; - FOR_EACH(n, 0, 3) - if(eq_eps(attrib.value[n], 0, FLT_EPSILON) - || eq_eps(attrib.value[n], 1, FLT_EPSILON)) - c++; - CHK(c == 1); - S3D(primitive_get_attrib(&prim, S3D_GEOMETRY_NORMAL, st, &attrib)); - c = 0; - FOR_EACH(n, 0, 3) - if(eq_eps(attrib.value[n], -1, FLT_EPSILON) - || eq_eps(attrib.value[n], 1, FLT_EPSILON)) - c++; - CHK(c == 1); - c = 0; - FOR_EACH(n, 0, 3) - if(eq_eps(attrib.value[n], 0, FLT_EPSILON)) - c++; - CHK(c == 2); - } - - SENC(enclosure_ref_put(enclosure)); - SENC(scene_ref_put(scn)); - SENC(device_ref_put(dev)); - - SSP(rng_ref_put(rng)); - - S3D(shape_ref_put(s3d_shp)); - S3D(scene_view_ref_put(s3d_view)); - S3D(device_ref_put(s3d)); - S3D(scene_ref_put(s3d_scn)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - - return 0; -} diff --git a/src/test_senc_scene.c b/src/test_senc_scene.c @@ -1,296 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 "senc.h" -#include "test_senc_utils.h" - -#include <rsys/float3.h> -#include <rsys/double3.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct senc_enclosure* enc = NULL; - struct senc_enclosure_header header; - struct context ctx = CONTEXT_NULL__; - unsigned medfront[2], medback[2], ind[3], ids[2]; - double vrtx[3]; - unsigned count, i, maxm; - int convention; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* A 3D cube. - * With this geometry front is inside with NORMAL_BACK convention, - * outside with NORMAL_FRONT convention */ - ctx.positions = box_vertices; - ctx.indices = box_indices; - ctx.front_media = medium0; - ctx.back_media = medium1; - - BA(senc_scene_create(NULL, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - BA(senc_scene_create(dev, - 0, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - BA(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - 0, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - BA(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, NULL, get_media, - nvertices, get_position, &ctx, &scn)); - BA(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - 0, get_position, &ctx, &scn)); - BA(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, NULL, &ctx, &scn)); - BA(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, NULL)); - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - - BA(senc_scene_get_convention(NULL, &convention)); - BA(senc_scene_get_convention(scn, NULL)); - BA(senc_scene_get_convention(NULL, NULL)); - OK(senc_scene_get_convention(scn, &convention)); - CHK(convention - == (SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE)); - - BA(senc_scene_get_triangles_count(NULL, &count)); - BA(senc_scene_get_triangles_count(scn, NULL)); - BA(senc_scene_get_triangles_count(NULL, NULL)); - OK(senc_scene_get_triangles_count(scn, &count)); - CHK(count == ntriangles); - - BA(senc_scene_get_vertices_count(NULL, &count)); - BA(senc_scene_get_vertices_count(scn, NULL)); - BA(senc_scene_get_vertices_count(NULL, NULL)); - OK(senc_scene_get_vertices_count(scn, &count)); - CHK(count == nvertices); - - BA(senc_scene_get_triangle(NULL, 0, ind)); - BA(senc_scene_get_triangle(scn, UINT_MAX, ind)); - BA(senc_scene_get_triangle(scn, 0, NULL)); - BA(senc_scene_get_triangle(NULL, UINT_MAX, ind)); - BA(senc_scene_get_triangle(NULL, 0, NULL)); - BA(senc_scene_get_triangle(scn, UINT_MAX, NULL)); - BA(senc_scene_get_triangle(NULL, UINT_MAX, NULL)); - OK(senc_scene_get_triangle(scn, 0, ind)); - - BA(senc_scene_get_triangle_media(NULL, 0, ind)); - BA(senc_scene_get_triangle_media(scn, UINT_MAX, ind)); - BA(senc_scene_get_triangle_media(scn, 0, NULL)); - BA(senc_scene_get_triangle_media(NULL, UINT_MAX, ind)); - BA(senc_scene_get_triangle_media(NULL, 0, NULL)); - BA(senc_scene_get_triangle_media(scn, UINT_MAX, NULL)); - BA(senc_scene_get_triangle_media(NULL, UINT_MAX, NULL)); - OK(senc_scene_get_triangle_media(scn, 0, ind)); - - BA(senc_scene_get_vertex(NULL, 0, vrtx)); - BA(senc_scene_get_vertex(scn, UINT_MAX, vrtx)); - BA(senc_scene_get_vertex(scn, 0, NULL)); - BA(senc_scene_get_vertex(NULL, UINT_MAX, vrtx)); - BA(senc_scene_get_vertex(NULL, 0, NULL)); - BA(senc_scene_get_vertex(scn, UINT_MAX, NULL)); - BA(senc_scene_get_vertex(NULL, UINT_MAX, NULL)); - OK(senc_scene_get_vertex(scn, 0, vrtx)); - - BA(senc_scene_get_max_medium(NULL, &maxm)); - BA(senc_scene_get_max_medium(scn, NULL)); - BA(senc_scene_get_max_medium(NULL, NULL)); - OK(senc_scene_get_max_medium(scn, &maxm)); - CHK(maxm == 1); - - BA(senc_scene_get_enclosure_count(NULL, &count)); - BA(senc_scene_get_enclosure_count(scn, NULL)); - BA(senc_scene_get_enclosure_count(NULL, NULL)); - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 2); - - BA(senc_scene_get_enclosure_count_by_medium(NULL, 0, &count)); - BA(senc_scene_get_enclosure_count_by_medium(scn, 100, &count)); - BA(senc_scene_get_enclosure_count_by_medium(scn, 0, NULL)); - BA(senc_scene_get_enclosure_count_by_medium(NULL, 100, &count)); - BA(senc_scene_get_enclosure_count_by_medium(NULL, 0, NULL)); - BA(senc_scene_get_enclosure_count_by_medium(scn, 100, NULL)); - BA(senc_scene_get_enclosure_count_by_medium(NULL, 100, NULL)); - OK(senc_scene_get_enclosure_count_by_medium(scn, 0, &count)); - CHK(count == 1); - OK(senc_scene_get_enclosure_count_by_medium(scn, SENC_UNSPECIFIED_MEDIUM, - &count)); - CHK(count == 0); - - BA(senc_scene_get_enclosure(NULL, 0, &enc)); - BA(senc_scene_get_enclosure(scn, UINT_MAX, &enc)); - BA(senc_scene_get_enclosure(scn, 0, NULL)); - BA(senc_scene_get_enclosure(NULL, UINT_MAX, &enc)); - BA(senc_scene_get_enclosure(NULL, 0, NULL)); - BA(senc_scene_get_enclosure(scn, UINT_MAX, NULL)); - BA(senc_scene_get_enclosure(NULL, UINT_MAX, NULL)); - OK(senc_scene_get_enclosure(scn, 0, &enc)); - OK(senc_enclosure_ref_put(enc)); - - BA(senc_scene_get_enclosure_by_medium(NULL, 0, 0, &enc)); - BA(senc_scene_get_enclosure_by_medium(scn, 100, 0, &enc)); - BA(senc_scene_get_enclosure_by_medium(scn, 0, UINT_MAX, &enc)); - BA(senc_scene_get_enclosure_by_medium(scn, 0, 0, NULL)); - BA(senc_scene_get_enclosure_by_medium(NULL, 100, 0, &enc)); - BA(senc_scene_get_enclosure_by_medium(NULL, 0, UINT_MAX, &enc)); - BA(senc_scene_get_enclosure_by_medium(NULL, 0, 0, NULL)); - BA(senc_scene_get_enclosure_by_medium(scn, 100, UINT_MAX, &enc)); - BA(senc_scene_get_enclosure_by_medium(scn, 100, 0, NULL)); - BA(senc_scene_get_enclosure_by_medium(scn, 0, UINT_MAX, NULL)); - BA(senc_scene_get_enclosure_by_medium(scn, 100, UINT_MAX, NULL)); - BA(senc_scene_get_enclosure_by_medium(NULL, 0, UINT_MAX, NULL)); - BA(senc_scene_get_enclosure_by_medium(NULL, 100, 0, NULL)); - BA(senc_scene_get_enclosure_by_medium(NULL, 100, UINT_MAX, &enc)); - BA(senc_scene_get_enclosure_by_medium(NULL, 100, UINT_MAX, NULL)); - OK(senc_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); - OK(senc_enclosure_ref_put(enc)); - /* Index 0 is out of range for SENC_UNSPECIFIED_MEDIUM. */ - BA(senc_scene_get_enclosure_by_medium(scn, SENC_UNSPECIFIED_MEDIUM, 0, &enc)); - - BA(senc_scene_get_triangle_enclosures(NULL, 0, ids)); - BA(senc_scene_get_triangle_enclosures(scn, UINT_MAX, ids)); - BA(senc_scene_get_triangle_enclosures(scn, 0, NULL)); - BA(senc_scene_get_triangle_enclosures(NULL, UINT_MAX, ids)); - BA(senc_scene_get_triangle_enclosures(NULL, 0, NULL)); - BA(senc_scene_get_triangle_enclosures(scn, UINT_MAX, NULL)); - BA(senc_scene_get_triangle_enclosures(NULL, UINT_MAX, NULL)); - OK(senc_scene_get_triangle_enclosures(scn, 0, ids)); - - BA(senc_scene_get_frontier_segments_count(NULL, &count)); - BA(senc_scene_get_frontier_segments_count(scn, NULL)); - BA(senc_scene_get_frontier_segments_count(NULL, NULL)); - OK(senc_scene_get_frontier_segments_count(scn, &count)); - CHK(count == 0); - - BA(senc_scene_get_frontier_segment(NULL, 0, ids)); - BA(senc_scene_get_frontier_segment(scn, UINT_MAX, ids)); - BA(senc_scene_get_frontier_segment(scn, 0, NULL)); - BA(senc_scene_get_frontier_segment(NULL, UINT_MAX, ids)); - BA(senc_scene_get_frontier_segment(NULL, 0, NULL)); - BA(senc_scene_get_frontier_segment(scn, UINT_MAX, NULL)); - BA(senc_scene_get_frontier_segment(NULL, UINT_MAX, NULL)); - - BA(senc_scene_ref_get(NULL)); - OK(senc_scene_ref_get(scn)); - BA(senc_scene_ref_put(NULL)); - OK(senc_scene_ref_put(scn)); - - OK(senc_scene_ref_put(scn)); - - /* Same geometry with SENC_UNSPECIFIED_MEDIUM */ - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, NULL, - nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_by_medium(scn, SENC_UNSPECIFIED_MEDIUM, 0, &enc)); - OK(senc_enclosure_ref_put(enc)); - BA(senc_scene_get_enclosure_by_medium(scn, SENC_UNSPECIFIED_MEDIUM, 100, &enc)); - - OK(senc_scene_ref_put(scn)); - - /* Same geometry with a hole (1 missing triangle) */ - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles - 1, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_frontier_segments_count(scn, &count)); - CHK(count == 3); - OK(senc_scene_get_frontier_segment(scn, 0, ids)); - BA(senc_scene_get_frontier_segment(scn, 3, ids)); - - OK(senc_scene_ref_put(scn)); - - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_convention(scn, &convention)); - CHK(convention - == (SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE)); - /* Check that medium 0 is inside */ - OK(senc_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); - OK(senc_enclosure_get_header(enc, &header)); - CHK(!header.is_infinite); - OK(senc_enclosure_ref_put(enc)); - - OK(senc_scene_get_triangle_media(scn, 0, medback)); - OK(senc_scene_ref_put(scn)); - - /* Medium mismatch between neighbour segments, but OK */ - ctx.front_media = medium1_3; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - - OK(senc_scene_get_max_medium(scn, &maxm)); - CHK(maxm == 3); - OK(senc_scene_get_enclosure_count_by_medium(scn, 0, &count)); - CHK(count == 0); /* Medium 0 unused */ - OK(senc_scene_get_enclosure_count_by_medium(scn, 1, &count)); - CHK(count == 2); /* Medium 1 used twice */ - OK(senc_scene_get_enclosure_count_by_medium(scn, 2, &count)); - CHK(count == 0); /* Medium 2 unused */ - OK(senc_scene_get_enclosure_count_by_medium(scn, 3, &count)); - CHK(count == 1); /* Medium 3 used */ - - OK(senc_scene_ref_put(scn)); - - ctx.front_media = medium0; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - ntriangles, get_indices, get_media, - nvertices, get_position, &ctx, &scn)); - /* Check that medium 0 is outside */ - OK(senc_scene_get_enclosure_by_medium(scn, 0, 0, &enc)); - OK(senc_enclosure_get_header(enc, &header)); - CHK(header.is_infinite); - OK(senc_enclosure_ref_put(enc)); - - OK(senc_scene_get_triangle_media(scn, 0, medfront)); - FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]); - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - - return 0; -} diff --git a/src/test_senc_some_enclosures.c b/src/test_senc_some_enclosures.c @@ -1,3427 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test has been created using the sg3_geometry_dump_as_C_code feature - * of star-geometry. It uses output from test_sg3_some_enclosures. - * This test is similar to test_senc_many_enclosures that creates a huge - * geometry by program. */ - -#include "senc.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -/* Dump of star-geometry 'some_enclosures'. */ -static const unsigned some_enclosures_vertices_count = 768; -static const double some_enclosures_vertices[2304] = -{ - -19, -20, -0.5, - -19, -20, 0.5, - -19.691, -19.0489, -0.5, - -19.691, -19.0489, 0.5, - -20.809, -19.4122, -0.5, - -20.809, -19.4122, 0.5, - -20.809, -20.5878, -0.5, - -20.809, -20.5878, 0.5, - -19.691, -20.9511, -0.5, - -19.691, -20.9511, 0.5, - -20, -20, -0.5, - -20, -20, 0.5, - -18, -20, -1, - -18, -20, 1, - -19.382, -18.0979, -1, - -19.382, -18.0979, 1, - -21.618, -18.8244, -1, - -21.618, -18.8244, 1, - -21.618, -21.1756, -1, - -21.618, -21.1756, 1, - -19.382, -21.9021, -1, - -19.382, -21.9021, 1, - -20, -20, -1, - -20, -20, 1, - -17, -20, -1.5, - -17, -20, 1.5, - -19.0729, -17.1468, -1.5, - -19.0729, -17.1468, 1.5, - -22.4271, -18.2366, -1.5, - -22.4271, -18.2366, 1.5, - -22.4271, -21.7634, -1.5, - -22.4271, -21.7634, 1.5, - -19.0729, -22.8532, -1.5, - -19.0729, -22.8532, 1.5, - -20, -20, -1.5, - -20, -20, 1.5, - -16, -20, -2, - -16, -20, 2, - -18.7639, -16.1958, -2, - -18.7639, -16.1958, 2, - -23.2361, -17.6489, -2, - -23.2361, -17.6489, 2, - -23.2361, -22.3511, -2, - -23.2361, -22.3511, 2, - -18.7639, -23.8042, -2, - -18.7639, -23.8042, 2, - -20, -20, -2, - -20, -20, 2, - -19, -10, -0.5, - -19, -10, 0.5, - -19.691, -9.04894, -0.5, - -19.691, -9.04894, 0.5, - -20.809, -9.41221, -0.5, - -20.809, -9.41221, 0.5, - -20.809, -10.5878, -0.5, - -20.809, -10.5878, 0.5, - -19.691, -10.9511, -0.5, - -19.691, -10.9511, 0.5, - -20, -10, -0.5, - -20, -10, 0.5, - -18, -10, -1, - -18, -10, 1, - -19.382, -8.09789, -1, - -19.382, -8.09789, 1, - -21.618, -8.82443, -1, - -21.618, -8.82443, 1, - -21.618, -11.1756, -1, - -21.618, -11.1756, 1, - -19.382, -11.9021, -1, - -19.382, -11.9021, 1, - -20, -10, -1, - -20, -10, 1, - -17, -10, -1.5, - -17, -10, 1.5, - -19.0729, -7.14683, -1.5, - -19.0729, -7.14683, 1.5, - -22.4271, -8.23664, -1.5, - -22.4271, -8.23664, 1.5, - -22.4271, -11.7634, -1.5, - -22.4271, -11.7634, 1.5, - -19.0729, -12.8532, -1.5, - -19.0729, -12.8532, 1.5, - -20, -10, -1.5, - -20, -10, 1.5, - -16, -10, -2, - -16, -10, 2, - -18.7639, -6.19577, -2, - -18.7639, -6.19577, 2, - -23.2361, -7.64886, -2, - -23.2361, -7.64886, 2, - -23.2361, -12.3511, -2, - -23.2361, -12.3511, 2, - -18.7639, -13.8042, -2, - -18.7639, -13.8042, 2, - -20, -10, -2, - -20, -10, 2, - -19, 0, -0.5, - -19, 0, 0.5, - -19.691, 0.951057, -0.5, - -19.691, 0.951057, 0.5, - -20.809, 0.587785, -0.5, - -20.809, 0.587785, 0.5, - -20.809, -0.587785, -0.5, - -20.809, -0.587785, 0.5, - -19.691, -0.951057, -0.5, - -19.691, -0.951057, 0.5, - -20, 0, -0.5, - -20, 0, 0.5, - -18, 0, -1, - -18, 0, 1, - -19.382, 1.90211, -1, - -19.382, 1.90211, 1, - -21.618, 1.17557, -1, - -21.618, 1.17557, 1, - -21.618, -1.17557, -1, - -21.618, -1.17557, 1, - -19.382, -1.90211, -1, - -19.382, -1.90211, 1, - -20, 0, -1, - -20, 0, 1, - -17, 0, -1.5, - -17, 0, 1.5, - -19.0729, 2.85317, -1.5, - -19.0729, 2.85317, 1.5, - -22.4271, 1.76336, -1.5, - -22.4271, 1.76336, 1.5, - -22.4271, -1.76336, -1.5, - -22.4271, -1.76336, 1.5, - -19.0729, -2.85317, -1.5, - -19.0729, -2.85317, 1.5, - -20, 0, -1.5, - -20, 0, 1.5, - -16, 0, -2, - -16, 0, 2, - -18.7639, 3.80423, -2, - -18.7639, 3.80423, 2, - -23.2361, 2.35114, -2, - -23.2361, 2.35114, 2, - -23.2361, -2.35114, -2, - -23.2361, -2.35114, 2, - -18.7639, -3.80423, -2, - -18.7639, -3.80423, 2, - -20, 0, -2, - -20, 0, 2, - -19, 10, -0.5, - -19, 10, 0.5, - -19.691, 10.9511, -0.5, - -19.691, 10.9511, 0.5, - -20.809, 10.5878, -0.5, - -20.809, 10.5878, 0.5, - -20.809, 9.41221, -0.5, - -20.809, 9.41221, 0.5, - -19.691, 9.04894, -0.5, - -19.691, 9.04894, 0.5, - -20, 10, -0.5, - -20, 10, 0.5, - -18, 10, -1, - -18, 10, 1, - -19.382, 11.9021, -1, - -19.382, 11.9021, 1, - -21.618, 11.1756, -1, - -21.618, 11.1756, 1, - -21.618, 8.82443, -1, - -21.618, 8.82443, 1, - -19.382, 8.09789, -1, - -19.382, 8.09789, 1, - -20, 10, -1, - -20, 10, 1, - -17, 10, -1.5, - -17, 10, 1.5, - -19.0729, 12.8532, -1.5, - -19.0729, 12.8532, 1.5, - -22.4271, 11.7634, -1.5, - -22.4271, 11.7634, 1.5, - -22.4271, 8.23664, -1.5, - -22.4271, 8.23664, 1.5, - -19.0729, 7.14683, -1.5, - -19.0729, 7.14683, 1.5, - -20, 10, -1.5, - -20, 10, 1.5, - -16, 10, -2, - -16, 10, 2, - -18.7639, 13.8042, -2, - -18.7639, 13.8042, 2, - -23.2361, 12.3511, -2, - -23.2361, 12.3511, 2, - -23.2361, 7.64886, -2, - -23.2361, 7.64886, 2, - -18.7639, 6.19577, -2, - -18.7639, 6.19577, 2, - -20, 10, -2, - -20, 10, 2, - -9, -20, -0.5, - -9, -20, 0.5, - -9.69098, -19.0489, -0.5, - -9.69098, -19.0489, 0.5, - -10.809, -19.4122, -0.5, - -10.809, -19.4122, 0.5, - -10.809, -20.5878, -0.5, - -10.809, -20.5878, 0.5, - -9.69098, -20.9511, -0.5, - -9.69098, -20.9511, 0.5, - -10, -20, -0.5, - -10, -20, 0.5, - -8, -20, -1, - -8, -20, 1, - -9.38197, -18.0979, -1, - -9.38197, -18.0979, 1, - -11.618, -18.8244, -1, - -11.618, -18.8244, 1, - -11.618, -21.1756, -1, - -11.618, -21.1756, 1, - -9.38197, -21.9021, -1, - -9.38197, -21.9021, 1, - -10, -20, -1, - -10, -20, 1, - -7, -20, -1.5, - -7, -20, 1.5, - -9.07295, -17.1468, -1.5, - -9.07295, -17.1468, 1.5, - -12.4271, -18.2366, -1.5, - -12.4271, -18.2366, 1.5, - -12.4271, -21.7634, -1.5, - -12.4271, -21.7634, 1.5, - -9.07295, -22.8532, -1.5, - -9.07295, -22.8532, 1.5, - -10, -20, -1.5, - -10, -20, 1.5, - -6, -20, -2, - -6, -20, 2, - -8.76393, -16.1958, -2, - -8.76393, -16.1958, 2, - -13.2361, -17.6489, -2, - -13.2361, -17.6489, 2, - -13.2361, -22.3511, -2, - -13.2361, -22.3511, 2, - -8.76393, -23.8042, -2, - -8.76393, -23.8042, 2, - -10, -20, -2, - -10, -20, 2, - -9, -10, -0.5, - -9, -10, 0.5, - -9.69098, -9.04894, -0.5, - -9.69098, -9.04894, 0.5, - -10.809, -9.41221, -0.5, - -10.809, -9.41221, 0.5, - -10.809, -10.5878, -0.5, - -10.809, -10.5878, 0.5, - -9.69098, -10.9511, -0.5, - -9.69098, -10.9511, 0.5, - -10, -10, -0.5, - -10, -10, 0.5, - -8, -10, -1, - -8, -10, 1, - -9.38197, -8.09789, -1, - -9.38197, -8.09789, 1, - -11.618, -8.82443, -1, - -11.618, -8.82443, 1, - -11.618, -11.1756, -1, - -11.618, -11.1756, 1, - -9.38197, -11.9021, -1, - -9.38197, -11.9021, 1, - -10, -10, -1, - -10, -10, 1, - -7, -10, -1.5, - -7, -10, 1.5, - -9.07295, -7.14683, -1.5, - -9.07295, -7.14683, 1.5, - -12.4271, -8.23664, -1.5, - -12.4271, -8.23664, 1.5, - -12.4271, -11.7634, -1.5, - -12.4271, -11.7634, 1.5, - -9.07295, -12.8532, -1.5, - -9.07295, -12.8532, 1.5, - -10, -10, -1.5, - -10, -10, 1.5, - -6, -10, -2, - -6, -10, 2, - -8.76393, -6.19577, -2, - -8.76393, -6.19577, 2, - -13.2361, -7.64886, -2, - -13.2361, -7.64886, 2, - -13.2361, -12.3511, -2, - -13.2361, -12.3511, 2, - -8.76393, -13.8042, -2, - -8.76393, -13.8042, 2, - -10, -10, -2, - -10, -10, 2, - -9, 0, -0.5, - -9, 0, 0.5, - -9.69098, 0.951057, -0.5, - -9.69098, 0.951057, 0.5, - -10.809, 0.587785, -0.5, - -10.809, 0.587785, 0.5, - -10.809, -0.587785, -0.5, - -10.809, -0.587785, 0.5, - -9.69098, -0.951057, -0.5, - -9.69098, -0.951057, 0.5, - -10, 0, -0.5, - -10, 0, 0.5, - -8, 0, -1, - -8, 0, 1, - -9.38197, 1.90211, -1, - -9.38197, 1.90211, 1, - -11.618, 1.17557, -1, - -11.618, 1.17557, 1, - -11.618, -1.17557, -1, - -11.618, -1.17557, 1, - -9.38197, -1.90211, -1, - -9.38197, -1.90211, 1, - -10, 0, -1, - -10, 0, 1, - -7, 0, -1.5, - -7, 0, 1.5, - -9.07295, 2.85317, -1.5, - -9.07295, 2.85317, 1.5, - -12.4271, 1.76336, -1.5, - -12.4271, 1.76336, 1.5, - -12.4271, -1.76336, -1.5, - -12.4271, -1.76336, 1.5, - -9.07295, -2.85317, -1.5, - -9.07295, -2.85317, 1.5, - -10, 0, -1.5, - -10, 0, 1.5, - -6, 0, -2, - -6, 0, 2, - -8.76393, 3.80423, -2, - -8.76393, 3.80423, 2, - -13.2361, 2.35114, -2, - -13.2361, 2.35114, 2, - -13.2361, -2.35114, -2, - -13.2361, -2.35114, 2, - -8.76393, -3.80423, -2, - -8.76393, -3.80423, 2, - -10, 0, -2, - -10, 0, 2, - -9, 10, -0.5, - -9, 10, 0.5, - -9.69098, 10.9511, -0.5, - -9.69098, 10.9511, 0.5, - -10.809, 10.5878, -0.5, - -10.809, 10.5878, 0.5, - -10.809, 9.41221, -0.5, - -10.809, 9.41221, 0.5, - -9.69098, 9.04894, -0.5, - -9.69098, 9.04894, 0.5, - -10, 10, -0.5, - -10, 10, 0.5, - -8, 10, -1, - -8, 10, 1, - -9.38197, 11.9021, -1, - -9.38197, 11.9021, 1, - -11.618, 11.1756, -1, - -11.618, 11.1756, 1, - -11.618, 8.82443, -1, - -11.618, 8.82443, 1, - -9.38197, 8.09789, -1, - -9.38197, 8.09789, 1, - -10, 10, -1, - -10, 10, 1, - -7, 10, -1.5, - -7, 10, 1.5, - -9.07295, 12.8532, -1.5, - -9.07295, 12.8532, 1.5, - -12.4271, 11.7634, -1.5, - -12.4271, 11.7634, 1.5, - -12.4271, 8.23664, -1.5, - -12.4271, 8.23664, 1.5, - -9.07295, 7.14683, -1.5, - -9.07295, 7.14683, 1.5, - -10, 10, -1.5, - -10, 10, 1.5, - -6, 10, -2, - -6, 10, 2, - -8.76393, 13.8042, -2, - -8.76393, 13.8042, 2, - -13.2361, 12.3511, -2, - -13.2361, 12.3511, 2, - -13.2361, 7.64886, -2, - -13.2361, 7.64886, 2, - -8.76393, 6.19577, -2, - -8.76393, 6.19577, 2, - -10, 10, -2, - -10, 10, 2, - 1, -20, -0.5, - 1, -20, 0.5, - 0.309017, -19.0489, -0.5, - 0.309017, -19.0489, 0.5, - -0.809017, -19.4122, -0.5, - -0.809017, -19.4122, 0.5, - -0.809017, -20.5878, -0.5, - -0.809017, -20.5878, 0.5, - 0.309017, -20.9511, -0.5, - 0.309017, -20.9511, 0.5, - 0, -20, -0.5, - 0, -20, 0.5, - 2, -20, -1, - 2, -20, 1, - 0.618034, -18.0979, -1, - 0.618034, -18.0979, 1, - -1.61803, -18.8244, -1, - -1.61803, -18.8244, 1, - -1.61803, -21.1756, -1, - -1.61803, -21.1756, 1, - 0.618034, -21.9021, -1, - 0.618034, -21.9021, 1, - 0, -20, -1, - 0, -20, 1, - 3, -20, -1.5, - 3, -20, 1.5, - 0.927051, -17.1468, -1.5, - 0.927051, -17.1468, 1.5, - -2.42705, -18.2366, -1.5, - -2.42705, -18.2366, 1.5, - -2.42705, -21.7634, -1.5, - -2.42705, -21.7634, 1.5, - 0.927051, -22.8532, -1.5, - 0.927051, -22.8532, 1.5, - 0, -20, -1.5, - 0, -20, 1.5, - 4, -20, -2, - 4, -20, 2, - 1.23607, -16.1958, -2, - 1.23607, -16.1958, 2, - -3.23607, -17.6489, -2, - -3.23607, -17.6489, 2, - -3.23607, -22.3511, -2, - -3.23607, -22.3511, 2, - 1.23607, -23.8042, -2, - 1.23607, -23.8042, 2, - 0, -20, -2, - 0, -20, 2, - 1, -10, -0.5, - 1, -10, 0.5, - 0.309017, -9.04894, -0.5, - 0.309017, -9.04894, 0.5, - -0.809017, -9.41221, -0.5, - -0.809017, -9.41221, 0.5, - -0.809017, -10.5878, -0.5, - -0.809017, -10.5878, 0.5, - 0.309017, -10.9511, -0.5, - 0.309017, -10.9511, 0.5, - 0, -10, -0.5, - 0, -10, 0.5, - 2, -10, -1, - 2, -10, 1, - 0.618034, -8.09789, -1, - 0.618034, -8.09789, 1, - -1.61803, -8.82443, -1, - -1.61803, -8.82443, 1, - -1.61803, -11.1756, -1, - -1.61803, -11.1756, 1, - 0.618034, -11.9021, -1, - 0.618034, -11.9021, 1, - 0, -10, -1, - 0, -10, 1, - 3, -10, -1.5, - 3, -10, 1.5, - 0.927051, -7.14683, -1.5, - 0.927051, -7.14683, 1.5, - -2.42705, -8.23664, -1.5, - -2.42705, -8.23664, 1.5, - -2.42705, -11.7634, -1.5, - -2.42705, -11.7634, 1.5, - 0.927051, -12.8532, -1.5, - 0.927051, -12.8532, 1.5, - 0, -10, -1.5, - 0, -10, 1.5, - 4, -10, -2, - 4, -10, 2, - 1.23607, -6.19577, -2, - 1.23607, -6.19577, 2, - -3.23607, -7.64886, -2, - -3.23607, -7.64886, 2, - -3.23607, -12.3511, -2, - -3.23607, -12.3511, 2, - 1.23607, -13.8042, -2, - 1.23607, -13.8042, 2, - 0, -10, -2, - 0, -10, 2, - 1, 0, -0.5, - 1, 0, 0.5, - 0.309017, 0.951057, -0.5, - 0.309017, 0.951057, 0.5, - -0.809017, 0.587785, -0.5, - -0.809017, 0.587785, 0.5, - -0.809017, -0.587785, -0.5, - -0.809017, -0.587785, 0.5, - 0.309017, -0.951057, -0.5, - 0.309017, -0.951057, 0.5, - 0, 0, -0.5, - 0, 0, 0.5, - 2, 0, -1, - 2, 0, 1, - 0.618034, 1.90211, -1, - 0.618034, 1.90211, 1, - -1.61803, 1.17557, -1, - -1.61803, 1.17557, 1, - -1.61803, -1.17557, -1, - -1.61803, -1.17557, 1, - 0.618034, -1.90211, -1, - 0.618034, -1.90211, 1, - 0, 0, -1, - 0, 0, 1, - 3, 0, -1.5, - 3, 0, 1.5, - 0.927051, 2.85317, -1.5, - 0.927051, 2.85317, 1.5, - -2.42705, 1.76336, -1.5, - -2.42705, 1.76336, 1.5, - -2.42705, -1.76336, -1.5, - -2.42705, -1.76336, 1.5, - 0.927051, -2.85317, -1.5, - 0.927051, -2.85317, 1.5, - 0, 0, -1.5, - 0, 0, 1.5, - 4, 0, -2, - 4, 0, 2, - 1.23607, 3.80423, -2, - 1.23607, 3.80423, 2, - -3.23607, 2.35114, -2, - -3.23607, 2.35114, 2, - -3.23607, -2.35114, -2, - -3.23607, -2.35114, 2, - 1.23607, -3.80423, -2, - 1.23607, -3.80423, 2, - 0, 0, -2, - 0, 0, 2, - 1, 10, -0.5, - 1, 10, 0.5, - 0.309017, 10.9511, -0.5, - 0.309017, 10.9511, 0.5, - -0.809017, 10.5878, -0.5, - -0.809017, 10.5878, 0.5, - -0.809017, 9.41221, -0.5, - -0.809017, 9.41221, 0.5, - 0.309017, 9.04894, -0.5, - 0.309017, 9.04894, 0.5, - 0, 10, -0.5, - 0, 10, 0.5, - 2, 10, -1, - 2, 10, 1, - 0.618034, 11.9021, -1, - 0.618034, 11.9021, 1, - -1.61803, 11.1756, -1, - -1.61803, 11.1756, 1, - -1.61803, 8.82443, -1, - -1.61803, 8.82443, 1, - 0.618034, 8.09789, -1, - 0.618034, 8.09789, 1, - 0, 10, -1, - 0, 10, 1, - 3, 10, -1.5, - 3, 10, 1.5, - 0.927051, 12.8532, -1.5, - 0.927051, 12.8532, 1.5, - -2.42705, 11.7634, -1.5, - -2.42705, 11.7634, 1.5, - -2.42705, 8.23664, -1.5, - -2.42705, 8.23664, 1.5, - 0.927051, 7.14683, -1.5, - 0.927051, 7.14683, 1.5, - 0, 10, -1.5, - 0, 10, 1.5, - 4, 10, -2, - 4, 10, 2, - 1.23607, 13.8042, -2, - 1.23607, 13.8042, 2, - -3.23607, 12.3511, -2, - -3.23607, 12.3511, 2, - -3.23607, 7.64886, -2, - -3.23607, 7.64886, 2, - 1.23607, 6.19577, -2, - 1.23607, 6.19577, 2, - 0, 10, -2, - 0, 10, 2, - 11, -20, -0.5, - 11, -20, 0.5, - 10.309, -19.0489, -0.5, - 10.309, -19.0489, 0.5, - 9.19098, -19.4122, -0.5, - 9.19098, -19.4122, 0.5, - 9.19098, -20.5878, -0.5, - 9.19098, -20.5878, 0.5, - 10.309, -20.9511, -0.5, - 10.309, -20.9511, 0.5, - 10, -20, -0.5, - 10, -20, 0.5, - 12, -20, -1, - 12, -20, 1, - 10.618, -18.0979, -1, - 10.618, -18.0979, 1, - 8.38197, -18.8244, -1, - 8.38197, -18.8244, 1, - 8.38197, -21.1756, -1, - 8.38197, -21.1756, 1, - 10.618, -21.9021, -1, - 10.618, -21.9021, 1, - 10, -20, -1, - 10, -20, 1, - 13, -20, -1.5, - 13, -20, 1.5, - 10.9271, -17.1468, -1.5, - 10.9271, -17.1468, 1.5, - 7.57295, -18.2366, -1.5, - 7.57295, -18.2366, 1.5, - 7.57295, -21.7634, -1.5, - 7.57295, -21.7634, 1.5, - 10.9271, -22.8532, -1.5, - 10.9271, -22.8532, 1.5, - 10, -20, -1.5, - 10, -20, 1.5, - 14, -20, -2, - 14, -20, 2, - 11.2361, -16.1958, -2, - 11.2361, -16.1958, 2, - 6.76393, -17.6489, -2, - 6.76393, -17.6489, 2, - 6.76393, -22.3511, -2, - 6.76393, -22.3511, 2, - 11.2361, -23.8042, -2, - 11.2361, -23.8042, 2, - 10, -20, -2, - 10, -20, 2, - 11, -10, -0.5, - 11, -10, 0.5, - 10.309, -9.04894, -0.5, - 10.309, -9.04894, 0.5, - 9.19098, -9.41221, -0.5, - 9.19098, -9.41221, 0.5, - 9.19098, -10.5878, -0.5, - 9.19098, -10.5878, 0.5, - 10.309, -10.9511, -0.5, - 10.309, -10.9511, 0.5, - 10, -10, -0.5, - 10, -10, 0.5, - 12, -10, -1, - 12, -10, 1, - 10.618, -8.09789, -1, - 10.618, -8.09789, 1, - 8.38197, -8.82443, -1, - 8.38197, -8.82443, 1, - 8.38197, -11.1756, -1, - 8.38197, -11.1756, 1, - 10.618, -11.9021, -1, - 10.618, -11.9021, 1, - 10, -10, -1, - 10, -10, 1, - 13, -10, -1.5, - 13, -10, 1.5, - 10.9271, -7.14683, -1.5, - 10.9271, -7.14683, 1.5, - 7.57295, -8.23664, -1.5, - 7.57295, -8.23664, 1.5, - 7.57295, -11.7634, -1.5, - 7.57295, -11.7634, 1.5, - 10.9271, -12.8532, -1.5, - 10.9271, -12.8532, 1.5, - 10, -10, -1.5, - 10, -10, 1.5, - 14, -10, -2, - 14, -10, 2, - 11.2361, -6.19577, -2, - 11.2361, -6.19577, 2, - 6.76393, -7.64886, -2, - 6.76393, -7.64886, 2, - 6.76393, -12.3511, -2, - 6.76393, -12.3511, 2, - 11.2361, -13.8042, -2, - 11.2361, -13.8042, 2, - 10, -10, -2, - 10, -10, 2, - 11, 0, -0.5, - 11, 0, 0.5, - 10.309, 0.951057, -0.5, - 10.309, 0.951057, 0.5, - 9.19098, 0.587785, -0.5, - 9.19098, 0.587785, 0.5, - 9.19098, -0.587785, -0.5, - 9.19098, -0.587785, 0.5, - 10.309, -0.951057, -0.5, - 10.309, -0.951057, 0.5, - 10, 0, -0.5, - 10, 0, 0.5, - 12, 0, -1, - 12, 0, 1, - 10.618, 1.90211, -1, - 10.618, 1.90211, 1, - 8.38197, 1.17557, -1, - 8.38197, 1.17557, 1, - 8.38197, -1.17557, -1, - 8.38197, -1.17557, 1, - 10.618, -1.90211, -1, - 10.618, -1.90211, 1, - 10, 0, -1, - 10, 0, 1, - 13, 0, -1.5, - 13, 0, 1.5, - 10.9271, 2.85317, -1.5, - 10.9271, 2.85317, 1.5, - 7.57295, 1.76336, -1.5, - 7.57295, 1.76336, 1.5, - 7.57295, -1.76336, -1.5, - 7.57295, -1.76336, 1.5, - 10.9271, -2.85317, -1.5, - 10.9271, -2.85317, 1.5, - 10, 0, -1.5, - 10, 0, 1.5, - 14, 0, -2, - 14, 0, 2, - 11.2361, 3.80423, -2, - 11.2361, 3.80423, 2, - 6.76393, 2.35114, -2, - 6.76393, 2.35114, 2, - 6.76393, -2.35114, -2, - 6.76393, -2.35114, 2, - 11.2361, -3.80423, -2, - 11.2361, -3.80423, 2, - 10, 0, -2, - 10, 0, 2, - 11, 10, -0.5, - 11, 10, 0.5, - 10.309, 10.9511, -0.5, - 10.309, 10.9511, 0.5, - 9.19098, 10.5878, -0.5, - 9.19098, 10.5878, 0.5, - 9.19098, 9.41221, -0.5, - 9.19098, 9.41221, 0.5, - 10.309, 9.04894, -0.5, - 10.309, 9.04894, 0.5, - 10, 10, -0.5, - 10, 10, 0.5, - 12, 10, -1, - 12, 10, 1, - 10.618, 11.9021, -1, - 10.618, 11.9021, 1, - 8.38197, 11.1756, -1, - 8.38197, 11.1756, 1, - 8.38197, 8.82443, -1, - 8.38197, 8.82443, 1, - 10.618, 8.09789, -1, - 10.618, 8.09789, 1, - 10, 10, -1, - 10, 10, 1, - 13, 10, -1.5, - 13, 10, 1.5, - 10.9271, 12.8532, -1.5, - 10.9271, 12.8532, 1.5, - 7.57295, 11.7634, -1.5, - 7.57295, 11.7634, 1.5, - 7.57295, 8.23664, -1.5, - 7.57295, 8.23664, 1.5, - 10.9271, 7.14683, -1.5, - 10.9271, 7.14683, 1.5, - 10, 10, -1.5, - 10, 10, 1.5, - 14, 10, -2, - 14, 10, 2, - 11.2361, 13.8042, -2, - 11.2361, 13.8042, 2, - 6.76393, 12.3511, -2, - 6.76393, 12.3511, 2, - 6.76393, 7.64886, -2, - 6.76393, 7.64886, 2, - 11.2361, 6.19577, -2, - 11.2361, 6.19577, 2, - 10, 10, -2, - 10, 10, 2 -}; -static const unsigned some_enclosures_triangles_count = 1280; -static const unsigned some_enclosures_triangles[3840] = -{ - 0, 1, 2, - 2, 1, 3, - 2, 3, 4, - 4, 3, 5, - 4, 5, 6, - 6, 5, 7, - 6, 7, 8, - 8, 7, 9, - 8, 9, 0, - 0, 9, 1, - 10, 0, 2, - 10, 2, 4, - 10, 4, 6, - 10, 6, 8, - 10, 8, 0, - 11, 3, 1, - 11, 5, 3, - 11, 7, 5, - 11, 9, 7, - 11, 1, 9, - 12, 13, 14, - 14, 13, 15, - 14, 15, 16, - 16, 15, 17, - 16, 17, 18, - 18, 17, 19, - 18, 19, 20, - 20, 19, 21, - 20, 21, 12, - 12, 21, 13, - 22, 12, 14, - 22, 14, 16, - 22, 16, 18, - 22, 18, 20, - 22, 20, 12, - 23, 15, 13, - 23, 17, 15, - 23, 19, 17, - 23, 21, 19, - 23, 13, 21, - 24, 25, 26, - 26, 25, 27, - 26, 27, 28, - 28, 27, 29, - 28, 29, 30, - 30, 29, 31, - 30, 31, 32, - 32, 31, 33, - 32, 33, 24, - 24, 33, 25, - 34, 24, 26, - 34, 26, 28, - 34, 28, 30, - 34, 30, 32, - 34, 32, 24, - 35, 27, 25, - 35, 29, 27, - 35, 31, 29, - 35, 33, 31, - 35, 25, 33, - 36, 37, 38, - 38, 37, 39, - 38, 39, 40, - 40, 39, 41, - 40, 41, 42, - 42, 41, 43, - 42, 43, 44, - 44, 43, 45, - 44, 45, 36, - 36, 45, 37, - 46, 36, 38, - 46, 38, 40, - 46, 40, 42, - 46, 42, 44, - 46, 44, 36, - 47, 39, 37, - 47, 41, 39, - 47, 43, 41, - 47, 45, 43, - 47, 37, 45, - 48, 49, 50, - 50, 49, 51, - 50, 51, 52, - 52, 51, 53, - 52, 53, 54, - 54, 53, 55, - 54, 55, 56, - 56, 55, 57, - 56, 57, 48, - 48, 57, 49, - 58, 48, 50, - 58, 50, 52, - 58, 52, 54, - 58, 54, 56, - 58, 56, 48, - 59, 51, 49, - 59, 53, 51, - 59, 55, 53, - 59, 57, 55, - 59, 49, 57, - 60, 61, 62, - 62, 61, 63, - 62, 63, 64, - 64, 63, 65, - 64, 65, 66, - 66, 65, 67, - 66, 67, 68, - 68, 67, 69, - 68, 69, 60, - 60, 69, 61, - 70, 60, 62, - 70, 62, 64, - 70, 64, 66, - 70, 66, 68, - 70, 68, 60, - 71, 63, 61, - 71, 65, 63, - 71, 67, 65, - 71, 69, 67, - 71, 61, 69, - 72, 73, 74, - 74, 73, 75, - 74, 75, 76, - 76, 75, 77, - 76, 77, 78, - 78, 77, 79, - 78, 79, 80, - 80, 79, 81, - 80, 81, 72, - 72, 81, 73, - 82, 72, 74, - 82, 74, 76, - 82, 76, 78, - 82, 78, 80, - 82, 80, 72, - 83, 75, 73, - 83, 77, 75, - 83, 79, 77, - 83, 81, 79, - 83, 73, 81, - 84, 85, 86, - 86, 85, 87, - 86, 87, 88, - 88, 87, 89, - 88, 89, 90, - 90, 89, 91, - 90, 91, 92, - 92, 91, 93, - 92, 93, 84, - 84, 93, 85, - 94, 84, 86, - 94, 86, 88, - 94, 88, 90, - 94, 90, 92, - 94, 92, 84, - 95, 87, 85, - 95, 89, 87, - 95, 91, 89, - 95, 93, 91, - 95, 85, 93, - 96, 97, 98, - 98, 97, 99, - 98, 99, 100, - 100, 99, 101, - 100, 101, 102, - 102, 101, 103, - 102, 103, 104, - 104, 103, 105, - 104, 105, 96, - 96, 105, 97, - 106, 96, 98, - 106, 98, 100, - 106, 100, 102, - 106, 102, 104, - 106, 104, 96, - 107, 99, 97, - 107, 101, 99, - 107, 103, 101, - 107, 105, 103, - 107, 97, 105, - 108, 109, 110, - 110, 109, 111, - 110, 111, 112, - 112, 111, 113, - 112, 113, 114, - 114, 113, 115, - 114, 115, 116, - 116, 115, 117, - 116, 117, 108, - 108, 117, 109, - 118, 108, 110, - 118, 110, 112, - 118, 112, 114, - 118, 114, 116, - 118, 116, 108, - 119, 111, 109, - 119, 113, 111, - 119, 115, 113, - 119, 117, 115, - 119, 109, 117, - 120, 121, 122, - 122, 121, 123, - 122, 123, 124, - 124, 123, 125, - 124, 125, 126, - 126, 125, 127, - 126, 127, 128, - 128, 127, 129, - 128, 129, 120, - 120, 129, 121, - 130, 120, 122, - 130, 122, 124, - 130, 124, 126, - 130, 126, 128, - 130, 128, 120, - 131, 123, 121, - 131, 125, 123, - 131, 127, 125, - 131, 129, 127, - 131, 121, 129, - 132, 133, 134, - 134, 133, 135, - 134, 135, 136, - 136, 135, 137, - 136, 137, 138, - 138, 137, 139, - 138, 139, 140, - 140, 139, 141, - 140, 141, 132, - 132, 141, 133, - 142, 132, 134, - 142, 134, 136, - 142, 136, 138, - 142, 138, 140, - 142, 140, 132, - 143, 135, 133, - 143, 137, 135, - 143, 139, 137, - 143, 141, 139, - 143, 133, 141, - 144, 145, 146, - 146, 145, 147, - 146, 147, 148, - 148, 147, 149, - 148, 149, 150, - 150, 149, 151, - 150, 151, 152, - 152, 151, 153, - 152, 153, 144, - 144, 153, 145, - 154, 144, 146, - 154, 146, 148, - 154, 148, 150, - 154, 150, 152, - 154, 152, 144, - 155, 147, 145, - 155, 149, 147, - 155, 151, 149, - 155, 153, 151, - 155, 145, 153, - 156, 157, 158, - 158, 157, 159, - 158, 159, 160, - 160, 159, 161, - 160, 161, 162, - 162, 161, 163, - 162, 163, 164, - 164, 163, 165, - 164, 165, 156, - 156, 165, 157, - 166, 156, 158, - 166, 158, 160, - 166, 160, 162, - 166, 162, 164, - 166, 164, 156, - 167, 159, 157, - 167, 161, 159, - 167, 163, 161, - 167, 165, 163, - 167, 157, 165, - 168, 169, 170, - 170, 169, 171, - 170, 171, 172, - 172, 171, 173, - 172, 173, 174, - 174, 173, 175, - 174, 175, 176, - 176, 175, 177, - 176, 177, 168, - 168, 177, 169, - 178, 168, 170, - 178, 170, 172, - 178, 172, 174, - 178, 174, 176, - 178, 176, 168, - 179, 171, 169, - 179, 173, 171, - 179, 175, 173, - 179, 177, 175, - 179, 169, 177, - 180, 181, 182, - 182, 181, 183, - 182, 183, 184, - 184, 183, 185, - 184, 185, 186, - 186, 185, 187, - 186, 187, 188, - 188, 187, 189, - 188, 189, 180, - 180, 189, 181, - 190, 180, 182, - 190, 182, 184, - 190, 184, 186, - 190, 186, 188, - 190, 188, 180, - 191, 183, 181, - 191, 185, 183, - 191, 187, 185, - 191, 189, 187, - 191, 181, 189, - 192, 193, 194, - 194, 193, 195, - 194, 195, 196, - 196, 195, 197, - 196, 197, 198, - 198, 197, 199, - 198, 199, 200, - 200, 199, 201, - 200, 201, 192, - 192, 201, 193, - 202, 192, 194, - 202, 194, 196, - 202, 196, 198, - 202, 198, 200, - 202, 200, 192, - 203, 195, 193, - 203, 197, 195, - 203, 199, 197, - 203, 201, 199, - 203, 193, 201, - 204, 205, 206, - 206, 205, 207, - 206, 207, 208, - 208, 207, 209, - 208, 209, 210, - 210, 209, 211, - 210, 211, 212, - 212, 211, 213, - 212, 213, 204, - 204, 213, 205, - 214, 204, 206, - 214, 206, 208, - 214, 208, 210, - 214, 210, 212, - 214, 212, 204, - 215, 207, 205, - 215, 209, 207, - 215, 211, 209, - 215, 213, 211, - 215, 205, 213, - 216, 217, 218, - 218, 217, 219, - 218, 219, 220, - 220, 219, 221, - 220, 221, 222, - 222, 221, 223, - 222, 223, 224, - 224, 223, 225, - 224, 225, 216, - 216, 225, 217, - 226, 216, 218, - 226, 218, 220, - 226, 220, 222, - 226, 222, 224, - 226, 224, 216, - 227, 219, 217, - 227, 221, 219, - 227, 223, 221, - 227, 225, 223, - 227, 217, 225, - 228, 229, 230, - 230, 229, 231, - 230, 231, 232, - 232, 231, 233, - 232, 233, 234, - 234, 233, 235, - 234, 235, 236, - 236, 235, 237, - 236, 237, 228, - 228, 237, 229, - 238, 228, 230, - 238, 230, 232, - 238, 232, 234, - 238, 234, 236, - 238, 236, 228, - 239, 231, 229, - 239, 233, 231, - 239, 235, 233, - 239, 237, 235, - 239, 229, 237, - 240, 241, 242, - 242, 241, 243, - 242, 243, 244, - 244, 243, 245, - 244, 245, 246, - 246, 245, 247, - 246, 247, 248, - 248, 247, 249, - 248, 249, 240, - 240, 249, 241, - 250, 240, 242, - 250, 242, 244, - 250, 244, 246, - 250, 246, 248, - 250, 248, 240, - 251, 243, 241, - 251, 245, 243, - 251, 247, 245, - 251, 249, 247, - 251, 241, 249, - 252, 253, 254, - 254, 253, 255, - 254, 255, 256, - 256, 255, 257, - 256, 257, 258, - 258, 257, 259, - 258, 259, 260, - 260, 259, 261, - 260, 261, 252, - 252, 261, 253, - 262, 252, 254, - 262, 254, 256, - 262, 256, 258, - 262, 258, 260, - 262, 260, 252, - 263, 255, 253, - 263, 257, 255, - 263, 259, 257, - 263, 261, 259, - 263, 253, 261, - 264, 265, 266, - 266, 265, 267, - 266, 267, 268, - 268, 267, 269, - 268, 269, 270, - 270, 269, 271, - 270, 271, 272, - 272, 271, 273, - 272, 273, 264, - 264, 273, 265, - 274, 264, 266, - 274, 266, 268, - 274, 268, 270, - 274, 270, 272, - 274, 272, 264, - 275, 267, 265, - 275, 269, 267, - 275, 271, 269, - 275, 273, 271, - 275, 265, 273, - 276, 277, 278, - 278, 277, 279, - 278, 279, 280, - 280, 279, 281, - 280, 281, 282, - 282, 281, 283, - 282, 283, 284, - 284, 283, 285, - 284, 285, 276, - 276, 285, 277, - 286, 276, 278, - 286, 278, 280, - 286, 280, 282, - 286, 282, 284, - 286, 284, 276, - 287, 279, 277, - 287, 281, 279, - 287, 283, 281, - 287, 285, 283, - 287, 277, 285, - 288, 289, 290, - 290, 289, 291, - 290, 291, 292, - 292, 291, 293, - 292, 293, 294, - 294, 293, 295, - 294, 295, 296, - 296, 295, 297, - 296, 297, 288, - 288, 297, 289, - 298, 288, 290, - 298, 290, 292, - 298, 292, 294, - 298, 294, 296, - 298, 296, 288, - 299, 291, 289, - 299, 293, 291, - 299, 295, 293, - 299, 297, 295, - 299, 289, 297, - 300, 301, 302, - 302, 301, 303, - 302, 303, 304, - 304, 303, 305, - 304, 305, 306, - 306, 305, 307, - 306, 307, 308, - 308, 307, 309, - 308, 309, 300, - 300, 309, 301, - 310, 300, 302, - 310, 302, 304, - 310, 304, 306, - 310, 306, 308, - 310, 308, 300, - 311, 303, 301, - 311, 305, 303, - 311, 307, 305, - 311, 309, 307, - 311, 301, 309, - 312, 313, 314, - 314, 313, 315, - 314, 315, 316, - 316, 315, 317, - 316, 317, 318, - 318, 317, 319, - 318, 319, 320, - 320, 319, 321, - 320, 321, 312, - 312, 321, 313, - 322, 312, 314, - 322, 314, 316, - 322, 316, 318, - 322, 318, 320, - 322, 320, 312, - 323, 315, 313, - 323, 317, 315, - 323, 319, 317, - 323, 321, 319, - 323, 313, 321, - 324, 325, 326, - 326, 325, 327, - 326, 327, 328, - 328, 327, 329, - 328, 329, 330, - 330, 329, 331, - 330, 331, 332, - 332, 331, 333, - 332, 333, 324, - 324, 333, 325, - 334, 324, 326, - 334, 326, 328, - 334, 328, 330, - 334, 330, 332, - 334, 332, 324, - 335, 327, 325, - 335, 329, 327, - 335, 331, 329, - 335, 333, 331, - 335, 325, 333, - 336, 337, 338, - 338, 337, 339, - 338, 339, 340, - 340, 339, 341, - 340, 341, 342, - 342, 341, 343, - 342, 343, 344, - 344, 343, 345, - 344, 345, 336, - 336, 345, 337, - 346, 336, 338, - 346, 338, 340, - 346, 340, 342, - 346, 342, 344, - 346, 344, 336, - 347, 339, 337, - 347, 341, 339, - 347, 343, 341, - 347, 345, 343, - 347, 337, 345, - 348, 349, 350, - 350, 349, 351, - 350, 351, 352, - 352, 351, 353, - 352, 353, 354, - 354, 353, 355, - 354, 355, 356, - 356, 355, 357, - 356, 357, 348, - 348, 357, 349, - 358, 348, 350, - 358, 350, 352, - 358, 352, 354, - 358, 354, 356, - 358, 356, 348, - 359, 351, 349, - 359, 353, 351, - 359, 355, 353, - 359, 357, 355, - 359, 349, 357, - 360, 361, 362, - 362, 361, 363, - 362, 363, 364, - 364, 363, 365, - 364, 365, 366, - 366, 365, 367, - 366, 367, 368, - 368, 367, 369, - 368, 369, 360, - 360, 369, 361, - 370, 360, 362, - 370, 362, 364, - 370, 364, 366, - 370, 366, 368, - 370, 368, 360, - 371, 363, 361, - 371, 365, 363, - 371, 367, 365, - 371, 369, 367, - 371, 361, 369, - 372, 373, 374, - 374, 373, 375, - 374, 375, 376, - 376, 375, 377, - 376, 377, 378, - 378, 377, 379, - 378, 379, 380, - 380, 379, 381, - 380, 381, 372, - 372, 381, 373, - 382, 372, 374, - 382, 374, 376, - 382, 376, 378, - 382, 378, 380, - 382, 380, 372, - 383, 375, 373, - 383, 377, 375, - 383, 379, 377, - 383, 381, 379, - 383, 373, 381, - 384, 385, 386, - 386, 385, 387, - 386, 387, 388, - 388, 387, 389, - 388, 389, 390, - 390, 389, 391, - 390, 391, 392, - 392, 391, 393, - 392, 393, 384, - 384, 393, 385, - 394, 384, 386, - 394, 386, 388, - 394, 388, 390, - 394, 390, 392, - 394, 392, 384, - 395, 387, 385, - 395, 389, 387, - 395, 391, 389, - 395, 393, 391, - 395, 385, 393, - 396, 397, 398, - 398, 397, 399, - 398, 399, 400, - 400, 399, 401, - 400, 401, 402, - 402, 401, 403, - 402, 403, 404, - 404, 403, 405, - 404, 405, 396, - 396, 405, 397, - 406, 396, 398, - 406, 398, 400, - 406, 400, 402, - 406, 402, 404, - 406, 404, 396, - 407, 399, 397, - 407, 401, 399, - 407, 403, 401, - 407, 405, 403, - 407, 397, 405, - 408, 409, 410, - 410, 409, 411, - 410, 411, 412, - 412, 411, 413, - 412, 413, 414, - 414, 413, 415, - 414, 415, 416, - 416, 415, 417, - 416, 417, 408, - 408, 417, 409, - 418, 408, 410, - 418, 410, 412, - 418, 412, 414, - 418, 414, 416, - 418, 416, 408, - 419, 411, 409, - 419, 413, 411, - 419, 415, 413, - 419, 417, 415, - 419, 409, 417, - 420, 421, 422, - 422, 421, 423, - 422, 423, 424, - 424, 423, 425, - 424, 425, 426, - 426, 425, 427, - 426, 427, 428, - 428, 427, 429, - 428, 429, 420, - 420, 429, 421, - 430, 420, 422, - 430, 422, 424, - 430, 424, 426, - 430, 426, 428, - 430, 428, 420, - 431, 423, 421, - 431, 425, 423, - 431, 427, 425, - 431, 429, 427, - 431, 421, 429, - 432, 433, 434, - 434, 433, 435, - 434, 435, 436, - 436, 435, 437, - 436, 437, 438, - 438, 437, 439, - 438, 439, 440, - 440, 439, 441, - 440, 441, 432, - 432, 441, 433, - 442, 432, 434, - 442, 434, 436, - 442, 436, 438, - 442, 438, 440, - 442, 440, 432, - 443, 435, 433, - 443, 437, 435, - 443, 439, 437, - 443, 441, 439, - 443, 433, 441, - 444, 445, 446, - 446, 445, 447, - 446, 447, 448, - 448, 447, 449, - 448, 449, 450, - 450, 449, 451, - 450, 451, 452, - 452, 451, 453, - 452, 453, 444, - 444, 453, 445, - 454, 444, 446, - 454, 446, 448, - 454, 448, 450, - 454, 450, 452, - 454, 452, 444, - 455, 447, 445, - 455, 449, 447, - 455, 451, 449, - 455, 453, 451, - 455, 445, 453, - 456, 457, 458, - 458, 457, 459, - 458, 459, 460, - 460, 459, 461, - 460, 461, 462, - 462, 461, 463, - 462, 463, 464, - 464, 463, 465, - 464, 465, 456, - 456, 465, 457, - 466, 456, 458, - 466, 458, 460, - 466, 460, 462, - 466, 462, 464, - 466, 464, 456, - 467, 459, 457, - 467, 461, 459, - 467, 463, 461, - 467, 465, 463, - 467, 457, 465, - 468, 469, 470, - 470, 469, 471, - 470, 471, 472, - 472, 471, 473, - 472, 473, 474, - 474, 473, 475, - 474, 475, 476, - 476, 475, 477, - 476, 477, 468, - 468, 477, 469, - 478, 468, 470, - 478, 470, 472, - 478, 472, 474, - 478, 474, 476, - 478, 476, 468, - 479, 471, 469, - 479, 473, 471, - 479, 475, 473, - 479, 477, 475, - 479, 469, 477, - 480, 481, 482, - 482, 481, 483, - 482, 483, 484, - 484, 483, 485, - 484, 485, 486, - 486, 485, 487, - 486, 487, 488, - 488, 487, 489, - 488, 489, 480, - 480, 489, 481, - 490, 480, 482, - 490, 482, 484, - 490, 484, 486, - 490, 486, 488, - 490, 488, 480, - 491, 483, 481, - 491, 485, 483, - 491, 487, 485, - 491, 489, 487, - 491, 481, 489, - 492, 493, 494, - 494, 493, 495, - 494, 495, 496, - 496, 495, 497, - 496, 497, 498, - 498, 497, 499, - 498, 499, 500, - 500, 499, 501, - 500, 501, 492, - 492, 501, 493, - 502, 492, 494, - 502, 494, 496, - 502, 496, 498, - 502, 498, 500, - 502, 500, 492, - 503, 495, 493, - 503, 497, 495, - 503, 499, 497, - 503, 501, 499, - 503, 493, 501, - 504, 505, 506, - 506, 505, 507, - 506, 507, 508, - 508, 507, 509, - 508, 509, 510, - 510, 509, 511, - 510, 511, 512, - 512, 511, 513, - 512, 513, 504, - 504, 513, 505, - 514, 504, 506, - 514, 506, 508, - 514, 508, 510, - 514, 510, 512, - 514, 512, 504, - 515, 507, 505, - 515, 509, 507, - 515, 511, 509, - 515, 513, 511, - 515, 505, 513, - 516, 517, 518, - 518, 517, 519, - 518, 519, 520, - 520, 519, 521, - 520, 521, 522, - 522, 521, 523, - 522, 523, 524, - 524, 523, 525, - 524, 525, 516, - 516, 525, 517, - 526, 516, 518, - 526, 518, 520, - 526, 520, 522, - 526, 522, 524, - 526, 524, 516, - 527, 519, 517, - 527, 521, 519, - 527, 523, 521, - 527, 525, 523, - 527, 517, 525, - 528, 529, 530, - 530, 529, 531, - 530, 531, 532, - 532, 531, 533, - 532, 533, 534, - 534, 533, 535, - 534, 535, 536, - 536, 535, 537, - 536, 537, 528, - 528, 537, 529, - 538, 528, 530, - 538, 530, 532, - 538, 532, 534, - 538, 534, 536, - 538, 536, 528, - 539, 531, 529, - 539, 533, 531, - 539, 535, 533, - 539, 537, 535, - 539, 529, 537, - 540, 541, 542, - 542, 541, 543, - 542, 543, 544, - 544, 543, 545, - 544, 545, 546, - 546, 545, 547, - 546, 547, 548, - 548, 547, 549, - 548, 549, 540, - 540, 549, 541, - 550, 540, 542, - 550, 542, 544, - 550, 544, 546, - 550, 546, 548, - 550, 548, 540, - 551, 543, 541, - 551, 545, 543, - 551, 547, 545, - 551, 549, 547, - 551, 541, 549, - 552, 553, 554, - 554, 553, 555, - 554, 555, 556, - 556, 555, 557, - 556, 557, 558, - 558, 557, 559, - 558, 559, 560, - 560, 559, 561, - 560, 561, 552, - 552, 561, 553, - 562, 552, 554, - 562, 554, 556, - 562, 556, 558, - 562, 558, 560, - 562, 560, 552, - 563, 555, 553, - 563, 557, 555, - 563, 559, 557, - 563, 561, 559, - 563, 553, 561, - 564, 565, 566, - 566, 565, 567, - 566, 567, 568, - 568, 567, 569, - 568, 569, 570, - 570, 569, 571, - 570, 571, 572, - 572, 571, 573, - 572, 573, 564, - 564, 573, 565, - 574, 564, 566, - 574, 566, 568, - 574, 568, 570, - 574, 570, 572, - 574, 572, 564, - 575, 567, 565, - 575, 569, 567, - 575, 571, 569, - 575, 573, 571, - 575, 565, 573, - 576, 577, 578, - 578, 577, 579, - 578, 579, 580, - 580, 579, 581, - 580, 581, 582, - 582, 581, 583, - 582, 583, 584, - 584, 583, 585, - 584, 585, 576, - 576, 585, 577, - 586, 576, 578, - 586, 578, 580, - 586, 580, 582, - 586, 582, 584, - 586, 584, 576, - 587, 579, 577, - 587, 581, 579, - 587, 583, 581, - 587, 585, 583, - 587, 577, 585, - 588, 589, 590, - 590, 589, 591, - 590, 591, 592, - 592, 591, 593, - 592, 593, 594, - 594, 593, 595, - 594, 595, 596, - 596, 595, 597, - 596, 597, 588, - 588, 597, 589, - 598, 588, 590, - 598, 590, 592, - 598, 592, 594, - 598, 594, 596, - 598, 596, 588, - 599, 591, 589, - 599, 593, 591, - 599, 595, 593, - 599, 597, 595, - 599, 589, 597, - 600, 601, 602, - 602, 601, 603, - 602, 603, 604, - 604, 603, 605, - 604, 605, 606, - 606, 605, 607, - 606, 607, 608, - 608, 607, 609, - 608, 609, 600, - 600, 609, 601, - 610, 600, 602, - 610, 602, 604, - 610, 604, 606, - 610, 606, 608, - 610, 608, 600, - 611, 603, 601, - 611, 605, 603, - 611, 607, 605, - 611, 609, 607, - 611, 601, 609, - 612, 613, 614, - 614, 613, 615, - 614, 615, 616, - 616, 615, 617, - 616, 617, 618, - 618, 617, 619, - 618, 619, 620, - 620, 619, 621, - 620, 621, 612, - 612, 621, 613, - 622, 612, 614, - 622, 614, 616, - 622, 616, 618, - 622, 618, 620, - 622, 620, 612, - 623, 615, 613, - 623, 617, 615, - 623, 619, 617, - 623, 621, 619, - 623, 613, 621, - 624, 625, 626, - 626, 625, 627, - 626, 627, 628, - 628, 627, 629, - 628, 629, 630, - 630, 629, 631, - 630, 631, 632, - 632, 631, 633, - 632, 633, 624, - 624, 633, 625, - 634, 624, 626, - 634, 626, 628, - 634, 628, 630, - 634, 630, 632, - 634, 632, 624, - 635, 627, 625, - 635, 629, 627, - 635, 631, 629, - 635, 633, 631, - 635, 625, 633, - 636, 637, 638, - 638, 637, 639, - 638, 639, 640, - 640, 639, 641, - 640, 641, 642, - 642, 641, 643, - 642, 643, 644, - 644, 643, 645, - 644, 645, 636, - 636, 645, 637, - 646, 636, 638, - 646, 638, 640, - 646, 640, 642, - 646, 642, 644, - 646, 644, 636, - 647, 639, 637, - 647, 641, 639, - 647, 643, 641, - 647, 645, 643, - 647, 637, 645, - 648, 649, 650, - 650, 649, 651, - 650, 651, 652, - 652, 651, 653, - 652, 653, 654, - 654, 653, 655, - 654, 655, 656, - 656, 655, 657, - 656, 657, 648, - 648, 657, 649, - 658, 648, 650, - 658, 650, 652, - 658, 652, 654, - 658, 654, 656, - 658, 656, 648, - 659, 651, 649, - 659, 653, 651, - 659, 655, 653, - 659, 657, 655, - 659, 649, 657, - 660, 661, 662, - 662, 661, 663, - 662, 663, 664, - 664, 663, 665, - 664, 665, 666, - 666, 665, 667, - 666, 667, 668, - 668, 667, 669, - 668, 669, 660, - 660, 669, 661, - 670, 660, 662, - 670, 662, 664, - 670, 664, 666, - 670, 666, 668, - 670, 668, 660, - 671, 663, 661, - 671, 665, 663, - 671, 667, 665, - 671, 669, 667, - 671, 661, 669, - 672, 673, 674, - 674, 673, 675, - 674, 675, 676, - 676, 675, 677, - 676, 677, 678, - 678, 677, 679, - 678, 679, 680, - 680, 679, 681, - 680, 681, 672, - 672, 681, 673, - 682, 672, 674, - 682, 674, 676, - 682, 676, 678, - 682, 678, 680, - 682, 680, 672, - 683, 675, 673, - 683, 677, 675, - 683, 679, 677, - 683, 681, 679, - 683, 673, 681, - 684, 685, 686, - 686, 685, 687, - 686, 687, 688, - 688, 687, 689, - 688, 689, 690, - 690, 689, 691, - 690, 691, 692, - 692, 691, 693, - 692, 693, 684, - 684, 693, 685, - 694, 684, 686, - 694, 686, 688, - 694, 688, 690, - 694, 690, 692, - 694, 692, 684, - 695, 687, 685, - 695, 689, 687, - 695, 691, 689, - 695, 693, 691, - 695, 685, 693, - 696, 697, 698, - 698, 697, 699, - 698, 699, 700, - 700, 699, 701, - 700, 701, 702, - 702, 701, 703, - 702, 703, 704, - 704, 703, 705, - 704, 705, 696, - 696, 705, 697, - 706, 696, 698, - 706, 698, 700, - 706, 700, 702, - 706, 702, 704, - 706, 704, 696, - 707, 699, 697, - 707, 701, 699, - 707, 703, 701, - 707, 705, 703, - 707, 697, 705, - 708, 709, 710, - 710, 709, 711, - 710, 711, 712, - 712, 711, 713, - 712, 713, 714, - 714, 713, 715, - 714, 715, 716, - 716, 715, 717, - 716, 717, 708, - 708, 717, 709, - 718, 708, 710, - 718, 710, 712, - 718, 712, 714, - 718, 714, 716, - 718, 716, 708, - 719, 711, 709, - 719, 713, 711, - 719, 715, 713, - 719, 717, 715, - 719, 709, 717, - 720, 721, 722, - 722, 721, 723, - 722, 723, 724, - 724, 723, 725, - 724, 725, 726, - 726, 725, 727, - 726, 727, 728, - 728, 727, 729, - 728, 729, 720, - 720, 729, 721, - 730, 720, 722, - 730, 722, 724, - 730, 724, 726, - 730, 726, 728, - 730, 728, 720, - 731, 723, 721, - 731, 725, 723, - 731, 727, 725, - 731, 729, 727, - 731, 721, 729, - 732, 733, 734, - 734, 733, 735, - 734, 735, 736, - 736, 735, 737, - 736, 737, 738, - 738, 737, 739, - 738, 739, 740, - 740, 739, 741, - 740, 741, 732, - 732, 741, 733, - 742, 732, 734, - 742, 734, 736, - 742, 736, 738, - 742, 738, 740, - 742, 740, 732, - 743, 735, 733, - 743, 737, 735, - 743, 739, 737, - 743, 741, 739, - 743, 733, 741, - 744, 745, 746, - 746, 745, 747, - 746, 747, 748, - 748, 747, 749, - 748, 749, 750, - 750, 749, 751, - 750, 751, 752, - 752, 751, 753, - 752, 753, 744, - 744, 753, 745, - 754, 744, 746, - 754, 746, 748, - 754, 748, 750, - 754, 750, 752, - 754, 752, 744, - 755, 747, 745, - 755, 749, 747, - 755, 751, 749, - 755, 753, 751, - 755, 745, 753, - 756, 757, 758, - 758, 757, 759, - 758, 759, 760, - 760, 759, 761, - 760, 761, 762, - 762, 761, 763, - 762, 763, 764, - 764, 763, 765, - 764, 765, 756, - 756, 765, 757, - 766, 756, 758, - 766, 758, 760, - 766, 760, 762, - 766, 762, 764, - 766, 764, 756, - 767, 759, 757, - 767, 761, 759, - 767, 763, 761, - 767, 765, 763, - 767, 757, 765 -}; -static const unsigned some_enclosures_properties[3840] = -{ - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 1, 2, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 2, 3, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0, - 3, 4, 0 -}; - -#define NB_CYL_X 4 -#define NB_CYL_Y 4 -#define NB_CYL_Z 4 -#define NB_CYL (NB_CYL_X * NB_CYL_Y * NB_CYL_Z) -#define CYL_VRTX_COUNT 12u -#define CYL_TRG_COUNT 20u - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct context ctx = CONTEXT_NULL__; - unsigned e, count; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* Create a scene */ - ctx.positions = some_enclosures_vertices; - ctx.indices = some_enclosures_triangles; - ctx.properties = some_enclosures_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - some_enclosures_triangles_count, get_indices, get_media_from_properties, - some_enclosures_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_vertices_count(scn, &count)); - CHK(count == NB_CYL * CYL_VRTX_COUNT); - OK(senc_scene_get_triangles_count(scn, &count)); - CHK(count == NB_CYL * CYL_TRG_COUNT); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 1 + NB_CYL); - FOR_EACH(e, 0, count) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - unsigned m; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - CHK(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &m)); - CHK(header.primitives_count == - (header.is_infinite /* Outermost enclosure: NB_CYL_X*NB_CYL_Y cylinders */ - ? NB_CYL_X * NB_CYL_Y * CYL_TRG_COUNT - : (m == 0 - ? CYL_TRG_COUNT /* Innermost enclosures: 1 cylinder */ - : 2 * CYL_TRG_COUNT))); /* Other enclosures: 2 cylinders */ - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_some_triangles.c b/src/test_senc_some_triangles.c @@ -1,2737 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test has been created using the sg3_geometry_dump_as_C_code feature - * of star-geometry. It uses output from test_sg3_some_triangles. - * This test is similar to test_senc_many_triangles that creates a huge - * geometry by program. */ - -#include "senc.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -/* Dump of star-geometry 'some_triangles'. */ -static const unsigned some_triangles_vertices_count = 536; -static const double some_triangles_vertices[1608] = -{ - 1, 0, -1, - 1, 0, -0.8, - 1, 0, -0.6, - 1, 0, -0.4, - 1, 0, -0.2, - 1, 0, -5.55112e-17, - 1, 0, 0.2, - 1, 0, 0.4, - 1, 0, 0.6, - 1, 0, 0.8, - 1, 0, 1, - 0.866025, 0.5, -1, - 0.866025, 0.5, -0.8, - 0.866025, 0.5, -0.6, - 0.866025, 0.5, -0.4, - 0.866025, 0.5, -0.2, - 0.866025, 0.5, -5.55112e-17, - 0.866025, 0.5, 0.2, - 0.866025, 0.5, 0.4, - 0.866025, 0.5, 0.6, - 0.866025, 0.5, 0.8, - 0.866025, 0.5, 1, - 0.5, 0.866025, -1, - 0.5, 0.866025, -0.8, - 0.5, 0.866025, -0.6, - 0.5, 0.866025, -0.4, - 0.5, 0.866025, -0.2, - 0.5, 0.866025, -5.55112e-17, - 0.5, 0.866025, 0.2, - 0.5, 0.866025, 0.4, - 0.5, 0.866025, 0.6, - 0.5, 0.866025, 0.8, - 0.5, 0.866025, 1, - 6.12323e-17, 1, -1, - 6.12323e-17, 1, -0.8, - 6.12323e-17, 1, -0.6, - 6.12323e-17, 1, -0.4, - 6.12323e-17, 1, -0.2, - 6.12323e-17, 1, -5.55112e-17, - 6.12323e-17, 1, 0.2, - 6.12323e-17, 1, 0.4, - 6.12323e-17, 1, 0.6, - 6.12323e-17, 1, 0.8, - 6.12323e-17, 1, 1, - -0.5, 0.866025, -1, - -0.5, 0.866025, -0.8, - -0.5, 0.866025, -0.6, - -0.5, 0.866025, -0.4, - -0.5, 0.866025, -0.2, - -0.5, 0.866025, -5.55112e-17, - -0.5, 0.866025, 0.2, - -0.5, 0.866025, 0.4, - -0.5, 0.866025, 0.6, - -0.5, 0.866025, 0.8, - -0.5, 0.866025, 1, - -0.866025, 0.5, -1, - -0.866025, 0.5, -0.8, - -0.866025, 0.5, -0.6, - -0.866025, 0.5, -0.4, - -0.866025, 0.5, -0.2, - -0.866025, 0.5, -5.55112e-17, - -0.866025, 0.5, 0.2, - -0.866025, 0.5, 0.4, - -0.866025, 0.5, 0.6, - -0.866025, 0.5, 0.8, - -0.866025, 0.5, 1, - -1, 1.22465e-16, -1, - -1, 1.22465e-16, -0.8, - -1, 1.22465e-16, -0.6, - -1, 1.22465e-16, -0.4, - -1, 1.22465e-16, -0.2, - -1, 1.22465e-16, -5.55112e-17, - -1, 1.22465e-16, 0.2, - -1, 1.22465e-16, 0.4, - -1, 1.22465e-16, 0.6, - -1, 1.22465e-16, 0.8, - -1, 1.22465e-16, 1, - -0.866025, -0.5, -1, - -0.866025, -0.5, -0.8, - -0.866025, -0.5, -0.6, - -0.866025, -0.5, -0.4, - -0.866025, -0.5, -0.2, - -0.866025, -0.5, -5.55112e-17, - -0.866025, -0.5, 0.2, - -0.866025, -0.5, 0.4, - -0.866025, -0.5, 0.6, - -0.866025, -0.5, 0.8, - -0.866025, -0.5, 1, - -0.5, -0.866025, -1, - -0.5, -0.866025, -0.8, - -0.5, -0.866025, -0.6, - -0.5, -0.866025, -0.4, - -0.5, -0.866025, -0.2, - -0.5, -0.866025, -5.55112e-17, - -0.5, -0.866025, 0.2, - -0.5, -0.866025, 0.4, - -0.5, -0.866025, 0.6, - -0.5, -0.866025, 0.8, - -0.5, -0.866025, 1, - -1.83697e-16, -1, -1, - -1.83697e-16, -1, -0.8, - -1.83697e-16, -1, -0.6, - -1.83697e-16, -1, -0.4, - -1.83697e-16, -1, -0.2, - -1.83697e-16, -1, -5.55112e-17, - -1.83697e-16, -1, 0.2, - -1.83697e-16, -1, 0.4, - -1.83697e-16, -1, 0.6, - -1.83697e-16, -1, 0.8, - -1.83697e-16, -1, 1, - 0.5, -0.866025, -1, - 0.5, -0.866025, -0.8, - 0.5, -0.866025, -0.6, - 0.5, -0.866025, -0.4, - 0.5, -0.866025, -0.2, - 0.5, -0.866025, -5.55112e-17, - 0.5, -0.866025, 0.2, - 0.5, -0.866025, 0.4, - 0.5, -0.866025, 0.6, - 0.5, -0.866025, 0.8, - 0.5, -0.866025, 1, - 0.866025, -0.5, -1, - 0.866025, -0.5, -0.8, - 0.866025, -0.5, -0.6, - 0.866025, -0.5, -0.4, - 0.866025, -0.5, -0.2, - 0.866025, -0.5, -5.55112e-17, - 0.866025, -0.5, 0.2, - 0.866025, -0.5, 0.4, - 0.866025, -0.5, 0.6, - 0.866025, -0.5, 0.8, - 0.866025, -0.5, 1, - 0, 0, -1, - 0, 0, 1, - 1, 0, 9, - 1, 0, 9.2, - 1, 0, 9.4, - 1, 0, 9.6, - 1, 0, 9.8, - 1, 0, 10, - 1, 0, 10.2, - 1, 0, 10.4, - 1, 0, 10.6, - 1, 0, 10.8, - 1, 0, 11, - 0.866025, 0.5, 9, - 0.866025, 0.5, 9.2, - 0.866025, 0.5, 9.4, - 0.866025, 0.5, 9.6, - 0.866025, 0.5, 9.8, - 0.866025, 0.5, 10, - 0.866025, 0.5, 10.2, - 0.866025, 0.5, 10.4, - 0.866025, 0.5, 10.6, - 0.866025, 0.5, 10.8, - 0.866025, 0.5, 11, - 0.5, 0.866025, 9, - 0.5, 0.866025, 9.2, - 0.5, 0.866025, 9.4, - 0.5, 0.866025, 9.6, - 0.5, 0.866025, 9.8, - 0.5, 0.866025, 10, - 0.5, 0.866025, 10.2, - 0.5, 0.866025, 10.4, - 0.5, 0.866025, 10.6, - 0.5, 0.866025, 10.8, - 0.5, 0.866025, 11, - 6.12323e-17, 1, 9, - 6.12323e-17, 1, 9.2, - 6.12323e-17, 1, 9.4, - 6.12323e-17, 1, 9.6, - 6.12323e-17, 1, 9.8, - 6.12323e-17, 1, 10, - 6.12323e-17, 1, 10.2, - 6.12323e-17, 1, 10.4, - 6.12323e-17, 1, 10.6, - 6.12323e-17, 1, 10.8, - 6.12323e-17, 1, 11, - -0.5, 0.866025, 9, - -0.5, 0.866025, 9.2, - -0.5, 0.866025, 9.4, - -0.5, 0.866025, 9.6, - -0.5, 0.866025, 9.8, - -0.5, 0.866025, 10, - -0.5, 0.866025, 10.2, - -0.5, 0.866025, 10.4, - -0.5, 0.866025, 10.6, - -0.5, 0.866025, 10.8, - -0.5, 0.866025, 11, - -0.866025, 0.5, 9, - -0.866025, 0.5, 9.2, - -0.866025, 0.5, 9.4, - -0.866025, 0.5, 9.6, - -0.866025, 0.5, 9.8, - -0.866025, 0.5, 10, - -0.866025, 0.5, 10.2, - -0.866025, 0.5, 10.4, - -0.866025, 0.5, 10.6, - -0.866025, 0.5, 10.8, - -0.866025, 0.5, 11, - -1, 1.22465e-16, 9, - -1, 1.22465e-16, 9.2, - -1, 1.22465e-16, 9.4, - -1, 1.22465e-16, 9.6, - -1, 1.22465e-16, 9.8, - -1, 1.22465e-16, 10, - -1, 1.22465e-16, 10.2, - -1, 1.22465e-16, 10.4, - -1, 1.22465e-16, 10.6, - -1, 1.22465e-16, 10.8, - -1, 1.22465e-16, 11, - -0.866025, -0.5, 9, - -0.866025, -0.5, 9.2, - -0.866025, -0.5, 9.4, - -0.866025, -0.5, 9.6, - -0.866025, -0.5, 9.8, - -0.866025, -0.5, 10, - -0.866025, -0.5, 10.2, - -0.866025, -0.5, 10.4, - -0.866025, -0.5, 10.6, - -0.866025, -0.5, 10.8, - -0.866025, -0.5, 11, - -0.5, -0.866025, 9, - -0.5, -0.866025, 9.2, - -0.5, -0.866025, 9.4, - -0.5, -0.866025, 9.6, - -0.5, -0.866025, 9.8, - -0.5, -0.866025, 10, - -0.5, -0.866025, 10.2, - -0.5, -0.866025, 10.4, - -0.5, -0.866025, 10.6, - -0.5, -0.866025, 10.8, - -0.5, -0.866025, 11, - -1.83697e-16, -1, 9, - -1.83697e-16, -1, 9.2, - -1.83697e-16, -1, 9.4, - -1.83697e-16, -1, 9.6, - -1.83697e-16, -1, 9.8, - -1.83697e-16, -1, 10, - -1.83697e-16, -1, 10.2, - -1.83697e-16, -1, 10.4, - -1.83697e-16, -1, 10.6, - -1.83697e-16, -1, 10.8, - -1.83697e-16, -1, 11, - 0.5, -0.866025, 9, - 0.5, -0.866025, 9.2, - 0.5, -0.866025, 9.4, - 0.5, -0.866025, 9.6, - 0.5, -0.866025, 9.8, - 0.5, -0.866025, 10, - 0.5, -0.866025, 10.2, - 0.5, -0.866025, 10.4, - 0.5, -0.866025, 10.6, - 0.5, -0.866025, 10.8, - 0.5, -0.866025, 11, - 0.866025, -0.5, 9, - 0.866025, -0.5, 9.2, - 0.866025, -0.5, 9.4, - 0.866025, -0.5, 9.6, - 0.866025, -0.5, 9.8, - 0.866025, -0.5, 10, - 0.866025, -0.5, 10.2, - 0.866025, -0.5, 10.4, - 0.866025, -0.5, 10.6, - 0.866025, -0.5, 10.8, - 0.866025, -0.5, 11, - 0, 0, 9, - 0, 0, 11, - 1, 0, 19, - 1, 0, 19.2, - 1, 0, 19.4, - 1, 0, 19.6, - 1, 0, 19.8, - 1, 0, 20, - 1, 0, 20.2, - 1, 0, 20.4, - 1, 0, 20.6, - 1, 0, 20.8, - 1, 0, 21, - 0.866025, 0.5, 19, - 0.866025, 0.5, 19.2, - 0.866025, 0.5, 19.4, - 0.866025, 0.5, 19.6, - 0.866025, 0.5, 19.8, - 0.866025, 0.5, 20, - 0.866025, 0.5, 20.2, - 0.866025, 0.5, 20.4, - 0.866025, 0.5, 20.6, - 0.866025, 0.5, 20.8, - 0.866025, 0.5, 21, - 0.5, 0.866025, 19, - 0.5, 0.866025, 19.2, - 0.5, 0.866025, 19.4, - 0.5, 0.866025, 19.6, - 0.5, 0.866025, 19.8, - 0.5, 0.866025, 20, - 0.5, 0.866025, 20.2, - 0.5, 0.866025, 20.4, - 0.5, 0.866025, 20.6, - 0.5, 0.866025, 20.8, - 0.5, 0.866025, 21, - 6.12323e-17, 1, 19, - 6.12323e-17, 1, 19.2, - 6.12323e-17, 1, 19.4, - 6.12323e-17, 1, 19.6, - 6.12323e-17, 1, 19.8, - 6.12323e-17, 1, 20, - 6.12323e-17, 1, 20.2, - 6.12323e-17, 1, 20.4, - 6.12323e-17, 1, 20.6, - 6.12323e-17, 1, 20.8, - 6.12323e-17, 1, 21, - -0.5, 0.866025, 19, - -0.5, 0.866025, 19.2, - -0.5, 0.866025, 19.4, - -0.5, 0.866025, 19.6, - -0.5, 0.866025, 19.8, - -0.5, 0.866025, 20, - -0.5, 0.866025, 20.2, - -0.5, 0.866025, 20.4, - -0.5, 0.866025, 20.6, - -0.5, 0.866025, 20.8, - -0.5, 0.866025, 21, - -0.866025, 0.5, 19, - -0.866025, 0.5, 19.2, - -0.866025, 0.5, 19.4, - -0.866025, 0.5, 19.6, - -0.866025, 0.5, 19.8, - -0.866025, 0.5, 20, - -0.866025, 0.5, 20.2, - -0.866025, 0.5, 20.4, - -0.866025, 0.5, 20.6, - -0.866025, 0.5, 20.8, - -0.866025, 0.5, 21, - -1, 1.22465e-16, 19, - -1, 1.22465e-16, 19.2, - -1, 1.22465e-16, 19.4, - -1, 1.22465e-16, 19.6, - -1, 1.22465e-16, 19.8, - -1, 1.22465e-16, 20, - -1, 1.22465e-16, 20.2, - -1, 1.22465e-16, 20.4, - -1, 1.22465e-16, 20.6, - -1, 1.22465e-16, 20.8, - -1, 1.22465e-16, 21, - -0.866025, -0.5, 19, - -0.866025, -0.5, 19.2, - -0.866025, -0.5, 19.4, - -0.866025, -0.5, 19.6, - -0.866025, -0.5, 19.8, - -0.866025, -0.5, 20, - -0.866025, -0.5, 20.2, - -0.866025, -0.5, 20.4, - -0.866025, -0.5, 20.6, - -0.866025, -0.5, 20.8, - -0.866025, -0.5, 21, - -0.5, -0.866025, 19, - -0.5, -0.866025, 19.2, - -0.5, -0.866025, 19.4, - -0.5, -0.866025, 19.6, - -0.5, -0.866025, 19.8, - -0.5, -0.866025, 20, - -0.5, -0.866025, 20.2, - -0.5, -0.866025, 20.4, - -0.5, -0.866025, 20.6, - -0.5, -0.866025, 20.8, - -0.5, -0.866025, 21, - -1.83697e-16, -1, 19, - -1.83697e-16, -1, 19.2, - -1.83697e-16, -1, 19.4, - -1.83697e-16, -1, 19.6, - -1.83697e-16, -1, 19.8, - -1.83697e-16, -1, 20, - -1.83697e-16, -1, 20.2, - -1.83697e-16, -1, 20.4, - -1.83697e-16, -1, 20.6, - -1.83697e-16, -1, 20.8, - -1.83697e-16, -1, 21, - 0.5, -0.866025, 19, - 0.5, -0.866025, 19.2, - 0.5, -0.866025, 19.4, - 0.5, -0.866025, 19.6, - 0.5, -0.866025, 19.8, - 0.5, -0.866025, 20, - 0.5, -0.866025, 20.2, - 0.5, -0.866025, 20.4, - 0.5, -0.866025, 20.6, - 0.5, -0.866025, 20.8, - 0.5, -0.866025, 21, - 0.866025, -0.5, 19, - 0.866025, -0.5, 19.2, - 0.866025, -0.5, 19.4, - 0.866025, -0.5, 19.6, - 0.866025, -0.5, 19.8, - 0.866025, -0.5, 20, - 0.866025, -0.5, 20.2, - 0.866025, -0.5, 20.4, - 0.866025, -0.5, 20.6, - 0.866025, -0.5, 20.8, - 0.866025, -0.5, 21, - 0, 0, 19, - 0, 0, 21, - 1, 0, 29, - 1, 0, 29.2, - 1, 0, 29.4, - 1, 0, 29.6, - 1, 0, 29.8, - 1, 0, 30, - 1, 0, 30.2, - 1, 0, 30.4, - 1, 0, 30.6, - 1, 0, 30.8, - 1, 0, 31, - 0.866025, 0.5, 29, - 0.866025, 0.5, 29.2, - 0.866025, 0.5, 29.4, - 0.866025, 0.5, 29.6, - 0.866025, 0.5, 29.8, - 0.866025, 0.5, 30, - 0.866025, 0.5, 30.2, - 0.866025, 0.5, 30.4, - 0.866025, 0.5, 30.6, - 0.866025, 0.5, 30.8, - 0.866025, 0.5, 31, - 0.5, 0.866025, 29, - 0.5, 0.866025, 29.2, - 0.5, 0.866025, 29.4, - 0.5, 0.866025, 29.6, - 0.5, 0.866025, 29.8, - 0.5, 0.866025, 30, - 0.5, 0.866025, 30.2, - 0.5, 0.866025, 30.4, - 0.5, 0.866025, 30.6, - 0.5, 0.866025, 30.8, - 0.5, 0.866025, 31, - 6.12323e-17, 1, 29, - 6.12323e-17, 1, 29.2, - 6.12323e-17, 1, 29.4, - 6.12323e-17, 1, 29.6, - 6.12323e-17, 1, 29.8, - 6.12323e-17, 1, 30, - 6.12323e-17, 1, 30.2, - 6.12323e-17, 1, 30.4, - 6.12323e-17, 1, 30.6, - 6.12323e-17, 1, 30.8, - 6.12323e-17, 1, 31, - -0.5, 0.866025, 29, - -0.5, 0.866025, 29.2, - -0.5, 0.866025, 29.4, - -0.5, 0.866025, 29.6, - -0.5, 0.866025, 29.8, - -0.5, 0.866025, 30, - -0.5, 0.866025, 30.2, - -0.5, 0.866025, 30.4, - -0.5, 0.866025, 30.6, - -0.5, 0.866025, 30.8, - -0.5, 0.866025, 31, - -0.866025, 0.5, 29, - -0.866025, 0.5, 29.2, - -0.866025, 0.5, 29.4, - -0.866025, 0.5, 29.6, - -0.866025, 0.5, 29.8, - -0.866025, 0.5, 30, - -0.866025, 0.5, 30.2, - -0.866025, 0.5, 30.4, - -0.866025, 0.5, 30.6, - -0.866025, 0.5, 30.8, - -0.866025, 0.5, 31, - -1, 1.22465e-16, 29, - -1, 1.22465e-16, 29.2, - -1, 1.22465e-16, 29.4, - -1, 1.22465e-16, 29.6, - -1, 1.22465e-16, 29.8, - -1, 1.22465e-16, 30, - -1, 1.22465e-16, 30.2, - -1, 1.22465e-16, 30.4, - -1, 1.22465e-16, 30.6, - -1, 1.22465e-16, 30.8, - -1, 1.22465e-16, 31, - -0.866025, -0.5, 29, - -0.866025, -0.5, 29.2, - -0.866025, -0.5, 29.4, - -0.866025, -0.5, 29.6, - -0.866025, -0.5, 29.8, - -0.866025, -0.5, 30, - -0.866025, -0.5, 30.2, - -0.866025, -0.5, 30.4, - -0.866025, -0.5, 30.6, - -0.866025, -0.5, 30.8, - -0.866025, -0.5, 31, - -0.5, -0.866025, 29, - -0.5, -0.866025, 29.2, - -0.5, -0.866025, 29.4, - -0.5, -0.866025, 29.6, - -0.5, -0.866025, 29.8, - -0.5, -0.866025, 30, - -0.5, -0.866025, 30.2, - -0.5, -0.866025, 30.4, - -0.5, -0.866025, 30.6, - -0.5, -0.866025, 30.8, - -0.5, -0.866025, 31, - -1.83697e-16, -1, 29, - -1.83697e-16, -1, 29.2, - -1.83697e-16, -1, 29.4, - -1.83697e-16, -1, 29.6, - -1.83697e-16, -1, 29.8, - -1.83697e-16, -1, 30, - -1.83697e-16, -1, 30.2, - -1.83697e-16, -1, 30.4, - -1.83697e-16, -1, 30.6, - -1.83697e-16, -1, 30.8, - -1.83697e-16, -1, 31, - 0.5, -0.866025, 29, - 0.5, -0.866025, 29.2, - 0.5, -0.866025, 29.4, - 0.5, -0.866025, 29.6, - 0.5, -0.866025, 29.8, - 0.5, -0.866025, 30, - 0.5, -0.866025, 30.2, - 0.5, -0.866025, 30.4, - 0.5, -0.866025, 30.6, - 0.5, -0.866025, 30.8, - 0.5, -0.866025, 31, - 0.866025, -0.5, 29, - 0.866025, -0.5, 29.2, - 0.866025, -0.5, 29.4, - 0.866025, -0.5, 29.6, - 0.866025, -0.5, 29.8, - 0.866025, -0.5, 30, - 0.866025, -0.5, 30.2, - 0.866025, -0.5, 30.4, - 0.866025, -0.5, 30.6, - 0.866025, -0.5, 30.8, - 0.866025, -0.5, 31, - 0, 0, 29, - 0, 0, 31 -}; -static const unsigned some_triangles_triangles_count = 1056; -static const unsigned some_triangles_triangles[3168] = -{ - 0, 1, 11, - 11, 1, 12, - 1, 2, 12, - 12, 2, 13, - 2, 3, 13, - 13, 3, 14, - 3, 4, 14, - 14, 4, 15, - 4, 5, 15, - 15, 5, 16, - 5, 6, 16, - 16, 6, 17, - 6, 7, 17, - 17, 7, 18, - 7, 8, 18, - 18, 8, 19, - 8, 9, 19, - 19, 9, 20, - 9, 10, 20, - 20, 10, 21, - 11, 12, 22, - 22, 12, 23, - 12, 13, 23, - 23, 13, 24, - 13, 14, 24, - 24, 14, 25, - 14, 15, 25, - 25, 15, 26, - 15, 16, 26, - 26, 16, 27, - 16, 17, 27, - 27, 17, 28, - 17, 18, 28, - 28, 18, 29, - 18, 19, 29, - 29, 19, 30, - 19, 20, 30, - 30, 20, 31, - 20, 21, 31, - 31, 21, 32, - 22, 23, 33, - 33, 23, 34, - 23, 24, 34, - 34, 24, 35, - 24, 25, 35, - 35, 25, 36, - 25, 26, 36, - 36, 26, 37, - 26, 27, 37, - 37, 27, 38, - 27, 28, 38, - 38, 28, 39, - 28, 29, 39, - 39, 29, 40, - 29, 30, 40, - 40, 30, 41, - 30, 31, 41, - 41, 31, 42, - 31, 32, 42, - 42, 32, 43, - 33, 34, 44, - 44, 34, 45, - 34, 35, 45, - 45, 35, 46, - 35, 36, 46, - 46, 36, 47, - 36, 37, 47, - 47, 37, 48, - 37, 38, 48, - 48, 38, 49, - 38, 39, 49, - 49, 39, 50, - 39, 40, 50, - 50, 40, 51, - 40, 41, 51, - 51, 41, 52, - 41, 42, 52, - 52, 42, 53, - 42, 43, 53, - 53, 43, 54, - 44, 45, 55, - 55, 45, 56, - 45, 46, 56, - 56, 46, 57, - 46, 47, 57, - 57, 47, 58, - 47, 48, 58, - 58, 48, 59, - 48, 49, 59, - 59, 49, 60, - 49, 50, 60, - 60, 50, 61, - 50, 51, 61, - 61, 51, 62, - 51, 52, 62, - 62, 52, 63, - 52, 53, 63, - 63, 53, 64, - 53, 54, 64, - 64, 54, 65, - 55, 56, 66, - 66, 56, 67, - 56, 57, 67, - 67, 57, 68, - 57, 58, 68, - 68, 58, 69, - 58, 59, 69, - 69, 59, 70, - 59, 60, 70, - 70, 60, 71, - 60, 61, 71, - 71, 61, 72, - 61, 62, 72, - 72, 62, 73, - 62, 63, 73, - 73, 63, 74, - 63, 64, 74, - 74, 64, 75, - 64, 65, 75, - 75, 65, 76, - 66, 67, 77, - 77, 67, 78, - 67, 68, 78, - 78, 68, 79, - 68, 69, 79, - 79, 69, 80, - 69, 70, 80, - 80, 70, 81, - 70, 71, 81, - 81, 71, 82, - 71, 72, 82, - 82, 72, 83, - 72, 73, 83, - 83, 73, 84, - 73, 74, 84, - 84, 74, 85, - 74, 75, 85, - 85, 75, 86, - 75, 76, 86, - 86, 76, 87, - 77, 78, 88, - 88, 78, 89, - 78, 79, 89, - 89, 79, 90, - 79, 80, 90, - 90, 80, 91, - 80, 81, 91, - 91, 81, 92, - 81, 82, 92, - 92, 82, 93, - 82, 83, 93, - 93, 83, 94, - 83, 84, 94, - 94, 84, 95, - 84, 85, 95, - 95, 85, 96, - 85, 86, 96, - 96, 86, 97, - 86, 87, 97, - 97, 87, 98, - 88, 89, 99, - 99, 89, 100, - 89, 90, 100, - 100, 90, 101, - 90, 91, 101, - 101, 91, 102, - 91, 92, 102, - 102, 92, 103, - 92, 93, 103, - 103, 93, 104, - 93, 94, 104, - 104, 94, 105, - 94, 95, 105, - 105, 95, 106, - 95, 96, 106, - 106, 96, 107, - 96, 97, 107, - 107, 97, 108, - 97, 98, 108, - 108, 98, 109, - 99, 100, 110, - 110, 100, 111, - 100, 101, 111, - 111, 101, 112, - 101, 102, 112, - 112, 102, 113, - 102, 103, 113, - 113, 103, 114, - 103, 104, 114, - 114, 104, 115, - 104, 105, 115, - 115, 105, 116, - 105, 106, 116, - 116, 106, 117, - 106, 107, 117, - 117, 107, 118, - 107, 108, 118, - 118, 108, 119, - 108, 109, 119, - 119, 109, 120, - 110, 111, 121, - 121, 111, 122, - 111, 112, 122, - 122, 112, 123, - 112, 113, 123, - 123, 113, 124, - 113, 114, 124, - 124, 114, 125, - 114, 115, 125, - 125, 115, 126, - 115, 116, 126, - 126, 116, 127, - 116, 117, 127, - 127, 117, 128, - 117, 118, 128, - 128, 118, 129, - 118, 119, 129, - 129, 119, 130, - 119, 120, 130, - 130, 120, 131, - 121, 122, 0, - 0, 122, 1, - 122, 123, 1, - 1, 123, 2, - 123, 124, 2, - 2, 124, 3, - 124, 125, 3, - 3, 125, 4, - 125, 126, 4, - 4, 126, 5, - 126, 127, 5, - 5, 127, 6, - 127, 128, 6, - 6, 128, 7, - 128, 129, 7, - 7, 129, 8, - 129, 130, 8, - 8, 130, 9, - 130, 131, 9, - 9, 131, 10, - 132, 0, 11, - 132, 11, 22, - 132, 22, 33, - 132, 33, 44, - 132, 44, 55, - 132, 55, 66, - 132, 66, 77, - 132, 77, 88, - 132, 88, 99, - 132, 99, 110, - 132, 110, 121, - 132, 121, 0, - 133, 21, 10, - 133, 32, 21, - 133, 43, 32, - 133, 54, 43, - 133, 65, 54, - 133, 76, 65, - 133, 87, 76, - 133, 98, 87, - 133, 109, 98, - 133, 120, 109, - 133, 131, 120, - 133, 10, 131, - 134, 135, 145, - 145, 135, 146, - 135, 136, 146, - 146, 136, 147, - 136, 137, 147, - 147, 137, 148, - 137, 138, 148, - 148, 138, 149, - 138, 139, 149, - 149, 139, 150, - 139, 140, 150, - 150, 140, 151, - 140, 141, 151, - 151, 141, 152, - 141, 142, 152, - 152, 142, 153, - 142, 143, 153, - 153, 143, 154, - 143, 144, 154, - 154, 144, 155, - 145, 146, 156, - 156, 146, 157, - 146, 147, 157, - 157, 147, 158, - 147, 148, 158, - 158, 148, 159, - 148, 149, 159, - 159, 149, 160, - 149, 150, 160, - 160, 150, 161, - 150, 151, 161, - 161, 151, 162, - 151, 152, 162, - 162, 152, 163, - 152, 153, 163, - 163, 153, 164, - 153, 154, 164, - 164, 154, 165, - 154, 155, 165, - 165, 155, 166, - 156, 157, 167, - 167, 157, 168, - 157, 158, 168, - 168, 158, 169, - 158, 159, 169, - 169, 159, 170, - 159, 160, 170, - 170, 160, 171, - 160, 161, 171, - 171, 161, 172, - 161, 162, 172, - 172, 162, 173, - 162, 163, 173, - 173, 163, 174, - 163, 164, 174, - 174, 164, 175, - 164, 165, 175, - 175, 165, 176, - 165, 166, 176, - 176, 166, 177, - 167, 168, 178, - 178, 168, 179, - 168, 169, 179, - 179, 169, 180, - 169, 170, 180, - 180, 170, 181, - 170, 171, 181, - 181, 171, 182, - 171, 172, 182, - 182, 172, 183, - 172, 173, 183, - 183, 173, 184, - 173, 174, 184, - 184, 174, 185, - 174, 175, 185, - 185, 175, 186, - 175, 176, 186, - 186, 176, 187, - 176, 177, 187, - 187, 177, 188, - 178, 179, 189, - 189, 179, 190, - 179, 180, 190, - 190, 180, 191, - 180, 181, 191, - 191, 181, 192, - 181, 182, 192, - 192, 182, 193, - 182, 183, 193, - 193, 183, 194, - 183, 184, 194, - 194, 184, 195, - 184, 185, 195, - 195, 185, 196, - 185, 186, 196, - 196, 186, 197, - 186, 187, 197, - 197, 187, 198, - 187, 188, 198, - 198, 188, 199, - 189, 190, 200, - 200, 190, 201, - 190, 191, 201, - 201, 191, 202, - 191, 192, 202, - 202, 192, 203, - 192, 193, 203, - 203, 193, 204, - 193, 194, 204, - 204, 194, 205, - 194, 195, 205, - 205, 195, 206, - 195, 196, 206, - 206, 196, 207, - 196, 197, 207, - 207, 197, 208, - 197, 198, 208, - 208, 198, 209, - 198, 199, 209, - 209, 199, 210, - 200, 201, 211, - 211, 201, 212, - 201, 202, 212, - 212, 202, 213, - 202, 203, 213, - 213, 203, 214, - 203, 204, 214, - 214, 204, 215, - 204, 205, 215, - 215, 205, 216, - 205, 206, 216, - 216, 206, 217, - 206, 207, 217, - 217, 207, 218, - 207, 208, 218, - 218, 208, 219, - 208, 209, 219, - 219, 209, 220, - 209, 210, 220, - 220, 210, 221, - 211, 212, 222, - 222, 212, 223, - 212, 213, 223, - 223, 213, 224, - 213, 214, 224, - 224, 214, 225, - 214, 215, 225, - 225, 215, 226, - 215, 216, 226, - 226, 216, 227, - 216, 217, 227, - 227, 217, 228, - 217, 218, 228, - 228, 218, 229, - 218, 219, 229, - 229, 219, 230, - 219, 220, 230, - 230, 220, 231, - 220, 221, 231, - 231, 221, 232, - 222, 223, 233, - 233, 223, 234, - 223, 224, 234, - 234, 224, 235, - 224, 225, 235, - 235, 225, 236, - 225, 226, 236, - 236, 226, 237, - 226, 227, 237, - 237, 227, 238, - 227, 228, 238, - 238, 228, 239, - 228, 229, 239, - 239, 229, 240, - 229, 230, 240, - 240, 230, 241, - 230, 231, 241, - 241, 231, 242, - 231, 232, 242, - 242, 232, 243, - 233, 234, 244, - 244, 234, 245, - 234, 235, 245, - 245, 235, 246, - 235, 236, 246, - 246, 236, 247, - 236, 237, 247, - 247, 237, 248, - 237, 238, 248, - 248, 238, 249, - 238, 239, 249, - 249, 239, 250, - 239, 240, 250, - 250, 240, 251, - 240, 241, 251, - 251, 241, 252, - 241, 242, 252, - 252, 242, 253, - 242, 243, 253, - 253, 243, 254, - 244, 245, 255, - 255, 245, 256, - 245, 246, 256, - 256, 246, 257, - 246, 247, 257, - 257, 247, 258, - 247, 248, 258, - 258, 248, 259, - 248, 249, 259, - 259, 249, 260, - 249, 250, 260, - 260, 250, 261, - 250, 251, 261, - 261, 251, 262, - 251, 252, 262, - 262, 252, 263, - 252, 253, 263, - 263, 253, 264, - 253, 254, 264, - 264, 254, 265, - 255, 256, 134, - 134, 256, 135, - 256, 257, 135, - 135, 257, 136, - 257, 258, 136, - 136, 258, 137, - 258, 259, 137, - 137, 259, 138, - 259, 260, 138, - 138, 260, 139, - 260, 261, 139, - 139, 261, 140, - 261, 262, 140, - 140, 262, 141, - 262, 263, 141, - 141, 263, 142, - 263, 264, 142, - 142, 264, 143, - 264, 265, 143, - 143, 265, 144, - 266, 134, 145, - 266, 145, 156, - 266, 156, 167, - 266, 167, 178, - 266, 178, 189, - 266, 189, 200, - 266, 200, 211, - 266, 211, 222, - 266, 222, 233, - 266, 233, 244, - 266, 244, 255, - 266, 255, 134, - 267, 155, 144, - 267, 166, 155, - 267, 177, 166, - 267, 188, 177, - 267, 199, 188, - 267, 210, 199, - 267, 221, 210, - 267, 232, 221, - 267, 243, 232, - 267, 254, 243, - 267, 265, 254, - 267, 144, 265, - 268, 269, 279, - 279, 269, 280, - 269, 270, 280, - 280, 270, 281, - 270, 271, 281, - 281, 271, 282, - 271, 272, 282, - 282, 272, 283, - 272, 273, 283, - 283, 273, 284, - 273, 274, 284, - 284, 274, 285, - 274, 275, 285, - 285, 275, 286, - 275, 276, 286, - 286, 276, 287, - 276, 277, 287, - 287, 277, 288, - 277, 278, 288, - 288, 278, 289, - 279, 280, 290, - 290, 280, 291, - 280, 281, 291, - 291, 281, 292, - 281, 282, 292, - 292, 282, 293, - 282, 283, 293, - 293, 283, 294, - 283, 284, 294, - 294, 284, 295, - 284, 285, 295, - 295, 285, 296, - 285, 286, 296, - 296, 286, 297, - 286, 287, 297, - 297, 287, 298, - 287, 288, 298, - 298, 288, 299, - 288, 289, 299, - 299, 289, 300, - 290, 291, 301, - 301, 291, 302, - 291, 292, 302, - 302, 292, 303, - 292, 293, 303, - 303, 293, 304, - 293, 294, 304, - 304, 294, 305, - 294, 295, 305, - 305, 295, 306, - 295, 296, 306, - 306, 296, 307, - 296, 297, 307, - 307, 297, 308, - 297, 298, 308, - 308, 298, 309, - 298, 299, 309, - 309, 299, 310, - 299, 300, 310, - 310, 300, 311, - 301, 302, 312, - 312, 302, 313, - 302, 303, 313, - 313, 303, 314, - 303, 304, 314, - 314, 304, 315, - 304, 305, 315, - 315, 305, 316, - 305, 306, 316, - 316, 306, 317, - 306, 307, 317, - 317, 307, 318, - 307, 308, 318, - 318, 308, 319, - 308, 309, 319, - 319, 309, 320, - 309, 310, 320, - 320, 310, 321, - 310, 311, 321, - 321, 311, 322, - 312, 313, 323, - 323, 313, 324, - 313, 314, 324, - 324, 314, 325, - 314, 315, 325, - 325, 315, 326, - 315, 316, 326, - 326, 316, 327, - 316, 317, 327, - 327, 317, 328, - 317, 318, 328, - 328, 318, 329, - 318, 319, 329, - 329, 319, 330, - 319, 320, 330, - 330, 320, 331, - 320, 321, 331, - 331, 321, 332, - 321, 322, 332, - 332, 322, 333, - 323, 324, 334, - 334, 324, 335, - 324, 325, 335, - 335, 325, 336, - 325, 326, 336, - 336, 326, 337, - 326, 327, 337, - 337, 327, 338, - 327, 328, 338, - 338, 328, 339, - 328, 329, 339, - 339, 329, 340, - 329, 330, 340, - 340, 330, 341, - 330, 331, 341, - 341, 331, 342, - 331, 332, 342, - 342, 332, 343, - 332, 333, 343, - 343, 333, 344, - 334, 335, 345, - 345, 335, 346, - 335, 336, 346, - 346, 336, 347, - 336, 337, 347, - 347, 337, 348, - 337, 338, 348, - 348, 338, 349, - 338, 339, 349, - 349, 339, 350, - 339, 340, 350, - 350, 340, 351, - 340, 341, 351, - 351, 341, 352, - 341, 342, 352, - 352, 342, 353, - 342, 343, 353, - 353, 343, 354, - 343, 344, 354, - 354, 344, 355, - 345, 346, 356, - 356, 346, 357, - 346, 347, 357, - 357, 347, 358, - 347, 348, 358, - 358, 348, 359, - 348, 349, 359, - 359, 349, 360, - 349, 350, 360, - 360, 350, 361, - 350, 351, 361, - 361, 351, 362, - 351, 352, 362, - 362, 352, 363, - 352, 353, 363, - 363, 353, 364, - 353, 354, 364, - 364, 354, 365, - 354, 355, 365, - 365, 355, 366, - 356, 357, 367, - 367, 357, 368, - 357, 358, 368, - 368, 358, 369, - 358, 359, 369, - 369, 359, 370, - 359, 360, 370, - 370, 360, 371, - 360, 361, 371, - 371, 361, 372, - 361, 362, 372, - 372, 362, 373, - 362, 363, 373, - 373, 363, 374, - 363, 364, 374, - 374, 364, 375, - 364, 365, 375, - 375, 365, 376, - 365, 366, 376, - 376, 366, 377, - 367, 368, 378, - 378, 368, 379, - 368, 369, 379, - 379, 369, 380, - 369, 370, 380, - 380, 370, 381, - 370, 371, 381, - 381, 371, 382, - 371, 372, 382, - 382, 372, 383, - 372, 373, 383, - 383, 373, 384, - 373, 374, 384, - 384, 374, 385, - 374, 375, 385, - 385, 375, 386, - 375, 376, 386, - 386, 376, 387, - 376, 377, 387, - 387, 377, 388, - 378, 379, 389, - 389, 379, 390, - 379, 380, 390, - 390, 380, 391, - 380, 381, 391, - 391, 381, 392, - 381, 382, 392, - 392, 382, 393, - 382, 383, 393, - 393, 383, 394, - 383, 384, 394, - 394, 384, 395, - 384, 385, 395, - 395, 385, 396, - 385, 386, 396, - 396, 386, 397, - 386, 387, 397, - 397, 387, 398, - 387, 388, 398, - 398, 388, 399, - 389, 390, 268, - 268, 390, 269, - 390, 391, 269, - 269, 391, 270, - 391, 392, 270, - 270, 392, 271, - 392, 393, 271, - 271, 393, 272, - 393, 394, 272, - 272, 394, 273, - 394, 395, 273, - 273, 395, 274, - 395, 396, 274, - 274, 396, 275, - 396, 397, 275, - 275, 397, 276, - 397, 398, 276, - 276, 398, 277, - 398, 399, 277, - 277, 399, 278, - 400, 268, 279, - 400, 279, 290, - 400, 290, 301, - 400, 301, 312, - 400, 312, 323, - 400, 323, 334, - 400, 334, 345, - 400, 345, 356, - 400, 356, 367, - 400, 367, 378, - 400, 378, 389, - 400, 389, 268, - 401, 289, 278, - 401, 300, 289, - 401, 311, 300, - 401, 322, 311, - 401, 333, 322, - 401, 344, 333, - 401, 355, 344, - 401, 366, 355, - 401, 377, 366, - 401, 388, 377, - 401, 399, 388, - 401, 278, 399, - 402, 403, 413, - 413, 403, 414, - 403, 404, 414, - 414, 404, 415, - 404, 405, 415, - 415, 405, 416, - 405, 406, 416, - 416, 406, 417, - 406, 407, 417, - 417, 407, 418, - 407, 408, 418, - 418, 408, 419, - 408, 409, 419, - 419, 409, 420, - 409, 410, 420, - 420, 410, 421, - 410, 411, 421, - 421, 411, 422, - 411, 412, 422, - 422, 412, 423, - 413, 414, 424, - 424, 414, 425, - 414, 415, 425, - 425, 415, 426, - 415, 416, 426, - 426, 416, 427, - 416, 417, 427, - 427, 417, 428, - 417, 418, 428, - 428, 418, 429, - 418, 419, 429, - 429, 419, 430, - 419, 420, 430, - 430, 420, 431, - 420, 421, 431, - 431, 421, 432, - 421, 422, 432, - 432, 422, 433, - 422, 423, 433, - 433, 423, 434, - 424, 425, 435, - 435, 425, 436, - 425, 426, 436, - 436, 426, 437, - 426, 427, 437, - 437, 427, 438, - 427, 428, 438, - 438, 428, 439, - 428, 429, 439, - 439, 429, 440, - 429, 430, 440, - 440, 430, 441, - 430, 431, 441, - 441, 431, 442, - 431, 432, 442, - 442, 432, 443, - 432, 433, 443, - 443, 433, 444, - 433, 434, 444, - 444, 434, 445, - 435, 436, 446, - 446, 436, 447, - 436, 437, 447, - 447, 437, 448, - 437, 438, 448, - 448, 438, 449, - 438, 439, 449, - 449, 439, 450, - 439, 440, 450, - 450, 440, 451, - 440, 441, 451, - 451, 441, 452, - 441, 442, 452, - 452, 442, 453, - 442, 443, 453, - 453, 443, 454, - 443, 444, 454, - 454, 444, 455, - 444, 445, 455, - 455, 445, 456, - 446, 447, 457, - 457, 447, 458, - 447, 448, 458, - 458, 448, 459, - 448, 449, 459, - 459, 449, 460, - 449, 450, 460, - 460, 450, 461, - 450, 451, 461, - 461, 451, 462, - 451, 452, 462, - 462, 452, 463, - 452, 453, 463, - 463, 453, 464, - 453, 454, 464, - 464, 454, 465, - 454, 455, 465, - 465, 455, 466, - 455, 456, 466, - 466, 456, 467, - 457, 458, 468, - 468, 458, 469, - 458, 459, 469, - 469, 459, 470, - 459, 460, 470, - 470, 460, 471, - 460, 461, 471, - 471, 461, 472, - 461, 462, 472, - 472, 462, 473, - 462, 463, 473, - 473, 463, 474, - 463, 464, 474, - 474, 464, 475, - 464, 465, 475, - 475, 465, 476, - 465, 466, 476, - 476, 466, 477, - 466, 467, 477, - 477, 467, 478, - 468, 469, 479, - 479, 469, 480, - 469, 470, 480, - 480, 470, 481, - 470, 471, 481, - 481, 471, 482, - 471, 472, 482, - 482, 472, 483, - 472, 473, 483, - 483, 473, 484, - 473, 474, 484, - 484, 474, 485, - 474, 475, 485, - 485, 475, 486, - 475, 476, 486, - 486, 476, 487, - 476, 477, 487, - 487, 477, 488, - 477, 478, 488, - 488, 478, 489, - 479, 480, 490, - 490, 480, 491, - 480, 481, 491, - 491, 481, 492, - 481, 482, 492, - 492, 482, 493, - 482, 483, 493, - 493, 483, 494, - 483, 484, 494, - 494, 484, 495, - 484, 485, 495, - 495, 485, 496, - 485, 486, 496, - 496, 486, 497, - 486, 487, 497, - 497, 487, 498, - 487, 488, 498, - 498, 488, 499, - 488, 489, 499, - 499, 489, 500, - 490, 491, 501, - 501, 491, 502, - 491, 492, 502, - 502, 492, 503, - 492, 493, 503, - 503, 493, 504, - 493, 494, 504, - 504, 494, 505, - 494, 495, 505, - 505, 495, 506, - 495, 496, 506, - 506, 496, 507, - 496, 497, 507, - 507, 497, 508, - 497, 498, 508, - 508, 498, 509, - 498, 499, 509, - 509, 499, 510, - 499, 500, 510, - 510, 500, 511, - 501, 502, 512, - 512, 502, 513, - 502, 503, 513, - 513, 503, 514, - 503, 504, 514, - 514, 504, 515, - 504, 505, 515, - 515, 505, 516, - 505, 506, 516, - 516, 506, 517, - 506, 507, 517, - 517, 507, 518, - 507, 508, 518, - 518, 508, 519, - 508, 509, 519, - 519, 509, 520, - 509, 510, 520, - 520, 510, 521, - 510, 511, 521, - 521, 511, 522, - 512, 513, 523, - 523, 513, 524, - 513, 514, 524, - 524, 514, 525, - 514, 515, 525, - 525, 515, 526, - 515, 516, 526, - 526, 516, 527, - 516, 517, 527, - 527, 517, 528, - 517, 518, 528, - 528, 518, 529, - 518, 519, 529, - 529, 519, 530, - 519, 520, 530, - 530, 520, 531, - 520, 521, 531, - 531, 521, 532, - 521, 522, 532, - 532, 522, 533, - 523, 524, 402, - 402, 524, 403, - 524, 525, 403, - 403, 525, 404, - 525, 526, 404, - 404, 526, 405, - 526, 527, 405, - 405, 527, 406, - 527, 528, 406, - 406, 528, 407, - 528, 529, 407, - 407, 529, 408, - 529, 530, 408, - 408, 530, 409, - 530, 531, 409, - 409, 531, 410, - 531, 532, 410, - 410, 532, 411, - 532, 533, 411, - 411, 533, 412, - 534, 402, 413, - 534, 413, 424, - 534, 424, 435, - 534, 435, 446, - 534, 446, 457, - 534, 457, 468, - 534, 468, 479, - 534, 479, 490, - 534, 490, 501, - 534, 501, 512, - 534, 512, 523, - 534, 523, 402, - 535, 423, 412, - 535, 434, 423, - 535, 445, 434, - 535, 456, 445, - 535, 467, 456, - 535, 478, 467, - 535, 489, 478, - 535, 500, 489, - 535, 511, 500, - 535, 522, 511, - 535, 533, 522, - 535, 412, 533 -}; -static const unsigned some_triangles_properties[3168] = -{ - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 2, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0, - 3, 0, 0 -}; - -#define NB_CYL 4 -#define CYL_VRTX_COUNT 134u -#define CYL_TRG_COUNT 264u - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct context ctx = CONTEXT_NULL__; - unsigned e, count; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* Create a scene */ - ctx.positions = some_triangles_vertices; - ctx.indices = some_triangles_triangles; - ctx.properties = some_triangles_properties; - OK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, - some_triangles_triangles_count, get_indices, get_media_from_properties, - some_triangles_vertices_count, get_position, &ctx, &scn)); - - OK(senc_scene_get_vertices_count(scn, &count)); - CHK(count == NB_CYL * CYL_VRTX_COUNT); - OK(senc_scene_get_triangles_count(scn, &count)); - CHK(count == NB_CYL * CYL_TRG_COUNT); - - OK(senc_scene_get_enclosure_count(scn, &count)); - CHK(count == 1 + NB_CYL); - FOR_EACH(e, 0, count) { - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - OK(senc_scene_get_enclosure(scn, e, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - CHK(header.primitives_count == - (e ? CYL_TRG_COUNT : NB_CYL * CYL_TRG_COUNT)); - OK(senc_enclosure_ref_put(enclosure)); - } - - OK(senc_scene_ref_put(scn)); - OK(senc_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_senc_unspecified_medium.c b/src/test_senc_unspecified_medium.c @@ -1,327 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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/>. */ - -/* This test has been created using the sg3_geometry_dump_as_C_code feature - * of star-geometry. It uses output from test_sg3_unspecified_properties. - * This test is similar to test_senc_many_enclosures that creates a huge - * geometry by program. */ - -#include "senc.h" -#include "senc_s3d_helper.h" -#include "test_senc_utils.h" - -#include <rsys/double3.h> - -#define SG3_UNSPECIFED_PROPERTY UINT_MAX - -/* Dump of star-geometry 'front_unspecified'. */ -static const unsigned front_unspecified_vertices_count = 8; -static const double front_unspecified_vertices[24] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1 -}; -static const unsigned front_unspecified_triangles_count = 12; -static const unsigned front_unspecified_triangles[36] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5 -}; -static const unsigned front_unspecified_properties[36] = -{ - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY -}; -/* Dump of star-geometry 'front_half_unspecified'. */ -static const unsigned front_half_unspecified_vertices_count = 8; -static const double front_half_unspecified_vertices[24] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1 -}; -static const unsigned front_half_unspecified_triangles_count = 12; -static const unsigned front_half_unspecified_triangles[36] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5 -}; -static const unsigned front_half_unspecified_properties[36] = -{ - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - 0, 1, 0, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - 0, 1, 0, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - 0, 1, 0, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - 0, 1, 0, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - 0, 1, 0, - SG3_UNSPECIFED_PROPERTY, 1, SG3_UNSPECIFED_PROPERTY, - 0, 1, 0 -}; -/* Dump of star-geometry 'all_defined'. */ -static const unsigned all_defined_vertices_count = 8; -static const double all_defined_vertices[24] = -{ - 0.1, 0, 0, - 1, 0, 0, - 0, 1, 0, - 1, 1, 0, - 0, 0, 1.1, - 1, 0, 1, - 0, 1, 1, - 1, 1.1, 1 -}; -static const unsigned all_defined_triangles_count = 12; -static const unsigned all_defined_triangles[36] = -{ - 0, 2, 1, - 1, 2, 3, - 0, 4, 2, - 2, 4, 6, - 4, 5, 6, - 6, 5, 7, - 3, 7, 1, - 1, 7, 5, - 2, 6, 3, - 3, 6, 7, - 0, 1, 4, - 4, 1, 5 -}; -static const unsigned all_defined_properties[36] = -{ - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0, - 0, 1, 0 -}; - -static void -test(const int convention) -{ - struct mem_allocator allocator; - struct senc_device* dev = NULL; - struct senc_scene* scn = NULL; - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - unsigned medium, expected_external_medium, expected_internal_medium; - unsigned gid; - enum senc_side side; - struct context ctx = CONTEXT_NULL__; - unsigned i, t, ecount; - const int conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)); - - /* Geometry with no media information on both sides */ - ctx.positions = front_unspecified_vertices; - ctx.indices = front_unspecified_triangles; - ctx.properties = front_unspecified_properties; - OK(senc_scene_create(dev, convention, front_unspecified_triangles_count, - get_indices, get_media_from_properties, front_unspecified_vertices_count, - get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - struct senc_enclosure* ee; - struct senc_enclosure_header hh; - unsigned cc; - OK(senc_scene_get_enclosure(scn, i, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - - OK(senc_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input triangles: - * if convention is front, front medium (unspecified) is outside, - * that is medium 0's enclosure is infinite */ - expected_external_medium = conv_front ? SENC_UNSPECIFIED_MEDIUM : 1; - expected_internal_medium = conv_front ? 1 : SENC_UNSPECIFIED_MEDIUM; - - CHK(medium == (header.is_infinite - ? expected_external_medium : expected_internal_medium)); - CHK(header.primitives_count == ntriangles); - CHK(header.unique_primitives_count == ntriangles); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - OK(senc_scene_get_enclosure_count_by_medium(scn, medium, &cc)); - CHK(cc == 1); - OK(senc_scene_get_enclosure_by_medium(scn, medium, 0, &ee)); - OK(senc_enclosure_get_header(ee, &hh)); - CHK(header.enclosure_id == hh.enclosure_id); - OK(senc_enclosure_ref_put(ee)); - - FOR_EACH(t, 0, header.primitives_count) { - unsigned ind[3]; - OK(senc_enclosure_get_triangle_id(enclosure, t, &gid, &side)); - CHK(gid == t); - CHK(side == (medium == 1) ? SENC_BACK : SENC_FRONT); - OK(senc_enclosure_get_triangle(enclosure, t, ind)); - } - OK(senc_enclosure_ref_put(enclosure)); - } - OK(senc_scene_ref_put(scn)); - - /* Same geometry, front media are defined for odd triangles */ - ctx.positions = front_half_unspecified_vertices; - ctx.indices = front_half_unspecified_triangles; - ctx.properties = front_half_unspecified_properties; - OK(senc_scene_create(dev, convention, front_half_unspecified_triangles_count, - get_indices, get_media_from_properties, front_half_unspecified_vertices_count, - get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - unsigned expected_external_media_count, expected_internal_media_count, - expected_media_count; - OK(senc_scene_get_enclosure(scn, i, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - - OK(senc_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input triangles: - * if convention is front, front medium is outside and the enclosure - * contains 2 media */ - expected_external_media_count = conv_front ? 2 : 1; - expected_internal_media_count = conv_front ? 1 : 2; - expected_media_count = header.is_infinite - ? expected_external_media_count : expected_internal_media_count; - CHK(header.enclosed_media_count == expected_media_count); - OK(senc_enclosure_ref_put(enclosure)); - } - OK(senc_scene_ref_put(scn)); - - /* Same geometry, all media are defined */ - ctx.positions = all_defined_vertices; - ctx.indices = all_defined_triangles; - ctx.properties = all_defined_properties; - OK(senc_scene_create(dev, convention, all_defined_triangles_count, - get_indices, get_media_from_properties, all_defined_vertices_count, - get_position, &ctx, &scn)); - - OK(senc_scene_get_enclosure_count(scn, &ecount)); - CHK(ecount == 2); - - FOR_EACH(i, 0, ecount) { - struct senc_enclosure* ee; - struct senc_enclosure_header hh; - unsigned cc; - OK(senc_scene_get_enclosure(scn, i, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - - CHK(header.enclosure_id == i); - CHK(header.enclosed_media_count == 1); - OK(senc_enclosure_get_medium(enclosure, 0, &medium)); - /* Geometrical normals point outside the cube in input triangles: - * if convention is front, front medium (0) is outside, - * that is medium 0's enclosure is infinite */ - CHK(conv_front == ((medium == 0) == header.is_infinite)); - CHK(header.primitives_count == ntriangles); - CHK(header.unique_primitives_count == ntriangles); - CHK(header.vertices_count == nvertices); - CHK(header.is_infinite == (i == 0)); - - OK(senc_scene_get_enclosure_count_by_medium(scn, medium, &cc)); - CHK(cc == 1); - OK(senc_scene_get_enclosure_by_medium(scn, medium, 0, &ee)); - OK(senc_enclosure_get_header(ee, &hh)); - CHK(header.enclosure_id == hh.enclosure_id); - OK(senc_enclosure_ref_put(ee)); - - FOR_EACH(t, 0, header.primitives_count) { - OK(senc_enclosure_get_triangle_id(enclosure, t, &gid, &side)); - CHK(gid == t); - CHK(side == (medium == 1) ? SENC_BACK : SENC_FRONT); - } - OK(senc_enclosure_ref_put(enclosure)); - } - - SENC(scene_ref_put(scn)); - SENC(device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); -} - -int -main(int argc, char** argv) -{ - (void) argc, (void) argv; - test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE); - test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE); - test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_OUTSIDE); - test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_OUTSIDE); - return 0; -} diff --git a/src/test_senc_utils.h b/src/test_senc_utils.h @@ -1,271 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 TEST_UTILS_H -#define TEST_UTILS_H - -#include <rsys/rsys.h> -#include <rsys/mem_allocator.h> -#include <rsys/double3.h> - -#include <stdio.h> - -#define OK(Expr) CHK((Expr) == RES_OK) -#define BA(Expr) CHK((Expr) == RES_BAD_ARG) - -/******************************************************************************* - * Geometry - ******************************************************************************/ -/* Distorded cube */ -static const double box_vertices[8/*#vertices*/*3/*#coords per vertex*/] = { - 0.1, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 0.0, 0.0, 1.1, - 1.0, 0.0, 1.0, - 0.0, 1.0, 1.0, - 1.0, 1.1, 1.0 -}; -/* Need a true cube for some tests */ -static const double cube_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = { - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - 1.0, 0.0, 1.0, - 0.0, 1.0, 1.0, - 1.0, 1.0, 1.0 -}; -static const unsigned nvertices = sizeof(box_vertices) / sizeof(double[3]); -STATIC_ASSERT(sizeof(box_vertices) == sizeof(cube_vertices), - The_2_geometries_must_have_the_same_number_of_vertices); - -/* The following array lists the indices toward the 3D vertices of each - * triangle. - * ,2---,3 ,2----3 - * ,' | ,'/| ,'/| \ | - * 6----7' / | 6' / | \ | Y - * |', | / ,1 | / ,0---,1 | - * | ',|/,' |/,' | ,' o--X - * 4----5' 4----5' / - * Front, right Back, left and Z - * and Top faces bottom faces */ -static const unsigned -box_indices[12/*#triangles*/*3/*#indices per triangle*/] = { - 0, 2, 1, 1, 2, 3, /* Front face */ - 0, 4, 2, 2, 4, 6, /* Left face*/ - 4, 5, 6, 6, 5, 7, /* Back face */ - 3, 7, 1, 1, 7, 5, /* Right face */ - 2, 6, 3, 3, 6, 7, /* Top face */ - 0, 1, 4, 4, 1, 5 /* Bottom face */ -}; -static const unsigned -ntriangles = sizeof(box_indices) / (3 * sizeof(*box_indices)); - -struct context { - const double* positions; - const unsigned* indices; - const unsigned* front_media; - const unsigned* back_media; - const unsigned* properties; - void* custom; - double offset[3]; - double scale; - char reverse_vrtx, reverse_med; -}; -#define CONTEXT_NULL__ {\ - NULL, NULL, NULL, NULL, NULL, NULL, {0,0,0}, 1, 0, 0\ -} - -static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -static const unsigned medium2[12] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; -static const unsigned medium1_3[12] = { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 }; -static const unsigned medium1_back0[12] = { 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }; -static const unsigned medium1_front0[12] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -static INLINE void -get_indices(const unsigned itri, unsigned ids[3], void* context) -{ - const struct context* ctx = context; - ASSERT(ids && ctx); - ids[0] = ctx->indices[itri * 3 + 0]; - ids[ctx->reverse_vrtx ? 2 : 1] = ctx->indices[itri * 3 + 1]; - ids[ctx->reverse_vrtx ? 1 : 2] = ctx->indices[itri * 3 + 2]; -} - -static INLINE void -get_position(const unsigned ivert, double pos[3], void* context) -{ - const struct context* ctx = context; - ASSERT(pos && ctx); - pos[0] = ctx->positions[ivert * 3 + 0] * ctx->scale + ctx->offset[0]; - pos[1] = ctx->positions[ivert * 3 + 1] * ctx->scale + ctx->offset[1]; - pos[2] = ctx->positions[ivert * 3 + 2] * ctx->scale + ctx->offset[2]; -} - -static INLINE void -get_media(const unsigned itri, unsigned medium[2], void* context) -{ - const struct context* ctx = context; - ASSERT(medium && ctx); - medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[itri]; - medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri]; -} - -static INLINE void -get_media_from_properties(const unsigned itri, unsigned medium[2], void* context) -{ - const struct context* ctx = context; - ASSERT(medium && ctx); - medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * itri + 0]; - medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * itri + 1]; -} - -/******************************************************************************* - * Miscellaneous - ******************************************************************************/ -static INLINE void -dump_global - (struct senc_scene* scn, - const char* name) -{ - FILE* stream; - unsigned triangles_count, vertices_count, i; - - ASSERT(scn && name); - - OK(senc_scene_get_vertices_count(scn, &vertices_count)); - OK(senc_scene_get_triangles_count(scn, &triangles_count)); - - stream = fopen(name, "w"); - CHK(stream); - FOR_EACH(i, 0, vertices_count) { - double tmp[3]; - OK(senc_scene_get_vertex(scn, i, tmp)); - fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); - } - FOR_EACH(i, 0, triangles_count) { - unsigned indices[3]; - OK(senc_scene_get_triangle(scn, i, indices)); - fprintf(stream, "f %lu %lu %lu\n", (unsigned long)(1 + indices[0]), - (unsigned long)(1 + indices[1]), (unsigned long)(1 + indices[2])); - } - fclose(stream); -} - -static INLINE void -dump_enclosure - (struct senc_scene* scn, - const unsigned enc, - const char* name) -{ - struct senc_enclosure* enclosure; - struct senc_enclosure_header header; - FILE* stream; - unsigned count, i; - - ASSERT(scn && name); - - SENC(scene_get_enclosure_count(scn, &count)); - ASSERT(enc < count); - OK(senc_scene_get_enclosure(scn, enc, &enclosure)); - OK(senc_enclosure_get_header(enclosure, &header)); - - stream = fopen(name, "w"); - CHK(stream); - FOR_EACH(i, 0, header.vertices_count) { - double tmp[3]; - OK(senc_enclosure_get_vertex(enclosure, i, tmp)); - fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); - } - FOR_EACH(i, 0, header.primitives_count) { - unsigned indices[3]; - OK(senc_enclosure_get_triangle(enclosure, i, indices)); - fprintf(stream, "f %lu %lu %lu\n", (unsigned long)(1+indices[0]), - (unsigned long)(1+indices[1]), (unsigned long)(1+indices[2])); - } - OK(senc_enclosure_ref_put(enclosure)); - fclose(stream); -} - -static INLINE void -check_memory_allocator(struct mem_allocator* allocator) -{ - if(MEM_ALLOCATED_SIZE(allocator)) { - char dump[1024]; - MEM_DUMP(allocator, dump, sizeof(dump)); - fprintf(stderr, "%s\n", dump); - FATAL("Memory leaks.\n"); - } -} - -/******************************************************************************* - * Check functions - ******************************************************************************/ -/* Compare the itri-th triangle of enclosure with a triangle described by trg2 & vertices2 */ -static INLINE void -cmp_trg - (const unsigned itri, - const struct senc_enclosure* enclosure, - const unsigned trg2[3], - const double* vertices2, - int* trg_eq, - int* trg_reversed) -{ - unsigned trg1[3]; - double t1[3][3]; - double t2[3][3]; - unsigned trg1_eq[3] = { 3, 3, 3 }; - unsigned i, j, fst_vrtx = 3; - - ASSERT(enclosure && trg2 && vertices2 && trg_eq && trg_reversed); - - OK(senc_enclosure_get_triangle(enclosure, itri, trg1)); - FOR_EACH(i, 0, 3) { - OK(senc_enclosure_get_vertex(enclosure, trg1[i], t1[i])); - d3_set(t2[i], vertices2 + (3 * trg2[i])); - } - FOR_EACH(i, 0, 3) { - FOR_EACH(j, 0, 3) { - if(d3_eq(t1[i], t2[j])) { - trg1_eq[i] = j; - if(i == 0) fst_vrtx = j; - break; - } - } - } - FOR_EACH(i, 0, 3) { - if(trg1_eq[i] == 3) { - *trg_eq = 0; - return; - } - if(trg1_eq[i] == trg1_eq[(i + 1) % 3] - || trg1_eq[i] == trg1_eq[(i + 2) % 3]) { - *trg_eq = 0; - return; - } - } - /* Same 3 vertices */ - ASSERT(fst_vrtx != 3); - *trg_eq = 1; - - *trg_reversed = (trg1_eq[1] != (fst_vrtx + 1) % 3); - ASSERT(*trg_reversed != (trg1_eq[1] != (fst_vrtx + 2) % 3)); -} - -#endif /* TEST_UTILS_H */ diff --git a/src/test_senc_utils2.h b/src/test_senc_utils2.h @@ -1,107 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2020 (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 TEST_UTILS2_H -#define TEST_UTILS2_H - -#if !defined(NB_CYL_X) || !defined(NB_CYL_Y) || !defined(NB_CYL_Z) | !defined(NB_CYL) -#error "Macro definitions are missing" -#endif - -#include "test_senc_utils.h" - -#include <star/s3dut.h> -#include <rsys/double3.h> - -struct s3dut_context { - struct s3dut_mesh_data data; - struct context ctx; -}; - -static void -get_s3dut_indices(const unsigned itri, unsigned ids[3], void* context) -{ - struct s3dut_context* ctx = context; - unsigned s3dut_itri, cyl_idx, v_offset; - ASSERT(ids && ctx); - ASSERT(itri < NB_CYL * ctx->data.nprimitives); - /* Get cyl_idx along with the s3dut vertice index */ - s3dut_itri = itri % (unsigned)ctx->data.nprimitives; - cyl_idx = itri / (unsigned)ctx->data.nprimitives; - ASSERT(ctx->data.indices[s3dut_itri * 3 + 0] <= UINT_MAX - && ctx->data.indices[s3dut_itri * 3 + 1] <= UINT_MAX - && ctx->data.indices[s3dut_itri * 3 + 2] <= UINT_MAX); - /* Compute the vertex index in the user numbering - * from cyl_idx and s3dut data; vertex related getters - * will have to get the s3dut index back */ - v_offset = cyl_idx * (unsigned)ctx->data.nvertices; - ids[0] = v_offset + (unsigned)ctx->data.indices[s3dut_itri * 3 + 0]; - ids[ctx->ctx.reverse_vrtx ? 2 : 1] - = v_offset + (unsigned)ctx->data.indices[s3dut_itri * 3 + 1]; - ids[ctx->ctx.reverse_vrtx ? 1 : 2] - = v_offset + (unsigned)ctx->data.indices[s3dut_itri * 3 + 2]; -} - -static void -get_s3dut_position(const unsigned ivert, double pos[3], void* context) -{ - struct s3dut_context* ctx = context; - unsigned s3dut_ivert, cyl_idx; - int i, j, k; - double offset[3], tmp[3]; - double center_x, center_y, scale, misalignment = 0; - ASSERT(pos && ctx); - ASSERT(ivert < NB_CYL * ctx->data.nvertices); - /* Get cyl_idx and cylinder imbrication along with the s3dut vertice index */ - s3dut_ivert = ivert % (unsigned)ctx->data.nvertices; - cyl_idx = ivert / (unsigned)ctx->data.nvertices; - /* k th cylinder of the imbrication at grid position i,j */ - i = (int)cyl_idx / (NB_CYL_Y * NB_CYL_Z); - j = (cyl_idx / NB_CYL_Z) % NB_CYL_Y; - k = cyl_idx % NB_CYL_Z; - ASSERT(i < NB_CYL_X && j < NB_CYL_Y && k < NB_CYL_Z); - ASSERT((unsigned)(i * NB_CYL_Y * NB_CYL_Z + j * NB_CYL_Z + k) - * ctx->data.nvertices + s3dut_ivert == ivert); - center_x = 2 * (1 + NB_CYL_Z) * (i - NB_CYL_X / 2); - center_y = 2 * (1 + NB_CYL_Z) * (j - NB_CYL_Y / 2); - /* Compute scale and offset from imbrication */ - scale = k + 1; -#ifdef MITIGATE_EMBREE_181 - /* Mitigate Embree issue #181 - * We cannot keep perfect alignment of cylinders - * or some hits are missed */ - misalignment = (k % 2) ? -0.01 : +0.01; -#endif - d3(offset, center_x + misalignment, center_y + misalignment, 0); - d3_add(pos, d3_muld(tmp, ctx->data.positions + s3dut_ivert * 3, scale), - offset); -} - -static void -get_s3dut_media(const unsigned itri, unsigned medium[2], void* context) -{ - struct s3dut_context* ctx = context; - unsigned cyl_idx; - int k; - ASSERT(medium && ctx); - ASSERT(itri < NB_CYL * ctx->data.nprimitives); - /* Get cyl_idx */ - cyl_idx = itri / (unsigned)ctx->data.nprimitives; - /* k th cylinder of the imbrication at some grid position */ - k = cyl_idx % NB_CYL_Z; - medium[ctx->ctx.reverse_med ? SENC_BACK : SENC_FRONT] = (unsigned)k; - medium[ctx->ctx.reverse_med ? SENC_FRONT : SENC_BACK] = (unsigned)(k + 1); -} -#endif /* TEST_UTILS2_H */