star-3daw

Create star-3d geometries from OBJ files
git clone git://git.meso-star.fr/star-3daw.git
Log | Files | Refs | README | LICENSE

commit 93668ff4dc34e44f1a1ebf444b7b5890269293b4
parent 0044bb951983f9708c120b0914da60cbee646228
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 21 Feb 2020 16:09:55 +0100

Merge branch 'release_0.4'

Diffstat:
MREADME.md | 15+++++++++++----
Mcmake/CMakeLists.txt | 8++++----
Msrc/s3daw.c | 361+++++++++++++++++++++++++------------------------------------------------------
Msrc/s3daw.h | 2+-
Msrc/test_s3daw.c | 2+-
5 files changed, 132 insertions(+), 256 deletions(-)

diff --git a/README.md b/README.md @@ -22,10 +22,17 @@ generate the project from the `cmake/CMakeLists.txt` file by appending to the dependencies. The generated project can be edited, built, tested and installed as any CMake project. +## Release notes + +### Version 0.4 + +- Bump the version of the AW dependency to 2.0:.uUdate the code to handle the + API breaks introduce by this update. + ## License -Star-3DAW is Copyright (C) |Meso|Star> 2015-2016 (<contact@meso-star.com>). It -is a free software released under the [OSI](http://opensource.org)-approved -CeCILL license. You are welcome to redistribute it under certain conditions; -refer to the COPYING files for details. +Copyright (C) 2015, 2016, 2020 |Meso|Star> (<contact@meso-star.com>). Star-3DAW +is free software released under the CeCILLv2.1 license. You are welcome to +redistribute it under certain conditions; refer to the COPYING files for +details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +# Copyright (C) 2015, 2016, 2020 |Meso|Star> (contact@meso-star.com) # # This software is governed by the CeCILL license under French law and # abiding by the rules of distribution of free software. You can use, @@ -36,7 +36,7 @@ option(NO_TEST "Disable the test" OFF) ################################################################################ # Check dependencies ################################################################################ -find_package(AW 1.2.0 REQUIRED) +find_package(AW 2.0.0 REQUIRED) find_package(Polygon 0.1 REQUIRED) find_package(RCMake 0.2 REQUIRED) find_package(RSys 0.6 REQUIRED) @@ -56,8 +56,8 @@ include(rcmake_runtime) # Configure and define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 3) -set(VERSION_PATCH 1) +set(VERSION_MINOR 4) +set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(S3DAW_FILES_SRC s3daw.c) diff --git a/src/s3daw.c b/src/s3daw.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) 2015, 2016, 2020 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, @@ -30,8 +30,8 @@ #include "s3daw.h" -#include <rsys/dynamic_array_char.h> -#include <rsys/dynamic_array_size_t.h> +#include <rsys/dynamic_array_uint.h> +#include <rsys/dynamic_array_float.h> #include <rsys/float3.h> #include <rsys/float4.h> #include <rsys/hash_table.h> @@ -45,30 +45,13 @@ #include <polygon.h> #include <string.h> -#ifdef COMPILER_GCC - #include <libgen.h> /* dirname function */ -#endif - #define DARRAY_NAME shape #define DARRAY_DATA struct s3d_shape* #include <rsys/dynamic_array.h> -#define DARRAY_NAME vertex -#define DARRAY_DATA struct aw_obj_vertex -#include <rsys/dynamic_array.h> - -static FINLINE char -vertex_eq(const struct aw_obj_vertex* v0, const struct aw_obj_vertex* v1) -{ - return f4_eq_eps(v0->position, v1->position, 1.e-6f) - && f3_eq_eps(v0->normal, v1->normal, 1.e-6f) - && f3_eq_eps(v0->texcoord, v1->texcoord, 1.e-6f); -} - #define HTABLE_NAME vertex_id -#define HTABLE_DATA uint64_t -#define HTABLE_KEY struct aw_obj_vertex -#define HTABLE_KEY_FUNCTOR_EQ vertex_eq +#define HTABLE_DATA unsigned +#define HTABLE_KEY size_t #include <rsys/hash_table.h> #define HTABLE_NAME material @@ -80,196 +63,165 @@ vertex_eq(const struct aw_obj_vertex* v0, const struct aw_obj_vertex* v1) #define HTABLE_KEY_FUNCTOR_COPY str_copy #define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release #define HTABLE_KEY_FUNCTOR_RELEASE str_release -#define HTABLE_DATA_FUNCTOR_INIT aw_material_init -#define HTABLE_DATA_FUNCTOR_COPY aw_material_copy -#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE aw_material_copy_and_release -#define HTABME_DATA_FUNCTOR_RELEASE aw_material_release #include <rsys/hash_table.h> struct s3daw { - ref_T ref; - struct mem_allocator* allocator; - struct logger* logger; - int verbose; - struct aw_obj* loader_obj; struct aw_mtl* loader_mtl; struct polygon* polygon; struct s3d_device* s3d; + struct darray_shape shapes; - /* Scratch data structure used during shape registration */ - struct aw_obj_named_group mtl; /* Material of primitive soup */ - struct darray_size_t indices; /* Triangle indices */ - struct darray_vertex vertices; /* float[3], vertex coordinates */ - struct darray_char mtllib; /* Temp buffer for the mtllib filename */ - struct htable_vertex_id vertices_ids; /* Map a aw_obj_vertex to an id */ - struct htable_material materials; /* Map a material name to an aw_material */ + int verbose; + + struct mem_allocator* allocator; + struct logger* logger; + ref_T ref; +}; + +struct context { + const struct darray_float* positions; + const struct darray_uint* indices; }; /******************************************************************************* * Helper functions ******************************************************************************/ static void -get_indices(const unsigned itri, unsigned ids[3], void* ctx) +get_indices(const unsigned itri, unsigned ids[3], void* context) { - struct s3daw* s3daw = ctx; - const size_t* indices; - ASSERT(ids && ctx && itri < darray_size_t_size_get(&s3daw->indices)/3); - indices = darray_size_t_cdata_get(&s3daw->indices) + itri * 3; - ids[0] = (unsigned)indices[0]; - ids[1] = (unsigned)indices[1]; - ids[2] = (unsigned)indices[2]; + struct context* ctx = context; + const unsigned* indices; + ASSERT(ids && ctx && itri < darray_uint_size_get(ctx->indices)/3); + indices = darray_uint_cdata_get(ctx->indices) + itri*3; + ids[0] = indices[0]; + ids[1] = indices[1]; + ids[2] = indices[2]; } static void -get_position(const unsigned ivert, float pos[3], void* ctx) +get_position(const unsigned ivert, float pos[3], void* context) { - struct s3daw* s3daw = ctx; - const struct aw_obj_vertex* vertex; - ASSERT(ctx && pos && ivert < darray_vertex_size_get(&s3daw->vertices)); - vertex = darray_vertex_cdata_get(&s3daw->vertices) + ivert; - f3_set(pos, vertex->position); + struct context* ctx = context; + const float* position; + ASSERT(ctx && pos && ivert < darray_float_size_get(ctx->positions)/3); + position = darray_float_cdata_get(ctx->positions) + ivert*3; + pos[0] = position[0]; + pos[1] = position[1]; + pos[2] = position[2]; } -#ifdef COMPILER_CL -/* On MSVC mime the dirname POSIX function */ -static INLINE char* -dirname(char* filename) +static INLINE void +shapes_clear(struct darray_shape* shapes) { - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - size_t drive_len, dir_len; - errno_t err; - ASSERT(filename); - - err = _splitpath_s - (filename, drive, sizeof(drive), dir, sizeof(dir), NULL, 0, NULL, 0); - ASSERT(err == 0); - drive_len = strlen(drive); - dir_len = strlen(dir); - if(!drive_len && !dir_len) { - ASSERT(strlen(filename) >= 1); - filename[0] = '.'; - filename[1] = '\0'; - } else { - if(dir_len && dir[dir_len - 1] == '/') - dir[--dir_len] = '\0'; - ASSERT(strlen(filename) >= drive_len + dir_len); - strncpy(filename, drive, drive_len); - strncpy(filename + drive_len, dir, dir_len + 1/*'\0'*/); + size_t i; + ASSERT(shapes); + FOR_EACH(i, 0, darray_shape_size_get(shapes)) { + S3D(shape_ref_put(darray_shape_data_get(shapes)[i])); } - return filename; -} -#endif - -static INLINE res_T -get_dirname(const char* filename, struct darray_char* filedir) -{ - const char* dir; - size_t dir_len; - res_T res = RES_OK; - ASSERT(filename && filedir); - - res = darray_char_resize(filedir, strlen(filename) + 1/*'\0'*/); - if(res != RES_OK) goto error; - - strcpy(darray_char_data_get(filedir), filename); - dir = dirname(darray_char_data_get(filedir)); - dir_len = strlen(dir); - - res = darray_char_resize(filedir, dir_len + 1/*'/'*/); - if(res != RES_OK) goto error; - - memmove(darray_char_data_get(filedir), dir, dir_len); - darray_char_data_get(filedir)[dir_len] = '/'; - -exit: - return res; -error: - darray_char_clear(filedir); - goto exit; + darray_shape_clear(shapes); } static res_T -shape_register(struct s3daw* s3daw, const struct aw_obj_named_group* obj_mtl) +shape_register + (struct s3daw* s3daw, + const struct aw_obj_named_group* obj_mtl, + struct darray_float* vertices, + struct darray_uint* indices, + struct htable_vertex_id* vertices_ids) { + struct context ctx; struct s3d_vertex_data vertex_data; struct s3d_shape* shape = NULL; size_t iface; size_t ntris, nverts; - res_T res = RES_OK; - ASSERT(s3daw && obj_mtl); + ASSERT(s3daw && obj_mtl && vertices && indices && vertices_ids); /* Reset the scrach shape data */ - darray_vertex_clear(&s3daw->vertices); - darray_size_t_clear(&s3daw->indices); - htable_vertex_id_clear(&s3daw->vertices_ids); + darray_float_clear(vertices); + darray_uint_clear(indices); + htable_vertex_id_clear(vertices_ids); FOR_EACH(iface, obj_mtl->face_id, obj_mtl->face_id + obj_mtl->faces_count) { struct aw_obj_face face; struct aw_obj_vertex vertex; + struct aw_obj_vertex_data vdata; const uint32_t* tri_ids; uint32_t ntri_ids; size_t ivertex; size_t i; - AW(obj_face_get(s3daw->loader_obj, iface, &face)); + AW(obj_get_face(s3daw->loader_obj, iface, &face)); /* Triangulate the face */ POLYGON(clear(s3daw->polygon)); FOR_EACH(ivertex, face.vertex_id, face.vertex_id + face.vertices_count) { - AW(obj_vertex_get(s3daw->loader_obj, ivertex, &vertex)); - res = polygon_vertex_add(s3daw->polygon, vertex.position); + float position[3]; + AW(obj_get_vertex(s3daw->loader_obj, ivertex, &vertex)); + AW(obj_get_vertex_data(s3daw->loader_obj, &vertex, &vdata)); + position[0] = (float)vdata.position[0]; + position[1] = (float)vdata.position[1]; + position[2] = (float)vdata.position[2]; + res = polygon_vertex_add(s3daw->polygon, position); if(res != RES_OK) goto error; } res = polygon_triangulate(s3daw->polygon, &tri_ids, &ntri_ids); if(res != RES_OK) goto error; FOR_EACH(i, 0, ntri_ids) { - size_t* ivertex_registered; + unsigned* ivertex_registered; /* Define if the obj_face vertex is already registered */ ivertex = tri_ids[i] + face.vertex_id; - AW(obj_vertex_get(s3daw->loader_obj, ivertex, &vertex)); - ivertex_registered = htable_vertex_id_find(&s3daw->vertices_ids, &vertex); + AW(obj_get_vertex(s3daw->loader_obj, ivertex, &vertex)); + ivertex_registered = htable_vertex_id_find(vertices_ids, &vertex.position_id); if(ivertex_registered) { /* Vertex is registered. Simply add its id to the indices */ - res = darray_size_t_push_back(&s3daw->indices, ivertex_registered); + res = darray_uint_push_back(indices, ivertex_registered); if(res != RES_OK) goto error; } else { /* Vertex is not registered. Register it and add its id to the indices */ - const size_t ivertex_new = darray_vertex_size_get(&s3daw->vertices); - res = darray_vertex_push_back(&s3daw->vertices, &vertex); - if(res != RES_OK) goto error; - res = darray_size_t_push_back(&s3daw->indices, &ivertex_new); - if(res != RES_OK) goto error; - res = htable_vertex_id_set(&s3daw->vertices_ids, &vertex, &ivertex_new); - if(res != RES_OK) goto error; + float position[3]; + const unsigned ivertex_new = (unsigned)darray_float_size_get(vertices)/3; + + AW(obj_get_vertex_data(s3daw->loader_obj, &vertex, &vdata)); + position[0] = (float)vdata.position[0]; + position[1] = (float)vdata.position[1]; + position[2] = (float)vdata.position[2]; + + #define CALL(Func) if((res = Func) != RES_OK) goto error; + CALL(darray_float_push_back(vertices, position+0)); + CALL(darray_float_push_back(vertices, position+1)); + CALL(darray_float_push_back(vertices, position+2)); + CALL(darray_uint_push_back(indices, &ivertex_new)); + CALL(htable_vertex_id_set(vertices_ids, &vertex.position_id, &ivertex_new)); + #undef CALL } } } - /* Create the S3D shape */ - - nverts = darray_vertex_size_get(&s3daw->vertices); - ntris = darray_size_t_size_get(&s3daw->indices); - if(!ntris) goto exit; - ASSERT(!(ntris % 3)); - ntris /= 3; + nverts = darray_float_size_get(vertices) / 3; + ntris = darray_uint_size_get(indices) / 3; + if(!ntris) goto exit; /* Nothing to do */ res = s3d_shape_create_mesh(s3daw->s3d, &shape); if(res != RES_OK) goto error; + vertex_data.usage = S3D_POSITION; vertex_data.type = S3D_FLOAT3; vertex_data.get = get_position; + ctx.indices = indices; + ctx.positions = vertices; + /* Setup the S3D mesh data */ res = s3d_mesh_setup_indexed_vertices(shape, (unsigned)ntris, get_indices, - (unsigned)nverts, &vertex_data, 1, s3daw); + (unsigned)nverts, &vertex_data, 1, &ctx); if(res != RES_OK) goto error; + /* Register the shape */ res = darray_shape_push_back(&s3daw->shapes, &shape); if(res != RES_OK) goto error; @@ -280,46 +232,27 @@ error: goto exit; } -static void -materials_clear(struct htable_material* materials) -{ - struct htable_material_iterator it, end; - ASSERT(materials); - - htable_material_begin(materials, &it); - htable_material_end(materials, &end); - while(!htable_material_iterator_eq(&it, &end)) { - struct aw_material* material = htable_material_iterator_data_get(&it); - htable_material_iterator_next(&it); - AW(material_release(material)); - } - htable_material_clear(materials); -} - -static INLINE void -shapes_clear(struct darray_shape* shapes) -{ - size_t i; - ASSERT(shapes); - FOR_EACH(i, 0, darray_shape_size_get(shapes)) { - S3D(shape_ref_put(darray_shape_data_get(shapes)[i])); - } - darray_shape_clear(shapes); -} - static res_T shapes_create(struct s3daw* s3daw, const char* filename) { + struct darray_uint indices; + struct darray_float vertices; + struct htable_vertex_id vertices_ids; struct aw_obj_desc obj_desc; - struct aw_material material; - size_t imtl; + struct aw_obj_named_group grp; res_T res = RES_OK; ASSERT(s3daw && filename); - AW(material_init(s3daw->allocator, &material)); - AW(obj_desc_get(s3daw->loader_obj, &obj_desc)); + /* Clean up the previously created shapes */ shapes_clear(&s3daw->shapes); + /* Init scratch data structures */ + darray_uint_init(s3daw->allocator, &indices); + darray_float_init(s3daw->allocator, &vertices); + htable_vertex_id_init(s3daw->allocator, &vertices_ids); + + AW(obj_get_desc(s3daw->loader_obj, &obj_desc)); + if(obj_desc.faces_count == 0) { if(s3daw->verbose) { logger_print(s3daw->logger, LOG_WARNING, @@ -329,70 +262,27 @@ shapes_create(struct s3daw* s3daw, const char* filename) } if(!obj_desc.usemtls_count) { /* No material grouping => triangle soup */ - str_clear(&s3daw->mtl.name); - s3daw->mtl.face_id = 0; - s3daw->mtl.faces_count = obj_desc.faces_count; - res = shape_register(s3daw, &s3daw->mtl); - if(res != RES_OK) goto error; - } else { - size_t imtllib; - size_t dirname_len; - - /* Setup the `mtllib' buffer with the directory of the filename */ - res = get_dirname(filename, &s3daw->mtllib); + grp.name = NULL; + grp.face_id = 0; + grp.faces_count = obj_desc.faces_count; + res = shape_register(s3daw, &grp, &vertices, &indices, &vertices_ids); if(res != RES_OK) goto error; - dirname_len = darray_char_size_get(&s3daw->mtllib); - - /* Load the materials */ - FOR_EACH(imtllib, 0, obj_desc.mtllibs_count) { - const char* mtllib; - size_t mtllib_len; - size_t nmtls; - - AW(obj_mtllib_get(s3daw->loader_obj, imtllib, &mtllib)); - - /* Append the mtllib name to the directory stored into the `mtllib' */ - mtllib_len = strlen(mtllib); - res = darray_char_resize(&s3daw->mtllib, mtllib_len + 1/*'\0'*/); - if(res != RES_OK) goto error; - strncpy(darray_char_data_get(&s3daw->mtllib) + dirname_len, - mtllib, mtllib_len + 1); - - /* Load the material library */ - res = aw_mtl_load(s3daw->loader_mtl, darray_char_cdata_get(&s3daw->mtllib)); - if(res != RES_OK && res != RES_IO_ERR/*The mtl lib may not be found*/) - goto error; - - /* Register the materials of the material library */ - AW(mtl_materials_count_get(s3daw->loader_mtl, &nmtls)); - FOR_EACH(imtl, 0, nmtls) { - AW(mtl_material_get(s3daw->loader_mtl, imtl, &material)); - res = htable_material_set(&s3daw->materials, &material.name, &material); - if(res != RES_OK) goto error; - } - } - - /* Create a S3D shape per material */ + } else { /* Create a S3D shape per material */ + size_t imtl; FOR_EACH(imtl, 0, obj_desc.usemtls_count) { - const struct aw_material* pmaterial; - AW(obj_mtl_get(s3daw->loader_obj, imtl, &s3daw->mtl)); - pmaterial = htable_material_find(&s3daw->materials, &s3daw->mtl.name); - if(!pmaterial) { /* Some material may not be loaded */ - logger_print(s3daw->logger, LOG_WARNING, - "The material `%s' is not loaded\n", str_cget(&s3daw->mtl.name)); - str_clear(&s3daw->mtl.name); - } - res = shape_register(s3daw, &s3daw->mtl); + AW(obj_get_mtl(s3daw->loader_obj, imtl, &grp)); + res = shape_register(s3daw, &grp, &vertices, &indices, &vertices_ids); if(res != RES_OK) goto error; } } exit: - AW(material_release(&material)); + darray_uint_release(&indices); + darray_float_release(&vertices); + htable_vertex_id_release(&vertices_ids); return res; error: shapes_clear(&s3daw->shapes); - materials_clear(&s3daw->materials); goto exit; } @@ -401,24 +291,12 @@ release_s3daw(ref_T* ref) { struct s3daw* s3daw = CONTAINER_OF(ref, struct s3daw, ref); ASSERT(ref); - if(s3daw->loader_obj) AW(obj_ref_put(s3daw->loader_obj)); if(s3daw->loader_mtl) AW(mtl_ref_put(s3daw->loader_mtl)); if(s3daw->polygon) POLYGON(ref_put(s3daw->polygon)); if(s3daw->s3d) S3D(device_ref_put(s3daw->s3d)); - shapes_clear(&s3daw->shapes); - materials_clear(&s3daw->materials); - darray_shape_release(&s3daw->shapes); - - AW(obj_named_group_release(&s3daw->mtl)); - darray_size_t_release(&s3daw->indices); - darray_vertex_release(&s3daw->vertices); - darray_char_release(&s3daw->mtllib); - htable_vertex_id_release(&s3daw->vertices_ids); - htable_material_release(&s3daw->materials); - MEM_RM(s3daw->allocator, s3daw); } @@ -457,12 +335,6 @@ s3daw_create S3D(device_ref_get(s3d)); s3daw->s3d = s3d; darray_shape_init(s3daw->allocator, &s3daw->shapes); - AW(obj_named_group_init(allocator, &s3daw->mtl)); - darray_size_t_init(s3daw->allocator, &s3daw->indices); - darray_vertex_init(s3daw->allocator, &s3daw->vertices); - darray_char_init(s3daw->allocator, &s3daw->mtllib); - htable_vertex_id_init(s3daw->allocator, &s3daw->vertices_ids); - htable_material_init(s3daw->allocator, &s3daw->materials); res = polygon_create(s3daw->allocator, &s3daw->polygon); if(res != RES_OK) goto error; @@ -546,7 +418,7 @@ s3daw_load_stream(struct s3daw* s3daw, FILE* stream) if(!s3daw || !stream) return RES_BAD_ARG; - res = aw_obj_load_stream(s3daw->loader_obj, stream); + res = aw_obj_load_stream(s3daw->loader_obj, stream, "stream"); if(res != RES_OK) return res; return shapes_create(s3daw, "./"); } @@ -562,12 +434,6 @@ s3daw_clear(struct s3daw* s3daw) /* Clear shape */ shapes_clear(&s3daw->shapes); - /* Clear scratch data structures */ - darray_size_t_clear(&s3daw->indices); - darray_vertex_clear(&s3daw->vertices); - darray_char_clear(&s3daw->mtllib); - htable_vertex_id_clear(&s3daw->vertices_ids); - AW(obj_clear(s3daw->loader_obj)); AW(mtl_clear(s3daw->loader_mtl)); @@ -583,7 +449,10 @@ s3daw_get_shapes_count(const struct s3daw* s3daw, size_t* nshapes) } res_T -s3daw_get_shape(struct s3daw* s3daw, const size_t ishape, struct s3d_shape** shape) +s3daw_get_shape + (struct s3daw* s3daw, + const size_t ishape, + struct s3d_shape** shape) { if(!s3daw || !shape || ishape >= darray_shape_size_get(&s3daw->shapes)) return RES_BAD_ARG; diff --git a/src/s3daw.h b/src/s3daw.h @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) 2015, 2016, 2020 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_s3daw.c b/src/test_s3daw.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) 2015, 2016, 2020 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use,