BRL-CAD
sh_air.c
Go to the documentation of this file.
1 /* S H _ A I R . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file liboptical/sh_air.c
21  *
22  */
23 
24 #include "common.h"
25 
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <math.h>
30 
31 #include "bu/units.h"
32 #include "vmath.h"
33 #include "raytrace.h"
34 #include "optical.h"
35 
36 
37 #define AIR_MAGIC 0x41697200 /* "Air" */
38 struct air_specific {
39  uint32_t magic;
40  double d_p_mm; /* density per unit millimeter (specified in m)*/
41  double scale; /* only used in emist */
42  double delta; /* only used in emist */
43  char *name; /* name of "ground" object for emist_terrain_render */
44 };
45 #define CK_AIR_SP(_p) BU_CKMAG(_p, AIR_MAGIC, "air_specific")
46 
47 static struct air_specific air_defaults = {
48  AIR_MAGIC,
49  .1, /* d_p_mm */
50  .01, /* scale */
51  0.0, /* delta */
52  NULL /* name */
53 };
54 
55 
56 #define SHDR_NULL ((struct air_specific *)0)
57 #define SHDR_O(m) bu_offsetof(struct air_specific, m)
58 
59 /* local sp_hook function */
60 static void dpm_hook(const struct bu_structparse *, const char *name, void *, const char *, void *);
61 
63  {"%g", 1, "dpm", SHDR_O(d_p_mm), dpm_hook, NULL, NULL },
64  {"%g", 1, "scale", SHDR_O(scale), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
65  {"%g", 1, "s", SHDR_O(scale), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
66  {"%g", 1, "delta", SHDR_O(delta), bu_mm_cvt, NULL, NULL },
67  {"%f", 1, "d", SHDR_O(delta), bu_mm_cvt, NULL, NULL },
68  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
69 };
70 
71 
72 HIDDEN int air_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip);
73 HIDDEN int airtest_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
74 HIDDEN int air_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
75 HIDDEN int emist_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
76 HIDDEN int tmist_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
77 HIDDEN void air_print(register struct region *rp, void *dp);
78 HIDDEN void air_free(void *cp);
79 
80 struct mfuncs air_mfuncs[] = {
81  {MF_MAGIC, "airtest", 0, MFI_HIT, MFF_PROC,
82  air_setup, airtest_render, air_print, air_free },
83 
84  {MF_MAGIC, "air", 0, MFI_HIT, MFF_PROC,
85  air_setup, air_render, air_print, air_free },
86 
87  {MF_MAGIC, "fog", 0, MFI_HIT, MFF_PROC,
88  air_setup, air_render, air_print, air_free },
89 
90  {MF_MAGIC, "emist", 0, MFI_HIT, MFF_PROC,
91  air_setup, emist_render, air_print, air_free },
92 
93  {MF_MAGIC, "tmist", 0, MFI_HIT, MFF_PROC,
94  air_setup, tmist_render, air_print, air_free },
95 
96  {0, (char *)0, 0, 0, 0,
97  0, 0, 0, 0 }
98 };
99 
100 static void
101 dpm_hook(const struct bu_structparse *UNUSED(sdp),
102  const char *UNUSED(name),
103  void *base,
104  const char *UNUSED(value),
105  void *UNUSED(data))
106 /* structure description */
107 /* struct member name */
108 /* beginning of structure */
109 /* string containing value */
110 {
111 #define meters_to_millimeters 0.001
112  struct air_specific *air_sp = (struct air_specific *)base;
113 
114  air_sp->d_p_mm *= meters_to_millimeters;
115 }
116 
117 /*
118  * This routine is called (at prep time)
119  * once for each region which uses this shader.
120  * Any shader-specific initialization should be done here.
121  */
122 HIDDEN int
123 air_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
124 /* pointer to reg_udata in *rp */
125 /* New since 4.4 release */
126 {
127  register struct air_specific *air_sp;
128 
129  if (rdebug&RDEBUG_SHADE) bu_log("air_setup\n");
130 
131  RT_CHECK_RTI(rtip);
132  BU_CK_VLS(matparm);
133  RT_CK_REGION(rp);
134  BU_GET(air_sp, struct air_specific);
135  *dpp = (char *)air_sp;
136 
137  memcpy(air_sp, &air_defaults, sizeof(struct air_specific));
138 
139  if (rp->reg_aircode == 0) {
140  bu_log("WARNING(%s): air shader '%s' applied to non-air region.\n%s\n",
141  rp->reg_name,
142  mfp->mf_name,
143  " Set air flag with \"edcodes\" in mged");
144  bu_bomb("");
145  }
146 
147  if (rdebug&RDEBUG_SHADE) bu_log("\"%s\"\n", bu_vls_addr(matparm));
148  if (bu_struct_parse(matparm, air_parse, (char *)air_sp, NULL) < 0)
149  return -1;
150 
151  if (rdebug&RDEBUG_SHADE) air_print(rp, (char *)air_sp);
152 
153  return 1;
154 }
155 
156 
157 HIDDEN void
158 air_print(register struct region *rp, void *dp)
159 {
160  bu_struct_print(rp->reg_name, air_parse, (const char *)dp);
161 }
162 
163 
164 HIDDEN void
165 air_free(void *cp)
166 {
167  if (rdebug&RDEBUG_SHADE)
168  bu_log("air_free(%s:%d)\n", __FILE__, __LINE__);
169  BU_PUT(cp, struct air_specific);
170 }
171 
172 
173 /*
174  * This is called (from viewshade() in shade.c)
175  * once for each hit point to be shaded.
176  */
177 int
178 airtest_render(struct application *ap, const struct partition *pp, struct shadework *UNUSED(swp), void *dp)
179 {
180  register struct air_specific *air_sp =
181  (struct air_specific *)dp;
182 
183  RT_AP_CHECK(ap);
184  RT_CHECK_PT(pp);
185  CK_AIR_SP(air_sp);
186 
187  if (rdebug&RDEBUG_SHADE) {
188  bu_struct_print("air_specific", air_parse, (char *)air_sp);
189 
190  bu_log("air in(%g) out%g)\n",
191  pp->pt_inhit->hit_dist,
192  pp->pt_outhit->hit_dist);
193  }
194 
195  return 1;
196 }
197 /*
198  * This is called (from viewshade() in shade.c)
199  * once for each hit point to be shaded.
200  *
201  *
202  * This implements Beer's law homogeneous Fog/haze
203  *
204  * Tau = optical path depth = density_per_unit_distance * distance
205  *
206  * transmission = e^(-Tau)
207  */
208 int
209 air_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
210 {
211  register struct air_specific *air_sp =
212  (struct air_specific *)dp;
213  double tau;
214  double dist;
215 
216  RT_AP_CHECK(ap);
217  RT_CHECK_PT(pp);
218  CK_AIR_SP(air_sp);
219 
220  if (rdebug&RDEBUG_SHADE) {
221  bu_struct_print("air_specific", air_parse, (char *)air_sp);
222  bu_log("air in(%g) out(%g) r_pt(%g %g %g)\n",
223  pp->pt_inhit->hit_dist,
224  pp->pt_outhit->hit_dist,
225  V3ARGS(ap->a_ray.r_pt));
226  }
227 
228  /* Beer's Law Homogeneous Fog */
229 
230  /* get the path length right */
231  if (pp->pt_inhit->hit_dist < 0.0)
232  dist = pp->pt_outhit->hit_dist;
233  else
234  dist = (pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist);
235 
236  /* tau = optical path depth = density per mm * distance in mm */
237  tau = air_sp->d_p_mm * dist;
238 
239  /* transmission = e^(-tau) */
240  swp->sw_transmit = exp(-tau);
241 
242  if (swp->sw_transmit > 1.0) swp->sw_transmit = 1.0;
243  else if (swp->sw_transmit < 0.0) swp->sw_transmit = 0.0;
244 
245  /* extinction = 1.0 - transmission. Extinguished part replaced by
246  * the "color of the air".
247  */
248 
249  if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
250  (void)rr_render(ap, pp, swp);
251 
252  if (rdebug&RDEBUG_SHADE)
253  bu_log("air o dist:%gmm tau:%g transmit:%g\n",
254  dist, tau, swp->sw_transmit);
255 
256  return 1;
257 }
258 
259 
260 int
261 tmist_hit(register struct application *UNUSED(ap), struct partition *UNUSED(PartHeadp), struct seg *UNUSED(segHeadp))
262 {
263  /* go looking for the object named in
264  * ((struct air_specific *)ap->a_uptr)->name
265  * in the partition list,
266  * set ap->a_dist to distance to that object
267  */
268  return 0;
269 }
270 
271 
272 int
273 tmist_miss(register struct application *UNUSED(ap))
274 {
275  /* we missed?! This is bogus!
276  * but set ap->a_dist to something big
277  */
278  return 0;
279 }
280 
281 
282 /*
283  * Use height above named terrain object
284  *
285  *
286  * This is called (from viewshade() in shade.c)
287  * once for each hit point to be shaded.
288  */
289 int
290 tmist_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
291 {
292  register struct air_specific *air_sp =
293  (struct air_specific *)dp;
294  point_t in_pt, out_pt;
295  vect_t vapor_path;
296  fastf_t dist;
297  fastf_t step_dist;
298  fastf_t tau;
299  fastf_t dt;
300  struct application my_ap;
301  long meters;
302 
303  RT_AP_CHECK(ap);
304  RT_CHECK_PT(pp);
305  CK_AIR_SP(air_sp);
306 
307  RT_APPLICATION_INIT(&my_ap);
308 
309  /* Get entry point */
310  if (pp->pt_inhit->hit_dist < 0.0) {
311  VMOVE(in_pt, ap->a_ray.r_pt);
312  } else {
313  VJOIN1(in_pt, ap->a_ray.r_pt,
314  pp->pt_inhit->hit_dist, ap->a_ray.r_dir);
315  }
316 
317  /* Get exit point */
318  VJOIN1(out_pt,
319  ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
320 
321  VSUB2(vapor_path, out_pt, in_pt);
322 
323  dist = MAGNITUDE(vapor_path);
324  meters = (long)dist;
325  meters = meters >> 3;
326 
327  if (meters < 1) step_dist = dist;
328  else step_dist = dist / (fastf_t)meters;
329 
330  for (dt = 0.0; dt <= dist; dt += step_dist) {
331  memcpy((char *)&my_ap, (char *)ap, sizeof(struct application));
332  VJOIN1(my_ap.a_ray.r_pt, in_pt, dt, my_ap.a_ray.r_dir);
333  VSET(my_ap.a_ray.r_dir, 0.0, 0.0, -1.0);
334  my_ap.a_hit = tmist_hit;
335  my_ap.a_miss = tmist_miss;
336  my_ap.a_logoverlap = ap->a_logoverlap;
337  my_ap.a_onehit = 0;
338  my_ap.a_uptr = (void *)air_sp;
339  rt_shootray(&my_ap);
340 
341  /* XXX check my_ap.a_dist for distance to ground */
342 
343  /* XXX compute optical density at this altitude */
344 
345  /* XXX integrate in the effects of this meter of air */
346 
347  }
348  tau = 42;
349 
350 
351  swp->sw_transmit = exp(-tau);
352 
353  if (swp->sw_transmit > 1.0) swp->sw_transmit = 1.0;
354  else if (swp->sw_transmit < 0.0) swp->sw_transmit = 0.0;
355 
356  if (rdebug&RDEBUG_SHADE)
357  bu_log("tmist transmit = %g\n", swp->sw_transmit);
358 
359  return 1;
360 }
361 /*
362  * te = dist from pt to end of ray (out hit point)
363  * Zo = elevation at ray start
364  * Ze = elevation at ray end
365  * Zd = Z component of normalized ray vector
366  * d_p_mm = overall fog density
367  * B = density falloff with altitude
368  *
369  *
370  * delta = height at which fog starts
371  * scale = stretches exponential decay zone
372  * d_p_mm = maximum density @ ground
373  *
374  * This is called (from viewshade() in shade.c)
375  * once for each hit point to be shaded.
376  */
377 int
378 emist_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
379 {
380  register struct air_specific *air_sp =
381  (struct air_specific *)dp;
382  point_t in_pt, out_pt;
383  double tau;
384  double Zo, Ze, Zd, te;
385 
386  RT_AP_CHECK(ap);
387  RT_CHECK_PT(pp);
388  CK_AIR_SP(air_sp);
389 
390  /* compute hit point & length of ray */
391  if (pp->pt_inhit->hit_dist < 0.0) {
392  VMOVE(in_pt, ap->a_ray.r_pt);
393  te = pp->pt_outhit->hit_dist;
394  } else {
395  VJOIN1(in_pt, ap->a_ray.r_pt,
396  pp->pt_inhit->hit_dist, ap->a_ray.r_dir);
397  te = pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist;
398  }
399 
400  /* get exit point */
401  VJOIN1(out_pt,
402  ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
403 
404  Zo = (air_sp->delta + in_pt[Z]) * air_sp->scale;
405  Ze = (air_sp->delta + out_pt[Z]) * air_sp->scale;
406  Zd = ap->a_ray.r_dir[Z];
407 
408  if (ZERO(Zd))
409  tau = air_sp->d_p_mm * te * exp(-Zo);
410  else
411  tau = ((air_sp->d_p_mm * te) / Zd) * (exp(-Zo) - exp(-Ze));
412 
413 /* XXX future
414  tau *= bn_noise_fbm(pt);
415 */
416 
417  swp->sw_transmit = exp(-tau);
418 
419  if (swp->sw_transmit > 1.0) swp->sw_transmit = 1.0;
420  else if (swp->sw_transmit < 0.0) swp->sw_transmit = 0.0;
421 
422  if (rdebug&RDEBUG_SHADE)
423  bu_log("emist transmit = %g\n", swp->sw_transmit);
424 
425  return 1;
426 }
427 /*
428  * te = dist from pt to end of ray (out hit point)
429  * Zo = elevation at ray start
430  * Ze = elevation at ray end
431  * Zd = Z component of normalized ray vector
432  * d_p_mm = overall fog density
433  * B = density falloff with altitude
434  *
435  *
436  * delta = height at which fog starts
437  * scale = stretches exponential decay zone
438  * d_p_mm = maximum density @ ground
439  *
440  * This is called (from viewshade() in shade.c)
441  * once for each hit point to be shaded.
442  */
443 int
444 emist_fbm_render(struct application *ap, const struct partition *pp, struct shadework *UNUSED(swp), void *UNUSED(dp))
445 {
446  point_t in_pt, out_pt;
447  vect_t dist_v;
448  double dist, delta;
449 
450  RT_AP_CHECK(ap);
451  RT_CHECK_PT(pp);
452 
453  /* compute hit point & length of ray */
454  if (pp->pt_inhit->hit_dist < 0.0) {
455  VMOVE(in_pt, ap->a_ray.r_pt);
456  } else {
457  VJOIN1(in_pt, ap->a_ray.r_pt,
458  pp->pt_inhit->hit_dist, ap->a_ray.r_dir);
459  }
460 
461  /* get exit point */
462  VJOIN1(out_pt,
463  ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
464 
465 
466  /* we march along the ray, evaluating the atmospheric function
467  * at each step.
468  */
469 
470  VSUB2(dist_v, out_pt, in_pt);
471  dist = MAGNITUDE(dist_v);
472 
473  for (delta = 0; delta < dist; delta += 1.0) {
474  /* compute the current point in space */
475 
476  /* Shoot a ray down the -Z axis to find our current height
477  * above the local terrain.
478  */
479 
480  }
481 
482 
483  return 1;
484 }
485 
486 
487 /*
488  * Local Variables:
489  * mode: C
490  * tab-width: 8
491  * indent-tabs-mode: t
492  * c-file-style: "stroustrup"
493  * End:
494  * ex: shiftwidth=4 tabstop=8
495  */
struct xray a_ray
Actual ray to be shot.
Definition: raytrace.h:1583
HIDDEN int air_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_air.c:209
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
struct hit * pt_outhit
OUT hit ptr.
Definition: raytrace.h:579
struct bu_structparse air_parse[]
Definition: sh_air.c:62
#define MF_MAGIC
Definition: magic.h:205
#define meters_to_millimeters
Definition: clone.c:90
#define VSET(a, b, c, d)
Definition: color.c:53
#define SHDR_O(m)
Definition: sh_air.c:57
Definition: raytrace.h:368
Header file for the BRL-CAD common definitions.
const char * reg_name
Identifying string.
Definition: raytrace.h:539
HIDDEN void air_print(register struct region *rp, void *dp)
Definition: sh_air.c:158
void bu_mm_cvt(const struct bu_structparse *sdp, const char *name, void *base, const char *value, void *data)
Definition: units.c:386
double delta
Definition: sh_air.c:42
int a_onehit
flag to stop on first hit
Definition: raytrace.h:1586
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
int(* a_hit)(struct application *, struct partition *, struct seg *)
called when shot hits model
Definition: raytrace.h:1584
struct hit * pt_inhit
IN hit pointer.
Definition: raytrace.h:577
#define HIDDEN
Definition: common.h:86
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
Definition: parse.c:1221
#define RT_AP_CHECK(_ap)
Definition: raytrace.h:1685
int tmist_hit(register struct application *ap, struct partition *PartHeadp, struct seg *segHeadp)
Definition: sh_air.c:261
char * name
Definition: sh_air.c:43
COMPLEX data[64]
Definition: fftest.c:34
double d_p_mm
Definition: sh_air.c:40
#define BU_CK_VLS(_vp)
Definition: vls.h:69
#define RT_CHECK_RTI(_p)
Definition: raytrace.h:1832
#define V3ARGS(a)
Definition: color.c:56
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
HIDDEN int emist_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_air.c:378
HIDDEN int airtest_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_air.c:178
HIDDEN int air_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
Definition: sh_air.c:123
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
int tmist_miss(register struct application *ap)
Definition: sh_air.c:273
int emist_fbm_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_air.c:444
#define ZERO(val)
Definition: units.c:38
HIDDEN void air_free(void *cp)
Definition: sh_air.c:165
void(* a_logoverlap)(struct application *, const struct partition *, const struct bu_ptbl *, const struct partition *)
called to log overlaps
Definition: raytrace.h:1594
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
int reg_aircode
Region ID AIR code.
Definition: raytrace.h:543
#define RDEBUG_SHADE
Definition: optical.h:130
double scale
Definition: sh_air.c:41
uint32_t magic
Definition: sh_air.c:39
int bu_struct_parse(const struct bu_vls *in_vls, const struct bu_structparse *desc, const char *base, void *data)
Definition: parse.c:878
HIDDEN int tmist_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_air.c:290
Definition: color.c:51
int rt_shootray(struct application *ap)
void * a_uptr
application-specific pointer
Definition: raytrace.h:1618
#define AIR_MAGIC
Definition: sh_air.c:37
int rr_render(struct application *app, const struct partition *pp, struct shadework *swp)
struct mfuncs air_mfuncs[]
Definition: sh_air.c:80
int(* a_miss)(struct application *)
called when shot misses
Definition: raytrace.h:1585
#define RT_CHECK_PT(_p)
compat
Definition: raytrace.h:588
#define RT_APPLICATION_INIT(_p)
Definition: raytrace.h:1676
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
HIDDEN const point_t delta
Definition: sh_prj.c:618
double fastf_t
Definition: defines.h:300
Header file for the BRL-CAD Optical Library, LIBOPTICAL.
int rdebug
Definition: init.c:39
#define CK_AIR_SP(_p)
Definition: sh_air.c:45