solstice-solver

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

test_ssol_draw.c (13694B)


      1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2016, 2018 CNRS
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #include "ssol.h"
     18 #include "test_ssol_utils.h"
     19 #include "test_ssol_geometries.h"
     20 #include "test_ssol_materials.h"
     21 
     22 #include <rsys/double3.h>
     23 #include <rsys/float3.h>
     24 #include <rsys/image.h>
     25 #include <rsys/math.h>
     26 
     27 #include <string.h>
     28 
     29 #define WIDTH 256
     30 #define HEIGHT 256
     31 #define PITCH (WIDTH*sizeof(unsigned char[3]))
     32 #define PROJ_RATIO ((double)WIDTH/(double)HEIGHT)
     33 
     34 static void
     35 get_wlen(const size_t i, double* wlen, double* data, void* ctx)
     36 {
     37   double wavelengths[3] = { 1, 2, 3 };
     38   double intensities[3] = { 1, 0.8, 1 };
     39   CHK(i < 3);
     40   (void)ctx;
     41   *wlen = wavelengths[i];
     42   *data = intensities[i];
     43 }
     44 
     45 static res_T
     46 write_RGB8
     47   (void* data,
     48    const size_t org[2],
     49    const size_t sz[2],
     50    const enum ssol_pixel_format fmt,
     51    const void* pixels)
     52 {
     53   unsigned char* img = data;
     54   const char* src_pixels = pixels;
     55   size_t src_pitch = ssol_sizeof_pixel_format(fmt) * sz[0];
     56   size_t x, y;
     57 
     58   CHK(org[0] + sz[0] <= WIDTH);
     59   CHK(org[1] + sz[1] <= HEIGHT);
     60 
     61   FOR_EACH(y, 0, sz[1]) {
     62     unsigned char* row_dst = img + (y + org[1]) * PITCH;
     63     const char* row_src = src_pixels + y * src_pitch;
     64     FOR_EACH(x, 0, sz[0]) {
     65       unsigned char* dst = row_dst + (x + org[0])*3/*#channels*/;
     66       const char* src = row_src + x*ssol_sizeof_pixel_format(fmt);
     67 
     68       switch(fmt) {
     69         case SSOL_PIXEL_DOUBLE3:
     70           dst[0] = (unsigned char)(255.0 * ((const double*)src)[0]);
     71           dst[1] = (unsigned char)(255.0 * ((const double*)src)[1]);
     72           dst[2] = (unsigned char)(255.0 * ((const double*)src)[2]);
     73           break;
     74         default: FATAL("Unreachable code.\n"); break;
     75       }
     76     }
     77   }
     78   return RES_OK;
     79 }
     80 
     81 static void
     82 setup_cornell_box(struct ssol_device* dev, struct ssol_scene* scn)
     83 {
     84   const float walls[] = {
     85     552.f, 0.f,   0.f,
     86     0.f,   0.f,   0.f,
     87     0.f,   559.f, 0.f,
     88     552.f, 559.f, 0.f,
     89     552.f, 0.f,   548.f,
     90     0.f,   0.f,   548.f,
     91     0.f,   559.f, 548.f,
     92     552.f, 559.f, 548.f
     93   };
     94   const float tall_block[] = {
     95     423.f, 247.f, 0.f,
     96     265.f, 296.f, 0.f,
     97     314.f, 456.f, 0.f,
     98     472.f, 406.f, 0.f,
     99     423.f, 247.f, 330.f,
    100     265.f, 296.f, 330.f,
    101     314.f, 456.f, 330.f,
    102     472.f, 406.f, 330.f
    103   };
    104   const float short_block[] = {
    105     130.f, 65.f,  0.f,
    106     82.f,  225.f, 0.f,
    107     240.f, 272.f, 0.f,
    108     290.f, 114.f, 0.f,
    109     130.f, 65.f,  165.f,
    110     82.f,  225.f, 165.f,
    111     240.f, 272.f, 165.f,
    112     290.f, 114.f, 165.f
    113   };
    114   const unsigned  block_ids[] = {
    115     4, 5, 6, 6, 7, 4,
    116     1, 2, 6, 6, 5, 1,
    117     0, 3, 7, 7, 4, 0,
    118     2, 3, 7, 7, 6, 2,
    119     0, 1, 5, 5, 4, 0
    120   };
    121   const unsigned walls_ids[] = {
    122     0, 1, 2, 2, 3, 0,
    123     4, 5, 6, 6, 7, 4,
    124     1, 2, 6, 6, 5, 1,
    125     0, 3, 7, 7, 4, 0,
    126     2, 3, 7, 7, 6, 2
    127   };
    128   struct ssol_shape* shape;
    129   struct ssol_object* obj;
    130   struct ssol_instance* inst;
    131   struct ssol_material* mtl;
    132   struct ssol_matte_shader shader = SSOL_MATTE_SHADER_NULL;
    133   struct ssol_vertex_data vdata;
    134   struct desc desc;
    135   float lower[3], upper[3];
    136   float tmp[3];
    137 
    138   shader.normal = get_shader_normal;
    139   shader.reflectivity = get_shader_reflectivity;
    140   CHK(ssol_material_create_matte(dev, &mtl) == RES_OK);
    141   CHK(ssol_matte_setup(mtl, &shader) == RES_OK);
    142 
    143   vdata.usage = SSOL_POSITION;
    144   vdata.get = get_position;
    145 
    146   desc.vertices = walls;
    147   desc.indices = walls_ids;
    148 
    149   CHK(ssol_shape_create_mesh(dev, &shape) == RES_OK);
    150   CHK(ssol_mesh_setup(shape, 10, get_ids, 8, &vdata, 1, &desc) == RES_OK);
    151   CHK(ssol_object_create(dev, &obj) == RES_OK);
    152   CHK(ssol_object_add_shaded_shape(obj, shape, mtl, mtl) == RES_OK);
    153   CHK(ssol_object_instantiate(obj, &inst) == RES_OK);
    154   CHK(ssol_scene_attach_instance(scn, inst) == RES_OK);
    155   CHK(ssol_instance_ref_put(inst) == RES_OK);
    156   CHK(ssol_shape_ref_put(shape) == RES_OK);
    157   CHK(ssol_object_ref_put(obj) == RES_OK);
    158 
    159   desc.vertices = short_block;
    160   desc.indices = block_ids;
    161   CHK(ssol_shape_create_mesh(dev, &shape) == RES_OK);
    162   CHK(ssol_mesh_setup(shape, 10, get_ids, 8, &vdata, 1, &desc) == RES_OK);
    163   CHK(ssol_object_create(dev, &obj) == RES_OK);
    164   CHK(ssol_object_add_shaded_shape(obj, shape, mtl, mtl) == RES_OK);
    165   CHK(ssol_object_instantiate(obj, &inst) == RES_OK);
    166   CHK(ssol_scene_attach_instance(scn, inst) == RES_OK);
    167   CHK(ssol_instance_ref_put(inst) == RES_OK);
    168   CHK(ssol_shape_ref_put(shape) == RES_OK);
    169   CHK(ssol_object_ref_put(obj) == RES_OK);
    170 
    171   desc.vertices = tall_block;
    172   desc.indices = block_ids;
    173   CHK(ssol_shape_create_mesh(dev, &shape) == RES_OK);
    174   CHK(ssol_mesh_setup(shape, 10, get_ids, 8, &vdata, 1, &desc) == RES_OK);
    175   CHK(ssol_object_create(dev, &obj) == RES_OK);
    176   CHK(ssol_object_add_shaded_shape(obj, shape, mtl, mtl) == RES_OK);
    177   CHK(ssol_object_instantiate(obj, &inst) == RES_OK);
    178   CHK(ssol_scene_attach_instance(scn, inst) == RES_OK);
    179   CHK(ssol_instance_ref_put(inst) == RES_OK);
    180   CHK(ssol_shape_ref_put(shape) == RES_OK);
    181   CHK(ssol_object_ref_put(obj) == RES_OK);
    182 
    183   CHK(ssol_material_ref_put(mtl) == RES_OK);
    184 
    185   CHK(ssol_scene_compute_aabb(scn, lower, upper) == RES_OK);
    186   CHK(f3_eq_eps(lower, f3(tmp, 0, 0, 0), 1.e-6f) == 1);
    187   CHK(f3_eq_eps(upper, f3(tmp, 552.f, 559.f, 548.f), 1.e-6f) == 1);
    188 }
    189 
    190 
    191 /* Wrap the ssol_draw_pt function to match the ssol_draw_draft profile */
    192 static INLINE res_T
    193 draw_pt
    194   (struct ssol_scene* scn,
    195    struct ssol_camera* cam,
    196    const size_t width,
    197    const size_t height,
    198    const size_t spp,
    199    ssol_write_pixels_T writer,
    200    void* data)
    201 {
    202   const double up[3] = {0, 0, 1};
    203   return ssol_draw_pt(scn, cam, width, height, spp, up, writer, data);
    204 }
    205 
    206 int
    207 main(int argc, char** argv)
    208 {
    209   struct mem_allocator allocator;
    210   struct ssol_device* dev;
    211   struct ssol_camera* cam;
    212   struct ssol_scene* scn;
    213   struct ssol_spectrum* spectrum;
    214   struct ssol_sun* sun;
    215   struct image img;
    216   uint8_t* pixels;
    217   const double pos[3] = {278.0, -1000.0, 273.0};
    218   const double tgt[3] = {278.0, 0.0, 273.0};
    219   const double up[3] = {0.0, 0.0, 1.0};
    220   double dir[3];
    221   size_t pitch;
    222   res_T (*draw_func)
    223     (struct ssol_scene* scn,
    224      struct ssol_camera* cam,
    225      const size_t width,
    226      const size_t height,
    227      const size_t spp,
    228      ssol_write_pixels_T writer,
    229      void* data);
    230   (void)argc, (void)argv;
    231 
    232   if(argc <= 1) {
    233     fprintf(stderr, "Usage: %s <draft|pt>\n", argv[0]);
    234     return -1;
    235   }
    236 
    237   if(!strcmp(argv[1], "draft")) {
    238     draw_func = ssol_draw_draft;
    239   } else if(!strcmp(argv[1], "pt")) {
    240     draw_func = draw_pt;
    241   } else {
    242     fprintf(stderr, "Usage: %s <draft|pt>\n", argv[0]);
    243     return -1;
    244   }
    245 
    246   CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
    247 
    248   CHK(ssol_device_create
    249     (NULL, &allocator, SSOL_NTHREADS_DEFAULT, 0, &dev) == RES_OK);
    250 
    251   CHK(ssol_scene_create(dev, &scn) == RES_OK);
    252 
    253   setup_cornell_box(dev, scn);
    254 
    255   CHK(ssol_camera_create(dev, &cam) == RES_OK);
    256   CHK(ssol_camera_set_proj_ratio(cam, PROJ_RATIO) == RES_OK);
    257   CHK(ssol_camera_set_fov(cam, PI/4.0) == RES_OK);
    258   CHK(ssol_camera_look_at(cam, pos, tgt, up) == RES_OK);
    259 
    260   d3(dir, 1, 1, -1);
    261   d3_normalize(dir, dir);
    262   CHK(ssol_sun_create_directional(dev, &sun) == RES_OK);
    263   CHK(ssol_sun_set_direction(sun, dir) == RES_OK);
    264   CHK(ssol_sun_set_dni(sun, 1000) == RES_OK);
    265   CHK(ssol_scene_attach_sun(scn, sun) == RES_OK);
    266 
    267   pitch = WIDTH * sizeof_image_format(IMAGE_RGB8);
    268   image_init(&allocator, &img);
    269   image_setup(&img, WIDTH, HEIGHT, pitch, IMAGE_RGB8, NULL);
    270   pixels = (uint8_t*)img.pixels;
    271 
    272   CHK(draw_func(NULL, NULL, 0, 0, 0, NULL, pixels) == RES_BAD_ARG);
    273   CHK(draw_func(scn, NULL, 0, 0, 0, NULL, pixels) == RES_BAD_ARG);
    274   CHK(draw_func(NULL, cam, 0, 0, 0, NULL, pixels) == RES_BAD_ARG);
    275   CHK(draw_func(scn, cam, 0, 0, 0, NULL, pixels) == RES_BAD_ARG);
    276   CHK(draw_func(NULL, NULL, WIDTH, 0, 0, NULL, pixels) == RES_BAD_ARG);
    277   CHK(draw_func(scn, NULL, WIDTH, 0, 0, NULL, pixels) == RES_BAD_ARG);
    278   CHK(draw_func(NULL, cam, WIDTH, 0, 0, NULL, pixels) == RES_BAD_ARG);
    279   CHK(draw_func(scn, cam, WIDTH, 0, 0, NULL, pixels) == RES_BAD_ARG);
    280   CHK(draw_func(NULL, NULL, 0, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    281   CHK(draw_func(scn, NULL, 0, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    282   CHK(draw_func(NULL, cam, 0, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    283   CHK(draw_func(scn, cam, 0, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    284   CHK(draw_func(NULL, NULL, WIDTH, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    285   CHK(draw_func(scn, NULL, WIDTH, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    286   CHK(draw_func(NULL, cam, WIDTH, WIDTH, 0, NULL, pixels) == RES_BAD_ARG);
    287   CHK(draw_func(scn, cam, WIDTH, HEIGHT, 0, NULL, pixels) == RES_BAD_ARG);
    288   CHK(draw_func(NULL, NULL, 0, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    289   CHK(draw_func(scn, NULL, 0, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    290   CHK(draw_func(NULL, cam, 0, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    291   CHK(draw_func(scn, cam, 0, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    292   CHK(draw_func(NULL, NULL, WIDTH, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    293   CHK(draw_func(scn, NULL, WIDTH, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    294   CHK(draw_func(NULL, cam, WIDTH, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    295   CHK(draw_func(scn, cam, WIDTH, 0, 0, write_RGB8, pixels) == RES_BAD_ARG);
    296   CHK(draw_func(NULL, NULL, 0, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    297   CHK(draw_func(scn, NULL, 0, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    298   CHK(draw_func(NULL, cam, 0, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    299   CHK(draw_func(scn, cam, 0, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    300   CHK(draw_func(NULL, NULL, WIDTH, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    301   CHK(draw_func(scn, NULL, WIDTH, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    302   CHK(draw_func(NULL, cam, WIDTH, WIDTH, 0, write_RGB8, pixels) == RES_BAD_ARG);
    303   CHK(draw_func(scn, cam, WIDTH, HEIGHT, 0, write_RGB8, pixels) == RES_BAD_ARG);
    304   CHK(draw_func(NULL, NULL, 0, 0, 4, NULL, pixels) == RES_BAD_ARG);
    305   CHK(draw_func(scn, NULL, 0, 0, 4, NULL, pixels) == RES_BAD_ARG);
    306   CHK(draw_func(NULL, cam, 0, 0, 4, NULL, pixels) == RES_BAD_ARG);
    307   CHK(draw_func(scn, cam, 0, 0, 4, NULL, pixels) == RES_BAD_ARG);
    308   CHK(draw_func(NULL, NULL, WIDTH, 0, 4, NULL, pixels) == RES_BAD_ARG);
    309   CHK(draw_func(scn, NULL, WIDTH, 0, 4, NULL, pixels) == RES_BAD_ARG);
    310   CHK(draw_func(NULL, cam, WIDTH, 0, 4, NULL, pixels) == RES_BAD_ARG);
    311   CHK(draw_func(scn, cam, WIDTH, 0, 4, NULL, pixels) == RES_BAD_ARG);
    312   CHK(draw_func(NULL, NULL, 0, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    313   CHK(draw_func(scn, NULL, 0, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    314   CHK(draw_func(NULL, cam, 0, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    315   CHK(draw_func(scn, cam, 0, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    316   CHK(draw_func(NULL, NULL, WIDTH, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    317   CHK(draw_func(scn, NULL, WIDTH, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    318   CHK(draw_func(NULL, cam, WIDTH, WIDTH, 4, NULL, pixels) == RES_BAD_ARG);
    319   CHK(draw_func(scn, cam, WIDTH, HEIGHT, 4, NULL, pixels) == RES_BAD_ARG);
    320   CHK(draw_func(NULL, NULL, 0, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    321   CHK(draw_func(scn, NULL, 0, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    322   CHK(draw_func(NULL, cam, 0, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    323   CHK(draw_func(scn, cam, 0, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    324   CHK(draw_func(NULL, NULL, WIDTH, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    325   CHK(draw_func(scn, NULL, WIDTH, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    326   CHK(draw_func(NULL, cam, WIDTH, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    327   CHK(draw_func(scn, cam, WIDTH, 0, 4, write_RGB8, pixels) == RES_BAD_ARG);
    328   CHK(draw_func(NULL, NULL, 0, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    329   CHK(draw_func(scn, NULL, 0, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    330   CHK(draw_func(NULL, cam, 0, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    331   CHK(draw_func(scn, cam, 0, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    332   CHK(draw_func(NULL, NULL, WIDTH, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    333   CHK(draw_func(scn, NULL, WIDTH, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    334   CHK(draw_func(NULL, cam, WIDTH, WIDTH, 4, write_RGB8, pixels) == RES_BAD_ARG);
    335 
    336   /* No sun spectrum */
    337   CHK(draw_func(scn, cam, WIDTH, HEIGHT, 4, write_RGB8, pixels) == RES_BAD_ARG);
    338 
    339   CHK(ssol_spectrum_create(dev, &spectrum) == RES_OK);
    340   CHK(ssol_spectrum_setup(spectrum, get_wlen, 3, NULL) == RES_OK);
    341   CHK(ssol_sun_set_spectrum(sun, spectrum) == RES_OK);
    342   CHK(draw_func(scn, cam, WIDTH, HEIGHT, 4, write_RGB8, pixels) == RES_OK);
    343 
    344   CHK(image_write_ppm_stream(&img, 0, stdout) == RES_OK);
    345 
    346   if(draw_func == draw_pt) {
    347     CHK(ssol_draw_pt
    348       (scn, cam, WIDTH, HEIGHT, 4, NULL, write_RGB8, pixels) == RES_BAD_ARG);
    349   }
    350 
    351   CHK(image_release(&img) == RES_OK);
    352   CHK(ssol_device_ref_put(dev) == RES_OK);
    353   CHK(ssol_camera_ref_put(cam) == RES_OK);
    354   CHK(ssol_scene_ref_put(scn) == RES_OK);
    355   CHK(ssol_spectrum_ref_put(spectrum) == RES_OK);
    356   CHK(ssol_sun_ref_put(sun) == RES_OK);
    357 
    358   check_memory_allocator(&allocator);
    359   mem_shutdown_proxy_allocator(&allocator);
    360   CHK(mem_allocated_size() == 0);
    361   return 0;
    362 }
    363