commit 10345c084a53917caa88af238cb8e3313a27fbcf
parent 174a238ae6151575f0590dc4fdf2320652112226
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 18 Oct 2016 15:23:03 +0200
Implement the SGF 3D shape
Diffstat:
5 files changed, 287 insertions(+), 4 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -47,9 +47,14 @@ set(VERSION_MINOR 1)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
-set(SGF_FILES_SRC sgf_device.c sgf_estimator.c)
+set(SGF_FILES_SRC
+ sgf_device.c
+ sgf_estimator.c
+ sgf_shape.c)
set(SGF_FILES_INC_API sgf.h)
-set(SGF_FILES_INC sgf_device_c.h sgf_realisation.h)
+set(SGF_FILES_INC
+ sgf_device_c.h
+ sgf_realisation.h)
set(SGF_FILES_DOC COPYING README.md)
# Prepend each file in the `SGF_FILES_<SRC|INC>' list by `SGF_SOURCE_DIR'
diff --git a/src/sgf.h b/src/sgf.h
@@ -80,6 +80,25 @@ static const struct sgf_scene_desc SGF_SCENE_DESC_NULL = {
NULL, NULL, 0, 0, SGF_3D, { NULL }
};
+struct sgf_shape3d_desc {
+ void (*get_indices)(const unsigned itri, unsigned ids[3], void* ctx);
+ void (*get_position)(const unsigned ivert, float pos[3], void* ctx);
+
+ void (*get_emissivity)
+ (const unsigned itri, const unsigned iband, double* val, void* ctx);
+ void (*get_reflectivity)
+ (const unsigned itri, const unsigned iband, double* val, void* ctx);
+ void (*get_specularity)
+ (const unsigned itri, const unsigned iband, double* val, void* ctx);
+ void (*get_absorption) /* May be NULL <=> no medium */
+ (const unsigned itri, const unsigned iband, double* val, void* ctx);
+
+ void* context; /* User defined data */
+ unsigned ntris; /* #triangles */
+ unsigned nverts; /* #vertices */
+ unsigned nbands; /* #spectral bands */
+};
+
/* Estimated Gebart Factor between 2 faces */
struct sgf_status {
double E; /* Expected value */
@@ -91,9 +110,11 @@ struct sgf_status {
/* Opaque types */
struct sgf_device;
struct sgf_estimator;
+struct sgf_shape;
+struct sgf_scene;
/*******************************************************************************
- * Star Gebhart Factor API
+ * Device API
******************************************************************************/
BEGIN_DECLS
@@ -112,6 +133,60 @@ SGF_API res_T
sgf_device_ref_put
(struct sgf_device* dev);
+/*******************************************************************************
+ * Shape API
+ ******************************************************************************/
+SGF_API res_T
+sgf_shape3d_create
+ (struct sgf_device* device,
+ struct sgf_shape** shape);
+
+SGF_API res_T
+sgf_shape_ref_get
+ (struct sgf_shape* shape);
+
+SGF_API res_T
+sgf_shape_ref_put
+ (struct sgf_shape* shape);
+
+SGF_API res_T
+sgf_shape3d_setup
+ (struct sgf_shape* shape,
+ const struct sgf_shape3d_desc* desc);
+
+/*******************************************************************************
+ * Scene API
+ ******************************************************************************/
+SGF_API res_T
+sgf_scene3d_create
+ (struct sgf_device,
+ struct sgf_scene** scn);
+
+SGF_API res_T
+sgf_scene_ref_get
+ (struct sgf_scene* scn);
+
+SGF_API res_T
+sgf_scene_ref_put
+ (struct sgf_scene* scn);
+
+SGF_API res_T
+sgf_scene_attach_shape
+ (struct sgf_scene* scn,
+ struct sgf_shape* shape);
+
+SGF_API res_T
+sgf_scene_detach_shape
+ (struct sgf_scene* scn,
+ struct sgf_shape* shape);
+
+SGF_API res_T
+sgf_scene_clear
+ (struct sgf_scene* scn);
+
+/*******************************************************************************
+ * Integration API
+ ******************************************************************************/
/* Numerical estimation of the Gebhart Factor between `primitive_id' and the
* other scene primitives. An active S3D_TRACE/S3D_GET_PRIMITIVE session must
* be active on `desc->scene'. This function is thread safe and can be invoked
diff --git a/src/sgf_device.c b/src/sgf_device.c
@@ -19,6 +19,8 @@
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
+#include <star/s3d.h>
+
/*******************************************************************************
* Helper function
******************************************************************************/
@@ -28,6 +30,7 @@ device_release(ref_T* ref)
struct sgf_device* dev;
ASSERT(ref);
dev = CONTAINER_OF(ref, struct sgf_device, ref);
+ if(dev->s3d) S3D(device_ref_put(dev->s3d));
MEM_RM(dev->allocator, dev);
}
@@ -58,7 +61,7 @@ sgf_device_create
if(!dev) {
if(verbose) {
logger_print(logger, LOG_ERROR,
- "Couldn't allocate the Star-Gebhart-Factor device.\n");
+ "%s: couldn't allocate the Star-Gebhart-Factor device.\n", FUNC_NAME);
}
res = RES_MEM_ERR;
goto error;
@@ -68,6 +71,12 @@ sgf_device_create
dev->logger = logger;
dev->verbose = verbose;
+ res = s3d_device_create(NULL, dev->allocator, 0, &dev->s3d);
+ if(res != RES_OK) {
+ log_error(dev, "%s: couldn't create the Star-3D device.\n", FUNC_NAME);
+ goto error;
+ }
+
exit:
if(out_dev) *out_dev = dev;
return res;
diff --git a/src/sgf_device_c.h b/src/sgf_device_c.h
@@ -20,10 +20,12 @@
struct logger;
struct mem_allocator;
+struct s3d_device;
struct sgf_device {
int verbose;
struct logger* logger;
+ struct s3d_device* s3d;
struct mem_allocator* allocator;
ref_T ref;
diff --git a/src/sgf_shape.c b/src/sgf_shape.c
@@ -0,0 +1,192 @@
+/* Copyright (C) 2015-2016 EDF S.A., France (syrthes-support@edf.fr)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "sgf.h"
+#include "sgf_device_c.h"
+
+#include <rsys/dynamic_array_double.h>
+#include <rsys/ref_count.h>
+
+#include <star/s3d.h>
+
+struct sgf_shape {
+ struct s3d_shape* s3d_shape;
+ struct darray_double abs; /* Per primitive absorption */
+ struct darray_double emi; /* Per primitive emissivity */
+ struct darray_double refl; /* Per primitive reflectivity */
+ struct darray_double spec; /* Per primitive specularity */
+ size_t nbands; /* #spectral bands */
+
+ ref_T ref;
+ struct sgf_device* dev;
+};
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+static FINLINE int
+check_shape3d_desc(const struct sgf_shape3d_desc* desc)
+{
+ return desc
+ && desc->get_indices
+ && desc->get_emissivity
+ && desc->get_reflectivity
+ && desc->get_specularity
+ && desc->get_position
+ && desc->ntris
+ && desc->nverts;
+}
+
+static void
+shape_release(ref_T* ref)
+{
+ struct sgf_device* dev;
+ struct sgf_shape* shape;
+ ASSERT(ref);
+ shape = CONTAINER_OF(ref, struct sgf_shape, ref);
+ dev = shape->dev;
+ if(shape->s3d_shape) S3D(shape_ref_put(shape->s3d_shape));
+ darray_double_release(&shape->abs);
+ darray_double_release(&shape->emi);
+ darray_double_release(&shape->refl);
+ darray_double_release(&shape->spec);
+ MEM_RM(dev->allocator, shape);
+ SGF(device_ref_put(dev));
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+sgf_shape3d_create(struct sgf_device* dev, struct sgf_shape** out_shape)
+{
+ struct sgf_shape* shape = NULL;
+ res_T res = RES_OK;
+
+ if(!dev || !out_shape) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ shape = MEM_CALLOC(dev->allocator, 1, sizeof(struct sgf_shape));
+ if(!shape) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ ref_init(&shape->ref);
+ SGF(device_ref_get(dev));
+ shape->dev = dev;
+
+ res = s3d_shape_create_mesh(dev->s3d, &shape->s3d_shape);
+ if(res != RES_OK) goto error;
+
+ darray_double_init(dev->allocator, &shape->abs);
+ darray_double_init(dev->allocator, &shape->emi);
+ darray_double_init(dev->allocator, &shape->refl);
+ darray_double_init(dev->allocator, &shape->spec);
+
+exit:
+ if(out_shape) *out_shape = shape;
+ return res;
+error:
+ if(shape) {
+ SGF(shape_ref_put(shape));
+ shape = NULL;
+ }
+ goto exit;
+}
+
+res_T
+sgf_shape_ref_get(struct sgf_shape* shape)
+{
+ if(!shape) return RES_BAD_ARG;
+ ref_get(&shape->ref);
+ return RES_OK;
+}
+
+res_T
+sgf_shape_ref_put(struct sgf_shape* shape)
+{
+ if(!shape) return RES_BAD_ARG;
+ ref_put(&shape->ref, shape_release);
+ return RES_OK;
+}
+
+res_T
+sgf_shape3d_setup
+ (struct sgf_shape* shape, const struct sgf_shape3d_desc* desc)
+{
+ struct s3d_vertex_data vdata;
+ unsigned iprim, iband, i;
+ double* abs, *emi, *refl, *spec;
+ res_T res = RES_OK;
+
+ if(!shape || !check_shape3d_desc(desc)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the buffers of material attributes */
+ #define RESIZE(V, Name) { \
+ res = darray_double_resize(&(V), desc->ntris*desc->nbands); \
+ if(res != RES_OK) { \
+ log_error(shape->dev, \
+ "%s: couldn't allocate the "Name" buffer.", FUNC_NAME); \
+ goto error; \
+ } \
+ } (void)0
+ RESIZE(shape->emi, "emissivity");
+ RESIZE(shape->refl, "reflectivity");
+ RESIZE(shape->spec, "specularity");
+ if(desc->get_absorption) RESIZE(shape->abs, "absorption");
+ #undef RESIZE
+
+ /* Setup the material */
+ abs = desc->get_absorption ? darray_double_data_get(&shape->abs) : NULL;
+ emi = darray_double_data_get(&shape->emi);
+ refl = darray_double_data_get(&shape->refl);
+ spec = darray_double_data_get(&shape->spec);
+ FOR_EACH(iband, 0, desc->nbands) {
+ FOR_EACH(iprim, 0, desc->ntris) {
+ if(abs) desc->get_absorption(iprim, iband, abs + i, desc->context);
+ desc->get_emissivity(iprim, iband, emi + i, desc->context);
+ desc->get_reflectivity(iprim, iband, refl + i, desc->context);
+ desc->get_specularity(iprim, iband, spec + i, desc->context);
+ ++i;
+ }}
+
+ /* Setup the geometry */
+ vdata.usage = S3D_POSITION;
+ vdata.type = S3D_FLOAT3;
+ vdata.get = desc->get_position;
+ res = s3d_mesh_setup_indexed_vertices(shape->s3d_shape, desc->ntris,
+ desc->get_indices, desc->nverts, &vdata, 1, desc->context);
+ if(res != RES_OK) {
+ log_error(shape->dev, "%s: couldn't setup the geometry.\n", FUNC_NAME);
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ if(shape) {
+ darray_double_clear(&shape->abs);
+ darray_double_clear(&shape->emi);
+ darray_double_clear(&shape->refl);
+ darray_double_clear(&shape->spec);
+ }
+ goto exit;
+}
+