sdis_misc.c (3731B)
1 /* Copyright (C) 2016-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 "sdis.h" 17 #include "sdis_heat_path.h" 18 #include "sdis_log.h" 19 #include "sdis_medium_c.h" 20 #include "sdis_misc.h" 21 #include "sdis_green.h" 22 23 #include <star/ssp.h> 24 25 res_T 26 time_rewind 27 (struct sdis_scene* scn, 28 const double mu, 29 const double t0, 30 struct ssp_rng* rng, 31 struct rwalk* rwalk, 32 const struct rwalk_context* ctx, 33 struct temperature* T) 34 { 35 const struct enclosure* enc = NULL; 36 struct sdis_medium* mdm = NULL; 37 double temperature; 38 double tau; 39 res_T res = RES_OK; 40 ASSERT(scn && rwalk && ctx && rng && T); 41 42 /* Get the current medium */ 43 enc = scene_get_enclosure(scn, rwalk->enc_id); 44 res = scene_get_enclosure_medium(scn, enc, &mdm); 45 if(res != RES_OK) goto error; 46 47 /* Sample the time using the upper bound. */ 48 tau = ssp_ran_exp(rng, mu); 49 50 /* Increment the elapsed time */ 51 ASSERT(rwalk->vtx.time >= t0); 52 rwalk->elapsed_time += MMIN(tau, rwalk->vtx.time - t0); 53 54 if(IS_INF(rwalk->vtx.time)) goto exit; /* Steady computation */ 55 56 /* Time rewind */ 57 rwalk->vtx.time = MMAX(rwalk->vtx.time - tau, t0); /* Time rewind */ 58 59 /* The path does not reach the limit condition */ 60 if(rwalk->vtx.time > t0) goto exit; 61 62 /* Fetch the initial temperature */ 63 temperature = medium_get_temperature(mdm, &rwalk->vtx); 64 if(SDIS_TEMPERATURE_IS_UNKNOWN(temperature)) { 65 log_err(mdm->dev, "the path reaches the limit condition but the " 66 "%s temperature remains unknown -- position=%g, %g, %g\n", 67 medium_type_to_string(sdis_medium_get_type(mdm)), 68 SPLIT3(rwalk->vtx.P)); 69 res = RES_BAD_ARG; 70 goto error; 71 } 72 73 /* Update temperature */ 74 T->value += temperature; 75 T->done = 1; 76 77 if(ctx->heat_path) { 78 /* Update the registered vertex data */ 79 struct sdis_heat_vertex* vtx; 80 vtx = heat_path_get_last_vertex(ctx->heat_path); 81 vtx->time = rwalk->vtx.time; 82 vtx->weight = T->value; 83 } 84 85 if(ctx->green_path) { 86 res = green_path_set_limit_vertex 87 (ctx->green_path, mdm, &rwalk->vtx, rwalk->elapsed_time); 88 if(res != RES_OK) goto error; 89 } 90 91 exit: 92 return res; 93 error: 94 goto exit; 95 } 96 97 res_T 98 check_primitive_uv_2d(struct sdis_device* dev, const double param_coord[]) 99 { 100 double u; 101 res_T res = RES_OK; 102 ASSERT(dev && param_coord); 103 104 u = param_coord[0]; 105 106 if(u < 0 || 1 < u) { 107 log_err(dev, 108 "%s: invalid parametric coordinates u=%g; it must be in [0, 1].\n", 109 FUNC_NAME, u); 110 res = RES_BAD_ARG; 111 goto error; 112 } 113 114 exit: 115 return res; 116 error: 117 goto exit; 118 } 119 120 res_T 121 check_primitive_uv_3d(struct sdis_device* dev, const double param_coords[]) 122 { 123 double u, v, w; 124 res_T res = RES_OK; 125 ASSERT(dev && param_coords); 126 127 u = param_coords[0]; 128 v = param_coords[1]; 129 w = CLAMP(1 - u - v, 0, 1); 130 131 if(u < 0 || 1 < u || v < 0 || 1 < v || !eq_eps(u + v + w, 1, 1.e-6)) { 132 log_err(dev, 133 "%s: invalid parametric coordinates u=%g; v=%g. " 134 "u + v + (1-u-v) must be equal to 1 with u and v in [0, 1].\n", 135 FUNC_NAME, u, v); 136 res = RES_BAD_ARG; 137 goto error; 138 } 139 140 exit: 141 return res; 142 error: 143 goto exit; 144 }