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_fresnel.c (3515B)


      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_fresnel_c.h"
     17 
     18 #include <rsys/math.h>
     19 #include <rsys/mem_allocator.h>
     20 
     21 #include <string.h>
     22 
     23 /*******************************************************************************
     24  * Helper functions
     25  ******************************************************************************/
     26 static INLINE int
     27 check_fresnel_type(const struct ssf_fresnel_type* type)
     28 {
     29   return type
     30       && type->eval
     31       && IS_POW2(type->alignof_fresnel);
     32 }
     33 
     34 static void
     35 fresnel_release(ref_T* ref)
     36 {
     37   struct ssf_fresnel* fresnel = CONTAINER_OF(ref, struct ssf_fresnel, ref);
     38   ASSERT(ref);
     39   if(fresnel->data) {
     40     if(fresnel->type.release) fresnel->type.release(fresnel->data);
     41     MEM_RM(fresnel->allocator, fresnel->data);
     42   }
     43   MEM_RM(fresnel->allocator, fresnel);
     44 }
     45 
     46 /*******************************************************************************
     47  * Exported functions
     48  ******************************************************************************/
     49 res_T
     50 ssf_fresnel_create
     51   (struct mem_allocator* allocator,
     52    const struct ssf_fresnel_type* type,
     53    struct ssf_fresnel** out_fresnel)
     54 {
     55   struct mem_allocator* mem_allocator;
     56   struct ssf_fresnel* fresnel = NULL;
     57   res_T res = RES_OK;
     58 
     59   if(!out_fresnel || !check_fresnel_type(type)) {
     60     res = RES_BAD_ARG;
     61     goto error;
     62   }
     63 
     64   mem_allocator = allocator ? allocator : &mem_default_allocator;
     65   fresnel = MEM_CALLOC(mem_allocator, 1, sizeof(struct ssf_fresnel));
     66   if(!fresnel) {
     67     res = RES_MEM_ERR;
     68     goto error;
     69   }
     70   ref_init(&fresnel->ref);
     71   fresnel->allocator = mem_allocator;
     72   fresnel->type = *type;
     73 
     74   if(fresnel->type.sizeof_fresnel) {
     75     fresnel->data = MEM_ALLOC_ALIGNED(fresnel->allocator,
     76       fresnel->type.sizeof_fresnel, fresnel->type.alignof_fresnel);
     77     if(!fresnel->data) {
     78       res = RES_MEM_ERR;
     79       goto error;
     80     }
     81     memset(fresnel->data, 0, fresnel->type.sizeof_fresnel);
     82     if(fresnel->type.init) {
     83       res = fresnel->type.init(fresnel->allocator, fresnel->data);
     84       if(res != RES_OK) goto error;
     85     }
     86   }
     87 
     88 exit:
     89   if(out_fresnel) *out_fresnel = fresnel;
     90   return res;
     91 error:
     92   if(fresnel) {
     93     SSF(fresnel_ref_put(fresnel));
     94     fresnel = NULL;
     95   }
     96   goto exit;
     97 }
     98 
     99 res_T
    100 ssf_fresnel_ref_get(struct ssf_fresnel* fresnel)
    101 {
    102   if(!fresnel) return RES_BAD_ARG;
    103   ref_get(&fresnel->ref);
    104   return RES_OK;
    105 }
    106 
    107 res_T
    108 ssf_fresnel_ref_put(struct ssf_fresnel* fresnel)
    109 {
    110   if(!fresnel) return RES_BAD_ARG;
    111   ref_put(&fresnel->ref, fresnel_release);
    112   return RES_OK;
    113 }
    114 
    115 double
    116 ssf_fresnel_eval(struct ssf_fresnel* fresnel, const double cos_theta)
    117 {
    118   ASSERT(fresnel && cos_theta >= 0);
    119   return fresnel->type.eval(fresnel->data, cos_theta);
    120 }
    121 
    122 res_T
    123 ssf_fresnel_get_data(struct ssf_fresnel* fresnel, void** data)
    124 {
    125   if(!fresnel || !data) return RES_BAD_ARG;
    126   *data = fresnel->data;
    127   return RES_OK;
    128 }
    129