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