Add support of multi STL solids loading

This commit is contained in:
Hugues Delorme 2016-02-24 16:43:40 +01:00
parent 9260bc480a
commit 77c65947bb
16 changed files with 1817 additions and 50 deletions

View File

@ -28,10 +28,16 @@ GMIO_INLINE int gmio_stream_error(struct gmio_stream* stream);
GMIO_INLINE size_t gmio_stream_read( GMIO_INLINE size_t gmio_stream_read(
struct gmio_stream* stream, void *ptr, size_t size, size_t count); struct gmio_stream* stream, void *ptr, size_t size, size_t count);
GMIO_INLINE size_t gmio_stream_read_bytes(
struct gmio_stream* stream, void *ptr, size_t count);
/*! Safe and convenient function for gmio_stream::func_write() */ /*! Safe and convenient function for gmio_stream::func_write() */
GMIO_INLINE size_t gmio_stream_write( GMIO_INLINE size_t gmio_stream_write(
struct gmio_stream* stream, const void *ptr, size_t size, size_t count); struct gmio_stream* stream, const void *ptr, size_t size, size_t count);
GMIO_INLINE size_t gmio_stream_write_bytes(
struct gmio_stream* stream, const void *ptr, size_t count);
/*! Safe and convenient function for gmio_stream::func_size() */ /*! Safe and convenient function for gmio_stream::func_size() */
GMIO_INLINE gmio_streamsize_t gmio_stream_size(struct gmio_stream* stream); GMIO_INLINE gmio_streamsize_t gmio_stream_size(struct gmio_stream* stream);
@ -75,6 +81,14 @@ size_t gmio_stream_read(
return 0; return 0;
} }
size_t gmio_stream_read_bytes(
struct gmio_stream* stream, void *ptr, size_t count)
{
if (stream != NULL && stream->func_read != NULL)
return stream->func_read(stream->cookie, ptr, 1, count);
return 0;
}
size_t gmio_stream_write( size_t gmio_stream_write(
struct gmio_stream* stream, const void *ptr, size_t size, size_t count) struct gmio_stream* stream, const void *ptr, size_t size, size_t count)
{ {
@ -83,6 +97,14 @@ size_t gmio_stream_write(
return 0; return 0;
} }
size_t gmio_stream_write_bytes(
struct gmio_stream* stream, const void *ptr, size_t count)
{
if (stream != NULL && stream->func_write != NULL)
return stream->func_write(stream->cookie, ptr, 1, count);
return 0;
}
gmio_streamsize_t gmio_stream_size(struct gmio_stream* stream) gmio_streamsize_t gmio_stream_size(struct gmio_stream* stream)
{ {
if (stream != NULL && stream->func_size != NULL) if (stream != NULL && stream->func_size != NULL)

View File

@ -23,6 +23,7 @@ struct gmio_stringstream gmio_stringstream(
struct gmio_stringstream sstream = {0}; struct gmio_stringstream sstream = {0};
sstream.stream = stream; sstream.stream = stream;
sstream.strbuff = strbuff; sstream.strbuff = strbuff;
sstream.func_stream_read = gmio_stringstream_default_func_read;
gmio_stringstream_init_pos(&sstream); gmio_stringstream_init_pos(&sstream);
return sstream; return sstream;
} }

View File

@ -41,12 +41,12 @@ struct gmio_stringstream
/*! Position indicator in strbuff */ /*! Position indicator in strbuff */
const char* strbuff_at; const char* strbuff_at;
/*! User data to be passed to callback func_stream_read_hook */ /*! Data to be passed to callback func_stream_read */
void* cookie; void* cookie;
/*! Pointer on user function called each time next contents is read */ /*! Pointer on a function called each time next contents has to be read */
void (*func_stream_read_hook)( size_t (*func_stream_read)(
void* cookie, const struct gmio_string* strbuff); void* cookie, struct gmio_stream* stream, char* ptr, size_t len);
}; };
/*! Returns an initialized gmio_stringstream object */ /*! Returns an initialized gmio_stringstream object */
@ -57,6 +57,10 @@ struct gmio_stringstream gmio_stringstream(
/*! Initializes position indicator */ /*! Initializes position indicator */
void gmio_stringstream_init_pos(struct gmio_stringstream* sstream); void gmio_stringstream_init_pos(struct gmio_stringstream* sstream);
/*! Default function for gmio_stringstream::func_stream_read */
GMIO_INLINE size_t gmio_stringstream_default_func_read(
void* cookie, struct gmio_stream* stream, char* ptr, size_t len);
/*! Returns the char where the iterator is currently pointing at */ /*! Returns the char where the iterator is currently pointing at */
GMIO_INLINE const char* gmio_stringstream_current_char( GMIO_INLINE const char* gmio_stringstream_current_char(
const struct gmio_stringstream* sstream); const struct gmio_stringstream* sstream);
@ -142,6 +146,13 @@ const char* gmio_stringstream_current_char(
NULL; NULL;
} }
size_t gmio_stringstream_default_func_read(
void* cookie, struct gmio_stream* stream, char* ptr, size_t len)
{
GMIO_UNUSED(cookie);
return gmio_stream_read(stream, ptr, 1, len);
}
const char *gmio_stringstream_next_char(struct gmio_stringstream *sstream) const char *gmio_stringstream_next_char(struct gmio_stringstream *sstream)
{ {
++(sstream->strbuff_at); ++(sstream->strbuff_at);
@ -151,15 +162,13 @@ const char *gmio_stringstream_next_char(struct gmio_stringstream *sstream)
/* Read next chunk of data */ /* Read next chunk of data */
sstream->strbuff_at = sstream->strbuff.ptr; sstream->strbuff_at = sstream->strbuff.ptr;
sstream->strbuff.len = sstream->strbuff.len =
gmio_stream_read( sstream->func_stream_read(
&sstream->stream, sstream->strbuff.ptr, 1, sstream->strbuff.max_len); sstream->cookie,
&sstream->stream,
sstream->strbuff.ptr,
sstream->strbuff.max_len);
sstream->strbuff_end = sstream->strbuff.ptr + sstream->strbuff.len; sstream->strbuff_end = sstream->strbuff.ptr + sstream->strbuff.len;
if (sstream->strbuff.len > 0) { return sstream->strbuff.len > 0 ? sstream->strbuff.ptr : NULL;
if (sstream->func_stream_read_hook != NULL)
sstream->func_stream_read_hook(sstream->cookie, &sstream->strbuff);
return sstream->strbuff.ptr;
}
return NULL;
} }
struct gmio_stringstream* gmio_stringstream_move_next_char( struct gmio_stringstream* gmio_stringstream_move_next_char(

View File

@ -50,12 +50,14 @@ static bool gmio_stringstream_icase_eat(
} }
/* Callback invoked by gmio_stringstream */ /* Callback invoked by gmio_stringstream */
static void gmio_stringstream_update_streamsize( static size_t gmio_stringstream_read(
void* cookie, const struct gmio_string* strbuff) void* cookie, struct gmio_stream* stream, char* ptr, size_t len)
{ {
gmio_streamsize_t* ptr_size = (gmio_streamsize_t*)(cookie); gmio_streamsize_t* ptr_size = (gmio_streamsize_t*)(cookie);
const size_t len_read = gmio_stream_read_bytes(stream, ptr, len);
if (ptr_size != NULL) if (ptr_size != NULL)
*ptr_size += strbuff->len; *ptr_size += len_read;
return len_read;
} }
int gmio_stla_infos_get( int gmio_stla_infos_get(
@ -88,7 +90,7 @@ int gmio_stla_infos_get(
if (flag_size) { if (flag_size) {
infos->size = 0; infos->size = 0;
sstream.cookie = &infos->size; sstream.cookie = &infos->size;
sstream.func_stream_read_hook = gmio_stringstream_update_streamsize; sstream.func_stream_read = gmio_stringstream_read;
} }
gmio_stringstream_init_pos(&sstream); gmio_stringstream_init_pos(&sstream);

View File

@ -57,13 +57,16 @@ int gmio_stlb_infos_get(
memcpy(infos->stlb_header.data, buff, GMIO_STLB_HEADER_SIZE); memcpy(infos->stlb_header.data, buff, GMIO_STLB_HEADER_SIZE);
if (flags & GMIO_STL_INFO_FLAG_FACET_COUNT) if (flags & GMIO_STL_INFO_FLAG_FACET_COUNT)
infos->facet_count = facet_count; infos->facet_count = facet_count;
if (flags & GMIO_STL_INFO_FLAG_SIZE) { if (flags & GMIO_STL_INFO_FLAG_SIZE)
infos->size = infos->size = gmio_stlb_infos_size(facet_count);
GMIO_STLB_HEADER_SIZE
+ sizeof(uint32_t)
+ facet_count * GMIO_STLB_TRIANGLE_RAWSIZE;
}
} }
return GMIO_ERROR_OK; return GMIO_ERROR_OK;
} }
gmio_streamsize_t gmio_stlb_infos_size(uint32_t facet_count)
{
return GMIO_STLB_HEADER_SIZE
+ sizeof(uint32_t)
+ facet_count * GMIO_STLB_TRIANGLE_RAWSIZE;
}

View File

@ -19,11 +19,15 @@
#include "../stl_infos.h" #include "../stl_infos.h"
#include "../../gmio_core/endian.h" #include "../../gmio_core/endian.h"
/*! Find infos from a STL binary stream */ /*! Finds infos from a STL binary stream */
int gmio_stlb_infos_get( int gmio_stlb_infos_get(
struct gmio_stl_infos* infos, struct gmio_stl_infos* infos,
struct gmio_stream stream, struct gmio_stream stream,
unsigned flags, unsigned flags,
const struct gmio_stl_infos_get_options* opts); const struct gmio_stl_infos_get_options* opts);
/*! Returns the size(in bytes) of the whole STL binary data given some facet
* count */
gmio_streamsize_t gmio_stlb_infos_size(uint32_t facet_count);
#endif /* GMIO_INTERNAL_STLB_INFOS_GET_H */ #endif /* GMIO_INTERNAL_STLB_INFOS_GET_H */

View File

@ -73,3 +73,14 @@ label_end:
gmio_memblock_helper_release(&mblock_helper); gmio_memblock_helper_release(&mblock_helper);
return error; return error;
} }
gmio_streamsize_t gmio_stla_infos_get_streamsize(
struct gmio_stream *stream, struct gmio_memblock *stream_memblock)
{
struct gmio_stl_infos infos = {0};
struct gmio_stl_infos_get_options options = {0};
options.stream_memblock = *stream_memblock;
options.format_hint = GMIO_STL_FORMAT_ASCII;
gmio_stl_infos_get(&infos, *stream, GMIO_STL_INFO_FLAG_SIZE, &options);
return infos.size;
}

