BRL-CAD
sh_camo.c
Go to the documentation of this file.
1 /* S H _ C A M O . 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_camo.c
21  *
22  * A shader to apply a crude camouflage color pattern to an object
23  * using a fractional Brownian motion of 3 colors
24  *
25  * At each hit point, the shader evaluate the fbm to obtain a "Noise"
26  * value between -1 and 1. The color produced is:
27  *
28  * Noise value Color
29  * -1 <= N < t1 c1
30  * t1 <= N < t2 c2
31  * t2 <= N <= 1 c3
32  */
33 
34 #include "common.h"
35 
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <math.h>
40 
41 #include "bu/units.h"
42 #include "vmath.h"
43 #include "raytrace.h"
44 #include "optical.h"
45 
46 #ifdef RT_MULTISPECTRAL
47 # include "spectrum.h"
48 #endif
49 
50 #define SMOOTHSTEP(x) ((x)*(x)*(3 - 2*(x)))
51 
52 
53 #define camo_MAGIC 0x18364 /* XXX change this number for each shader */
54 struct camo_specific {
55  uint32_t magic;
57  double noise_h_val;
58  double noise_octaves;
59  double noise_size;
60  point_t noise_vscale; /* size of noise coordinate space */
61  vect_t noise_delta; /* a delta in noise space to be applied to pts */
62 
63  double t1; /* noise threshold for color1 */
64  double t2; /* noise threshold for color2 */
65  point_t c1; /* color 1 */
66  point_t c2; /* color 2 */
67  point_t c3; /* color 3 */
68  mat_t xform; /* model->region coord sys matrix */
69 };
70 #define CK_camo_SP(_p) BU_CKMAG(_p, camo_MAGIC, "camo_specific")
71 
72 static struct camo_specific camo_defaults = {
73  camo_MAGIC,
74  2.1753974, /* noise_lacunarity */
75  1.0, /* noise_h_val */
76  4.0, /* noise_octaves */
77  1.0, /* noise_size */
78  VINITALL(0.0125), /* noise_vscale */
79  VINITALL(1000.0), /* delta into noise space */
80  -0.25, /* t1 */
81  0.25, /* t2 */
82  { .38, .29, .16 }, /* darker color c1 (97/74/41) */
83  { .1, .30, .04 }, /* basic color c2 (26/77/10) */
84  VINITALL(0.15), /* dark black (38/38/38) */
85  MAT_INIT_IDN
86 };
87 
88 
89 static struct camo_specific marble_defaults = {
90  camo_MAGIC,
91  2.1753974, /* noise_lacunarity */
92  1.0, /* noise_h_val */
93  4.0, /* noise_octaves */
94  1.0, /* noise_size */
95  VINITALL(1.0), /* noise_vscale */
96  VINITALL(1000.0), /* delta into noise space */
97  0.25, /* t1 */
98  0.5, /* t2 */
99  { .8, .2, .16 }, /* darker color c1 (97/74/41) */
100  { .9, .9, .8 }, /* basic color c2 (26/77/10) */
101  VINITALL(0.15), /* dark black (38/38/38) */
102  MAT_INIT_IDN
103 };
104 
105 
106 #define SHDR_NULL ((struct camo_specific *)0)
107 #define SHDR_O(m) bu_offsetof(struct camo_specific, m)
108 
109 /* local sp_hook function */
110 void color_fix(const struct bu_structparse *, const char *, void *, const char *, void *);
111 
113  {"%g", 1, "lacunarity", SHDR_O(noise_lacunarity), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
114  {"%g", 1, "H", SHDR_O(noise_h_val), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
115  {"%g", 1, "octaves", SHDR_O(noise_octaves), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
116  {"%g", 1, "size", SHDR_O(noise_size), bu_mm_cvt, NULL, NULL },
117  {"%f", 3, "vscale", SHDR_O(noise_vscale), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
118  {"%g", 1, "thresh1", SHDR_O(t1), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
119  {"%g", 1, "thresh2", SHDR_O(t2), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
120  {"%f", 3, "color1", SHDR_O(c1), color_fix, NULL, NULL },
121  {"%f", 3, "color2", SHDR_O(c2), color_fix, NULL, NULL },
122  {"%f", 3, "color3", SHDR_O(c3), color_fix, NULL, NULL },
123  {"%f", 3, "delta", SHDR_O(noise_delta), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
124  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
125 };
126 
127 
129  {"%g", 1, "lacunarity", SHDR_O(noise_lacunarity), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
130  {"%g", 1, "l", SHDR_O(noise_lacunarity), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
131  {"%g", 1, "H", SHDR_O(noise_h_val), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
132  {"%g", 1, "octaves", SHDR_O(noise_octaves), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
133  {"%g", 1, "o", SHDR_O(noise_octaves), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
134  {"%g", 1, "t1", SHDR_O(t1), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
135  {"%g", 1, "t2", SHDR_O(t2), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
136  {"%g", 1, "size", SHDR_O(noise_size), bu_mm_cvt, NULL, NULL },
137  {"%g", 1, "s", SHDR_O(noise_size), bu_mm_cvt, NULL, NULL },
138  {"%f", 3, "vscale", SHDR_O(noise_vscale), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
139  {"%f", 3, "vs", SHDR_O(noise_vscale), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
140  {"%f", 3, "v", SHDR_O(noise_vscale), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
141  {"%f", 3, "c1", SHDR_O(c1), color_fix, NULL, NULL },
142  {"%f", 3, "c2", SHDR_O(c2), color_fix, NULL, NULL },
143  {"%f", 3, "c3", SHDR_O(c3), color_fix, NULL, NULL },
144  {"%f", 3, "delta", SHDR_O(noise_delta), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
145  {"%f", 3, "d", SHDR_O(noise_delta), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
146  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
147 };
148 
149 
150 HIDDEN int marble_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip);
151 HIDDEN int marble_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
152 HIDDEN int camo_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip);
153 HIDDEN int camo_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
154 HIDDEN void camo_print(register struct region *rp, void *dp);
155 HIDDEN void camo_free(void *cp);
156 
157 struct mfuncs camo_mfuncs[] = {
158  {MF_MAGIC, "camo", 0, MFI_HIT, 0,
159  camo_setup, camo_render, camo_print, camo_free },
160 
161  {MF_MAGIC, "marble", 0, MFI_HIT, 0,
162  marble_setup, marble_render, camo_print, camo_free },
163 
164  {0, (char *)0, 0, 0, 0,
165  0, 0, 0, 0 }
166 };
167 
168 
169 /* color_fix
170  *
171  * Used as a hooked function for input of color values
172  */
173 void
174 color_fix(const struct bu_structparse *sdp,
175  const char *UNUSED(name),
176  void *base,
177  const char *UNUSED(value),
178  void *UNUSED(data))
179 /* structure description */
180 /* struct member name */
181 /* beginning of structure */
182 /* string containing value */
183 {
184  register double *p = (double *)((char *)base + sdp->sp_offset);
185  size_t i;
186  int ok;
187 
188  /* if all the values are in the range [0..1] there's nothing to do */
189  for (ok = 1, i = 0; i < sdp->sp_count; i++, p++) {
190  if (*p > 1.0) ok = 0;
191  }
192  if (ok) return;
193 
194  /* user specified colors in the range [0..255] so we need to
195  * map those into [0..1]
196  */
197  p = (double *)((char *)base + sdp->sp_offset);
198  for (i = 0; i < sdp->sp_count; i++, p++) {
199  *p /= 255.0;
200  }
201 }
202 
203 
204 HIDDEN int
205 setup(register struct region *rp, struct bu_vls *matparm, void **dpp, struct rt_i *rtip, char *parameters, struct camo_specific defaults)
206 {
207 /* pointer to reg_udata in *rp */
208 
209 /* New since 4.4 release */
210  register struct camo_specific *camo_sp;
211  mat_t model_to_region;
212  mat_t tmp;
213 
214  RT_CHECK_RTI(rtip);
215  BU_CK_VLS(matparm);
216  RT_CK_REGION(rp);
217  BU_GET(camo_sp, struct camo_specific);
218  *dpp = camo_sp;
219 
220  if (rdebug&RDEBUG_SHADE) {
221  bu_log("%s'%s'\n", parameters, bu_vls_addr(matparm));
222  }
223  memcpy(camo_sp, &defaults, sizeof(struct camo_specific));
224 
225  if (bu_struct_parse(matparm, camo_parse, (char *)camo_sp, NULL) < 0)
226  return -1;
227 
228  /* Optional: get the matrix which maps model space into
229  * "region" or "shader" space
230  */
231  db_region_mat(model_to_region, rtip->rti_dbip, rp->reg_name, &rt_uniresource);
232 
233  /* add the noise-space scaling */
234  MAT_IDN(tmp);
235  if (!EQUAL(camo_sp->noise_size, 1.0)) {
236  /* the user sets "noise_size" to the size of the biggest
237  * noise-space blob in model coordinates
238  */
239  tmp[0] = tmp[5] = tmp[10] = 1.0/camo_sp->noise_size;
240  } else {
241  tmp[0] = 1.0/camo_sp->noise_vscale[0];
242  tmp[5] = 1.0/camo_sp->noise_vscale[1];
243  tmp[10] = 1.0/camo_sp->noise_vscale[2];
244  }
245 
246  bn_mat_mul(camo_sp->xform, tmp, model_to_region);
247 
248  /* Add any translation within shader/region space */
249  MAT_IDN(tmp);
250  tmp[MDX] = camo_sp->noise_delta[0];
251  tmp[MDY] = camo_sp->noise_delta[1];
252  tmp[MDZ] = camo_sp->noise_delta[2];
253  bn_mat_mul2(tmp, camo_sp->xform);
254 
255  if (rdebug&RDEBUG_SHADE) {
256  bu_struct_print(rp->reg_name, camo_print_tab,
257  (char *)camo_sp);
258  bn_mat_print("xform", camo_sp->xform);
259  }
260 
261  return 1;
262 }
263 
264 
265 /*
266  * This routine is called (at prep time)
267  * once for each region which uses this shader.
268  * Any shader-specific initialization should be done here.
269  */
270 HIDDEN int
271 camo_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)
272 {
273  return setup(rp, matparm, dpp, rtip, "camouflage parameters = ", camo_defaults);
274 }
275 
276 
277 HIDDEN void
278 camo_print(register struct region *rp, void *dp)
279 {
280  bu_struct_print(rp->reg_name, camo_print_tab, (char *)dp);
281 }
282 
283 
284 HIDDEN void
285 camo_free(void *cp)
286 {
287  BU_PUT(cp, struct camo_specific);
288 }
289 
290 
291 /*
292  * This is called (from viewshade() in shade.c)
293  * once for each hit point to be shaded.
294  */
295 int
296 camo_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
297 {
298  register struct camo_specific *camo_sp =
299  (struct camo_specific *)dp;
300  point_t pt;
301  double val;
302 #ifdef RT_MULTISPECTRAL
303  float fcolor[3];
304 #endif
305 
306  RT_AP_CHECK(ap);
307  RT_CHECK_PT(pp);
308  CK_camo_SP(camo_sp);
309 
310  if (rdebug&RDEBUG_SHADE)
311  bu_struct_print("foo", camo_parse, (char *)camo_sp);
312 
313  /* Optional: transform hit point into "shader-space coordinates" */
314  MAT4X3PNT(pt, camo_sp->xform, swp->sw_hit.hit_point);
315 
316 
317  /* bn_noise_fbm returns a value in the approximate range of
318  * -1.0 ~<= bn_noise_fbm() ~<= 1.0
319  */
320  val = bn_noise_fbm(pt, camo_sp->noise_h_val,
321  camo_sp->noise_lacunarity, camo_sp->noise_octaves);
322 
323 #ifdef RT_MULTISPECTRAL
324  BN_CK_TABDATA(swp->msw_color);
325  if (val < camo_sp->t1) {
326  VMOVE(fcolor, camo_sp->c1);
327  rt_spect_reflectance_rgb(swp->msw_color, fcolor);
328  } else if (val < camo_sp->t2) {
329  VMOVE(fcolor, camo_sp->c2);
330  rt_spect_reflectance_rgb(swp->msw_color, fcolor);
331  } else {
332  VMOVE(fcolor, camo_sp->c3);
333  rt_spect_reflectance_rgb(swp->msw_color, fcolor);
334  }
335 #else
336  if (val < camo_sp->t1) {
337  VMOVE(swp->sw_color, camo_sp->c1);
338  } else if (val < camo_sp->t2) {
339  VMOVE(swp->sw_color, camo_sp->c2);
340  } else {
341  VMOVE(swp->sw_color, camo_sp->c3);
342  }
343 #endif
344 
345  return 1;
346 }
347 /*
348  * This routine is called (at prep time)
349  * once for each region which uses this shader.
350  * Any shader-specific initialization should be done here.
351  */
352 HIDDEN int
353 marble_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)
354 {
355  return setup(rp, matparm, dpp, rtip, "marble parameters = ", marble_defaults);
356 }
357 
358 
359 /*
360  * This is called (from viewshade() in shade.c)
361  * once for each hit point to be shaded.
362  */
363 int
364 marble_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
365 {
366  register struct camo_specific *camo_sp =
367  (struct camo_specific *)dp;
368  point_t pt;
369  double val, inv_val;
370 #ifdef RT_MULTISPECTRAL
371  float fcolor[3];
372 #endif
373 
374  RT_AP_CHECK(ap);
375  RT_CHECK_PT(pp);
376  CK_camo_SP(camo_sp);
377 
378  if (rdebug&RDEBUG_SHADE)
379  bu_struct_print("foo", camo_parse, (char *)camo_sp);
380 
381  /* Optional: transform hit point into "shader-space coordinates" */
382  MAT4X3PNT(pt, camo_sp->xform, swp->sw_hit.hit_point);
383 
384 
385  /* bn_noise_turb returns a value in the approximate range of
386  * 0.0 ~<= bn_noise_turb() ~<= 1.0
387  */
388  val = bn_noise_turb(pt, camo_sp->noise_h_val,
389  camo_sp->noise_lacunarity, camo_sp->noise_octaves);
390 
391  val = sin(val*M_PI);
392 
393  inv_val = 1.0 - val;
394 
395 #ifdef RT_MULTISPECTRAL
396  {
397  struct bn_tabdata *tcolor;
398 
399  BN_CK_TABDATA(swp->msw_color);
400  BN_GET_TABDATA(tcolor, spectrum);
401 
402  VMOVE(fcolor, camo_sp->c2);
403 
404  rt_spect_reflectance_rgb(tcolor, fcolor);
405  bn_tabdata_blend2(swp->msw_color, val, swp->msw_color,
406  inv_val, tcolor);
407  bn_tabdata_free(tcolor);
408  }
409 #else
410  VCOMB2(swp->sw_color, val, swp->sw_color, inv_val, camo_sp->c2);
411 #endif
412 
413  return 1;
414 }
415 
416 
417 /*
418  * Local Variables:
419  * mode: C
420  * tab-width: 8
421  * indent-tabs-mode: t
422  * c-file-style: "stroustrup"
423  * End:
424  * ex: shiftwidth=4 tabstop=8
425  */
Definition: db_flip.c:35
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
double t1
Definition: sh_camo.c:63
#define MF_MAGIC
Definition: magic.h:205
#define BN_GET_TABDATA(_data, _table)
Definition: tabdata.h:114
void bn_tabdata_free(struct bn_tabdata *data)
Definition: tabdata.c:67
Definition: clone.c:90
double bn_noise_turb(point_t point, double h_val, double lacunarity, double octaves)
Procedural turbulence evaluated at "point";.
#define M_PI
Definition: fft.h:35
void bn_tabdata_blend2(struct bn_tabdata *out, double scale1, const struct bn_tabdata *in1, double scale2, const struct bn_tabdata *in2)
point_t c1
Definition: sh_camo.c:65
Header file for the BRL-CAD common definitions.
struct bu_structparse camo_parse[]
Definition: sh_camo.c:128
const char * reg_name
Identifying string.
Definition: raytrace.h:539
HIDDEN int setup(register struct region *rp, struct bu_vls *matparm, void **dpp, struct rt_i *rtip, char *parameters, struct camo_specific defaults)
Definition: sh_camo.c:205
void bu_mm_cvt(const struct bu_structparse *sdp, const char *name, void *base, const char *value, void *data)
Definition: units.c:386
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
struct bu_structparse camo_print_tab[]
Definition: sh_camo.c:112
#define HIDDEN
Definition: common.h:86
#define BN_CK_TABDATA(_p)
Definition: tabdata.h:106
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
Definition: parse.c:1221
void bn_mat_mul2(const mat_t i, mat_t o)
#define RT_AP_CHECK(_ap)
Definition: raytrace.h:1685
HIDDEN int marble_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
Definition: sh_camo.c:353
COMPLEX data[64]
Definition: fftest.c:34
#define BU_CK_VLS(_vp)
Definition: vls.h:69
HIDDEN void camo_print(register struct region *rp, void *dp)
Definition: sh_camo.c:278
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define SHDR_O(m)
Definition: sh_camo.c:107
#define CK_camo_SP(_p)
Definition: sh_camo.c:70
void bn_mat_print(const char *title, const mat_t m)
Definition: mat.c:81
#define RT_CHECK_RTI(_p)
Definition: raytrace.h:1832
#define camo_MAGIC
Definition: sh_camo.c:53
mat_t xform
Definition: sh_camo.c:68
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
double noise_h_val
Definition: sh_camo.c:57
point_t c2
Definition: sh_camo.c:66
point_t noise_vscale
Definition: sh_camo.c:60
#define UNUSED(parameter)
Definition: common.h:239
double noise_lacunarity
Definition: sh_camo.c:56
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
struct mfuncs camo_mfuncs[]
Definition: sh_camo.c:157
size_t sp_offset
Definition: parse.h:141
void color_fix(const struct bu_structparse *, const char *, void *, const char *, void *)
Definition: sh_camo.c:174
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
void rt_spect_reflectance_rgb(struct bn_tabdata *curve, const float *rgb)
Definition: spectrum.c:191
HIDDEN int camo_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
Definition: sh_camo.c:271
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
double noise_size
Definition: sh_camo.c:59
double t2
Definition: sh_camo.c:64
int db_region_mat(mat_t m, struct db_i *dbip, const char *name, struct resource *resp)
Definition: db_tree.c:2269
double noise_octaves
Definition: sh_camo.c:58
HIDDEN int camo_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_camo.c:296
#define RDEBUG_SHADE
Definition: optical.h:130
struct db_i * rti_dbip
prt to Database instance struct
Definition: raytrace.h:1774
size_t sp_count
Definition: parse.h:139
int bu_struct_parse(const struct bu_vls *in_vls, const struct bu_structparse *desc, const char *base, void *data)
Definition: parse.c:878
point_t c3
Definition: sh_camo.c:67
HIDDEN int marble_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_camo.c:364
HIDDEN void camo_free(void *cp)
Definition: sh_camo.c:285
uint32_t magic
Definition: sh_camo.c:55
double bn_noise_fbm(point_t point, double h_val, double lacunarity, double octaves)
Procedural fBm evaluated at "point"; returns value stored in "value".
struct bn_table * spectrum
Definition: init.c:41
#define RT_CHECK_PT(_p)
compat
Definition: raytrace.h:588
vect_t noise_delta
Definition: sh_camo.c:61
Definition: vls.h:56
Header file for the BRL-CAD Optical Library, LIBOPTICAL.
int rdebug
Definition: init.c:39