commit 3521ff276c65ea2003fffc993baf53377f2dbe01
parent 133e3892932f293e9a3066a168a1e6256d4e4da1
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 13 Dec 2016 17:03:31 +0100
Begin the implementation of the ssol_draw function
Diffstat:
4 files changed, 171 insertions(+), 4 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -56,6 +56,7 @@ set(SSOL_FILES_SRC
ssol_atmosphere.c
ssol_camera.c
ssol_device.c
+ ssol_draw.c
ssol_estimator.c
ssol_image.c
ssol_material.c
diff --git a/src/ssol_camera.h b/src/ssol_camera.h
@@ -38,7 +38,7 @@ struct ssol_camera {
static FINLINE void
camera_ray
(const struct ssol_camera* cam,
- const double sample[2], /* In [0, 1[ */
+ const float sample[2], /* In [0, 1[ */
float org[3],
float dir[3])
{
@@ -48,8 +48,8 @@ camera_ray
ASSERT(sample[0] >= 0 || sample[0] < 1.f);
ASSERT(sample[1] >= 0 || sample[1] < 1.f);
- f3_mulf(x, cam->axis_x, (float)sample[0]*2.f - 1.f);
- f3_mulf(y, cam->axis_y, (float)sample[1]*2.f - 1.f);
+ f3_mulf(x, cam->axis_x, sample[0]*2.f - 1.f);
+ f3_mulf(y, cam->axis_y, sample[1]*2.f - 1.f);
f3_add(dir, f3_add(dir, x, y), cam->axis_z);
len = f3_normalize(dir, dir);
ASSERT(len >= 1.e-6f);
diff --git a/src/ssol_draw.c b/src/ssol_draw.c
@@ -0,0 +1,166 @@
+/* Copyright (C) CNRS 2016
+ *
+ * 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 "ssol.h"
+#include "ssol_c.h"
+#include "ssol_camera.h"
+
+#include <rsys/double3.h>
+#include <rsys/math.h>
+#include <star/s3d.h>
+
+#define TILE_SIZE 32 /* definition in X & Y of a tile */
+STATIC_ASSERT(IS_POW2(TILE_SIZE), TILE_SIZE_must_be_a_power_of_2);
+
+/*******************************************************************************
+ * Helper function
+ ******************************************************************************/
+static FINLINE uint16_t
+morton2D_decode(const uint32_t u32)
+{
+ uint32_t x = u32 & 0x55555555;
+ x = (x | (x >> 1)) & 0x33333333;
+ x = (x | (x >> 2)) & 0x0F0F0F0F;
+ x = (x | (x >> 4)) & 0x00FF00FF;
+ x = (x | (x >> 8)) & 0x0000FFFF;
+ return (uint16_t)x;
+}
+
+static void
+Li(struct ssol_scene* scn,
+ struct s3d_scene_view* view,
+ const float org[3],
+ const float dir[3],
+ double val[3])
+{
+ const float range[2] = {0, FLT_MAX};
+ struct ray_data ray_data = RAY_DATA_NULL;
+ struct s3d_hit hit;
+
+ ray_data.scn = scn;
+ ray_data.discard_virtual_materials = 1;
+ S3D(scene_view_trace_ray(view, org, dir, range, &ray_data, &hit));
+ if(S3D_HIT_NONE(&hit)) {
+ d3_splat(val, 0);
+ } else {
+ float N[3];
+ f3_normalize(N, hit.normal);
+ d3_splat(val, fabs(f3_dot(N, dir)));
+ }
+}
+
+static void
+draw_tile
+ (struct ssol_scene* scn,
+ struct s3d_scene_view* view,
+ const struct ssol_camera* cam,
+ const size_t origin[2], /* Tile origin */
+ const size_t size[2], /* Tile definition */
+ const float pix_sz[2], /* Normalized size of a pixel in the image plane */
+ double* pixels)
+{
+ size_t npixels;
+ size_t mcode; /* Morton code of the tile pixel */
+ ASSERT(scn && view && cam && origin && size && pix_sz && pixels);
+
+ /* Adjust the #pixels to process them wrt a morton order */
+ npixels = round_up_pow2(MMAX(size[0], size[1]));
+ npixels *= npixels;
+
+ FOR_EACH(mcode, 0, npixels) {
+ size_t ipix[2];
+ float org[3], dir[3], samp[2];
+ double* pixel;
+
+ ipix[0] = morton2D_decode((uint32_t)(mcode>>0));
+ if(ipix[0] >= size[0]) continue;
+ ipix[1] = morton2D_decode((uint32_t)(mcode>>1));
+ if(ipix[1] >= size[1]) continue;
+
+ ipix[0] = ipix[0] + origin[0];
+ ipix[1] = ipix[1] + origin[1];
+ samp[0] = ((float)ipix[0] + 0.5f) * pix_sz[0];
+ samp[1] = ((float)ipix[1] + 0.5f) * pix_sz[1];
+
+ camera_ray(cam, samp, org, dir);
+ pixel = pixels + (ipix[1]*size[0] + ipix[0])*3/*#channels*/;
+
+ Li(scn, view, org, dir, pixel);
+ }
+}
+
+/*******************************************************************************
+ * Exported function
+ ******************************************************************************/
+static res_T /* FIXME */
+ssol_draw
+ (struct ssol_scene* scn,
+ struct ssol_camera* cam,
+ const size_t width,
+ const size_t height,
+ ssol_write_pixels_T writer,
+ void* data)
+{
+ struct s3d_scene_view* view = NULL; /* TODO */
+ int64_t mcode; /* Morton code of a tile */
+ float pix_sz[2];
+ size_t ntiles_x, ntiles_y, ntiles;
+ ATOMIC res = RES_OK;
+
+ if(!scn || !cam || !writer || !data) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ntiles_x = (width + (TILE_SIZE-1)/*ceil*/)/TILE_SIZE;
+ ntiles_y = (height+ (TILE_SIZE-1)/*ceil*/)/TILE_SIZE;
+ ntiles = round_up_pow2(MMAX(ntiles_x, ntiles_y));
+ ntiles *= ntiles;
+
+ pix_sz[0] = 1.f / (float)width;
+ pix_sz[1] = 1.f / (float)height;
+
+ FOR_EACH(mcode, 0, (int64_t)ntiles) {
+ size_t tile_org[2];
+ size_t tile_sz[2];
+ double* pixels = NULL; /* TODO */
+ res_T res_local;
+
+ if(ATOMIC_GET(&res) != RES_OK) continue;
+
+ tile_org[0] = morton2D_decode((uint32_t)(mcode>>0));
+ if(tile_org[0] >= ntiles_x) continue;
+ tile_org[1] = morton2D_decode((uint32_t)(mcode>>1));
+ if(tile_org[1] >= ntiles_y) continue;
+
+ tile_org[0] *= TILE_SIZE;
+ tile_org[1] *= TILE_SIZE;
+ tile_sz[0] = MMIN(TILE_SIZE, width - tile_org[0]);
+ tile_sz[1] = MMIN(TILE_SIZE, height- tile_org[1]);
+
+ draw_tile(scn, view, cam, tile_org, tile_sz, pix_sz, pixels);
+
+ res_local = writer(data, tile_org, tile_sz, SSOL_PIXEL_DOUBLE3, pixels);
+ if(res_local != RES_OK) {
+ ATOMIC_SET(&res, res_local);
+ continue;
+ }
+ }
+
+exit:
+ return (res_T)res;
+error:
+ goto exit;
+}
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -446,7 +446,7 @@ ssol_solve
}
/* Trace the next ray */
- ray_data.scn = scn,
+ ray_data.scn = scn;
ray_data.prim_from = pt.prim;
ray_data.inst_from = pt.inst;
ray_data.side_from = pt.side;