star-camera

Camera models
git clone git://git.meso-star.fr/star-camera.git
Log | Files | Refs | README | LICENSE

commit 939fa0923226953c5fef27cceecec4ac2dd87cdc
parent 6934852821e419ec9cfbb02ee02ae2a2051bb2d5
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 21 Jul 2021 16:43:31 +0200

Add a test that draws a Cornell Box

Diffstat:
Mcmake/CMakeLists.txt | 6++++++
Asrc/test_scam_cbox.c | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_scam_cbox.h | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_scam_pinhole.c | 8+-------
Asrc/test_scam_utils.h | 28++++++++++++++++++++++++++++
5 files changed, 364 insertions(+), 7 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -25,6 +25,7 @@ option(NO_TEST "Do not build tests" OFF) ################################################################################ find_package(RCMake 0.4 REQUIRED) find_package(RSys 0.9 REQUIRED) +find_package(Star3D 0.8 QUIET) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) @@ -81,6 +82,11 @@ if(NOT NO_TEST) endfunction() new_test(test_scam_pinhole) + + if(Star3D_FOUND) + new_test(test_scam_cbox) + target_link_libraries(test_scam_cbox Star3D) + endif() endif() ################################################################################ diff --git a/src/test_scam_cbox.c b/src/test_scam_cbox.c @@ -0,0 +1,159 @@ +/* Copyright (C) 2021 |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 "scam.h" +#include "test_scam_cbox.h" +#include "test_scam_utils.h" + +#include <star/s3d.h> + +#include <rsys/double3.h> +#include <rsys/float2.h> +#include <rsys/float3.h> +#include <rsys/image.h> +#include <rsys/mem_allocator.h> + +#define IMG_WIDTH 640 +#define IMG_HEIGHT 480 +#define IMG_SPP 16 + +static struct s3d_scene_view* +create_s3d_scene_view(void) +{ + struct s3d_vertex_data vdata; + struct s3d_device* s3d = NULL; + struct s3d_scene* scn = NULL; + struct s3d_shape* shape = NULL; + struct s3d_scene_view* view = NULL; + + CHK(s3d_device_create(NULL, NULL, 0, &s3d) == RES_OK); + + vdata.usage = S3D_POSITION; + vdata.type = S3D_FLOAT3; + vdata.get = cbox_get_vtx; + CHK(s3d_shape_create_mesh(s3d, &shape) == RES_OK); + CHK(s3d_mesh_setup_indexed_vertices(shape, cbox_ntris, cbox_get_tri, + cbox_nvtxs, &vdata, 1, NULL) == RES_OK); + + CHK(s3d_scene_create(s3d, &scn) == RES_OK); + CHK(s3d_scene_attach_shape(scn, shape) == RES_OK); + CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK); + + CHK(s3d_device_ref_put(s3d) == RES_OK); + CHK(s3d_shape_ref_put(shape) == RES_OK); + CHK(s3d_scene_ref_put(scn) == RES_OK); + + return view; +} + +static void +draw + (const struct scam* cam, + struct s3d_scene_view* view, + struct image* img) +{ + int x, y, s; + double pixsz[2]; + CHK(img); + + pixsz[0] = 1.0 / (double)IMG_WIDTH; + pixsz[1] = 1.0 / (double)IMG_HEIGHT; + + FOR_EACH(y, 0, IMG_HEIGHT) { + FOR_EACH(x, 0, IMG_WIDTH) { + double sum[3] = {0,0,0}; + double E[3] = {0,0,0}; + int ipix; + + FOR_EACH(s, 0, IMG_SPP) { + struct s3d_hit hit = S3D_HIT_NULL; + struct scam_sample sample = SCAM_SAMPLE_NULL; + struct scam_ray ray = SCAM_RAY_NULL; + double col[3]; + float org[3]; + float dir[3]; + float range[2]; + float N[3]; + float cos_N_dir; + + /* Generate the camera ray */ + sample.film[0] = ((double)x + rand_canonical()) * pixsz[0]; + sample.film[1] = ((double)y + rand_canonical()) * pixsz[1]; + CHK(scam_generate_ray(cam, &sample, &ray) == RES_OK); + + /* Trace the ray */ + f3_set_d3(org, ray.org); + f3_normalize(dir, f3_set_d3(dir, ray.dir)); + f2(range, 0, (float)INF); + CHK(s3d_scene_view_trace_ray(view, org, dir, range, NULL, &hit) == RES_OK); + + if(S3D_HIT_NONE(&hit)) continue; + + /* Shade */ + cbox_get_col(hit.prim.prim_id, col); + f3_normalize(N, hit.normal); + cos_N_dir = absf(f3_dot(N, dir)); + + sum[0] += (float)(cos_N_dir * col[0]); + sum[1] += (float)(cos_N_dir * col[1]); + sum[2] += (float)(cos_N_dir * col[2]); + } + /* Compute pixel color */ + E[0] = sum[0] / (double)IMG_SPP; + E[1] = sum[1] / (double)IMG_SPP; + E[2] = sum[2] / (double)IMG_SPP; + + /* Write pixel color */ + ipix = (y*IMG_WIDTH + x) * 3/*RGB*/; + ((uint8_t*)img->pixels)[ipix+0] = (uint8_t)(E[0] * 255); + ((uint8_t*)img->pixels)[ipix+1] = (uint8_t)(E[1] * 255); + ((uint8_t*)img->pixels)[ipix+2] = (uint8_t)(E[2] * 255); + } + } +} + +int +main(int argc, char** argv) +{ + struct scam_pinhole_args args = SCAM_PINHOLE_ARGS_DEFAULT; + struct s3d_scene_view* view = NULL; + struct scam* cam = NULL; + struct image img; + (void)argc, (void)argv; + + view = create_s3d_scene_view(); + + d3(args.position, 276.0, -700.0, 273.0); + d3(args.target, 276.0, 0.0, 273.0); + d3(args.up, 0, 0, 1); + args.aspect_ratio = (double)IMG_WIDTH/(double)IMG_HEIGHT; + args.field_of_view = PI*0.25; + CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_OK); + + image_init(NULL, &img); + CHK(image_setup + (&img, IMG_WIDTH, IMG_HEIGHT, IMG_WIDTH*3, IMAGE_RGB8, NULL) == RES_OK); + + draw(cam, view, &img); + + CHK(image_write_ppm_stream(&img, 0, stdout) == RES_OK); + + CHK(s3d_scene_view_ref_put(view) == RES_OK); + CHK(scam_ref_put(cam) == RES_OK); + image_release(&img); + + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_scam_cbox.h b/src/test_scam_cbox.h @@ -0,0 +1,170 @@ +/* Copyright (C) 2021 |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 TEST_SCAM_CBOX_H +#define TEST_SCAM_CBOX_H + +#include <rsys/rsys.h> + +/******************************************************************************* + * Mesh & properties + ******************************************************************************/ +static const float cbox_vtxs[] = { + /* Walls */ + 552.f, 0.f, 0.f, + 0.f, 0.f, 0.f, + 0.f, 559.f, 0.f, + 552.f, 559.f, 0.f, + 552.f, 0.f, 548.f, + 0.f, 0.f, 548.f, + 0.f, 559.f, 548.f, + 552.f, 559.f, 548.f, + + /* Short block */ + 130.f, 65.f, 0.f, + 82.f, 225.f, 0.f, + 240.f, 272.f, 0.f, + 290.f, 114.f, 0.f, + 130.f, 65.f, 165.f, + 82.f, 225.f, 165.f, + 240.f, 272.f, 165.f, + 290.f, 114.f, 165.f, + + /* Tall block */ + 423.0f, 247.0f, 0.f, + 265.0f, 296.0f, 0.f, + 314.0f, 456.0f, 0.f, + 472.0f, 406.0f, 0.f, + 423.0f, 247.0f, 330.f, + 265.0f, 296.0f, 330.f, + 314.0f, 456.0f, 330.f, + 472.0f, 406.0f, 330.f +}; +const unsigned cbox_tris[] = { + /* Walls */ + 0, 1, 2, 2, 3, 0, /* Bottom */ + 4, 5, 6, 6, 7, 4, /* Top */ + 1, 2, 6, 6, 5, 1, /* Left */ + 0, 3, 7, 7, 4, 0, /* Right */ + 2, 3, 7, 7, 6, 2, /* Back */ + + /* Short block */ + 12, 13, 14, 14, 15, 12, + 9, 10, 14, 14, 13, 9, + 8, 11, 15, 15, 12, 8, + 10, 11, 15, 15, 14, 10, + 8, 9, 13, 13, 12, 8, + + /* Tall block */ + 20, 21, 22, 22, 23, 20, + 17, 18, 22, 22, 21, 17, + 16, 19, 23, 23, 20, 16, + 18, 19, 23, 23, 22, 18, + 16, 17, 21, 21, 20, 16 +}; + +#define WHITE 1.0,1.0,1.0 +#define RED 1.0,0.0,0.0 +#define GREEN 0.0,1.0,0.0 + +const double cbox_cols[] = { + /* Walls */ + WHITE, WHITE, /* Bottom */ + WHITE, WHITE, /* Top */ + RED, RED, /* Left */ + GREEN, GREEN, /* Right */ + WHITE, WHITE, /* Back */ + + /* Short block */ + WHITE, WHITE, + WHITE, WHITE, + WHITE, WHITE, + WHITE, WHITE, + WHITE, WHITE, + + /* Tall block */ + WHITE, WHITE, + WHITE, WHITE, + WHITE, WHITE, + WHITE, WHITE, + WHITE, WHITE +}; + +#undef WHITE +#undef RED +#undef GREEN + +const unsigned cbox_nvtxs = sizeof(cbox_vtxs) / sizeof(float[3]); +const unsigned cbox_ntris = sizeof(cbox_tris) / sizeof(unsigned[3]); +STATIC_ASSERT + ( sizeof(cbox_tris)/sizeof(unsigned[3]) + == sizeof(cbox_cols)/sizeof(double[3]), Unexpected_data_layout); + +/******************************************************************************* + * Functions + ******************************************************************************/ +static INLINE void +cbox_get_vtx(const unsigned ivtx, float vtx[3], void* data) +{ + const unsigned id = ivtx * 3; + (void)data; + CHK(ivtx < cbox_nvtxs); + vtx[0] = cbox_vtxs[id+0]; + vtx[1] = cbox_vtxs[id+1]; + vtx[2] = cbox_vtxs[id+2]; +} + +static INLINE void +cbox_get_tri(const unsigned itri, unsigned tri[3], void* data) +{ + const unsigned id = itri * 3; + (void)data; + CHK(itri < cbox_ntris); + tri[0] = cbox_tris[id+0]; + tri[1] = cbox_tris[id+1]; + tri[2] = cbox_tris[id+2]; +} + +static INLINE void +cbox_get_col(const unsigned itri, double col[3]) +{ + const unsigned id = itri * 3; + CHK(itri < cbox_ntris); + col[0] = cbox_cols[id+0]; + col[1] = cbox_cols[id+1]; + col[2] = cbox_cols[id+2]; +} + +static INLINE void +cbox_dump(FILE* stream) +{ + unsigned i; + + FOR_EACH(i, 0, cbox_nvtxs) { + fprintf(stream, "v %g %g %g\n", + cbox_vtxs[i*3+0], + cbox_vtxs[i*3+1], + cbox_vtxs[i*3+2]); + } + + FOR_EACH(i, 0, cbox_ntris) { + fprintf(stream, "f %u %u %u\n", + cbox_tris[i*3+0]+1, + cbox_tris[i*3+1]+1, + cbox_tris[i*3+2]+1); + } +} + +#endif /* TEST_SCAM_CBOX_H */ diff --git a/src/test_scam_pinhole.c b/src/test_scam_pinhole.c @@ -16,19 +16,13 @@ #define _POSIX_C_SOURCE 200112L /* nextafter */ #include "scam.h" +#include "test_scam_utils.h" #include <rsys/double3.h> #include <rsys/logger.h> #include <rsys/mem_allocator.h> #include <math.h> -#include <stdlib.h> - -static INLINE double -rand_canonical(void) -{ - return (double)rand() / (double)((int64_t)RAND_MAX + 1); -} static void log_stream(const char* msg, void* ctx) diff --git a/src/test_scam_utils.h b/src/test_scam_utils.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2021 |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 TEST_SCAM_UTILS_H +#define TEST_SCAM_UTILS_H + +#include <rsys/rsys.h> +#include <stdlib.h> + +static INLINE double +rand_canonical(void) +{ + return (double)rand() / (double)((int64_t)RAND_MAX + 1); +} + +#endif /* TEST_SCAM_UTILS_H */