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/memory.h \
../../../src/c/stream.h \ ../../../src/c/stream.h \
../../../src/c/task_control.h \ ../../../src/c/task_control.h \
../../../src/c/libstl/stlb_global.h \
../../../src/c/libstl/stlb_read.h \ ../../../src/c/libstl/stlb_read.h \
../../../src/c/libstl/stlb_write.h \
../../../src/c/libstl/triangle.h ../../../src/c/libstl/triangle.h
SOURCES += \ SOURCES += \
../../../src/c/endian.c \ ../../../src/c/endian.c \
../../../src/c/stream.c \ ../../../src/c/stream.c \
../../../src/c/task_control.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 *-g++*:QMAKE_CFLAGS += -ansi

View File

@ -1,5 +1,15 @@
#include "endian.h" #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() foug_endianness_t foug_host_endianness()
{ {
union { union {
@ -42,6 +52,11 @@ uint16_t foug_decode_uint16_be(const uint8_t* bytes)
return (bytes[0] << 8) | bytes[1]; 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) uint32_t foug_uint32_swap(uint32_t val)
{ {
return 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); 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) static foug_real32_t convert_real32(uint32_t val)
{ {
union union
@ -100,3 +120,8 @@ foug_real32_t foug_decode_real32_be(const uint8_t* bytes)
{ {
return convert_real32(foug_decode_uint32_be(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_uint16_noswap(uint16_t val);
uint16_t foug_decode_uint16_le(const uint8_t* bytes); uint16_t foug_decode_uint16_le(const uint8_t* bytes);
uint16_t foug_decode_uint16_be(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_swap(uint32_t val);
uint32_t foug_uint32_noswap(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_le(const uint8_t* bytes);
uint32_t foug_decode_uint32_me(const uint8_t* bytes); uint32_t foug_decode_uint32_me(const uint8_t* bytes);
uint32_t foug_decode_uint32_be(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_le(const uint8_t* bytes);
foug_real32_t foug_decode_real32_me(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); 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 */ #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_read.h"
#include "stlb_global.h"
#include "../endian.h" #include "../endian.h"
struct _internal_foug_stlb_geom struct _internal_foug_stlb_geom_input
{ {
void* cookie; void* cookie;
foug_stlb_geom_input_manip_t manip; foug_stlb_geom_input_manip_t manip;
}; };
foug_stlb_geom_t* foug_stlb_geom_create(foug_malloc_func_t func, foug_stlb_geom_input_t* foug_stlb_geom_input_create(foug_malloc_func_t func,
void* data, void* data,
foug_stlb_geom_input_manip_t manip) foug_stlb_geom_input_manip_t manip)
{ {
if (func == NULL) if (func == NULL)
return 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) { if (geom != NULL) {
geom->cookie = data; geom->cookie = data;
geom->manip = manip; geom->manip = manip;
@ -22,14 +23,11 @@ foug_stlb_geom_t* foug_stlb_geom_create(foug_malloc_func_t func,
return geom; 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; 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) static foug_bool_t foug_stlb_no_error(int code)
{ {
return code == FOUG_STLB_READ_NO_ERROR; 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) int foug_stlb_read(foug_stlb_read_args_t args)
{ {
if (args.geom == NULL) if (args.geom_input == NULL)
return FOUG_STLB_READ_NULL_GEOM_ERROR; return FOUG_STLB_READ_NULL_GEOM_INPUT_ERROR;
if (args.stream == NULL) if (args.stream == NULL)
return FOUG_STLB_READ_NULL_STREAM_ERROR; return FOUG_STLB_READ_NULL_STREAM_ERROR;
if (args.buffer_size == 0) if (args.buffer_size == 0)
@ -47,20 +45,20 @@ int foug_stlb_read(foug_stlb_read_args_t args)
uint8_t buffer[8192]; uint8_t buffer[8192];
/* Read header */ /* Read header */
uint8_t header_data[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) 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; return FOUG_STLB_READ_HEADER_WRONG_SIZE_ERROR;
if (args.geom->manip.process_header_func != NULL) if (args.geom_input->manip.process_header_func != NULL)
(*(args.geom->manip.process_header_func))(args.geom, header_data); (*(args.geom_input->manip.process_header_func))(args.geom_input, header_data);
/* Read facet count */ /* Read facet count */
if (foug_stream_read(args.stream, buffer, sizeof(uint32_t), 1) != 1) if (foug_stream_read(args.stream, buffer, sizeof(uint32_t), 1) != 1)
return FOUG_STLB_READ_FACET_COUNT_ERROR; return FOUG_STLB_READ_FACET_COUNT_ERROR;
const uint32_t total_facet_count = foug_decode_uint32_le(buffer); const uint32_t total_facet_count = foug_decode_uint32_le(buffer);
if (args.geom->manip.begin_triangles_func != NULL) if (args.geom_input->manip.begin_triangles_func != NULL)
(*(args.geom->manip.begin_triangles_func))(args.geom, total_facet_count); (*(args.geom_input->manip.begin_triangles_func))(args.geom_input, total_facet_count);
foug_task_control_reset(args.task_control); foug_task_control_reset(args.task_control);
foug_task_control_set_range(args.task_control, 0., (foug_real32_t)total_facet_count); 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; int error = FOUG_STLB_READ_NO_ERROR;
while (foug_stlb_no_error(error) && accum_facet_count_read < total_facet_count) { while (foug_stlb_no_error(error) && accum_facet_count_read < total_facet_count) {
const size_t facet_count_read = 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 : error = foug_stream_error(args.stream) != 0 ? FOUG_STLB_READ_STREAM_ERROR :
FOUG_STLB_READ_NO_ERROR; FOUG_STLB_READ_NO_ERROR;
if (foug_stlb_no_error(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); foug_decode_uint16_le(buffer + 12*sizeof(foug_real32_t) + buffer_offset);
/* Add triangle */ /* Add triangle */
if (args.geom->manip.process_next_triangle_func != NULL) if (args.geom_input->manip.process_next_triangle_func != NULL) {
(*(args.geom->manip.process_next_triangle_func))(args.geom, &triangle, attribute_byte_count); (*(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 */ } /* end for */
accum_facet_count_read += facet_count_read; accum_facet_count_read += facet_count_read;
@ -121,8 +122,8 @@ int foug_stlb_read(foug_stlb_read_args_t args)
} }
} /* end while */ } /* end while */
if (foug_stlb_no_error(error) && args.geom->manip.end_triangles_func != NULL) if (foug_stlb_no_error(error) && args.geom_input->manip.end_triangles_func != NULL)
(*(args.geom->manip.end_triangles_func))(args.geom); (*(args.geom_input->manip.end_triangles_func))(args.geom_input);
if (foug_stlb_no_error(error) && accum_facet_count_read != total_facet_count) if (foug_stlb_no_error(error) && accum_facet_count_read != total_facet_count)
error = FOUG_STLB_READ_FACET_COUNT_ERROR; error = FOUG_STLB_READ_FACET_COUNT_ERROR;

View File

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