2015-03-03 00:38:33 +08:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** GeomIO Library
|
|
|
|
** Copyright FougSys (2 Mar. 2015)
|
|
|
|
** contact@fougsys.fr
|
|
|
|
**
|
|
|
|
** 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"
|
|
|
|
#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"
|
|
|
|
#include "../gmio_core/internal/safe_cast.h"
|
2015-03-13 18:04:14 +08:00
|
|
|
#include "../gmio_core/internal/helper_stream.h"
|
|
|
|
#include "../gmio_core/internal/helper_transfer.h"
|
2014-03-28 23:33:35 +08:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
2015-03-20 00:31:08 +08:00
|
|
|
GMIO_INLINE static void read_triangle_memcpy(
|
|
|
|
const uint8_t* buffer, gmio_stl_triangle_t* triangle)
|
2014-03-28 23:33:35 +08:00
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
/* *triangle = *((gmio_stl_triangle_t*)(buffer)); */
|
|
|
|
memcpy(triangle, buffer, GMIO_STLB_TRIANGLE_RAWSIZE);
|
2014-03-28 23:33:35 +08:00
|
|
|
}
|
|
|
|
|
2015-03-20 00:31:08 +08:00
|
|
|
static void gmio_stlb_read_facets(
|
|
|
|
gmio_stl_mesh_creator_t* creator,
|
|
|
|
const uint8_t* buffer,
|
|
|
|
const gmio_stlb_readwrite_helper_t* rparams)
|
2014-03-28 23:33:35 +08:00
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
const uint32_t facet_count = rparams->facet_count;
|
|
|
|
const uint32_t i_facet_offset = rparams->i_facet_offset;
|
|
|
|
gmio_stl_triangle_t triangle;
|
|
|
|
uint32_t buffer_offset = 0;
|
|
|
|
uint32_t i_facet = 0;
|
|
|
|
|
|
|
|
if (creator == NULL || creator->add_triangle_func == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i_facet = 0; i_facet < facet_count; ++i_facet) {
|
|
|
|
/* Decode data */
|
|
|
|
read_triangle_memcpy(buffer + buffer_offset, &triangle);
|
|
|
|
buffer_offset += GMIO_STLB_TRIANGLE_RAWSIZE;
|
|
|
|
|
|
|
|
if (rparams->fix_endian_func != NULL)
|
|
|
|
rparams->fix_endian_func(&triangle);
|
|
|
|
|
|
|
|
/* Declare triangle */
|
2015-03-20 00:31:08 +08:00
|
|
|
creator->add_triangle_func(
|
|
|
|
creator->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(
|
|
|
|
gmio_transfer_t* trsf,
|
2015-03-24 01:21:04 +08:00
|
|
|
gmio_stl_mesh_creator_t *creator,
|
2015-03-20 00:31:08 +08:00
|
|
|
const gmio_stlb_read_options_t* options)
|
2014-03-28 23:33:35 +08:00
|
|
|
{
|
2015-03-20 00:31:08 +08:00
|
|
|
/* Constants */
|
2015-03-30 15:15:20 +08:00
|
|
|
const gmio_endianness_t byte_order =
|
2015-03-20 15:53:20 +08:00
|
|
|
options != NULL ? options->byte_order : GMIO_HOST_ENDIANNESS;
|
2015-03-03 17:35:36 +08:00
|
|
|
const uint32_t max_facet_count_per_read =
|
2015-03-19 23:40:50 +08:00
|
|
|
trsf != NULL ?
|
|
|
|
gmio_size_to_uint32(
|
2015-03-24 01:21:04 +08:00
|
|
|
trsf->buffer.size / GMIO_STLB_TRIANGLE_RAWSIZE)
|
2015-03-19 23:40:50 +08:00
|
|
|
: 0;
|
2015-03-20 00:31:08 +08:00
|
|
|
/* Variables */
|
2015-03-03 17:35:36 +08:00
|
|
|
gmio_stlb_readwrite_helper_t rparams = {0};
|
2015-03-20 00:31:08 +08:00
|
|
|
uint8_t header_data[GMIO_STLB_HEADER_SIZE];
|
|
|
|
uint32_t total_facet_count = 0; /* Facet count, as declared in the stream */
|
|
|
|
int error = GMIO_NO_ERROR; /* Helper to store function result error code */
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
/* Check validity of input parameters */
|
|
|
|
if (!gmio_stlb_check_params(&error, trsf, byte_order))
|
|
|
|
return error;
|
|
|
|
|
|
|
|
/* Initialize rparams */
|
2015-03-20 15:53:20 +08:00
|
|
|
if (byte_order != GMIO_HOST_ENDIANNESS)
|
2015-03-03 17:35:36 +08:00
|
|
|
rparams.fix_endian_func = gmio_stl_triangle_bswap;
|
|
|
|
|
|
|
|
/* Read header */
|
|
|
|
if (gmio_stream_read(&trsf->stream, header_data, 1, GMIO_STLB_HEADER_SIZE)
|
|
|
|
!= GMIO_STLB_HEADER_SIZE)
|
|
|
|
{
|
|
|
|
return GMIO_STLB_READ_HEADER_WRONG_SIZE_ERROR;
|
|
|
|
}
|
2014-03-28 23:33:35 +08:00
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
/* Read facet count */
|
2015-03-24 01:21:04 +08:00
|
|
|
if (gmio_stream_read(&trsf->stream, trsf->buffer.ptr, sizeof(uint32_t), 1)
|
|
|
|
!= 1)
|
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
return GMIO_STLB_READ_FACET_COUNT_ERROR;
|
2015-03-24 01:21:04 +08:00
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
2015-03-24 01:21:04 +08:00
|
|
|
memcpy(&total_facet_count, trsf->buffer.ptr, sizeof(uint32_t));
|
2015-03-20 15:53:20 +08:00
|
|
|
if (byte_order != GMIO_HOST_ENDIANNESS)
|
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 */
|
2015-03-20 00:31:08 +08:00
|
|
|
if (creator != NULL && creator->binary_begin_solid_func != NULL) {
|
|
|
|
creator->binary_begin_solid_func(
|
|
|
|
creator->cookie, total_facet_count, header_data);
|
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
/* Read triangles */
|
|
|
|
while (gmio_no_error(error)
|
|
|
|
&& rparams.i_facet_offset < total_facet_count)
|
|
|
|
{
|
2015-03-13 17:32:18 +08:00
|
|
|
gmio_transfer_handle_progress(
|
|
|
|
trsf, rparams.i_facet_offset, total_facet_count);
|
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
rparams.facet_count =
|
|
|
|
gmio_size_to_uint32(
|
|
|
|
gmio_stream_read(
|
|
|
|
&trsf->stream,
|
2015-03-24 01:21:04 +08:00
|
|
|
trsf->buffer.ptr,
|
2015-03-03 17:35:36 +08:00
|
|
|
GMIO_STLB_TRIANGLE_RAWSIZE,
|
|
|
|
max_facet_count_per_read));
|
|
|
|
if (gmio_stream_error(&trsf->stream) != 0)
|
|
|
|
error = GMIO_STREAM_ERROR;
|
|
|
|
else if (rparams.facet_count > 0)
|
|
|
|
error = GMIO_NO_ERROR;
|
|
|
|
else
|
|
|
|
break; /* Exit if no facet to read */
|
|
|
|
|
|
|
|
if (gmio_no_error(error)) {
|
2015-03-24 01:21:04 +08:00
|
|
|
gmio_stlb_read_facets(creator, trsf->buffer.ptr, &rparams);
|
2015-03-03 17:35:36 +08:00
|
|
|
rparams.i_facet_offset += rparams.facet_count;
|
2015-03-13 00:46:40 +08:00
|
|
|
if (gmio_transfer_is_stop_requested(trsf))
|
|
|
|
error = GMIO_TRANSFER_STOPPED_ERROR;
|
2015-03-03 17:35:36 +08:00
|
|
|
}
|
|
|
|
} /* end while */
|
|
|
|
|
|
|
|
if (gmio_no_error(error)
|
|
|
|
&& creator != NULL
|
|
|
|
&& creator->end_solid_func != NULL)
|
|
|
|
{
|
|
|
|
creator->end_solid_func(creator->cookie);
|
2014-03-28 23:33:35 +08:00
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
if (gmio_no_error(error) && rparams.i_facet_offset != total_facet_count)
|
|
|
|
error = GMIO_STLB_READ_FACET_COUNT_ERROR;
|
|
|
|
return error;
|
2014-03-28 23:33:35 +08:00
|
|
|
}
|