c-lib: workable binary STL writing function

This commit is contained in:
Hugues Delorme 2013-01-15 13:10:44 +01:00
parent 2cfe22896b
commit 1f0f4a311f
8 changed files with 255 additions and 40 deletions

View File

@ -26,14 +26,17 @@ HEADERS += \
../../../src/c/memory.h \
../../../src/c/stream.h \
../../../src/c/task_control.h \
../../../src/c/libstl/stlb_global.h \
../../../src/c/libstl/stlb_read.h \
../../../src/c/libstl/stlb_write.h \
../../../src/c/libstl/triangle.h
SOURCES += \
../../../src/c/endian.c \
../../../src/c/stream.c \
../../../src/c/task_control.c \
../../../src/c/libstl/stlb_read.c
../../../src/c/libstl/stlb_read.c \
../../../src/c/libstl/stlb_write.c
*-g++*:QMAKE_CFLAGS += -ansi

View File

@ -1,5 +1,15 @@
#include "endian.h"
#include <string.h>
#define _INTERNAL_FOUG_ENCODE_NUMERIC_LE(NUMERIC_TYPE) \
union { \
NUMERIC_TYPE as_numeric; \
uint8_t as_bytes[sizeof(NUMERIC_TYPE)]; \
} u; \
u.as_numeric = val; \
memcpy(bytes, u.as_bytes, sizeof(NUMERIC_TYPE));
foug_endianness_t foug_host_endianness()
{
union {
@ -42,6 +52,11 @@ uint16_t foug_decode_uint16_be(const uint8_t* bytes)
return (bytes[0] << 8) | bytes[1];
}
void foug_encode_uint16_le(uint16_t val, uint8_t* bytes)
{
_INTERNAL_FOUG_ENCODE_NUMERIC_LE(uint16_t);
}
uint32_t foug_uint32_swap(uint32_t val)
{
return
@ -74,6 +89,11 @@ uint32_t foug_decode_uint32_be(const uint8_t* bytes)
return bytes[3] | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24);
}
void foug_encode_uint32_le(uint32_t val, uint8_t* bytes)
{
_INTERNAL_FOUG_ENCODE_NUMERIC_LE(uint32_t);
}
static foug_real32_t convert_real32(uint32_t val)
{
union
@ -100,3 +120,8 @@ foug_real32_t foug_decode_real32_be(const uint8_t* bytes)
{
return convert_real32(foug_decode_uint32_be(bytes));
}
void foug_encode_real32_le(foug_real32_t val, uint8_t* bytes)
{
_INTERNAL_FOUG_ENCODE_NUMERIC_LE(foug_real32_t);
}

View File

@ -17,15 +17,18 @@ uint16_t foug_uint16_swap(uint16_t val);
uint16_t foug_uint16_noswap(uint16_t val);
uint16_t foug_decode_uint16_le(const uint8_t* bytes);
uint16_t foug_decode_uint16_be(const uint8_t* bytes);
void foug_encode_uint16_le(uint16_t val, uint8_t* bytes);
uint32_t foug_uint32_swap(uint32_t val);
uint32_t foug_uint32_noswap(uint32_t val);
uint32_t foug_decode_uint32_le(const uint8_t* bytes);
uint32_t foug_decode_uint32_me(const uint8_t* bytes);
uint32_t foug_decode_uint32_be(const uint8_t* bytes);
void foug_encode_uint32_le(uint32_t val, uint8_t* bytes);
foug_real32_t foug_decode_real32_le(const uint8_t* bytes);
foug_real32_t foug_decode_real32_me(const uint8_t* bytes);
foug_real32_t foug_decode_real32_be(const uint8_t* bytes);
void foug_encode_real32_le(foug_real32_t val, uint8_t* bytes);
#endif /* FOUG_ENDIAN_H */

View File

@ -0,0 +1,10 @@
#ifndef FOUG_C_LIBSTL_STLB_GLOBAL_H
#define FOUG_C_LIBSTL_STLB_GLOBAL_H
#include "../foug_global.h"
#define FOUG_STLB_HEADER_SIZE 80
#define FOUG_STLB_MIN_CONTENTS_SIZE 284
#define FOUG_STLB_TRIANGLE_SIZE 50 /* 12 * sizeof(foug_real32_t) + sizeof(uint16_t) */
#endif /* FOUG_C_LIBSTL_STLB_GLOBAL_H */

View File

@ -1,20 +1,21 @@
#include "stlb_read.h"
#include "stlb_global.h"
#include "../endian.h"
struct _internal_foug_stlb_geom
struct _internal_foug_stlb_geom_input
{
void* cookie;
foug_stlb_geom_input_manip_t manip;
};
foug_stlb_geom_t* foug_stlb_geom_create(foug_malloc_func_t func,
void* data,
foug_stlb_geom_input_manip_t manip)
foug_stlb_geom_input_t* foug_stlb_geom_input_create(foug_malloc_func_t func,
void* data,
foug_stlb_geom_input_manip_t manip)
{
if (func == NULL)
return NULL;
foug_stlb_geom_t* geom = (*func)(sizeof(struct _internal_foug_stlb_geom));
foug_stlb_geom_input_t* geom = (*func)(sizeof(struct _internal_foug_stlb_geom_input));
if (geom != NULL) {
geom->cookie = data;
geom->manip = manip;
@ -22,14 +23,11 @@ foug_stlb_geom_t* foug_stlb_geom_create(foug_malloc_func_t func,
return geom;
}
void* foug_stlb_geom_get_cookie(const foug_stlb_geom_t* geom)
void* foug_stlb_geom_input_get_cookie(const foug_stlb_geom_input_t* geom)
{
return geom != NULL ? geom->cookie : NULL;
}
static const int stlb_min_file_size = 284;
static const int stlb_facet_size = (4 * 3) * sizeof(foug_real32_t) + sizeof(uint16_t);
static foug_bool_t foug_stlb_no_error(int code)
{
return code == FOUG_STLB_READ_NO_ERROR;
@ -37,8 +35,8 @@ static foug_bool_t foug_stlb_no_error(int code)
int foug_stlb_read(foug_stlb_read_args_t args)
{
if (args.geom == NULL)
return FOUG_STLB_READ_NULL_GEOM_ERROR;
if (args.geom_input == NULL)
return FOUG_STLB_READ_NULL_GEOM_INPUT_ERROR;
if (args.stream == NULL)
return FOUG_STLB_READ_NULL_STREAM_ERROR;
if (args.buffer_size == 0)
@ -47,20 +45,20 @@ int foug_stlb_read(foug_stlb_read_args_t args)
uint8_t buffer[8192];
/* Read header */
uint8_t header_data[foug_stlb_header_size];
if (foug_stream_read(args.stream, header_data, 1, foug_stlb_header_size) != foug_stlb_header_size)
uint8_t header_data[FOUG_STLB_HEADER_SIZE];
if (foug_stream_read(args.stream, header_data, 1, FOUG_STLB_HEADER_SIZE) != FOUG_STLB_HEADER_SIZE)
return FOUG_STLB_READ_HEADER_WRONG_SIZE_ERROR;
if (args.geom->manip.process_header_func != NULL)
(*(args.geom->manip.process_header_func))(args.geom, header_data);
if (args.geom_input->manip.process_header_func != NULL)
(*(args.geom_input->manip.process_header_func))(args.geom_input, header_data);
/* Read facet count */
if (foug_stream_read(args.stream, buffer, sizeof(uint32_t), 1) != 1)
return FOUG_STLB_READ_FACET_COUNT_ERROR;
const uint32_t total_facet_count = foug_decode_uint32_le(buffer);
if (args.geom->manip.begin_triangles_func != NULL)
(*(args.geom->manip.begin_triangles_func))(args.geom, total_facet_count);
if (args.geom_input->manip.begin_triangles_func != NULL)
(*(args.geom_input->manip.begin_triangles_func))(args.geom_input, total_facet_count);
foug_task_control_reset(args.task_control);
foug_task_control_set_range(args.task_control, 0., (foug_real32_t)total_facet_count);
@ -72,7 +70,7 @@ int foug_stlb_read(foug_stlb_read_args_t args)
int error = FOUG_STLB_READ_NO_ERROR;
while (foug_stlb_no_error(error) && accum_facet_count_read < total_facet_count) {
const size_t facet_count_read =
foug_stream_read(args.stream, buffer, stlb_facet_size, buffer_facet_count);
foug_stream_read(args.stream, buffer, FOUG_STLB_TRIANGLE_SIZE, buffer_facet_count);
error = foug_stream_error(args.stream) != 0 ? FOUG_STLB_READ_STREAM_ERROR :
FOUG_STLB_READ_NO_ERROR;
if (foug_stlb_no_error(error)) {
@ -104,10 +102,13 @@ int foug_stlb_read(foug_stlb_read_args_t args)
foug_decode_uint16_le(buffer + 12*sizeof(foug_real32_t) + buffer_offset);
/* Add triangle */
if (args.geom->manip.process_next_triangle_func != NULL)
(*(args.geom->manip.process_next_triangle_func))(args.geom, &triangle, attribute_byte_count);
if (args.geom_input->manip.process_next_triangle_func != NULL) {
(*(args.geom_input->manip.process_next_triangle_func))(args.geom_input,
&triangle,
attribute_byte_count);
}
buffer_offset += stlb_facet_size;
buffer_offset += FOUG_STLB_TRIANGLE_SIZE;
} /* end for */
accum_facet_count_read += facet_count_read;
@ -121,8 +122,8 @@ int foug_stlb_read(foug_stlb_read_args_t args)
}
} /* end while */
if (foug_stlb_no_error(error) && args.geom->manip.end_triangles_func != NULL)
(*(args.geom->manip.end_triangles_func))(args.geom);
if (foug_stlb_no_error(error) && args.geom_input->manip.end_triangles_func != NULL)
(*(args.geom_input->manip.end_triangles_func))(args.geom_input);
if (foug_stlb_no_error(error) && accum_facet_count_read != total_facet_count)
error = FOUG_STLB_READ_FACET_COUNT_ERROR;

View File

@ -6,16 +6,14 @@
#include "../stream.h"
#include "../task_control.h"
enum { foug_stlb_header_size = 80 };
/* foug_stlb_geom : opaque structure */
typedef struct _internal_foug_stlb_geom foug_stlb_geom_t;
typedef void (*foug_stlb_geom_input_process_header_func_t)(foug_stlb_geom_t*, const uint8_t*);
typedef void (*foug_stlb_geom_input_begin_triangles_func_t)(foug_stlb_geom_t*, uint32_t);
typedef void (*foug_stlb_geom_input_process_next_triangle_func_t)(foug_stlb_geom_t*,
/* foug_stlb_geom_input : opaque structure */
typedef struct _internal_foug_stlb_geom_input foug_stlb_geom_input_t;
typedef void (*foug_stlb_geom_input_process_header_func_t)(foug_stlb_geom_input_t*, const uint8_t*);
typedef void (*foug_stlb_geom_input_begin_triangles_func_t)(foug_stlb_geom_input_t*, uint32_t);
typedef void (*foug_stlb_geom_input_process_next_triangle_func_t)(foug_stlb_geom_input_t*,
const foug_stl_triangle_t*,
uint16_t);
typedef void (*foug_stlb_geom_input_end_triangles_func_t)(foug_stlb_geom_t*);
typedef void (*foug_stlb_geom_input_end_triangles_func_t)(foug_stlb_geom_input_t*);
typedef struct
{
@ -25,24 +23,24 @@ typedef struct
foug_stlb_geom_input_end_triangles_func_t end_triangles_func;
} foug_stlb_geom_input_manip_t;
foug_stlb_geom_t* foug_stlb_geom_create(foug_malloc_func_t func,
void* data,
foug_stlb_geom_input_manip_t manip);
foug_stlb_geom_input_t* foug_stlb_geom_input_create(foug_malloc_func_t func,
void* data,
foug_stlb_geom_input_manip_t manip);
void* foug_stlb_geom_get_cookie(const foug_stlb_geom_t* geom);
void* foug_stlb_geom_input_get_cookie(const foug_stlb_geom_input_t* geom);
typedef struct
{
foug_stlb_geom_t* geom;
foug_stlb_geom_input_t* geom_input;
foug_stream_t* stream;
foug_task_control_t* task_control;
uint32_t buffer_size;
} foug_stlb_read_args_t;
int foug_stlb_read(foug_stlb_read_args_t args);
#define FOUG_STLB_READ_NO_ERROR 0;
#define FOUG_STLB_READ_NULL_GEOM_ERROR 1;
#define FOUG_STLB_READ_NULL_STREAM_ERROR 2;
#define FOUG_STLB_READ_NO_ERROR 0
#define FOUG_STLB_READ_NULL_GEOM_INPUT_ERROR 1
#define FOUG_STLB_READ_NULL_STREAM_ERROR 2
#define FOUG_STLB_READ_INVALID_BUFFER_SIZE_ERROR 3
#define FOUG_STLB_READ_HEADER_WRONG_SIZE_ERROR 4
#define FOUG_STLB_READ_FACET_COUNT_ERROR 5

120
src/c/libstl/stlb_write.c Normal file
View File

@ -0,0 +1,120 @@
#include "stlb_write.h"
#include "stlb_global.h"
#include "../endian.h"
#include <string.h>
struct _internal_foug_stlb_geom_output
{
void* cookie;
foug_stlb_geom_output_manip_t manip;
};
foug_stlb_geom_output_t* foug_stlb_geom_output_create(foug_malloc_func_t func,
void* data,
foug_stlb_geom_output_manip_t manip)
{
if (func == NULL)
return NULL;
foug_stlb_geom_output_t* geom = (*func)(sizeof(struct _internal_foug_stlb_geom_output));
if (geom != NULL) {
geom->cookie = data;
geom->manip = manip;
}
return geom;
}
void* foug_stlb_geom_output_get_cookie(const foug_stlb_geom_output_t* geom)
{
return geom != NULL ? geom->cookie : NULL;
}
static foug_bool_t foug_stlb_no_error(int code)
{
return code == FOUG_STLB_WRITE_NO_ERROR;
}
int foug_stlb_write(foug_stlb_write_args_t args)
{
if (args.geom_output == NULL)
return FOUG_STLB_WRITE_NULL_GEOM_OUTPUT_ERROR;
if (args.stream == NULL)
return FOUG_STLB_WRITE_NULL_STREAM_ERROR;
if (args.buffer_size == 0)
return FOUG_STLB_WRITE_INVALID_BUFFER_SIZE_ERROR;
if (args.geom_output->manip.get_triangle_count_func == NULL)
return FOUG_STLB_WRITE_NULL_GET_TRIANGLE_COUNT_FUNC;
if (args.geom_output->manip.get_triangle_func == NULL)
return FOUG_STLB_WRITE_NULL_GET_TRIANGLE_FUNC;
uint8_t buffer[128];
/* Write header */
uint8_t header_data[FOUG_STLB_HEADER_SIZE];
if (args.geom_output->manip.get_header_func != NULL)
(*(args.geom_output->manip.get_header_func))(args.geom_output, header_data);
else
memset(header_data, 0, FOUG_STLB_HEADER_SIZE);
if (foug_stream_write(args.stream, header_data, FOUG_STLB_HEADER_SIZE, 1) != 1)
return FOUG_STLB_WRITE_HEADER_ERROR;
/* Write facet count */
const uint32_t facet_count = (*(args.geom_output->manip.get_triangle_count_func))(args.geom_output);
foug_encode_uint32_le(facet_count, buffer);
if (foug_stream_write(args.stream, buffer, sizeof(uint32_t), 1) != 1)
return FOUG_STLB_WRITE_STREAM_ERROR;
foug_task_control_reset(args.task_control);
foug_task_control_set_range(args.task_control, 0., (foug_real32_t)facet_count);
/* Write triangles */
foug_stl_triangle_t triangle;
uint16_t attr_byte_count = 0;
uint32_t i_facet;
int error = FOUG_STLB_WRITE_NO_ERROR;
for (i_facet = 0; i_facet < facet_count && foug_stlb_no_error(error); ++i_facet) {
(*(args.geom_output->manip.get_triangle_func))(args.geom_output, i_facet,
&triangle, &attr_byte_count);
/* Normal */
foug_encode_real32_le(triangle.normal.x, buffer);
foug_encode_real32_le(triangle.normal.y, buffer + 1*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.normal.z, buffer + 2*sizeof(foug_real32_t));
/* Vertex1 */
foug_encode_real32_le(triangle.v1.x, buffer + 3*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.v1.y, buffer + 4*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.v1.z, buffer + 5*sizeof(foug_real32_t));
/* Vertex2 */
foug_encode_real32_le(triangle.v2.x, buffer + 6*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.v2.y, buffer + 7*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.v2.z, buffer + 8*sizeof(foug_real32_t));
/* Vertex3 */
foug_encode_real32_le(triangle.v3.x, buffer + 9*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.v3.y, buffer + 10*sizeof(foug_real32_t));
foug_encode_real32_le(triangle.v3.z, buffer + 11*sizeof(foug_real32_t));
/* Attribute byte count */
foug_encode_uint16_le(attr_byte_count, buffer + 12*sizeof(foug_real32_t));
/* Write to stream */
if (foug_stream_write(args.stream, buffer, FOUG_STLB_TRIANGLE_SIZE, 1) != 1)
error = FOUG_STLB_WRITE_NULL_STREAM_ERROR;
/* Task control */
if (foug_stlb_no_error(error)) {
if (foug_task_control_is_stop_requested(args.task_control)) {
foug_task_control_handle_stop(args.task_control);
error = FOUG_STLB_WRITE_TASK_STOPPED_ERROR;
}
else {
foug_task_control_set_progress(args.task_control, i_facet + 1);
}
}
} /* end for */
return error;
}

55
src/c/libstl/stlb_write.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef FOUG_C_LIBSTL_STLB_WRITE_H
#define FOUG_C_LIBSTL_STLB_WRITE_H
#include "triangle.h"
#include "../foug_global.h"
#include "../stream.h"
#include "../task_control.h"
enum { foug_stlb_header_size = 80 };
/* foug_stlb_geom_output : opaque structure */
typedef struct _internal_foug_stlb_geom_output foug_stlb_geom_output_t;
typedef void (*foug_stlb_geom_output_get_header_func_t)(const foug_stlb_geom_output_t*, uint8_t*);
typedef uint32_t (*foug_stlb_geom_output_get_triangle_count_func_t)(const foug_stlb_geom_output_t*);
typedef void (*foug_stlb_geom_output_get_triangle_func_t)(const foug_stlb_geom_output_t*,
uint32_t,
foug_stl_triangle_t*,
uint16_t*);
typedef struct
{
foug_stlb_geom_output_get_header_func_t get_header_func;
foug_stlb_geom_output_get_triangle_count_func_t get_triangle_count_func;
foug_stlb_geom_output_get_triangle_func_t get_triangle_func;
} foug_stlb_geom_output_manip_t;
foug_stlb_geom_output_t* foug_stlb_geom_output_create(foug_malloc_func_t func,
void* data,
foug_stlb_geom_output_manip_t manip);
void* foug_stlb_geom_output_get_cookie(const foug_stlb_geom_output_t* geom);
typedef struct
{
foug_stlb_geom_output_t* geom_output;
foug_stream_t* stream;
foug_task_control_t* task_control;
uint32_t buffer_size;
} foug_stlb_write_args_t;
int foug_stlb_write(foug_stlb_write_args_t args);
#define FOUG_STLB_WRITE_NO_ERROR 0
#define FOUG_STLB_WRITE_NULL_GEOM_OUTPUT_ERROR 1
#define FOUG_STLB_WRITE_NULL_STREAM_ERROR 2
#define FOUG_STLB_WRITE_NULL_GET_TRIANGLE_COUNT_FUNC 3
#define FOUG_STLB_WRITE_NULL_GET_TRIANGLE_FUNC 4
#define FOUG_STLB_WRITE_INVALID_BUFFER_SIZE_ERROR 3
#define FOUG_STLB_WRITE_HEADER_ERROR 4
#define FOUG_STLB_WRITE_FACET_COUNT_ERROR 5
#define FOUG_STLB_WRITE_STREAM_ERROR 6
#define FOUG_STLB_WRITE_TASK_STOPPED_ERROR 7
#endif /* FOUG_C_LIBSTL_STLB_WRITE_H */