gmio_stl: new STL read facade functions

This commit is contained in:
Hugues Delorme 2015-03-23 18:21:04 +01:00
parent 4fcfbab5e0
commit 6fd9399fdd
10 changed files with 197 additions and 78 deletions

View File

@ -20,6 +20,7 @@
#ifndef GMIO_TRANSFER_H
#define GMIO_TRANSFER_H
#include "buffer.h"
#include "global.h"
#include "stream.h"
@ -50,12 +51,8 @@ struct gmio_transfer
/*! The stream object to be used for I/O */
gmio_stream_t stream;
/*! Pointer on a memory buffer used by the transfer for stream
* operations */
void* buffer;
/*! Size (in bytes) of the memory buffer */
size_t buffer_size;
/*! The memory buffer used by the transfer for stream operations */
gmio_buffer_t buffer;
};
typedef struct gmio_transfer gmio_transfer_t;

View File

@ -24,9 +24,9 @@ gmio_bool_t gmio_check_transfer(int *error, const gmio_transfer_t* trsf)
*error = GMIO_NULL_TRANSFER_ERROR;
}
else {
if (trsf->buffer == NULL)
if (trsf->buffer.ptr == NULL)
*error = GMIO_NULL_BUFFER_ERROR;
else if (trsf->buffer_size == 0)
else if (trsf->buffer.size == 0)
*error = GMIO_INVALID_BUFFER_SIZE_ERROR;
}
@ -51,7 +51,7 @@ gmio_bool_t gmio_stlb_check_params(int *error,
if (!gmio_check_transfer(error, trsf))
return GMIO_FALSE;
if (trsf->buffer_size < GMIO_STLB_MIN_CONTENTS_SIZE)
if (trsf->buffer.size < GMIO_STLB_MIN_CONTENTS_SIZE)
*error = GMIO_INVALID_BUFFER_SIZE_ERROR;
if (byte_order != GMIO_LITTLE_ENDIAN && byte_order != GMIO_BIG_ENDIAN)
*error = GMIO_STLB_UNSUPPORTED_BYTE_ORDER_ERROR;

View File

@ -27,10 +27,13 @@ enum { GMIO_STL_ERROR_TAG = 0x11000000 };
* functions */
enum gmio_stl_error
{
/*! STL format could not be guessed in read function */
GMIO_STL_UNKNOWN_FORMAT_ERROR = GMIO_STL_ERROR_TAG + 1,
/*! Common STL write error indicating gmio_stl_mesh::get_triangle_func()
* pointer is NULL
*/
GMIO_STL_WRITE_NULL_GET_TRIANGLE_FUNC_ERROR = GMIO_STL_ERROR_TAG + 1,
GMIO_STL_WRITE_NULL_GET_TRIANGLE_FUNC_ERROR = GMIO_STL_ERROR_TAG + 2,
/* Specific error codes returned by STL_ascii read function */

83
src/gmio_stl/stl_io.c Normal file
View File

@ -0,0 +1,83 @@
/****************************************************************************
** 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
** "http://www.cecill.info".
****************************************************************************/
#include "stl_io.h"
#include "stl_error.h"
#include "stl_format.h"
#include "../gmio_core/error.h"
#include "../gmio_core/stream.h"
#include "../gmio_core/transfer.h"
#include "../gmio_core/internal/helper_stream.h"
int gmio_stl_read_file(
const char* filepath,
gmio_stl_mesh_creator_t* creator,
gmio_buffer_t* buffer)
{
int error = GMIO_NO_ERROR;
FILE* file = NULL;
file = fopen(filepath, "rb");
if (file != NULL) {
gmio_transfer_t trsf = { 0 };
trsf.stream = gmio_stream_stdio(file);
if (buffer != NULL)
trsf.buffer = *buffer;
error = gmio_stl_read(&trsf, creator);
fclose(file);
}
else {
error = GMIO_UNKNOWN_ERROR;
}
return error;
}
int gmio_stl_read(gmio_transfer_t *trsf, gmio_stl_mesh_creator_t *creator)
{
int error = GMIO_NO_ERROR;
if (trsf != NULL) {
const gmio_stl_format_t stl_format = gmio_stl_get_format(&trsf->stream);
switch (stl_format) {
case GMIO_STL_ASCII_FORMAT: {
error = gmio_stla_read(trsf, creator, NULL);
break;
}
case GMIO_STL_BINARY_BE_FORMAT: {
const gmio_stlb_read_options_t opts = { GMIO_BIG_ENDIAN };
error = gmio_stlb_read(trsf, creator, &opts);
break;
}
case GMIO_STL_BINARY_LE_FORMAT: {
const gmio_stlb_read_options_t opts = { GMIO_LITTLE_ENDIAN };
error = gmio_stlb_read(trsf, creator, &opts);
break;
}
case GMIO_STL_UNKNOWN_FORMAT: {
error = GMIO_STL_UNKNOWN_FORMAT_ERROR;
}
} /* end switch() */
}
else {
error = GMIO_NULL_TRANSFER_ERROR;
}
return error;
}

View File

@ -23,11 +23,37 @@
#include "stl_global.h"
#include "stl_mesh.h"
#include "stl_mesh_creator.h"
#include "../gmio_core/buffer.h"
#include "../gmio_core/endian.h"
#include "../gmio_core/transfer.h"
GMIO_C_LINKAGE_BEGIN
/*! Reads STL file, format is automatically guessed
*
* \param filepath Path to the STL file. A stream is opened with fopen() so
* the string has to be encoded using the system's charset (locale-8bit)
* \param creator Defines the callbacks for the mesh creation
* \param buffer The memory block used by stream operations
*
* \return Error code (see error.h and stl_error.h)
*/
GMIO_LIBSTL_EXPORT int gmio_stl_read_file(
const char* filepath,
gmio_stl_mesh_creator_t* creator,
gmio_buffer_t* buffer);
/*! Reads STL file, format is automatically guessed
*
* \param trsf Defines needed objects for the read operation
* \param creator Defines the callbacks for the mesh creation
*
* \return Error code (see error.h and stl_error.h)
*/
GMIO_LIBSTL_EXPORT int gmio_stl_read(
gmio_transfer_t* trsf,
gmio_stl_mesh_creator_t* creator);
/* ========================================================================
* STL ascii
* ======================================================================== */
@ -40,30 +66,25 @@ GMIO_C_LINKAGE_BEGIN
*/
struct gmio_stla_read_options
{
/*! Hint about the total size (in bytes) of the STL ascii data to be read
* from stream
*
* \p stream_size is passed to gmio_transfer::handle_progress_func() as
* the \p max_value argument.
*
* Defaulted to \c 0 when calling gmio_stla_read() with \c options==NULL
*/
size_t stream_size;
void* dummy; /* Empty structs are forbidden with ISO-C90 */
};
typedef struct gmio_stla_read_options gmio_stla_read_options_t;
/*! Reads geometry from STL ascii stream
*
* \param mesh Defines the callbacks for the mesh creation
* \param creator Defines the callbacks for the mesh creation
* \param trsf Defines needed objects for the read operation
* \param options Options for the operation, can be \c NULL to use default
* values
* \param options Options for the operation, shoul be set to NULL (just here
* for future use)
*
* Stream size is passed to gmio_transfer::handle_progress_func() as the
* \p max_value argument.
*
* \return Error code (see error.h and stl_error.h)
*/
GMIO_LIBSTL_EXPORT
int gmio_stla_read(gmio_stl_mesh_creator_t* creator,
gmio_transfer_t* trsf,
int gmio_stla_read(gmio_transfer_t* trsf,
gmio_stl_mesh_creator_t* creator,
const gmio_stla_read_options_t* options);
@ -97,8 +118,8 @@ typedef struct gmio_stla_write_options gmio_stla_write_options_t;
* \retval GMIO_INVALID_BUFFER_SIZE_ERROR if \c trs->buffer_size < 512
*/
GMIO_LIBSTL_EXPORT
int gmio_stla_write(const gmio_stl_mesh_t* mesh,
gmio_transfer_t* trsf,
int gmio_stla_write(gmio_transfer_t* trsf,
const gmio_stl_mesh_t* mesh,
const gmio_stla_write_options_t* options);
/* ========================================================================
@ -129,8 +150,8 @@ typedef struct gmio_stlb_read_options gmio_stlb_read_options_t;
* if \c trs->buffer_size < GMIO_STLB_MIN_CONTENTS_SIZE
*/
GMIO_LIBSTL_EXPORT
int gmio_stlb_read(gmio_stl_mesh_creator_t* creator,
gmio_transfer_t* trsf,
int gmio_stlb_read(gmio_transfer_t* trsf,
gmio_stl_mesh_creator_t* creator,
const gmio_stlb_read_options_t* options);
@ -166,8 +187,8 @@ typedef struct gmio_stlb_write_options gmio_stlb_write_options_t;
* if \c trs->buffer_size < GMIO_STLB_MIN_CONTENTS_SIZE
*/
GMIO_LIBSTL_EXPORT
int gmio_stlb_write(const gmio_stl_mesh_t* mesh,
gmio_transfer_t* trsf,
int gmio_stlb_write(gmio_transfer_t* trsf,
const gmio_stl_mesh_t* mesh,
const gmio_stlb_write_options_t* options);
GMIO_C_LINKAGE_END

View File

@ -23,6 +23,8 @@
#include "stl_global.h"
#include "stl_triangle.h"
#include <stddef.h>
/*! Provides an interface for the creation of the underlying(hidden)
* user mesh */
struct gmio_stl_mesh_creator
@ -38,7 +40,8 @@ struct gmio_stl_mesh_creator
*
* Optional function useful only with STL ascii (ie. gmio_stla_read())
*/
void (*ascii_begin_solid_func)(void* cookie, const char* solid_name);
void (*ascii_begin_solid_func)(
void* cookie, size_t stream_size, const char* solid_name);
/*! Pointer on a function that handles declaration of a mesh with
* \p tri_count number of triangles

View File

@ -21,6 +21,7 @@
#include "internal/stl_rw_common.h"
#include "../gmio_core/error.h"
#include "../gmio_core/internal/helper_stream.h"
#include "../gmio_core/internal/helper_transfer.h"
#include "../gmio_core/internal/string_parse.h"
@ -308,6 +309,7 @@ static void parse_beginsolid(gmio_stla_parse_data_t* data)
{
data->creator->ascii_begin_solid_func(
data->creator->cookie,
data->stream_iterator_cookie.stream_size,
current_token_as_identifier(data));
}
if (data->token == ID_token)
@ -423,13 +425,14 @@ static void parse_solid(gmio_stla_parse_data_t* data)
enum { GMIO_STLA_READ_STRING_BUFFER_LEN = 512 };
int gmio_stla_read(
gmio_stl_mesh_creator_t* creator,
gmio_transfer_t* trsf,
gmio_stl_mesh_creator_t* creator,
const gmio_stla_read_options_t* options)
{
char fixed_buffer[GMIO_STLA_READ_STRING_BUFFER_LEN];
gmio_stla_parse_data_t parse_data;
GMIO_UNUSED(options);
{ /* Check validity of input parameters */
int error = GMIO_NO_ERROR;
if (!gmio_check_transfer(&error, trsf))
@ -442,12 +445,12 @@ int gmio_stla_read(
parse_data.stream_iterator_cookie.transfer = trsf;
parse_data.stream_iterator_cookie.stream_offset = 0;
parse_data.stream_iterator_cookie.stream_size =
options != NULL ? options->stream_size : 0;
gmio_stream_size(&trsf->stream);
parse_data.stream_iterator_cookie.is_stop_requested = GMIO_FALSE;
parse_data.stream_iterator.stream = &trsf->stream;
parse_data.stream_iterator.buffer.ptr = trsf->buffer;
parse_data.stream_iterator.buffer.max_len = trsf->buffer_size;
parse_data.stream_iterator.buffer.ptr = trsf->buffer.ptr;
parse_data.stream_iterator.buffer.max_len = trsf->buffer.size;
parse_data.stream_iterator.cookie = &parse_data.stream_iterator_cookie;
parse_data.stream_iterator.stream_read_hook =
gmio_stream_fwd_iterator_stla_read_hook;

View File

@ -109,12 +109,14 @@ static char* gmio_write_coords(
static gmio_bool_t gmio_transfer_flush_buffer(gmio_transfer_t* trsf, size_t n)
{
return gmio_stream_write(&trsf->stream, trsf->buffer, sizeof(char), n) == n;
const size_t write_count =
gmio_stream_write(&trsf->stream, trsf->buffer.ptr, sizeof(char), n);
return write_count == n;
}
int gmio_stla_write(
const gmio_stl_mesh_t* mesh,
gmio_transfer_t* trsf,
const gmio_stl_mesh_t* mesh,
const gmio_stla_write_options_t* options)
{
/* Constants */
@ -123,11 +125,12 @@ int gmio_stla_write(
const uint32_t total_facet_count = mesh != NULL ? mesh->triangle_count : 0;
const uint32_t buffer_facet_count =
trsf != NULL ?
gmio_size_to_uint32(trsf->buffer_size / GMIO_STLA_FACET_SIZE_P2)
gmio_size_to_uint32(trsf->buffer.size / GMIO_STLA_FACET_SIZE_P2)
: 0;
/* Variables */
uint32_t ifacet = 0;
char* buff_it = trsf != NULL ? trsf->buffer : NULL;
void* buffer_ptr = trsf != NULL ? trsf->buffer.ptr : NULL;
char* buffc = buffer_ptr;
char coords_format[64];
int error = GMIO_NO_ERROR;
@ -138,7 +141,7 @@ int gmio_stla_write(
return error;
if (float32_prec == 0 || float32_prec > 9)
return GMIO_STLA_WRITE_INVALID_REAL32_PREC_ERROR;
if (trsf->buffer_size < GMIO_STLA_FACET_SIZE_P2)
if (trsf->buffer.size < GMIO_STLA_FACET_SIZE_P2)
return GMIO_INVALID_BUFFER_SIZE_ERROR;
{ /* Create XYZ coords format string (for normal and vertex coords) */
@ -154,9 +157,9 @@ int gmio_stla_write(
/* Write solid declaration */
{
buff_it = gmio_write_string(buff_it, "solid ");
buff_it = gmio_write_string_eol(buff_it, solid_name);
if (!gmio_transfer_flush_buffer(trsf, buff_it - (char*)trsf->buffer))
buffc = gmio_write_string(buffc, "solid ");
buffc = gmio_write_string_eol(buffc, solid_name);
if (!gmio_transfer_flush_buffer(trsf, buffc - (char*)buffer_ptr))
return GMIO_STREAM_ERROR;
}
@ -173,32 +176,32 @@ int gmio_stla_write(
gmio_transfer_handle_progress(trsf, ifacet, total_facet_count);
/* Writing of facets is buffered */
buff_it = trsf->buffer;
buffc = buffer_ptr;
for (ibuffer_facet = ifacet;
ibuffer_facet < clamped_facet_count;
++ibuffer_facet)
{
mesh->get_triangle_func(mesh->cookie, ibuffer_facet, &tri);
buff_it = gmio_write_string(buff_it, "facet normal ");
buff_it = gmio_write_coords(buff_it, coords_format, &tri.normal);
buff_it = gmio_write_eol(buff_it);
buffc = gmio_write_string(buffc, "facet normal ");
buffc = gmio_write_coords(buffc, coords_format, &tri.normal);
buffc = gmio_write_eol(buffc);
buff_it = gmio_write_string_eol(buff_it, " outer loop");
buff_it = gmio_write_string(buff_it, " vertex ");
buff_it = gmio_write_coords(buff_it, coords_format, &tri.v1);
buff_it = gmio_write_eol(buff_it);
buff_it = gmio_write_string(buff_it, " vertex ");
buff_it = gmio_write_coords(buff_it, coords_format, &tri.v2);
buff_it = gmio_write_eol(buff_it);
buff_it = gmio_write_string(buff_it, " vertex ");
buff_it = gmio_write_coords(buff_it, coords_format, &tri.v3);
buff_it = gmio_write_eol(buff_it);
buff_it = gmio_write_string_eol(buff_it, " endloop");
buffc = gmio_write_string_eol(buffc, " outer loop");
buffc = gmio_write_string(buffc, " vertex ");
buffc = gmio_write_coords(buffc, coords_format, &tri.v1);
buffc = gmio_write_eol(buffc);
buffc = gmio_write_string(buffc, " vertex ");
buffc = gmio_write_coords(buffc, coords_format, &tri.v2);
buffc = gmio_write_eol(buffc);
buffc = gmio_write_string(buffc, " vertex ");
buffc = gmio_write_coords(buffc, coords_format, &tri.v3);
buffc = gmio_write_eol(buffc);
buffc = gmio_write_string_eol(buffc, " endloop");
buff_it = gmio_write_string_eol(buff_it, "endfacet");
buffc = gmio_write_string_eol(buffc, "endfacet");
} /* end for (ibuffer_facet) */
if (!gmio_transfer_flush_buffer(trsf, buff_it - (char*)trsf->buffer))
if (!gmio_transfer_flush_buffer(trsf, buffc - (char*)buffer_ptr))
error = GMIO_STREAM_ERROR;
/* Task control */
@ -208,9 +211,9 @@ int gmio_stla_write(
/* Write end of solid */
if (gmio_no_error(error)) {
buff_it = gmio_write_string(trsf->buffer, "endsolid ");
buff_it = gmio_write_string_eol(buff_it, solid_name);
if (!gmio_transfer_flush_buffer(trsf, buff_it - (char*)trsf->buffer))
buffc = gmio_write_string(trsf->buffer.ptr, "endsolid ");
buffc = gmio_write_string_eol(buffc, solid_name);
if (!gmio_transfer_flush_buffer(trsf, buffc - (char*)buffer_ptr))
error = GMIO_STREAM_ERROR;
}

View File

@ -67,8 +67,8 @@ static void gmio_stlb_read_facets(
}
int gmio_stlb_read(
gmio_stl_mesh_creator_t *creator,
gmio_transfer_t* trsf,
gmio_stl_mesh_creator_t *creator,
const gmio_stlb_read_options_t* options)
{
/* Constants */
@ -77,7 +77,7 @@ int gmio_stlb_read(
const uint32_t max_facet_count_per_read =
trsf != NULL ?
gmio_size_to_uint32(
trsf->buffer_size / GMIO_STLB_TRIANGLE_RAWSIZE)
trsf->buffer.size / GMIO_STLB_TRIANGLE_RAWSIZE)
: 0;
/* Variables */
gmio_stlb_readwrite_helper_t rparams = {0};
@ -101,10 +101,13 @@ int gmio_stlb_read(
}
/* Read facet count */
if (gmio_stream_read(&trsf->stream, trsf->buffer, sizeof(uint32_t), 1) != 1)
if (gmio_stream_read(&trsf->stream, trsf->buffer.ptr, sizeof(uint32_t), 1)
!= 1)
{
return GMIO_STLB_READ_FACET_COUNT_ERROR;
}
memcpy(&total_facet_count, trsf->buffer, sizeof(uint32_t));
memcpy(&total_facet_count, trsf->buffer.ptr, sizeof(uint32_t));
if (byte_order != GMIO_HOST_ENDIANNESS)
total_facet_count = gmio_uint32_bswap(total_facet_count);
@ -125,7 +128,7 @@ int gmio_stlb_read(
gmio_size_to_uint32(
gmio_stream_read(
&trsf->stream,
trsf->buffer,
trsf->buffer.ptr,
GMIO_STLB_TRIANGLE_RAWSIZE,
max_facet_count_per_read));
if (gmio_stream_error(&trsf->stream) != 0)
@ -136,7 +139,7 @@ int gmio_stlb_read(
break; /* Exit if no facet to read */
if (gmio_no_error(error)) {
gmio_stlb_read_facets(creator, trsf->buffer, &rparams);
gmio_stlb_read_facets(creator, trsf->buffer.ptr, &rparams);
rparams.i_facet_offset += rparams.facet_count;
if (gmio_transfer_is_stop_requested(trsf))
error = GMIO_TRANSFER_STOPPED_ERROR;

View File

@ -68,8 +68,8 @@ static void gmio_stlb_write_facets(
}
int gmio_stlb_write(
const gmio_stl_mesh_t* mesh,
gmio_transfer_t* trsf,
const gmio_stl_mesh_t* mesh,
const gmio_stlb_write_options_t* options)
{
/* Constants */
@ -94,13 +94,13 @@ int gmio_stlb_write(
if (byte_order != GMIO_HOST_ENDIANNESS)
wparams.fix_endian_func = gmio_stl_triangle_bswap;
wparams.facet_count = gmio_size_to_uint32(
trsf->buffer_size / GMIO_STLB_TRIANGLE_RAWSIZE);
trsf->buffer.size / GMIO_STLB_TRIANGLE_RAWSIZE);
/* Write header */
if (header_data == NULL) {
/* Use buffer to store an empty header (filled with zeroes) */
memset(trsf->buffer, 0, GMIO_STLB_HEADER_SIZE);
header_data = (const uint8_t*)trsf->buffer;
memset(trsf->buffer.ptr, 0, GMIO_STLB_HEADER_SIZE);
header_data = (const uint8_t*)trsf->buffer.ptr;
}
if (gmio_stream_write(&trsf->stream, header_data, GMIO_STLB_HEADER_SIZE, 1)
!= 1)
@ -110,11 +110,14 @@ int gmio_stlb_write(
/* Write facet count */
if (byte_order == GMIO_LITTLE_ENDIAN)
gmio_encode_uint32_le(facet_count, trsf->buffer);
gmio_encode_uint32_le(facet_count, trsf->buffer.ptr);
else
gmio_encode_uint32_be(facet_count, trsf->buffer);
if (gmio_stream_write(&trsf->stream, trsf->buffer, sizeof(uint32_t), 1) != 1)
gmio_encode_uint32_be(facet_count, trsf->buffer.ptr);
if (gmio_stream_write(&trsf->stream, trsf->buffer.ptr, sizeof(uint32_t), 1)
!= 1)
{
return GMIO_STREAM_ERROR;
}
/* Write triangles */
for (i_facet = 0;
@ -127,13 +130,13 @@ int gmio_stlb_write(
wparams.facet_count = GMIO_MIN(wparams.facet_count,
facet_count - wparams.i_facet_offset);
gmio_stlb_write_facets(mesh, trsf->buffer, &wparams);
gmio_stlb_write_facets(mesh, trsf->buffer.ptr, &wparams);
wparams.i_facet_offset += wparams.facet_count;
/* Write buffer to stream */
if (gmio_stream_write(
&trsf->stream,
trsf->buffer,
trsf->buffer.ptr,
GMIO_STLB_TRIANGLE_RAWSIZE,
wparams.facet_count)
!= wparams.facet_count)