star-camera

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

test_scam_cbox.c (6875B)


      1 /* Copyright (C) 2021-2023 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "scam.h"
     17 #include "test_scam_cbox.h"
     18 #include "test_scam_utils.h"
     19 
     20 #include <star/s3d.h>
     21 
     22 #include <rsys/double3.h>
     23 #include <rsys/float2.h>
     24 #include <rsys/float3.h>
     25 #include <rsys/image.h>
     26 #include <rsys/mem_allocator.h>
     27 
     28 #include <string.h>
     29 
     30 #define IMG_WIDTH 640
     31 #define IMG_HEIGHT 480
     32 #define IMG_SPP 16
     33 
     34 enum lens_model {
     35   PINHOLE,
     36   THIN_LENS
     37 };
     38 
     39 enum camera_model {
     40   ORTHOGRAPHIC,
     41   PERSPECTIVE
     42 };
     43 
     44 static struct s3d_scene_view*
     45 create_s3d_scene_view(void)
     46 {
     47   struct s3d_vertex_data vdata;
     48   struct s3d_device* s3d = NULL;
     49   struct s3d_scene* scn = NULL;
     50   struct s3d_shape* shape = NULL;
     51   struct s3d_scene_view* view = NULL;
     52 
     53   CHK(s3d_device_create(NULL, NULL, 0, &s3d) == RES_OK);
     54 
     55   vdata.usage = S3D_POSITION;
     56   vdata.type = S3D_FLOAT3;
     57   vdata.get = cbox_get_vtx;
     58   CHK(s3d_shape_create_mesh(s3d, &shape) == RES_OK);
     59   CHK(s3d_mesh_setup_indexed_vertices(shape, cbox_ntris, cbox_get_tri,
     60     cbox_nvtxs, &vdata, 1, NULL) == RES_OK);
     61 
     62   CHK(s3d_scene_create(s3d, &scn) == RES_OK);
     63   CHK(s3d_scene_attach_shape(scn, shape) == RES_OK);
     64   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
     65 
     66   CHK(s3d_device_ref_put(s3d) == RES_OK);
     67   CHK(s3d_shape_ref_put(shape) == RES_OK);
     68   CHK(s3d_scene_ref_put(scn) == RES_OK);
     69 
     70   return view;
     71 }
     72 
     73 static void
     74 create_perspective(const enum lens_model lens_model, struct scam** cam)
     75 {
     76   struct scam_perspective_args args = SCAM_PERSPECTIVE_ARGS_DEFAULT;
     77   CHK(cam);
     78 
     79   args.position[0] = 89.66;
     80   args.position[1] = 21.89;
     81   args.position[2] = 202.22;
     82   args.target[0] = 150.03;
     83   args.target[1] = 135;
     84   args.target[2] = 196.87;
     85   args.up[0] = 0;
     86   args.up[1] = 0;
     87   args.up[2] = 1;
     88   args.field_of_view = 1.22173047639603070383; /* ~70 degrees */
     89   args.aspect_ratio = (double)IMG_WIDTH/(double)IMG_HEIGHT;
     90 
     91   switch(lens_model) {
     92     case PINHOLE: 
     93       args.lens_radius = 0;
     94       break;
     95     case THIN_LENS:
     96       args.lens_radius = 5;
     97       args.focal_distance = 300;
     98       break;
     99     default: FATAL("Unreachable code.\n"); break;
    100   }
    101 
    102   CHK(scam_create_perspective(NULL, NULL, 1, &args, cam) == RES_OK);
    103 }
    104 
    105 static void
    106 create_orthographic(const enum lens_model lens_model, struct scam** cam)
    107 {
    108   struct scam_orthographic_args args = SCAM_ORTHOGRAPHIC_ARGS_DEFAULT;
    109   CHK(cam);
    110 
    111   args.position[0] = 89.66;
    112   args.position[1] = 21.89;
    113   args.position[2] = 202.22;
    114   args.target[0] = 150.03;
    115   args.target[1] = 135;
    116   args.target[2] = 196.87;
    117   args.up[0] = 0;
    118   args.up[1] = 0;
    119   args.up[2] = 1;
    120   args.height = 500;
    121   args.aspect_ratio = (double)IMG_WIDTH/(double)IMG_HEIGHT;
    122 
    123   /* No thin-lens model for orthographic projection */
    124   CHK(lens_model == PINHOLE);
    125 
    126   CHK(scam_create_orthographic(NULL, NULL, 1, &args, cam) == RES_OK);
    127 }
    128 
    129 
    130 static void
    131 draw
    132   (const struct scam* cam,
    133    struct s3d_scene_view* view,
    134    struct image* img)
    135 {
    136   int x, y, s;
    137   double pixsz[2];
    138   CHK(img);
    139 
    140   pixsz[0] = 1.0 / (double)IMG_WIDTH;
    141   pixsz[1] = 1.0 / (double)IMG_HEIGHT;
    142 
    143   FOR_EACH(y, 0, IMG_HEIGHT) {
    144     FOR_EACH(x, 0, IMG_WIDTH) {
    145       double sum[3] = {0,0,0};
    146       double E[3] = {0,0,0};
    147       int ipix;
    148 
    149       FOR_EACH(s, 0, IMG_SPP) {
    150         struct s3d_hit hit = S3D_HIT_NULL;
    151         struct scam_sample sample = SCAM_SAMPLE_NULL;
    152         struct scam_ray ray = SCAM_RAY_NULL;
    153         double col[3];
    154         float org[3];
    155         float dir[3];
    156         float range[2];
    157         float N[3];
    158         float cos_N_dir;
    159 
    160         /* Generate the camera ray */
    161         sample.film[0] = ((double)x + rand_canonical()) * pixsz[0];
    162         sample.film[1] = ((double)y + rand_canonical()) * pixsz[1];
    163         sample.lens[0] = rand_canonical();
    164         sample.lens[1] = rand_canonical();
    165         CHK(scam_generate_ray(cam, &sample, &ray) == RES_OK);
    166 
    167         /* Trace the ray */
    168         f3_set_d3(org, ray.org);
    169         f3_normalize(dir, f3_set_d3(dir, ray.dir));
    170         f2(range, 0, (float)INF);
    171         CHK(s3d_scene_view_trace_ray(view, org, dir, range, NULL, &hit) == RES_OK);
    172 
    173         if(S3D_HIT_NONE(&hit)) continue;
    174 
    175         /* Shade */
    176         cbox_get_col(hit.prim.prim_id, col);
    177         f3_normalize(N, hit.normal);
    178         cos_N_dir = absf(f3_dot(N, dir));
    179 
    180         sum[0] += (float)(cos_N_dir * col[0]);
    181         sum[1] += (float)(cos_N_dir * col[1]);
    182         sum[2] += (float)(cos_N_dir * col[2]);
    183       }
    184       /* Compute pixel color */
    185       E[0] = sum[0] / (double)IMG_SPP;
    186       E[1] = sum[1] / (double)IMG_SPP;
    187       E[2] = sum[2] / (double)IMG_SPP;
    188 
    189       /* Write pixel color */
    190       ipix = (y*IMG_WIDTH + x) * 3/*RGB*/;
    191       ((uint8_t*)img->pixels)[ipix+0] = (uint8_t)(E[0] * 255);
    192       ((uint8_t*)img->pixels)[ipix+1] = (uint8_t)(E[1] * 255);
    193       ((uint8_t*)img->pixels)[ipix+2] = (uint8_t)(E[2] * 255);
    194     }
    195   }
    196 }
    197 
    198 int
    199 main(int argc, char** argv)
    200 {
    201   struct s3d_scene_view* view = NULL;
    202   struct scam* cam = NULL;
    203   struct image img;
    204   enum camera_model cam_model;
    205   enum lens_model lens_model;
    206   int err = 0;
    207 
    208   if(argc <= 2) {
    209     fprintf(stderr,
    210       "Usage: %s <orthographic|perspective> <pinhole|thin-lens>\n",
    211       argv[0]);
    212     goto error;
    213   }
    214 
    215   if(!strcmp(argv[1], "orthographic")) {
    216     cam_model = ORTHOGRAPHIC;
    217   } else if(!strcmp(argv[1], "perspective")) {
    218     cam_model = PERSPECTIVE;
    219   } else {
    220     fprintf(stderr, "Invalid camera model `%s'.\n", argv[1]);
    221     goto error;
    222   }
    223 
    224   if(!strcmp(argv[2], "pinhole")){
    225     lens_model = PINHOLE;
    226   } else if(!strcmp(argv[2], "thin-lens")) {
    227     lens_model = THIN_LENS;
    228   } else {
    229     fprintf(stderr, "Invalid lens model `%s'.\n", argv[2]);
    230     goto error;
    231   }
    232 
    233   view = create_s3d_scene_view();
    234 
    235   switch(cam_model) {
    236     case ORTHOGRAPHIC: create_orthographic(lens_model, &cam); break;
    237     case PERSPECTIVE: create_perspective(lens_model, &cam); break;
    238     default: FATAL("Unreachable code.\n"); break;
    239   }
    240 
    241   image_init(NULL, &img);
    242   CHK(image_setup
    243     (&img, IMG_WIDTH, IMG_HEIGHT, IMG_WIDTH*3, IMAGE_RGB8, NULL) == RES_OK);
    244 
    245   draw(cam, view, &img);
    246 
    247   CHK(image_write_ppm_stream(&img, 0, stdout) == RES_OK);
    248 
    249   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    250   CHK(scam_ref_put(cam) == RES_OK);
    251   image_release(&img);
    252 
    253 exit:
    254   CHK(mem_allocated_size() == 0);
    255   return err;
    256 error:
    257   err = 1;
    258   goto exit;
    259 }