solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 1+
Msrc/ssol_camera.h | 6+++---
Asrc/ssol_draw.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ssol_solver.c | 2+-
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;