star-sf

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

test_ssf_phase_rayleigh.c (2497B)


      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 "test_ssf_utils.h"
     18 
     19 #define NSAMPS 10000
     20 
     21 int
     22 main(int argc, char** argv)
     23 {
     24   struct mem_allocator allocator;
     25   struct ssf_phase* phase;
     26   struct ssp_rng* rng;
     27   double wo[3];
     28   double wi[3];
     29   double sum_cos = 0;
     30   double sum_cos_sqr = 0;
     31   double sum_cos_sqr2 = 0;
     32   double E, V, SE;
     33   size_t i;
     34   (void)argc, (void)argv;
     35 
     36   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
     37   CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
     38 
     39   CHK(ssf_phase_create(&allocator, &ssf_phase_rayleigh, &phase) == RES_OK);
     40 
     41   ssp_ran_sphere_uniform(rng, wo, NULL);
     42   FOR_EACH(i, 0, NSAMPS) {
     43     double w[3];
     44     double weight;
     45     double pdf;
     46     double ref;
     47     double r;
     48     ssf_phase_sample(phase, rng, wo, wi, &pdf);
     49     CHK(d3_is_normalized(wi));
     50     CHK(eq_eps(ssf_phase_pdf(phase, wo, wi), pdf, 1.e-6f));
     51     d3_minus(w, wo);
     52     weight = d3_dot(wo, wi);
     53     sum_cos += weight;
     54     sum_cos_sqr += weight*weight;
     55     sum_cos_sqr2 += weight*weight*weight*weight;
     56 
     57     r = ssf_phase_eval(phase, wo, wi);
     58     ref = 3.0/(16.0*PI)*(1.0+weight*weight);
     59     CHK(eq_eps(r, ref, 1.e-6));
     60     CHK(eq_eps(r, pdf, 1.e-6));
     61   }
     62 
     63   /* On average cos(-wo,wi) should be 0 */
     64   E = sum_cos / NSAMPS;
     65   V = sum_cos_sqr / NSAMPS - E*E;
     66   SE = sqrt(V/NSAMPS);
     67   CHK(eq_eps(E, 0, SE*3));
     68 
     69   /* On average cos(-wo,wi)^2 should be 2/5 */
     70   E = sum_cos_sqr / NSAMPS;
     71   V = sum_cos_sqr2 / NSAMPS - E*E;
     72   SE = sqrt(V/NSAMPS);
     73   CHK(eq_eps(E, 2.0/5.0, SE*3));
     74 
     75   ssf_phase_sample(phase, rng, wo, wi, NULL);
     76   CHK(d3_is_normalized(wi));
     77 
     78   CHK(ssf_phase_ref_put(phase) == RES_OK);
     79   CHK(ssp_rng_ref_put(rng) == RES_OK);
     80 
     81   check_memory_allocator(&allocator);
     82   mem_shutdown_proxy_allocator(&allocator);
     83   CHK(mem_allocated_size() == 0);
     84   return 0;
     85 }