PageRenderTime 122ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/tags/rel-4-5/liboptical/sh_Nfbm.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 280 lines | 201 code | 47 blank | 32 comment | 12 complexity | fd119d6e907801bb06d3b63b40f85e8e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /*
  2. * S H _ N F B M . C
  3. *
  4. */
  5. #include "conf.h"
  6. #include <stdio.h>
  7. #include <math.h>
  8. #include "machine.h"
  9. #include "vmath.h"
  10. #include "raytrace.h"
  11. #include "./material.h"
  12. #include "./mathtab.h"
  13. #include "./rdebug.h"
  14. #define Nfbm_MAGIC 0x18364 /* XXX change this number for each shader */
  15. struct Nfbm_specific {
  16. long magic;
  17. double lacunarity;
  18. double h_val;
  19. double octaves;
  20. double max_angle;
  21. double size;
  22. point_t vsize;
  23. vect_t delta;
  24. mat_t xform;
  25. };
  26. #define CK_Nfbm_SP(_p) RT_CKMAG(_p, Nfbm_MAGIC, "Nfbm_specific")
  27. static struct Nfbm_specific Nfbm_defaults = {
  28. Nfbm_MAGIC,
  29. 2.1753974, /* lacunarity */
  30. 1.0, /* h_val */
  31. 4, /* octaves */
  32. 22.5, /* Angle */
  33. 1.0, /* size */
  34. { 1.0, 1.0, 1.0 }, /* Vector Size */
  35. { 1000.0, 1000.0, 1000.0 } /* delta */
  36. };
  37. #define SHDR_NULL ((struct Nfbm_specific *)0)
  38. #define SHDR_O(m) offsetof(struct Nfbm_specific, m)
  39. #define SHDR_AO(m) offsetofarray(struct Nfbm_specific, m)
  40. void
  41. cvt_parse( sdp, name, base, value )
  42. register CONST struct bu_structparse *sdp; /* structure description */
  43. register CONST char *name; /* struct member name */
  44. char *base; /* begining of structure */
  45. CONST char *value; /* string containing value */
  46. {
  47. double v;
  48. double *p = (double *)(base+sdp->sp_offset);
  49. /* reconvert with optional units */
  50. *p = rt_mm_value(value);
  51. }
  52. struct bu_structparse Nfbm_parse[] = {
  53. {"%f", 1, "lacunarity", SHDR_O(lacunarity), FUNC_NULL },
  54. {"%f", 1, "l", SHDR_O(lacunarity), FUNC_NULL },
  55. {"%f", 1, "H", SHDR_O(h_val), FUNC_NULL },
  56. {"%f", 1, "octaves", SHDR_O(octaves), FUNC_NULL },
  57. {"%f", 1, "o", SHDR_O(octaves), FUNC_NULL },
  58. {"%f", 1, "angle", SHDR_O(max_angle), FUNC_NULL },
  59. {"%f", 1, "a", SHDR_O(max_angle), FUNC_NULL },
  60. {"%f", 1, "size", SHDR_O(size), cvt_parse },
  61. {"%f", 1, "s", SHDR_O(size), cvt_parse },
  62. {"%f", 3, "vsize", SHDR_AO(vsize), FUNC_NULL },
  63. {"%f", 3, "v", SHDR_AO(vsize), FUNC_NULL },
  64. {"%f", 3, "delta", SHDR_AO(delta), FUNC_NULL },
  65. {"%f", 3, "d", SHDR_AO(delta), FUNC_NULL },
  66. {"", 0, (char *)0, 0, FUNC_NULL }
  67. };
  68. HIDDEN int Nfbm_setup(), Nfbm_render();
  69. HIDDEN void Nfbm_print(), Nfbm_free();
  70. struct mfuncs Nfbm_mfuncs[] = {
  71. {"Nfbm", 0, 0, MFI_NORMAL, 0,
  72. Nfbm_setup, Nfbm_render, Nfbm_print, Nfbm_free },
  73. {(char *)0, 0, 0, 0, 0,
  74. 0, 0, 0, 0 }
  75. };
  76. /* N F B M _ S E T U P
  77. *
  78. * This routine is called (at prep time)
  79. * once for each region which uses this shader.
  80. * Any shader-specific initialization should be done here.
  81. */
  82. HIDDEN int
  83. Nfbm_setup( rp, matparm, dpp, mfp, rtip)
  84. register struct region *rp;
  85. struct rt_vls *matparm;
  86. char **dpp; /* pointer to reg_udata in *rp */
  87. struct mfuncs *mfp;
  88. struct rt_i *rtip; /* New since 4.4 release */
  89. {
  90. register struct Nfbm_specific *Nfbm_sp;
  91. mat_t model_to_region;
  92. mat_t tmp;
  93. RT_CHECK_RTI(rtip);
  94. RT_VLS_CHECK( matparm );
  95. RT_CK_REGION(rp);
  96. GETSTRUCT( Nfbm_sp, Nfbm_specific );
  97. *dpp = (char *)Nfbm_sp;
  98. memcpy(Nfbm_sp, &Nfbm_defaults, sizeof(struct Nfbm_specific) );
  99. if( bu_struct_parse( matparm, Nfbm_parse, (char *)Nfbm_sp ) < 0 )
  100. return(-1);
  101. /* Optional: get the matrix which maps model space into
  102. * "region" or "shader" space
  103. */
  104. db_region_mat(model_to_region, rtip->rti_dbip, rp->reg_name);
  105. /* add the noise-space scaling */
  106. mat_idn(tmp);
  107. if (Nfbm_sp->size != 1.0) {
  108. tmp[0] = tmp[5] = tmp[10] = 1.0/Nfbm_sp->size;
  109. } else {
  110. tmp[0] = 1.0/Nfbm_sp->vsize[0];
  111. tmp[5] = 1.0/Nfbm_sp->vsize[1];
  112. tmp[10] = 1.0/Nfbm_sp->vsize[2];
  113. }
  114. mat_mul(Nfbm_sp->xform, tmp, model_to_region);
  115. /* Add any translation within shader/region space */
  116. mat_idn(tmp);
  117. tmp[MDX] = Nfbm_sp->delta[0];
  118. tmp[MDY] = Nfbm_sp->delta[1];
  119. tmp[MDZ] = Nfbm_sp->delta[2];
  120. mat_mul2(tmp, Nfbm_sp->xform);
  121. if( rdebug&RDEBUG_SHADE) {
  122. bu_struct_print( rp->reg_name, Nfbm_parse, (char *)Nfbm_sp );
  123. mat_print( "xform", Nfbm_sp->xform );
  124. }
  125. return(1);
  126. }
  127. /*
  128. * N F B M _ P R I N T
  129. */
  130. HIDDEN void
  131. Nfbm_print( rp, dp )
  132. register struct region *rp;
  133. char *dp;
  134. {
  135. bu_struct_print( rp->reg_name, Nfbm_parse, (char *)dp );
  136. }
  137. /*
  138. * N F B M _ F R E E
  139. */
  140. HIDDEN void
  141. Nfbm_free( cp )
  142. char *cp;
  143. {
  144. rt_free( cp, "Nfbm_specific" );
  145. }
  146. /* N F B M _ R E N D E R
  147. *
  148. * This is called (from viewshade() in shade.c)
  149. * once for each hit point to be shaded.
  150. */
  151. int
  152. Nfbm_render( ap, pp, swp, dp )
  153. struct application *ap;
  154. struct partition *pp;
  155. struct shadework *swp;
  156. char *dp;
  157. {
  158. register struct Nfbm_specific *Nfbm_sp =
  159. (struct Nfbm_specific *)dp;
  160. point_t pt;
  161. vect_t v_noise; /* noise vector for each octave */
  162. vect_t freq_v;
  163. double cos_angle;
  164. double angle;
  165. quat_t q;
  166. static CONST vect_t up = { 0.0, 0.0, 1.0 };
  167. vect_t N;
  168. mat_t mat;
  169. int i;
  170. double freq;
  171. point_t p;
  172. RT_AP_CHECK(ap);
  173. RT_CHECK_PT(pp);
  174. CK_Nfbm_SP(Nfbm_sp);
  175. if( rdebug&RDEBUG_SHADE)
  176. bu_struct_print( "foo", Nfbm_parse, (char *)Nfbm_sp );
  177. /* transform hit point into "shader-space coordinates" */
  178. MAT4X3PNT(pt, Nfbm_sp->xform, swp->sw_hit.hit_point);
  179. /* Compute random vector from point */
  180. VSETALL(v_noise, 0.0);
  181. freq = 1.0;
  182. for (i=0 ; i < Nfbm_sp->octaves ; i++ ) {
  183. #if 0
  184. noise_vec(pt, freq_v);
  185. #else
  186. freq_v[X] = noise_perlin(pt);
  187. VSCALE(p, pt, Nfbm_sp->lacunarity);
  188. freq_v[Y] = noise_perlin(p);
  189. VSCALE(p, pt, Nfbm_sp->lacunarity*Nfbm_sp->lacunarity);
  190. freq_v[Z] = noise_perlin(p);
  191. #endif
  192. VJOIN1(v_noise, v_noise, 1.0/freq, freq_v);
  193. VSCALE(pt, pt, Nfbm_sp->lacunarity);
  194. freq *= Nfbm_sp->lacunarity;
  195. }
  196. VUNITIZE(v_noise);
  197. cos_angle = VDOT(v_noise, up);
  198. angle = acos(cos_angle);
  199. angle *= Nfbm_sp->max_angle / 180.0;
  200. /* form quaternion to rotate Normal to new location */
  201. VCROSS(q, up, v_noise);
  202. QUAT_FROM_VROT_RAD(q, angle, q);
  203. quat_quat2mat(mat, q);
  204. VMOVE(N, swp->sw_hit.hit_normal);
  205. MAT4X3VEC(swp->sw_hit.hit_normal, mat, N);
  206. return(1);
  207. }
  208. #if 0
  209. /* compute the footprint of the ray intersect point */
  210. radius = ap->a_rbeam + ap->a_diverge * swp->sw_hit.hit_dist;
  211. /* Compute random vector from point */
  212. VSET(v_noise, 0.0, 0.0, 0.0);
  213. VSET(N, 0.0, 0.0, 0.0);
  214. freq = 1.0;
  215. for (i=0 ; i < Nfbm_sp->octaves ; i++ ) {
  216. noise_vec(pt, v_noise);
  217. VJOIN1(N, N, 1.0/freq, v_noise);
  218. VSCALE(pt, pt, Nfbm_sp->lacunarity);
  219. freq *= Nfbm_sp->lacunarity;
  220. }
  221. /* XXX This is bad */
  222. while ( MAGSQ(N) > .125) {
  223. VSCALE(N, N, 0.5);
  224. }
  225. VADD2(swp->sw_hit.hit_normal, swp->sw_hit.hit_normal, N);
  226. VUNITIZE(swp->sw_hit.hit_normal);
  227. new_cos_angle = VDOT(swp->sw_hit.hit_normal, ap->a_ray.r_dir) ;
  228. /* preserve the normal vs ray orientation */
  229. if (cos_angle <= 0.0 && new_cos_angle > 0.0 ||
  230. cos_angle > 0.0 && new_cos_angle <= 0.0) {
  231. VREVERSE(swp->sw_hit.hit_normal, swp->sw_hit.hit_normal);
  232. }
  233. #endif