commit 19160f8ba423fcc764a8dad777e3f65a352bbce1
parent 5201cd3cf44c3a2d459d41ab074b7c0a71735405
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 6 Mar 2020 16:07:26 +0100
Add support of the ground materials
Diffstat:
13 files changed, 609 insertions(+), 196 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -24,12 +24,12 @@ option(NO_TEST "Do not build the tests" OFF)
################################################################################
# Check dependencies
################################################################################
+find_package(AW 2.0 REQUIRED)
find_package(HTSky REQUIRED)
find_package(MruMtl REQUIRED)
find_package(RCMake 0.3 REQUIRED)
find_package(RSys 0.7 REQUIRED)
find_package(Star3D 0.6 REQUIRED)
-find_package(Star3DAW 0.3.1 REQUIRED)
find_package(StarSF 0.6 REQUIRED)
find_package(StarSP 0.8 REQUIRED)
find_package(StarVX REQUIRED)
@@ -43,10 +43,10 @@ include(rcmake_runtime)
set(CMAKE_C_COMPILER ${MPI_C_COMPILER})
include_directories(
+ ${AW_INCLUDE_DIR}
${MruMtl_INCLUDE_DIR}
${RSys_INCLUDE_DIR}
${Star3D_INCLUDE_DIR}
- ${Star3DAW_INCLUDE_DIR}
${StarSF_INCLUDE_DIR}
${StarSP_INCLUDE_DIR}
${StarVX_INCLUDE_DIR}
@@ -67,8 +67,6 @@ set(HTRDR_ARGS_DEFAULT_CAMERA_POS "0,0,0")
set(HTRDR_ARGS_DEFAULT_CAMERA_TGT "0,1,0")
set(HTRDR_ARGS_DEFAULT_CAMERA_UP "0,0,1")
set(HTRDR_ARGS_DEFAULT_CAMERA_FOV "70")
-set(HTRDR_ARGS_DEFAULT_GROUND_BSDF "HTRDR_BSDF_DIFFUSE")
-set(HTRDR_ARGS_DEFAULT_GROUND_REFLECTIVITY "0.5")
set(HTRDR_ARGS_DEFAULT_IMG_WIDTH "320")
set(HTRDR_ARGS_DEFAULT_IMG_HEIGHT "240")
set(HTRDR_ARGS_DEFAULT_IMG_SPP "1")
@@ -97,6 +95,7 @@ set(HTRDR_FILES_SRC
htrdr_draw_radiance_sw.c
htrdr_grid.c
htrdr_ground.c
+ htrdr_interface.c
htrdr_main.c
htrdr_mtl.c
htrdr_rectangle.c
@@ -109,6 +108,7 @@ set(HTRDR_FILES_INC
htrdr_camera.h
htrdr_grid.h
htrdr_ground.h
+ htrdr_interface.h
htrdr_mtl.h
htrdr_rectangle.h
htrdr_slab.h
@@ -126,7 +126,7 @@ rcmake_prepend_path(HTRDR_FILES_INC2 ${CMAKE_CURRENT_BINARY_DIR})
rcmake_prepend_path(HTRDR_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
add_executable(htrdr ${HTRDR_FILES_SRC} ${HTRDR_FILES_INC} ${HTRDR_FILES_INC2})
-target_link_libraries(htrdr HTSky MruMtl RSys Star3D Star3DAW StarSF StarSP)
+target_link_libraries(htrdr AW HTSky MruMtl RSys Star3D StarSF StarSP)
if(CMAKE_COMPILER_IS_GNUCC)
target_link_libraries(htrdr m)
diff --git a/doc/ground b/doc/ground
@@ -0,0 +1,5 @@
+<materials-list> ::= <material>
+ [ <material> ... ]
+<material> ::= <material-name> <mrumtl-path>
+<material-name> ::= STRING
+<mrumtl-path> ::= PATH
diff --git a/src/htrdr.c b/src/htrdr.c
@@ -22,6 +22,7 @@
#include "htrdr_buffer.h"
#include "htrdr_camera.h"
#include "htrdr_ground.h"
+#include "htrdr_mtl.h"
#include "htrdr_sun.h"
#include "htrdr_solve.h"
@@ -428,8 +429,14 @@ htrdr_init
goto error;
}
- res = htrdr_ground_create(htrdr, args->filename_obj, args->ground_bsdf_type,
- args->ground_reflectivity, args->repeat_ground, &htrdr->ground);
+ /* Materials are necessary only if a ground geometry is defined */
+ if(args->filename_obj) {
+ res = htrdr_mtl_create(htrdr, args->filename_mtl, &htrdr->mtl);
+ if(res != RES_OK) goto error;
+ }
+
+ res = htrdr_ground_create(htrdr, args->filename_obj, args->repeat_ground,
+ &htrdr->ground);
if(res != RES_OK) goto error;
proj_ratio =
diff --git a/src/htrdr.h b/src/htrdr.h
@@ -46,6 +46,7 @@ struct htrdr {
struct s3d_device* s3d;
struct htrdr_ground* ground;
+ struct htrdr_mtl* mtl;
struct htrdr_sun* sun;
struct htrdr_camera* cam;
diff --git a/src/htrdr_args.c b/src/htrdr_args.c
@@ -28,18 +28,6 @@
/*******************************************************************************
* Helper functions
******************************************************************************/
-static const char*
-bsdf_type_to_string(const enum htrdr_bsdf_type type)
-{
- const char* str = "<none>";
- switch(type) {
- case HTRDR_BSDF_DIFFUSE: str = "diffuse"; break;
- case HTRDR_BSDF_SPECULAR: str = "specular"; break;
- default: FATAL("Unreachable code.\n"); break;
- }
- return str;
-}
-
static void
print_help(const char* cmd)
{
@@ -51,10 +39,6 @@ print_help(const char* cmd)
printf(
" -a ATMOSPHERE gas optical properties of the atmosphere.\n");
printf(
-" -b <diffuse|specular>\n"
-" BSDF of the ground. Default value is %s.\n",
- bsdf_type_to_string(HTRDR_ARGS_DEFAULT.ground_bsdf_type));
- printf(
" -c CLOUDS properties of the clouds.\n");
printf(
" -C <camera> define the rendering point of view.\n");
@@ -67,9 +51,6 @@ print_help(const char* cmd)
printf(
" -d dump octrees data to OUTPUT and exit.\n");
printf(
-" -e REFLECT ground reflectivity in [0, 1]. Default value is %g.\n",
- HTRDR_ARGS_DEFAULT.ground_reflectivity);
- printf(
" -f overwrite the OUTPUT file if it already exists.\n");
printf(
" -g GROUND ground geometry.\n");
@@ -82,6 +63,8 @@ print_help(const char* cmd)
printf(
" -r infinitely repeat the clouds along the X and Y axis.\n");
printf(
+" -M MATERIALS file listing the scene ground materials.\n");
+ printf(
" -m MIE file of Mie's data.\n");
printf(
" -O CACHE name of the cache file used to store/restore the sky data.\n");
@@ -371,26 +354,6 @@ error:
goto exit;
}
-static res_T
-parse_bsdf_type(struct htrdr_args* args, const char* str)
-{
- res_T res = RES_OK;
- if(!strcmp(str, "diffuse")) {
- args->ground_bsdf_type = HTRDR_BSDF_DIFFUSE;
- } else if(!strcmp(str, "specular")) {
- args->ground_bsdf_type = HTRDR_BSDF_SPECULAR;
- } else {
- fprintf(stderr, "Invalid BRDF type `%s'.\n", str);
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
/*******************************************************************************
* Local functions
******************************************************************************/
@@ -415,25 +378,16 @@ htrdr_args_init(struct htrdr_args* args, int argc, char** argv)
}
}
- while((opt = getopt(argc, argv, "a:b:C:c:D:de:fg:hi:m:O:o:RrT:t:V:v")) != -1) {
+ while((opt = getopt(argc, argv, "a:C:c:D:dfg:hi:M:m:O:o:RrT:t:V:v")) != -1) {
switch(opt) {
case 'a': args->filename_gas = optarg; break;
- case 'b':
- res = parse_bsdf_type(args, optarg);
- break;
- case 'C':
+ case 'C':
res = parse_multiple_parameters
(args, optarg, parse_camera_parameter);
break;
case 'c': args->filename_les = optarg; break;
case 'D': res = parse_sun_dir(args, optarg); break;
case 'd': args->dump_vtk = 1; break;
- case 'e':
- res = cstr_to_double(optarg, &args->ground_reflectivity);
- if(args->ground_reflectivity < 0 || args->ground_reflectivity > 1) {
- res = RES_BAD_ARG;
- }
- break;
case 'f': args->force_overwriting = 1; break;
case 'g': args->filename_obj = optarg; break;
case 'h':
@@ -476,6 +430,12 @@ htrdr_args_init(struct htrdr_args* args, int argc, char** argv)
res = RES_BAD_ARG;
goto error;
}
+ if(args->filename_obj && !args->filename_mtl) {
+ fprintf(stderr,
+ "Missing the path of the file listing the ground materials -- opton '-M'\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
if(args->filename_les && !args->filename_mie) {
fprintf(stderr,
"Missing the path toward the file of the Mie's data -- option '-m'\n");
diff --git a/src/htrdr_args.h.in b/src/htrdr_args.h.in
@@ -21,11 +21,13 @@
#include <limits.h>
#include <rsys/rsys.h>
+
struct htrdr_args {
const char* filename_gas; /* Path of the gas file */
const char* filename_les; /* Path of the HTCP file */
const char* filename_mie; /* Path of the Mie properties */
const char* filename_obj; /* Path of the 3D geometry */
+ const char* filename_mtl; /* Path of the materials */
const char* cache;
const char* output;
@@ -51,8 +53,6 @@ struct htrdr_args {
double sun_azimuth; /* In degrees */
double sun_elevation; /* In degrees */
double optical_thickness; /* Threshold used during octree building */
- enum htrdr_bsdf_type ground_bsdf_type;
- double ground_reflectivity; /* Reflectivity of the ground */
unsigned grid_max_definition[3]; /* Maximum definition of the grid */
unsigned nthreads; /* Hint on the number of threads to use */
@@ -69,6 +69,7 @@ struct htrdr_args {
NULL, /* LES filename */ \
NULL, /* Mie filename */ \
NULL, /* Obj filename */ \
+ NULL, /* Mtl filename */ \
NULL, /* Cache filename */ \
NULL, /* Output filename */ \
{ \
@@ -88,8 +89,6 @@ struct htrdr_args {
0, /* Sun azimuth */ \
90, /* Sun elevation */ \
@HTRDR_ARGS_DEFAULT_OPTICAL_THICKNESS_THRESHOLD@, /* Optical thickness */ \
- @HTRDR_ARGS_DEFAULT_GROUND_BSDF@, \
- @HTRDR_ARGS_DEFAULT_GROUND_REFLECTIVITY@, /* Ground reflectivity */ \
{UINT_MAX, UINT_MAX, UINT_MAX}, /* Maximum definition of the grid */ \
(unsigned)~0, /* #threads */ \
0, /* Force overwriting */ \
diff --git a/src/htrdr_compute_radiance_sw.c b/src/htrdr_compute_radiance_sw.c
@@ -16,6 +16,7 @@
#include "htrdr.h"
#include "htrdr_c.h"
+#include "htrdr_interface.h"
#include "htrdr_ground.h"
#include "htrdr_solve.h"
#include "htrdr_sun.h"
@@ -255,7 +256,6 @@ htrdr_compute_radiance_sw
struct svx_hit svx_hit = SVX_HIT_NULL;
struct ssf_phase* phase_hg = NULL;
struct ssf_phase* phase_rayleigh = NULL;
- struct ssf_bsdf* bsdf = NULL;
double pos[3];
double dir[3];
@@ -290,9 +290,6 @@ htrdr_compute_radiance_sw
(htrdr->sky, iband, iquad);
SSF(phase_hg_setup(phase_hg, g));
- /* Fetch the ground BSDF */
- bsdf = htrdr_ground_get_bsdf(htrdr->ground);
-
/* Fetch sun properties. Arbitrarily use the wavelength at the center of the
* band to retrieve the sun radiance of the current band. Note that the sun
* spectral data are defined by bands that, actually are the same of the SW
@@ -389,9 +386,16 @@ htrdr_compute_radiance_sw
/* Scattering at a surface */
if(SVX_HIT_NONE(&svx_hit)) {
+ struct htrdr_interface interf = HTRDR_INTERFACE_NULL;
+ struct ssf_bsdf* bsdf = NULL;
double N[3];
int type;
+ /* Fetch the hit interface and build its BSDF */
+ htrdr_ground_get_interface(htrdr->ground, &s3d_hit, &interf);
+ HTRDR(interface_create_bsdf
+ (htrdr, &interf, ithread, wlen, pos_next, dir, &s3d_hit, &bsdf));
+
d3_normalize(N, d3_set_f3(N, s3d_hit.normal));
if(d3_dot(N, wo) < 0) d3_minus(N, N);
diff --git a/src/htrdr_ground.c b/src/htrdr_ground.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
- * Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
+/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
+ * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
*
* 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
@@ -15,19 +15,43 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "htrdr.h"
+#include "htrdr_interface.h"
#include "htrdr_ground.h"
+#include "htrdr_mtl.h"
#include "htrdr_slab.h"
+#include <aw.h>
#include <rsys/clock_time.h>
#include <rsys/cstr.h>
+#include <rsys/dynamic_array_double.h>
+#include <rsys/dynamic_array_size_t.h>
#include <rsys/double2.h>
#include <rsys/double3.h>
#include <rsys/float2.h>
#include <rsys/float3.h>
+#include <rsys/hash_table.h>
#include <star/s3d.h>
-#include <star/s3daw.h>
-#include <star/ssf.h>
+#include <star/smtl.h>
+
+/* Define the hash table that maps an Obj vertex id to its position into the
+ * vertex buffer */
+#define HTABLE_NAME vertex
+#define HTABLE_KEY size_t /* Obj vertex id */
+#define HTABLE_DATA size_t
+#include <rsys/hash_table.h>
+
+/* Define the hash table that maps the Star-3D shape id to its interface */
+#define HTABLE_NAME interface
+#define HTABLE_KEY unsigned /* Star-3D shape id */
+#define HTABLE_DATA struct htrdr_interface
+#include <rsys/hash_table.h>
+
+struct mesh {
+ const struct darray_double* positions;
+ const struct darray_size_t* indices;
+};
+static const struct mesh MESH_NULL;
struct ray_context {
float range[2];
@@ -50,9 +74,10 @@ struct htrdr_ground {
struct s3d_scene_view* view;
float lower[3]; /* Ground lower bound */
float upper[3]; /* Ground upper bound */
- struct ssf_bsdf* bsdf;
int repeat; /* Make the ground infinite in X and Y */
+ struct htable_interface interfaces; /* Map a Star3D shape to its interface */
+
struct htrdr* htrdr;
ref_T ref;
};
@@ -131,146 +156,341 @@ trace_ground
}
static res_T
-setup_ground(struct htrdr_ground* ground, const char* obj_filename)
+parse_shape_interface
+ (struct htrdr* htrdr,
+ const char* name,
+ struct htrdr_interface* interf)
{
- struct s3d_scene* scn = NULL;
- struct s3daw* s3daw = NULL;
- size_t nshapes;
- size_t ishape;
+ struct str str;
+ char* mtl_name_front = NULL;
+ char* mtl_name_back = NULL;
+ char* tk_ctx = NULL;
res_T res = RES_OK;
- ASSERT(ground);
+ ASSERT(htrdr && name && interf);
- if(!obj_filename) {
- /* No geometry! Discard the creation of the scene view */
- htrdr_log_warn(ground->htrdr,
- "%s: the scene does not have ground geometry.\n",
- FUNC_NAME);
- goto exit;
- }
+ str_init(htrdr->allocator, &str);
- res = s3daw_create(&ground->htrdr->logger, ground->htrdr->allocator, NULL,
- NULL, ground->htrdr->s3d, ground->htrdr->verbose, &s3daw);
+ /* Locally copy the string to parse */
+ res = str_set(&str, name);
if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not create the Star-3DAW device -- %s.\n",
- FUNC_NAME, res_to_cstr(res));
+ htrdr_log_err(htrdr,
+ "Could not locally copy the shape material string `%s' -- %s.\n",
+ name, res_to_cstr(res));
goto error;
}
- res = s3daw_load(s3daw, obj_filename);
- if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not load the obj file `%s' -- %s.\n",
- FUNC_NAME, obj_filename, res_to_cstr(res));
+ /* Parse the name of the front/back faces */
+ mtl_name_front = strtok_r(str_get(&str), ":", &tk_ctx);
+ ASSERT(mtl_name_front); /* This can't be NULL */
+ mtl_name_back = strtok_r(NULL, ":", &tk_ctx);
+ if(!mtl_name_back) {
+ htrdr_log_err(htrdr,
+ "The material name of the shape back faces are missing `%s'.\n", name);
+ res = RES_BAD_ARG;
goto error;
}
- res = s3d_scene_create(ground->htrdr->s3d, &scn);
- if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not create the Star-3D scene of the ground -- %s.\n",
- FUNC_NAME, res_to_cstr(res));
+ /* Fetch the front/back materials */
+ interf->mtl_front = htrdr_mtl_get(htrdr->mtl, mtl_name_front);
+ interf->mtl_back = htrdr_mtl_get(htrdr->mtl, mtl_name_back);
+ if(!interf->mtl_front && !interf->mtl_back) {
+ htrdr_log_err(htrdr,
+ "Invalid interface `%s:%s'. "
+ "The front and the back materials are both uknown.\n",
+ mtl_name_front, mtl_name_back);
+ res = RES_BAD_ARG;
goto error;
}
+exit:
+ str_release(&str);
+ return res;
+error:
+ interf->mtl_front = interf->mtl_back = NULL;
+ goto exit;
+}
- S3DAW(get_shapes_count(s3daw, &nshapes));
- FOR_EACH(ishape, 0, nshapes) {
- struct s3d_shape* shape;
- S3DAW(get_shape(s3daw, ishape, &shape));
- res = s3d_mesh_set_hit_filter_function(shape, ground_filter, NULL);
- if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not setup the hit filter function of the ground geometry "
- "-- %s.\n", FUNC_NAME, res_to_cstr(res));
+static res_T
+setup_mesh
+ (struct htrdr* htrdr,
+ const char* filename,
+ struct aw_obj* obj,
+ struct aw_obj_named_group* mtl,
+ struct darray_double* positions,
+ struct darray_size_t* indices,
+ struct htable_vertex* vertices) /* Scratch data structure */
+{
+ size_t iface;
+ res_T res = RES_OK;
+ ASSERT(htrdr && filename && obj && mtl && positions && indices && vertices);
+
+ darray_double_clear(positions);
+ darray_size_t_clear(indices);
+ htable_vertex_clear(vertices);
+
+ FOR_EACH(iface, mtl->face_id, mtl->faces_count) {
+ struct aw_obj_face face;
+ size_t ivertex;
+
+ AW(obj_get_face(obj, iface, &face));
+ if(face.vertices_count != 3) {
+ htrdr_log_err(htrdr,
+ "The obj `%s' has non-triangulated polygons "
+ "while currently only triangular meshes are supported.\n",
+ filename);
+ res = RES_BAD_ARG;
goto error;
}
- res = s3d_scene_attach_shape(scn, shape);
- if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not attach the ground geometry to its Star-3D scene -- %s.\n",
- FUNC_NAME, res_to_cstr(res));
- goto error;
+
+ FOR_EACH(ivertex, 0, face.vertices_count) {
+ struct aw_obj_vertex vertex;
+ size_t id;
+ size_t* pid;
+
+ AW(obj_get_vertex(obj, face.vertex_id + ivertex, &vertex));
+ pid = htable_vertex_find(vertices, &vertex.position_id);
+ if(pid) {
+ id = *pid;
+ } else {
+ struct aw_obj_vertex_data vdata;
+
+ id = darray_double_size_get(positions) / 3;
+
+ res = darray_double_resize(positions, id*3 + 3);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "Could not locally copy the vertex position -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ AW(obj_get_vertex_data(obj, &vertex, &vdata));
+ darray_double_data_get(positions)[id*3+0] = vdata.position[0];
+ darray_double_data_get(positions)[id*3+1] = vdata.position[1];
+ darray_double_data_get(positions)[id*3+2] = vdata.position[2];
+
+ res = htable_vertex_set(vertices, &vertex.position_id, &id);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "Could not register the vertex position -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+ }
+
+ res = darray_size_t_push_back(indices, &id);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "Could not locally copy the face index -- %s\n",
+ res_to_cstr(res));
+ goto error;
+ }
}
}
+exit:
+ return res;
+error:
+ darray_double_clear(positions);
+ darray_size_t_clear(indices);
+ htable_vertex_clear(vertices);
+ goto exit;
+}
+
+static void
+get_position(const unsigned ivert, float position[3], void* ctx)
+{
+ const struct mesh* mesh = ctx;
+ const double* pos = NULL;
+ ASSERT(mesh);
+ ASSERT(ivert < darray_double_size_get(mesh->positions) / 3);
+ pos = darray_double_cdata_get(mesh->positions) + ivert*3;
+ position[0] = (float)pos[0];
+ position[1] = (float)pos[1];
+ position[2] = (float)pos[2];
+}
+
+static void
+get_indices(const unsigned itri, unsigned indices[3], void* ctx)
+{
+ const struct mesh* mesh = ctx;
+ const size_t* ids = NULL;
+ ASSERT(mesh);
+ ASSERT(itri < darray_size_t_size_get(mesh->indices) / 3);
+ ids = darray_size_t_cdata_get(mesh->indices) + itri*3;
+ indices[0] = (unsigned)ids[0];
+ indices[1] = (unsigned)ids[1];
+ indices[2] = (unsigned)ids[2];
+}
+
+static res_T
+create_s3d_shape
+ (struct htrdr* htrdr,
+ const struct darray_double* positions,
+ const struct darray_size_t* indices,
+ struct s3d_shape** out_shape)
+{
+ struct s3d_shape* shape = NULL;
+ struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL;
+ struct mesh mesh = MESH_NULL;
+ res_T res = RES_OK;
+ ASSERT(htrdr && positions && indices && out_shape);
+ ASSERT(darray_double_size_get(positions) != 0);
+ ASSERT(darray_size_t_size_get(indices) != 0);
+ ASSERT(darray_double_size_get(positions)%3 == 0);
+ ASSERT(darray_size_t_size_get(indices)%3 == 0);
+
+ mesh.positions = positions;
+ mesh.indices = indices;
- res = s3d_scene_view_create(scn, S3D_TRACE, &ground->view);
+ res = s3d_shape_create_mesh(htrdr->s3d, &shape);
if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not create the Star-3D scene view of the ground geometry "
- "-- %s.\n", FUNC_NAME, res_to_cstr(res));
+ htrdr_log_err(htrdr, "Error creating a Star-3D shape -- %s.\n",
+ res_to_cstr(res));
goto error;
}
- res = s3d_scene_view_get_aabb(ground->view, ground->lower, ground->upper);
+ vdata.usage = S3D_POSITION;
+ vdata.type = S3D_FLOAT3;
+ vdata.get = get_position;
+
+ res = s3d_mesh_setup_indexed_vertices
+ (shape, (unsigned int)(darray_size_t_size_get(indices)/3), get_indices,
+ (unsigned int)(darray_double_size_get(positions)/3), &vdata, 1, &mesh);
+ if(res != RES_OK){
+ htrdr_log_err(htrdr, "Could not setup the Star-3D shape -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ res = s3d_mesh_set_hit_filter_function(shape, ground_filter, NULL);
if(res != RES_OK) {
- htrdr_log_err(ground->htrdr,
- "%s: could not get the ground bounding box -- %s.\n",
- FUNC_NAME, res_to_cstr(res));
+ htrdr_log_err(htrdr,
+ "Could not setup the Star-3D hit filter function of the ground geometry "
+ "-- %s.\n", res_to_cstr(res));
goto error;
}
exit:
- if(s3daw) S3DAW(ref_put(s3daw));
- if(scn) S3D(scene_ref_put(scn));
+ *out_shape = shape;
return res;
error:
+ if(shape) {
+ S3D(shape_ref_put(shape));
+ shape = NULL;
+ }
goto exit;
}
static res_T
-setup_bsdf_diffuse(struct htrdr_ground* ground, const double reflectivity)
+setup_ground(struct htrdr_ground* ground, const char* obj_filename)
{
+ struct aw_obj_desc desc;
+ struct htable_vertex vertices;
+ struct darray_double positions;
+ struct darray_size_t indices;
+ struct aw_obj* obj = NULL;
+ struct s3d_shape* shape = NULL;
+ struct s3d_scene* scene = NULL;
+ size_t iusemtl;
+
res_T res = RES_OK;
- ASSERT(ground);
+ ASSERT(obj_filename);
- res = ssf_bsdf_create
- (ground->htrdr->allocator, &ssf_lambertian_reflection, &ground->bsdf);
- if(res != RES_OK) goto error;
+ htable_vertex_init(ground->htrdr->allocator, &vertices);
+ darray_double_init(ground->htrdr->allocator, &positions);
+ darray_size_t_init(ground->htrdr->allocator, &indices);
+
+ res = aw_obj_create(&ground->htrdr->logger, ground->htrdr->allocator,
+ ground->htrdr->verbose, &obj);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr, "Could not create the obj loader -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ res = s3d_scene_create(ground->htrdr->s3d, &scene);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr, "Could not create the Star-3D scene -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
- res = ssf_lambertian_reflection_setup(ground->bsdf, reflectivity);
+ /* Load the geometry data */
+ res = aw_obj_load(obj, obj_filename);
if(res != RES_OK) goto error;
-exit:
- return res;
-error:
- htrdr_log_err(ground->htrdr,
- "Could not setup the ground diffuse BSDF with a reflectivity of %g -- %s.\n",
- reflectivity, res_to_cstr(res));
- if(ground->bsdf) {
- SSF(bsdf_ref_put(ground->bsdf));
- ground->bsdf = NULL;
+ /* Fetch the descriptor of the loaded geometry */
+ AW(obj_get_desc(obj, &desc));
+
+ if(desc.usemtls_count == 0) {
+ htrdr_log_err(ground->htrdr, "The obj `%s' has no material.\n", obj_filename);
+ res = RES_BAD_ARG;
+ goto error;
}
- goto exit;
-}
-static res_T
-setup_bsdf_specular(struct htrdr_ground* ground, const double reflectivity)
-{
- struct ssf_fresnel* fresnel = NULL;
- res_T res = RES_OK;
- ASSERT(ground);
+ /* Setup the geometry */
+ FOR_EACH(iusemtl, 0, desc.usemtls_count) {
+ struct aw_obj_named_group mtl;
+ struct htrdr_interface interf;
+ unsigned ishape;
- res = ssf_bsdf_create
- (ground->htrdr->allocator, &ssf_specular_reflection, &ground->bsdf);
- if(res != RES_OK) goto error;
- res = ssf_fresnel_create
- (ground->htrdr->allocator, &ssf_fresnel_constant, &fresnel);
- if(res != RES_OK) goto error;
- res = ssf_fresnel_constant_setup(fresnel, reflectivity);
- if(res != RES_OK) goto error;
- res = ssf_specular_reflection_setup(ground->bsdf, fresnel);
- if(res != RES_OK) goto error;
+ AW(obj_get_mtl(obj, iusemtl , &mtl));
+
+ res = parse_shape_interface(ground->htrdr, mtl.name, &interf);
+ if(res != RES_OK) goto error;
+
+ res = setup_mesh
+ (ground->htrdr, obj_filename, obj, &mtl, &positions, &indices, &vertices);
+ if(res != RES_OK) goto error;
+
+ res = create_s3d_shape(ground->htrdr, &positions, &indices, &shape);
+ if(res != RES_OK) goto error;
+
+ S3D(shape_get_id(shape, &ishape));
+ res = htable_interface_set(&ground->interfaces, &ishape, &interf);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr,
+ "Could not map the Star-3D shape to its Star-Materials -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ res = s3d_scene_attach_shape(scene, shape);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr,
+ "Could not attach a Star-3D shape to the Star-3D scene -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ S3D(shape_ref_put(shape));
+ shape = NULL;
+ }
+
+ res = s3d_scene_view_create(scene, S3D_GET_PRIMITIVE|S3D_TRACE, &ground->view);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr,
+ "Could not create the Star-3D scene view -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ res = s3d_scene_view_get_aabb(ground->view, ground->lower, ground->upper);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr,
+ "Could not get the bounding box of the geometry -- %s.\n",
+ res_to_cstr(res));
+ goto error;
+ }
exit:
+ if(obj) AW(obj_ref_put(obj));
+ if(shape) S3D(shape_ref_put(shape));
+ if(scene) S3D(scene_ref_put(scene));
+ htable_vertex_release(&vertices);
+ darray_double_release(&positions);
+ darray_size_t_release(&indices);
return res;
error:
- htrdr_log_err(ground->htrdr,
- "Could not setup the ground specular BSDF with a reflectivity of %g -- %s.\n",
- reflectivity, res_to_cstr(res));
- if(ground->bsdf) {
- SSF(bsdf_ref_put(ground->bsdf));
- ground->bsdf = NULL;
- }
goto exit;
}
@@ -281,7 +501,7 @@ release_ground(ref_T* ref)
ASSERT(ref);
ground = CONTAINER_OF(ref, struct htrdr_ground, ref);
if(ground->view) S3D(scene_view_ref_put(ground->view));
- if(ground->bsdf) SSF(bsdf_ref_put(ground->bsdf));
+ htable_interface_release(&ground->interfaces);
MEM_RM(ground->htrdr->allocator, ground);
}
@@ -292,8 +512,6 @@ res_T
htrdr_ground_create
(struct htrdr* htrdr,
const char* obj_filename, /* May be NULL */
- const enum htrdr_bsdf_type bsdf_type,
- const double reflectivity,
const int repeat_ground, /* Infinitely repeat the ground in X and Y */
struct htrdr_ground** out_ground)
{
@@ -302,7 +520,6 @@ htrdr_ground_create
struct time t0, t1;
res_T res = RES_OK;
ASSERT(htrdr && out_ground);
- ASSERT(reflectivity >= 0 || reflectivity <= 1);
ground = MEM_CALLOC(htrdr->allocator, 1, sizeof(*ground));
if(!ground) {
@@ -317,18 +534,9 @@ htrdr_ground_create
ground->repeat = repeat_ground;
f3_splat(ground->lower, (float)INF);
f3_splat(ground->upper,-(float)INF);
+ htable_interface_init(ground->htrdr->allocator, &ground->interfaces);
- switch(bsdf_type) {
- case HTRDR_BSDF_DIFFUSE:
- res = setup_bsdf_diffuse(ground, reflectivity);
- break;
- case HTRDR_BSDF_SPECULAR:
- res = setup_bsdf_specular(ground, reflectivity);
- break;
- default: FATAL("Unreachable code\n");
-
- }
- if(res != RES_OK) goto error;
+ if(!obj_filename) goto exit;
time_current(&t0);
res = setup_ground(ground, obj_filename);
@@ -362,11 +570,19 @@ htrdr_ground_ref_put(struct htrdr_ground* ground)
ref_put(&ground->ref, release_ground);
}
-struct ssf_bsdf*
-htrdr_ground_get_bsdf(const struct htrdr_ground* ground)
+void
+htrdr_ground_get_interface
+ (struct htrdr_ground* ground,
+ const struct s3d_hit* hit,
+ struct htrdr_interface* out_interface)
{
- ASSERT(ground);
- return ground->bsdf;
+ struct htrdr_interface* interf = NULL;
+ ASSERT(ground && hit && out_interface);
+
+ interf = htable_interface_find(&ground->interfaces, &hit->prim.geom_id);
+ ASSERT(interf);
+
+ *out_interface = *interf;
}
res_T
diff --git a/src/htrdr_ground.h b/src/htrdr_ground.h
@@ -1,5 +1,5 @@
-/* Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
- * Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
+/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
+ * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
*
* 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
@@ -19,14 +19,10 @@
#include <rsys/rsys.h>
-enum htrdr_bsdf_type {
- HTRDR_BSDF_DIFFUSE,
- HTRDR_BSDF_SPECULAR
-};
-
/* Forward declarations */
struct htrdr;
struct htrdr_ground;
+struct htrdr_interface;
struct s3d_hit;
struct ssf_bsdf;
@@ -34,8 +30,6 @@ extern LOCAL_SYM res_T
htrdr_ground_create
(struct htrdr* htrdr,
const char* obj_filename, /* May be NULL <=> No ground geometry */
- const enum htrdr_bsdf_type bsdf_type,
- const double reflectivity, /* In [0, 1] */
const int repeat_ground, /* Infinitely repeat the ground in X and Y */
struct htrdr_ground** ground);
@@ -47,9 +41,22 @@ extern LOCAL_SYM void
htrdr_ground_ref_put
(struct htrdr_ground* ground);
-extern LOCAL_SYM struct ssf_bsdf*
-htrdr_ground_get_bsdf
- (const struct htrdr_ground* ground);
+extern LOCAL_SYM void
+htrdr_ground_get_interface
+ (struct htrdr_ground* ground,
+ const struct s3d_hit* hit,
+ struct htrdr_interface* interface);
+
+extern LOCAL_SYM res_T
+htrdr_ground_create_bsdf
+ (struct htrdr_ground* ground,
+ const size_t ithread,
+ const double wavelength,
+ const double pos[3],
+ const double dir[3], /* Incoming ray */
+ const struct s3d_hit* hit,
+ struct htrdr_interface* interf, /* NULL <=> do not return the interface */
+ struct ssf_bsdf** bsdf);
extern LOCAL_SYM res_T
htrdr_ground_trace_ray
diff --git a/src/htrdr_interface.c b/src/htrdr_interface.c
@@ -0,0 +1,169 @@
+/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
+ * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
+ *
+ * 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 "htrdr.h"
+#include "htrdr_interface.h"
+
+#include <modradurb/mrumtl.h>
+
+#include <star/s3d.h>
+#include <star/ssf.h>
+
+#include <rsys/cstr.h>
+#include <rsys/double3.h>
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static res_T
+create_bsdf_diffuse
+ (struct htrdr* htrdr,
+ const struct mrumtl_brdf* brdf,
+ const size_t ithread,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ double reflectivity = 0;
+ res_T res = RES_OK;
+ ASSERT(htrdr && brdf && out_bsdf);
+ ASSERT(mrumtl_brdf_get_type(brdf) == MRUMTL_BRDF_LAMBERTIAN);
+ ASSERT(ithread < htrdr->nthreads);
+
+ res = ssf_bsdf_create
+ (&htrdr->lifo_allocators[ithread], &ssf_lambertian_reflection, &bsdf);
+ if(res != RES_OK) goto error;
+
+ reflectivity = mrumtl_brdf_lambertian_get_reflectivity(brdf);
+ res = ssf_lambertian_reflection_setup(bsdf, reflectivity);
+ if(res != RES_OK) goto error;
+
+exit:
+ *out_bsdf = bsdf;
+ return res;
+error:
+ if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
+ goto exit;
+}
+
+static res_T
+create_bsdf_specular
+ (struct htrdr* htrdr,
+ const struct mrumtl_brdf* brdf,
+ const size_t ithread,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ struct ssf_fresnel* fresnel = NULL;
+ double reflectivity = 0;
+ res_T res = RES_OK;
+ ASSERT(htrdr && brdf && out_bsdf);
+ ASSERT(mrumtl_brdf_get_type(brdf) == MRUMTL_BRDF_SPECULAR);
+ ASSERT(ithread < htrdr->nthreads);
+
+ res = ssf_bsdf_create
+ (&htrdr->lifo_allocators[ithread], &ssf_specular_reflection, &bsdf);
+ if(res != RES_OK) goto error;
+
+ res = ssf_fresnel_create
+ (&htrdr->lifo_allocators[ithread], &ssf_fresnel_constant, &fresnel);
+ if(res != RES_OK) goto error;
+
+ reflectivity = mrumtl_brdf_specular_get_reflectivity(brdf);
+ res = ssf_fresnel_constant_setup(fresnel, reflectivity);
+ if(res != RES_OK) goto error;
+
+ res = ssf_specular_reflection_setup(bsdf, fresnel);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(fresnel) SSF(fresnel_ref_put(fresnel));
+ *out_bsdf = bsdf;
+ return res;
+error:
+ if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+htrdr_interface_create_bsdf
+ (struct htrdr* htrdr,
+ const struct htrdr_interface* interf,
+ const size_t ithread,
+ const double wavelength,
+ const double pos[3],
+ const double dir[3],
+ struct s3d_hit* hit,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ const struct mrumtl_brdf* brdf = NULL;
+ const struct mrumtl* mat = NULL;
+ double N[3];
+ res_T res = RES_OK;
+ ASSERT(htrdr && pos && hit && out_bsdf);
+ ASSERT(interf && interf->mtl_front && interf->mtl_back);
+
+ ASSERT(htrdr && interf && pos && dir && hit && out_bsdf);
+ ASSERT(d3_is_normalized(dir));
+
+ /* Check incoming ray */
+ d3_normalize(N, d3_set_f3(N, hit->normal));
+ if(d3_dot(N, dir) < 0) {
+ mat = interf->mtl_front;
+ } else {
+ mat = interf->mtl_back;
+ }
+ if(!mat) {
+ htrdr_log_err(htrdr, "%s: the hit surface has no material.\n", FUNC_NAME);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = mrumtl_fetch_brdf(mat, wavelength, &brdf);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "%s: error retreiving the MruMtl BRDF for the wavelength %g.\n",
+ FUNC_NAME, wavelength);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ switch(mrumtl_brdf_get_type(brdf)) {
+ case MRUMTL_BRDF_LAMBERTIAN:
+ res = create_bsdf_diffuse(htrdr, brdf, ithread, &bsdf);
+ break;
+ case MRUMTL_BRDF_SPECULAR:
+ res = create_bsdf_specular(htrdr, brdf, ithread, &bsdf);
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr, "%s: could not create the BSDF -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ *out_bsdf = bsdf;
+ return res;
+error:
+ if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
+ goto exit;
+}
+
diff --git a/src/htrdr_interface.h b/src/htrdr_interface.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
+ * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
+ *
+ * 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/>. */
+
+#ifndef HTRDR_INTERFACE_H
+#define HTRDR_INTERFACE_H
+
+#include <star/ssf.h>
+
+/* Forward declaration of external data type */
+struct mrumtl;
+struct s3d_hit;
+struct ssf_bsdf;
+
+struct htrdr_interface {
+ const struct mrumtl* mtl_front;
+ const struct mrumtl* mtl_back;
+};
+static const struct htrdr_interface HTRDR_INTERFACE_NULL;
+
+extern LOCAL_SYM res_T
+htrdr_interface_create_bsdf
+ (struct htrdr* htrdr,
+ const struct htrdr_interface* interf,
+ const size_t ithread,
+ const double wavelength,
+ const double pos[3],
+ const double dir[3], /* Normalized incoming direction */
+ struct s3d_hit* hit,
+ struct ssf_bsdf** bsdf);
+
+#endif /* HTRDR_INTERFACE_H */
+
diff --git a/src/htrdr_mtl.c b/src/htrdr_mtl.c
@@ -182,7 +182,7 @@ mtl_release(ref_T* ref)
* Local symbol
******************************************************************************/
res_T
-htrdr_mtl_load
+htrdr_mtl_create
(struct htrdr* htrdr,
const char* filename,
struct htrdr_mtl** out_mtl)
diff --git a/src/htrdr_mtl.h b/src/htrdr_mtl.h
@@ -21,7 +21,7 @@ struct htrdr_mtl;
struct mrumtl;
extern LOCAL_SYM res_T
-htrdr_mtl_load
+htrdr_mtl_create
(struct htrdr* htrdr,
const char* filename,
struct htrdr_mtl** mtl);