2015-03-03 00:38:33 +08:00
|
|
|
/****************************************************************************
|
2015-05-28 15:40:24 +08:00
|
|
|
** gmio
|
2016-06-24 18:03:07 +08:00
|
|
|
** Copyright Fougue (24 Jun. 2016)
|
2015-07-13 17:42:03 +08:00
|
|
|
** contact@fougue.pro
|
2015-03-03 00:38:33 +08:00
|
|
|
**
|
|
|
|
** This software is a reusable library whose purpose is to provide complete
|
|
|
|
** I/O support for various CAD file formats (eg. STL)
|
|
|
|
**
|
|
|
|
** This software is governed by the CeCILL-B license under French law and
|
|
|
|
** abiding by the rules of distribution of free software. You can use,
|
|
|
|
** modify and/ or redistribute the software under the terms of the CeCILL-B
|
|
|
|
** license as circulated by CEA, CNRS and INRIA at the following URL
|
2015-03-30 15:05:25 +08:00
|
|
|
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
|
2015-03-03 00:38:33 +08:00
|
|
|
****************************************************************************/
|
|
|
|
|
2014-03-28 23:33:35 +08:00
|
|
|
#include "stl_io.h"
|
|
|
|
|
|
|
|
#include "stl_error.h"
|
2015-03-30 16:18:18 +08:00
|
|
|
#include "internal/helper_stl_mesh_creator.h"
|
2015-10-15 00:17:03 +08:00
|
|
|
#include "internal/stl_funptr_typedefs.h"
|
2014-03-28 23:33:35 +08:00
|
|
|
#include "internal/stl_rw_common.h"
|
|
|
|
#include "internal/stlb_byte_swap.h"
|
|
|
|
|
|
|
|
#include "../gmio_core/endian.h"
|
|
|
|
#include "../gmio_core/error.h"
|
|
|
|
#include "../gmio_core/internal/byte_swap.h"
|
2015-03-03 17:29:47 +08:00
|
|
|
#include "../gmio_core/internal/convert.h"
|
2015-12-17 19:03:45 +08:00
|
|
|
#include "../gmio_core/internal/helper_memblock.h"
|
2015-03-13 18:04:14 +08:00
|
|
|
#include "../gmio_core/internal/helper_stream.h"
|
2016-01-29 19:47:01 +08:00
|
|
|
#include "../gmio_core/internal/helper_task_iface.h"
|
2016-02-24 23:43:40 +08:00
|
|
|
#include "../gmio_core/internal/min_max.h"
|
2015-03-30 16:26:39 +08:00
|
|
|
#include "../gmio_core/internal/safe_cast.h"
|
2014-03-28 23:33:35 +08:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
2016-01-26 22:54:06 +08:00
|
|
|
GMIO_INLINE void decode_facet(
|
2015-12-04 01:00:25 +08:00
|
|
|
const uint8_t* buffer, struct gmio_stl_triangle* triangle)
|
2014-03-28 23:33:35 +08:00
|
|
|
{
|
2015-12-04 01:00:25 +08:00
|
|
|
/* *triangle = *((struct gmio_stl_triangle*)(buffer)); */
|
2015-03-03 17:35:36 +08:00
|
|
|
memcpy(triangle, buffer, GMIO_STLB_TRIANGLE_RAWSIZE);
|
2014-03-28 23:33:35 +08:00
|
|
|
}
|
|
|
|
|
2016-01-26 22:54:06 +08:00
|
|
|
typedef void (*func_gmio_stlb_decode_facets_t)(
|
|
|
|
struct gmio_stl_mesh_creator*,
|
|
|
|
const uint8_t*, /* buffer */
|
|
|
|
const uint32_t, /* facet_count */
|
|
|
|
const uint32_t); /* i_facet_offset */
|
|
|
|
|
|
|
|
static void gmio_stlb_decode_facets(
|
2015-12-04 01:00:25 +08:00
|
|
|
struct gmio_stl_mesh_creator* creator,
|
2015-03-20 00:31:08 +08:00
|
|
|
const uint8_t* buffer,
|
2016-01-26 22:54:06 +08:00
|
|
|
const uint32_t facet_count,
|
|
|
|
const uint32_t i_facet_offset)
|
2014-03-28 23:33:35 +08:00
|
|
|
{
|
2015-10-15 00:17:03 +08:00
|
|
|
const gmio_stl_mesh_creator_func_add_triangle_t func_add_triangle =
|
2016-01-26 22:54:06 +08:00
|
|
|
creator->func_add_triangle;
|
2015-10-06 17:30:36 +08:00
|
|
|
void* cookie = creator->cookie;
|
2015-03-03 17:35:36 +08:00
|
|
|
|
2016-01-26 22:54:06 +08:00
|
|
|
if (func_add_triangle != NULL) {
|
|
|
|
struct gmio_stl_triangle triangle;
|
|
|
|
uint32_t i_facet;
|
|
|
|
for (i_facet = 0; i_facet < facet_count; ++i_facet) {
|
|
|
|
decode_facet(buffer, &triangle);
|
|
|
|
buffer += GMIO_STLB_TRIANGLE_RAWSIZE;
|
|
|
|
func_add_triangle(cookie, i_facet_offset + i_facet, &triangle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
2016-01-26 22:54:06 +08:00
|
|
|
static void gmio_stlb_decode_facets_byteswap(
|
|
|
|
struct gmio_stl_mesh_creator* creator,
|
|
|
|
const uint8_t* buffer,
|
|
|
|
const uint32_t facet_count,
|
|
|
|
const uint32_t i_facet_offset)
|
|
|
|
{
|
|
|
|
const gmio_stl_mesh_creator_func_add_triangle_t func_add_triangle =
|
|
|
|
creator->func_add_triangle;
|
|
|
|
void* cookie = creator->cookie;
|
2015-03-03 17:35:36 +08:00
|
|
|
|
2016-01-26 22:54:06 +08:00
|
|
|
if (func_add_triangle != NULL) {
|
|
|
|
struct gmio_stl_triangle triangle;
|
|
|
|
uint32_t i_facet;
|
|
|
|
for (i_facet = 0; i_facet < facet_count; ++i_facet) {
|
|
|
|
decode_facet(buffer, &triangle);
|
|
|
|
buffer += GMIO_STLB_TRIANGLE_RAWSIZE;
|
|
|
|
gmio_stl_triangle_bswap(&triangle);
|
|
|
|
func_add_triangle(cookie, i_facet_offset + i_facet, &triangle);
|
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
}
|
2014-03-28 23:33:35 +08:00
|
|
|
}
|
|
|
|
|
2015-03-20 00:31:08 +08:00
|
|
|
int gmio_stlb_read(
|
2016-03-01 21:50:31 +08:00
|
|
|
struct gmio_stream* stream,
|
|
|
|
struct gmio_stl_mesh_creator* mesh_creator,
|
2016-01-29 19:47:01 +08:00
|
|
|
enum gmio_endianness byte_order,
|
|
|
|
const struct gmio_stl_read_options* opts)
|
2014-03-28 23:33:35 +08:00
|
|
|
{
|
2015-03-20 00:31:08 +08:00
|
|
|
/* Variables */
|
2015-12-17 19:03:45 +08:00
|
|
|
struct gmio_memblock_helper mblock_helper =
|
2016-01-29 19:47:01 +08:00
|
|
|
gmio_memblock_helper(opts != NULL ? &opts->stream_memblock : NULL);
|
|
|
|
struct gmio_memblock* mblock = &mblock_helper.memblock;
|
|
|
|
const struct gmio_task_iface* task = opts != NULL ? &opts->task_iface : NULL;
|
2015-12-04 01:00:25 +08:00
|
|
|
struct gmio_stlb_header header;
|
2016-01-26 22:54:06 +08:00
|
|
|
uint32_t i_facet = 0; /* Facet counter */
|
2015-03-20 00:31:08 +08:00
|
|
|
uint32_t total_facet_count = 0; /* Facet count, as declared in the stream */
|
2016-02-24 23:43:40 +08:00
|
|
|
int error = GMIO_ERROR_OK; /* Function result(error code) */
|
2015-12-17 19:03:45 +08:00
|
|
|
/* Constants */
|
2016-01-26 22:54:06 +08:00
|
|
|
const func_gmio_stlb_decode_facets_t func_decode_facets =
|
|
|
|
byte_order != GMIO_ENDIANNESS_HOST ?
|
|
|
|
gmio_stlb_decode_facets_byteswap :
|
|
|
|
gmio_stlb_decode_facets;
|
2015-12-17 19:03:45 +08:00
|
|
|
const uint32_t max_facet_count_per_read =
|
2016-02-24 23:43:40 +08:00
|
|
|
gmio_size_to_uint32(mblock->size / GMIO_STLB_TRIANGLE_RAWSIZE);
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
/* Check validity of input parameters */
|
2016-01-29 19:47:01 +08:00
|
|
|
if (!gmio_check_memblock_size(&error, mblock, GMIO_STLB_MIN_CONTENTS_SIZE))
|
|
|
|
goto label_end;
|
|
|
|
if (!gmio_stlb_check_byteorder(&error, byte_order))
|
2015-12-17 19:03:45 +08:00
|
|
|
goto label_end;
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
/* Read header */
|
2016-03-01 21:50:31 +08:00
|
|
|
if (gmio_stream_read(stream, &header, GMIO_STLB_HEADER_SIZE, 1) != 1) {
|
2015-12-17 19:03:45 +08:00
|
|
|
error = GMIO_STL_ERROR_HEADER_WRONG_SIZE;
|
|
|
|
goto label_end;
|
2015-03-03 17:35:36 +08:00
|
|
|
}
|
2014-03-28 23:33:35 +08:00
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
/* Read facet count */
|
2016-03-01 21:50:31 +08:00
|
|
|
if (gmio_stream_read(stream, mblock->ptr, sizeof(uint32_t), 1) != 1) {
|
2015-12-17 19:03:45 +08:00
|
|
|
error = GMIO_STL_ERROR_FACET_COUNT;
|
|
|
|
goto label_end;
|
2015-03-24 01:21:04 +08:00
|
|
|
}
|
2016-02-24 23:43:40 +08:00
|
|
|
memcpy(&total_facet_count, mblock->ptr, sizeof(uint32_t));
|
2015-04-02 15:45:02 +08:00
|
|
|
if (byte_order != GMIO_ENDIANNESS_HOST)
|
2015-03-03 17:35:36 +08:00
|
|
|
total_facet_count = gmio_uint32_bswap(total_facet_count);
|
|
|
|
|
|
|
|
/* Callback to notify triangle count and header data */
|
2016-02-01 23:53:45 +08:00
|
|
|
{
|
|
|
|
struct gmio_stl_mesh_creator_infos infos = {0};
|
|
|
|
infos.format =
|
|
|
|
byte_order == GMIO_ENDIANNESS_LITTLE ?
|
|
|
|
GMIO_STL_FORMAT_BINARY_LE :
|
|
|
|
GMIO_STL_FORMAT_BINARY_BE;
|
|
|
|
infos.stlb_header = &header;
|
|
|
|
infos.stlb_triangle_count = total_facet_count;
|
2016-03-01 21:50:31 +08:00
|
|
|
gmio_stl_mesh_creator_begin_solid(mesh_creator, &infos);
|
2016-02-01 23:53:45 +08:00
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
/* Read triangles */
|
2016-01-29 19:47:01 +08:00
|
|
|
gmio_task_iface_handle_progress(task, 0, total_facet_count);
|
2016-01-26 22:54:06 +08:00
|
|
|
while (gmio_no_error(error) && i_facet < total_facet_count) {
|
2016-02-24 23:43:40 +08:00
|
|
|
const uint32_t facet_count_to_read =
|
|
|
|
GMIO_MIN(max_facet_count_per_read,
|
|
|
|
total_facet_count - i_facet);
|
2016-01-26 22:54:06 +08:00
|
|
|
const uint32_t read_facet_count =
|
2015-03-03 17:35:36 +08:00
|
|
|
gmio_size_to_uint32(
|
|
|
|
gmio_stream_read(
|
2016-03-01 21:50:31 +08:00
|
|
|
stream,
|
2016-02-24 23:43:40 +08:00
|
|
|
mblock->ptr,
|
2015-03-03 17:35:36 +08:00
|
|
|
GMIO_STLB_TRIANGLE_RAWSIZE,
|
2016-02-24 23:43:40 +08:00
|
|
|
facet_count_to_read));
|
2016-01-26 22:54:06 +08:00
|
|
|
|
2016-03-01 21:50:31 +08:00
|
|
|
if (gmio_stream_error(stream) != 0)
|
2015-04-02 16:04:24 +08:00
|
|
|
error = GMIO_ERROR_STREAM;
|
2016-01-26 22:54:06 +08:00
|
|
|
else if (read_facet_count > 0)
|
2015-04-02 16:04:24 +08:00
|
|
|
error = GMIO_ERROR_OK;
|
2015-03-03 17:35:36 +08:00
|
|
|
else
|
|
|
|
break; /* Exit if no facet to read */
|
|
|
|
|
|
|
|
if (gmio_no_error(error)) {
|
2016-01-26 22:54:06 +08:00
|
|
|
func_decode_facets(
|
2016-03-01 21:50:31 +08:00
|
|
|
mesh_creator, mblock->ptr, read_facet_count, i_facet);
|
2016-01-26 22:54:06 +08:00
|
|
|
i_facet += read_facet_count;
|
2016-01-29 19:47:01 +08:00
|
|
|
if (gmio_task_iface_is_stop_requested(task))
|
2015-04-02 16:04:24 +08:00
|
|
|
error = GMIO_ERROR_TRANSFER_STOPPED;
|
2015-03-03 17:35:36 +08:00
|
|
|
}
|
2016-01-29 19:47:01 +08:00
|
|
|
gmio_task_iface_handle_progress(task, i_facet, total_facet_count);
|
2015-03-03 17:35:36 +08:00
|
|
|
} /* end while */
|
|
|
|
|
2015-03-30 16:18:18 +08:00
|
|
|
if (gmio_no_error(error))
|
2016-03-01 21:50:31 +08:00
|
|
|
gmio_stl_mesh_creator_end_solid(mesh_creator);
|
2015-03-03 17:35:36 +08:00
|
|
|
|
2016-01-26 22:54:06 +08:00
|
|
|
if (gmio_no_error(error) && i_facet != total_facet_count)
|
2015-04-02 16:04:24 +08:00
|
|
|
error = GMIO_STL_ERROR_FACET_COUNT;
|
2015-12-17 19:03:45 +08:00
|
|
|
|
|
|
|
label_end:
|
|
|
|
gmio_memblock_helper_release(&mblock_helper);
|
2015-03-03 17:35:36 +08:00
|
|
|
return error;
|
2014-03-28 23:33:35 +08:00
|
|
|
}
|