ssf_fresnel_dielectric_conductor.c (3057B)
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_fresnel_c.h" 18 19 #include <math.h> 20 21 struct fresnel_dielectric_conductor { 22 double eta_i; /* Refraction id of the dielectric medium */ 23 double eta_t; /* Real part of the refraction index */ 24 double eta_k_t; /* Imaginary part of the refraction index */ 25 }; 26 27 /******************************************************************************* 28 * Private functions 29 ******************************************************************************/ 30 /* Code from 31 * https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ */ 32 static double 33 fresnel_dielectric_conductor_eval(void* fresnel, const double cos_theta_i) 34 { 35 const struct fresnel_dielectric_conductor* fc = fresnel; 36 double cos_theta_i2; 37 double sin_theta_i2; 38 double eta, eta_k, eta2, eta_k2; 39 double t0, t1, t2, t3, t4; 40 double a; 41 double a2_add_b2; 42 double Rp, Rs; 43 ASSERT(fresnel && cos_theta_i >= 0 && fc->eta_i > 0); 44 45 cos_theta_i2 = cos_theta_i * cos_theta_i; 46 sin_theta_i2 = 1.0 - cos_theta_i2; 47 eta = fc->eta_t / fc->eta_i; /* Real part */ 48 eta_k = fc->eta_k_t / fc->eta_i; /* Imaginary part */ 49 eta2 = eta*eta; 50 eta_k2 = eta_k*eta_k; 51 52 t0 = eta2 - eta_k2 - sin_theta_i2; 53 a2_add_b2 = sqrt(t0*t0 + 4*eta2*eta_k2); 54 t1 = a2_add_b2 + cos_theta_i2; 55 a = sqrt(0.5 * (a2_add_b2 + t0)); 56 t2 = 2.0*a*cos_theta_i; 57 Rs = (t1 - t2) / (t1 + t2); 58 59 t3 = cos_theta_i2 * a2_add_b2 + sin_theta_i2 * sin_theta_i2; 60 t4 = t2 * sin_theta_i2; 61 Rp = Rs * (t3 - t4) / (t3 + t4); 62 return 0.5 * (Rp + Rs); 63 } 64 65 /******************************************************************************* 66 * Exported symbols 67 ******************************************************************************/ 68 const struct ssf_fresnel_type ssf_fresnel_dielectric_conductor = { 69 NULL, 70 NULL, 71 fresnel_dielectric_conductor_eval, 72 sizeof(struct fresnel_dielectric_conductor), 73 ALIGNOF(struct fresnel_dielectric_conductor) 74 }; 75 76 res_T 77 ssf_fresnel_dielectric_conductor_setup 78 (struct ssf_fresnel* fresnel, 79 const double eta_i, 80 const double eta_t, 81 const double eta_k_t) 82 { 83 struct fresnel_dielectric_conductor* fc; 84 if(!fresnel 85 || !FRESNEL_TYPE_EQ(&fresnel->type, &ssf_fresnel_dielectric_conductor)) { 86 return RES_BAD_ARG; 87 } 88 fc = fresnel->data; 89 fc->eta_i = eta_i; 90 fc->eta_t = eta_t; 91 fc->eta_k_t = eta_k_t; 92 return RES_OK; 93 } 94