commit a1aef46023def6863cbdcda68cec023c96c1a463
parent ee7c9e6439f70ec2a427f9f2a2321cc6a6fa3379
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 16 Oct 2018 14:20:44 +0200
Add the ground data API
Diffstat:
7 files changed, 308 insertions(+), 84 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -24,7 +24,7 @@ option(NO_TEST "Do not build the tests" OFF)
# Check dependencies
################################################################################
find_package(RCMake 0.3 REQUIRED)
-find_package(RSys 0.6 REQUIRED)
+find_package(RSys 0.7 REQUIRED)
find_package(Star3D 0.5 REQUIRED)
find_package(Star3DAW 0.3.1 REQUIRED)
find_package(StarSF 0.6 REQUIRED)
@@ -66,6 +66,7 @@ set(HTRDR_FILES_SRC
htrdr_compute_radiance_sw.c
htrdr_draw_radiance_sw.c
htrdr_grid.c
+ htrdr_ground.c
htrdr_main.c
htrdr_rectangle.c
htrdr_sky.c
@@ -77,6 +78,7 @@ set(HTRDR_FILES_INC
htrdr_buffer.h
htrdr_camera.h
htrdr_grid.h
+ htrdr_ground.h
htrdr_rectangle.h
htrdr_sky.h
htrdr_sun.h
diff --git a/src/htrdr.c b/src/htrdr.c
@@ -20,6 +20,7 @@
#include "htrdr_args.h"
#include "htrdr_buffer.h"
#include "htrdr_camera.h"
+#include "htrdr_ground.h"
#include "htrdr_sky.h"
#include "htrdr_sun.h"
#include "htrdr_solve.h"
@@ -29,7 +30,6 @@
#include <rsys/str.h>
#include <star/s3d.h>
-#include <star/s3daw.h>
#include <star/ssf.h>
#include <star/svx.h>
@@ -149,6 +149,7 @@ error:
goto exit;
}
+#if 0
static res_T
setup_geometry(struct htrdr* htrdr, const char* filename)
{
@@ -210,6 +211,7 @@ exit:
error:
goto exit;
}
+#endif
static res_T
open_file_stamp
@@ -370,7 +372,7 @@ htrdr_init
goto error;
}
- res = setup_geometry(htrdr, args->filename_obj);
+ res = htrdr_ground_create(htrdr, args->filename_obj, 0, &htrdr->ground);
if(res != RES_OK) goto error;
proj_ratio =
@@ -431,9 +433,9 @@ void
htrdr_release(struct htrdr* htrdr)
{
ASSERT(htrdr);
- if(htrdr->s3d_scn_view) S3D(scene_view_ref_put(htrdr->s3d_scn_view));
if(htrdr->s3d) S3D(device_ref_put(htrdr->s3d));
if(htrdr->svx) SVX(device_ref_put(htrdr->svx));
+ if(htrdr->ground) htrdr_ground_ref_put(htrdr->ground);
if(htrdr->sky) htrdr_sky_ref_put(htrdr->sky);
if(htrdr->sun) htrdr_sun_ref_put(htrdr->sun);
if(htrdr->cam) htrdr_camera_ref_put(htrdr->cam);
diff --git a/src/htrdr.h b/src/htrdr.h
@@ -45,8 +45,7 @@ struct htrdr {
struct svx_device* svx;
struct s3d_device* s3d;
- struct s3d_scene_view* s3d_scn_view;
-
+ struct htrdr_ground* ground;
struct htrdr_sky* sky;
struct htrdr_sun* sun;
diff --git a/src/htrdr_compute_radiance_sw.c b/src/htrdr_compute_radiance_sw.c
@@ -15,6 +15,7 @@
#include "htrdr.h"
#include "htrdr_c.h"
+#include "htrdr_ground.h"
#include "htrdr_solve.h"
#include "htrdr_sky.h"
#include "htrdr_sun.h"
@@ -28,14 +29,6 @@
#include <rsys/float2.h>
#include <rsys/float3.h>
-struct ray_context {
- float range[2];
- struct s3d_hit hit_prev;
-};
-static const struct ray_context RAY_CONTEXT_NULL = {
- {0, INF}, S3D_HIT_NULL__
-};
-
struct scattering_context {
struct ssp_rng* rng;
const struct htrdr_sky* sky;
@@ -68,24 +61,6 @@ static const struct transmissivity_context TRANSMISSION_CONTEXT_NULL = {
/*******************************************************************************
* Helper functions
******************************************************************************/
-/* Check that `hit' roughly lies on an edge. For triangular primitives, a
- * simple but approximative way is to test that its position have at least one
- * barycentric coordinate roughly equal to 0 or 1. */
-static FINLINE int
-hit_on_edge(const struct s3d_hit* hit)
-{
- const float on_edge_eps = 1.e-4f;
- float w;
- ASSERT(hit && !S3D_HIT_NONE(hit));
- w = 1.f - hit->uv[0] - hit->uv[1];
- return eq_epsf(hit->uv[0], 0.f, on_edge_eps)
- || eq_epsf(hit->uv[0], 1.f, on_edge_eps)
- || eq_epsf(hit->uv[1], 0.f, on_edge_eps)
- || eq_epsf(hit->uv[1], 1.f, on_edge_eps)
- || eq_epsf(w, 0.f, on_edge_eps)
- || eq_epsf(w, 1.f, on_edge_eps);
-}
-
static int
scattering_hit_filter
(const struct svx_hit* hit,
@@ -245,23 +220,12 @@ transmissivity
struct s3d_hit s3d_hit;
struct svx_hit svx_hit;
struct transmissivity_context transmissivity_ctx = TRANSMISSION_CONTEXT_NULL;
- struct ray_context rctx = RAY_CONTEXT_NULL;
- float ray_pos[3];
- float ray_dir[3];
ASSERT(htrdr && rng && pos && dir && range);
- /* Find the first intersection with a surface */
- f3_set_d3(ray_pos, pos);
- f3_set_d3(ray_dir, dir);
- f2_set_d2(rctx.range, range);
- rctx.hit_prev = hit_prev ? *hit_prev : S3D_HIT_NULL;
- S3D(scene_view_trace_ray(htrdr->s3d_scn_view, ray_pos, ray_dir, rctx.range,
- &rctx, &s3d_hit));
-
- if(!S3D_HIT_NONE(&s3d_hit)) {
- return 0;
- }
+ /* Check that the ray is not occlude along the submitted range */
+ HTRDR(ground_trace_ray(htrdr->ground, pos, dir, range, hit_prev, &s3d_hit));
+ if(!S3D_HIT_NONE(&s3d_hit)) return 0;
transmissivity_ctx.rng = rng;
transmissivity_ctx.sky = htrdr->sky;
@@ -322,9 +286,6 @@ htrdr_compute_radiance_sw
double w = 0; /* MC weight */
double g = 0; /* Asymmetry parameter of the HG phase function */
- float ray_pos[3];
- float ray_dir[3];
-
ASSERT(htrdr && rng && pos_in && dir_in && ithread < htrdr->nthreads);
CHK(RES_OK == ssf_bsdf_create
@@ -366,17 +327,11 @@ htrdr_compute_radiance_sw
/* Radiative random walk */
for(;;) {
struct scattering_context scattering_ctx = SCATTERING_CONTEXT_NULL;
- struct ray_context rctx = RAY_CONTEXT_NULL;
-
- /* Setup the ray to trace */
- f3_set_d3(ray_pos, pos);
- f3_set_d3(ray_dir, dir);
- f2(rctx.range, 0, FLT_MAX);
- rctx.hit_prev = s3d_hit_prev;
/* Find the first intersection with a surface */
- S3D(scene_view_trace_ray(htrdr->s3d_scn_view, ray_pos, ray_dir, rctx.range,
- &rctx, &s3d_hit));
+ d2(range, 0, DBL_MAX);
+ HTRDR(ground_trace_ray
+ (htrdr->ground, pos, dir, range, &s3d_hit_prev, &s3d_hit));
/* Sample an optical thickness */
scattering_ctx.Ts = ssp_ran_exp(rng, 1);
@@ -481,28 +436,3 @@ htrdr_compute_radiance_sw
return w;
}
-int
-htrdr_ground_filter
- (const struct s3d_hit* hit,
- const float ray_org[3],
- const float ray_dir[3],
- void* ray_data,
- void* filter_data)
-{
- const struct ray_context* ray_ctx = ray_data;
- (void)ray_org, (void)ray_dir, (void)filter_data;
-
- if(!ray_ctx) return 0;
-
- if(S3D_PRIMITIVE_EQ(&hit->prim, &ray_ctx->hit_prev.prim)) return 1;
-
- if(!S3D_HIT_NONE(&ray_ctx->hit_prev) && eq_epsf(hit->distance, 0, 1.e-1f)) {
- /* If the targeted point is near of the origin, check that it lies on an
- * edge/vertex shared by the 2 primitives. */
- return hit_on_edge(&ray_ctx->hit_prev) && hit_on_edge(hit);
- }
-
- return hit->distance <= ray_ctx->range[0]
- || hit->distance >= ray_ctx->range[1];
-}
-
diff --git a/src/htrdr_ground.c b/src/htrdr_ground.c
@@ -0,0 +1,240 @@
+/* Copyright (C) 2018 Université Paul Sabatier, |Meso|Star>
+ *
+ * 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_ground.h"
+
+#include <rsys/cstr.h>
+#include <rsys/float2.h>
+#include <rsys/float3.h>
+
+#include <star/s3d.h>
+#include <star/s3daw.h>
+
+struct ray_context {
+ float range[2];
+ struct s3d_hit hit_prev;
+};
+static const struct ray_context RAY_CONTEXT_NULL = {
+ {0, INF}, S3D_HIT_NULL__
+};
+
+struct htrdr_ground {
+ struct s3d_scene_view* view;
+ struct htrdr* htrdr;
+ int repeat; /* Make the ground infinite in X and Y */
+ ref_T ref;
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+/* Check that `hit' roughly lies on an edge. For triangular primitives, a
+ * simple but approximative way is to test that its position have at least one
+ * barycentric coordinate roughly equal to 0 or 1. */
+static FINLINE int
+hit_on_edge(const struct s3d_hit* hit)
+{
+ const float on_edge_eps = 1.e-4f;
+ float w;
+ ASSERT(hit && !S3D_HIT_NONE(hit));
+ w = 1.f - hit->uv[0] - hit->uv[1];
+ return eq_epsf(hit->uv[0], 0.f, on_edge_eps)
+ || eq_epsf(hit->uv[0], 1.f, on_edge_eps)
+ || eq_epsf(hit->uv[1], 0.f, on_edge_eps)
+ || eq_epsf(hit->uv[1], 1.f, on_edge_eps)
+ || eq_epsf(w, 0.f, on_edge_eps)
+ || eq_epsf(w, 1.f, on_edge_eps);
+}
+
+static int
+ground_filter
+ (const struct s3d_hit* hit,
+ const float ray_org[3],
+ const float ray_dir[3],
+ void* ray_data,
+ void* filter_data)
+{
+ const struct ray_context* ray_ctx = ray_data;
+ (void)ray_org, (void)ray_dir, (void)filter_data;
+
+ if(!ray_ctx) return 0;
+
+ if(S3D_PRIMITIVE_EQ(&hit->prim, &ray_ctx->hit_prev.prim)) return 1;
+
+ if(!S3D_HIT_NONE(&ray_ctx->hit_prev) && eq_epsf(hit->distance, 0, 1.e-1f)) {
+ /* If the targeted point is near of the origin, check that it lies on an
+ * edge/vertex shared by the 2 primitives. */
+ return hit_on_edge(&ray_ctx->hit_prev) && hit_on_edge(hit);
+ }
+
+ return hit->distance <= ray_ctx->range[0]
+ || hit->distance >= ray_ctx->range[1];
+}
+
+static void
+release_ground(ref_T* ref)
+{
+ struct htrdr_ground* ground;
+ ASSERT(ref);
+ ground = CONTAINER_OF(ref, struct htrdr_ground, ref);
+ if(ground->view) S3D(scene_view_ref_put(ground->view));
+ MEM_RM(ground->htrdr->allocator, ground);
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+htrdr_ground_create
+ (struct htrdr* htrdr,
+ const char* obj_filename,
+ const int repeat_ground, /* Infinitely repeat the ground in X and Y */
+ struct htrdr_ground** out_ground)
+{
+ struct s3d_scene* scn = NULL;
+ struct s3daw* s3daw = NULL;
+ struct htrdr_ground* ground = NULL;
+ size_t ishape;
+ size_t nshapes;
+ res_T res = RES_OK;
+ ASSERT(htrdr && obj_filename && out_ground);
+
+ ground = MEM_CALLOC(htrdr->allocator, 1, sizeof(*ground));
+ if(!ground) {
+ res = RES_MEM_ERR;
+ htrdr_log_err(htrdr,
+ "%s: could not allocate the ground data structure -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+ ref_init(&ground->ref);
+ ground->htrdr = htrdr;
+ ground->repeat = repeat_ground;
+
+ res = s3daw_create(&htrdr->logger, htrdr->allocator, NULL, NULL, htrdr->s3d,
+ htrdr->verbose, &s3daw);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "%s: could not create the Star-3DAW device -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+
+ res = s3daw_load(s3daw, obj_filename);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr, "%s: could not load the obj file `%s' -- %s.\n",
+ FUNC_NAME, obj_filename, res_to_cstr(res));
+ goto error;
+ }
+
+ res = s3d_scene_create(htrdr->s3d, &scn);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "%s: could not create the Star-3D scene of the ground -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+
+ 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(htrdr,
+ "%s: could not setup the hit filter function of the ground geometry "
+ "-- %s.\n", FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+ res = s3d_scene_attach_shape(scn, shape);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "%s: could not attach the ground geometry to its Star-3D scene -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+ }
+
+ res = s3d_scene_view_create(scn, S3D_TRACE, &ground->view);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "%s: could not create the Star-3D scene view of the ground geometry "
+ "-- %s.\n", FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ if(s3daw) S3DAW(ref_put(s3daw));
+ if(scn) S3D(scene_ref_put(scn));
+ *out_ground = ground;
+ return res;
+error:
+ if(ground) {
+ htrdr_ground_ref_put(ground);
+ ground = NULL;
+ }
+ goto exit;
+}
+
+void
+htrdr_ground_ref_get(struct htrdr_ground* ground)
+{
+ ASSERT(ground);
+ ref_get(&ground->ref);
+}
+
+void
+htrdr_ground_ref_put(struct htrdr_ground* ground)
+{
+ ASSERT(ground);
+ ref_put(&ground->ref, release_ground);
+}
+
+res_T
+htrdr_ground_trace_ray
+ (struct htrdr_ground* ground,
+ const double org[3],
+ const double dir[3], /* Must be normalized */
+ const double range[2],
+ const struct s3d_hit* prev_hit,
+ struct s3d_hit* hit)
+{
+ struct ray_context ctx = RAY_CONTEXT_NULL;
+ float ray_org[3];
+ float ray_dir[3];
+ res_T res = RES_OK;
+ ASSERT(ground && org && dir && range && hit);
+
+ f3_set_d3(ray_org, org);
+ f3_set_d3(ray_dir, dir);
+ f2_set_d2(ctx.range, range);
+ ctx.hit_prev = prev_hit ? *prev_hit : S3D_HIT_NULL;
+
+ res = s3d_scene_view_trace_ray
+ (ground->view, ray_org, ray_dir, ctx.range, &ctx, hit);
+ if(res != RES_OK) {
+ htrdr_log_err(ground->htrdr,
+ "%s: could not trace the ray against the ground geometry -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
diff --git a/src/htrdr_ground.h b/src/htrdr_ground.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2018 Université Paul Sabatier, |Meso|Star>
+ *
+ * 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_GROUND_H
+#define HTRDR_GROUND_H
+
+#include <rsys/rsys.h>
+
+/* Forward declarations */
+struct htrdr;
+struct htrdr_ground;
+struct s3d_hit;
+
+extern LOCAL_SYM res_T
+htrdr_ground_create
+ (struct htrdr* htrdr,
+ const char* obj_filename,
+ const int repeat_ground, /* Infinitely repeat the ground in X and Y */
+ struct htrdr_ground** ground);
+
+extern LOCAL_SYM void
+htrdr_ground_ref_get
+ (struct htrdr_ground* ground);
+
+extern LOCAL_SYM void
+htrdr_ground_ref_put
+ (struct htrdr_ground* ground);
+
+extern LOCAL_SYM res_T
+htrdr_ground_trace_ray
+ (struct htrdr_ground* ground,
+ const double ray_origin[3],
+ const double ray_direction[3], /* Must be normalized */
+ const double ray_range[2],
+ const struct s3d_hit* prev_hit,/* Previous hit. Avoid self hit. May be NULL*/
+ struct s3d_hit* hit);
+
+#endif /* HTRDR_GROUND_H */
+
diff --git a/src/htrdr_sky.h b/src/htrdr_sky.h
@@ -64,7 +64,7 @@ htrdr_sky_create
const char* htgop_filename,
const char* htmie_filename,
const double optical_thickness, /* Threshold used during octree building */
- const int repeat_clouds, /* Infinitly repeat the clouds in X and Y */
+ const int repeat_clouds, /* Infinitely repeat the clouds in X and Y */
struct htrdr_sky** sky);
extern LOCAL_SYM void