star-sf

Set of surface and volume scattering functions
git clone git://git.meso-star.fr/star-sf.git
Log | Files | Refs | README | LICENSE

ssf_bsdf.c (4144B)


      1 /* Copyright (C) 2016-2018, 2021-2025 |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 "ssf.h"
     17 #include "ssf_bsdf_c.h"
     18 
     19 #include <rsys/double3.h>
     20 #include <rsys/mem_allocator.h>
     21 #include <rsys/ref_count.h>
     22 
     23 #include <string.h>
     24 
     25 /*******************************************************************************
     26  * Helper functions
     27  ******************************************************************************/
     28 static INLINE int
     29 check_bsdf_type(const struct ssf_bsdf_type* type)
     30 {
     31   return type
     32       && type->sample
     33       && type->eval
     34       && type->pdf
     35       && IS_POW2(type->alignof_bsdf);
     36 }
     37 
     38 static void
     39 bsdf_release(ref_T* ref)
     40 {
     41   struct ssf_bsdf* bsdf = CONTAINER_OF(ref, struct ssf_bsdf, ref);
     42   ASSERT(ref);
     43   if(bsdf->data) {
     44     if(bsdf->type.release) bsdf->type.release(bsdf->data);
     45     MEM_RM(bsdf->allocator, bsdf->data);
     46   }
     47   MEM_RM(bsdf->allocator, bsdf);
     48 }
     49 
     50 /*******************************************************************************
     51  * Exported functions
     52  ******************************************************************************/
     53 res_T
     54 ssf_bsdf_create
     55   (struct mem_allocator* allocator,
     56    const struct ssf_bsdf_type* type,
     57    struct ssf_bsdf** out_bsdf)
     58 {
     59   struct mem_allocator* mem_allocator = NULL;
     60   struct ssf_bsdf* bsdf = NULL;
     61   res_T res = RES_OK;
     62 
     63   if(!out_bsdf || !check_bsdf_type(type)) {
     64     res = RES_BAD_ARG;
     65     goto error;
     66   }
     67   mem_allocator = allocator ? allocator : &mem_default_allocator;
     68   bsdf = MEM_CALLOC(mem_allocator, 1, sizeof(struct ssf_bsdf));
     69   if(!bsdf) {
     70     res = RES_MEM_ERR;
     71     goto error;
     72   }
     73   ref_init(&bsdf->ref);
     74   bsdf->allocator = mem_allocator;
     75   bsdf->type = *type;
     76 
     77   if(bsdf->type.sizeof_bsdf) {
     78     bsdf->data = MEM_ALLOC_ALIGNED
     79       (bsdf->allocator, bsdf->type.sizeof_bsdf, bsdf->type.alignof_bsdf);
     80     if(!bsdf->data) {
     81       res = RES_MEM_ERR;
     82       goto error;
     83     }
     84     memset(bsdf->data, 0, bsdf->type.sizeof_bsdf);
     85     if(bsdf->type.init) {
     86       res = bsdf->type.init(mem_allocator, bsdf->data);
     87       if(res != RES_OK) goto error;
     88     }
     89   }
     90 
     91 exit:
     92   if(out_bsdf) *out_bsdf = bsdf;
     93   return res;
     94 error:
     95   if(bsdf) {
     96     SSF(bsdf_ref_put(bsdf));
     97     bsdf = NULL;
     98   }
     99   goto exit;
    100 }
    101 
    102 res_T
    103 ssf_bsdf_ref_get(struct ssf_bsdf* bsdf)
    104 {
    105   if(!bsdf) return RES_BAD_ARG;
    106   ref_get(&bsdf->ref);
    107   return RES_OK;
    108 }
    109 
    110 res_T
    111 ssf_bsdf_ref_put(struct ssf_bsdf* bsdf)
    112 {
    113   if(!bsdf) return RES_BAD_ARG;
    114   ref_put(&bsdf->ref, bsdf_release);
    115   return RES_OK;
    116 }
    117 
    118 double
    119 ssf_bsdf_sample
    120   (struct ssf_bsdf* bsdf,
    121    struct ssp_rng* rng,
    122    const double wo[3],
    123    const double N[3],
    124    double wi[3],
    125    int* type,
    126    double* out_pdf)
    127 {
    128   double R;
    129   ASSERT(bsdf && rng && wo && N && wi);
    130   ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
    131   R = bsdf->type.sample(bsdf->data, rng, wo, N, wi, type, out_pdf);
    132   return R;
    133 }
    134 
    135 double
    136 ssf_bsdf_eval
    137   (struct ssf_bsdf* bsdf,
    138    const double wo[3],
    139    const double N[3],
    140    const double wi[3])
    141 {
    142   ASSERT(bsdf && wo && N && wi);
    143   ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi));
    144   return bsdf->type.eval(bsdf->data, wo, N, wi);
    145 }
    146 
    147 double
    148 ssf_bsdf_pdf
    149   (struct ssf_bsdf* bsdf,
    150    const double wo[3],
    151    const double N[3],
    152    const double wi[3])
    153 {
    154   ASSERT(bsdf && wi && wo);
    155   ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi));
    156   return bsdf->type.pdf(bsdf->data, wo, N, wi);
    157 }
    158 
    159 res_T
    160 ssf_bsdf_get_data(struct ssf_bsdf* bsdf, void** data)
    161 {
    162   if(!bsdf || !data) return RES_BAD_ARG;
    163   *data = bsdf->data;
    164   return RES_OK;
    165 }
    166