View File

@ -117,6 +117,15 @@ int gmio_stl_infos_get(
unsigned flags, /*!< Bitor combination of gmio_stl_info_flag values */ unsigned flags, /*!< Bitor combination of gmio_stl_info_flag values */
const struct gmio_stl_infos_get_options* options); const struct gmio_stl_infos_get_options* options);
/*! Returns the size(in bytes) of next STL ascii solid in \p stream
*
* It is a facade over gmio_stl_infos_get() for gmio_stl_infos::size only
*/
GMIO_LIBSTL_EXPORT
gmio_streamsize_t gmio_stla_infos_get_streamsize(
struct gmio_stream* stream,
struct gmio_memblock* stream_memblock);
GMIO_C_LINKAGE_END GMIO_C_LINKAGE_END
#endif /* GMIO_STL_INFOS_H */ #endif /* GMIO_STL_INFOS_H */

View File

@ -82,19 +82,24 @@
*/ */
/* Callback used for gmio_stringstream::func_stream_read_hook */ /* Callback used for gmio_stringstream::func_stream_read */
static void gmio_stringstream_stla_read_hook( static size_t gmio_stringstream_stla_read(
void* cookie, const struct gmio_string* strbuff) void* cookie, struct gmio_stream* stream, char* ptr, size_t len)
{ {
struct gmio_stringstream_stla_cookie* tcookie = struct gmio_stringstream_stla_cookie* stlac =
(struct gmio_stringstream_stla_cookie*)(cookie); (struct gmio_stringstream_stla_cookie*)(cookie);
if (tcookie != NULL) { if (stlac != NULL) {
const struct gmio_task_iface* task = tcookie->task; const struct gmio_task_iface* task = stlac->task;
tcookie->stream_offset += strbuff->len; const size_t to_read =
tcookie->is_stop_requested = gmio_task_iface_is_stop_requested(task); GMIO_MIN(len, stlac->stream_size - stlac->stream_offset + 1);
const size_t len_read = gmio_stream_read_bytes(stream, ptr, to_read);
stlac->stream_offset += len_read;
stlac->is_stop_requested = gmio_task_iface_is_stop_requested(task);
gmio_task_iface_handle_progress( gmio_task_iface_handle_progress(
task, tcookie->stream_offset, tcookie->stream_size); task, stlac->stream_offset, stlac->stream_size);
return len_read;
} }
return 0;
} }
/* Root function, parses a whole solid */ /* Root function, parses a whole solid */
@ -127,7 +132,7 @@ int gmio_stla_read(
parse_data.strstream.strbuff.ptr = mblock->ptr; parse_data.strstream.strbuff.ptr = mblock->ptr;
parse_data.strstream.strbuff.max_len = mblock->size; parse_data.strstream.strbuff.max_len = mblock->size;
parse_data.strstream.cookie = &parse_data.strstream_cookie; parse_data.strstream.cookie = &parse_data.strstream_cookie;
parse_data.strstream.func_stream_read_hook = gmio_stringstream_stla_read_hook; parse_data.strstream.func_stream_read = gmio_stringstream_stla_read;
gmio_stringstream_init_pos(&parse_data.strstream); gmio_stringstream_init_pos(&parse_data.strstream);
parse_data.token_str = gmio_string(fixed_buffer, 0, sizeof(fixed_buffer)); parse_data.token_str = gmio_string(fixed_buffer, 0, sizeof(fixed_buffer));
@ -532,8 +537,11 @@ int gmio_stla_parse_solidname_beg(struct gmio_stla_parse_data* data)
int parse_solidname_end(struct gmio_stla_parse_data* data) int parse_solidname_end(struct gmio_stla_parse_data* data)
{ {
GMIO_UNUSED(data); struct gmio_stringstream* sstream = &data->strstream;
/* TODO: parse according to retrieved solid name */ /* Eat whole line after "endsolid" */
const char* c = gmio_stringstream_current_char(sstream);
while (c != NULL && *c != '\n' && *c != '\r')
c = gmio_stringstream_next_char(sstream);
return 0; return 0;
} }

View File

@ -28,6 +28,7 @@
#include "../gmio_core/internal/helper_memblock.h" #include "../gmio_core/internal/helper_memblock.h"
#include "../gmio_core/internal/helper_stream.h" #include "../gmio_core/internal/helper_stream.h"
#include "../gmio_core/internal/helper_task_iface.h" #include "../gmio_core/internal/helper_task_iface.h"
#include "../gmio_core/internal/min_max.h"
#include "../gmio_core/internal/safe_cast.h" #include "../gmio_core/internal/safe_cast.h"
#include <string.h> #include <string.h>
@ -98,19 +99,18 @@ int gmio_stlb_read(
struct gmio_memblock_helper mblock_helper = struct gmio_memblock_helper mblock_helper =
gmio_memblock_helper(opts != NULL ? &opts->stream_memblock : NULL); gmio_memblock_helper(opts != NULL ? &opts->stream_memblock : NULL);
struct gmio_memblock* mblock = &mblock_helper.memblock; struct gmio_memblock* mblock = &mblock_helper.memblock;
void* mblock_ptr = mblock->ptr;
const struct gmio_task_iface* task = opts != NULL ? &opts->task_iface : NULL; const struct gmio_task_iface* task = opts != NULL ? &opts->task_iface : NULL;
struct gmio_stlb_header header; struct gmio_stlb_header header;
uint32_t i_facet = 0; /* Facet counter */ uint32_t i_facet = 0; /* Facet counter */
uint32_t total_facet_count = 0; /* Facet count, as declared in the stream */ uint32_t total_facet_count = 0; /* Facet count, as declared in the stream */
int error = GMIO_ERROR_OK; /* Helper to store function result error code */ int error = GMIO_ERROR_OK; /* Function result(error code) */
/* Constants */ /* Constants */
const func_gmio_stlb_decode_facets_t func_decode_facets = const func_gmio_stlb_decode_facets_t func_decode_facets =
byte_order != GMIO_ENDIANNESS_HOST ? byte_order != GMIO_ENDIANNESS_HOST ?
gmio_stlb_decode_facets_byteswap : gmio_stlb_decode_facets_byteswap :
gmio_stlb_decode_facets; gmio_stlb_decode_facets;
const uint32_t max_facet_count_per_read = const uint32_t max_facet_count_per_read =
gmio_size_to_uint32(mblock->size / GMIO_STLB_TRIANGLE_RAWSIZE); gmio_size_to_uint32(mblock->size / GMIO_STLB_TRIANGLE_RAWSIZE);
/* Check validity of input parameters */ /* Check validity of input parameters */
if (!gmio_check_memblock_size(&error, mblock, GMIO_STLB_MIN_CONTENTS_SIZE)) if (!gmio_check_memblock_size(&error, mblock, GMIO_STLB_MIN_CONTENTS_SIZE))
@ -119,22 +119,17 @@ int gmio_stlb_read(
goto label_end; goto label_end;
/* Read header */ /* Read header */
if (gmio_stream_read(&stream, &header, GMIO_STLB_HEADER_SIZE, 1) if (gmio_stream_read(&stream, &header, GMIO_STLB_HEADER_SIZE, 1) != 1) {
!= 1)
{
error = GMIO_STL_ERROR_HEADER_WRONG_SIZE; error = GMIO_STL_ERROR_HEADER_WRONG_SIZE;
goto label_end; goto label_end;
} }
/* Read facet count */ /* Read facet count */
if (gmio_stream_read(&stream, mblock_ptr, sizeof(uint32_t), 1) if (gmio_stream_read(&stream, mblock->ptr, sizeof(uint32_t), 1) != 1) {
!= 1)
{
error = GMIO_STL_ERROR_FACET_COUNT; error = GMIO_STL_ERROR_FACET_COUNT;
goto label_end; goto label_end;
} }
memcpy(&total_facet_count, mblock->ptr, sizeof(uint32_t));
memcpy(&total_facet_count, mblock_ptr, sizeof(uint32_t));
if (byte_order != GMIO_ENDIANNESS_HOST) if (byte_order != GMIO_ENDIANNESS_HOST)
total_facet_count = gmio_uint32_bswap(total_facet_count); total_facet_count = gmio_uint32_bswap(total_facet_count);
@ -153,13 +148,16 @@ int gmio_stlb_read(
/* Read triangles */ /* Read triangles */
gmio_task_iface_handle_progress(task, 0, total_facet_count); gmio_task_iface_handle_progress(task, 0, total_facet_count);
while (gmio_no_error(error) && i_facet < total_facet_count) { while (gmio_no_error(error) && i_facet < total_facet_count) {
const uint32_t facet_count_to_read =
GMIO_MIN(max_facet_count_per_read,
total_facet_count - i_facet);
const uint32_t read_facet_count = const uint32_t read_facet_count =
gmio_size_to_uint32( gmio_size_to_uint32(
gmio_stream_read( gmio_stream_read(
&stream, &stream,
mblock_ptr, mblock->ptr,
GMIO_STLB_TRIANGLE_RAWSIZE, GMIO_STLB_TRIANGLE_RAWSIZE,
max_facet_count_per_read)); facet_count_to_read));
if (gmio_stream_error(&stream) != 0) if (gmio_stream_error(&stream) != 0)
error = GMIO_ERROR_STREAM; error = GMIO_ERROR_STREAM;
@ -170,7 +168,7 @@ int gmio_stlb_read(
if (gmio_no_error(error)) { if (gmio_no_error(error)) {
func_decode_facets( func_decode_facets(
&mesh_creator, mblock_ptr, read_facet_count, i_facet); &mesh_creator, mblock->ptr, read_facet_count, i_facet);
i_facet += read_facet_count; i_facet += read_facet_count;
if (gmio_task_iface_is_stop_requested(task)) if (gmio_task_iface_is_stop_requested(task))
error = GMIO_ERROR_TRANSFER_STOPPED; error = GMIO_ERROR_TRANSFER_STOPPED;

View File

@ -15,6 +15,8 @@
#include "utest_lib.h" #include "utest_lib.h"
#include "../src/gmio_core/memblock.h"
const char* test_stl_coords_packing(); const char* test_stl_coords_packing();
const char* test_stl_triangle_packing(); const char* test_stl_triangle_packing();
const char* test_stl_triangle_compute_normal(); const char* test_stl_triangle_compute_normal();
@ -24,6 +26,7 @@ const char* test_stl_internal__rw_common();
const char* test_stl_infos(); const char* test_stl_infos();
const char* test_stl_read(); const char* test_stl_read();
const char* test_stl_read_multi_solid();
const char* test_stla_write(); const char* test_stla_write();
const char* test_stlb_write_header(); const char* test_stlb_write_header();
const char* test_stlb_write(); const char* test_stlb_write();
@ -31,10 +34,21 @@ const char* test_stlb_write();
const char* test_stlb_header_str(); const char* test_stlb_header_str();
const char* test_stlb_header_to_printable_str(); const char* test_stlb_header_to_printable_str();
void generate_stlb_tests_models();
/* Static memblock */
struct gmio_memblock gmio_memblock_for_tests()
{
static uint8_t buff[1024]; /* 1KB */
return gmio_memblock(buff, sizeof(buff), NULL);
}
const char* all_tests() const char* all_tests()
{ {
UTEST_SUITE_START(); UTEST_SUITE_START();
gmio_memblock_set_default_constructor(gmio_memblock_for_tests);
UTEST_RUN(test_stl_coords_packing); UTEST_RUN(test_stl_coords_packing);
UTEST_RUN(test_stl_triangle_packing); UTEST_RUN(test_stl_triangle_packing);
UTEST_RUN(test_stl_triangle_compute_normal); UTEST_RUN(test_stl_triangle_compute_normal);
@ -44,6 +58,7 @@ const char* all_tests()
UTEST_RUN(test_stl_infos); UTEST_RUN(test_stl_infos);
UTEST_RUN(test_stl_read); UTEST_RUN(test_stl_read);
UTEST_RUN(test_stl_read_multi_solid);
UTEST_RUN(test_stla_write); UTEST_RUN(test_stla_write);
UTEST_RUN(test_stlb_write_header); UTEST_RUN(test_stlb_write_header);
UTEST_RUN(test_stlb_write); UTEST_RUN(test_stlb_write);
@ -51,6 +66,10 @@ const char* all_tests()
UTEST_RUN(test_stlb_header_str); UTEST_RUN(test_stlb_header_str);
UTEST_RUN(test_stlb_header_to_printable_str); UTEST_RUN(test_stlb_header_to_printable_str);
#if 0
generate_stlb_tests_models();
#endif
return NULL; return NULL;
} }
UTEST_MAIN(all_tests) UTEST_MAIN(all_tests)

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,16 @@ struct gmio_stl_triangle_array gmio_stl_triangle_array_malloc(size_t tri_count)
return array; return array;
} }
void gmio_stl_triangle_array_free(struct gmio_stl_triangle_array *array)
{
if (array != NULL) {
free(array->ptr);
array->ptr = NULL;
array->count = 0;
array->capacity = 0;
}
}
static void gmio_stl_data__begin_solid( static void gmio_stl_data__begin_solid(
void* cookie, const struct gmio_stl_mesh_creator_infos* infos) void* cookie, const struct gmio_stl_mesh_creator_infos* infos)
{ {

View File

@ -65,6 +65,8 @@ struct gmio_stl_triangle_array
*/ */
struct gmio_stl_triangle_array gmio_stl_triangle_array_malloc(size_t tri_count); struct gmio_stl_triangle_array gmio_stl_triangle_array_malloc(size_t tri_count);
void gmio_stl_triangle_array_free(struct gmio_stl_triangle_array* array);
/*! Holds complete STL data (usable for both binary and ascii formats) */ /*! Holds complete STL data (usable for both binary and ascii formats) */
struct gmio_stl_data struct gmio_stl_data
{ {

View File

@ -21,6 +21,7 @@
#include "../src/gmio_core/error.h" #include "../src/gmio_core/error.h"
#include "../src/gmio_core/internal/min_max.h" #include "../src/gmio_core/internal/min_max.h"
#include "../src/gmio_stl/stl_error.h" #include "../src/gmio_stl/stl_error.h"
#include "../src/gmio_stl/stl_infos.h"
#include "../src/gmio_stl/stl_io.h" #include "../src/gmio_stl/stl_io.h"
#include "../src/gmio_stl/stl_io_options.h" #include "../src/gmio_stl/stl_io_options.h"
@ -319,7 +320,7 @@ const char* test_stla_write()
{ {
const char* model_filepath = stl_grabcad_arm11_filepath; const char* model_filepath = stl_grabcad_arm11_filepath;
const char* model_filepath_out = "temp/solid.stla"; const char* model_filepath_out = "temp/solid.stla";
struct gmio_stl_data data = {0}; struct gmio_stl_data data = {0}; /* TODO: fix memory leak on error */
char header_str[GMIO_STLB_HEADER_SIZE + 1] = {0}; char header_str[GMIO_STLB_HEADER_SIZE + 1] = {0};
int error = GMIO_ERROR_OK; int error = GMIO_ERROR_OK;
@ -370,6 +371,42 @@ const char* test_stla_write()
return NULL; return NULL;
} }
const char* generic_test_stl_read_multi_solid(
const char* filepath, unsigned expected_solid_count)
{
FILE* infile = fopen(filepath, "rb");
if (infile != NULL) {
unsigned solid_count = 0;
int error = GMIO_ERROR_OK;
struct gmio_stl_read_options roptions = {0};
roptions.func_stla_get_streamsize = gmio_stla_infos_get_streamsize;
while (gmio_no_error(error)) {
const struct gmio_stl_mesh_creator null_creator = {0};
error = gmio_stl_read(
gmio_stream_stdio(infile), null_creator, &roptions);
if (gmio_no_error(error))
++solid_count;
}
fclose(infile);
UTEST_COMPARE_UINT(expected_solid_count, solid_count);
}
else {
perror(NULL);
UTEST_FAIL("");
}
return NULL;
}
const char* test_stl_read_multi_solid()
{
const char* res = NULL;
res = generic_test_stl_read_multi_solid("models/solid_4meshs.stla", 4);
if (res != NULL)
return res;
res = generic_test_stl_read_multi_solid("models/solid_4meshs.le_stlb", 4);
return res;
}
void generate_stlb_tests_models() void generate_stlb_tests_models()
{ {
{ {
@ -403,4 +440,29 @@ void generate_stlb_tests_models()
gmio_stl_data_mesh(&data), gmio_stl_data_mesh(&data),
NULL); NULL);
} }
{
FILE* infile = fopen("models/solid_4meshs.stla", "rb");
FILE* outfile = fopen("models/solid_4meshs.le_stlb", "wb");
int read_error = GMIO_ERROR_OK;
struct gmio_stl_read_options roptions = {0};
roptions.func_stla_get_streamsize = gmio_stla_infos_get_streamsize;
while (gmio_no_error(read_error)) {
struct gmio_stl_data data = {0};
struct gmio_stl_write_options woptions = {0};
read_error = gmio_stla_read(
gmio_stream_stdio(infile),
gmio_stl_data_mesh_creator(&data),
&roptions);
woptions.stlb_header = gmio_stlb_header_str(data.solid_name);
gmio_stl_write(
GMIO_STL_FORMAT_BINARY_LE,
gmio_stream_stdio(outfile),
gmio_stl_data_mesh(&data),
&woptions);
gmio_stl_triangle_array_free(&data.tri_array);
}
fclose(infile);
fclose(outfile);
}
} }